Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DSourceComboVertexer.cc
Go to the documentation of this file.
5 
6 namespace DAnalysis
7 {
8 
9 DSourceComboVertexer::DSourceComboVertexer(JEventLoop* locEventLoop, DSourceComboer* locSourceComboer, DSourceComboP4Handler* locSourceComboP4Handler) :
10 dSourceComboer(locSourceComboer), dSourceComboP4Handler(locSourceComboP4Handler)
11 {
12  locEventLoop->GetSingle(dAnalysisUtilities);
13 
14  //GET THE GEOMETRY
15  DApplication* locApplication = dynamic_cast<DApplication*>(locEventLoop->GetJApplication());
16  DGeometry* locGeometry = locApplication->GetDGeometry(locEventLoop->GetJEvent().GetRunNumber());
17 
18  //TARGET INFORMATION
19  double locTargetCenterZ = 65.0;
20  locGeometry->GetTargetZ(locTargetCenterZ);
21  dTargetCenter.SetXYZ(0.0, 0.0, locTargetCenterZ);
22 
23  gPARMS->SetDefaultParameter("COMBO:DEBUG_LEVEL", dDebugLevel);
24 }
25 
26 vector<signed char> DSourceComboVertexer::Get_VertexZBins(const DReactionVertexInfo* locReactionVertexInfo, const DSourceCombo* locReactionCombo, const DKinematicData* locBeamParticle, bool locComboIsFullyCharged) const
27 {
28  if(locReactionCombo == nullptr)
29  return {};
30 
31  vector<signed char> locVertexZBins;
32  for(auto locStepInfo : locReactionVertexInfo->Get_StepVertexInfos())
33  locVertexZBins.emplace_back(Get_VertexZBin(locStepInfo, locReactionCombo, locBeamParticle, locComboIsFullyCharged));
34 
35  return locVertexZBins;
36 }
37 
38 signed char DSourceComboVertexer::Get_VertexZBin(const DReactionStepVertexInfo* locStepVertexInfo, const DSourceCombo* locReactionCombo, const DKinematicData* locBeamParticle, bool locComboIsFullyCharged) const
39 {
40  if(locStepVertexInfo->Get_DanglingVertexFlag())
41  {
42  auto locParentVertexInfo = locStepVertexInfo->Get_ParentVertexInfo();
43  return (locParentVertexInfo != nullptr) ? Get_VertexZBin(locParentVertexInfo, locReactionCombo, locBeamParticle, locComboIsFullyCharged) : dSourceComboTimeHandler->Get_VertexZBin_TargetCenter();
44  }
45 
46  auto locVertexPrimaryCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionCombo, locStepVertexInfo);
47  auto locIsCombo2ndVertex = (locComboIsFullyCharged && locStepVertexInfo->Get_FullConstrainParticles(false, d_FinalState, d_Charged, false).empty());
48  return Get_VertexZBin(locStepVertexInfo->Get_ProductionVertexFlag(), locReactionCombo, locVertexPrimaryCombo, locBeamParticle, locIsCombo2ndVertex);
49 }
50 
51 DVector3 DSourceComboVertexer::Get_Vertex(const DReactionStepVertexInfo* locStepVertexInfo, const DSourceCombo* locReactionCombo, const DKinematicData* locBeamParticle, bool locComboIsFullyCharged) const
52 {
53  if(locStepVertexInfo->Get_DanglingVertexFlag())
54  {
55  auto locParentVertexInfo = locStepVertexInfo->Get_ParentVertexInfo();
56  return (locParentVertexInfo != nullptr) ? Get_Vertex(locParentVertexInfo, locReactionCombo, locBeamParticle, locComboIsFullyCharged) : dTargetCenter;
57  }
58 
59  auto locVertexPrimaryCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionCombo, locStepVertexInfo);
60  auto locIsCombo2ndVertex = (locComboIsFullyCharged && locStepVertexInfo->Get_FullConstrainParticles(false, d_FinalState, d_Charged, false).empty());
61  return Get_Vertex(locStepVertexInfo->Get_ProductionVertexFlag(), locReactionCombo, locVertexPrimaryCombo, locBeamParticle, locIsCombo2ndVertex);
62 }
63 
64 double DSourceComboVertexer::Get_TimeOffset(const DReactionVertexInfo* locReactionVertexInfo, const DReactionStepVertexInfo* locStepVertexInfo, const DSourceCombo* locReactionCombo, const DKinematicData* locBeamParticle) const
65 {
66  if(locStepVertexInfo->Get_DanglingVertexFlag())
67  {
68  auto locParentVertexInfo = locStepVertexInfo->Get_ParentVertexInfo();
69  return (locParentVertexInfo != nullptr) ? Get_TimeOffset(locReactionVertexInfo, locParentVertexInfo, locReactionCombo, locBeamParticle) : 0.0;
70  }
71 
72  auto locVertexPrimaryCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionCombo, locStepVertexInfo);
73  auto locIsPrimaryProductionVertex = locReactionVertexInfo->Get_StepVertexInfo(0)->Get_ProductionVertexFlag();
74  return Get_TimeOffset(locIsPrimaryProductionVertex, locReactionCombo, locVertexPrimaryCombo, locBeamParticle);
75 }
76 
77 signed char DSourceComboVertexer::Get_VertexZBin(bool locIsProductionVertex, const DSourceCombo* locReactionCombo, const DSourceCombo* locPrimaryVertexCombo, const DKinematicData* locBeamParticle, bool locIsCombo2ndVertex) const
78 {
79  if(locPrimaryVertexCombo == nullptr)
81 
82  auto locConstrainingParticles = Get_ConstrainingParticles(locIsProductionVertex, locReactionCombo, locPrimaryVertexCombo, locBeamParticle, locIsCombo2ndVertex);
83  if(locConstrainingParticles.empty())
85  auto locVertexZ = Get_Vertex(locIsProductionVertex, locConstrainingParticles).Z();
87 }
88 
89 void DSourceComboVertexer::Calc_VertexTimeOffsets_WithCharged(const DReactionVertexInfo* locReactionVertexInfo, const DSourceCombo* locReactionChargedCombo)
90 {
91  if(dDebugLevel >= 10)
92  cout << "DSourceComboVertexer::Calc_VertexTimeOffsets_WithCharged()" << endl;
93 
94  auto locIsPrimaryProductionVertex = locReactionVertexInfo->Get_StepVertexInfo(0)->Get_ProductionVertexFlag();
95  //even if below is true, we still need to register step vertex infos
96  auto locEverythingFoundFlag = (dTimeOffsets.find(std::make_tuple(locIsPrimaryProductionVertex, locReactionChargedCombo, (const DKinematicData*)nullptr)) != dTimeOffsets.end());
97 
98  //loop through vertices
99  map<pair<int, int>, const DKinematicData*> locReconDecayParticleMap; //decaying particle indices -> kinematic data //indices: when the decaying particle is in the INITIAL state
100  unordered_map<const DReactionStepVertexInfo*, const DSourceCombo*> locVertexPrimaryComboMap;
101  for(const auto& locStepVertexInfo : locReactionVertexInfo->Get_StepVertexInfos())
102  {
103  if(dDebugLevel >= 10)
104  cout << "Step: " << locStepVertexInfo->Get_StepIndices().front() << endl;
105 
106  /***************************************** CHECK IF VERTEX POSITION IS INDETERMINATE AT THIS STAGE ********************************************/
107 
108  auto locVertexPrimaryCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionChargedCombo, locStepVertexInfo);
109  auto locIsCombo2ndVertex = locStepVertexInfo->Get_FullConstrainParticles(false, d_FinalState, d_Charged, false).empty();
110  auto locIsProductionVertexFlag = locStepVertexInfo->Get_ProductionVertexFlag();
111  auto locComboProductionTuple = std::make_tuple(locIsProductionVertexFlag, (const DSourceCombo*)nullptr, locVertexPrimaryCombo, (const DKinematicData*)nullptr, locIsCombo2ndVertex);
112 
113  if(locStepVertexInfo->Get_DanglingVertexFlag())
114  continue; //is forever indeterminate, even with neutrals and beam energy
115 
116  //get combo & info
117  locVertexPrimaryComboMap.emplace(locStepVertexInfo, locVertexPrimaryCombo);
118 
119  //get particles
120  auto locChargedSourceParticles = !locIsCombo2ndVertex ? DAnalysis::Get_SourceParticles_ThisVertex(locVertexPrimaryCombo) : vector<pair<Particle_t, const JObject*>>();
121  auto locDecayingParticles = Get_FullConstrainDecayingParticles(locStepVertexInfo, locReconDecayParticleMap);
122  if(dDebugLevel >= 10)
123  cout << "# charged/decaying particles at vertex = " << locChargedSourceParticles.size() << ", " << locDecayingParticles.size() << endl;
124 
125  //now, just because it isn't dangling, it doesn't mean we have enough information to actually determine the vertex
126  //e.g. we may need neutrals or beam energy to define constraining decay particle p4/trajectory
127  auto locDeterminableIterator = dVertexDeterminableWithChargedMap.find(locStepVertexInfo);
128  if(locDeterminableIterator == dVertexDeterminableWithChargedMap.end())
129  {
130  //we don't know yet if it is determinable or not. figure it out
131  auto locNumConstrainingParticles = locChargedSourceParticles.size() + locDecayingParticles.size();
132 
133  //determine it, save result, and continue if can't
134  bool locVertexDeterminableFlag = locIsProductionVertexFlag ? (locNumConstrainingParticles > 0) : (locNumConstrainingParticles > 1);
135  if(dDebugLevel >= 10)
136  cout << "vertex determinable flag = " << locVertexDeterminableFlag << endl;
137  dVertexDeterminableWithChargedMap.emplace(locStepVertexInfo, locVertexDeterminableFlag);
138  if(!locVertexDeterminableFlag)
139  continue; //can't determine yet, but will be able to in the future
140  }
141  else if(!locDeterminableIterator->second)
142  continue;
143  if(locEverythingFoundFlag)
144  continue; //already done
145 
146  vector<const DKinematicData*> locVertexParticles;
147  auto locVertex = Calc_Vertex(locIsProductionVertexFlag, locChargedSourceParticles, locDecayingParticles, locVertexParticles);
148  dConstrainingParticlesByCombo.emplace(locComboProductionTuple, locVertexParticles);
149 
150  //set the vertices (really, the vertex particles) for the other combos for faster lookup during neutral comboing
151  auto locVertexCombos = DAnalysis::Get_SourceCombos_ThisVertex(locVertexPrimaryCombo);
152  for(const auto& locVertexCombo : locVertexCombos)
153  dConstrainingParticlesByCombo.emplace(std::make_tuple(locIsProductionVertexFlag, (const DSourceCombo*)nullptr, locVertexCombo, (const DKinematicData*)nullptr, locIsCombo2ndVertex), locVertexParticles);
154  Construct_DecayingParticle_InvariantMass(locStepVertexInfo, locVertexPrimaryCombo, locVertex, locReconDecayParticleMap);
155  }
156  if(locEverythingFoundFlag)
157  return; //already done
158 
159  //do time offsets once all the vertices have been found
160  Calc_TimeOffsets(locReactionVertexInfo, locReactionChargedCombo, nullptr);
161 }
162 
163 void DSourceComboVertexer::Calc_VertexTimeOffsets_WithPhotons(const DReactionVertexInfo* locReactionVertexInfo, const DSourceCombo* locReactionChargedCombo, const DSourceCombo* locReactionFullCombo)
164 {
165  //Calculate vertex positions & time offsets using photons
166  //not likely to have any effect, but it's necessary sometimes (but rarely)
167  //E.g. g, p -> K0, Sigma+ K0 -> 3pi: The selected pi0 photons could help define the production vertex
168  if(dDebugLevel > 0)
169  cout << "Calc_VertexTimeOffsets_WithPhotons()" << endl;
170 
171  auto locIsPrimaryProductionVertex = locReactionVertexInfo->Get_StepVertexInfo(0)->Get_ProductionVertexFlag();
172  //even if below is true, we still need to register step vertex infos
173  auto locEverythingFoundFlag = (dTimeOffsets.find(std::make_tuple(locIsPrimaryProductionVertex, locReactionFullCombo, (const DKinematicData*)nullptr)) != dTimeOffsets.end());
174 
175  //loop over vertices in dependency order
176  map<pair<int, int>, const DKinematicData*> locReconDecayParticleMap; //decaying particle indices -> kinematic data //indices: when the decaying particle is in the INITIAL state
177  for(const auto& locStepVertexInfo : locReactionVertexInfo->Get_StepVertexInfos())
178  {
179  if(locStepVertexInfo->Get_DanglingVertexFlag())
180  continue; //is forever indeterminate, even with neutrals and beam energy
181 
182  auto locIsProductionVertexFlag = locStepVertexInfo->Get_ProductionVertexFlag();
183  auto locVertexPrimaryChargedCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionChargedCombo, locStepVertexInfo);
184  auto locIsChargedCombo2ndVertex = locStepVertexInfo->Get_FullConstrainParticles(false, d_EitherState, d_AllCharges, false).empty();
185  auto locVertexPrimaryFullCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionFullCombo, locStepVertexInfo);
186 
187  //see if vertex has already been found
188  auto locFullComboProductionTuple = std::make_tuple(locIsProductionVertexFlag, (const DSourceCombo*)nullptr, locVertexPrimaryFullCombo, (const DKinematicData*)nullptr, false);
189  auto locChargedComboProductionTuple = std::make_tuple(locIsProductionVertexFlag, (const DSourceCombo*)nullptr, locVertexPrimaryChargedCombo, (const DKinematicData*)nullptr, locIsChargedCombo2ndVertex);
190  if(dConstrainingParticlesByCombo.find(locChargedComboProductionTuple) != dConstrainingParticlesByCombo.end())
191  {
192  //already done! get/construct any recon decaying particles
193  auto locVertex = Get_Vertex_NoBeam(locIsProductionVertexFlag, locVertexPrimaryChargedCombo, locIsChargedCombo2ndVertex);
194  auto locVertexParticles = dConstrainingParticlesByCombo[locChargedComboProductionTuple];
195  dConstrainingParticlesByCombo.emplace(locFullComboProductionTuple, locVertexParticles); //so that the vertex can be retrieved by either the charged or full combo
196  Construct_DecayingParticle_InvariantMass(locStepVertexInfo, locVertexPrimaryFullCombo, locVertex, locReconDecayParticleMap);
197  continue;
198  }
199 
200  //get particles
201  auto locChargedSourceParticles = DAnalysis::Get_SourceParticles_ThisVertex(locVertexPrimaryChargedCombo);
202  auto locDecayingParticles = Get_FullConstrainDecayingParticles(locStepVertexInfo, locReconDecayParticleMap);
203 
204  //now, just because it isn't dangling, it doesn't mean we have enough information to actually determine the vertex
205  //e.g. we may need beam energy to define constraining decay particle p4/trajectory
206  auto locDeterminableIterator = dVertexDeterminableWithPhotonsMap.find(locStepVertexInfo);
207  if(locDeterminableIterator == dVertexDeterminableWithPhotonsMap.end())
208  {
209  //we don't know yet if it is determinable or not. figure it out
210  auto locNumConstrainingParticles = locChargedSourceParticles.size() + locDecayingParticles.size();
211 
212  //determine it, save result, and continue if can't
213  bool locVertexDeterminableFlag = locIsProductionVertexFlag ? (locNumConstrainingParticles > 0) : (locNumConstrainingParticles > 1);
214  dVertexDeterminableWithPhotonsMap.emplace(locStepVertexInfo, locVertexDeterminableFlag);
215  if(!locVertexDeterminableFlag)
216  continue; //can't determine yet, but will be able to in the future
217  }
218  else if(!locDeterminableIterator->second)
219  continue;
220  if(locEverythingFoundFlag)
221  return; //already done
222 
223  //find the vertex, save the results
224  DVector3 locVertex;
225  if(dConstrainingParticlesByCombo.find(locFullComboProductionTuple) == dConstrainingParticlesByCombo.end())
226  {
227  vector<const DKinematicData*> locVertexParticles;
228  locVertex = Calc_Vertex(locIsProductionVertexFlag, locChargedSourceParticles, locDecayingParticles, locVertexParticles);
229  dConstrainingParticlesByCombo.emplace(locFullComboProductionTuple, locVertexParticles);
230  }
231  else //vertex found previously //we didn't check this earlier because we may need the decaying particle reconstructed below
232  locVertex = Get_Vertex(locIsProductionVertexFlag, dConstrainingParticlesByCombo[locFullComboProductionTuple]);
233 
234  Construct_DecayingParticle_InvariantMass(locStepVertexInfo, locVertexPrimaryFullCombo, locVertex, locReconDecayParticleMap);
235  }
236  if(locEverythingFoundFlag)
237  return; //already done
238 
239  //CALC TIME OFFSETS
240  Calc_TimeOffsets(locReactionVertexInfo, locReactionChargedCombo, locReactionFullCombo);
241 }
242 
243 void DSourceComboVertexer::Calc_VertexTimeOffsets_WithBeam(const DReactionVertexInfo* locReactionVertexInfo, const DSourceComboUse& locReactionFullComboUse, const DSourceCombo* locReactionFullCombo, const DKinematicData* locBeamParticle)
244 {
245  if(dDebugLevel >= 10)
246  cout << "DSourceComboVertexer::Calc_VertexTimeOffsets_WithBeam()" << endl;
247 
248  //IF PRIMARY VERTEX IS UNKNOWN THEN DO NOTHING!
249  if(!Get_IsVertexKnown_NoBeam(true, locReactionFullCombo, false))
250  {
251  if(dDebugLevel >= 10)
252  cout << "primary vertex unknown, nothing we can do." << endl;
253  return;
254  }
255 
256  auto locPrimaryVertexZ = Get_PrimaryVertex(locReactionVertexInfo, locReactionFullCombo, locBeamParticle).Z();
257  int locRFBunch = dSourceComboTimeHandler->Calc_RFBunchShift(locBeamParticle->time());
258  if(dDebugLevel >= 10)
259  cout << "primary vertex-z, rf bunch: " << locPrimaryVertexZ << ", " << locRFBunch << endl;
260 
261  //uses the beam to define remaining vertices
262  //loop over vertices in dependency order
263  map<pair<int, int>, const DKinematicData*> locReconDecayParticleMap; //decaying particle indices -> kinematic data //indices: when the decaying particle is in the INITIAL state
264  for(const auto& locStepVertexInfo : locReactionVertexInfo->Get_StepVertexInfos())
265  {
266  if(dDebugLevel >= 10)
267  cout << "Step: " << locStepVertexInfo->Get_StepIndices().front() << ", dangling-flag = " << locStepVertexInfo->Get_DanglingVertexFlag() << endl;
268  if(locStepVertexInfo->Get_DanglingVertexFlag())
269  continue; //is forever indeterminate, even with beam energy
270 
271  auto locIsProductionVertexFlag = locStepVertexInfo->Get_ProductionVertexFlag();
272  auto locVertexPrimaryFullCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionFullCombo, locStepVertexInfo);
273  if(dDebugLevel >= 10)
274  {
275  cout << "Vertex primary combo:" << endl;
276  DAnalysis::Print_SourceCombo(locVertexPrimaryFullCombo);
277  }
278 
279  //see if vertex has already been found //can search with either charged or full
280  auto locFullComboProductionTuple = std::make_tuple(true, locReactionFullCombo, locVertexPrimaryFullCombo, locBeamParticle, false);
281  if(dDebugLevel >= 20)
282  cout << "is determinable by charge/neutral: " << Get_VertexDeterminableWithCharged(locStepVertexInfo) << ", " << Get_VertexDeterminableWithPhotons(locStepVertexInfo) << endl;
283  if(Get_VertexDeterminableWithCharged(locStepVertexInfo) || Get_VertexDeterminableWithPhotons(locStepVertexInfo))
284  {
285  if(dDebugLevel >= 10)
286  cout << "vertex already found" << endl;
287 
288  //already done! get/construct any recon decaying particles
289  auto locVertex = Get_Vertex(locIsProductionVertexFlag, locReactionFullCombo, locVertexPrimaryFullCombo, locBeamParticle, false);
290  Construct_DecayingParticle_InvariantMass(locStepVertexInfo, locVertexPrimaryFullCombo, locVertex, locReconDecayParticleMap);
291  if(locIsProductionVertexFlag) //do missing if needed
292  {
293  auto locRFVertexTime = dSourceComboTimeHandler->Calc_PropagatedRFTime(locPrimaryVertexZ, locRFBunch, 0.0);
294  Construct_DecayingParticle_MissingMass(locStepVertexInfo, locReactionFullComboUse, locReactionFullCombo, locVertexPrimaryFullCombo, locBeamParticle, locVertex, locRFBunch, locRFVertexTime, locReconDecayParticleMap);
295  }
296  continue;
297  }
298 
299  if(dDebugLevel >= 10)
300  cout << "vertex not found yet" << endl;
301 
302  //get particles
303  auto locChargedSourceParticles = DAnalysis::Get_SourceParticles_ThisVertex(locVertexPrimaryFullCombo, d_Charged);
304  auto locDecayingParticles = Get_FullConstrainDecayingParticles(locStepVertexInfo, locReconDecayParticleMap);
305  if(dDebugLevel >= 10)
306  cout << "# charged/decaying particles at vertex = " << locChargedSourceParticles.size() << ", " << locDecayingParticles.size() << endl;
307 
308  //find the vertex, save the results
309  vector<const DKinematicData*> locVertexParticles;
310  auto locVertex = Calc_Vertex(locIsProductionVertexFlag, locChargedSourceParticles, locDecayingParticles, locVertexParticles);
311  dConstrainingParticlesByCombo.emplace(locFullComboProductionTuple, locVertexParticles);
312 
313  //CALC AND STORE TIME OFFSET
314  auto locFullReactionTuple_TimeOffset = std::make_tuple(true, locReactionFullCombo, locBeamParticle);
315 
316  //get parent
317  auto locParentVertexInfo = locStepVertexInfo->Get_ParentVertexInfo();
318  auto locParentVertexFullCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionFullCombo, locParentVertexInfo);
319  auto locParentTimeOffset = dTimeOffsets[locFullReactionTuple_TimeOffset][locParentVertexFullCombo];
320 
321  //get vertices & path length
322  auto locParentProductionVertex = Get_Vertex(locParentVertexInfo->Get_ProductionVertexFlag(), locReactionFullCombo, locParentVertexFullCombo, locBeamParticle, false);
323  auto locPathLength = (locVertex - locParentProductionVertex).Mag();
324 
325  //compute and save result
326  auto locP4 = locDecayingParticles.back()->lorentzMomentum(); //when locDecayingParticles retrieved, this particle was saved to the back!
327  auto locTimeOffset = locPathLength/(locP4.Beta()*SPEED_OF_LIGHT) + locParentTimeOffset;
328  dTimeOffsets[locFullReactionTuple_TimeOffset].emplace(locVertexPrimaryFullCombo, locTimeOffset);
329 
330  //construct decaying particles by missing mass
331  auto locRFVertexTime = dSourceComboTimeHandler->Calc_PropagatedRFTime(locPrimaryVertexZ, locRFBunch, locTimeOffset);
332  if(dDebugLevel >= 10)
333  cout << "parent time offset, beta, path length, time offset, prop rf time: " << locParentTimeOffset << ", " << locP4.Beta() << ", " << locPathLength << ", " << locTimeOffset << ", " << locRFVertexTime << endl;
334  Construct_DecayingParticle_MissingMass(locStepVertexInfo, locReactionFullComboUse, locReactionFullCombo, locVertexPrimaryFullCombo, locBeamParticle, locVertex, locRFBunch, locRFVertexTime, locReconDecayParticleMap);
335  }
336 }
337 
338 DVector3 DSourceComboVertexer::Calc_Vertex(bool locIsProductionVertexFlag, const vector<pair<Particle_t, const JObject*>>& locChargedSourceParticles, const vector<const DKinematicData*>& locDecayingParticles, vector<const DKinematicData*>& locVertexParticles)
339 {
340  if(dDebugLevel >= 10)
341  cout << "DSourceComboVertexer::Calc_Vertex()" << endl;
342 
343  /************************************************** CALCULATING VERTEX POSITIONS ***********************************************
344  *
345  * Production vertex:
346  * 1) If there is at least one charged track at the production vertex with a theta > 30 degrees:
347  * The production vertex is the POCA to the beamline of the track with the largest theta.
348  * 2) If not, then for each detached vertex:
349  * a) If there are any neutral or missing particles, or there are < 2 detected charged tracks at the detached vertex: ignore it
350  * b) Otherwise:
351  * i) The detached vertex is at the center of the lines between the POCAs of the two closest tracks.
352  * ii) Calculate the p3 of the decaying particles at this point and then find the POCA of the decaying particle to the beamline.
353  * 3) Now, the production vertex is the POCA to the beamline of the track/decaying-particle with the largest theta.
354  * 4) Otherwise, the production vertex is the center of the target.
355  *
356  * Detached vertices:
357  * 1) If at least 2 decay products have defined trajectories (detected & charged or decaying & reconstructed):
358  * The detached vertex is at the center of the lines between the POCAs of the two closest particles.
359  * 2) If one decay product is detected & charged, and the decaying particle production vertex was well defined (i.e. not forced to be center of target):
360  * a) Determine the decaying particle trajectory from the missing mass of the system (must be done after beam photon selection!!)
361  * b) The detached vertex is at the POCA of the charged decay product and the decaying particle
362  * 3) Otherwise use the decaying particle production vertex for its position.
363  *
364  *******************************************************************************************************************************/
365 
366  //Get detected charged track hypotheses at this vertex
367  locVertexParticles.clear();
368  locVertexParticles.reserve(locChargedSourceParticles.size());
369  auto Get_Hypothesis = [](const pair<Particle_t, const JObject*>& locPair) -> const DChargedTrackHypothesis*
370  {return static_cast<const DChargedTrack*>(locPair.second)->Get_Hypothesis(locPair.first);};
371  std::transform(locChargedSourceParticles.begin(), locChargedSourceParticles.end(), std::back_inserter(locVertexParticles), Get_Hypothesis);
372  locVertexParticles.insert(locVertexParticles.end(), locDecayingParticles.begin(), locDecayingParticles.end());
373 
374  if(dDebugLevel >= 10)
375  cout << "locIsProductionVertexFlag = " << locIsProductionVertexFlag << endl;
376  if(locIsProductionVertexFlag)
377  {
378  //use track with theta nearest 90 degrees
379  auto locThetaNearest90Iterator = Get_ThetaNearest90Iterator(locVertexParticles);
380  double locThetaNearest90 = (locThetaNearest90Iterator != locVertexParticles.end()) ? (*locThetaNearest90Iterator)->momentum().Theta()*180.0/TMath::Pi() : 0.0;
381  if(locThetaNearest90 < dMinThetaForVertex)
382  {
383  //try decaying particles instead
384  auto locThetaNearest90Iterator_Decaying = Get_ThetaNearest90Iterator(locDecayingParticles);
385  double locLargestTheta_Decaying = (locThetaNearest90Iterator_Decaying != locDecayingParticles.end()) ? (*locThetaNearest90Iterator_Decaying)->momentum().Theta()*180.0/TMath::Pi() : 0.0;
386  if(locLargestTheta_Decaying > locThetaNearest90)
387  locThetaNearest90Iterator = locThetaNearest90Iterator_Decaying;
388  }
389  locVertexParticles = {*locThetaNearest90Iterator};
390  auto locPOCAToBeamline = locVertexParticles[0]->position(); //not true if decaying
391 
392  //see if is a decaying particle
393  if(std::find(locDecayingParticles.begin(), locDecayingParticles.end(), locVertexParticles[0]) != locDecayingParticles.end())
394  {
395  //it is decaying: find POCA to beamline
396  DVector3 locInterDOCA1, locInterDOCA2;
397  dAnalysisUtilities->Calc_DOCA(locVertexParticles[0]->momentum().Unit(), DVector3(0.0, 0.0, 1.0), locPOCAToBeamline, DVector3(), locInterDOCA1, locInterDOCA2);
398  locPOCAToBeamline = locInterDOCA1;
399  }
400 
401  //vertex is 1/2-way between track POCA to beamline and the beamline itself: if POCA not on beamline, likely due to resolution issues,
402  auto locTrackPosition = locVertexParticles[0]->position();
403  auto locVertex = DVector3(0.5*locTrackPosition.X(), 0.5*locTrackPosition.Y(), locTrackPosition.Z());
404  if(false) //COMPARE: Comparison-to-old mode
405  locVertex = dVertex->dSpacetimeVertex.Vect();
406  dVertexMap.emplace(std::make_pair(locIsProductionVertexFlag, locVertexParticles), locVertex);
407  if(dDebugLevel >= 10)
408  cout << "pointer, particle PID, theta, production vertex = " << locVertexParticles[0] << ", " << locVertexParticles[0]->PID() << ", " << locVertexParticles[0]->momentum().Theta()*180.0/TMath::Pi() << ", " << locVertex.X() << ", " << locVertex.Y() << ", " << locVertex.Z() << endl;
409  return locVertex;
410  }
411 
412  //detached vertex
413  if(locVertexParticles.size() < 2)
414  locVertexParticles.insert(locVertexParticles.end(), locDecayingParticles.begin(), locDecayingParticles.end());
415  std::sort(locVertexParticles.begin(), locVertexParticles.end());
416 
417  //if vertex already computed, don't bother
418  auto locVertexIterator = dVertexMap.find(std::make_pair(locIsProductionVertexFlag, locVertexParticles));
419  if(locVertexIterator == dVertexMap.end())
420  {
421  auto locVertex = dAnalysisUtilities->Calc_CrudeVertex(locVertexParticles);
422  if(dDebugLevel >= 10)
423  cout << "crude vertex = " << locVertex.X() << ", " << locVertex.Y() << ", " << locVertex.Z() << endl;
424  dVertexMap.emplace(std::make_pair(locIsProductionVertexFlag, locVertexParticles), locVertex);
425  return locVertex;
426  }
427  else if(dDebugLevel >= 10)
428  cout << "crude vertex saved previously = " << locVertexIterator->second.X() << ", " << locVertexIterator->second.Y() << ", " << locVertexIterator->second.Z() << endl;
429 
430  return locVertexIterator->second;
431 }
432 
433 vector<const DKinematicData*> DSourceComboVertexer::Get_FullConstrainDecayingParticles(const DReactionStepVertexInfo* locStepVertexInfo, const map<pair<int, int>, const DKinematicData*>& locReconDecayParticleMap)
434 {
435  auto locConstrainingDecayingParticles = locStepVertexInfo->Get_DecayingParticles_FullConstrain(false);
436  vector<const DKinematicData*> locDecayingParticles;
437  pair<int, int> locDecayMissingMassReconPair(-99, -99); //if there is one (and there will be at most one), save for last (easy to retrieve)
438  for(const auto& locDecayPair : locConstrainingDecayingParticles)
439  {
440  //the particle pair in the map is where the decaying particle was when it was created (in the initial/final state for invariant/missing mass)
441  //however, the pairs in locConstrainingDecayingParticles are when then the decaying particles are USED (the other state)
442  //so, we have to convert from final state to initial state (or vice versa) to do the map lookup
443  pair<int, int> locParticlePair(-99, -99);
444  if(locDecayPair.first.second >= 0) //need it in the final state, was created in the initial state: convert from final to initial for map lookup
445  {
446  int locDecayStepIndex = DAnalysis::Get_DecayStepIndex(locStepVertexInfo->Get_Reaction(), locDecayPair.first.first, locDecayPair.first.second);
447  locParticlePair = std::make_pair(locDecayStepIndex, DReactionStep::Get_ParticleIndex_Initial());
448  }
449  else //need it in the initial state, was created in the final state: convert: convert from initial to final for map lookup
450  {
451  locDecayMissingMassReconPair = DAnalysis::Get_InitialParticleDecayFromIndices(locStepVertexInfo->Get_Reaction(), locDecayPair.first.first);
452  continue;
453  }
454 
455  auto locReconIterator = locReconDecayParticleMap.find(locParticlePair);
456  if(locReconIterator != locReconDecayParticleMap.end())
457  locDecayingParticles.push_back(locReconIterator->second);
458  }
459 
460  //retrieve the decay missing-mass recon particle, if there was one
461  auto locReconIterator = locReconDecayParticleMap.find(locDecayMissingMassReconPair);
462  if(locReconIterator != locReconDecayParticleMap.end())
463  locDecayingParticles.push_back(locReconIterator->second);
464 
465  return locDecayingParticles;
466 }
467 
468 void DSourceComboVertexer::Construct_DecayingParticle_InvariantMass(const DReactionStepVertexInfo* locStepVertexInfo, const DSourceCombo* locVertexCombo, DVector3 locVertex, map<pair<int, int>, const DKinematicData*>& locReconDecayParticleMap)
469 {
470  if(dDebugLevel >= 10)
471  cout << "DSourceComboVertexer::Construct_DecayingParticle_InvariantMass()" << endl;
472  //we also can't compute the p4 yet if the decay products contain neutrals: this is done before comboing them!
473  auto locSourceComboUse = dSourceComboer->Get_SourceComboUse(locStepVertexInfo);
474  if(dSourceComboer->Get_HasMassiveNeutrals(std::get<2>(locSourceComboUse)))
475  {
476  //can't compute the p4 yet if the decay products contain massive neutrals: time offset is needed for massive neutral p4, but isn't known yet because decay p4 unknown!
477  //will have to be computed via missing mass instead (although it technically isn't needed for it)
478  return;
479  }
480 
481  auto locIsProductionVertexFlag = locStepVertexInfo->Get_ProductionVertexFlag();
482  if(dDebugLevel >= 10)
483  cout << "locIsProductionVertexFlag = " << locIsProductionVertexFlag << endl;
484 
485  //loop over decaying no-constrain decaying particles
486  map<pair<int, int>, const DReactionStepVertexInfo*> locNoConstrainDecayingParticles = locStepVertexInfo->Get_DecayingParticles_NoConstrain(false);
487  for(const auto& locNoConstrainPair : locNoConstrainDecayingParticles)
488  {
489  //we cannot define decaying p4 via missing mass, because the beam is not chosen yet
490  //therefore, if the no-constrain decaying particle is a final-state particle at this vertex, we cannot define its p4
491  const auto& locParticlePair = locNoConstrainPair.first;
492  if(locParticlePair.second >= 0)
493  continue; //momentum must be determined by missing mass, cannot do yet! (or isn't detached, for which we don't care)
494 
495  //only create kinematic data for detached PIDs
496  auto locDecayPID = std::get<0>(locSourceComboUse);
497  if(!IsDetachedVertex(locDecayPID))
498  continue; //either not detached (we don't care!), or is Unknown (missing decay product: can't compute)
499 
500  if(dDebugLevel >= 10)
501  cout << "detached decaying pid = " << locDecayPID << endl;
502 
503  //if the particle has already been created, reuse it!
504  auto locDecayParticleTuple = std::make_tuple(locDecayPID, locIsProductionVertexFlag, locVertexCombo, (const DKinematicData*)nullptr);
505  auto locIterator = dReconDecayParticles_FromProducts.find(locDecayParticleTuple);
506  if(locIterator != dReconDecayParticles_FromProducts.end())
507  {
508  locReconDecayParticleMap.emplace(locParticlePair, locIterator->second);
509  continue;
510  }
511 
512  //create a new one
513  auto locP4 = dSourceComboP4Handler->Calc_P4_NoMassiveNeutrals(nullptr, locVertexCombo, locVertex, std::get<1>(locSourceComboUse), nullptr, DSourceComboUse(Unknown, 0, nullptr, false, Unknown), 1, false);
514  auto locKinematicData = dResourcePool_KinematicData.Get_Resource();
515  locKinematicData->Reset();
516  locKinematicData->Set_Members(locDecayPID, locP4.Vect(), locVertex, 0.0);
517 
518  if(dDebugLevel >= 10)
519  cout << "decaying particle created, pxyzE = " << locP4.X() << ", " << locP4.Y() << ", " << locP4.Z() << ", " << locP4.E() << endl;
520 
521  //register it
522  locReconDecayParticleMap.emplace(locParticlePair, locKinematicData);
523  dReconDecayParticles_FromProducts.emplace(locDecayParticleTuple, locKinematicData);
524  }
525 }
526 
527 void DSourceComboVertexer::Construct_DecayingParticle_MissingMass(const DReactionStepVertexInfo* locStepVertexInfo, const DSourceComboUse& locReactionFullComboUse, const DSourceCombo* locReactionFullCombo, const DSourceCombo* locFullVertexCombo, const DKinematicData* locBeamParticle, DVector3 locVertex, int locRFBunch, double locRFVertexTime, map<pair<int, int>, const DKinematicData*>& locReconDecayParticleMap)
528 {
529  if(dDebugLevel >= 10)
530  cout << "DSourceComboVertexer::Construct_DecayingParticle_MissingMass()" << endl;
531 
532  if(locStepVertexInfo->Get_IsInclusiveVertexFlag() || !locStepVertexInfo->Get_MissingParticles().empty())
533  return; //decaying particles are not defined!
534 
535  //we can only calculate up to 1 at a time
536  //the input full combo contains the decaying particle for which the missing mass is to be computed
537  //if there is more than one, then this is impossible
538 
539  auto locSourceComboUse = dSourceComboer->Get_SourceComboUse(locStepVertexInfo);
540  auto locReaction = locStepVertexInfo->Get_Reaction();
541  auto locIsProductionVertexFlag = locStepVertexInfo->Get_ProductionVertexFlag();
542 
543  //loop over decaying no-constrain decaying particles, figure out how many we have to do this for (can't do more than 1!)
544  map<pair<int, int>, const DReactionStepVertexInfo*> locNoConstrainDecayingParticles = locStepVertexInfo->Get_DecayingParticles_NoConstrain(false);
545  pair<int, int> locToReconParticleIndices(-99, -99);
546  for(const auto& locNoConstrainPair : locNoConstrainDecayingParticles)
547  {
548  //we are defining p4 through missing mass. therefore, the decaying particle must be in the final state at this vertex
549  //therefore, if the no-constrain decaying particle is a final-state particle at this vertex, we cannot define its p4
550  const auto& locParticlePair = locNoConstrainPair.first;
551  if(locParticlePair.second < 0)
552  continue; //momentum already determined by invariant mass!
553 
554  //the particle must be a constraining particle at another vertex, or else we aren't interested (i.e. detached)
555  auto locReactionStep = locReaction->Get_ReactionStep(locParticlePair.first);
556  auto locDecayPID = locReactionStep->Get_PID(locParticlePair.second);
557  if(!IsDetachedVertex(locDecayPID))
558  continue; //not detached: we don't care!
559 
560  if(locToReconParticleIndices.first >= 0)
561  return; //can't recon more than 1 decaying particle via missing mass!
562  locToReconParticleIndices = locParticlePair;
563  }
564 
565  if(dDebugLevel >= 10)
566  cout << "to-recon decay particle indices: " << locToReconParticleIndices.first << ", " << locToReconParticleIndices.second << endl;
567  if(locToReconParticleIndices.first < 0)
568  return;
569 
570  auto locDecayStepIndex = Get_DecayStepIndex(locReaction, locToReconParticleIndices.first, locToReconParticleIndices.second);
571  auto locDecayUsePair = dSourceComboer->Get_StepSourceComboUse(locReaction, locDecayStepIndex, locReactionFullComboUse, 0);
572 
573  auto locReactionStep = locReaction->Get_ReactionStep(locToReconParticleIndices.first);
574  auto locDecayPID = locReactionStep->Get_PID(locToReconParticleIndices.second);
575 
576  //if the particle has already been created, reuse it!
577  auto locDecayParticleTuple = std::make_tuple(locDecayPID, locReactionFullCombo, locIsProductionVertexFlag, locFullVertexCombo, locBeamParticle);
578  auto locIterator = dReconDecayParticles_FromMissing.find(locDecayParticleTuple);
579  if(locIterator != dReconDecayParticles_FromMissing.end())
580  {
581  locReconDecayParticleMap.emplace(locToReconParticleIndices, locIterator->second);
582  return;
583  }
584 
585  //make sure there isn't another missing particle
586  for(const auto& locStepIndex : locStepVertexInfo->Get_StepIndices())
587  {
588  if(int(locStepIndex) == locDecayStepIndex)
589  continue;
590  if(DAnalysis::Get_HasMissingParticle_FinalState(locReaction->Get_ReactionStep(locStepIndex)))
591  return; //missing decay product! can't compute 2 missing p4's at once!
592  }
593 
594  //create a new one
595  //calc final state p4, excluding the decay use for the decay that we are trying to reconstruct via missing mass
596  DLorentzVector locFinalStateP4;
597  if(dDebugLevel >= 10)
598  {
599  cout << "Calc final-state p4, decay use to exclude: " << endl;
600  DAnalysis::Print_SourceComboUse(locDecayUsePair.first);
601  }
602 
603  auto locTimeOffset = Get_TimeOffset(true, locReactionFullCombo, locFullVertexCombo, locBeamParticle);
604  if(!dSourceComboP4Handler->Calc_P4_HasMassiveNeutrals(locIsProductionVertexFlag, true, locReactionFullCombo, locFullVertexCombo, locVertex, locTimeOffset, locRFBunch, locRFVertexTime, locDecayUsePair.first, locDecayUsePair.second, locFinalStateP4, locBeamParticle, true))
605  return; //invalid somehow
606 
607  //ASSUMES FIXED TARGET EXPERIMENT!
608  DLorentzVector locInitialStateP4; //lookup or is beam + target
609  if(locIsProductionVertexFlag)
610  {
611  Particle_t locPID = locReaction->Get_ReactionStep(0)->Get_TargetPID();
612  locInitialStateP4 = locBeamParticle->lorentzMomentum() + DLorentzVector(0.0, 0.0, 0.0, ParticleMass(locPID));
613  }
614  else //already computed, look it up!
615  {
616  auto locPreviousVertexInfo = (locStepVertexInfo->Get_ParentVertexInfo() == nullptr) ? locStepVertexInfo : locStepVertexInfo->Get_ParentVertexInfo();
617  auto locPreviousIsProdVertexFlag = locPreviousVertexInfo->Get_ProductionVertexFlag();
618  auto locPreviousFullVertexCombo = dSourceComboer->Get_VertexPrimaryCombo(locReactionFullCombo, locPreviousVertexInfo);
619  auto locPreviousDecayPID = std::get<0>(locSourceComboUse);
620  auto locPreviousDecayParticleTuple = std::make_tuple(locPreviousDecayPID, locReactionFullCombo, locPreviousIsProdVertexFlag, locPreviousFullVertexCombo, locBeamParticle);
621  auto locPreviousIterator = dReconDecayParticles_FromMissing.find(locPreviousDecayParticleTuple);
622  if(locPreviousIterator != dReconDecayParticles_FromMissing.end())
623  locInitialStateP4 = dReconDecayParticles_FromMissing[locPreviousDecayParticleTuple]->lorentzMomentum();
624  else //if the previous vertex only had additional photons, it might not be computed yet
625  return;
626  if(dDebugLevel >= 10)
627  cout << "retrieved decaying pid, p4: " << locPreviousDecayPID << ", " << locInitialStateP4.Px() << ", " << locInitialStateP4.Py() << ", " << locInitialStateP4.Pz() << ", " << locInitialStateP4.E() << endl;
628  }
629 
630  auto locP4 = locInitialStateP4 - locFinalStateP4;
631  if(dDebugLevel >= 10)
632  cout << "pid, missing p4: " << locDecayPID << ", " << locP4.Px() << ", " << locP4.Py() << ", " << locP4.Pz() << ", " << locP4.E() << endl;
633  auto locKinematicData = dResourcePool_KinematicData.Get_Resource();
634  locKinematicData->Reset();
635  locKinematicData->Set_Members(locDecayPID, locP4.Vect(), locVertex, 0.0);
636 
637  //register it
638  locReconDecayParticleMap.emplace(locToReconParticleIndices, locKinematicData);
639  dReconDecayParticles_FromMissing.emplace(locDecayParticleTuple, locKinematicData);
640 }
641 
642 void DSourceComboVertexer::Calc_TimeOffsets(const DReactionVertexInfo* locReactionVertexInfo, const DSourceCombo* locChargedReactionCombo, const DSourceCombo* locFullReactionCombo)
643 {
644  if(dDebugLevel >= 10)
645  cout << "DSourceComboVertexer::Calc_TimeOffsets()" << endl;
646 
647  //only for calculating from invariant mass, not missing mass vertices
648  auto locIsPrimaryProductionVertex = locReactionVertexInfo->Get_StepVertexInfo(0)->Get_ProductionVertexFlag();
649  auto locActiveReactionCombo = (locFullReactionCombo != nullptr) ? locFullReactionCombo : locChargedReactionCombo;
650 
651  auto locChargedReactionTuple = std::make_tuple(locIsPrimaryProductionVertex, locChargedReactionCombo, (const DKinematicData*)nullptr);
652  auto locNeutralReactionTuple = std::make_tuple(locIsPrimaryProductionVertex, locFullReactionCombo, (const DKinematicData*)nullptr);
653 
654  auto& locChargedTimeOffsetMap = dTimeOffsets[locChargedReactionTuple];
655  auto& locFullTimeOffsetMap = dTimeOffsets[locNeutralReactionTuple];
656  auto& locActiveTimeOffsetMap = (locFullReactionCombo != nullptr) ? locFullTimeOffsetMap : locChargedTimeOffsetMap;
657 
658  //loop over vertices
659  //MUST GO IN STEP ORDER!!
660  for(const auto& locStepVertexInfo : DAnalysis::Get_StepVertexInfos_OrderByStep(locReactionVertexInfo))
661  {
662  if(dDebugLevel >= 10)
663  cout << "Step: " << locStepVertexInfo->Get_StepIndices().front() << endl;
664  if(locStepVertexInfo->Get_DanglingVertexFlag())
665  continue; //is forever indeterminate, even with beam energy
666 
667  auto locChargedVertexCombo = dSourceComboer->Get_VertexPrimaryCombo(locChargedReactionCombo, locStepVertexInfo);
668  auto locFullVertexCombo = (locFullReactionCombo != nullptr) ? dSourceComboer->Get_VertexPrimaryCombo(locFullReactionCombo, locStepVertexInfo) : nullptr;
669  auto locActiveVertexCombo = (locFullReactionCombo != nullptr) ? locFullVertexCombo : locChargedVertexCombo;
670 
671  //see if already determined
672  auto locActiveIterator = locActiveTimeOffsetMap.find(locFullVertexCombo);
673  if(locActiveIterator != locActiveTimeOffsetMap.end())
674  continue; //previously determined!
675 
676  //see if at full-combo stage (not charged only). If so, and offset already found at charged stage, just copy the result
677  if(locFullReactionCombo != nullptr) //full stage
678  {
679  auto locChargedIterator = locChargedTimeOffsetMap.find(locChargedVertexCombo);
680  if(locChargedIterator != locChargedTimeOffsetMap.end())
681  {
682  //save in full map
683  locFullTimeOffsetMap.emplace(locFullVertexCombo, locChargedIterator->second);
684  continue; //previously determined!
685  }
686  }
687 
688  auto locParentVertexInfo = locStepVertexInfo->Get_ParentVertexInfo();
689  if(locStepVertexInfo->Get_ProductionVertexFlag() || (locParentVertexInfo == nullptr))
690  {
691  if(dDebugLevel >= 10)
692  cout << "Primary vertex: time offset = 0" << endl;
693  locChargedTimeOffsetMap.emplace(locChargedReactionCombo, 0.0);
694  continue;
695  }
696 
697  //if this vertex has not been determined yet: save calcing of time offset for later
698  if((locFullReactionCombo == nullptr) && !Get_VertexDeterminableWithCharged(locStepVertexInfo))
699  continue; //don't know the vertex yet, try the next vertex
700  if((locFullReactionCombo != nullptr) && !Get_VertexDeterminableWithCharged(locStepVertexInfo) && !Get_VertexDeterminableWithPhotons(locStepVertexInfo))
701  continue; //don't know the vertex yet, try the next vertex
702 
703  //the time offset cannot yet be determined if the momentum of the decaying particle in question is not yet known
704  //this can happen if there's a missing decay product, or if we're on the charged stage and some of the decay products are neutrals
705  //we also can't calculate by missing mass yet because we haven't yet selected a beam photon
706  auto locVertexComboUse = dSourceComboer->Get_SourceComboUse(locStepVertexInfo);
707  if(std::get<3>(locVertexComboUse) || ((locFullReactionCombo == nullptr) && (Get_ChargeContent(std::get<2>(locVertexComboUse)) != d_Charged)))
708  continue; //1st condition: has a missing decay product //2nd condition: on charged stage, has neutral decay products (not comboed yet)
709 
710  //get parent information
711  auto locParentCombo = dSourceComboer->Get_VertexPrimaryCombo(locActiveReactionCombo, locParentVertexInfo);
712  auto locParentOffsetIterator = locActiveTimeOffsetMap.find(locParentCombo);
713  if(locParentOffsetIterator == locActiveTimeOffsetMap.end())
714  continue; //parent offset unknown
715  auto locParentTimeOffset = locParentOffsetIterator->second;
716 
717  if(dDebugLevel >= 10)
718  cout << "Parent time offset = " << locParentTimeOffset << endl;
719 
720  //get vertices & path length
721  auto locVertex = Get_Vertex_NoBeam(false, locActiveVertexCombo, false); //2nd false: if true, then we're on the charged stage and we can't calc the time offset: wouldn't be here anyway
722  auto locParentProductionVertex = Get_Vertex_NoBeam(locParentVertexInfo->Get_ProductionVertexFlag(), locParentCombo, false);
723  auto locPathLength = (locVertex - locParentProductionVertex).Mag();
724  if(dDebugLevel >= 10)
725  cout << "Vertex, parent vertex, path length: " << locVertex.X() << ", " << locVertex.Y() << ", " << locVertex.Z() << ", " << locParentProductionVertex.X() << ", " << locParentProductionVertex.Y() << ", " << locParentProductionVertex.Z() << ", " << locPathLength << endl;
726 
727  //compute and save result
728  auto locVertexZBin = Get_VertexZBin_NoBeam(false, locActiveVertexCombo, false); //2nd false: if true, then we're on the charged stage and we can't calc the time offset: wouldn't be here anyway
729  auto locP4 = dSourceComboP4Handler->Calc_P4_NoMassiveNeutrals(nullptr, locActiveVertexCombo, locVertex, locVertexZBin, nullptr, DSourceComboUse(Unknown, 0, nullptr, false, Unknown), 1, false);
730  auto locTimeOffset = locPathLength/(locP4.Beta()*SPEED_OF_LIGHT) + locParentTimeOffset;
731 
732  if(dDebugLevel >= 10)
733  cout << "Time offset = " << locTimeOffset << endl;
734 
735  locActiveTimeOffsetMap.emplace(locActiveVertexCombo, locTimeOffset);
736  }
737 }
738 
739 } //end DAnalysis namespace
740 
vector< pair< int, int > > Get_FullConstrainParticles(bool locFitFlag, DReactionState_t locState=d_EitherState, Charge_t locCharge=d_AllCharges, bool locIncludeDecayingFlag=true) const
pair< DSourceComboUse, size_t > Get_StepSourceComboUse(const DReaction *locReaction, size_t locDesiredStepIndex, DSourceComboUse locVertexPrimaryComboUse, size_t locVertexPrimaryStepIndex) const
bool Get_VertexDeterminableWithPhotons(const DReactionStepVertexInfo *locStepVertexInfo) const
signed char Get_VertexZBin_NoBeam(bool locIsProductionVertex, const DSourceCombo *locPrimaryVertexCombo, bool locIsCombo2ndVertex) const
double Get_TimeOffset(bool locIsPrimaryProductionVertex, const DSourceCombo *locReactionCombo, const DSourceCombo *locVertexCombo, const DKinematicData *locBeamParticle) const
#define SPEED_OF_LIGHT
static constexpr int Get_ParticleIndex_Initial(void)
pair< int, int > Get_InitialParticleDecayFromIndices(const DReaction *locReaction, int locStepIndex)
Definition: DReaction.cc:93
DSourceComboUse Get_SourceComboUse(const DReactionStepVertexInfo *locStepVertexInfo) const
unordered_map< const DReactionStepVertexInfo *, bool > dVertexDeterminableWithPhotonsMap
TVector3 DVector3
Definition: DVector3.h:14
void Calc_TimeOffsets(const DReactionVertexInfo *locReactionVertexInfo, const DSourceCombo *locChargedReactionCombo, const DSourceCombo *locFullReactionCombo=nullptr)
const DReactionStepVertexInfo * Get_StepVertexInfo(size_t locStepIndex) const
map< tuple< bool, const DSourceCombo *, const DSourceCombo *, const DKinematicData *, bool >, vector< const DKinematicData * > > dConstrainingParticlesByCombo
DVector3 Calc_Vertex(bool locIsProductionVertexFlag, const vector< pair< Particle_t, const JObject * >> &locChargedSourceParticles, const vector< const DKinematicData * > &locDecayingParticles, vector< const DKinematicData * > &locVertexParticles)
bool Get_VertexDeterminableWithCharged(const DReactionStepVertexInfo *locStepVertexInfo) const
map< pair< int, int >, const DReactionStepVertexInfo * > Get_DecayingParticles_FullConstrain(bool locFitFlag) const
vector< const DKinematicData * > Get_FullConstrainDecayingParticles(const DReactionStepVertexInfo *locStepVertexInfo, const map< pair< int, int >, const DKinematicData * > &locReconDecayParticleMap)
static unsigned short int IsDetachedVertex(Particle_t p)
Definition: particleType.h:817
DVector3 Get_Vertex(bool locIsProductionVertex, const DSourceCombo *locReactionCombo, const DSourceCombo *locVertexCombo, const DKinematicData *locBeamParticle, bool locIsCombo2ndVertex) const
vector< const DReactionStepVertexInfo * > Get_StepVertexInfos_OrderByStep(const DReactionVertexInfo *locReactionVertexInfo)
int Calc_RFBunchShift(double locTimeToStepTo) const
vector< pair< int, int > > Get_MissingParticles(DReactionState_t locState=d_EitherState, Charge_t locCharge=d_AllCharges) const
static signed char Get_VertexZIndex_Unknown(void)
Definition: DSourceCombo.h:82
TLorentzVector DLorentzVector
DVector3 Get_PrimaryVertex(const DReactionVertexInfo *locReactionVertexInfo, const DSourceCombo *locReactionCombo, const DKinematicData *locBeamParticle) const
const DSourceComboTimeHandler * dSourceComboTimeHandler
double Calc_DOCA(const DVector3 &locUnitDir1, const DVector3 &locUnitDir2, const DVector3 &locVertex1, const DVector3 &locVertex2) const
bool Get_HasMissingParticle_FinalState(const DReactionStep *locStep)
tuple< Particle_t, signed char, const DSourceComboInfo *, bool, Particle_t > DSourceComboUse
Definition: DSourceCombo.h:34
bool Calc_P4_HasMassiveNeutrals(bool locIsProductionVertex, bool locIsPrimaryProductionVertex, const DSourceCombo *locReactionFullCombo, const DSourceCombo *locCurrentCombo, DVector3 locVertex, double locTimeOffset, int locRFBunch, double locRFVertexTime, const DSourceComboUse &locToExcludeUse, size_t locInstanceToExclude, DLorentzVector &locTotalP4, const DKinematicData *locBeamParticle, bool locAccuratePhotonsFlag)
const DReactionStepVertexInfo * Get_ParentVertexInfo(void) const
double time(void) const
DType * Get_Resource(void)
const DReaction * Get_Reaction(void) const
Charge_t Get_ChargeContent(const DSourceComboInfo *locSourceComboInfo)
Definition: DSourceCombo.h:467
map< pair< bool, vector< const DKinematicData * > >, DVector3 > dVertexMap
const DAnalysisUtilities * dAnalysisUtilities
map< tuple< Particle_t, const DSourceCombo *, bool, const DSourceCombo *, const DKinematicData * >, const DKinematicData * > dReconDecayParticles_FromMissing
signed char Get_PhotonVertexZBin(double locVertexZ) const
DVector3 Calc_CrudeVertex(const vector< const DKinematicData * > &locParticles) const
signed char Get_VertexZBin(bool locIsProductionVertex, const DSourceCombo *locReactionCombo, const DSourceCombo *locPrimaryVertexCombo, const DKinematicData *locBeamParticle, bool locIsCombo2ndVertex) const
unordered_map< const DReactionStepVertexInfo *, bool > dVertexDeterminableWithChargedMap
DGeometry * GetDGeometry(unsigned int run_number)
void Calc_VertexTimeOffsets_WithBeam(const DReactionVertexInfo *locReactionVertexInfo, const DSourceComboUse &locReactionFullComboUse, const DSourceCombo *locReactionFullCombo, const DKinematicData *locBeamParticle)
vector< signed char > Get_VertexZBins(const DReactionVertexInfo *locReactionVertexInfo, const DSourceCombo *locReactionCombo, const DKinematicData *locBeamParticle, bool locComboIsFullyCharged) const
DLorentzVector dSpacetimeVertex
Definition: DVertex.h:28
map< tuple< Particle_t, bool, const DSourceCombo *, const DKinematicData * >, const DKinematicData * > dReconDecayParticles_FromProducts
void Construct_DecayingParticle_MissingMass(const DReactionStepVertexInfo *locReactionStepVertexInfo, const DSourceComboUse &locReactionFullComboUse, const DSourceCombo *locReactionFullCombo, const DSourceCombo *locFullVertexCombo, const DKinematicData *locBeamParticle, DVector3 locVertex, int locRFBunch, double locRFVertexTime, map< pair< int, int >, const DKinematicData * > &locReconDecayParticleMap)
DLorentzVector lorentzMomentum(void) const
static double ParticleMass(Particle_t p)
vector< const DReactionStepVertexInfo * > Get_StepVertexInfos(void) const
const DSourceCombo * Get_VertexPrimaryCombo(const DSourceCombo *locReactionCombo, const DReactionStepVertexInfo *locStepVertexInfo) const
void Print_SourceComboUse(const DSourceComboUse &locComboUse, unsigned char locNumTabs=0, bool locIgnoreTabs=false)
Definition: DSourceCombo.h:337
vector< const DKinematicData * > Get_ConstrainingParticles(bool locIsProductionVertex, const DSourceCombo *locReactionCombo, const DSourceCombo *locVertexCombo, const DKinematicData *locBeamParticle, bool locIsCombo2ndVertex) const
DSourceComboP4Handler * dSourceComboP4Handler
virtual void Reset(void)
void Construct_DecayingParticle_InvariantMass(const DReactionStepVertexInfo *locReactionStepVertexInfo, const DSourceCombo *locVertexCombo, DVector3 locVertex, map< pair< int, int >, const DKinematicData * > &locReconDecayParticleMap)
vector< const DSourceCombo * > Get_SourceCombos_ThisVertex(const DSourceCombo *locSourceCombo)
Definition: DSourceCombo.h:415
vector< pair< Particle_t, const JObject * > > Get_SourceParticles_ThisVertex(const DSourceCombo *locSourceCombo, Charge_t locCharge=d_AllCharges)
Definition: DSourceCombo.h:396
int Get_DecayStepIndex(const DReaction *locReaction, size_t locStepIndex, size_t locParticleIndex)
Definition: DReaction.cc:135
DVector3 Get_Vertex_NoBeam(bool locIsProductionVertex, const DSourceCombo *locVertexCombo, bool locIsCombo2ndVertex) const
bool Get_IsVertexKnown_NoBeam(bool locIsProductionVertex, const DSourceCombo *locVertexCombo, bool locIsCombo2ndVertex) const
map< tuple< bool, const DSourceCombo *, const DKinematicData * >, unordered_map< const DSourceCombo *, double > > dTimeOffsets
map< pair< int, int >, const DReactionStepVertexInfo * > Get_DecayingParticles_NoConstrain(bool locFitFlag) const
void Calc_VertexTimeOffsets_WithCharged(const DReactionVertexInfo *locReactionVertexInfo, const DSourceCombo *locReactionChargedCombo)
vector< size_t > Get_StepIndices(void) const
void Calc_VertexTimeOffsets_WithPhotons(const DReactionVertexInfo *locReactionVertexInfo, const DSourceCombo *locReactionChargedCombo, const DSourceCombo *locReactionFullCombo)
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
double Calc_PropagatedRFTime(double locPrimaryVertexZ, int locNumRFBunchShifts, double locDetachedVertexTimeOffset) const
bool Get_HasMassiveNeutrals(const DSourceComboInfo *locSourceComboInfo) const
DResourcePool< DKinematicData > dResourcePool_KinematicData
DLorentzVector Calc_P4_NoMassiveNeutrals(const DSourceCombo *locReactionCombo, const DSourceCombo *locVertexCombo, const DVector3 &locVertex, signed char locVertexZBin, const DKinematicData *locBeamParticle, const DSourceComboUse &locToExcludeUse, size_t locInstanceToExclude, bool locAccuratePhotonsFlag)
vector< const DKinematicData * >::const_iterator Get_ThetaNearest90Iterator(const vector< const DKinematicData * > &locParticles)
void Print_SourceCombo(const DSourceCombo *locCombo, unsigned char locNumTabs=0)
Definition: DSourceCombo.h:346
Particle_t
Definition: particleType.h:12