eventAnalysis  7.0-49-g0ac7482
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
TGlobalReconModule.cxx
Go to the documentation of this file.
1 #include <algorithm>
2 #include <functional>
3 #include <vector>
4 
5 #include <TG4VHit.hxx>
6 #include <retrieveHitTruthInfo.hxx>
7 #include <TG4Trajectory.hxx>
8 
9 #include "TDatum.hxx"
10 #include "TRealDatum.hxx"
11 #include "TReconNode.hxx"
12 #include "TReconShower.hxx"
13 #include "TReconTrack.hxx"
14 
15 #include "TGeomInfo.hxx"
16 
17 #include "TComboHit.hxx"
18 #include "TG4HitSegment.hxx"
19 #include "TReconHit.hxx"
20 #include "TTPCmcDigit.hxx"
21 
22 #include "TEventFolder.hxx"
23 #include "TRecPackManager.hxx"
24 #include "TValidationUtils.hxx"
25 
26 #include "ReconObjectUtils.hxx"
27 #include "ReconPrintout.hxx"
28 #include "TIntegerDatum.hxx"
29 #include "TrackTruthInfo.hxx"
30 #include "TrackingUtils.hxx"
31 #include "fgdUtils.hxx"
32 #include "pidUtils.hxx"
33 
34 #include "TReconStateUtilities.hxx"
35 #include "TTrackerReconUtils.hxx"
36 
38 
39 #include "TGlobalReconModule.hxx"
40 
41 const int NMAXALTERNATES = 6;
42 const int NMAXECAL = 5;
43 const int NMAXP0DECAL = 2;
44 const int NMAXTPC = 6;
45 const int NMAXFGD = 2;
46 const int NMAXSFG = 2;
47 const int NMAXP0D = 1;
48 const int NMAXSMRD = 4;
49 const int NMAXTRACKER = 10;
50 const int NMAXTPCOTHER = 20;
51 
52 const bool debug_kine = false;
53 const bool debug_pids = false;
54 const bool debug_broken = false;
55 const bool debug_extrap = false;
56 const bool debug_vertex_extrap = false;
57 
58 const int DEFAULT_MIN = 99999;
59 const int DEFAULT_MAX = -99999;
60 using std::cout;
61 using std::endl;
64 
67  TrueParticle;*/
68 }
69 
71  Alternates = new TClonesArray("ND::TGlobalReconModule::TGlobalPIDAlternate",
73  ECAL = new TClonesArray("ND::TGlobalReconModule::TECALObject", NMAXECAL);
74  P0DECAL =
75  new TClonesArray("ND::TGlobalReconModule::TECALObject", NMAXP0DECAL);
76  TPC = new TClonesArray("ND::TGlobalReconModule::TTPCObject", NMAXTPC);
77  FGD = new TClonesArray("ND::TGlobalReconModule::TFGDObject", NMAXFGD);
78  SFG = new TClonesArray("ND::TGlobalReconModule::TSFGObject", NMAXSFG);
79  P0D = new TClonesArray("ND::TGlobalReconModule::TP0DObject", NMAXP0D);
80  SMRD = new TClonesArray("ND::TGlobalReconModule::TSMRDObject", NMAXSMRD);
81  TRACKER =
82  new TClonesArray("ND::TGlobalReconModule::TTrackerObject", NMAXTRACKER);
83  HitsSaved = new TClonesArray("ND::TGlobalReconModule::TGlobalHit", 4);
84 
85  // TPC digit decoding is a little too verbose.
86  // Disable it here.
87  ND::TND280Log::SetLogLevel("eventUnpack", ND::TND280Log::QuietLevel);
88 
89  NAlternates = 0;
90  Alternates->Clear();
91 
92  NDsECALs = 0;
93  NTrECALs = 0;
94  NECALs = 0;
95  ECAL->Clear();
96 
97  NP0DECALs = 0;
98  P0DECAL->Clear();
99 
100  NTPCs = 0;
101  TPC->Clear();
102 
103  NFGDs = 0;
104  FGD->Clear();
105 
106  NSFGs = 0;
107  SFG->Clear();
108 
109  NSMRDs = 0;
110  SMRD->Clear();
111 
112  NP0Ds = 0;
113  P0D->Clear();
114 
115  NTRACKERs = 0;
116  TRACKER->Clear();
117 
118  NHitsSaved = 0;
119  HitsSaved->Clear();
120 }
121 
124 
128  Constituents = new TClonesArray("ND::TGlobalReconModule::TVertexConstituent",
129  NCONSTITUENTS);
130  TrueVertices = new TClonesArray("ND::TTrueVertex", NCONSTITUENTS);
131  NConstituents = 0;
132  Constituents->Clear();
133  NTrueVertices = 0;
134  TrueVertices->Clear();
135 }
136 
139 
142 
145 
148 
151 
154 
157 
160 
163 
166 
168  FGD1Unused = new TClonesArray("ND::TGlobalReconModule::TGlobalHit", 20);
169  FGD2Unused = new TClonesArray("ND::TGlobalReconModule::TGlobalHit", 20);
170 
171  NFGD1Unused = 0;
172  FGD1Unused->Clear();
173 
174  NFGD2Unused = 0;
175  FGD2Unused->Clear();
176 }
177 
179  SFGUnused = new TClonesArray("ND::TGlobalReconModule::TGlobalHit", 20);
180  NSFGUnused = 0;
181  SFGUnused->Clear();
182 }
183 
186 
189 
192 
193 bool SortHitsInX(const ND::THandle<ND::THit>& h1,
194  const ND::THandle<ND::THit>& h2)
195 {
196  return h1->GetPosition().X() < h2->GetPosition().X();
197 }
198 bool SortHitsInY(const ND::THandle<ND::THit>& h1,
199  const ND::THandle<ND::THit>& h2)
200 {
201  return h1->GetPosition().Y() < h2->GetPosition().Y();
202 }
203 bool SortHitsInZ(const ND::THandle<ND::THit>& h1,
204  const ND::THandle<ND::THit>& h2)
205 {
206  return h1->GetPosition().Z() < h2->GetPosition().Z();
207 }
208 
209 bool SortNodesInX(const ND::THandle<ND::TReconNode>& n1,
210  const ND::THandle<ND::TReconNode>& n2)
211 {
212  return TrackingUtils::GetPosition(n1->GetState()).X() <
213  TrackingUtils::GetPosition(n2->GetState()).X();
214 }
215 bool SortNodesInY(const ND::THandle<ND::TReconNode>& n1,
216  const ND::THandle<ND::TReconNode>& n2)
217 {
218  return TrackingUtils::GetPosition(n1->GetState()).Y() <
219  TrackingUtils::GetPosition(n2->GetState()).Y();
220 }
221 bool SortNodesInZ(const ND::THandle<ND::TReconNode>& n1,
222  const ND::THandle<ND::TReconNode>& n2)
223 {
224  return TrackingUtils::GetPosition(n1->GetState()).Z() <
225  TrackingUtils::GetPosition(n2->GetState()).Z();
226 }
227 bool SortNodesInXReverse(const ND::THandle<ND::TReconNode>& n1,
228  const ND::THandle<ND::TReconNode>& n2)
229 
230 {
231  return TrackingUtils::GetPosition(n1->GetState()).X() >=
232  TrackingUtils::GetPosition(n2->GetState()).X();
233 }
234 bool SortNodesInYReverse(const ND::THandle<ND::TReconNode>& n1,
235  const ND::THandle<ND::TReconNode>& n2)
236 {
237  return TrackingUtils::GetPosition(n1->GetState()).Y() >=
238  TrackingUtils::GetPosition(n2->GetState()).Y();
239 }
240 bool SortNodesInZReverse(const ND::THandle<ND::TReconNode>& n1,
241  const ND::THandle<ND::TReconNode>& n2)
242 {
243  return TrackingUtils::GetPosition(n1->GetState()).Z() >=
244  TrackingUtils::GetPosition(n2->GetState()).Z();
245 }
246 #include "../cvstags/TGlobalReconModule.cxx"
247 
248 
249 //*************************************************************
251  const char* title)
252 {
253  //*************************************************************
254 
255  fTestTPCInfo = false;
256  fTestTPCInfo = true;
257 
258  SetNameTitle(name, title);
259 
260  // Enable this module by default:
261  fIsEnabled = kTRUE;
262  fDescription = "Global Recon Output";
264  fCVSID = CVSID;
265 
266  // Tree variables
267  fNPIDs = 0;
268  fPIDs = new TClonesArray("ND::TGlobalReconModule::TGlobalPID", 20);
269 
270  fNTPCOthers = 0;
271  fTPCOthers =
272  new TClonesArray("ND::TGlobalReconModule::TTPCOtherObject", NMAXTPCOTHER);
273 
274  fNVertices = 0;
275  fVertices = new TClonesArray("ND::TGlobalReconModule::TGlobalVertex", 20);
276  fPVInd = 0;
277  fNSVertices = 0;
278 
279  fNFgdTimeBins = 0;
280  fFgdTimeBins = new TClonesArray("ND::TGlobalReconModule::TFgdTimeBin", 20);
281 
282  fNSfgTimeBins = 0;
283  fSfgTimeBins = new TClonesArray("ND::TGlobalReconModule::TSfgTimeBin", 20);
284 
285  fSMRDUnused = new TClonesArray("ND::TGlobalReconModule::TSMRDHit", 100);
286 
287  fP0DUnused = new TClonesArray("ND::TGlobalReconModule::TGlobalHit", 100);
288 
289  fNTPCPIDs = 0;
290  if (fTestTPCInfo) {
291  fTPCPIDs = new TClonesArray("ND::TGlobalReconModule::TTpcPID", 20);
292  } else {
293  fTPCPIDs = NULL;
294  }
295 
296  fUseECalVertices = false;
297  fRecPackInitialized = false;
298 }
299 
301 {
302  if (fFilledConfigTree) {
303  ND280NamedWarn(
304  "TGlobalReconModule",
305  "Module: " << this->GetName()
306  << " has already written the config tree this run.");
307  }
308  configTree->Branch("AllModules", &fALLMODULES);
309  configTree->Branch("UseECalVertices", &fUseECalVertices);
310 
312 }
313 
314 //*************************************************************
316 //*************************************************************
317 
318 Bool_t ND::TGlobalReconModule::Configure(std::string& opt)
319 {
320  if (opt == "UseECalVertices") {
321  fUseECalVertices = true;
322  return true;
323  }
324  return false;
325 }
326 
327 //*************************************************************
328 Bool_t ND::TGlobalReconModule::ProcessFirstEvent(ND::TND280Event& event)
329 {
330  //*************************************************************
331  return true;
332 }
333 
334 //*************************************************************
336 //*************************************************************
337 
338 //*************************************************************
340 {
341  //*************************************************************
342  SetSplitLevel(1);
343 
344  if (fTestTPCInfo)
345  {
346  fOutputTree->Branch("NTPCPIDs", &fNTPCPIDs, "NTPCPIDs/I", fBufferSize);
347 
348  fOutputTree->Branch("TPCPIDs", "TClonesArray", &fTPCPIDs, fBufferSize,
349  fSplitLevel);
350  }
351 
352  // The number of vertex objects that have been saved.
353  fOutputTree->Branch("NVertices", &fNVertices, "NVertices/I", fBufferSize)
354  ->SetTitle("The number of added primary vertices. ");
355 
356  // Vertex branch
357  fOutputTree->Branch("Vertices", &fVertices, fBufferSize, fSplitLevel)
358  ->SetTitle("The TGlobalVertex vector of vertices. ");
359 
360  // FGD hit time bins
361  fOutputTree->Branch("NFgdTimeBins", &fNFgdTimeBins, "NFgdTimeBins/I",
362  fBufferSize)
363  ->SetTitle(" Number of hit time bins in the FGD as determined by fgdRecon. ");
364  fOutputTree->Branch("FgdTimeBins", &fFgdTimeBins, fBufferSize, fSplitLevel)
365  ->SetTitle(" Information for each hit time bin (TFgdTimeBins). ");
366  // SFG hit time bins
367  fOutputTree->Branch("NSfgTimeBins", &fNSfgTimeBins, "NSfgTimeBins/I",
368  fBufferSize)
369  ->SetTitle(" Number of hit time bins in the SFG as determined by sfgRecon. ");
370  fOutputTree->Branch("SfgTimeBins", &fSfgTimeBins, fBufferSize, fSplitLevel)
371  ->SetTitle(" Information for each hit time bin (TSfgTimeBins). ");
372  // The number of objects that have been saved.
373  fOutputTree->Branch("NPIDs", &fNPIDs, "NPIDs/I", fBufferSize)
374  ->SetTitle(" The number of global objects.");
375  // A branch for the clone array of Global object information.
376  fOutputTree->Branch("PIDs", "TClonesArray", &fPIDs, fBufferSize, fSplitLevel)
377  ->SetTitle(" The vector of TGlobalPID.");
378  // The number of objects that have been saved.
379  fOutputTree->Branch("NTPCOthers", &fNTPCOthers, "NTPCOthers/I", fBufferSize)
380  ->SetTitle("The number of TPC other objects. ");
381  // A branch for the clone array of Global object information.
382  fOutputTree->Branch("TPCOthers", "TClonesArray", &fTPCOthers, fBufferSize,
383  fSplitLevel)
384  ->SetTitle("The vector of TPC other objects (TTPCOtherObject). ");
385  // number of unused hits in FGD1, FGD2, P0D and SMRD
386  fOutputTree->Branch("NFGD1Unused", &fNFGD1Unused, "NFGD1Unused/I", fBufferSize)
387  ->SetTitle(" Number of hits unused in FGD1");
388  fOutputTree->Branch("NFGD2Unused", &fNFGD2Unused, "NFGD2Unused/I", fBufferSize)
389  ->SetTitle(" Number of hits unused in FGD2");
390  fOutputTree->Branch("NSFGUnused", &fNSFGUnused, "NSFGUnused/I", fBufferSize)
391  ->SetTitle(" Number of hits unused in SFG");
392  fOutputTree->Branch("NP0DUnused", &fNP0DUnused, "NP0DUnused/I", fBufferSize)
393  ->SetTitle(" Number of hits unused in the P0D");
394  fOutputTree->Branch("P0DUnused", "TClonesArray", &fP0DUnused, fBufferSize,
395  fSplitLevel)
396  ->SetTitle("The vector unused hits in the P0D (TGlobalHit). ");
397  fOutputTree->Branch("SMRDUnused", "TClonesArray", &fSMRDUnused, fBufferSize,
398  fSplitLevel)
399  ->SetTitle(" The vector unused hits in the SMRD (TSMRDHit). ");
400  fOutputTree->Branch("NSMRDUnused", &fNSMRDUnused, "NSMRDU nused/I",
401  fBufferSize)
402  ->SetTitle(" Number of all hits unused in the SMRD");
403  fOutputTree->Branch("NSMRDTopUnused", &fNSMRDTopUnused, "NSMRDTopUnused/I",
404  fBufferSize)
405  ->SetTitle(" Number of hits unused in the SMRDTop ");
406  fOutputTree->Branch("NSMRDBottomUnused", &fNSMRDBottomUnused,
407  "NSMRDBottomUnused/I", fBufferSize)
408  ->SetTitle(" Number of hits unused in the SMRDBottom.");
409  fOutputTree->Branch("NSMRDLeftUnused", &fNSMRDLeftUnused, "NSMRDLeftUnused/I",
410  fBufferSize)
411  ->SetTitle("Number of hits unused in the SMRDLeft. ");
412  fOutputTree->Branch("NSMRDRightUnused", &fNSMRDRightUnused,
413  "NSMRDRightUnused/I", fBufferSize)
414  ->SetTitle(" Number of hits unused in the SMRDRight.");
415 
416  fOutputTree->Branch("NTPCUnused", &fNTPCUnused, "NTPCUnused/I", fBufferSize)
417  ->SetTitle(" Number of hits unused in the TPC. ");
418 
419  // Save P0D outermost hits
420  fOutputTree->Branch("P0DOutermostHits", "TOutermostHits", &fP0DOutermostHits,
422  ->SetTitle("Outermost hits in the P0D. ");
423  // time of the median hit of the earliest track
424  fOutputTree->Branch("EarliestTrackTime", &fEarliestTrackMedianHitTime,
425  fBufferSize)
426  ->SetTitle(" Median hit time of the earliest track. ");
427  // Counters for each detector
428  fOutputTree->Branch("NDsECAL", &fNDsECAL, "NDsECAL/I", fBufferSize)
429  ->SetTitle("Number of objects containing the DsECAL. ");
430  fOutputTree->Branch("NTrECAL", &fNTrECAL, "NTrECAL/I", fBufferSize)
431  ->SetTitle(" Number of objects containing the TrECAL.");
432  fOutputTree->Branch("NP0DECAL", &fNP0DECAL, "NP0DECAL/I", fBufferSize)
433  ->SetTitle(" Number of objects containing the P0DECAL. ");
434  fOutputTree->Branch("NTPC", &fNTPC, "NTPC/I", fBufferSize)
435  ->SetTitle(" Number of objects containing the TPC.");
436  fOutputTree->Branch("NFGD", &fNFGD, "NFGD/I", fBufferSize)
437  ->SetTitle(" Number of objects containing the FGD.");
438  fOutputTree->Branch("NSFG", &fNSFG, "NSFG/I", fBufferSize)
439  ->SetTitle(" Number of objects containing the SFG.");
440  fOutputTree->Branch("NP0D", &fNP0D, "NP0D/I", fBufferSize)
441  ->SetTitle(" Number of objects containing the P0D.");
442  fOutputTree->Branch("NSMRD", &fNSMRD, "NSMRD/I", fBufferSize)
443  ->SetTitle(" Number of objects containing the SMRD.");
444  fOutputTree->Branch("NDsECALIso", &fNDsECALIso, "NDsECALIso/I", fBufferSize)
445  ->SetTitle("Number of objects in the DsECAL only. ");
446  fOutputTree->Branch("NTrECALIso", &fNTrECALIso, "NTrECALIso/I", fBufferSize)
447  ->SetTitle(" Number of objects in the TrECAL only. ");
448  fOutputTree->Branch("NP0DECALIso", &fNP0DECALIso, "NP0DECALIso/I",
449  fBufferSize)
450  ->SetTitle(" Number of objects in the P0DECAL only.");
451  fOutputTree->Branch("NTPCIso", &fNTPCIso, "NTPCIso/I", fBufferSize)
452  ->SetTitle(" Number of objects in the TPC only. ");
453  fOutputTree->Branch("NFGDIso", &fNFGDIso, "NFGDIso/I", fBufferSize)
454  ->SetTitle(" Number of objects in the FGD only. ");
455  fOutputTree->Branch("NSFGIso", &fNSFGIso, "NSFGIso/I", fBufferSize)
456  ->SetTitle(" Number of objects in the SFG only. ");
457  fOutputTree->Branch("NP0DIso", &fNP0DIso, "NP0DIso/I", fBufferSize)
458  ->SetTitle(" Number of objects in the P0D only.");
459  fOutputTree->Branch("NSMRDIso", &fNSMRDIso, "NSMRDIso/I", fBufferSize)
460  ->SetTitle("Number on objects in the SMRD only. ");
461 }
462 
463 //*************************************************************
464 bool ND::TGlobalReconModule::FillTree(ND::TND280Event& event)
465 {
466  //*************************************************************
467 
468  if (!fRecPackInitialized){
469  // add a new RecpackManager
470  ND::tman().add_manager("globalAnalysis");
471  ND::tman().select_manager("globalAnalysis");
472 
473  // only surfaces with measurements are tried inside a volume
474  ND::rpman("globalAnalysis")
475  .navigation_svc()
476  .navigator(RP::particle_helix)
477  .set_unique_surface(true);
478 
479  // enable energy loss correction
480  ND::rpman("globalAnalysis")
481  .model_svc()
482  .enable_correction(RP::particle_helix, RP::eloss, true);
483 
484  // enable MS
485  ND::rpman("globalAnalysis")
486  .model_svc()
487  .enable_noiser(RP::particle_helix, RP::ms, true);
488 
489  fEquation = ND::rpman()
490  .model_svc()
491  .model(RP::particle_helix)
492  .retrieve_tool<HelixEquation>("equation");
493 
494  if (debug_extrap) {
495  ND::tman("globalAnalysis").SetVerbosity(0, 2, 0, 0);
496  ND::rpman("globalAnalysis")
497  .model_svc()
498  .model(RP::particle_helix)
499  .tool("correction/eloss")
500  .set_verbosity(Messenger::VVERBOSE);
501  ND::rpman("globalAnalysis")
502  .navigation_svc()
503  .navigator(RP::particle_helix)
504  .master_inspector()
505  .set_verbosity(Messenger::VVERBOSE);
506  ND::rpman("globalAnalysis")
507  .navigation_svc()
508  .inspector("eloss")
509  .set_verbosity(Messenger::VVERBOSE);
510  }
512 
513  fRecPackInitialized = true;
514  }
515 
516  if (fTestTPCInfo)
517  {
518  fNTPCPIDs = 0;
519  fTPCPIDs->Clear();
520  }
521 
522  fNVertices = 0;
523  fVertices->Clear();
524  fNPIDs = 0;
525  fNSVertices = 0;
526 
527  fNPIDs = 0;
528  fPIDs->Clear();
529 
530  fNTPCOthers = 0;
531  fTPCOthers->Clear();
532 
533  fNFgdTimeBins = 0;
534  fFgdTimeBins->Clear();
535 
536  fNSfgTimeBins = 0;
537  fSfgTimeBins->Clear();
538 
539  fNFGD1Unused = 0;
540  fNFGD2Unused = 0;
541 
542  fNSFGUnused = 0;
543 
544  fNP0DUnused = 0;
545  fP0DUnused->Clear();
546 
547  fSMRDUnused->Clear();
548  fNSMRDUnused = 0;
549  fNSMRDTopUnused = 0;
550  fNSMRDBottomUnused = 0;
551  fNSMRDLeftUnused = 0;
552  fNSMRDRightUnused = 0;
553 
554  fNTPCUnused = 0;
555 
557 
558  fNDsECAL = 0;
559  fNTrECAL = 0;
560  fNP0DECAL = 0;
561  fNTPC = 0;
562  fNFGD = 0;
563  fNSFG = 0;
564  fNP0D = 0;
565  fNSMRD = 0;
566 
567  fNDsECALIso = 0;
568  fNTrECALIso = 0;
569  fNP0DECALIso = 0;
570  fNTPCIso = 0;
571  fNFGDIso = 0;
572  fNSFGIso = 0;
573  fNP0DIso = 0;
574  fNSMRDIso = 0;
575 
576  // Get the main result to save.
577  ND::THandle<ND::TAlgorithmResult> globalRecon = event.GetFit("oaRecon");
578  if (!globalRecon)
579  {
580  return true;
581  }
582 
583  // Get the results from reconstruction
584  ND::THandle<ND::TReconObjectContainer> allObjects =
585  globalRecon->GetResultsContainer("final");
586 
587  if (!allObjects) return true;
588 
589  // This is only for tests
590  if (fTestTPCInfo)
591  {
592  ND::THandle<ND::TAlgorithmResult> tpcRecon = event.GetFit("tpcRecon");
593  if (tpcRecon)
594  {
595  // Get the results from reconstruction
596  ND::THandle<ND::TReconObjectContainer> tpcObjects =
597  tpcRecon->GetResultsContainer("TPCPids");
598 
599  if (tpcObjects)
600  {
601  // Now loop over objects.
602  for (ND::TReconObjectContainer::iterator tt = tpcObjects->begin();
603  tt != tpcObjects->end(); tt++)
604  {
605  ND::THandle<ND::TReconBase> object = *tt;
606  if (object) FillTPCPID(object);
607  }
608  }
609  }
610  }
611 
612  // fill the map of broken tracks (to be used later)
613  FillBrokenTracksMap(*allObjects);
614 
615  // Now loop over object and fill the global analysis objects
616  fGlobalIndexMap.clear();
617  for (ND::TReconObjectContainer::iterator tt = allObjects->begin();
618  tt != allObjects->end(); tt++)
619  {
620  ND::THandle<ND::TReconBase> object = *tt;
621  if (!object) continue;
622 
623  // The way to be done in future
624  // ND::THandle<ND::TReconVertex> vertex = *tt;
625  // if (vertex)
626  // FillVertex(object);
627  // else//Fill track/pid informtaion
628 
629  FillGlobalPIDs(event, object);
630  }
631 
632  FillVertexInfo(event, allObjects);
633 
634  FillSfgTimeBins(event);
635 
636  FillFgdTimeBins(event);
637 
638  FillUnusedHits(event);
639 
640  FillTPCOther(event);
641 
642  FillSFGOther(event);
643 
644  // Fill P0D outermost hits
645  double p0d_charge_cut = 7;
646  ND::THandle<ND::THitSelection> p0dHits = event.GetHitSelection("p0d");
647  if (p0dHits) FillOutermostHits(*p0dHits, p0d_charge_cut, fP0DOutermostHits);
648 
649  fGlobalIndexMap.clear();
650  fBrokenIndexMap.clear();
651 
652  return true;
653 }
654 
655 
656 //*************************************************************
658  ND::TND280Event& event, ND::THandle<ND::TReconBase> object)
659 {
660 //*************************************************************
661 
662  if (debug_pids) std::cout << "Fill Global PID: " << object << std::endl;
663 
664  // Get the compact detector number and number of used detectors
665  unsigned long dets = GetDetectorNumber(object);
666  int det_count = CountDetector(object);
667 
668  // update counters for specfic detectors
669  if (object->UsesDetector(ND::TReconBase::kDSECal))
670  {
671  fNDsECAL++;
672  if (det_count == 1) fNDsECALIso++;
673  }
674  if (object->UsesDetector(ND::TReconBase::kECal))
675  {
676  fNTrECAL++;
677  if (det_count == 1) fNTrECALIso++;
678  }
679  if (object->UsesDetector(ND::TReconBase::kPECal))
680  {
681  fNP0DECAL++;
682  if (det_count == 1) fNP0DECALIso++;
683  }
684  if (object->UsesDetector(ND::TReconBase::kFGD))
685  {
686  fNFGD++;
687  if (det_count == 1) fNFGDIso++;
688  }
689  if (object->UsesDetector(ND::TReconBase::kSFG))
690  {
691  fNSFG++;
692  if (det_count == 1) fNSFGIso++;
693  }
694  if (object->UsesDetector(ND::TReconBase::kTPC))
695  {
696  fNTPC++;
697  if (det_count == 1) fNTPCIso++;
698  }
699  if (object->UsesDetector(ND::TReconBase::kP0D))
700  {
701  fNP0D++;
702  if (det_count == 1) fNP0DIso++;
703  }
704  if (object->UsesDetector(ND::TReconBase::kSMRD))
705  {
706  fNSMRD++;
707  if (det_count == 1) fNSMRDIso++;
708  }
709 
710  // __________________________________________________________
711  // Fill the reconstructed Global PIDs.
712 
713  // try to get the state of the object. If it dosen't exists skip the object.
714  try
715  {
716  ND::THandle<ND::TReconState> tstate = object->GetState();
717  } catch (ND::EReconObject const& e)
718  {
719  std::cout << "TReconBase with no state. Skip object !!" << std::endl;
720  return;
721  }
722 
723  // Fill the map of indexes used for vertex link
724  fGlobalIndexMap[object] = fNPIDs;
725 
726  // create a new TGlobalPID
727  TGlobalPID* globalObject = new ((*fPIDs)[fNPIDs++]) TGlobalPID;
728 
729  // the unique ID of the global object
730  globalObject->UniqueID = object->GetUniqueID();
731 
732  //--------- Fill the vector of unique IDs of associated tracks
733  if (fBrokenIndexMap.find(object) != fBrokenIndexMap.end())
734  globalObject->BrokenUniqueIDs = fBrokenIndexMap[object];
735 
736  //--------- Information about the detectors that used in this object
737  globalObject->Detectors = dets;
738  FillDetectorUsed(object, globalObject->DetectorUsed);
739 
740  //------- General information about the track --------
741 
742  globalObject->isForward = (TrackingUtils::GetDirection(object).Z() > 0);
743  globalObject->SenseOK = TrackingUtils::GetSenseOK(*object);
744  globalObject->IsCurvBack = TrackingUtils::GetCurvBackTrack(*object);
745  globalObject->Charge = TrackingUtils::GetCharge(object);
746  globalObject->EDeposit = TrackingUtils::GetEDeposit(object);
747  globalObject->Width =
748  TrackingUtils::GetWidth(object).X(); //! take only the first component
749  globalObject->Cone = TrackingUtils::GetCone(object);
750  globalObject->Length = ComputeTrackLength(object);
751 
752  globalObject->AlgorithmName = object->GetAlgorithmName();
753  globalObject->Status = object->CheckStatus(object->kSuccess);
754  globalObject->Chi2 = object->GetQuality();
755  globalObject->NDOF = object->GetNDOF();
756  try
757  {
758  globalObject->NNodes = object->GetNodes().size();
759  } catch (ND::EReconObject const& e)
760  {
761  globalObject->NNodes = 0;
762  }
763 
764  globalObject->NHits = DEFAULT_MAX;
765  if (object->GetHits()) globalObject->NHits = object->GetHits()->size();
766 
767  // The number of constituents. For composite objects
768  globalObject->NConstituents = 0;
769  globalObject->IsFgdECalIncremental = false;
770  if (object->GetConstituents())
771  {
772  globalObject->NConstituents = object->GetConstituents()->size();
773 
774  ND::TReconObjectContainer t1const =
775  ReconObjectUtils::GetConstituentsRecursive(object, true);
776 
777  if (t1const.size() > 0)
778  {
779  ND::TReconObjectContainer::const_iterator it1;
780 
781  for (it1 = t1const.begin(); it1 != t1const.end(); it1++)
782  {
783  ND::THandle<ND::TReconBase> obj = *it1;
784  if (obj)
785  {
786  if (obj->GetAlgorithmName() == "FgdECalIncremental")
787  {
788  globalObject->IsFgdECalIncremental = true;
789  break;
790  }
791  }
792  }
793  }
794  }
795 
796  //---------- Fill info about first and last hits
797  if (object->GetHits())
798  {
799 //#define FILL_ALL_GLOBAL_HITS
800 #ifdef FILL_ALL_GLOBAL_HITS
801  FillAllHits(*(object->GetHits()), *globalObject);
802 #else
803  FillFirstLastHits(*(object->GetHits()), *globalObject);
804 #endif
805  }
806 
807  // ------------ Fill the node position info
808  globalObject->NodePosition.clear();
809  const ND::TReconNodeContainer& nodes = object->GetNodes();
810  ND::TReconNodeContainer::const_iterator it;
811  for(it = nodes.begin(); it != nodes.end(); it++){
812  ND::THandle<ND::TReconState> nodeState = (*it)->GetState();
813  if(!nodeState) continue;
814 
815  TLorentzVector node_pos = ND::TReconStateUtilities::GetPosition(nodeState);
816  globalObject->NodePosition.push_back(node_pos);
817  }
818 
819  // ------------ Fill the hit position info
820  globalObject->HitPosition.clear();
821  const ND::THandle<ND::THitSelection> hits = object->GetHits();
822  ND::THitSelection::const_iterator it_h;
823  for(it_h = hits->begin(); it_h != hits->end(); it_h++){
824  ND::THandle<ND::THit> hit = *it_h;
825  if(!hit) continue;
826 
827  TVector3 hit_pos = hit->GetPosition();
828  TLorentzVector pos_temp(hit_pos.X(),hit_pos.Y(),hit_pos.Z(),
829  hit->GetTime());
830  globalObject->HitPosition.push_back(pos_temp);
831  }
832 
833  //---------- Fill time info: for each group of nodes in a sub-detector we
834  // store the
835  // times of two edge nodes
836 
837  // do not apply for TPC iso
838 
839  if (object->GetDetectors() != ND::TReconBase::kTPC1 &&
840  object->GetDetectors() != ND::TReconBase::kTPC2 &&
841  object->GetDetectors() != ND::TReconBase::kTPC3)
842  {
843  const ND::TReconNodeContainer& tnodes = object->GetNodes();
844  unsigned long det_prev = 0;
845  double first_time = DEFAULT_MIN;
846  double last_time = DEFAULT_MAX;
847  bool first = true;
848 
849  ND::TReconNodeContainer::const_iterator in;
850  for (in = tnodes.begin(); in != tnodes.end(); in++)
851  {
852  ND::THandle<ND::TReconBase> nodeObject = (*in)->GetObject();
853  if (!nodeObject) continue;
854 
855  ND::THandle<ND::TReconState> nodeState = (*in)->GetState();
856  if (!nodeState) continue;
857 
858  unsigned long det_current = GetDetectorNumber(nodeObject);
859 
860  double nodeTime = TrackingUtils::GetPosition(nodeState).T();
861 
862  if (det_current != det_prev){
863  if (!first) {
864  globalObject->NodeTimes.push_back(
865  std::make_pair(det_prev, TVector2(first_time, last_time)));
866  }
867  first = false;
868 
869  det_prev = det_current;
870  first_time = nodeTime;
871  last_time = nodeTime;
872  } else{
873  last_time = nodeTime;
874  }
875  }
876 
877  // last group of nodes
878  if (det_prev != 0){
879  globalObject->NodeTimes.push_back(
880  std::make_pair(det_prev, TVector2(first_time, last_time)));
881  }
882  }
883 
884  //--------- Fill the true particle when it is found
885  double pur, eff;
886  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*object, pur, eff);
887  FillTrueParticle(G4track, pur, eff, globalObject->TrueParticle);
888 
889  //--------- Fill the kinematic extrapolated to the true vertex
891  G4track, object, globalObject->PositionAtTrueVertex,
892  globalObject->DirectionAtTrueVertex, globalObject->MomentumAtTrueVertex,
893  globalObject->MomentumErrorAtTrueVertex, globalObject->ChargeAtTrueVertex,
894  globalObject->StateCovAtTrueVertex);
895 
896  //------- Front and Back kinematics
897 
898  // Get the edge states
899  ND::THandle<ND::TReconState> firstState, lastState;
900 
901  ND::tman().GetFirstAndLastStates(object, firstState, lastState);
902 
903  FillKinematics(firstState, globalObject->FrontPosition,
904  globalObject->FrontDirection, globalObject->FrontMomentum,
905  globalObject->FrontMomentumError, globalObject->FrontCharge,
906  globalObject->FrontStateCov);
907 
908  FillKinematics(lastState, globalObject->BackPosition,
909  globalObject->BackDirection, globalObject->BackMomentum,
910  globalObject->BackMomentumError, globalObject->BackCharge,
911  globalObject->BackStateCov);
912 
913  //------- Momentumby range
914 
915  // globalObject->RangeMomentum = TrackingUtils::GetMomentumByRange(*object);
916 // globalObject->RangeMomentum = TrackingUtils::GetMomentumByRange(*object);
917  globalObject->RangeMomentumMuon =
918  TrackingUtils::GetTRealDatumValue(*object, "prange_Muon", DEFAULT_MAX);
920  *object, "prange_Muon_flipped", DEFAULT_MAX);
921  globalObject->RangeMomentumEndToTPCMuon =
922  TrackingUtils::GetTRealDatumValue(*object, "prange_end_to_tpc_Muon", DEFAULT_MAX);
923 
924  globalObject->RangeMomentumPion =
925  TrackingUtils::GetTRealDatumValue(*object, "prange_Pion", DEFAULT_MAX);
927  *object, "prange_Pion_flipped", DEFAULT_MAX);
928  globalObject->RangeMomentumEndToTPCPion =
929  TrackingUtils::GetTRealDatumValue(*object, "prange_end_to_tpc_Pion", DEFAULT_MAX);
930 
932  *object, "prange_Electron", DEFAULT_MAX);
934  *object, "prange_Electron_flipped", DEFAULT_MAX);
935  globalObject->RangeMomentumEndToTPCElectron =
936  TrackingUtils::GetTRealDatumValue(*object, "prange_end_to_tpc_Electron", DEFAULT_MAX);
937 
938  globalObject->RangeMomentumProton =
939  TrackingUtils::GetTRealDatumValue(*object, "prange_Proton", DEFAULT_MAX);
941  *object, "prange_Proton_flipped", DEFAULT_MAX);
942  globalObject->RangeMomentumEndToTPCProton =
943  TrackingUtils::GetTRealDatumValue(*object, "prange_end_to_tpc_Proton", DEFAULT_MAX);
944 
945 
946  //---------- Set the PID information
947  ND::THandle<ND::TReconPID> PID = object;
948  if (PID) {
949  globalObject->PIDWeights.push_back(PID->GetPIDWeight());
950  globalObject->ParticleIds.push_back(ComputeParticleId(PID));
951 
952  ND::TReconObjectContainer::const_iterator it;
953  for (it = PID->GetAlternates().begin(); it != PID->GetAlternates().end();
954  it++) {
955  ND::THandle<ND::TReconPID> alter = *it;
956 
957  // check that this particle Id is not yet present (alternate for the main
958  // hypothesis, sense alternates)
959  int pid = ComputeParticleId(alter);
960  if (std::find(globalObject->ParticleIds.begin(),
961  globalObject->ParticleIds.end(),
962  pid) == globalObject->ParticleIds.end()) {
963  globalObject->PIDWeights.push_back(alter->GetPIDWeight());
964  globalObject->ParticleIds.push_back(ComputeParticleId(alter));
965  }
966  }
967  }
968 
969  //--------- Fill the information needed to do the association between the TREx
970  // output and global recon ---------
971  globalObject->TPCGasPatternIDs.clear();
972  globalObject->TPCGasPathIDs.clear();
973  globalObject->TPCGasJunctionIDs.clear();
974 
975  std::set<int> IDs;
976 
977  // Fill the patterns
978  IDs.clear();
979  ReconObjectUtils::GetTRExPatternIDs(object, IDs, kGas);
980 
981  globalObject->TPCGasPatternIDs.reserve(IDs.size());
982  std::copy(IDs.begin(), IDs.end(),
983  std::back_inserter(globalObject->TPCGasPatternIDs));
984 
985  // Fill the paths
986  IDs.clear();
987  ReconObjectUtils::GetTRExPathIDs(object, IDs, kGas);
988 
989  globalObject->TPCGasPathIDs.reserve(IDs.size());
990  std::copy(IDs.begin(), IDs.end(),
991  std::back_inserter(globalObject->TPCGasPathIDs));
992 
993  // Fill the junctions
994  IDs.clear();
995  ReconObjectUtils::GetTRExJunctionIDs(object, IDs, kGas);
996 
997  globalObject->TPCGasJunctionIDs.reserve(IDs.size());
998  std::copy(IDs.begin(), IDs.end(),
999  std::back_inserter(globalObject->TPCGasJunctionIDs));
1000 
1001  //---------- Extrapolate to the entrance and exit of each subdetector and save
1002  // position, direction and momentum
1003  FillExtrapolationToDetectors(object, *globalObject);
1004 
1005  //---------- get FGD vertex activity before calling FillFGDInfo but after
1006  // front/back position defined
1007  // Claculate Vertex Activity for Front position of reconstructed track
1008  if (ND::TGeomInfo::Get().FGD().IsInFGD1(globalObject->FrontPosition.Vect()) ||
1009  ND::TGeomInfo::Get().FGD().IsInFGD2(globalObject->FrontPosition.Vect()))
1010  GetFGDSimpleVA(event, object, globalObject->FrontPosition, 1, 1);
1011 
1012  // Claculate End Activity for Back position of reconstructed track
1013  if (ND::TGeomInfo::Get().FGD().IsInFGD1(globalObject->BackPosition.Vect()) ||
1014  ND::TGeomInfo::Get().FGD().IsInFGD2(globalObject->BackPosition.Vect()))
1015  GetFGDSimpleVA(event, object, globalObject->BackPosition, 1, 2);
1016 
1017  // Calculate Vertex and End Activities for Entering and Exiting positions to
1018  // FGD
1019  // Active volume of FGD1 and FGD2 as in oaGeomInfo TFGDGeom.cxx
1020  TVector3 fFGD1ActiveMin;
1021  TVector3 fFGD1ActiveMax;
1022  TVector3 fFGD2ActiveMin;
1023  TVector3 fFGD2ActiveMax;
1024  fFGD1ActiveMin.SetXYZ(-932.17, -877.17, 116.045);
1025  fFGD1ActiveMax.SetXYZ(932.17, 987.17, 446.955);
1026  fFGD2ActiveMin.SetXYZ(-932.17, -877.17, 1474.04);
1027  fFGD2ActiveMax.SetXYZ(932.17, 987.17, 1806.96);
1028 
1029  // FrontPosition in FGD1
1030  //-----------------------------
1031  if (ND::TGeomInfo::Get().FGD().IsInFGD1(
1032  globalObject->FrontPosition.Vect())) { // Front in FGD1
1033 
1034  if (ND::TGeomInfo::Get().FGD().IsInFGD1(
1035  globalObject->BackPosition.Vect())) { // Back in FGD1
1036  // std::cout<<"Front FGD1 Back FGD1"<<std::endl;
1037  } else if (ND::TGeomInfo::Get().FGD().IsInFGD2(
1038  globalObject->BackPosition.Vect())) { // Back in FGD2
1039 
1040  if (globalObject->ExitPosition[3].Z() != -99999) {
1041  TLorentzVector ExitPosFGD1;
1042  ExitPosFGD1.SetX(globalObject->ExitPosition[3].X());
1043  ExitPosFGD1.SetY(globalObject->ExitPosition[3].Y());
1044  ExitPosFGD1.SetZ(globalObject->ExitPosition[3].Z());
1045  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD1, fFGD1ActiveMin,
1046  fFGD1ActiveMax);
1047  GetFGDSimpleVA(event, object, ExitPosFGD1, 2, 2);
1048  }
1049 
1050  if (globalObject->EntrancePosition[4].Z() != -99999) {
1051  TLorentzVector EntrancePosFGD2;
1052  EntrancePosFGD2.SetX(globalObject->EntrancePosition[4].X());
1053  EntrancePosFGD2.SetY(globalObject->EntrancePosition[4].Y());
1054  EntrancePosFGD2.SetZ(globalObject->EntrancePosition[4].Z());
1055  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD2, fFGD2ActiveMin,
1056  fFGD2ActiveMax);
1057  GetFGDSimpleVA(event, object, EntrancePosFGD2, 2, 1);
1058  }
1059 
1060  } else { // Back !FGD1 and !FGD2
1061 
1062  if (globalObject->ExitPosition[3].Z() != -99999) {
1063  TLorentzVector ExitPosFGD1;
1064  ExitPosFGD1.SetX(globalObject->ExitPosition[3].X());
1065  ExitPosFGD1.SetY(globalObject->ExitPosition[3].Y());
1066  ExitPosFGD1.SetZ(globalObject->ExitPosition[3].Z());
1067 
1068  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD1, fFGD1ActiveMin,
1069  fFGD1ActiveMax);
1070  GetFGDSimpleVA(event, object, ExitPosFGD1, 2, 2);
1071  }
1072 
1073  // check if track passed through FGD2
1074  if ((globalObject->EntrancePosition[4].Z() != -99999) &&
1075  (globalObject->ExitPosition[4].Z() != -99999)) {
1076  // track Passed through FGD2
1077  TLorentzVector EntrancePosFGD2;
1078  EntrancePosFGD2.SetX(globalObject->EntrancePosition[4].X());
1079  EntrancePosFGD2.SetY(globalObject->EntrancePosition[4].Y());
1080  EntrancePosFGD2.SetZ(globalObject->EntrancePosition[4].Z());
1081  TLorentzVector ExitPosFGD2;
1082  ExitPosFGD2.SetX(globalObject->ExitPosition[4].X());
1083  ExitPosFGD2.SetY(globalObject->ExitPosition[4].Y());
1084  ExitPosFGD2.SetZ(globalObject->ExitPosition[4].Z());
1085 
1086  // check if distance between Entrance / ExitPosition is outside of FGD2
1087  // volume
1088  // if out-of-active distance is less than 2mm then assume edge of active
1089  // volume being exit position
1090  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD2, fFGD2ActiveMin,
1091  fFGD2ActiveMax);
1092  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD2, fFGD2ActiveMin,
1093  fFGD2ActiveMax);
1094  GetFGDSimpleVA(event, object, EntrancePosFGD2, 2, 1);
1095  GetFGDSimpleVA(event, object, ExitPosFGD2, 2, 2);
1096  }
1097  }
1098  }
1099  // FrontPosition in FGD2
1100  //-----------------------------
1101  else if (ND::TGeomInfo::Get().FGD().IsInFGD2(
1102  globalObject->FrontPosition.Vect())) { // Front in FGD2
1103  if (ND::TGeomInfo::Get().FGD().IsInFGD2(
1104  globalObject->BackPosition.Vect())) { // Back in FGD2
1105  // std::cout<<"Front FGD2 Back FGD2"<<std::endl;
1106  } else if (ND::TGeomInfo::Get().FGD().IsInFGD1(
1107  globalObject->BackPosition.Vect())) { // Back in FGD1
1108 
1109  if (globalObject->ExitPosition[4].Z() != -99999) {
1110  // track exiting FGD2
1111  TLorentzVector ExitPosFGD2;
1112  ExitPosFGD2.SetX(globalObject->ExitPosition[4].X());
1113  ExitPosFGD2.SetY(globalObject->ExitPosition[4].Y());
1114  ExitPosFGD2.SetZ(globalObject->ExitPosition[4].Z());
1115  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD2, fFGD2ActiveMin,
1116  fFGD2ActiveMax);
1117  GetFGDSimpleVA(event, object, ExitPosFGD2, 2, 2);
1118  }
1119 
1120  if (globalObject->EntrancePosition[3].Z() != -99999) {
1121  // track entering FGD1
1122  TLorentzVector EntrancePosFGD1;
1123  EntrancePosFGD1.SetX(globalObject->EntrancePosition[3].X());
1124  EntrancePosFGD1.SetY(globalObject->EntrancePosition[3].Y());
1125  EntrancePosFGD1.SetZ(globalObject->EntrancePosition[3].Z());
1126  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD1, fFGD1ActiveMin,
1127  fFGD1ActiveMax);
1128  GetFGDSimpleVA(event, object, EntrancePosFGD1, 2, 1);
1129  }
1130  } else { // Back !FGD1 and !FGD2
1131 
1132  if (globalObject->ExitPosition[4].Z() != -99999) {
1133  // track leaving FGD2
1134  TLorentzVector ExitPosFGD2;
1135  ExitPosFGD2.SetX(globalObject->ExitPosition[4].X());
1136  ExitPosFGD2.SetY(globalObject->ExitPosition[4].Y());
1137  ExitPosFGD2.SetZ(globalObject->ExitPosition[4].Z());
1138  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD2, fFGD2ActiveMin,
1139  fFGD2ActiveMax);
1140  GetFGDSimpleVA(event, object, ExitPosFGD2, 2, 2);
1141  }
1142 
1143  // check if track passed through FGD1
1144  if ((globalObject->EntrancePosition[3].Z() != -99999) &&
1145  (globalObject->ExitPosition[3].Z() != -99999)) {
1146  // Passed through FGD1
1147  TLorentzVector EntrancePosFGD1;
1148  EntrancePosFGD1.SetX(globalObject->EntrancePosition[3].X());
1149  EntrancePosFGD1.SetY(globalObject->EntrancePosition[3].Y());
1150  EntrancePosFGD1.SetZ(globalObject->EntrancePosition[3].Z());
1151  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD1, fFGD1ActiveMin,
1152  fFGD1ActiveMax);
1153 
1154  TLorentzVector ExitPosFGD1;
1155  ExitPosFGD1.SetX(globalObject->ExitPosition[3].X());
1156  ExitPosFGD1.SetY(globalObject->ExitPosition[3].Y());
1157  ExitPosFGD1.SetZ(globalObject->ExitPosition[3].Z());
1158  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD1, fFGD1ActiveMin,
1159  fFGD1ActiveMax);
1160 
1161  GetFGDSimpleVA(event, object, EntrancePosFGD1, 2, 1);
1162  GetFGDSimpleVA(event, object, ExitPosFGD1, 2, 2);
1163  }
1164  }
1165  }
1166 
1167  // FrontPosition outside of FGD1 and FGD2
1168  //-----------------------------
1169  else { // Front !FGD1 and !FGD2
1170  // check if track enters FDG1
1171  if (globalObject->EntrancePosition[3].Z() != -99999) {
1172  TLorentzVector EntrancePosFGD1;
1173  EntrancePosFGD1.SetX(globalObject->EntrancePosition[3].X());
1174  EntrancePosFGD1.SetY(globalObject->EntrancePosition[3].Y());
1175  EntrancePosFGD1.SetZ(globalObject->EntrancePosition[3].Z());
1176  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD1, fFGD1ActiveMin,
1177  fFGD1ActiveMax);
1178  GetFGDSimpleVA(event, object, EntrancePosFGD1, 2, 1);
1179  }
1180 
1181  if (globalObject->ExitPosition[3].Z() !=
1182  -99999) { // check if track leaves FGD1
1183  TLorentzVector ExitPosFGD1;
1184  ExitPosFGD1.SetX(globalObject->ExitPosition[3].X());
1185  ExitPosFGD1.SetY(globalObject->ExitPosition[3].Y());
1186  ExitPosFGD1.SetZ(globalObject->ExitPosition[3].Z());
1187  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD1, fFGD1ActiveMin,
1188  fFGD1ActiveMax);
1189  GetFGDSimpleVA(event, object, ExitPosFGD1, 2, 2);
1190  }
1191 
1192  if (globalObject->EntrancePosition[4].Z() !=
1193  -99999) { // check if track enters FGD2
1194  TLorentzVector EntrancePosFGD2;
1195  EntrancePosFGD2.SetX(globalObject->EntrancePosition[4].X());
1196  EntrancePosFGD2.SetY(globalObject->EntrancePosition[4].Y());
1197  EntrancePosFGD2.SetZ(globalObject->EntrancePosition[4].Z());
1198  ND::TGlobalReconModule::CheckFGDdist(EntrancePosFGD2, fFGD2ActiveMin,
1199  fFGD2ActiveMax);
1200  GetFGDSimpleVA(event, object, EntrancePosFGD2, 2, 1);
1201  }
1202 
1203  if (globalObject->ExitPosition[4].Z() !=
1204  -99999) { // check if track leaves FGD2
1205  TLorentzVector ExitPosFGD2;
1206  ExitPosFGD2.SetX(globalObject->ExitPosition[4].X());
1207  ExitPosFGD2.SetY(globalObject->ExitPosition[4].Y());
1208  ExitPosFGD2.SetZ(globalObject->ExitPosition[4].Z());
1209  ND::TGlobalReconModule::CheckFGDdist(ExitPosFGD2, fFGD2ActiveMin,
1210  fFGD2ActiveMax);
1211  GetFGDSimpleVA(event, object, ExitPosFGD2, 2, 2);
1212  }
1213  }
1214  // end calulation of Entering and Exiting FGD activities
1215 
1216  //---------- Fill subdetector information
1217  FillECALInfo (object, *globalObject);
1218  FillP0DInfo (object, *globalObject);
1219  FillTPCInfo (object, *globalObject);
1220  FillFGDInfo (object, *globalObject);
1221  FillSFGInfo (object, *globalObject);
1222  FillSMRDInfo (object, *globalObject);
1223  FillTrackerInfo(object, *globalObject);
1224 
1225  //---------- Fill the alternates information
1226  FillGlobalPIDAlternates(G4track, object, *globalObject);
1227 
1228  // Add subdetector recomputation of some variables for isolated objects
1229  // For ECAL
1230  if (det_count == 1 && globalObject->NECALs == 1) {
1231  TECALObject* sub = (TECALObject*)(*(globalObject->ECAL))[0];
1232  globalObject->Cone = sub->Cone;
1233  globalObject->EDeposit = sub->EDeposit;
1234  globalObject->Width = sub->Width.X();
1235  if (globalObject->Length == 0) globalObject->Length = sub->Length;
1236  }
1237  // For P0D
1238  else if (det_count == 1 && globalObject->NP0Ds == 1) {
1239  TP0DObject* sub = (TP0DObject*)(*(globalObject->P0D))[0];
1240  globalObject->Cone = sub->Cone;
1241  globalObject->EDeposit = sub->EDeposit;
1242  globalObject->Width = sub->Width;
1243  if (globalObject->Length == 0) globalObject->Length = sub->Length;
1244  }
1245 }
1246 
1247 //*************************************************************
1248 void ND::TGlobalReconModule::CheckFGDdist(TLorentzVector& FGDPos,
1249  TVector3 fFGDActiveMin,
1250  TVector3 fFGDActiveMax)
1251 {
1252  //*************************************************************
1253  TVector3 dist;
1254 
1255  dist.SetXYZ(0.0, 0.0, 0.0);
1256  if (FGDPos.X() < fFGDActiveMin.X()) {
1257  dist.SetX(fFGDActiveMin.X() - FGDPos.X());
1258  if (dist.X() != 0.0 && abs(dist.X()) < 2.0)
1259  FGDPos.SetX(fFGDActiveMin.X() + 0.1);
1260  }
1261  if (FGDPos.X() > fFGDActiveMax.X()) {
1262  dist.SetX(fFGDActiveMax.X() - FGDPos.X());
1263  if (dist.X() != 0.0 && abs(dist.X()) < 2.0)
1264  FGDPos.SetX(fFGDActiveMax.X() - 0.1);
1265  }
1266  if (FGDPos.Y() < fFGDActiveMin.Y()) {
1267  dist.SetY(fFGDActiveMin.Y() - FGDPos.Y());
1268  if (dist.Y() != 0.0 && abs(dist.Y()) < 2.0)
1269  FGDPos.SetY(fFGDActiveMin.Y() + 0.1);
1270  }
1271  if (FGDPos.Y() > fFGDActiveMax.Y()) {
1272  dist.SetY(fFGDActiveMax.Y() - FGDPos.Y());
1273  if (dist.Y() != 0.0 && abs(dist.Y()) < 2.0)
1274  FGDPos.SetY(fFGDActiveMax.Y() - 0.1);
1275  }
1276  if (FGDPos.Z() < fFGDActiveMin.Z()) {
1277  dist.SetZ(fFGDActiveMin.Z() - FGDPos.Z());
1278  if (dist.Z() != 0.0 && abs(dist.Z()) < 2.0)
1279  FGDPos.SetZ(fFGDActiveMin.Z() + 0.1);
1280  }
1281  if (FGDPos.Z() > fFGDActiveMax.Z()) {
1282  dist.SetZ(fFGDActiveMax.Z() - FGDPos.Z());
1283  if (dist.Z() != 0.0 && abs(dist.Z()) < 2.0)
1284  FGDPos.SetZ(fFGDActiveMax.Z() - 0.1);
1285  }
1286 }
1287 
1288 //*************************************************************
1289 int ND::TGlobalReconModule::ComputeParticleId(ND::THandle<ND::TReconPID> PID) {
1290  //*************************************************************
1291 
1292  // only three hypothesis considered at recon level
1293 
1294  int pdg = 0;
1295 
1296  if (PID->GetParticleId() == ND::TReconPID::kElectron)
1297  pdg = 11;
1298  else if (PID->GetParticleId() == ND::TReconPID::kMuon)
1299  pdg = 13;
1300  else if (PID->GetParticleId() == ND::TReconPID::kProton)
1301  pdg = 2212;
1302 
1303  return pdg;
1304 }
1305 
1306 //*************************************************************
1307 void ND::TGlobalReconModule::FillKinematics(ND::THandle<ND::TReconState> state,
1308  TLorentzVector& pos, TVector3& dir,
1309  double& mom, double& momErr,
1310  double& charge,
1311  double (&cov)[7][7])
1312 {
1313 //*************************************************************
1314 
1315  if (state) {
1316  pos = TrackingUtils::GetPosition(state);
1317  dir = TrackingUtils::GetDirection(state);
1318  mom = TrackingUtils::GetMomentum(state);
1319  momErr = TrackingUtils::GetMomentumError(state);
1320  charge = TrackingUtils::GetCharge(state);
1321 
1322  // get the cov matrix
1323  RP::State rp_state;
1324  bool ok = ND::converter().TReconState_to_State(*state, rp_state);
1325  size_t dim = 0;
1326 
1327  if (ok) {
1328  RP::rep().convert(rp_state, RP::pos_dir_curv);
1329  dim = rp_state.vector().num_row();
1330  }
1331 
1332  // should have vector of 7: pos, dir, curv
1333  if (dim == 7) {
1334  const EMatrix& C = rp_state.matrix();
1335 
1336  for (size_t i = 0; i < 7; i++)
1337  for (size_t j = 0; j < 7; j++) cov[i][j] = C[i][j];
1338 
1339  } else {
1340  std::fill(&cov[0][0], &cov[0][0] + 7 * 7, DEFAULT_MAX);
1341  }
1342 
1343  } // state is ok
1344  else {
1345  pos = TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1346  dir = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1347  mom = DEFAULT_MAX;
1348  momErr = DEFAULT_MAX;
1349  charge = DEFAULT_MAX;
1350 
1351  std::fill(&cov[0][0], &cov[0][0] + 7 * 7, DEFAULT_MAX);
1352  }
1353 
1354  if (debug_kine) {
1355  std::cout << "position: " << pos.X() << " " << pos.Y() << " " << pos.Z()
1356  << std::endl;
1357  std::cout << "direction: " << dir.X() << " " << dir.Y() << " " << dir.Z()
1358  << std::endl;
1359  std::cout << "momentum: " << mom << " " << momErr << std::endl;
1360  }
1361 }
1362 
1363 //*************************************************************
1364 void ND::TGlobalReconModule::FillKinematics(ND::THandle<ND::TReconState> state,
1365  TLorentzVector& pos,
1366  TLorentzVector& posVar,
1367  TVector3& dir, TVector3& dirVar,
1368  double& mom, double& momErr)
1369 {
1370  //*************************************************************
1371 
1372  if (state) {
1373  pos = TrackingUtils::GetPosition(state);
1374  posVar = TrackingUtils::GetPositionVariance(state);
1375  dir = TrackingUtils::GetDirection(state);
1376  dirVar = TrackingUtils::GetDirectionVariance(state);
1377  mom = TrackingUtils::GetMomentum(state);
1378  momErr = TrackingUtils::GetMomentumError(state);
1379  } else {
1380  pos = TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1381  posVar = TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1382  dir = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1383  dirVar = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1384  mom = DEFAULT_MAX;
1385  momErr = DEFAULT_MAX;
1386  }
1387 
1388  if (debug_kine) {
1389  std::cout << "position: " << pos.X() << " " << pos.Y() << " " << pos.Z()
1390  << std::endl;
1391  std::cout << "direction: " << dir.X() << " " << dir.Y() << " " << dir.Z()
1392  << std::endl;
1393  std::cout << "momentum: " << mom << " " << momErr << std::endl;
1394  }
1395 }
1396 
1397 //*************************************************************
1399  ND::THandle<ND::TG4Trajectory> G4track, ND::THandle<ND::TReconBase> object,
1400  TLorentzVector& pos, TVector3& dir, double& mom, double& momErr,
1401  double& charge, double (&cov)[7][7])
1402 {
1403  //*************************************************************
1404 
1405  // Propagate the first state in the track to a surface normal to z at the
1406  // vertex position.
1407 
1408  ND::THandle<ND::TReconState> tstate = object->GetState();
1409 
1410  ND::THandle<ND::TReconState> newstate = ND::THandle<ND::TReconState>();
1411 
1412  // The G4 track should exist and the track should have TPC, FGD, SFG or P0D
1413  // components
1414  if (tstate && G4track && (object->UsesDetector(ND::TReconBase::kTPC) ||
1415  object->UsesDetector(ND::TReconBase::kFGD) ||
1416  object->UsesDetector(ND::TReconBase::kSFG) ||
1417  object->UsesDetector(ND::TReconBase::kP0D))) {
1418  TVector3 snorm;
1419  double dir_max = -100;
1420  int idir_max = 2;
1421  TVector3 dirS = TrackingUtils::GetDirection(object);
1422  for (int i = 0; i < 3; i++) {
1423  if (fabs(dirS(i)) > dir_max) {
1424  dir_max = fabs(dirS(i));
1425  idir_max = i;
1426  }
1427  }
1428  if (idir_max == 0)
1429  snorm = TVector3(1, 0, 0);
1430  else if (idir_max == 1)
1431  snorm = TVector3(0, 1, 0);
1432  else if (idir_max == 2)
1433  snorm = TVector3(0, 0, 1);
1434 
1435  if (debug_vertex_extrap){
1436  std::cout << "Extrapolation to true vertex: dir = (" << dirS.X() << ", "
1437  << dirS.Y() << ", " << dirS.Z() << ")" << std::endl;
1438  }
1439  if (debug_vertex_extrap)
1440  ND::tman("globalAnalysis").SetVerbosity(0, 6, 0, 0);
1441 
1442  newstate = ND::THandle<ND::TReconState>(new ND::TTrackState);
1443  ND::tman("globalAnalysis").PropagateToSurface(
1444  *tstate, G4track->GetInitialPosition().Vect(),
1445  snorm, *newstate);
1446 
1447  if (debug_vertex_extrap)
1448  ND::tman("globalAnalysis").SetVerbosity(0, 0, 0, 0);
1449  }
1450 
1451  FillKinematics(newstate, pos, dir, mom, momErr, charge, cov);
1452 }
1453 //*************************************************************
1455  ND::THandle<ND::TG4Trajectory> G4track, ND::THandle<ND::TReconBase> object,
1456  TLorentzVector& pos, TLorentzVector& posVar, TVector3& dir,
1457  TVector3& dirVar, double& mom, double& momErr)
1458 {
1459  //*************************************************************
1460 
1461  // Propagate the first state in the track to a surface normal to z at the
1462  // vertex position.
1463 
1464  ND::THandle<ND::TReconState> tstate = object->GetState();
1465 
1466  ND::THandle<ND::TReconState> newstate = ND::THandle<ND::TReconState>();
1467 
1468  // The G4 track should exist and the track should have TPC, FGD, SFG or P0D
1469  // components
1470  if (tstate && G4track && (object->UsesDetector(ND::TReconBase::kTPC) ||
1471  object->UsesDetector(ND::TReconBase::kFGD) ||
1472  object->UsesDetector(ND::TReconBase::kSFG) ||
1473  object->UsesDetector(ND::TReconBase::kP0D))) {
1474 
1475  TVector3 snorm;
1476  double dir_max = -100;
1477  int idir_max = 2;
1478  TVector3 dirS = TrackingUtils::GetDirection(object);
1479  for (int i = 0; i < 3; i++) {
1480  if (fabs(dirS(i)) > dir_max) {
1481  dir_max = fabs(dirS(i));
1482  idir_max = i;
1483  }
1484  }
1485  if (idir_max == 0)
1486  snorm = TVector3(1, 0, 0);
1487  else if (idir_max == 1)
1488  snorm = TVector3(0, 1, 0);
1489  else if (idir_max == 2)
1490  snorm = TVector3(0, 0, 1);
1491 
1492  if (debug_vertex_extrap)
1493  std::cout << "Extrapolation to true vertex: dir = (" << dirS.X() << ", "
1494  << dirS.Y() << ", " << dirS.Z() << ")" << std::endl;
1495 
1496  if (debug_vertex_extrap)
1497  ND::tman("globalAnalysis").SetVerbosity(0, 6, 0, 0);
1498 
1499  newstate = ND::THandle<ND::TReconState>(new ND::TTrackState);
1500  ND::tman("globalAnalysis")
1501  .PropagateToSurface(*tstate, G4track->GetInitialPosition().Vect(),
1502  snorm, *newstate);
1503 
1504  if (debug_vertex_extrap)
1505  ND::tman("globalAnalysis").SetVerbosity(0, 0, 0, 0);
1506  }
1507 
1508  FillKinematics(newstate, pos, posVar, dir, dirVar, mom, momErr);
1509 }
1510 
1511 //*************************************************************
1513  ND::THandle<ND::TG4Trajectory> G4track, ND::THandle<ND::TReconBase> object,
1514  TGlobalPID& globalObject)
1515 {
1516  //*************************************************************
1517 
1518  // __________________________________________________________
1519  // Fill the Alternates information for Global PIDs.
1520 
1521  // make sure it is a PID
1522  ND::THandle<ND::TReconPID> pid = object;
1523  if (!pid) return;
1524 
1525  if (!(object->UsesDetector(ND::TReconBase::kTPC)) ||
1526  object->CheckStatus(ND::TReconBase::kLikelihoodFit))
1527  return;
1528 
1529  // do nothing for TPC-only objects
1530  if (object->GetDetectors() == ND::TReconBase::kTPC1 ||
1531  object->GetDetectors() == ND::TReconBase::kTPC2 ||
1532  object->GetDetectors() == ND::TReconBase::kTPC3)
1533  return;
1534 
1535  // do nothing for curving back tracks
1536  if (TrackingUtils::GetCurvBackTrack(*object)) return;
1537 
1538  const ND::TReconObjectContainer& alter = pid->GetAlternates();
1539  ND::TReconObjectContainer::const_iterator it;
1540  for (it = alter.begin(); it != alter.end(); it++) {
1541  // create a new TGlobalPIDAlternate
1542  TGlobalPIDAlternate* PIDAlternate =
1543  new ((*globalObject.Alternates)[globalObject.NAlternates++])
1545  FillGlobalPIDAlternate(G4track, *it, *PIDAlternate);
1546  }
1547 }
1548 
1549 //*************************************************************
1551  ND::THandle<ND::TG4Trajectory> G4track, ND::THandle<ND::TReconBase> object,
1552  TGlobalPIDAlternate& PIDAlternate)
1553 {
1554  //*************************************************************
1555 
1556  // __________________________________________________________
1557  // Fill the Alternates information for inner (P0D+Tracker) Global PIDs.
1558 
1559  // try to get the state of the object. If it dosen't exists skip the object.
1560  try {
1561  ND::THandle<ND::TReconState> tstate = object->GetState();
1562  } catch (ND::EReconObject e) {
1563  std::cout << "TReconBase with no state. Skip object !!" << std::endl;
1564  return;
1565  }
1566 
1567  //--------- Information about the detectors that used in this object
1568  PIDAlternate.Detectors = GetDetectorNumber(object);
1569  FillDetectorUsed(object, PIDAlternate.DetectorUsed);
1570 
1571  //------- General information
1572 
1573  PIDAlternate.Status = object->CheckStatus(object->kSuccess);
1574  PIDAlternate.Chi2 = object->GetQuality();
1575  PIDAlternate.NDOF = object->GetNDOF();
1576  PIDAlternate.Charge = TrackingUtils::GetCharge(object);
1577  PIDAlternate.Length = ComputeTrackLength(object);
1578 
1579  //------- Front and Back kinematics
1580  ND::THandle<ND::TReconState> firstState =
1581  TrackingUtils::GetFirstState(*object);
1582  FillKinematics(firstState, PIDAlternate.FrontPosition,
1583  PIDAlternate.FrontPositionVar, PIDAlternate.FrontDirection,
1584  PIDAlternate.FrontDirectionVar, PIDAlternate.FrontMomentum,
1585  PIDAlternate.FrontMomentumError);
1586 
1587  ND::THandle<ND::TReconState> lastState = TrackingUtils::GetLastState(*object);
1588  FillKinematics(lastState, PIDAlternate.BackPosition,
1589  PIDAlternate.BackPositionVar, PIDAlternate.BackDirection,
1590  PIDAlternate.BackDirectionVar, PIDAlternate.BackMomentum,
1591  PIDAlternate.BackMomentumError);
1592 
1593  //-------- Fill the kinematic extrapolated to the true vertex
1595  G4track, object, PIDAlternate.PositionAtTrueVertex,
1596  PIDAlternate.PositionVarAtTrueVertex, PIDAlternate.DirectionAtTrueVertex,
1597  PIDAlternate.DirectionVarAtTrueVertex, PIDAlternate.MomentumAtTrueVertex,
1598  PIDAlternate.MomentumErrorAtTrueVertex);
1599 
1600  //---------- Set the PID information
1601  ND::THandle<ND::TReconPID> PID = object;
1602  if (PID) {
1603  PIDAlternate.PIDWeight = PID->GetPIDWeight();
1604  PIDAlternate.ParticleId = ComputeParticleId(PID);
1605  }
1606 }
1607 
1608 //*************************************************************
1610  ND::THandle<ND::TReconBase> object)
1611 {
1612  //*************************************************************
1613 
1614  // Default for showers is 0
1615  double length = 0;
1616 
1617  double length_tmp;
1618 
1619  length = DEFAULT_MAX;
1620 
1621  if (!object) return length;
1622 
1623  if (TrackingUtils::IsShower(object)) return 0.;
1624 
1625  ND::THandle<ND::TReconPID> pid = object;
1626  ND::THandle<ND::TReconTrack> track = object;
1627 
1628  if (!pid && !track) return length;
1629 
1630  bool ok = ND::tman().ComputeObjectLength(object, length_tmp);
1631 
1632  if (ok) length = length_tmp;
1633 
1634  return length;
1635 }
1636 
1637 //*************************************************************
1639  ND::TND280Event& event,
1640  ND::THandle<ND::TReconObjectContainer> globalObjects)
1641 {
1642 //*************************************************************
1643  // Container names
1644  // containers are "trakerPrimaryVertex" and "trackerVertices"
1645  TString tname = "trackerRecon";
1646  TString tvname = "tracker";
1647  TString gname = "globalVertex";
1648  TString gvname = "globalVertex";
1649 
1650  // We assume it's global vertices first
1651  bool global = true;
1652  TString reconame = gname;
1653  TString vname = gvname;
1654 
1655  if (fUseECalVertices) {
1656  ND::THandle<ND::TAlgorithmResult> ResultBin = event.GetFit("globalVertex");
1657 
1658  ND::THandle<ND::TReconObjectContainer> pvertices =
1659  ResultBin->GetResultsContainer("vertices");
1660  if (!pvertices) {
1661  ND280NamedInfo("ECalVertexInTGRM",
1662  "Leaving FillVertexInfo as we couldn't find the container.");
1663  return;
1664  }
1665 
1666  ND::THandle<ND::TG4PrimaryVertexContainer> g4PrimVerts;
1667  if (fIsMC) {
1668  g4PrimVerts =
1669  event.Get<ND::TG4PrimaryVertexContainer>("truth/G4PrimVertex00");
1670  }
1671  for (size_t prim_vert_it = 0; prim_vert_it < pvertices->size();
1672  ++prim_vert_it) {
1673  ND::THandle<ND::TReconVertex> vert = pvertices->at(prim_vert_it);
1674  if (!vert) {
1675  continue;
1676  }
1677 
1678  // Fill the primary
1679  FillVertex(event,vert, true);
1680 
1681  if (fIsMC && bool(g4PrimVerts)) {
1682  MatchTrueVertex(g4PrimVerts);
1683  }
1684 
1685  if (vert->GetConstituents()) {
1686  for (size_t sec_vert_it = 0;
1687  sec_vert_it < vert->GetConstituents()->size(); ++sec_vert_it) {
1688  ND::THandle<ND::TReconVertex> sVert =
1689  vert->GetConstituents()->at(sec_vert_it);
1690 
1691  if (!sVert) {
1692  continue;
1693  }
1694  bool cool_beans = FillVertex(event,sVert, false);
1695  if (cool_beans) {
1696  ND280NamedInfo("ECalVertexInTGRM", "Added secondary vertex.");
1697  if (fIsMC && bool(g4PrimVerts)) {
1698  MatchTrueVertex(g4PrimVerts);
1699  }
1700  }
1701  }
1702  }
1703 
1704  ND280NamedInfo("ECalVertexInTGRM", "Added an ecalVertex.");
1705  }
1706  ND280NamedInfo("ECalVertexInTGRM", "Leaving FillVertexInfo having examined "
1707  << pvertices->size() << " vertices.");
1708  } // End us ECal Vertices
1709  else {
1710  // Fill primary and secondary vertex info
1711  //**********************************************************
1712  for (int ibin = 0; ibin < NTIMEBINS; ibin++) {
1713  TString bin_result_name = reconame + "_timebin";
1714  bin_result_name += ibin;
1715 
1716  ND::THandle<ND::TAlgorithmResult> ResultBin =
1717  event.GetFit(bin_result_name);
1718  // Check presence of global vertexing, if not try tracker vertices
1719  if (ibin == 0 && !ResultBin) {
1720  global = false;
1721  reconame = tname;
1722  vname = tvname;
1723  ResultBin = event.GetFit("trackerRecon_timebin0");
1724  }
1725 
1726  // If we didn't find a bin, stop looking
1727  if (!ResultBin) break;
1728 
1729  // Fill tracker to global tracks map
1730  if (!global) {
1731  TString container_name = "finalTrackerObjects";
1732  ND::THandle<ND::TReconObjectContainer> finalTracks =
1733  ResultBin->GetResultsContainer(container_name);
1734  if (!finalTracks) continue;
1735  if (finalTracks->size() == 0) continue;
1736  fTrackerGlobalIndexMap.clear();
1738  *finalTracks);
1739  }
1740 
1741  TString primary_name = vname + "PrimaryVertex";
1742  ND::THandle<ND::TReconObjectContainer> pvertices =
1743  ResultBin->GetResultsContainer(primary_name);
1744  if (!pvertices) continue;
1745  if (pvertices->size() == 0) continue;
1746 
1747  ND::THandle<ND::TReconVertex> pv = pvertices->front();
1748  if (!pv) continue;
1749 
1750  // Fill the primary vertex, if failed, do not proceed
1751  if (!FillVertex(event,pv, true)) continue;
1752 
1753  ND::THandle<ND::TG4PrimaryVertexContainer> g4PrimVert =
1754  event.Get<ND::TG4PrimaryVertexContainer>("truth/G4PrimVertex00");
1755  if (g4PrimVert) MatchTrueVertex(g4PrimVert);
1756 
1757  TString vertices_name = vname + "Vertices";
1758  ND::THandle<ND::TReconObjectContainer> svertices =
1759  ResultBin->GetResultsContainer(vertices_name);
1760  if (!svertices) continue;
1761 
1762  for (ND::TReconObjectContainer::iterator siter = svertices->begin();
1763  siter != svertices->end(); siter++) {
1764  ND::THandle<ND::TReconVertex> sv = *siter;
1765  if (!sv) continue;
1766 
1767  // Skip the primary vertex
1768  if (sv == pv) continue;
1769 
1770  bool vertexCreated = false;
1771 
1772  // Fill secondary vertex
1773  vertexCreated = FillVertex(event,sv, false);
1774 
1775  if (g4PrimVert && vertexCreated) MatchTrueVertex(g4PrimVert);
1776  }
1777  }
1778  }
1779 
1780  fTrackerGlobalIndexMap.clear();
1781 }
1782 
1783 //*************************************************************
1784 void ND::TGlobalReconModule::FillGlobalHit(ND::THandle<ND::THit> hit,
1785  TGlobalHit& gHit)
1786 {
1787  //*************************************************************
1788 
1789  if (hit) {
1790  gHit.Position = hit->GetPosition();
1791  gHit.Time = hit->GetTime();
1792  gHit.PositionError = hit->GetUncertainty();
1793  gHit.Charge = hit->GetCharge();
1794  gHit.Type = hit->IsXHit() + (hit->IsYHit()) * 10 + (hit->IsZHit()) * 100;
1795  } else {
1796  gHit.Position = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1797  gHit.Time = DEFAULT_MAX;
1798  gHit.PositionError = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1799  gHit.Charge = DEFAULT_MAX;
1800  gHit.Type = DEFAULT_MAX;
1801  }
1802 }
1803 
1804 //*************************************************************
1805 void ND::TGlobalReconModule::FillGlobalHit(ND::THandle<ND::THit> hit,
1806  TSMRDHit& smrdHit)
1807 {
1808  //*************************************************************
1809 
1810  if (hit) {
1811  smrdHit.Position = hit->GetPosition();
1812  smrdHit.Time = hit->GetTime();
1813  smrdHit.PositionError = hit->GetUncertainty();
1814  smrdHit.Charge = hit->GetCharge();
1815  smrdHit.Type = hit->IsXHit() + (hit->IsYHit()) * 10 + (hit->IsZHit()) * 100;
1816 
1817  } else {
1818  smrdHit.Position = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1819  smrdHit.Time = DEFAULT_MAX;
1820  smrdHit.PositionError = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
1821  smrdHit.Charge = DEFAULT_MAX;
1822  smrdHit.Type = DEFAULT_MAX;
1823  }
1824 }
1825 
1826 //*************************************************************
1827 void ND::TGlobalReconModule::FillSmrdHit(ND::THandle<ND::THit> hit,
1828  TSMRDHit& smrdHit)
1829 {
1830  //*************************************************************
1831  enum ESMRDWall { kTop = 0, kBottom, kRight, kLeft };
1832  // fill general info
1833  FillGlobalHit(hit, smrdHit);
1834  if (hit) {
1835  bool isTopWall = ND::TGeomInfo::SMRD().IsSMRDTopWall(hit);
1836  bool isBottomWall = ND::TGeomInfo::SMRD().IsSMRDBottomWall(hit);
1837  bool isRightWall = ND::TGeomInfo::SMRD().IsSMRDRightWall(hit);
1838  bool isLeftWall = ND::TGeomInfo::SMRD().IsSMRDLeftWall(hit);
1839 
1840  if (isTopWall) smrdHit.Wall = kTop;
1841  if (isBottomWall) smrdHit.Wall = kBottom;
1842  if (isRightWall) smrdHit.Wall = kRight;
1843  if (isLeftWall) smrdHit.Wall = kLeft;
1844  smrdHit.Yoke = ND::TGeomInfo::SMRD().GetYokeRingNumber(hit);
1845  smrdHit.Layer = ND::TGeomInfo::SMRD().GetSMRDRingNumber(hit);
1846  smrdHit.Tower = ND::TGeomInfo::SMRD().GetSMRDTowerNumber(hit);
1847  smrdHit.Counter = ND::TGeomInfo::SMRD().GetSMRDScintNumber(hit);
1848 
1849  } else {
1850  // fill with unmeaningful values
1851  smrdHit.Wall = -1;
1852  smrdHit.Yoke = -1;
1853  smrdHit.Layer = -1;
1854  smrdHit.Tower = -1;
1855  smrdHit.Counter = -1;
1856  }
1857 }
1858 
1859 //*************************************************************
1861  ND::THandle<ND::TReconBase> object, TSubBaseObject& sub, int det)
1862 {
1863  //*************************************************************
1864 
1865  if (ReconObjectUtils::GetOriginalObject(object))
1866  sub.UniqueID = ReconObjectUtils::GetOriginalObject(object)->GetUniqueID();
1867  else
1868  sub.UniqueID = object->GetUniqueID();
1869 
1870  sub.Detector = det;
1871  sub.Status = object->CheckStatus(object->kSuccess);
1872  sub.NDOF = object->GetNDOF();
1873  try {
1874  if (object->Get<ND::TIntegerDatum>("NNodes"))
1875  sub.NNodes = object->Get<ND::TIntegerDatum>("NNodes")
1876  ->GetValue(); // If this is a TPC object,should use the
1877  // new (P6) method of getting the number
1878  // of nodes
1879  else
1880  sub.NNodes = object->GetNodes().size();
1881  } catch (ND::EReconObject const& e) {
1882  sub.NNodes = 0;
1883  }
1884 
1885  sub.Chi2 = object->GetQuality();
1886  sub.EDeposit = TrackingUtils::GetEDeposit(object);
1887 
1888  // The number of constituents. For composite objects
1889  sub.NConstituents = 0;
1890  if (object->GetConstituents())
1891  sub.NConstituents = object->GetConstituents()->size();
1892 
1893  sub.NHits = DEFAULT_MAX;
1894  if (object->GetHits()) sub.NHits = object->GetHits()->size();
1895 
1896  // the length of the object for track-like objects
1897  sub.Length = ComputeTrackLength(object);
1898 
1899  //--------- Front and back Kinematics
1900  // Get the edge states
1901  ND::THandle<ND::TReconState> firstState, lastState;
1902 
1903  ND::tman().GetFirstAndLastStates(object, firstState, lastState);
1904 
1905  FillKinematics(firstState, sub.FrontPosition, sub.FrontPositionVar,
1907  sub.FrontMomentumError);
1908 
1909  FillKinematics(lastState, sub.BackPosition, sub.BackPositionVar,
1911  sub.BackMomentumError);
1912 
1913  // Fill the true particle when it is found
1914  double pur, eff;
1915  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*object, pur, eff);
1916  FillTrueParticle(G4track, pur, eff, sub.TrueParticle);
1917 }
1918 
1919 namespace {
1920  template <typename T, size_t N>
1921  size_t ArrSize(T const (&arr)[N]) {
1922  return N;
1923  }
1924 }
1925 
1926 //*************************************************************
1927 void ND::TGlobalReconModule::FillECALInfo(ND::THandle<ND::TReconBase> object,
1928  TGlobalPID& globalObject)
1929 {
1930  //*************************************************************
1931 
1932  static const ND::TReconBase::Status ECalDetBits[] = {
1933  ND::TReconBase::kLeftPECal, ND::TReconBase::kRightPECal,
1934  ND::TReconBase::kTopPECal, ND::TReconBase::kBottomPECal,
1935  ND::TReconBase::kLeftTECal, ND::TReconBase::kRightTECal,
1936  ND::TReconBase::kTopTECal, ND::TReconBase::kBottomTECal,
1937  ND::TReconBase::kDSECal};
1938 
1939  // Get constituents in any of the calorimeters
1940  for (size_t det_bit = 0; det_bit < ArrSize(ECalDetBits); det_bit++) {
1941  if (!object->UsesDetector(ECalDetBits[det_bit])) {
1942  continue;
1943  }
1944 
1945  // one needs to take into account that ecalRecon doesn`t combine tracks
1946  // that
1947  // cross
1948  // Left/Right sub-volumes for TECal Top and Bottom
1949  ND::THandle<ND::TReconObjectContainer> ecalObjects(
1950  new ND::TReconObjectContainer());
1951 
1952  ReconObjectUtils::GetConstituentsInDetector(object, ECalDetBits[det_bit],
1953  *ecalObjects);
1954 
1955  for (size_t eo_it = 0; eo_it < ecalObjects->size(); eo_it++) {
1956  ND::THandle<ND::TReconBase> ecalObject = ecalObjects->at(eo_it);
1957 
1958  if (!ecalObject) {
1959  continue;
1960  }
1961 
1962  ND280NamedVerbose(
1963  "TGlobalReconModule",
1964  "Transposing ECal object from: " << ecalObject->ConvertDetector());
1965 
1966  TECALObject* ECalObjToFill;
1967  // P0DECAL constituents
1968  if (det_bit < 4) {
1969  if (globalObject.NP0DECALs >= NMAXP0DECAL) {
1970  ND280NamedWarn("TGlobalReconModule",
1971  "Ignoring as already have too many P0DECal objects.");
1972  continue;
1973  }
1974  ECalObjToFill =
1975  new ((*(globalObject.P0DECAL))[globalObject.NP0DECALs++])
1976  TECALObject;
1977  }
1978  // TrECAL constituents
1979  else if (det_bit < 8) {
1980  if (globalObject.NECALs >= NMAXECAL) {
1981  ND280NamedWarn("TGlobalReconModule",
1982  "Ignoring as already have too many ECal objects.");
1983  continue;
1984  }
1985  ECalObjToFill =
1986  new ((*(globalObject.ECAL))[globalObject.NECALs++]) TECALObject;
1987  globalObject.NTrECALs++;
1988  }
1989  // DsECAL constituents
1990  else {
1991  if (globalObject.NECALs >= NMAXECAL) {
1992  ND280NamedWarn("TGlobalReconModule",
1993  "Ignoring as already have too many ECal objects.");
1994  continue;
1995  }
1996  ECalObjToFill =
1997  new ((*(globalObject.ECAL))[globalObject.NECALs++]) TECALObject;
1998  globalObject.NDsECALs++;
1999  }
2000 
2001  // fill general information
2002  FillSubBaseObject(ecalObject, *ECalObjToFill, det_bit + 1);
2003  // Still need to fill TSubBaseShowerObject::Cone
2004 
2005  // Set defaults:
2006  ECalObjToFill->LLR_Quality = -9999.;
2007  ECalObjToFill->LLR_MIP_EM = -9999.;
2008  ECalObjToFill->LLR_MIP_Pion = -9999.;
2009  ECalObjToFill->LLR_EM_HIP = -9999.;
2010  ECalObjToFill->LLR_MIP_EM_LowMomentum = -9999.;
2011  ECalObjToFill->LLR_MIP_HIP_VACut = -9999.;
2012  ECalObjToFill->AverageHitTime = DEFAULT_MAX;
2013  ECalObjToFill->AverageZPosition = DEFAULT_MAX;
2014  ECalObjToFill->EMEnergyFit_Result = DEFAULT_MAX;
2015  ECalObjToFill->EMEnergyFit_Uncertainty = DEFAULT_MAX;
2016  ECalObjToFill->FilledAsType = -1;
2017  ECalObjToFill->PID_Circularity = DEFAULT_MAX;
2018  ECalObjToFill->PID_Angle = DEFAULT_MAX;
2019  ECalObjToFill->PID_ShowerAngle = DEFAULT_MAX;
2020  ECalObjToFill->PID_Asymmetry = DEFAULT_MAX;
2021  ECalObjToFill->PID_TruncatedMaxRatio = DEFAULT_MAX;
2022  ECalObjToFill->PID_TransverseChargeRatio = DEFAULT_MAX;
2023  ECalObjToFill->PID_FrontBackRatio = DEFAULT_MAX;
2024  ECalObjToFill->Containment = DEFAULT_MAX;
2025  ECalObjToFill->Cone = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
2026  ECalObjToFill->EDeposit = DEFAULT_MAX;
2027  ECalObjToFill->Thrust = DEFAULT_MAX;
2028  ECalObjToFill->ThrustOrigin =
2029  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
2030  ECalObjToFill->ThrustAxis =
2031  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
2032  ECalObjToFill->InnerMostLayerHit = -1;
2033  ECalObjToFill->OuterMostLayerHit = -1;
2034  ECalObjToFill->Width = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
2035 
2036  if ((det_bit < 4) || !fUseECalVertices) {
2037  if (!ecalObject->GetConstituents()) {
2038  ND280NamedWarn("TGlobalReconModule",
2039  "ECal PID contained no constituents.");
2040  continue;
2041  }
2042  // Unlike TTrackerECALReconModule, we're just going to assume the first
2043  // constituent as thats what global did before.
2044  ND::THandle<ND::TReconTrack> track_constit =
2045  (*ecalObject->GetConstituents()->begin());
2046  ND::THandle<ND::TReconShower> shower_constit =
2047  (*ecalObject->GetConstituents()->begin());
2049  // Only the implicit dynamic cast that is valid will result in a new
2050  // object.
2051  if (track_constit) {
2052  if (!track_constit->GetEDeposit()) {
2053  ND280NamedWarn("TGlobalReconModule",
2054  "ECal PID-constituent track deposited no energy.");
2055  continue;
2056  }
2057  // Making a TECALReconObject ClonesArray entry...
2059  track_constit, ecalObject, false, &ECalIsoObjToFill);
2060 
2061  ECalObjToFill->LLR_Quality = ECalIsoObjToFill.PID_LLR_Quality;
2062  if (ECalObjToFill->LLR_Quality == 0) {
2063  // only fill the PID variables if the PID has good quality.
2064  ECalObjToFill->LLR_MIP_EM = ECalIsoObjToFill.PID_LLR_MIP_EM;
2065  ECalObjToFill->LLR_MIP_Pion = ECalIsoObjToFill.PID_LLR_MIP_Pion;
2066  ECalObjToFill->LLR_EM_HIP = ECalIsoObjToFill.PID_LLR_EM_HIP;
2067  ECalObjToFill->LLR_MIP_EM_LowMomentum =
2068  ECalIsoObjToFill.PID_LLR_MIP_EM_LowMomentum;
2069  }
2070  ECalObjToFill->AverageHitTime = ECalIsoObjToFill.AverageHitTime;
2071  ECalObjToFill->AverageZPosition = ECalIsoObjToFill.AverageZPosition;
2072  ECalObjToFill->EMEnergyFit_Result =
2073  ECalIsoObjToFill.EMEnergyFit_Result;
2074  ECalObjToFill->EMEnergyFit_Uncertainty =
2075  ECalIsoObjToFill.EMEnergyFit_Uncertainty;
2076  ECalObjToFill->FilledAsType = 0;
2077  ECalObjToFill->PID_Circularity = ECalIsoObjToFill.PID_Circularity;
2078  ECalObjToFill->PID_Angle = ECalIsoObjToFill.PID_Angle;
2079  ECalObjToFill->PID_ShowerAngle = ECalIsoObjToFill.PID_ShowerAngle;
2080  ECalObjToFill->PID_Asymmetry = ECalIsoObjToFill.PID_Asymmetry;
2081  ECalObjToFill->PID_TruncatedMaxRatio =
2082  ECalIsoObjToFill.PID_TruncatedMaxRatio;
2083  ECalObjToFill->PID_TransverseChargeRatio =
2084  ECalIsoObjToFill.PID_TransverseChargeRatio;
2085  ECalObjToFill->PID_FrontBackRatio =
2086  ECalIsoObjToFill.PID_FrontBackRatio;
2087  ECalObjToFill->Containment = ECalIsoObjToFill.Containment;
2088 
2089  ECalObjToFill->Cone = ECalIsoObjToFill.Shower.ConeAngle;
2090  ECalObjToFill->EDeposit = ECalIsoObjToFill.Track.EDeposit;
2091 
2092  ECalObjToFill->Thrust = ECalIsoObjToFill.Thrust;
2093  ECalObjToFill->ThrustOrigin = ECalIsoObjToFill.ThrustOrigin;
2094  ECalObjToFill->ThrustAxis = ECalIsoObjToFill.ThrustAxis;
2095  ECalObjToFill->InnerMostLayerHit =
2096  ECalIsoObjToFill.MostUpStreamLayerHit;
2097  ECalObjToFill->OuterMostLayerHit =
2098  ECalIsoObjToFill.MostDownStreamLayerHit;
2099 
2100  ECalObjToFill->Width = ECalIsoObjToFill.Track.Width;
2101  // The length has already been set, but it is the base object variable
2102  ECalObjToFill->Length = ECalObjToFill->TSubBaseObject::Length;
2103 
2104  ND280NamedVerbose(
2105  "TGlobalReconModule",
2106  "Added information about an ECal Track PID constituent.");
2107  } // End fill as track
2108  else if (shower_constit) {
2109  if (!shower_constit->GetEDeposit()) {
2110  ND280NamedWarn("TGlobalReconModule",
2111  "ECal PID-constituent shower deposited no energy.");
2112  continue;
2113  }
2114 
2116  shower_constit, ecalObject, false, &ECalIsoObjToFill);
2117  ECalObjToFill->LLR_Quality = ECalIsoObjToFill.PID_LLR_Quality;
2118  ECalObjToFill->LLR_MIP_EM = ECalIsoObjToFill.PID_LLR_MIP_EM;
2119  ECalObjToFill->LLR_MIP_Pion = ECalIsoObjToFill.PID_LLR_MIP_Pion;
2120  ECalObjToFill->LLR_EM_HIP = ECalIsoObjToFill.PID_LLR_EM_HIP;
2121  ECalObjToFill->LLR_MIP_EM_LowMomentum =
2122  ECalIsoObjToFill.PID_LLR_MIP_EM_LowMomentum;
2123  ECalObjToFill->AverageHitTime = ECalIsoObjToFill.AverageHitTime;
2124  ECalObjToFill->EMEnergyFit_Result =
2125  ECalIsoObjToFill.EMEnergyFit_Result;
2126  ECalObjToFill->EMEnergyFit_Uncertainty =
2127  ECalIsoObjToFill.EMEnergyFit_Uncertainty;
2128  ECalObjToFill->FilledAsType = 1;
2129  ECalObjToFill->PID_Circularity = ECalIsoObjToFill.PID_Circularity;
2130  ECalObjToFill->PID_Angle = ECalIsoObjToFill.PID_Angle;
2131  ECalObjToFill->PID_ShowerAngle = ECalIsoObjToFill.PID_ShowerAngle;
2132  ECalObjToFill->PID_Asymmetry = ECalIsoObjToFill.PID_Asymmetry;
2133  ECalObjToFill->PID_TruncatedMaxRatio =
2134  ECalIsoObjToFill.PID_TruncatedMaxRatio;
2135  ECalObjToFill->PID_TransverseChargeRatio =
2136  ECalIsoObjToFill.PID_TransverseChargeRatio;
2137  ECalObjToFill->PID_FrontBackRatio =
2138  ECalIsoObjToFill.PID_FrontBackRatio;
2139  ECalObjToFill->Containment = ECalIsoObjToFill.Containment;
2140 
2141  ECalObjToFill->Cone = ECalIsoObjToFill.Shower.ConeAngle;
2142  ECalObjToFill->Length = ECalIsoObjToFill.ObjectLength;
2143  ECalObjToFill->EDeposit = ECalIsoObjToFill.Shower.EDeposit;
2144 
2145  ECalObjToFill->Thrust = ECalIsoObjToFill.Thrust;
2146  ECalObjToFill->ThrustOrigin = ECalIsoObjToFill.ThrustOrigin;
2147  ECalObjToFill->ThrustAxis = ECalIsoObjToFill.ThrustAxis;
2148  ECalObjToFill->InnerMostLayerHit =
2149  ECalIsoObjToFill.MostUpStreamLayerHit;
2150  ECalObjToFill->OuterMostLayerHit =
2151  ECalIsoObjToFill.MostDownStreamLayerHit;
2152 
2153  Double_t widthHolder =
2154  ECalObjToFill->Length * tan(ECalObjToFill->PID_ShowerAngle);
2155  ECalObjToFill->Width =
2156  TVector3(widthHolder, widthHolder, widthHolder);
2157 
2158  ND280NamedVerbose(
2159  "TGlobalReconModule",
2160  "Added information about an ECal Shower PID constituent.");
2161  } // End fill as shower
2162  else {
2163  ND280NamedWarn(
2164  "TGlobalReconModule",
2165  "When transposing an ECal object from: "
2166  << ecalObject->ConvertDetector()
2167  << " found a constituent of type: "
2168  << (*ecalObject->GetConstituents()->begin())->ClassName()
2169  << ", expected TReconTrack or TReconShower.");
2170  }
2171  } // End Transpose P0DECal and non ECal-Vtx tracks
2172 
2173  else { // If we are a Tr/Ds object and we are using ECal vertexing.
2174 
2176  ECalIsoVtxTrackToFill;
2178  ecalObject, false, &ECalIsoVtxTrackToFill,
2179  ND::THandle<ND::TG4TrajectoryContainer>(NULL), false);
2180 
2181  // Combine these two to build MIP_HIP
2182  ECalObjToFill->LLR_MIP_EM = ECalIsoVtxTrackToFill.PID_LLR_MIP_EM;
2183  ECalObjToFill->LLR_EM_HIP = ECalIsoVtxTrackToFill.PID_LLR_EM_HIP;
2184 
2185  ECalObjToFill->AverageHitTime = ECalIsoVtxTrackToFill.AverageHitTime;
2186 
2187  ECalObjToFill->InnerMostLayerHit =
2188  ECalIsoVtxTrackToFill.FrontLayerNumber;
2189  ECalObjToFill->OuterMostLayerHit =
2190  ECalIsoVtxTrackToFill.BackLayerNumber;
2191 
2192  ECalObjToFill->EDeposit = ECalIsoVtxTrackToFill.TotalCharge;
2193 
2194  ECalObjToFill->LLR_MIP_HIP_VACut =
2195  ECalIsoVtxTrackToFill.PID_LLR_MIP_HIP_VACut;
2196 
2197  ECalObjToFill->Containment = ECalIsoVtxTrackToFill.Containment;
2198 
2199  ECalObjToFill->FilledAsType = 2;
2200 
2201  ND280NamedVerbose(
2202  "TGlobalReconModule",
2203  "Added information about an ECal Vertex Track constituent.");
2204  // Most non-standard members are unfilled.
2205  }
2206  } // End loop over ECal objects in module
2207  } // End loop over ECal modules
2208 }
2209 
2210 //*************************************************************
2211 void ND::TGlobalReconModule::FillTrackerInfo(ND::THandle<ND::TReconBase> object,
2212  TGlobalPID& globalObject)
2213 {
2214 //*************************************************************
2215 
2216  // We created dummy objects for the 18 possible Tracker combinations:
2217 
2218  // No detector missing
2219  // TPC1-FGD1
2220  // TPC1-FGD1-TPC2
2221  // TPC1-FGD1-TPC2-FGD2
2222  // TPC1-FGD1-TPC2-FGD2-TPC3
2223  // FGD1-TPC2
2224  // FGD1-TPC2-FGD2
2225  // FGD1-TPC2-FGD2-TPC3
2226  // TPC2-FGD2
2227  // TPC2-FGD2-TPC3
2228  // FGD2-TPC3
2229 
2230  ND::TReconTrack dummy[18];
2231  dummy[0].AddDetector(ND::TReconBase::kTPC1);
2232  dummy[0].AddDetector(ND::TReconBase::kFGD1);
2233 
2234  dummy[1].AddDetector(ND::TReconBase::kTPC1);
2235  dummy[1].AddDetector(ND::TReconBase::kFGD1);
2236  dummy[1].AddDetector(ND::TReconBase::kTPC2);
2237 
2238  dummy[2].AddDetector(ND::TReconBase::kTPC1);
2239  dummy[2].AddDetector(ND::TReconBase::kFGD1);
2240  dummy[2].AddDetector(ND::TReconBase::kTPC2);
2241  dummy[2].AddDetector(ND::TReconBase::kFGD2);
2242 
2243  dummy[3].AddDetector(ND::TReconBase::kTPC1);
2244  dummy[3].AddDetector(ND::TReconBase::kFGD1);
2245  dummy[3].AddDetector(ND::TReconBase::kTPC2);
2246  dummy[3].AddDetector(ND::TReconBase::kFGD2);
2247  dummy[3].AddDetector(ND::TReconBase::kTPC3);
2248 
2249  dummy[4].AddDetector(ND::TReconBase::kFGD1);
2250  dummy[4].AddDetector(ND::TReconBase::kTPC2);
2251 
2252  dummy[5].AddDetector(ND::TReconBase::kFGD1);
2253  dummy[5].AddDetector(ND::TReconBase::kTPC2);
2254  dummy[5].AddDetector(ND::TReconBase::kFGD2);
2255 
2256  dummy[6].AddDetector(ND::TReconBase::kFGD1);
2257  dummy[6].AddDetector(ND::TReconBase::kTPC2);
2258  dummy[6].AddDetector(ND::TReconBase::kFGD2);
2259  dummy[6].AddDetector(ND::TReconBase::kTPC3);
2260 
2261  dummy[7].AddDetector(ND::TReconBase::kTPC2);
2262  dummy[7].AddDetector(ND::TReconBase::kFGD2);
2263 
2264  dummy[8].AddDetector(ND::TReconBase::kTPC2);
2265  dummy[8].AddDetector(ND::TReconBase::kFGD2);
2266  dummy[8].AddDetector(ND::TReconBase::kTPC3);
2267 
2268  dummy[9].AddDetector(ND::TReconBase::kFGD2);
2269  dummy[9].AddDetector(ND::TReconBase::kTPC3);
2270 
2271  // one FGD missing
2272  // TPC1-FGD1-TPC2-TPC3
2273  // TPC1-FGD2-TPC2-TPC3
2274  // TPC1-TPC2
2275  // TPC2-TPC3
2276 
2277  dummy[10].AddDetector(ND::TReconBase::kTPC1);
2278  dummy[10].AddDetector(ND::TReconBase::kFGD1);
2279  dummy[10].AddDetector(ND::TReconBase::kTPC2);
2280  dummy[10].AddDetector(ND::TReconBase::kTPC3);
2281 
2282  dummy[11].AddDetector(ND::TReconBase::kTPC1);
2283  dummy[11].AddDetector(ND::TReconBase::kTPC2);
2284  dummy[11].AddDetector(ND::TReconBase::kFGD2);
2285  dummy[11].AddDetector(ND::TReconBase::kTPC3);
2286 
2287  dummy[12].AddDetector(ND::TReconBase::kTPC1);
2288  dummy[12].AddDetector(ND::TReconBase::kTPC2);
2289 
2290  dummy[13].AddDetector(ND::TReconBase::kTPC2);
2291  dummy[13].AddDetector(ND::TReconBase::kTPC3);
2292 
2293  // two FGDs missing
2294  // TPC1-TPC2-TPC3
2295 
2296  dummy[14].AddDetector(ND::TReconBase::kTPC1);
2297  dummy[14].AddDetector(ND::TReconBase::kTPC2);
2298  dummy[14].AddDetector(ND::TReconBase::kTPC3);
2299 
2300  // one TPC missing
2301  // TPC1-FGD1-TPC3
2302  // TPC1-FGD2-TPC3
2303 
2304  dummy[15].AddDetector(ND::TReconBase::kTPC1);
2305  dummy[15].AddDetector(ND::TReconBase::kFGD1);
2306  dummy[15].AddDetector(ND::TReconBase::kTPC3);
2307 
2308  dummy[16].AddDetector(ND::TReconBase::kTPC1);
2309  dummy[16].AddDetector(ND::TReconBase::kFGD2);
2310  dummy[16].AddDetector(ND::TReconBase::kTPC3);
2311 
2312  // two FGDs and one TPC missing
2313  // TPC1-TPC3
2314 
2315  dummy[17].AddDetector(ND::TReconBase::kTPC1);
2316  dummy[17].AddDetector(ND::TReconBase::kTPC3);
2317 
2318  for (int i = 0; i < 18; i++) {
2319  if (!object->UsesDetector(dummy[i].GetDetectors())) continue;
2320 
2321  ND::THandle<ND::TReconBase> trackerObject =
2322  ReconObjectUtils::GetConstituentInDetector(object,
2323  dummy[i].GetDetectors());
2324 
2325  if (trackerObject && globalObject.NTRACKERs < NMAXTRACKER) {
2326  TTrackerObject* tracker =
2327  new ((*(globalObject.TRACKER))[globalObject.NTRACKERs++])
2329 
2330  // fill general information
2331  int det = GetTrackerDetectorNumber(trackerObject);
2332  FillSubBaseObject(trackerObject, *tracker, det);
2333 
2334  // Fill charge for object.
2335  tracker->Charge = TrackingUtils::GetCharge(trackerObject);
2336  CheckMatchingFailure(tracker, trackerObject);
2337  }
2338  }
2339 }
2340 
2341 //*****************************************************
2343  ND::THandle<ND::TReconBase> object)
2344 {
2345 //*****************************************************
2346 
2347  int det = 0;
2348 
2349  if (object->UsesDetector(ND::TReconBase::kTPC1)) det = 1;
2350  if (object->UsesDetector(ND::TReconBase::kTPC2)) det = det * 10 + 2;
2351  if (object->UsesDetector(ND::TReconBase::kTPC3)) det = det * 10 + 3;
2352  if (object->UsesDetector(ND::TReconBase::kFGD1)) det = det * 10 + 4;
2353  if (object->UsesDetector(ND::TReconBase::kFGD2)) det = det * 10 + 5;
2354  if (object->UsesDetector(ND::TReconBase::kSFG)) det = det * 10 + 6;
2355  // What about the HATs????? (AJF 19/3/24) .. added these 3
2356  if (object->UsesDetector(ND::TReconBase::kTopHAT)) det = det * 10 + 7;
2357  if (object->UsesDetector(ND::TReconBase::kBottomHAT)) det = det * 10 + 8;
2358  if (object->UsesDetector(ND::TReconBase::kTOF)) det = det * 10 + 9;
2359 
2360  return det;
2361 }
2362 
2363 //*************************************************************
2364 void ND::TGlobalReconModule::FillTPCInfo(ND::THandle<ND::TReconBase> object,
2365  TGlobalPID& globalObject)
2366 {
2367  //*************************************************************
2368 
2369  ND::TReconBase::Status dets[3] = {
2371 
2372  for (int i = 0; i < 3; i++) {
2373  if (!object->UsesDetector(dets[i])) continue;
2374 
2375  // account for possible >1 segments in one TPC
2376  ND::TReconObjectContainer tpcObjects =
2377  ReconObjectUtils::GetAllConstituentsInDetector(object, dets[i]);
2378 
2379  if (tpcObjects.size() == 0) continue;
2380 
2381  for (ND::TReconObjectContainer::iterator iter = tpcObjects.begin();
2382  iter != tpcObjects.end(); iter++) {
2383  ND::THandle<ND::TReconBase> tpcObject = *iter;
2384 
2385  if (tpcObject && globalObject.NTPCs < NMAXTPC) {
2386  TTPCObject* tpc =
2387  new ((*(globalObject.TPC))[globalObject.NTPCs++]) TTPCObject;
2388  FillTPCObject(tpcObject, *tpc, i + 1);
2389  }
2390  }
2391  }
2392 }
2393 
2394 //*************************************************************
2396  ND::THandle<ND::TReconBase> tpcObject, TTPCObject& tpc, int det)
2397 
2398 {
2399  //*************************************************************
2400 
2401  // fill general information
2402  FillSubBaseObject(tpcObject, tpc, det);
2403 
2404  tpc.Charge = TrackingUtils::GetCharge(tpcObject);
2405 
2406  tpc.NTrun = 0;
2407  tpc.Ccorr = DEFAULT_MAX;
2408  tpc.PullEle = DEFAULT_MAX;
2409  tpc.PullMuon = DEFAULT_MAX;
2410  tpc.PullPion = DEFAULT_MAX;
2411  tpc.PullKaon = DEFAULT_MAX;
2412  tpc.PullProton = DEFAULT_MAX;
2413 
2414  tpc.SigmaEle = DEFAULT_MAX;
2415  tpc.SigmaMuon = DEFAULT_MAX;
2416  tpc.SigmaPion = DEFAULT_MAX;
2417  tpc.SigmaKaon = DEFAULT_MAX;
2418  tpc.SigmaProton = DEFAULT_MAX;
2419 
2420  tpc.dEdxexpEle = DEFAULT_MAX;
2421  tpc.dEdxexpMuon = DEFAULT_MAX;
2422  tpc.dEdxexpPion = DEFAULT_MAX;
2423  tpc.dEdxexpKaon = DEFAULT_MAX;
2424  tpc.dEdxexpProton = DEFAULT_MAX;
2425 
2426  tpc.PDist = DEFAULT_MAX;
2427  tpc.PEField = DEFAULT_MAX;
2428 
2429  tpc.TPCLength = DEFAULT_MAX;
2430  tpc.TrackType = DEFAULT_MAX;
2431 
2432  // True hit segment information
2433  int n_hitseg = 0;
2434  double edepo_sum = 0;
2435  double edepo_sec_sum = 0;
2436  double dedx_ave = 0;
2437  double dedx_sec_ave = 0;
2438 
2439  ND::THandle<ND::THitSelection> tpc_hits = tpcObject->GetHits();
2440  if(tpc_hits){
2441  // Loop over hits
2442  for(ND::THitSelection::iterator hit = tpc_hits->begin();
2443  hit != tpc_hits->end(); hit++){
2444 
2445  // Get true contributed G4VHits
2446  std::vector<ND::TG4VHit*> g4vhit = HitTruthInfo::GetHitTruthInfo(*hit);
2447 
2448  // Loop over G4VHits
2449  for(std::vector<ND::TG4VHit*>::iterator g4Hit = g4vhit.begin();
2450  g4Hit != g4vhit.end(); g4Hit++){
2451 
2452  // Cast the G4VHit into hit segment
2453  ND::TG4HitSegment* G4HitSeg = dynamic_cast<ND::TG4HitSegment*>(*g4Hit);
2454  if(G4HitSeg == NULL) continue;
2455 
2456  // Get the energy deposition of this hit segment
2457  double edepo_temp = G4HitSeg->GetEnergyDeposit();
2458  double edepo_sec_temp = G4HitSeg->GetSecondaryDeposit();
2459 
2460  // Get the "length" of this hit segment
2461  //TVector3 pos_temp;
2462  //pos_temp.SetXYZ(G4HitSeg->GetStopX() - G4HitSeg->GetStartX(),
2463  // G4HitSeg->GetStopY() - G4HitSeg->GetStartY(),
2464  // G4HitSeg->GetStopZ() - G4HitSeg->GetStartZ());
2465  //double len_temp = pos_temp.Mag();
2466  double len_temp = G4HitSeg->GetTrackLength();
2467 
2468  // Record information
2469  n_hitseg += 1;
2470  edepo_sum += edepo_temp;
2471  edepo_sec_sum += edepo_sec_temp;
2472  if(len_temp > 0){
2473  dedx_ave += (edepo_temp / len_temp);
2474  dedx_sec_ave += (edepo_sec_temp / len_temp);
2475  }
2476 
2477  } // End of G4VHit loop
2478 
2479  } // End of hit loop
2480  }
2481 
2482  tpc.TrueEDeposit = edepo_sum;
2483  tpc.TrueEDeposit_sec = edepo_sec_sum;
2484  if(n_hitseg > 0){
2485  tpc.TruedEdx = dedx_ave / n_hitseg;
2486  tpc.TruedEdx_sec = dedx_sec_ave / n_hitseg;
2487  }
2488  else{
2489  tpc.TruedEdx = 0;
2490  tpc.TruedEdx_sec = 0;
2491  }
2492 
2493  // Fill PID information when exists
2494  ND::THandle<ND::TReconPID> pid = tpcObject;
2495 
2496  if (pid) {
2497 
2498  try {
2499  GetTPCDatum<ND::TRealDatum, int>(pid, "NVerRows", tpc.NVerRows);
2500  } catch (ND::EBadConversion& ex) {
2501  GetTPCDatum<ND::TIntegerDatum, int>(pid, "NVerRows", tpc.NVerRows);
2502  }
2503 
2504  try {
2505  GetTPCDatum<ND::TRealDatum, int>(pid, "NHorRows", tpc.NVerRows);
2506  } catch (ND::EBadConversion& ex) {
2507  GetTPCDatum<ND::TIntegerDatum, int>(pid, "NHorRows", tpc.NVerRows);
2508  }
2509 
2510  try {
2511  GetTPCDatum<ND::TRealDatum, int>(pid, "T0Source", tpc.T0Source);
2512  } catch (ND::EBadConversion& ex) {
2513  GetTPCDatum<ND::TIntegerDatum, int>(pid, "T0Source", tpc.T0Source);
2514  }
2515 
2516  // Changed from tpcPid_PullEle to NTrun to fix bug 569 - no reason why
2517  // this
2518  // should work,
2519  // but it did, so the bug still needs investigating.
2520  ND::THandle<ND::TRealDatum> datum_ele =
2521  (pid)->Get<ND::TRealDatum>("tpcPid_NTrun");
2522  if (datum_ele) {
2523  tpc.NTrun = pid->Get<ND::TRealDatum>("tpcPid_NTrun")->GetValue();
2524  tpc.Craw = pid->Get<ND::TRealDatum>("tpcPid_Craw")->GetValue();
2525  tpc.Ccorr = pid->Get<ND::TRealDatum>("tpcPid_Ccorr")->GetValue();
2526  tpc.PullEle = pid->Get<ND::TRealDatum>("tpcPid_PullEle")->GetValue();
2527  tpc.PullMuon = pid->Get<ND::TRealDatum>("tpcPid_PullMuon")->GetValue();
2528  tpc.PullPion = pid->Get<ND::TRealDatum>("tpcPid_PullPion")->GetValue();
2529  tpc.PullKaon = pid->Get<ND::TRealDatum>("tpcPid_PullKaon")->GetValue();
2530  tpc.PullProton =
2531  pid->Get<ND::TRealDatum>("tpcPid_PullProton")->GetValue();
2532  tpc.dEdxexpEle =
2533  pid->Get<ND::TRealDatum>("tpcPid_dEdxexpEle")->GetValue();
2534  tpc.dEdxexpMuon =
2535  pid->Get<ND::TRealDatum>("tpcPid_dEdxexpMuon")->GetValue();
2536  tpc.dEdxexpPion =
2537  pid->Get<ND::TRealDatum>("tpcPid_dEdxexpPion")->GetValue();
2538  tpc.dEdxexpKaon =
2539  pid->Get<ND::TRealDatum>("tpcPid_dEdxexpKaon")->GetValue();
2540  tpc.dEdxexpProton =
2541  pid->Get<ND::TRealDatum>("tpcPid_dEdxexpProton")->GetValue();
2542  tpc.SigmaEle = pid->Get<ND::TRealDatum>("tpcPid_SigmaEle")->GetValue();
2543  tpc.SigmaMuon = pid->Get<ND::TRealDatum>("tpcPid_SigmaMuon")->GetValue();
2544  tpc.SigmaPion = pid->Get<ND::TRealDatum>("tpcPid_SigmaPion")->GetValue();
2545  tpc.SigmaKaon = pid->Get<ND::TRealDatum>("tpcPid_SigmaKaon")->GetValue();
2546  tpc.SigmaProton =
2547  pid->Get<ND::TRealDatum>("tpcPid_SigmaProton")->GetValue();
2548  }
2549 
2550  if (pid->Get<ND::TIntegerDatum>("TrackType")) {
2551  tpc.TrackType = pid->Get<ND::TIntegerDatum>("TrackType")->GetValue();
2552  }
2553  ND::tman("globalAnalysis").GetTPCLength(tpcObject, tpc.TPCLength);
2554  } // pid
2555 
2556  // Get the number of fitted vertical and horizontal cluster, relevant from
2557  // TREx era
2558  tpc.NbFittedVerticalClusters = 0;
2560  if (tpcObject->Get<ND::TIntegerDatum>("NbFittedVerticalClusters"))
2562  tpcObject->Get<ND::TIntegerDatum>("NbFittedVerticalClusters")
2563  ->GetValue();
2564 
2565  if (tpcObject->Get<ND::TIntegerDatum>("NbFittedHorizontalClusters"))
2567  tpcObject->Get<ND::TIntegerDatum>("NbFittedHorizontalClusters")
2568  ->GetValue();
2569 
2570  std::vector<double> vect_tmp;
2571 
2572  if (GetTPCDatum<ND::TRealDatum, double>(tpcObject, "RefitDistortionCorrMom",
2573  vect_tmp) &&
2574  vect_tmp.size() == 1)
2575  tpc.PDist = vect_tmp[0];
2576 
2577  if (GetTPCDatum<ND::TRealDatum, double>(tpcObject, "RefitEFieldDistortionMom",
2578  vect_tmp) &&
2579  vect_tmp.size() == 1)
2580  tpc.PEField = vect_tmp[0];
2581 }
2582 
2583 //*************************************************************
2584 template <class T, typename I>
2585 bool ND::TGlobalReconModule::GetTPCDatum(ND::THandle<ND::TReconBase> object,
2586  const std::string& datum,
2587  std::vector<I>& vvector) const
2588 {
2589  //*************************************************************
2590 
2591  // Clear the vector
2592  vvector.clear();
2593 
2594  bool ok = false;
2595  if (!object) return false;
2596 
2597  // Check whether the object has the datum
2598  if (object->Get<T>(datum.c_str())) {
2599  vvector.push_back(object->Get<T>(datum.c_str())->GetValue());
2600  ok = true;
2601  } else {
2602  // Try to get first layer constituents
2603  ND::THandle<ND::TReconObjectContainer> constituents1 =
2604  object->GetConstituents();
2605 
2606  if (!constituents1) return false;
2607 
2608  // The datum is expected either in each constituent itself or in its first
2609  // contributor
2610  for (ND::TReconObjectContainer::iterator iter = constituents1->begin();
2611  iter != constituents1->end(); iter++) {
2612  ND::THandle<ND::TReconBase> object_tmp1 = *iter;
2613  if (!object_tmp1) continue;
2614 
2615  if (object_tmp1->Get<T>(datum.c_str())) {
2616  vvector.push_back(object_tmp1->Get<T>(datum.c_str())->GetValue());
2617  ok = true;
2618  continue;
2619  }
2620 
2621  ND::THandle<ND::TReconObjectContainer> constituents2 =
2622  object_tmp1->GetConstituents();
2623  if (!constituents2 || constituents2->size() < 1) continue;
2624 
2625  ND::THandle<ND::TReconBase> object_tmp2 = *(constituents2->begin());
2626  if (!object_tmp2) continue;
2627 
2628  if (object_tmp2->Get<T>(datum.c_str())) {
2629  vvector.push_back(object_tmp2->Get<T>(datum.c_str())->GetValue());
2630  ok = true;
2631  continue;
2632  }
2633  }
2634  }
2635 
2636  return ok;
2637 }
2638 
2639 //*************************************************************
2641  ND::THandle<ND::TReconBase> object,
2642  TGlobalPID& globalObject)
2643 {
2644 //*************************************************************
2645 
2646  ND::TReconBase::Status det = ND::TReconBase::kSFG;
2647 
2648  do {
2649  if(!object->UsesDetector(det)) break;
2650 
2651  ND::TReconObjectContainer sfgObjects;
2652 
2653  // for curving-back tracks allow using two constituents in one SFG
2654  if (TrackingUtils::GetCurvBackTrack(*object)) {
2655  sfgObjects =
2656  ReconObjectUtils::GetAllConstituentsInDetector(object, det);
2657  } else {
2658  //!!! WHICH SFG CONSTITUENT ONE WANTS TO USE WHEN THERE ARE TO OR MORE
2659  ND::THandle<ND::TReconBase> sfgConst =
2660  ReconObjectUtils::GetConstituentInDetector(object, det);
2661  if (sfgConst) sfgObjects.push_back(sfgConst);
2662  }
2663 
2664  if (sfgObjects.size() == 0) break;
2665 
2666  for (ND::TReconObjectContainer::iterator iter = sfgObjects.begin();
2667  iter != sfgObjects.end(); iter++) {
2668  ND::THandle<ND::TReconBase> sfgObject = *iter;
2669  std::map<ND::THandle<THit>,int> hitIndices;
2670 
2671  if (sfgObject && globalObject.NSFGs < NMAXSFG) {
2672  TSFGObject* sfg =
2673  new ((*(globalObject.SFG))[globalObject.NSFGs++]) TSFGObject;
2674  // Fill general information
2675  // (for SFG, detector index should always be = 1)
2676  FillSubBaseObject(sfgObject, *sfg, 1 );
2677 
2678  // Fill information of individual SFG hits
2679  sfg->NHits = 0;
2680  ND::THandle<ND::THitSelection> tbHits = sfgObject->GetHits();
2681  if (tbHits) {
2682  int ihit = 0;
2683  for (ND::THitSelection::iterator hit = tbHits->begin();
2684  hit != tbHits->end(); hit++) {
2685  // Fill index map (will be used for filling the node hits)
2686  hitIndices.insert(std::make_pair(*hit, ihit));
2687  ++ihit;
2688  // Fill the information about individual SFG hit
2689  TVector3 pos = (*hit)->GetPosition();
2690  TLorentzVector hitpos = TLorentzVector(
2691  pos[0],pos[1],pos[2],(*hit)->GetTime());
2692  sfg->HitPosition.push_back(hitpos);
2693  sfg->HitCharge .push_back((*hit)->GetCharge());
2694  ND::THitSelection thisHit;
2695  thisHit.push_back(*hit);
2696  sfg->HitTrajID.push_back(
2697  TrackTruthInfo::GetG4TrajIDHits(thisHit));
2698  } // End loop over hits
2699  sfg->NHits = ihit;
2700  } // Finished filling information on individual SFG hits
2701 
2702  double edep_sum = 0;
2703  // Fill information on individual SFG nodes
2704  // (probably only used by tracks and particles, but
2705  // technically valid for all TReconBase objects)
2706  sfg->NNodes = 0;
2707  const ND::TReconNodeContainer& nodeCont = sfgObject->GetNodes();
2708  ND::TReconNodeContainer::const_iterator it_node;
2709  for (it_node = nodeCont.begin();
2710  it_node != nodeCont.end(); ++it_node) {
2711  if(!(*it_node)) continue;
2712  // Variables to fill node information
2713  TLorentzVector pos = TLorentzVector(-999,-999,-999,-999);
2714  TLorentzVector posvar = TLorentzVector(-999,-999,-999,-999);
2715  TVector3 dir = TVector3(-999,-999,-999);
2716  TVector3 dirvar = TVector3(-999,-999,-999);
2717  float edep = 0;
2718  double edep_fit = 0;
2719  int nhits = 0;
2720  std::vector<int> nodeHits;
2721  // Start
2722  const ND::THandle<ND::TReconNode> node = *it_node;
2723  ND::THandle<ND::TReconState> s1 = node->GetState();
2724  if (s1) {
2725  pos = ND::TReconStateUtilities::GetPosition(s1);
2726  posvar = ND::TReconStateUtilities::GetPositionVariance(s1);
2727  dir = ND::TPIDState::GetStateDirection(s1);
2728  dirvar = ND::TPIDState::GetStateDirectionVariance(s1);
2729  }
2730  ND::THandle<ND::TTrackState> s2 = node->GetState();
2731  if(s2){
2732  edep_fit = s2->GetEDeposit();
2733  }
2734  // Every node should have an object
2735  ND::THandle<ND::TReconBase> nodeObject = node->GetObject();
2736  if (nodeObject) {
2737  ND::THandle<ND::TReconState> objState = nodeObject->GetState();
2738  if (objState) {
2739  edep = ND::TPIDState::GetStateEDeposit(objState);
2740  edep_sum += ND::TPIDState::GetStateEDeposit(objState);
2741  }
2742  // Node hits
2743  const ND::THandle<ND::THitSelection>
2744  nodeObjectHits = nodeObject->GetHits();
2745  if (nodeObjectHits) {
2746  ND::THitSelection::const_iterator hit;
2747  for (hit = nodeObjectHits->begin();
2748  hit != nodeObjectHits->end(); ++hit) {
2749  auto find = hitIndices.find(*hit);
2750  if(find != hitIndices.end()){
2751  nodeHits.push_back(hitIndices[*hit]);
2752  ++nhits;
2753  }
2754  }
2755  }
2756  }
2757  // Fill variables
2758  sfg->NodePosition .push_back(pos);
2759  sfg->NodePosVariance.push_back(posvar);
2760  sfg->NodeDirection .push_back(dir);
2761  sfg->NodeDirVariance.push_back(dirvar);
2762  sfg->NodeEDeposit .push_back(edep);
2763  sfg->NodeEDeposit_fit.push_back(edep_fit);
2764  sfg->NodeNHits .push_back(nhits);
2765  sfg->NodeHits .push_back(nodeHits);
2766  ++sfg->NNodes;
2767  } // Finished filling information on individual SFG nodes
2768  // Fill length
2769  double length_temp = 0;
2770  it_node = nodeCont.begin();
2771  ND::THandle<ND::TReconState> nodeState = (*it_node)->GetState();
2772  TVector3 frontPos = ND::TReconStateUtilities::GetPosition(nodeState).Vect();
2773  ++it_node;
2774  while(it_node != nodeCont.end()){
2775  if(!(*it_node)){
2776  ++it_node;
2777  continue;
2778  }
2779  nodeState = (*it_node)->GetState();
2780  TVector3 currPos = ND::TReconStateUtilities::GetPosition(nodeState).Vect();
2781  length_temp += (currPos - frontPos).Mag();
2782  frontPos = currPos;
2783  ++it_node;
2784  }
2785  sfg->Length = length_temp;
2786  // Fill energy deposit
2787  ND::THandle<ND::TReconPID> sfgPID = sfgObject;
2788  ND::THandle<ND::TReconTrack> sfgTrack = sfgObject;
2789  ND::THandle<ND::TReconCluster> sfgCluster = sfgObject;
2790  if(sfgPID){
2791  sfg->Type = 0; // particle
2792  // If the object is TReconPID, fill position/direction/EDeposit.
2793  ND::THandle<ND::TPIDState> pidState = sfgPID->GetState();
2794  sfg->Position = pidState->GetPosition();
2795  sfg->PosVariance = pidState->GetPositionVariance();
2796  sfg->Direction = pidState->GetDirection();
2797  sfg->DirVariance = pidState->GetDirectionVariance();
2798  sfg->EDeposit = edep_sum; // Sum of all the node Edep
2799  // Get track properties
2800  // (Set value to -1 if not available)
2801  int contain = TrackingUtils::GetTRealDatumValue(*sfgObject, "Containment", -1);
2802  sfg->ProtonBraggCut = TrackingUtils::GetTRealDatumValue(*sfgObject, "ProtonBraggCut", -1);
2803  sfg->PionBraggCut = TrackingUtils::GetTRealDatumValue(*sfgObject, "PionBraggCut", -1);
2804  sfg->NegPionBraggCut = TrackingUtils::GetTRealDatumValue(*sfgObject, "NegPionBraggCut", -1);
2805 
2806  // Fill PID weights for each hypothesis
2807  std::vector<int> ParticleIds;
2808  std::vector<double> PIDWeights;
2809  // Loop over all PID alternates
2810  // For SFG all PID hypothesis are saved in alternates
2811  ND::TReconObjectContainer::const_iterator it;
2812  for(it = sfgPID->GetAlternates().begin();
2813  it != sfgPID->GetAlternates().end(); it++){
2814  ND::THandle<ND::TReconPID> alter = *it;
2815  if(contain == 1){ // SFG contained
2816  if(alter->GetParticleId() == ND::TReconPID::kProton){
2817  ParticleIds.push_back(2212);
2818  PIDWeights.push_back(alter->GetPIDWeight());
2819  }
2820  else if(alter->GetParticleId() == ND::TReconPID::kPion){
2821  ParticleIds.push_back(211);
2822  PIDWeights.push_back(alter->GetPIDWeight());
2823  }
2824  else if(alter->GetParticleId() == ND::TReconPID::kMuon){
2825  ParticleIds.push_back(13);
2826  PIDWeights.push_back(alter->GetPIDWeight());
2827  }
2828  else if(alter->GetParticleId() == ND::TReconPID::kEM){
2829  ParticleIds.push_back(11);
2830  PIDWeights.push_back(alter->GetPIDWeight());
2831  }
2832  }
2833  else{ // SFG escaped
2834  if(alter->GetParticleId() == ND::TReconPID::kHeavyTrack){
2835  ParticleIds.push_back(2212);
2836  PIDWeights.push_back(alter->GetPIDWeight());
2837  }
2838  else if(alter->GetParticleId() == ND::TReconPID::kLightTrack){
2839  ParticleIds.push_back(211);
2840  PIDWeights.push_back(alter->GetPIDWeight());
2841  ParticleIds.push_back(13);
2842  PIDWeights.push_back(alter->GetPIDWeight());
2843  }
2844  else if(alter->GetParticleId() == ND::TReconPID::kEM){
2845  ParticleIds.push_back(11);
2846  PIDWeights.push_back(alter->GetPIDWeight());
2847  }
2848  }
2849  } // End of PID alternates loop
2850  // Save PID weights for different hypothesis
2851  for(unsigned int hypo = 0; hypo < ParticleIds.size(); hypo++){
2852  if(ParticleIds[hypo] == 2212)
2853  sfg->PIDWeightProt = PIDWeights[hypo];
2854  else if(ParticleIds[hypo] == 211)
2855  sfg->PIDWeightPion = PIDWeights[hypo];
2856  else if(ParticleIds[hypo] == 13)
2857  sfg->PIDWeightMuon = PIDWeights[hypo];
2858  else if(ParticleIds[hypo] == 11)
2859  sfg->PIDWeightElec = PIDWeights[hypo];
2860  }
2861  }else if(sfgTrack){
2862  sfg->Type = 1; // track
2863  // If the object is TReconTrack, fill position/direction/EDeposit.
2864  ND::THandle<ND::TTrackState> trackState = sfgTrack->GetState();
2865  sfg->Position = trackState->GetPosition();
2866  sfg->PosVariance = trackState->GetPositionVariance();
2867  sfg->Direction = trackState->GetDirection();
2868  sfg->DirVariance = trackState->GetDirectionVariance();
2869  sfg->EDeposit = trackState->GetEDeposit();
2870  }else if(sfgCluster){
2871  sfg->Type = 2; // cluster
2872  // If the object is TReconCluster, fill position/direction/EDeposit.
2873  sfg->Position = sfgCluster->GetPosition();
2874  sfg->PosVariance = sfgCluster->GetPositionVariance();
2875  sfg->EDeposit = sfgCluster->GetEDeposit();
2876  }
2877  // fill average hit time
2878  ND::THandle<ND::TRealDatum> sfgTimeRD =
2879  sfgObject->Get<ND::TRealDatum>("averageHitTime");
2880  if (sfgTimeRD) {
2881  sfg->avgtime = sfgTimeRD->GetValue();
2882  } else {
2883  sfg->avgtime = DEFAULT_MAX;
2884  }
2885  }
2886  } // loop through SFG costituents
2887  } while (false); // always stops...
2888 }
2889 
2890 
2891 //*************************************************************
2892 void ND::TGlobalReconModule::FillSFGOther(ND::TND280Event& event)
2893 {
2894 //*************************************************************
2895 
2896  // Get the main result to save.
2897  ND::THandle<ND::TAlgorithmResult> sfgRecon = event.GetFit("sfgRecon");
2898  if (!sfgRecon) return;
2899  // Get the results from reconstruction
2900  ND::THandle<ND::TReconObjectContainer>
2901  sfgObjects = sfgRecon->GetResultsContainer("final");
2902  if (!sfgObjects) return;
2903 
2904  // Loop over all the objects and save clusters and vertices.
2905  ND::TReconObjectContainer::iterator it;
2906  for (it = sfgObjects->begin();
2907  it != sfgObjects->end(); it++){
2908  ND::THandle<ND::TReconBase> object = *it;
2909  if (!object) continue;
2910  ND::THandle<ND::TReconCluster> cluster = object;
2911  ND::THandle<ND::TReconVertex> vertex = object;
2912  if(!cluster && ! vertex) continue;
2913  if(cluster){
2914  // Fill the cluster as GlobalPID
2915  // Get the compact detector number and number of used detectors
2916  object->AddDetector(ND::TReconBase::kSFG);
2917  unsigned long dets = GetDetectorNumber(object);
2918  int det_count = CountDetector(object);
2919  if (object->UsesDetector(ND::TReconBase::kSFG)){
2920  fNSFG++;
2921  if (det_count == 1) fNSFGIso++;
2922  }
2923  // Try to get the state of the object.
2924  // If it dosen't exists skip the object.
2925  try
2926  {
2927  ND::THandle<ND::TReconState> tstate = object->GetState();
2928  } catch (ND::EReconObject const& e)
2929  {
2930  std::cout << "TReconBase with no state. Skip object !!" << std::endl;
2931  return;
2932  }
2933  // Fill the map of indexes used for vertex link
2934  fGlobalIndexMap[object] = fNPIDs;
2935  // create a new TGlobalPID
2936  TGlobalPID* globalObject = new ((*fPIDs)[fNPIDs++]) TGlobalPID;
2937  // the unique ID of the global object
2938  globalObject->UniqueID = object->GetUniqueID();
2939  // Fill the vector of unique IDs of associated tracks
2940  if (fBrokenIndexMap.find(object) != fBrokenIndexMap.end())
2941  globalObject->BrokenUniqueIDs = fBrokenIndexMap[object];
2942  // Information about the detectors that used in this object
2943  globalObject->Detectors = dets;
2944  FillDetectorUsed(object, globalObject->DetectorUsed);
2945  globalObject->Charge = TrackingUtils::GetCharge(object);
2946  globalObject->EDeposit = TrackingUtils::GetEDeposit(object);
2947  globalObject->Length = ComputeTrackLength(object);
2948  globalObject->Status = object->CheckStatus(object->kSuccess);
2949  globalObject->Chi2 = object->GetQuality();
2950  globalObject->NDOF = object->GetNDOF();
2951  globalObject->NNodes = 0;
2952  globalObject->AlgorithmName = object->GetAlgorithmName();
2953  globalObject->NHits = DEFAULT_MAX;
2954  if (object->GetHits())
2955  globalObject->NHits = object->GetHits()->size();
2956  globalObject->NConstituents = 0;
2957  //---------- Fill info about first and last hits
2958  if (object->GetHits()){
2959 #ifdef FILL_ALL_GLOBAL_HITS
2960  FillAllHits(*(object->GetHits()), *globalObject);
2961 #else
2962  FillFirstLastHits(*(object->GetHits()), *globalObject);
2963 #endif
2964  }
2965  // Fill SFG Info
2966  TSFGObject* sfg =
2967  new ((*(globalObject->SFG))[globalObject->NSFGs++]) TSFGObject;
2968  sfg->Type = 2; // cluster
2969  // Fill information of individual SFG hits
2970  sfg->NHits = 0;
2971  ND::THandle<ND::THitSelection> tbHits = object->GetHits();
2972  if (tbHits) {
2973  for (ND::THitSelection::iterator hit = tbHits->begin();
2974  hit != tbHits->end(); hit++) {
2975  // Fill the information about individual SFG hit
2976  TVector3 pos = (*hit)->GetPosition();
2977  TLorentzVector hitpos = TLorentzVector(
2978  pos[0],pos[1],pos[2],(*hit)->GetTime());
2979  sfg->HitPosition.push_back(hitpos);
2980  sfg->HitCharge .push_back((*hit)->GetCharge());
2981  ND::THitSelection thisHit;
2982  thisHit.push_back(*hit);
2983  sfg->HitTrajID.push_back(
2984  TrackTruthInfo::GetG4TrajIDHits(thisHit));
2985  ++sfg->NHits;
2986  } // End loop over hits
2987  } // Finished filling information on individual SFG hits
2988  ND::THandle<ND::TReconCluster> sfgCluster = object;
2989  if(sfgCluster){
2990  sfg->Position = sfgCluster->GetPosition();
2991  sfg->PosVariance = sfgCluster->GetPositionVariance();
2992  sfg->EDeposit = sfgCluster->GetEDeposit();
2993  }
2994  // fill general information
2995  // (for SFG, detector index should always be = 1)
2996  FillSubBaseObject(object, *sfg, 1 );
2997  // fill average hit time
2998  ND::THandle<ND::TRealDatum> sfgTimeRD =
2999  object->Get<ND::TRealDatum>("averageHitTime");
3000  if (sfgTimeRD) {
3001  sfg->avgtime = sfgTimeRD->GetValue();
3002  } else {
3003  sfg->avgtime = DEFAULT_MAX;
3004  }
3005  // This is not the ideal way to save the cluster position, but
3006  // is necessary to identify the bunch number.
3007  globalObject->FrontPosition = sfg->Position;
3008  globalObject->BackPosition = sfg->Position;
3009  }else if(vertex){
3010  ////////////////////////////////////////////////////////////////
3011  // Check that the vertex has a state
3012  ND::THandle<ND::TVertexState> vstate = vertex->GetState();
3013  if (!vstate) continue;
3014  // Create a global vertex
3015  TGlobalVertex* gVertex = new ((*fVertices)[fNVertices++]) TGlobalVertex;
3016  gVertex->Type = 1; // label as SFG vertex
3017  gVertex->NTrueVertices = 0;
3018  // Index of last added primary
3019  fPVInd = fNVertices - 1;
3020  gVertex->PrimaryIndex = -1;
3021  // Basic info
3022  gVertex->Position = vstate->GetPosition();
3023  gVertex->Variance = vstate->GetPositionVariance();
3024  gVertex->AlgorithmName = vertex->GetAlgorithmName();
3025  gVertex->Status = vertex->GetStatus();
3026  gVertex->Quality = vertex->GetQuality();
3027  gVertex->NDOF = vertex->GetNDOF();
3028  // Associated tracks
3029  ND::THandle<ND::TReconObjectContainer> tracksAssociated
3030  = vertex->GetConstituents();
3031  if (tracksAssociated->size() == 0) continue;
3032  std::map<ND::THandle<ND::TReconBase>,
3033  ND::THandle<ND::TReconObjectContainer>>::iterator cit;
3034  // Loop over associated tracks
3035  ND::TReconObjectContainer::iterator assocIter;
3036  for (assocIter = tracksAssociated->begin();
3037  assocIter != tracksAssociated->end(); assocIter++){
3038  // Skip vertex constituents
3039  if (ND::THandle<ND::TReconVertex> vtxDummy = (*assocIter)) continue;
3040  // Fill track info
3041  if (gVertex->NConstituents == NCONSTITUENTS) break;
3042  ND::THandle<ND::TReconBase> track = *assocIter;
3043  if (!track) continue;
3044  ND::THandle<ND::TReconState> frontState, backState;
3045  ND::tman().GetFirstAndLastStates(track, frontState, backState);
3046  if (!frontState || !backState) continue;
3047  TLorentzVector fpos = TrackingUtils::GetPosition(frontState);
3048  TLorentzVector bpos = TrackingUtils::GetPosition(backState);
3049  // Get index of the global track in the overall fPIDs list
3050  bool inMap = false;
3051  std::map<ND::THandle<ND::TReconBase>, int>::iterator mapIt;
3052  for (mapIt=fGlobalIndexMap.begin();mapIt!=fGlobalIndexMap.end();mapIt++){
3053  if (!mapIt->first) continue;
3054  // It should have SFG segment.
3055  ND::TReconBase::Status det = ND::TReconBase::kSFG;
3056  if(!((mapIt->first)->UsesDetector(det))) continue;
3057  ND::THandle<ND::TReconBase> sfgSeg =
3058  ReconObjectUtils::GetConstituentInDetector(mapIt->first, det);
3059  ND::THandle<ND::TReconState> frontTemp, backTemp;
3060  ND::tman().GetFirstAndLastStates(sfgSeg, frontTemp, backTemp);
3061  if (!frontTemp || !backTemp) continue;
3062  TLorentzVector fpos_tmp = TrackingUtils::GetPosition(frontTemp);
3063  TLorentzVector bpos_tmp = TrackingUtils::GetPosition(backTemp);
3064  // Compare the front and back position
3065  if((fpos.Vect()==fpos_tmp.Vect() && bpos.Vect()==bpos_tmp.Vect()) ||
3066  (fpos.Vect()==bpos_tmp.Vect() && bpos.Vect()==fpos_tmp.Vect())){
3067  inMap = true; break;
3068  }
3069  }
3070  if(!inMap) continue;
3071  // Set PID
3072  int GlobalPIDIndex = mapIt->second;
3073  // Fill constituent track info.
3074  TVertexConstituent* vConst =
3075  new ((*(gVertex->Constituents))[gVertex->NConstituents++])
3077  vConst->Charge = (int)TrackingUtils::GetCharge(track);
3078  vConst->Quality = track->GetQuality();
3079  double mom = TrackingUtils::GetMomentum(frontState);
3080  TVector3 mdir = TrackingUtils::GetDirection(frontState);
3081  mdir *= mom;
3082  vConst->Momentum = mdir;
3083  vConst->PID = GlobalPIDIndex;
3084  } // loop over associated tracks
3085  }
3086  }
3087 }
3088 
3089 //*************************************************************
3090 void ND::TGlobalReconModule::FillFGDInfo(ND::THandle<ND::TReconBase> object,
3091  TGlobalPID& globalObject)
3092 {
3093  //*************************************************************
3094 
3095  // Get the tracker recon version of the this object, if it is a FGD
3096  // iso-recon
3097  // object.
3098  // The global recon version of the object lacks the PID information.
3099  ND::THandle<ND::TReconBase> newFgdIso =
3101  if (newFgdIso) {
3102  object = newFgdIso;
3103  }
3104 
3105  ND::TReconBase::Status dets[2] = {ND::TReconBase::kFGD1,
3107 
3108  for (int i = 0; i < 2; i++) {
3109  if (!object->UsesDetector(dets[i])) continue;
3110 
3111  ND::TReconObjectContainer fgdObjects;
3112 
3113  // for curving-back tracks allow using two constituents in one FGD
3114  if (TrackingUtils::GetCurvBackTrack(*object)) {
3115  fgdObjects =
3116  ReconObjectUtils::GetAllConstituentsInDetector(object, dets[i]);
3117  } else {
3118  //!!! WHICH FGD CONSTITUENT ONE WANTS TO USE FOR THE THROUGH(FGD)-GOING
3119  //! TRACKS?
3120  ND::THandle<ND::TReconBase> fgdConst =
3121  ReconObjectUtils::GetConstituentInDetector(object, dets[i]);
3122  if (fgdConst) fgdObjects.push_back(fgdConst);
3123  }
3124 
3125  if (fgdObjects.size() == 0) continue;
3126 
3127  for (ND::TReconObjectContainer::iterator iter = fgdObjects.begin();
3128  iter != fgdObjects.end(); iter++) {
3129  ND::THandle<ND::TReconBase> fgdObject = *iter;
3130 
3131  if (fgdObject && globalObject.NFGDs < NMAXFGD) {
3132  TFGDObject* fgd =
3133  new ((*(globalObject.FGD))[globalObject.NFGDs++]) TFGDObject;
3134 
3135  // Fill information on individual FGD hits
3136  ND::THandle<ND::THitSelection> tbHits = fgdObject->GetHits();
3137  if (tbHits) {
3138  for (ND::THitSelection::iterator hit = tbHits->begin();
3139  hit != tbHits->end(); hit++) {
3140  // Fill the information about individual FGD hit
3141  TVector3 pos = (*hit)->GetPosition();
3142  int layer = ND::TGeomInfo::FGD().ActivePlane(pos.Z());
3143  fgd->fgdhits_Layer.push_back(layer);
3144  fgd->fgdhits_Position.push_back(pos);
3145  fgd->fgdhits_Time.push_back((*hit)->GetTime());
3146  fgd->fgdhits_Charge.push_back((*hit)->GetCharge());
3147  ND::THitSelection thisHit;
3148  thisHit.push_back(*hit);
3149  fgd->fgdhits_TrajID.push_back(
3150  TrackTruthInfo::GetG4TrajIDHits(thisHit));
3151 
3152  } // End loop over hits
3153  }
3154  // Finished filling information on individual FGD hits
3155 
3156  // Fill node information
3157  fgd->NodePosition.clear();
3158  fgd->NodeEDeposit.clear();
3159 
3160  const ND::TReconNodeContainer& nodeCont = fgdObject->GetNodes();
3161  ND::TReconNodeContainer::const_iterator it_node;
3162  for(it_node = nodeCont.begin(); it_node != nodeCont.end(); ++it_node){
3163 
3164  if(!(*it_node)) continue;
3165 
3166  // Variables to fill node information
3167  TLorentzVector pos_temp(-999,-999,-999,-999);
3168  double edepo_temp = -999;
3169 
3170  const ND::THandle<ND::TReconNode> node = *it_node;
3171  // Get the node state
3172  ND::THandle<ND::TReconState> node_state = node->GetState();
3173  if(node_state){
3174  // Retrieve the position
3175  pos_temp = ND::TReconStateUtilities::GetPosition(node_state);
3176  }
3177  // Get object from node
3178  ND::THandle<ND::TReconBase> node_object = node->GetObject();
3179  if(node_object){
3180  ND::THandle<ND::TReconState> object_state = node_object->GetState();
3181  if(object_state){
3182  edepo_temp = ND::TPIDState::GetStateEDeposit(object_state);
3183  }
3184  }
3185  // (If energy deposition can't get from object->state, then from state)
3186  if(edepo_temp < 0){
3187  if(node_state){
3188  edepo_temp = node_state->GetValue(node_state->GetEDepositIndex());
3189  }
3190  }
3191 
3192  fgd->NodePosition.push_back(pos_temp);
3193  fgd->NodeEDeposit.push_back(edepo_temp);
3194 
3195  } // End of node loop
3196 
3197  // fill general information
3198  FillSubBaseObject(fgdObject, *fgd, i + 1);
3199 
3200  // fill average hit time
3201  ND::THandle<ND::TRealDatum> fgdTimeRD =
3202  fgdObject->Get<ND::TRealDatum>("averageHitTime");
3203  if (fgdTimeRD) {
3204  fgd->avgtime = fgdTimeRD->GetValue();
3205  } else {
3206  fgd->avgtime = DEFAULT_MAX;
3207  }
3208 
3209  // Fill true energy deposit
3210  fgd->TrueE = -999.;
3211  ND::THandle<ND::TReconPID> pid = fgdObject;
3212  ND::THandle<ND::TReconTrack> track = fgdObject;
3213  if (pid){
3214  fgd->TrueE = pidUtils::GetTruthEDep(pid);
3215  }
3216  else if (track){
3217  fgd->TrueE = pidUtils::GetTruthEDep(track);
3218  }
3219 
3220 
3221  // Fill charge per layer information
3222  for (int ilayer = 0; ilayer < 30; ilayer++) {
3223  fgd->chargePerLayer[ilayer] = 0.;
3224  fgd->chargePerLayerAttenCorr[ilayer] = 0.;
3225  }
3226  std::map<int, double> chargeMap;
3227  if (fgdUtils::GetChargeByLayers(fgdObject->GetHits(), chargeMap)) {
3228  for (std::map<int, double>::iterator it = chargeMap.begin();
3229  it != chargeMap.end(); it++) {
3230  int layer = (*it).first;
3231  if (i == 1) {
3232  layer -= 30;
3233  }
3234  fgd->chargePerLayer[layer] = (*it).second;
3235  }
3236  }
3237  std::map<int, double> chargeMapAC;
3238  if (fgdUtils::GetFibreCorrectedChargeByLayersReconFit(
3239  fgdObject->GetHits(), fgdObject, chargeMapAC)) {
3240  for (std::map<int, double>::iterator it = chargeMapAC.begin();
3241  it != chargeMapAC.end(); it++) {
3242  int layer = (*it).first;
3243  if (i == 1) {
3244  layer -= 30;
3245  }
3246  fgd->chargePerLayerAttenCorr[layer] = (*it).second;
3247  }
3248  }
3249  // fill PID Information
3250 
3251  // fully contained info
3252  ND::THandle<ND::TIntegerDatum> RD_geomFC =
3253  fgdObject->Get<ND::TIntegerDatum>("fgdPidPar_geomFC");
3254  fgd->fgdContainment = 0;
3255  if (RD_geomFC) {
3256  fgd->fgdContainment = RD_geomFC->GetValue();
3257  }
3258 
3259  // measured E and x
3260  ND::THandle<ND::TRealDatum> RD_fgdPidPar_E =
3261  fgdObject->Get<ND::TRealDatum>("fgdPidPar_E");
3262  fgd->E = -1.;
3263  if (RD_fgdPidPar_E) {
3264  fgd->E = RD_fgdPidPar_E->GetValue();
3265  }
3266  ND::THandle<ND::TRealDatum> RD_fgdPidPar_x =
3267  fgdObject->Get<ND::TRealDatum>("fgdPidPar_x");
3268  fgd->x = -1.;
3269  if (RD_fgdPidPar_x) {
3270  fgd->x = RD_fgdPidPar_x->GetValue();
3271  }
3272 
3273  // expected E at the measured x
3274  ND::THandle<ND::TRealDatum> RD_fgdPidPar_E_exp_EvsXPull_Muon =
3275  fgdObject->Get<ND::TRealDatum>("fgdPidPar_E_exp_EvsXPull_Muon");
3276  fgd->E_exp_muon = -1.;
3277  if (RD_fgdPidPar_E_exp_EvsXPull_Muon) {
3278  fgd->E_exp_muon = RD_fgdPidPar_E_exp_EvsXPull_Muon->GetValue();
3279  }
3280  ND::THandle<ND::TRealDatum> RD_fgdPidPar_E_exp_EvsXPull_Pion =
3281  fgdObject->Get<ND::TRealDatum>("fgdPidPar_E_exp_EvsXPull_Pion");
3282  fgd->E_exp_pion = -1.;
3283  if (RD_fgdPidPar_E_exp_EvsXPull_Pion) {
3284  fgd->E_exp_pion = RD_fgdPidPar_E_exp_EvsXPull_Pion->GetValue();
3285  }
3286  ND::THandle<ND::TRealDatum> RD_fgdPidPar_E_exp_EvsXPull_Proton =
3287  fgdObject->Get<ND::TRealDatum>("fgdPidPar_E_exp_EvsXPull_Proton");
3288  fgd->E_exp_proton = -1.;
3289  if (RD_fgdPidPar_E_exp_EvsXPull_Proton) {
3290  fgd->E_exp_proton = RD_fgdPidPar_E_exp_EvsXPull_Proton->GetValue();
3291  }
3292  ND::THandle<ND::TRealDatum> RD_fgdPidPar_E_exp_EvsXPull_Electron =
3293  fgdObject->Get<ND::TRealDatum>("fgdPidPar_E_exp_EvsXPull_Electron");
3294  fgd->E_exp_electron = -1.;
3295  if (RD_fgdPidPar_E_exp_EvsXPull_Electron) {
3296  fgd->E_exp_electron =
3297  RD_fgdPidPar_E_exp_EvsXPull_Electron->GetValue();
3298  }
3299 
3300  // sigma E at the measured x
3301  ND::THandle<ND::TRealDatum> RD_fgdPidPar_error_EvsXPull_Muon =
3302  fgdObject->Get<ND::TRealDatum>("fgdPidPar_error_EvsXPull_Muon");
3303  fgd->sigmaE_muon = -1.;
3304  if (RD_fgdPidPar_error_EvsXPull_Muon) {
3305  fgd->sigmaE_muon = RD_fgdPidPar_error_EvsXPull_Muon->GetValue();
3306  }
3307  ND::THandle<ND::TRealDatum> RD_fgdPidPar_error_EvsXPull_Pion =
3308  fgdObject->Get<ND::TRealDatum>("fgdPidPar_error_EvsXPull_Pion");
3309  fgd->sigmaE_pion = -1.;
3310  if (RD_fgdPidPar_error_EvsXPull_Pion) {
3311  fgd->sigmaE_pion = RD_fgdPidPar_error_EvsXPull_Pion->GetValue();
3312  }
3313  ND::THandle<ND::TRealDatum> RD_fgdPidPar_error_EvsXPull_Proton =
3314  fgdObject->Get<ND::TRealDatum>("fgdPidPar_error_EvsXPull_Proton");
3315  fgd->sigmaE_proton = -1.;
3316  if (RD_fgdPidPar_error_EvsXPull_Proton) {
3317  fgd->sigmaE_proton = RD_fgdPidPar_error_EvsXPull_Proton->GetValue();
3318  }
3319  ND::THandle<ND::TRealDatum> RD_fgdPidPar_error_EvsXPull_Electron =
3320  fgdObject->Get<ND::TRealDatum>("fgdPidPar_error_EvsXPull_Electron");
3321  fgd->sigmaE_electron = -1.;
3322  if (RD_fgdPidPar_error_EvsXPull_Electron) {
3323  fgd->sigmaE_electron =
3324  RD_fgdPidPar_error_EvsXPull_Electron->GetValue();
3325  }
3326 
3327  // Pull values
3328  ND::THandle<ND::TRealDatum> RD_fgdPidWgt_EvsXPull_Muon =
3329  fgdObject->Get<ND::TRealDatum>("fgdPidWgt_EvsXPull_Muon");
3330  fgd->PullMuon = -1.e10;
3331  if (RD_fgdPidWgt_EvsXPull_Muon) {
3332  fgd->PullMuon = RD_fgdPidWgt_EvsXPull_Muon->GetValue();
3333  }
3334  ND::THandle<ND::TRealDatum> RD_fgdPidWgt_EvsXPull_Pion =
3335  fgdObject->Get<ND::TRealDatum>("fgdPidWgt_EvsXPull_Pion");
3336  fgd->PullPion = -1.e10;
3337  if (RD_fgdPidWgt_EvsXPull_Pion) {
3338  fgd->PullPion = RD_fgdPidWgt_EvsXPull_Pion->GetValue();
3339  }
3340  ND::THandle<ND::TRealDatum> RD_fgdPidWgt_EvsXPull_Proton =
3341  fgdObject->Get<ND::TRealDatum>("fgdPidWgt_EvsXPull_Proton");
3342  fgd->PullProton = -1.e10;
3343  if (RD_fgdPidWgt_EvsXPull_Proton) {
3344  fgd->PullProton = RD_fgdPidWgt_EvsXPull_Proton->GetValue();
3345  }
3346  ND::THandle<ND::TRealDatum> RD_fgdPidWgt_EvsXPull_Electron =
3347  fgdObject->Get<ND::TRealDatum>("fgdPidWgt_EvsXPull_Electron");
3348  fgd->PullElectron = -1.e10;
3349  if (RD_fgdPidWgt_EvsXPull_Electron) {
3350  fgd->PullElectron = RD_fgdPidWgt_EvsXPull_Electron->GetValue();
3351  }
3352  ND::THandle<ND::TRealDatum> RD_fgdPidWgt_EvsXPull_NotSet =
3353  fgdObject->Get<ND::TRealDatum>("fgdPidWgt_EvsXPull_NotSet");
3354  fgd->PullNotSet = -1.e10;
3355  if (RD_fgdPidWgt_EvsXPull_NotSet) {
3356  fgd->PullNotSet = RD_fgdPidWgt_EvsXPull_NotSet->GetValue();
3357  }
3358 
3359  int fgdNum;
3360  // FGD1 VA/EA variables
3361  // -------------------------
3362  if (i == 0) {
3363  // Vertex activity values
3364  int fgdNum = 2;
3365  ND::THandle<ND::TRealDatum> RD_fgdVA_FgdN;
3366  RD_fgdVA_FgdN = object->Get<ND::TRealDatum>("fgdVA_FgdN");
3367  if (RD_fgdVA_FgdN) {
3368  fgdNum = int(RD_fgdVA_FgdN->GetValue());
3369  }
3370 
3371  fgd->isFgdVA = 0;
3372  if (fgdNum == i) fgd->isFgdVA = 1;
3373 
3374  ND::THandle<ND::TRealDatum> RD_fgdVA_flag;
3375  RD_fgdVA_flag = object->Get<ND::TRealDatum>("fgdVA_flag");
3376  if (RD_fgdVA_flag && i == fgdNum) {
3377  fgd->isFgdVA_flag = int(RD_fgdVA_flag->GetValue());
3378  } else
3379  fgd->isFgdVA_flag = 0;
3380 
3381  ND::THandle<ND::TRealDatum> RD_globpassVA_flag;
3382  RD_globpassVA_flag = object->Get<ND::TRealDatum>("globpassVA_flag");
3383  if (RD_globpassVA_flag && i == fgdNum) {
3384  fgd->globpassVA_flag = int(RD_globpassVA_flag->GetValue());
3385  } else
3386  fgd->globpassVA_flag = 0;
3387 
3388  ND::THandle<ND::TRealDatum> RD_fgdVA_upMinZ;
3389  RD_fgdVA_upMinZ = object->Get<ND::TRealDatum>("fgdVA_upMinZ");
3390  if (RD_fgdVA_upMinZ && i == fgdNum) {
3391  fgd->fgdVA_upMinZ = RD_fgdVA_upMinZ->GetValue();
3392  } else
3393  fgd->fgdVA_upMinZ = 0;
3394 
3395  ND::THandle<ND::TRealDatum> RD_fgdVA_downMaxZ;
3396  RD_fgdVA_downMaxZ = object->Get<ND::TRealDatum>("fgdVA_downMaxZ");
3397  if (RD_fgdVA_downMaxZ && i == fgdNum) {
3398  fgd->fgdVA_downMaxZ = RD_fgdVA_downMaxZ->GetValue();
3399  } else
3400  fgd->fgdVA_downMaxZ = 0;
3401 
3402  ND::THandle<ND::TRealDatum> RD_fgdVA_upCosTheta;
3403  RD_fgdVA_upCosTheta = object->Get<ND::TRealDatum>("fgdVA_upCosTheta");
3404  if (RD_fgdVA_upCosTheta && i == fgdNum) {
3405  fgd->fgdVA_upCosTheta = RD_fgdVA_upCosTheta->GetValue();
3406  } else
3407  fgd->fgdVA_upCosTheta = 0;
3408 
3409  ND::THandle<ND::TRealDatum> RD_fgdVA_downCosTheta;
3410  RD_fgdVA_downCosTheta =
3411  object->Get<ND::TRealDatum>("fgdVA_downCosTheta");
3412  if (RD_fgdVA_downCosTheta && i == fgdNum) {
3413  fgd->fgdVA_downCosTheta = RD_fgdVA_downCosTheta->GetValue();
3414  } else
3415  fgd->fgdVA_downCosTheta = 0;
3416 
3417  ND::THandle<ND::TRealDatum> RD_fgdVA_otherUpQ;
3418  RD_fgdVA_otherUpQ = object->Get<ND::TRealDatum>("fgdVA_otherUpQ");
3419  if (RD_fgdVA_otherUpQ && i == fgdNum) {
3420  fgd->fgdVA_otherUpQ = RD_fgdVA_otherUpQ->GetValue();
3421  } else
3422  fgd->fgdVA_otherUpQ = 0;
3423 
3424  ND::THandle<ND::TRealDatum> RD_fgdVA_otherDownQ;
3425  RD_fgdVA_otherDownQ = object->Get<ND::TRealDatum>("fgdVA_otherDownQ");
3426  if (RD_fgdVA_otherDownQ && i == fgdNum) {
3427  fgd->fgdVA_otherDownQ = RD_fgdVA_otherDownQ->GetValue();
3428  } else
3429  fgd->fgdVA_otherDownQ = 0;
3430 
3431  ND::THandle<ND::TRealDatum> RD_fgdVA_verQ;
3432  RD_fgdVA_verQ = object->Get<ND::TRealDatum>("fgdVA_verQ");
3433  if (RD_fgdVA_verQ && i == fgdNum) {
3434  fgd->fgdVA_verQ = RD_fgdVA_verQ->GetValue();
3435  } else
3436  fgd->fgdVA_verQ = 0;
3437 
3438  ND::THandle<ND::TRealDatum> RD_fgdVA_verLayQ;
3439  RD_fgdVA_verLayQ = object->Get<ND::TRealDatum>("fgdVA_verLayQ");
3440  if (RD_fgdVA_verLayQ && i == fgdNum) {
3441  fgd->fgdVA_verLayQ = RD_fgdVA_verLayQ->GetValue();
3442  } else
3443  fgd->fgdVA_verLayQ = 0;
3444 
3445  ND::THandle<ND::TRealDatum> RD_fgdVA_verNearQ;
3446  RD_fgdVA_verNearQ = object->Get<ND::TRealDatum>("fgdVA_verNearQ");
3447  if (RD_fgdVA_verNearQ && i == fgdNum) {
3448  fgd->fgdVA_verNearQ = RD_fgdVA_verNearQ->GetValue();
3449  } else
3450  fgd->fgdVA_verNearQ = 0;
3451 
3452  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNearQ;
3453  RD_fgdVA_verNextNearQ =
3454  object->Get<ND::TRealDatum>("fgdVA_verNextNearQ");
3455  if (RD_fgdVA_verNextNearQ && i == fgdNum) {
3456  fgd->fgdVA_verNextNearQ = RD_fgdVA_verNextNearQ->GetValue();
3457  } else
3458  fgd->fgdVA_verNextNearQ = 0;
3459 
3460  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNextNearQ;
3461  RD_fgdVA_verNextNextNearQ =
3462  object->Get<ND::TRealDatum>("fgdVA_verNextNextNearQ");
3463  if (RD_fgdVA_verNextNextNearQ && i == fgdNum) {
3464  fgd->fgdVA_verNextNextNearQ = RD_fgdVA_verNextNextNearQ->GetValue();
3465  } else
3466  fgd->fgdVA_verNextNextNearQ = 0;
3467 
3468  ND::THandle<ND::TRealDatum> RD_fgdVA_totalQ;
3469  RD_fgdVA_totalQ = object->Get<ND::TRealDatum>("fgdVA_totalQ");
3470  if (RD_fgdVA_totalQ && i == fgdNum) {
3471  fgd->fgdVA_totalQ = RD_fgdVA_totalQ->GetValue();
3472  } else
3473  fgd->fgdVA_totalQ = 0;
3474 
3475  ND::THandle<ND::TRealDatum> RD_fgdVA_totalCorrE;
3476  RD_fgdVA_totalCorrE = object->Get<ND::TRealDatum>("fgdVA_totalCorrE");
3477  if (RD_fgdVA_totalCorrE && i == fgdNum) {
3478  fgd->fgdVA_totalCorrE = RD_fgdVA_totalCorrE->GetValue();
3479  } else
3480  fgd->fgdVA_totalCorrE = 0;
3481 
3482  // New Vertex Activity for FGD1
3483 
3484  // Vertex Activity in FGD1 2x3
3485  ND::THandle<ND::TRealDatum> RD_fgdVA_verNearQ_rect;
3486  RD_fgdVA_verNearQ_rect =
3487  object->Get<ND::TRealDatum>("fgdVA_verNearQ_rect");
3488  if (RD_fgdVA_verNearQ_rect && i == fgdNum) {
3489  fgd->fgdVA_verNearQ_rect = RD_fgdVA_verNearQ_rect->GetValue();
3490  } else
3491  fgd->fgdVA_verNearQ_rect = 0;
3492 
3493  // Vertex activity in FGD1 2x5
3494  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNearQ_rect;
3495  RD_fgdVA_verNextNearQ_rect =
3496  object->Get<ND::TRealDatum>("fgdVA_verNextNearQ_rect");
3497  if (RD_fgdVA_verNextNearQ_rect && i == fgdNum) {
3499  RD_fgdVA_verNextNearQ_rect->GetValue();
3500  } else
3501  fgd->fgdVA_verNextNearQ_rect = 0;
3502 
3503  // Vertex activity in FGD1 2x7
3504  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNextNearQ_rect;
3505  RD_fgdVA_verNextNextNearQ_rect =
3506  object->Get<ND::TRealDatum>("fgdVA_verNextNextNearQ_rect");
3507  if (RD_fgdVA_verNextNextNearQ_rect && i == fgdNum) {
3509  RD_fgdVA_verNextNextNearQ_rect->GetValue();
3510  } else
3511  fgd->fgdVA_verNextNextNearQ_rect = 0;
3512 
3513  // End Activity values
3514  // ----------------------------
3515  fgdNum = 2;
3516  ND::THandle<ND::TRealDatum> RD_fgdEA_FgdN;
3517  RD_fgdEA_FgdN = object->Get<ND::TRealDatum>("fgdEA_FgdN");
3518  if (RD_fgdEA_FgdN) {
3519  fgdNum = int(RD_fgdEA_FgdN->GetValue());
3520  }
3521 
3522  fgd->isFgdEA = 0;
3523  if (fgdNum == i) fgd->isFgdEA = 1;
3524 
3525  ND::THandle<ND::TRealDatum> RD_fgdEA_flag;
3526  RD_fgdEA_flag = object->Get<ND::TRealDatum>("fgdEA_flag");
3527  if (RD_fgdEA_flag && i == fgdNum) {
3528  fgd->isFgdEA_flag = int(RD_fgdEA_flag->GetValue());
3529  } else
3530  fgd->isFgdEA_flag = 0;
3531 
3532  ND::THandle<ND::TRealDatum> RD_globpassEA_flag;
3533  RD_globpassEA_flag = object->Get<ND::TRealDatum>("globpassEA_flag");
3534  if (RD_globpassEA_flag && i == fgdNum) {
3535  fgd->globpassEA_flag = int(RD_globpassEA_flag->GetValue());
3536  } else
3537  fgd->globpassEA_flag = 0;
3538 
3539  ND::THandle<ND::TRealDatum> RD_fgdEA_otherUpQ;
3540  RD_fgdEA_otherUpQ = object->Get<ND::TRealDatum>("fgdEA_otherUpQ");
3541  if (RD_fgdEA_otherUpQ && i == fgdNum) {
3542  fgd->fgdEA_otherUpQ = RD_fgdEA_otherUpQ->GetValue();
3543  } else
3544  fgd->fgdEA_otherUpQ = 0;
3545 
3546  ND::THandle<ND::TRealDatum> RD_fgdEA_otherDownQ;
3547  RD_fgdEA_otherDownQ = object->Get<ND::TRealDatum>("fgdEA_otherDownQ");
3548  if (RD_fgdEA_otherDownQ && i == fgdNum) {
3549  fgd->fgdEA_otherDownQ = RD_fgdEA_otherDownQ->GetValue();
3550  } else
3551  fgd->fgdEA_otherDownQ = 0;
3552 
3553  ND::THandle<ND::TRealDatum> RD_fgdEA_verQ;
3554  RD_fgdEA_verQ = object->Get<ND::TRealDatum>("fgdEA_verQ");
3555  if (RD_fgdEA_verQ && i == fgdNum) {
3556  fgd->fgdEA_verQ = RD_fgdEA_verQ->GetValue();
3557  } else
3558  fgd->fgdEA_verQ = 0;
3559 
3560  ND::THandle<ND::TRealDatum> RD_fgdEA_verLayQ;
3561  RD_fgdEA_verLayQ = object->Get<ND::TRealDatum>("fgdEA_verLayQ");
3562  if (RD_fgdEA_verLayQ && i == fgdNum) {
3563  fgd->fgdEA_verLayQ = RD_fgdEA_verLayQ->GetValue();
3564  } else
3565  fgd->fgdEA_verLayQ = 0;
3566 
3567  ND::THandle<ND::TRealDatum> RD_fgdEA_verNearQ;
3568  RD_fgdEA_verNearQ = object->Get<ND::TRealDatum>("fgdEA_verNearQ");
3569  if (RD_fgdEA_verNearQ && i == fgdNum) {
3570  fgd->fgdEA_verNearQ = RD_fgdEA_verNearQ->GetValue();
3571  } else
3572  fgd->fgdEA_verNearQ = 0;
3573 
3574  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNearQ;
3575  RD_fgdEA_verNextNearQ =
3576  object->Get<ND::TRealDatum>("fgdEA_verNextNearQ");
3577  if (RD_fgdEA_verNextNearQ && i == fgdNum) {
3578  fgd->fgdEA_verNextNearQ = RD_fgdEA_verNextNearQ->GetValue();
3579  } else
3580  fgd->fgdEA_verNextNearQ = 0;
3581 
3582  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNextNearQ;
3583  RD_fgdEA_verNextNextNearQ =
3584  object->Get<ND::TRealDatum>("fgdEA_verNextNextNearQ");
3585  if (RD_fgdEA_verNextNextNearQ && i == fgdNum) {
3586  fgd->fgdEA_verNextNextNearQ = RD_fgdEA_verNextNextNearQ->GetValue();
3587  } else
3588  fgd->fgdEA_verNextNextNearQ = 0;
3589 
3590  // End Activity in FGD1 2x3
3591  ND::THandle<ND::TRealDatum> RD_fgdEA_verNearQ_rect;
3592  RD_fgdEA_verNearQ_rect =
3593  object->Get<ND::TRealDatum>("fgdEA_verNearQ_rect");
3594  if (RD_fgdEA_verNearQ_rect && i == fgdNum) {
3595  fgd->fgdEA_verNearQ_rect = RD_fgdEA_verNearQ_rect->GetValue();
3596  } else
3597  fgd->fgdEA_verNearQ_rect = 0;
3598 
3599  // End activity in FGD1 2x5
3600  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNearQ_rect;
3601  RD_fgdEA_verNextNearQ_rect =
3602  object->Get<ND::TRealDatum>("fgdEA_verNextNearQ_rect");
3603  if (RD_fgdEA_verNextNearQ_rect && i == fgdNum) {
3605  RD_fgdEA_verNextNearQ_rect->GetValue();
3606  } else
3607  fgd->fgdEA_verNextNearQ_rect = 0;
3608 
3609  // End activity in FGD1 2x7
3610  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNextNearQ_rect;
3611  RD_fgdEA_verNextNextNearQ_rect =
3612  object->Get<ND::TRealDatum>("fgdEA_verNextNextNearQ_rect");
3613  if (RD_fgdEA_verNextNextNearQ_rect && i == fgdNum) {
3615  RD_fgdEA_verNextNextNearQ_rect->GetValue();
3616  } else
3617  fgd->fgdEA_verNextNextNearQ_rect = 0;
3618 
3619  }
3620  //--------------------------------------------------
3621  // FGD2 VA/EA variables
3622  else if (i == 1) {
3623  // Vertex activity values
3624  fgdNum = 2;
3625  ND::THandle<ND::TRealDatum> RD_fgdVA_FgdN_FGD2;
3626  RD_fgdVA_FgdN_FGD2 = object->Get<ND::TRealDatum>("fgdVA_FgdN_FGD2");
3627  if (RD_fgdVA_FgdN_FGD2) {
3628  fgdNum = int(RD_fgdVA_FgdN_FGD2->GetValue());
3629  }
3630 
3631  fgd->isFgdVA = 0;
3632  if (fgdNum == i) fgd->isFgdVA = 1;
3633 
3634  ND::THandle<ND::TRealDatum> RD_fgdVA_flag_FGD2;
3635  RD_fgdVA_flag_FGD2 = object->Get<ND::TRealDatum>("fgdVA_flag_FGD2");
3636  if (RD_fgdVA_flag_FGD2 && i == fgdNum) {
3637  fgd->isFgdVA_flag = int(RD_fgdVA_flag_FGD2->GetValue());
3638  } else
3639  fgd->isFgdVA_flag = 0;
3640 
3641  ND::THandle<ND::TRealDatum> RD_globpassVA_flag_FGD2;
3642  RD_globpassVA_flag_FGD2 =
3643  object->Get<ND::TRealDatum>("globpassVA_flag_FGD2");
3644  if (RD_globpassVA_flag_FGD2 && i == fgdNum) {
3645  fgd->globpassVA_flag = int(RD_globpassVA_flag_FGD2->GetValue());
3646  } else
3647  fgd->globpassVA_flag = 0;
3648 
3649  ND::THandle<ND::TRealDatum> RD_fgdVA_upMinZ_FGD2;
3650  RD_fgdVA_upMinZ_FGD2 =
3651  object->Get<ND::TRealDatum>("fgdVA_upMinZ_FGD2");
3652  if (RD_fgdVA_upMinZ_FGD2 && i == fgdNum) {
3653  fgd->fgdVA_upMinZ = RD_fgdVA_upMinZ_FGD2->GetValue();
3654  } else
3655  fgd->fgdVA_upMinZ = 0;
3656 
3657  ND::THandle<ND::TRealDatum> RD_fgdVA_downMaxZ_FGD2;
3658  RD_fgdVA_downMaxZ_FGD2 =
3659  object->Get<ND::TRealDatum>("fgdVA_downMaxZ_FGD2");
3660  if (RD_fgdVA_downMaxZ_FGD2 && i == fgdNum) {
3661  fgd->fgdVA_downMaxZ = RD_fgdVA_downMaxZ_FGD2->GetValue();
3662  } else
3663  fgd->fgdVA_downMaxZ = 0;
3664 
3665  ND::THandle<ND::TRealDatum> RD_fgdVA_upCosTheta_FGD2;
3666  RD_fgdVA_upCosTheta_FGD2 =
3667  object->Get<ND::TRealDatum>("fgdVA_upCosTheta_FGD2");
3668  if (RD_fgdVA_upCosTheta_FGD2 && i == fgdNum) {
3669  fgd->fgdVA_upCosTheta = RD_fgdVA_upCosTheta_FGD2->GetValue();
3670  } else
3671  fgd->fgdVA_upCosTheta = 0;
3672 
3673  ND::THandle<ND::TRealDatum> RD_fgdVA_downCosTheta_FGD2;
3674  RD_fgdVA_downCosTheta_FGD2 =
3675  object->Get<ND::TRealDatum>("fgdVA_downCosTheta_FGD2");
3676  if (RD_fgdVA_downCosTheta_FGD2 && i == fgdNum) {
3677  fgd->fgdVA_downCosTheta = RD_fgdVA_downCosTheta_FGD2->GetValue();
3678  } else
3679  fgd->fgdVA_downCosTheta = 0;
3680 
3681  ND::THandle<ND::TRealDatum> RD_fgdVA_otherUpQ_FGD2;
3682  RD_fgdVA_otherUpQ_FGD2 =
3683  object->Get<ND::TRealDatum>("fgdVA_otherUpQ_FGD2");
3684  if (RD_fgdVA_otherUpQ_FGD2 && i == fgdNum) {
3685  fgd->fgdVA_otherUpQ = RD_fgdVA_otherUpQ_FGD2->GetValue();
3686  } else
3687  fgd->fgdVA_otherUpQ = 0;
3688 
3689  ND::THandle<ND::TRealDatum> RD_fgdVA_otherDownQ_FGD2;
3690  RD_fgdVA_otherDownQ_FGD2 =
3691  object->Get<ND::TRealDatum>("fgdVA_otherDownQ_FGD2");
3692  if (RD_fgdVA_otherDownQ_FGD2 && i == fgdNum) {
3693  fgd->fgdVA_otherDownQ = RD_fgdVA_otherDownQ_FGD2->GetValue();
3694  } else
3695  fgd->fgdVA_otherDownQ = 0;
3696 
3697  ND::THandle<ND::TRealDatum> RD_fgdVA_verQ_FGD2;
3698  RD_fgdVA_verQ_FGD2 = object->Get<ND::TRealDatum>("fgdVA_verQ_FGD2");
3699  if (RD_fgdVA_verQ_FGD2 && i == fgdNum) {
3700  fgd->fgdVA_verQ = RD_fgdVA_verQ_FGD2->GetValue();
3701  } else
3702  fgd->fgdVA_verQ = 0;
3703 
3704  ND::THandle<ND::TRealDatum> RD_fgdVA_verLayQ_FGD2;
3705  RD_fgdVA_verLayQ_FGD2 =
3706  object->Get<ND::TRealDatum>("fgdVA_verLayQ_FGD2");
3707  if (RD_fgdVA_verLayQ_FGD2 && i == fgdNum) {
3708  fgd->fgdVA_verLayQ = RD_fgdVA_verLayQ_FGD2->GetValue();
3709  } else
3710  fgd->fgdVA_verLayQ = 0;
3711 
3712  ND::THandle<ND::TRealDatum> RD_fgdVA_verNearQ_FGD2;
3713  RD_fgdVA_verNearQ_FGD2 =
3714  object->Get<ND::TRealDatum>("fgdVA_verNearQ_FGD2");
3715  if (RD_fgdVA_verNearQ_FGD2 && i == fgdNum) {
3716  fgd->fgdVA_verNearQ = RD_fgdVA_verNearQ_FGD2->GetValue();
3717  } else
3718  fgd->fgdVA_verNearQ = 0;
3719 
3720  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNearQ_FGD2;
3721  RD_fgdVA_verNextNearQ_FGD2 =
3722  object->Get<ND::TRealDatum>("fgdVA_verNextNearQ_FGD2");
3723  if (RD_fgdVA_verNextNearQ_FGD2 && i == fgdNum) {
3724  fgd->fgdVA_verNextNearQ = RD_fgdVA_verNextNearQ_FGD2->GetValue();
3725  } else
3726  fgd->fgdVA_verNextNearQ = 0;
3727 
3728  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNextNearQ_FGD2;
3729  RD_fgdVA_verNextNextNearQ_FGD2 =
3730  object->Get<ND::TRealDatum>("fgdVA_verNextNextNearQ_FGD2");
3731  if (RD_fgdVA_verNextNextNearQ_FGD2 && i == fgdNum) {
3732  fgd->fgdVA_verNextNextNearQ =
3733  RD_fgdVA_verNextNextNearQ_FGD2->GetValue();
3734  } else
3735  fgd->fgdVA_verNextNextNearQ = 0;
3736 
3737  ND::THandle<ND::TRealDatum> RD_fgdVA_totalQ_FGD2;
3738  RD_fgdVA_totalQ_FGD2 =
3739  object->Get<ND::TRealDatum>("fgdVA_totalQ_FGD2");
3740  if (RD_fgdVA_totalQ_FGD2 && i == fgdNum) {
3741  fgd->fgdVA_totalQ = RD_fgdVA_totalQ_FGD2->GetValue();
3742  } else
3743  fgd->fgdVA_totalQ = 0;
3744 
3745  ND::THandle<ND::TRealDatum> RD_fgdVA_totalCorrE_FGD2;
3746  RD_fgdVA_totalCorrE_FGD2 =
3747  object->Get<ND::TRealDatum>("fgdVA_totalCorrE_FGD2");
3748  if (RD_fgdVA_totalCorrE_FGD2 && i == fgdNum) {
3749  fgd->fgdVA_totalCorrE = RD_fgdVA_totalCorrE_FGD2->GetValue();
3750  } else
3751  fgd->fgdVA_totalCorrE = 0;
3752 
3753  // New Vertex Activity for FGD2 (avoid taking into account the scint
3754  // layers after the water ones)
3755 
3756  // Vertex Activity in FGD2 2x3
3757  ND::THandle<ND::TRealDatum> RD_fgdVA_verNearQ_FGD2_rect;
3758  RD_fgdVA_verNearQ_FGD2_rect =
3759  object->Get<ND::TRealDatum>("fgdVA_verNearQ_FGD2_rect");
3760  if (RD_fgdVA_verNearQ_FGD2_rect && i == fgdNum)
3761  {
3762  fgd->fgdVA_verNearQ_rect = RD_fgdVA_verNearQ_FGD2_rect->GetValue();
3763  } else
3764  fgd->fgdVA_verNearQ_rect = 0;
3765 
3766  // Vertex activity in FGD2 2x5
3767  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNearQ_FGD2_rect;
3768  RD_fgdVA_verNextNearQ_FGD2_rect =
3769  object->Get<ND::TRealDatum>("fgdVA_verNextNearQ_FGD2_rect");
3770  if (RD_fgdVA_verNextNearQ_FGD2_rect && i == fgdNum) {
3772  RD_fgdVA_verNextNearQ_FGD2_rect->GetValue();
3773  } else
3774  fgd->fgdVA_verNextNearQ_rect = 0;
3775 
3776  // Vertex activity in FGD2 2x7
3777  ND::THandle<ND::TRealDatum> RD_fgdVA_verNextNextNearQ_FGD2_rect;
3778  RD_fgdVA_verNextNextNearQ_FGD2_rect =
3779  object->Get<ND::TRealDatum>("fgdVA_verNextNextNearQ_FGD2_rect");
3780  if (RD_fgdVA_verNextNextNearQ_FGD2_rect && i == fgdNum) {
3782  RD_fgdVA_verNextNextNearQ_FGD2_rect->GetValue();
3783  } else
3784  fgd->fgdVA_verNextNextNearQ_rect = 0;
3785 
3786  // End Activity values
3787  // ----------------------------
3788  fgdNum = 2;
3789  ND::THandle<ND::TRealDatum> RD_fgdEA_FgdN_FGD2;
3790  RD_fgdEA_FgdN_FGD2 = object->Get<ND::TRealDatum>("fgdEA_FgdN_FGD2");
3791  if (RD_fgdEA_FgdN_FGD2) {
3792  fgdNum = int(RD_fgdEA_FgdN_FGD2->GetValue());
3793  }
3794 
3795  fgd->isFgdEA = 0;
3796  if (fgdNum == i) fgd->isFgdEA = 1;
3797 
3798  ND::THandle<ND::TRealDatum> RD_fgdEA_flag_FGD2;
3799  RD_fgdEA_flag_FGD2 = object->Get<ND::TRealDatum>("fgdEA_flag_FGD2");
3800  if (RD_fgdEA_flag_FGD2 && i == fgdNum) {
3801  fgd->isFgdEA_flag = int(RD_fgdEA_flag_FGD2->GetValue());
3802  } else
3803  fgd->isFgdEA_flag = 0;
3804 
3805  ND::THandle<ND::TRealDatum> RD_globpassEA_flag_FGD2;
3806  RD_globpassEA_flag_FGD2 =
3807  object->Get<ND::TRealDatum>("globpassEA_flag_FGD2");
3808  if (RD_globpassEA_flag_FGD2 && i == fgdNum) {
3809  fgd->globpassEA_flag = int(RD_globpassEA_flag_FGD2->GetValue());
3810  } else
3811  fgd->globpassEA_flag = 0;
3812 
3813  ND::THandle<ND::TRealDatum> RD_fgdEA_otherUpQ_FGD2;
3814  RD_fgdEA_otherUpQ_FGD2 =
3815  object->Get<ND::TRealDatum>("fgdEA_otherUpQ_FGD2");
3816  if (RD_fgdEA_otherUpQ_FGD2 && i == fgdNum) {
3817  fgd->fgdEA_otherUpQ = RD_fgdEA_otherUpQ_FGD2->GetValue();
3818  } else
3819  fgd->fgdEA_otherUpQ = 0;
3820 
3821  ND::THandle<ND::TRealDatum> RD_fgdEA_otherDownQ_FGD2;
3822  RD_fgdEA_otherDownQ_FGD2 =
3823  object->Get<ND::TRealDatum>("fgdEA_otherDownQ_FGD2");
3824  if (RD_fgdEA_otherDownQ_FGD2 && i == fgdNum) {
3825  fgd->fgdEA_otherDownQ = RD_fgdEA_otherDownQ_FGD2->GetValue();
3826  } else
3827  fgd->fgdEA_otherDownQ = 0;
3828 
3829  ND::THandle<ND::TRealDatum> RD_fgdEA_verQ_FGD2;
3830  RD_fgdEA_verQ_FGD2 = object->Get<ND::TRealDatum>("fgdEA_verQ_FGD2");
3831  if (RD_fgdEA_verQ_FGD2 && i == fgdNum) {
3832  fgd->fgdEA_verQ = RD_fgdEA_verQ_FGD2->GetValue();
3833  } else
3834  fgd->fgdEA_verQ = 0;
3835 
3836  ND::THandle<ND::TRealDatum> RD_fgdEA_verLayQ_FGD2;
3837  RD_fgdEA_verLayQ_FGD2 =
3838  object->Get<ND::TRealDatum>("fgdEA_verLayQ_FGD2");
3839  if (RD_fgdEA_verLayQ_FGD2 && i == fgdNum) {
3840  fgd->fgdEA_verLayQ = RD_fgdEA_verLayQ_FGD2->GetValue();
3841  } else
3842  fgd->fgdEA_verLayQ = 0;
3843 
3844  ND::THandle<ND::TRealDatum> RD_fgdEA_verNearQ_FGD2;
3845  RD_fgdEA_verNearQ_FGD2 =
3846  object->Get<ND::TRealDatum>("fgdEA_verNearQ_FGD2");
3847  if (RD_fgdEA_verNearQ_FGD2 && i == fgdNum) {
3848  fgd->fgdEA_verNearQ = RD_fgdEA_verNearQ_FGD2->GetValue();
3849  } else
3850  fgd->fgdEA_verNearQ = 0;
3851 
3852  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNearQ_FGD2;
3853  RD_fgdEA_verNextNearQ_FGD2 =
3854  object->Get<ND::TRealDatum>("fgdEA_verNextNearQ_FGD2");
3855  if (RD_fgdEA_verNextNearQ_FGD2 && i == fgdNum) {
3856  fgd->fgdEA_verNextNearQ = RD_fgdEA_verNextNearQ_FGD2->GetValue();
3857  } else
3858  fgd->fgdEA_verNextNearQ = 0;
3859 
3860  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNextNearQ_FGD2;
3861  RD_fgdEA_verNextNextNearQ_FGD2 =
3862  object->Get<ND::TRealDatum>("fgdEA_verNextNextNearQ_FGD2");
3863  if (RD_fgdEA_verNextNextNearQ_FGD2 && i == fgdNum) {
3864  fgd->fgdEA_verNextNextNearQ =
3865  RD_fgdEA_verNextNextNearQ_FGD2->GetValue();
3866  } else
3867  fgd->fgdEA_verNextNextNearQ = 0;
3868 
3869  // End Activity in FGD2 2x3
3870  ND::THandle<ND::TRealDatum> RD_fgdEA_verNearQ_FGD2_rect;
3871  RD_fgdEA_verNearQ_FGD2_rect =
3872  object->Get<ND::TRealDatum>("fgdEA_verNearQ_FGD2_rect");
3873  if (RD_fgdEA_verNearQ_FGD2_rect && i == fgdNum) {
3874  fgd->fgdEA_verNearQ_rect = RD_fgdEA_verNearQ_FGD2_rect->GetValue();
3875  } else
3876  fgd->fgdEA_verNearQ_rect = 0;
3877 
3878  // End activity in FGD2 2x5
3879  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNearQ_FGD2_rect;
3880  RD_fgdEA_verNextNearQ_FGD2_rect =
3881  object->Get<ND::TRealDatum>("fgdEA_verNextNearQ_FGD2_rect");
3882  if (RD_fgdEA_verNextNearQ_FGD2_rect && i == fgdNum) {
3884  RD_fgdEA_verNextNearQ_FGD2_rect->GetValue();
3885  } else
3886  fgd->fgdEA_verNextNearQ_rect = 0;
3887 
3888  // End activity in FGD2 2x7
3889  ND::THandle<ND::TRealDatum> RD_fgdEA_verNextNextNearQ_FGD2_rect;
3890  RD_fgdEA_verNextNextNearQ_FGD2_rect =
3891  object->Get<ND::TRealDatum>("fgdEA_verNextNextNearQ_FGD2_rect");
3892  if (RD_fgdEA_verNextNextNearQ_FGD2_rect && i == fgdNum) {
3894  RD_fgdEA_verNextNextNearQ_FGD2_rect->GetValue();
3895  } else
3896  fgd->fgdEA_verNextNextNearQ_rect = 0;
3897  }
3898  // -----------------------------------------
3899  }
3900  } // loop through FGD costituents
3901  } // uses particular FGD
3902 }
3903 
3904 //*************************************************************
3905 void ND::TGlobalReconModule::FillP0DInfo(ND::THandle<ND::TReconBase> object,
3906  TGlobalPID& globalObject)
3907 {
3908  //*************************************************************
3909 
3910  if (!object->UsesDetector(ND::TReconBase::kP0D)) return;
3911 
3912  ND::THandle<ND::TReconBase> p0dObject =
3913  ReconObjectUtils::GetConstituentInDetector(object, ND::TReconBase::kP0D);
3914 
3915  if (p0dObject && globalObject.NP0Ds < NMAXP0D) {
3916  TP0DObject* p0d =
3917  new ((*(globalObject.P0D))[globalObject.NP0Ds++]) TP0DObject;
3918 
3919  // fill general information
3920  FillSubBaseObject(p0dObject, *p0d, 1);
3921 
3922  p0d->Cone = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
3923  p0d->Width = DEFAULT_MAX;
3924  p0d->EDeposit = DEFAULT_MAX;
3925 
3926  // fill average node time
3927  ND::THandle<ND::TRealDatum> p0dTimeRD =
3928  p0dObject->Get<ND::TRealDatum>("averageHitTime");
3929  if (p0dTimeRD) {
3930  p0d->avgtime = p0dTimeRD->GetValue();
3931  } else {
3932  p0d->avgtime = DEFAULT_MAX;
3933  }
3934 
3935  // The most likely PID is available through particle->GetParticle,
3936  // but it is also stored as one of the alternates. These are sorted
3937  // in order of PID, so copy them directly into the TTree.
3938  ND::TReconObjectContainer::const_iterator alternate;
3939 
3940  ND::THandle<ND::TReconPID> pid = p0dObject;
3941 
3942  for (alternate = pid->GetAlternates().begin();
3943  alternate != pid->GetAlternates().end(); alternate++) {
3944  ND::THandle<ND::TReconPID> alt = (*alternate);
3945  if (alt) {
3946  p0d->ParticleId.push_back(alt->GetParticleId());
3947  p0d->PIDWeight.push_back(alt->GetPIDWeight());
3948  } else
3949  ND280Warn("TReconPID alternate is not a TReconPID - Ignored");
3950  }
3951 
3952  ND::THandle<ND::TReconObjectContainer> conContainer =
3953  p0dObject->GetConstituents();
3954  if (conContainer) {
3955  // The PID variables are not saved in the main object but in its
3956  // constituent
3957  ND::THandle<ND::TReconBase> p0dObject2 = *(conContainer->begin());
3958  if (p0dObject2) {
3959  // The cone angle is only accesible form the shower object
3960  p0d->Cone = TrackingUtils::GetCone(p0dObject2);
3961  p0d->EDeposit = TrackingUtils::GetEDeposit(p0dObject2);
3962 
3963  if (GetObjectType(p0dObject).find("ND::TReconShower") ==
3964  std::string::npos)
3965  return;
3966 
3967  // Compute the length and the width for showers
3968  ND::THandle<ND::THitSelection> hits = p0dObject2->GetHits();
3969  if (hits) {
3970  double totalCharge = 0.0;
3971  double avgLen = 0.0;
3972  double avgLen2 = 0.0;
3973 
3974  for (ND::THitSelection::iterator h = hits->begin(); h != hits->end();
3975  ++h) {
3976  // Find the width.
3977  TVector3 diff = (*h)->GetPosition() - p0d->FrontPosition.Vect();
3978  TVector3 perp =
3979  diff - (diff * p0d->FrontDirection) * p0d->FrontDirection;
3980  if ((*h)->IsXHit()) {
3981  diff.SetY(0.0);
3982  perp.SetY(0.0);
3983  } else {
3984  diff.SetX(0.0);
3985  perp.SetX(0.0);
3986  }
3987  double q = std::max(3.0, (*h)->GetCharge());
3988  p0d->Width += q * perp.Mag();
3989  double len = diff.Mag();
3990  avgLen += q * len;
3991  avgLen2 += q * len * len;
3992  totalCharge += q;
3993  }
3994  p0d->Width /= std::max(totalCharge, 1.0);
3995  avgLen /= std::max(totalCharge, 1.0);
3996  avgLen2 /= std::max(totalCharge, 1.0);
3997  p0d->Length = avgLen2 - avgLen * avgLen;
3998  p0d->Length = std::sqrt(std::max(0.0, p0d->Length));
3999  }
4000  }
4001  }
4002  }
4003 }
4004 
4005 //*************************************************************
4006 void ND::TGlobalReconModule::FillSMRDInfo(ND::THandle<ND::TReconBase> object,
4007  TGlobalPID& globalObject)
4008 {
4009  //*************************************************************
4010 
4011  ND::TReconBase::Status dets[4] = {
4012  ND::TReconBase::kTopSMRD, ND::TReconBase::kBottomSMRD,
4013  ND::TReconBase::kLeftSMRD, ND::TReconBase::kRightSMRD};
4014 
4015  for (int i = 0; i < 4; i++) {
4016  if (!object->UsesDetector(dets[i])) continue;
4017 
4018  // account for possible >1 segments in one SMRD quadrant
4019  ND::TReconObjectContainer smrdObjects =
4020  ReconObjectUtils::GetAllConstituentsInDetector(object, dets[i]);
4021 
4022  if (smrdObjects.size() == 0) continue;
4023 
4024  for (ND::TReconObjectContainer::iterator iter = smrdObjects.begin();
4025  iter != smrdObjects.end(); iter++) {
4026  ND::THandle<ND::TReconBase> smrdObject = *iter;
4027 
4028  if (smrdObject && globalObject.NSMRDs < NMAXSMRD) {
4029  TSMRDObject* smrd =
4030  new ((*(globalObject.SMRD))[globalObject.NSMRDs++]) TSMRDObject;
4031 
4032  // fill general information
4033  FillSubBaseObject(smrdObject, *smrd, i + 1);
4034 
4035  // explicitly set SMRD EDeposit as a some of the charge of all hits
4036  smrd->EDeposit = DEFAULT_MAX;
4037  ND::THandle<ND::TRealDatum> totalCharge =
4038  smrdObject->Get<ND::TRealDatum>("totalCharge");
4039  if (totalCharge)
4040  smrd->EDeposit =
4041  smrdObject->Get<ND::TRealDatum>("totalCharge")->GetValue();
4042 
4043  // fill average hit time
4044  smrd->avgtime = DEFAULT_MAX;
4045  ND::THandle<ND::TRealDatum> smrdTimeRD =
4046  smrdObject->Get<ND::TRealDatum>("averageHitTime");
4047  if (smrdTimeRD) smrd->avgtime = smrdTimeRD->GetValue();
4048  }
4049  }
4050  }
4051 }
4052 
4053 //*************************************************************
4055 {
4056  //*************************************************************
4057 
4058  std::vector<ND::TGeomModuleBase*>::const_iterator it;
4059 
4060  fALLMODULES.resize(NDETSEXTRAP);
4061 
4062  // initialize all names
4063  for (int i = 0; i < NDETSEXTRAP; i++) fALLMODULES[i] = "";
4064 
4065  // Get TPC volumes
4066  std::vector<ND::TGeomModuleBase*> TPCMODULES =
4067  ND::TGeomInfo::Get().TPC().GetModules();
4068  int index = 0;
4069  for (it = TPCMODULES.begin(); it != TPCMODULES.end(); it++) {
4070  std::string name = (*it)->GetPath() + "/GasGap_0/Drift_0";
4071  fALLMODULES[index] = name;
4072  index++;
4073  }
4074 
4075  // Get FGD volumes
4076  std::vector<ND::TGeomModuleBase*> FGDMODULES =
4077  ND::TGeomInfo::Get().FGD().GetModules();
4078  index = 3;
4079  for (it = FGDMODULES.begin(); it != FGDMODULES.end(); it++) {
4080  fALLMODULES[index] = (*it)->GetPath() + "/Active_0";
4081  index++;
4082  }
4083 
4084  // Get P0D volumes
4085  std::vector<ND::TGeomModuleBase*> P0DMODULES =
4086  ND::TGeomInfo::Get().P0D().GetModules();
4087  index = 5;
4088  for (it = P0DMODULES.begin(); it != P0DMODULES.end(); it++) {
4089  fALLMODULES[index] = (*it)->GetPath();
4090  index++;
4091  }
4092 
4093  // Get DsECAL volume
4094  const std::vector<ND::TGeomModuleBase*> ECALMODULES =
4095  ND::TGeomInfo::Get().ECAL().GetModules();
4096  index = 6;
4097  for (it = ECALMODULES.begin(); it != ECALMODULES.end(); it++) {
4098  if ((*it)->GetPath().find("DsECal") != std::string::npos) {
4099  fALLMODULES[index] = (*it)->GetPath() + "/Active_0";
4100  index++;
4101  }
4102  }
4103 
4104  // Get SMRD volumes
4105  std::string SMRD_name[6];
4106  std::string magnet_name = ND::tman().GetSetup().GetVolumePath("Magnet_0");
4107  if (magnet_name != "") {
4108  SMRD_name[0] = magnet_name + "/RightClam_0/SMRD_0/Side_0";
4109  SMRD_name[1] = magnet_name + "/RightClam_0/SMRD_0/Top_0";
4110  SMRD_name[2] = magnet_name + "/RightClam_0/SMRD_0/Bottom_0";
4111  SMRD_name[3] = magnet_name + "/LeftClam_0/SMRD_0/Side_0";
4112  SMRD_name[4] = magnet_name + "/LeftClam_0/SMRD_0/Top_0";
4113  SMRD_name[5] = magnet_name + "/LeftClam_0/SMRD_0/Bottom_0";
4114 
4115  index = 7;
4116  for (int i = 0; i < 6; i++) {
4117  fALLMODULES[index] = SMRD_name[i];
4118  index++;
4119  }
4120  }
4121 
4122  // Get Barrel ECAL volumes
4123  index = 13;
4124  for (it = ECALMODULES.begin(); it != ECALMODULES.end(); it++) {
4125  if ((*it)->GetPath().find("DsECal") == std::string::npos) {
4126  fALLMODULES[index] = (*it)->GetPath() + "/Active_0";
4127  index++;
4128  }
4129  }
4130 
4131  // const int NDETS = fALLMODULES.size();
4132 
4133  for (int i = 0; i < NDETSEXTRAP; i++) {
4134  std::string volname = fALLMODULES[i];
4135  if (volname == "") continue;
4136  const Volume& vol = ND::gman().GetSetup().volume(volname);
4137  const surface_vector& surfs = vol.surfaces("outer");
4138  stc_tools::extend_vector<Surface*>(surfs, fDetSurfaces[i]);
4139 
4140  fDetIndex[vol.name("setup_name")] = i;
4141  }
4142 
4143  if (debug_extrap) {
4144  std::cout << "list of volumes: " << std::endl;
4145  for (int i = 0; i < NDETSEXTRAP; i++) {
4146  std::cout << i << " --> " << fALLMODULES[i] << std::endl;
4147  }
4148 
4149  std::cout << "fDetIndex" << std::endl;
4150  // std::map<std::string, int>::const_iterator it2;
4151  // dict::dictionary<int>::const_iterator it2;
4152  for (unsigned int it2 = 0; it2 < fDetIndex.keys().size(); it2++) {
4153  std::cout << fDetIndex.keys()[it2] << " "
4154  << fDetIndex[fDetIndex.keys()[it2]] << std::endl;
4155  int i = fDetIndex[fDetIndex.keys()[it2]];
4156  for (unsigned int j = 0; j < fDetSurfaces[i].size(); j++)
4157  std::cout << " " << j << ": "
4158  << (fDetSurfaces[i])[j]->name("setup_name") << std::endl;
4159  }
4160  }
4161 }
4162 
4163 //*************************************************************
4165  ND::THandle<ND::TReconBase> object, TGlobalPID& globalObject)
4166 {
4167  //*************************************************************
4168 
4169  if (debug_extrap) {
4170  std::cout << "--------------------------------------------------"
4171  << std::endl;
4172  std::cout << "TGlobalReconModule:: Extrapolate to subdetectors: "
4173  << std::endl;
4174  std::cout << "--------------------------------------------------"
4175  << std::endl;
4176  }
4177 
4178  // Initialize variables
4179  for (int i = 0; i < NDETSEXTRAP; i++) {
4180  fPassedDetector[i] = false;
4181  globalObject.EntranceOK[i] = 0;
4182  globalObject.ExitOK[i] = 0;
4183 
4184  globalObject.EntrancePosition[i] =
4185  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4186  globalObject.ExitPosition[i] =
4187  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4188 
4189  globalObject.EntranceDirection[i] =
4190  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4191  globalObject.ExitDirection[i] =
4192  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4193 
4194  globalObject.EntranceMomentum[i] = DEFAULT_MAX;
4195  globalObject.ExitMomentum[i] = DEFAULT_MAX;
4196 
4197  globalObject.EntrancePositionErr[i] =
4198  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4199  globalObject.ExitPositionErr[i] =
4200  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4201 
4202  globalObject.EntranceDirectionErr[i] =
4203  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4204  globalObject.ExitDirectionErr[i] =
4205  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4206 
4207  globalObject.EntranceMomentumErr[i] = DEFAULT_MAX;
4208  globalObject.ExitMomentumErr[i] = DEFAULT_MAX;
4209  }
4210 
4211  // convert the track to a RecPack trajectory
4212  Trajectory traj;
4213  bool ok = ND::converter().TReconBase_to_Trajectory(object, traj);
4214  if (!ok) return;
4215 
4216  if (!traj.status("fitted")) {
4217  return;
4218  }
4219 
4220  if (traj.state(traj.first_fitted_node()).vector()[5] < 0) {
4221  traj.sort_nodes(RP::z, -1);
4222  if (debug_extrap)
4223  std::cout << "Negative sense: sort nodes in reverse z order" << std::endl;
4224  }
4225 
4226  if (debug_extrap) std::cout << "Trajectory: " << traj << std::endl;
4227 
4228  // extrapolate forwards
4229  FillExtrapolationToDetectors(object, globalObject, traj, 1);
4230 
4231  // extrapolate backwards
4232  FillExtrapolationToDetectors(object, globalObject, traj, -1);
4233 
4234  if (debug_extrap) {
4235  std::cout << "---------------------------------------------------------"
4236  << std::endl;
4237  std::cout << "TGlobalReconModule:: Extrapolate to subdetectors results:"
4238  << std::endl;
4239  std::cout << "---------------------------------------------------------"
4240  << std::endl;
4241 
4242  std::cout << object << std::endl;
4243 
4244  for (int i = 0; i < NDETSEXTRAP; i++) {
4245  if (globalObject.EntranceOK[i])
4246  std::cout << i << " x = " << globalObject.EntrancePosition[i].X()
4247  << "\t y = " << globalObject.EntrancePosition[i].Y()
4248  << "\t z = " << globalObject.EntrancePosition[i].Z()
4249  << "\t ex = " << globalObject.EntrancePositionErr[i].X()
4250  << "\t ey = " << globalObject.EntrancePositionErr[i].Y()
4251  << "\t ez = " << globalObject.EntrancePositionErr[i].Z()
4252  << std::endl;
4253  if (globalObject.ExitOK[i])
4254  std::cout << i << " x = " << globalObject.ExitPosition[i].X()
4255  << "\t y = " << globalObject.ExitPosition[i].Y()
4256  << "\t z = " << globalObject.ExitPosition[i].Z()
4257  << "\t ex = " << globalObject.ExitPositionErr[i].X()
4258  << "\t ey = " << globalObject.ExitPositionErr[i].Y()
4259  << "\t ez = " << globalObject.ExitPositionErr[i].Z()
4260  << std::endl;
4261 
4262  if (globalObject.EntranceOK[i])
4263  std::cout << i << " ux = " << globalObject.EntranceDirection[i].X()
4264  << "\t uy = " << globalObject.EntranceDirection[i].Y()
4265  << "\t uz = " << globalObject.EntranceDirection[i].Z()
4266  << "\t ex = " << globalObject.EntranceDirectionErr[i].X()
4267  << "\t ey = " << globalObject.EntranceDirectionErr[i].Y()
4268  << "\t ez = " << globalObject.EntranceDirectionErr[i].Z()
4269  << std::endl;
4270  if (globalObject.ExitOK[i])
4271  std::cout << i << " ux = " << globalObject.ExitDirection[i].X()
4272  << "\t uy = " << globalObject.ExitDirection[i].Y()
4273  << "\t uz = " << globalObject.ExitDirection[i].Z()
4274  << "\t ex = " << globalObject.ExitDirectionErr[i].X()
4275  << "\t ey = " << globalObject.ExitDirectionErr[i].Y()
4276  << "\t ez = " << globalObject.ExitDirectionErr[i].Z()
4277  << std::endl;
4278 
4279  if (globalObject.EntranceOK[i])
4280  std::cout << i << " P0 = " << (globalObject.EntranceMomentum[i])
4281  << " eP0 = " << (globalObject.EntranceMomentumErr[i])
4282  << std::endl;
4283  if (globalObject.ExitOK[i])
4284  std::cout << i << " P1 = " << (globalObject.ExitMomentum[i])
4285  << " eP1 = " << (globalObject.ExitMomentumErr[i])
4286  << std::endl;
4287  }
4288  }
4289 }
4290 
4291 //*************************************************************
4293  ND::THandle<ND::TReconBase> object, TGlobalPID& globalObject,
4294  Trajectory& traj, int sense)
4295 {
4296  //*************************************************************
4297 
4298  // 1. Take the first state in the trajectory (taking into account the sense)
4299  int ifirst = traj.first_fitted_node();
4300  State state = traj.state(ifirst);
4301 
4302  if (debug_extrap) {
4303  std::cout << "Extrapolate to subdetectors: " << std::endl;
4304  std::cout << "1. First state: " << state << std::endl;
4305  }
4306 
4307  // 2. Find the volume associated to the first state
4308 
4309  const Volume* volume = NULL;
4310  EVector position = fEquation.position(state, 0.);
4311  bool ok = ND::gman().GetSetup().volume(position, volume);
4312  if (!ok) {
4313  if (debug_extrap)
4314  std::cout << "Volume not found. Position: " << position << std::endl;
4315  return;
4316  }
4317 
4318  int current_det = -1;
4319  for (unsigned int i = 0; i < fALLMODULES.size(); i++) {
4320  if (volume->name("setup_name").find(fALLMODULES[i]) != std::string::npos)
4321  current_det = i;
4322  }
4323 
4324  if (current_det < 0) {
4325  if (debug_extrap) {
4326  std::cout << "Extrapolate to subdetectors: " << std::endl;
4327  std::cout << "2. Current volume not in list, name = "
4328  << volume->name("setup_name") << std::endl;
4329  }
4330  return;
4331  }
4332 
4333  if (debug_extrap) {
4334  std::cout << "Extrapolate to subdetectors: " << std::endl;
4335  std::cout << "2. Current volume: index = " << current_det
4336  << ", name = " << volume->name("setup_name") << std::endl;
4337  }
4338 
4339  fPassedDetector[current_det] = false;
4340  int iexit = -1;
4341  bool in_found = true;
4342  int nLoops{0};
4343  while (volume) {
4344  nLoops++;
4345 
4346  if (debug_extrap) {
4347  std::cout<<" Loop: "<<nLoops<<std::endl;
4348  std::cout << "Extrapolate to subdetectors: " << std::endl;
4349  std::cout << "3. Exit from volume: " << volume->name("setup_name")
4350  << std::endl;
4351  std::cout << " ifirst: " << ifirst << ", iexit = " << iexit
4352  << ", in found = " << in_found << std::endl;
4353  }
4354 
4355  // 3. Loop over states until we exit from the volume. Only when there is
4356  // an
4357  // state inside the current volume (in_found=true)
4358  if (in_found) {
4359  // by default the exit state is the first one
4360  iexit = ifirst;
4361  if (sense == 1) {
4362  int iprev = ifirst;
4363  for (unsigned int i = ifirst + 1; i < traj.nodes().size(); i++) {
4364  if (traj.node(i).status("fitted")) {
4365  position = fEquation.position(traj.state(i), 0.);
4366  bool ok = volume->is_inside(position);
4367  if (!ok) {
4368  // this is the first state outside the volume. Take the previous
4369  // as exit state
4370  iexit = iprev;
4371  break;
4372  }
4373  iprev = i;
4374  }
4375  }
4376  }
4377  if (debug_extrap)
4378  std::cout << " Last state in volume: " << iexit << std::endl;
4379 
4380  // take the state
4381  state = traj.state(iexit);
4382 
4383  if (debug_extrap) std::cout << state << std::endl;
4384  } else {
4385  if (debug_extrap)
4386  std::cout << " No state inside volume. Propagate to exit surface "
4387  "from the entrance state "
4388  << std::endl;
4389  }
4390 
4391  // 4. Find the closest surface to the last state in the volume (or the
4392  // previous extrapolation if there is no state in the volume)
4393  surface_vector exit_surfaces;
4394  stc_tools::extend_vector<Surface*>(fDetSurfaces[current_det],
4395  exit_surfaces);
4396 
4397  double end_length = 1000000 * sense;
4398  double delta_length;
4399  const Surface* exit_surf;
4400 
4401  ok = ND::rpman("globalAnalysis")
4402  .navigation_svc()
4403  .next_surface(state, end_length, exit_surfaces, delta_length,
4404  exit_surf);
4405 
4406  if (ok) {
4407  if (debug_extrap) {
4408  std::cout << "Extrapolate to subdetectors: " << std::endl;
4409  std::cout << "4. Exit surface. Length: " << delta_length << std::endl;
4410  std::cout << " name: "
4411  << exit_surf->name("setup_name") << std::endl;
4412  std::cout << " volume: " << volume->name("setup_name")
4413  << std::endl;
4414  }
4415  } else {
4416  if (debug_extrap) {
4417  std::cout << "Extrapolate to subdetectors: " << std::endl;
4418  std::cout << "4. Exit surface. Fail in finding exit surface. stop !!! "
4419  << std::endl;
4420  }
4421  return;
4422  }
4423 
4424  // 5. propagate to the surface
4425  ok = ND::rpman("globalAnalysis")
4426  .navigation_svc()
4427  .propagate(0.1 * sense, state);
4428  ok = ND::rpman("globalAnalysis")
4429  .navigation_svc()
4430  .propagate(*exit_surf, state, delta_length);
4431 
4432  if (ok) {
4433  // take the position as the exit position
4434  EVector exitPosition = fEquation.position(state, 0.);
4435  EVector exitDirection = fEquation.direction(state, 0.);
4436  double exitMomentum = DEFAULT_MAX;
4437  if (state.vector()[6] != 0) exitMomentum = fabs(1 / state.vector()[6]);
4438 
4439  TLorentzVector posErr(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4440  if (state.matrix()[0][0] > 0 && state.matrix()[1][1] > 0 &&
4441  state.matrix()[2][2] > 0)
4442  posErr = TLorentzVector(sqrt(state.matrix()[0][0]),
4443  sqrt(state.matrix()[1][1]),
4444  sqrt(state.matrix()[2][2]), 0);
4445 
4446  TVector3 dirErr(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4447  if (state.matrix()[3][3] > 0 && state.matrix()[4][4] > 0 &&
4448  state.matrix()[5][5] > 0)
4449  dirErr =
4450  TVector3(sqrt(state.matrix()[3][3]), sqrt(state.matrix()[4][4]),
4451  sqrt(state.matrix()[5][5]));
4452 
4453  double exitMomentumErr = DEFAULT_MAX;
4454  if (state.matrix()[6][6] > 0 && state.vector()[6] != 0)
4455  exitMomentumErr =
4456  fabs(1 / pow(state.vector()[6], 2)) * sqrt(state.matrix()[6][6]);
4457 
4458  if (debug_extrap) {
4459  std::cout << "Extrapolate to subdetectors: " << std::endl;
4460  std::cout << "5. Exit position: " << print(exitPosition) << std::endl;
4461  std::cout << " Exit direction: " << print(exitDirection) << std::endl;
4462  std::cout << " Exit momentum: " << exitMomentum << std::endl;
4463  }
4464 
4465  TLorentzVector pos;
4466  ok = ND::converter().EVector3_to_TVector(exitPosition, pos);
4467 
4468  TLorentzVector dir4;
4469  ok = ND::converter().EVector3_to_TVector(exitDirection, dir4);
4470  TVector3 dir = dir4.Vect();
4471 
4472  if (sense == 1) {
4473  globalObject.ExitOK[current_det] = 1;
4474  globalObject.ExitPosition[current_det] = pos;
4475  globalObject.ExitDirection[current_det] = dir;
4476  globalObject.ExitMomentum[current_det] = exitMomentum;
4477  globalObject.ExitPositionErr[current_det] = posErr;
4478  globalObject.ExitDirectionErr[current_det] = dirErr;
4479  globalObject.ExitMomentumErr[current_det] = exitMomentumErr;
4480  } else {
4481  globalObject.EntranceOK[current_det] = 1;
4482  globalObject.EntrancePosition[current_det] = pos;
4483  globalObject.EntranceDirection[current_det] = dir;
4484  globalObject.EntranceMomentum[current_det] = exitMomentum;
4485  globalObject.EntrancePositionErr[current_det] = posErr;
4486  globalObject.EntranceDirectionErr[current_det] = dirErr;
4487  globalObject.EntranceMomentumErr[current_det] = exitMomentumErr;
4488  }
4489 
4490  } else {
4491  if (debug_extrap) {
4492  std::cout << "Extrapolate to subdetectors: " << std::endl;
4493  std::cout << "5. Exit position: "
4494  << "surface not intersected !!!" << std::endl;
4495  }
4496  }
4497 
4498  fPassedDetector[current_det] = true;
4499 
4500  // 6. Find the closest surface to the exit state among all other volumes
4501 
4502  // list of possible entrance surfaces
4503  surface_vector entrance_surfaces;
4504  for (int det = 0; det < NDETSEXTRAP; det++) {
4505  if (!fPassedDetector[det]) {
4506  stc_tools::extend_vector<Surface*>(fDetSurfaces[det],
4507  entrance_surfaces);
4508  }
4509  }
4510 
4511  const Surface* entrance_surf;
4512  ok = ND::rpman("globalAnalysis")
4513  .navigation_svc()
4514  .next_surface(state, end_length, entrance_surfaces, delta_length,
4515  entrance_surf);
4516 
4517  if (!ok) {
4518  if (debug_extrap) std::cout << "No suface intersected " << std::endl;
4519  break;
4520  }
4521 
4522  // find the parent volume
4523  const Volume* volume_try;
4524  ok = ND::gman().GetSetup().volume(*entrance_surf, volume_try);
4525 
4526  if (debug_extrap) {
4527  std::cout << "Extrapolate to subdetectors: " << std::endl;
4528  std::cout << "6. Entrance surface. Length: " << delta_length << std::endl;
4529  std::cout << " name: "
4530  << entrance_surf->name("setup_name") << std::endl;
4531  std::cout << " volume: "
4532  << volume_try->name("setup_name") << std::endl;
4533  }
4534 
4535  // 7. Check if the next state in the trajectory is in that volume
4536  in_found = false;
4537  if (sense == 1) {
4538  if ((unsigned int)(iexit + 1) < traj.nodes().size()) {
4539  for (unsigned int i = iexit + 1; i < traj.nodes().size(); i++) {
4540  if (traj.node(i).status("fitted")) {
4541  position = fEquation.position(traj.state(i), 0.);
4542  bool ok = volume_try->is_inside(position);
4543  if (ok) {
4544  ifirst = i;
4545  in_found = true;
4546  }
4547  break;
4548  }
4549  }
4550  }
4551  }
4552 
4553  if (debug_extrap) {
4554  std::cout << "Extrapolate to subdetectors: " << std::endl;
4555  std::cout << "7. Enter in volume: " << volume_try->name("setup_name")
4556  << std::endl;
4557  std::cout << " ifirst: " << ifirst << ", iexit = " << iexit
4558  << ", in found = " << in_found << std::endl;
4559  }
4560 
4561  // iexit=ifirst
4562 
4563  if (debug_extrap) {
4564  if (in_found)
4565  std::cout << " Next state inside volume: " << ifirst << std::endl;
4566  else
4567  std::cout << " No state inside volume. Propagate to entrance surface "
4568  "from the exit of the previous volume "
4569  << std::endl;
4570  }
4571 
4572  // 8. propagate to the surface
4573 
4574  if (in_found) {
4575  // from the first state in the current volume
4576  state = traj.state(ifirst);
4577  }
4578 
4579  ok = ND::rpman("globalAnalysis")
4580  .navigation_svc()
4581  .propagate(0.1 * sense, state);
4582  ok = ND::rpman("globalAnalysis")
4583  .navigation_svc()
4584  .propagate(*entrance_surf, state, delta_length);
4585 
4586  if (ok) {
4587  volume = volume_try;
4588  current_det = -1;
4589  for (unsigned int i = 0; i < fALLMODULES.size(); i++) {
4590  if (volume->name("setup_name").find(fALLMODULES[i]) !=
4591  std::string::npos)
4592  current_det = i;
4593  }
4594 
4595  // take the position as the entrance position
4596  EVector entrancePosition = fEquation.position(state, 0.);
4597  EVector entranceDirection = fEquation.direction(state, 0.);
4598  double entranceMomentum = DEFAULT_MAX;
4599 
4600  if (state.vector()[6] != 0)
4601  entranceMomentum = fabs(1 / state.vector()[6]);
4602 
4603  TLorentzVector posErr(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4604  if (state.matrix()[0][0] > 0 && state.matrix()[1][1] > 0 &&
4605  state.matrix()[2][2] > 0)
4606  posErr = TLorentzVector(sqrt(state.matrix()[0][0]),
4607  sqrt(state.matrix()[1][1]),
4608  sqrt(state.matrix()[2][2]), 0);
4609 
4610  TVector3 dirErr(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
4611  if (state.matrix()[3][3] > 0 && state.matrix()[4][4] > 0 &&
4612  state.matrix()[5][5] > 0)
4613  dirErr =
4614  TVector3(sqrt(state.matrix()[3][3]), sqrt(state.matrix()[4][4]),
4615  sqrt(state.matrix()[5][5]));
4616 
4617  double entranceMomentumErr = DEFAULT_MAX;
4618  if (state.matrix()[6][6] > 0 && state.vector()[6] != 0)
4619  entranceMomentumErr =
4620  fabs(1 / pow(state.vector()[6], 2)) * sqrt(state.matrix()[6][6]);
4621 
4622  if (debug_extrap) {
4623  std::cout << "8. Entrance position: " << print(entrancePosition)
4624  << std::endl;
4625  std::cout << " Entrance direction: " << print(entranceDirection)
4626  << std::endl;
4627  std::cout << " Entrance momentum: " << entranceMomentum << std::endl;
4628  }
4629 
4630  TLorentzVector pos;
4631  ok = ND::converter().EVector3_to_TVector(entrancePosition, pos);
4632 
4633  TLorentzVector dir4;
4634  ok = ND::converter().EVector3_to_TVector(entranceDirection, dir4);
4635  TVector3 dir = dir4.Vect();
4636 
4637  if (sense == 1) {
4638  globalObject.EntranceOK[current_det] = 1;
4639  globalObject.EntrancePosition[current_det] = pos;
4640  globalObject.EntranceDirection[current_det] = dir;
4641  globalObject.EntranceMomentum[current_det] = entranceMomentum;
4642  globalObject.EntrancePositionErr[current_det] = posErr;
4643  globalObject.EntranceDirectionErr[current_det] = dirErr;
4644  globalObject.EntranceMomentumErr[current_det] = entranceMomentumErr;
4645  } else {
4646  globalObject.ExitOK[current_det] = 1;
4647  globalObject.ExitPosition[current_det] = pos;
4648  globalObject.ExitDirection[current_det] = dir;
4649  globalObject.ExitMomentum[current_det] = entranceMomentum;
4650  globalObject.ExitPositionErr[current_det] = posErr;
4651  globalObject.ExitDirectionErr[current_det] = dirErr;
4652  globalObject.ExitMomentumErr[current_det] = entranceMomentumErr;
4653  }
4654  } else {
4655  if (debug_extrap) {
4656  std::cout << "Extrapolate to subdetectors: " << std::endl;
4657  std::cout << "8. Entrance position: "
4658  << "surface not intersected !!!" << std::endl;
4659  }
4660  if(nLoops>12)
4661  {
4662  ND280Log("ND::TGlobalReconModule::FillExtrapolationToDetectors : Extrapolation to subdetectors failed, and "<<nLoops<<" volumes have been attempted so abandoning extrapolation to avoid infinite loop.");
4663  return;
4664  }
4665  }
4666 
4667  // 9. Repit 3 to 8 for all other volumes.
4668  }
4669 }
4670 
4671 //*****************************************************************************
4673  ND::TND280Event& event, ND::THandle<ND::TReconVertex> vertex, bool primary)
4674 {
4675 //*****************************************************************************
4676  // Fill a reconstructed vertex and associated tracks
4677 
4678  // Maximum number of secondary vertices in spill
4679  if (!primary && fNSVertices == NSVERTICES) return false;
4680  // Check that the vertex has a state
4681  ND::THandle<ND::TVertexState> vs = vertex->GetState();
4682  if (!vs) return false;
4683  // Create a global vertex
4684  TGlobalVertex* gVertex = new ((*fVertices)[fNVertices++]) TGlobalVertex;
4685  gVertex->Type = 0;
4686  gVertex->NTrueVertices = 0;
4687 
4688  // Primary
4689  if (primary) {
4690  fPVInd = fNVertices - 1; // index of last added primary
4691  gVertex->PrimaryIndex = -1; //
4692  } else {
4693  // For secondaries set the index of the corresponding primary vertex
4694  gVertex->PrimaryIndex = fPVInd;
4695  fNSVertices++;
4696  }
4697  // Basic info
4698  gVertex->Position = vs->GetPosition();
4699  gVertex->Variance = vs->GetPositionVariance();
4700  gVertex->AlgorithmName = vertex->GetAlgorithmName();
4701  gVertex->Status = vertex->GetStatus();
4702  gVertex->Quality = vertex->GetQuality();
4703  gVertex->NDOF = vertex->GetNDOF();
4704 
4705  // Associated tracks
4706  ND::THandle<ND::TReconObjectContainer> tracksAssociated
4707  = vertex->GetConstituents();
4708  if (tracksAssociated->size() == 0) {
4709  ND280NamedWarn("ECalVertexInTGRMFV",
4710  "Leaving as vertex has no associated constituents.");
4711  return true;
4712  }
4713  std::map<ND::THandle<ND::TReconBase>,
4714  ND::THandle<ND::TReconObjectContainer> >::iterator cit;
4715  // Loop over associated tracks
4716  for (ND::TReconObjectContainer::iterator assocIter =
4717  tracksAssociated->begin();
4718  assocIter != tracksAssociated->end(); assocIter++){
4719  if (ND::THandle<ND::TReconVertex> vtxDummy = (*assocIter)) {
4720  ND280NamedDebug("ECalVertexInTGRMFV", "Skipping vertex constituent: "
4721  << vtxDummy->GetUniqueID());
4722  continue;
4723  }
4724 
4725  // Fill track info
4726  if (gVertex->NConstituents == NCONSTITUENTS) break;
4727  ND::THandle<ND::TReconBase> track = *assocIter;
4728  if (!track) continue;
4729  ND::THandle<ND::TReconState> state = track->GetState();
4730  if (!state) continue;
4731 
4732  // The original track stored as constituent for Kalman vertices
4733  ND::THandle<ND::TReconBase> otrack;
4734  if (gVertex->AlgorithmName == "Kalman") {
4735  ND::THandle<ND::TReconObjectContainer> trackC = track->GetConstituents();
4736  if (trackC->size() == 0) continue;
4737  otrack = trackC->front();
4738  if (!otrack) continue;
4739  }
4740  // Get index of the global track in the overall fPIDs list
4741  int GlobalPIDIndex = -1;
4742  bool inMap = false;
4743  std::map<ND::THandle<ND::TReconBase>, int>::iterator it, miter;
4744 
4745  TLorentzVector pos_track = TrackingUtils::GetPosition(state);
4746  double mom_track = TrackingUtils::GetMomentum(state);
4747 
4748  // Use original track for Kalman vertices
4749  // First look for ND::TIntegerDatum>("PIDID") in the track itself
4750  int PIDID=0;
4751  if(track->Has<ND::TIntegerDatum>("PIDID")){
4752  PIDID=track->Get<ND::TIntegerDatum>("PIDID")->at(0);
4753  }
4754  // failing that look in contained track
4755  if (otrack) {
4756  ND::THandle<ND::TReconState> ostate = otrack->GetState();
4757  mom_track = TrackingUtils::GetMomentum(ostate);
4758  pos_track = TrackingUtils::GetPosition(ostate);
4759  if(PIDID<1&&otrack->Has<ND::TIntegerDatum>("PIDID")){
4760  PIDID=otrack->Get<ND::TIntegerDatum>("PIDID")->at(0);
4761  }
4762  }
4763  if(PIDID!=0){
4764  for (it = fGlobalIndexMap.begin(); it != fGlobalIndexMap.end(); it++) {
4765  if (!it->first) continue;
4766  if((it->first)->Has<ND::TIntegerDatum>("PIDID")){
4767  if( (it->first)->Get<ND::TIntegerDatum>("PIDID")->at(0)==PIDID){
4768  inMap = true;
4769  miter = it;
4770  break;
4771  }
4772  }
4773  }
4774  }
4775  /*}
4776  }
4777  else
4778  { // no contained copy , look directly at the track itself
4779  if(track->Has<ND::TIntegerDatum>("PIDID"))
4780  {
4781  int PIDID=track->Get<ND::TIntegerDatum>("PIDID")->at(0);
4782  if(PIDID!=0)
4783  {
4784  for (it = fGlobalIndexMap.begin(); it != fGlobalIndexMap.end(); it++) {
4785  if (!it->first) continue;
4786  if((it->first)->Has<ND::TIntegerDatum>("PIDID"))
4787  {
4788  if( (it->first)->Get<ND::TIntegerDatum>("PIDID")->at(0)==PIDID)
4789  {
4790  inMap = true;
4791  miter = it;
4792  break;
4793  }
4794  }
4795  }
4796  }
4797  }
4798  }
4799  */
4800  // Global vertex#
4801  if(!inMap){
4802  for (it = fGlobalIndexMap.begin(); it != fGlobalIndexMap.end(); it++) {
4803  if (!it->first) continue;
4804  ND::THandle<ND::TReconState> state_tmp = (it->first)->GetState();
4805  if (!state_tmp) continue;
4806  double mom_tmp = TrackingUtils::GetMomentum(state_tmp);
4807  TLorentzVector pos_tmp = TrackingUtils::GetPosition(state_tmp);
4808  if (pos_track == pos_tmp && mom_track == mom_tmp){
4809  miter = it;
4810  inMap = true;
4811  break;
4812  }
4813  }
4814  }
4815 
4816  // Tracker vertex
4817  if (!inMap) {
4818  if (otrack)
4819  miter = fTrackerGlobalIndexMap.find(otrack);
4820  else
4821  miter = fTrackerGlobalIndexMap.find(track);
4822  if (miter != fTrackerGlobalIndexMap.end()) inMap = true;
4823  }
4824 
4825  if (fUseECalVertices) {
4826  if (!inMap) {
4827  ND280NamedWarn(
4828  "ECalVertexInTGRMFV",
4829  "Didn't find this constituent("
4830  << track->GetUniqueID() << ", " << track->ConvertDetector()
4831  << " " << track->ClassName() << ") in the global map of PIDs.");
4832  gVertex->Quality = 0;
4833  } else {
4834  ND280NamedVerbose("ECalVertexInTGRMFV",
4835  "Adding constituent("
4836  << track->GetUniqueID() << ", "
4837  << track->ConvertDetector()
4838  << ") which was in the global map of PIDs.");
4839  gVertex->Quality = 1;
4840  }
4841  }
4842 
4843  // Set PID
4844  if (inMap) {
4845  GlobalPIDIndex = miter->second;
4846  } else {
4847  // Dont add the constituent and issue a warning
4848  // for the moment log it anyway, since this indicates a special case
4849  // and better to pay attention
4850  std::cout << " WARNING: TGlobalReconModule::FillVertex(): GV constituent "
4851  << "not found among recon tracks! Event ID is "
4852  << event.GetEventId() << std::endl;
4853  continue;
4854  }
4855 
4856  TVertexConstituent* vConst =
4857  new ((*(gVertex->Constituents))[gVertex->NConstituents++])
4859 
4860  vConst->Charge = (int)TrackingUtils::GetCharge(track);
4861  vConst->Quality = track->GetQuality();
4862 
4863  double mom = TrackingUtils::GetMomentum(state);
4864  TVector3 mdir = TrackingUtils::GetDirection(state);
4865  mdir *= mom;
4866 
4867  vConst->Momentum = mdir;
4868  vConst->PID = GlobalPIDIndex;
4869  }
4870  return true;
4871 }
4872 
4873 //*************************************************************
4875  ND::THandle<ND::TG4PrimaryVertexContainer> g4PrimVert)
4876 {
4877  //*************************************************************
4878 
4879  TGlobalVertex* gVertex = (TGlobalVertex*)(*fVertices)[fNVertices - 1];
4880  std::vector<TLorentzVector> vertexPos;
4881  std::vector<std::vector<int> > vertexPIDs;
4882 
4883  int nConst = gVertex->NConstituents;
4884 
4885  // Loop over constituents and create a list of trueVertices with their
4886  // constituents for this global vertex
4887  for (int i = 0; i < nConst; i++) {
4888  if (gVertex->NTrueVertices == NCONSTITUENTS)
4889  break; // why is needed this limit? (max 6 globalV->trueV)
4890  TVertexConstituent* vConst =
4891  (TVertexConstituent*)(*(gVertex->Constituents))[i];
4892  int this_PID = vConst->PID;
4893  TGlobalPID* globalObject = (TGlobalPID*)(*fPIDs)[this_PID];
4894  TTrueParticle globalTrue = globalObject->TrueParticle;
4895  TLorentzVector vPos = globalTrue.Vertex.Position;
4896  bool inList = false;
4897  for (int j = 0; j < (int)vertexPos.size(); j++) {
4898  if (vertexPos[j] == vPos) inList = true;
4899  }
4900  if (inList) continue;
4901  vertexPos.push_back(vPos);
4902 
4903  // Fill globalV->trueV
4904  TTrueVertex* tVertex =
4905  new ((*(gVertex->TrueVertices))[gVertex->NTrueVertices++]) TTrueVertex;
4906  *tVertex = globalTrue.Vertex;
4907 
4908  // ************** the following part of this function, that evaluates
4909  // Cleanliness and Completeness
4910  // ************** has been replaced with in highland, where objects are
4911  // "bunched"
4912 
4913  // Loop over all PIDs, and store those that come from this true vertex
4914  std::vector<int> IDs;
4915  for (int k = 0; k < fNPIDs; k++) {
4916  TGlobalPID* thisGlobalObject = (TGlobalPID*)(*(fPIDs))[k];
4917 
4918  if (thisGlobalObject->NNodes > 0)
4919  ;
4920  else
4921  continue; // track not used in vertexing algorithm
4922  if (thisGlobalObject->Status != 1)
4923  continue; // track not used in vertexing algorithm
4924  if (thisGlobalObject->DetectorUsed[0] != 1 &&
4925  thisGlobalObject->DetectorUsed[1] != 1 &&
4926  thisGlobalObject->DetectorUsed[2] != 1 &&
4927  thisGlobalObject->DetectorUsed[3] != 1 &&
4928  thisGlobalObject->DetectorUsed[4] != 1)
4929  continue; // track not used in vertexing algorithm (only FGDs or TPCs
4930  // tracks)
4931 
4932  TTrueParticle thisGlobalTrue = thisGlobalObject->TrueParticle;
4933  if (thisGlobalTrue.ID == -1) continue; // track without true
4934 
4935  // here we should also select only primary true tracks and only in the
4936  // same bunch (that's why we do this in highland)
4937 
4938  TLorentzVector thisVPos = thisGlobalTrue.Vertex.Position;
4939  // broken tracks are double counted
4940  if (thisVPos == vPos) IDs.push_back(k);
4941  }
4942  vertexPIDs.push_back(IDs);
4943  }
4944 
4945  // Set efficiencies and purities FOR EACH TRUEV associated to the GlbV under
4946  // study
4947  // Loop over the found true vertices
4948  for (int i = 0; i < gVertex->NTrueVertices; i++) {
4949  std::vector<int> IDs = vertexPIDs[i];
4950  int nIDs = (int)IDs.size();
4951  int nMatch = 0;
4952 
4953  // Loop over vertex constituents
4954  for (int j = 0; j < nConst; j++) {
4955  TVertexConstituent* vConst =
4956  (TVertexConstituent*)(*(gVertex->Constituents))[j];
4957  int this_PID = vConst->PID;
4958  // Check if they match true vertex PID list
4959  for (int k = 0; k < nIDs; k++) {
4960  if (this_PID == IDs[k]) nMatch++;
4961  }
4962  }
4963 
4964  TTrueVertex* tVertex = (TTrueVertex*)(*gVertex->TrueVertices)[i];
4965 
4966  tVertex->Pur =
4967  (double)nMatch / nConst; // nConstituents of the GlbV under study
4968  tVertex->Eff =
4969  (double)nMatch /
4970  nIDs; // nIDS = n of true particle coming from this true vertex
4971  }
4972 }
4973 
4974 //*************************************************************
4976  ND::THandle<ND::TG4Trajectory> G4track, double pur, double eff,
4977  ND::TTrueParticle& trueParticle)
4978 {
4979  //*************************************************************
4980 
4981  if (G4track) {
4982  trueParticle.ID = G4track->GetTrackId();
4983 
4984  trueParticle.Pur = pur;
4985  trueParticle.Eff = eff;
4986 
4987  ND::TG4PrimaryVertex G4vertex;
4988  bool ok = GetG4Vertex(G4track, G4vertex);
4989  FillTrueVertex(ok, G4vertex, DEFAULT_MAX, DEFAULT_MAX, trueParticle.Vertex);
4990 
4991  } else {
4992  trueParticle.ID = -1;
4993 
4994  trueParticle.Pur = DEFAULT_MAX;
4995  trueParticle.Eff = DEFAULT_MAX;
4996 
4997  ND::TG4PrimaryVertex G4vertex;
4998  FillTrueVertex(false, G4vertex, DEFAULT_MAX, DEFAULT_MAX,
4999  trueParticle.Vertex);
5000  }
5001 }
5002 
5003 //*************************************************************
5004 ND::THandle<ND::TG4Trajectory> ND::TGlobalReconModule::GetParent(
5005  ND::THandle<ND::TG4Trajectory> G4track)
5006 {
5007  //*************************************************************
5008 
5009  const ND::TND280Event& event = *(ND::TEventFolder::GetCurrentEvent());
5010  ND::THandle<ND::TG4TrajectoryContainer> trajectories =
5011  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
5012 
5013  if (G4track->GetParentId() != 0) {
5014  ND::THandle<ND::TG4Trajectory> traj(
5015  new ND::TG4Trajectory(((*trajectories)[G4track->GetParentId()])));
5016  return traj;
5017  } else
5018  return ND::THandle<ND::TG4Trajectory>();
5019 
5020  /*
5021  // create a map with trajectories ordered in descending kinetic energy
5022  if(trajectories){
5023  ND::TG4TrajectoryContainer::iterator trajIter;
5024  for(trajIter = trajectories->begin();trajIter != trajectories->end();
5025  ++trajIter) {
5026  if ((*trajIter)->GetTrackId() == G4track->GetParentId()) return *trajIter;
5027  }
5028  }
5029 
5030  return ND::THandle<ND::TG4Trajectory>();
5031  */
5032 }
5033 
5034 //*************************************************************
5036  bool found, const ND::TG4PrimaryVertex& G4vertex, double pur, double eff,
5037  ND::TTrueVertex& vertex)
5038 {
5039  //*************************************************************
5040 
5041  if (found) {
5042  vertex.Position = G4vertex.GetPosition();
5043  vertex.ID = G4vertex.GetInteractionNumber();
5044  vertex.Pur = pur;
5045  vertex.Eff = eff;
5046  } else {
5047  vertex.Position =
5048  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5049  vertex.ID = -1;
5050  vertex.Pur = DEFAULT_MAX;
5051  vertex.Eff = DEFAULT_MAX;
5052  }
5053 }
5054 
5055 //*************************************************************
5056 ND::THandle<ND::TG4PrimaryVertex> ND::TGlobalReconModule::GetG4Vertex(
5057  const ND::TReconBase&, double& pur, double& eff)
5058 {
5059  //*************************************************************
5060 
5061  return ND::THandle<ND::TG4PrimaryVertex>();
5062 }
5063 
5064 //*************************************************************
5065 bool ND::TGlobalReconModule::GetG4Vertex(ND::THandle<ND::TG4Trajectory> G4track,
5066  ND::TG4PrimaryVertex& G4vertex)
5067 {
5068  //*************************************************************
5069 
5070  // 1. Find the primary particle associated to this G4 trajectory
5071 
5072  const ND::TND280Event& event = *(ND::TEventFolder::GetCurrentEvent());
5073  ND::THandle<ND::TG4TrajectoryContainer> trajectories =
5074  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
5075  if (!trajectories) return false;
5076 
5077  int nextparent;
5078  int count = 0;
5079  int primaryID = G4track->GetTrackId();
5080 
5081  while ((primaryID > 0) &&
5082  ((nextparent = (*trajectories)[primaryID].GetParentId()) > 0)) {
5083  primaryID = nextparent;
5084  if (count++ > 100000000) {
5085  // just to make sure it doesn't go into an infinite loop somehow
5086  ND280Error(
5087  "TGlobalReconModule: Particle has more than 100000000 levels of "
5088  "parents!");
5089  throw ND::EeventAnalysisInfiniteLoop2();
5090  }
5091  }
5092 
5093  // 2. Find the primary vertex associated to the primary particle
5094  ND::THandle<ND::TG4PrimaryVertexContainer> vertices =
5095  event.Get<ND::TG4PrimaryVertexContainer>("truth/G4PrimVertex00");
5096  if (!vertices) return false;
5097 
5098  std::vector<ND::TG4PrimaryVertex>::iterator it1;
5099  for (it1 = vertices->begin(); it1 != vertices->end(); it1++) {
5100  const ND::TG4PrimaryParticleContainer& particles =
5101  it1->GetPrimaryParticles();
5102 
5103  std::vector<ND::TG4PrimaryParticle>::const_iterator it2;
5104  for (it2 = particles.begin(); it2 != particles.end(); it2++) {
5105  if (it2->GetTrackId() == primaryID) {
5106  G4vertex = *it1;
5107  return true;
5108  }
5109  }
5110  }
5111 
5112  return false;
5113 }
5114 
5115 //*************************************************************
5117  const ND::TG4PrimaryVertex& G4vertex, ND::TG4PrimaryParticle& incoming)
5118 {
5119  //*************************************************************
5120 
5121  for (std::vector<ND::TG4PrimaryVertex>::const_iterator infoVtxIter =
5122  G4vertex.GetInfoVertex().begin();
5123  infoVtxIter != G4vertex.GetInfoVertex().end(); ++infoVtxIter) {
5124  std::vector<ND::TG4PrimaryParticle>::const_iterator particleIter;
5125  for (particleIter = infoVtxIter->GetPrimaryParticles().begin();
5126  particleIter != infoVtxIter->GetPrimaryParticles().end();
5127  ++particleIter) {
5128  Int_t pdg = particleIter->GetPDGCode();
5129  if (particleIter->GetTrackId() == -1) {
5130  // is an incoming particle (including target)
5131  if (TMath::Abs(pdg) == 12 || TMath::Abs(pdg) == 14 ||
5132  TMath::Abs(pdg) == 16) {
5133  incoming = *particleIter;
5134  return true;
5135  }
5136  }
5137  }
5138  }
5139 
5140  return false;
5141 }
5142 
5143 //*************************************************************
5145  ND::THandle<ND::TReconBase> object)
5146 {
5147  //*************************************************************
5148 
5149  int nHits = 0;
5150  if (object->GetHits())
5151  nHits += object->GetHits()->size();
5152  else if (object->GetConstituents()) {
5153  ND::TReconObjectContainer::const_iterator it;
5154  for (it = object->GetConstituents()->begin();
5155  it != object->GetConstituents()->end(); it++) {
5156  nHits += GetNumberOfHits(*it);
5157  }
5158  }
5159 
5160  return nHits;
5161 }
5162 
5163 //*****************************************************
5165  ND::THandle<ND::TReconBase> object)
5166 {
5167 //*****************************************************
5168 
5169  unsigned long det = 0;
5170 
5171  if (object->UsesDetector(ND::TReconBase::kFGD1))
5173  if (object->UsesDetector(ND::TReconBase::kFGD2))
5175  if (object->UsesDetector(ND::TReconBase::kTPC1))
5177  if (object->UsesDetector(ND::TReconBase::kTPC2))
5179  if (object->UsesDetector(ND::TReconBase::kTPC3))
5181  if (object->UsesDetector(ND::TReconBase::kSFG))
5183  if (object->UsesDetector(ND::TReconBase::kP0D))
5185  if (object->UsesDetector(ND::TReconBase::kDSECal))
5187  if (object->UsesDetector(ND::TReconBase::kTopPECal))
5189  if (object->UsesDetector(ND::TReconBase::kBottomPECal))
5191  if (object->UsesDetector(ND::TReconBase::kLeftPECal))
5193  if (object->UsesDetector(ND::TReconBase::kRightPECal))
5195  if (object->UsesDetector(ND::TReconBase::kTopTECal))
5197  if (object->UsesDetector(ND::TReconBase::kBottomTECal))
5199  if (object->UsesDetector(ND::TReconBase::kLeftTECal))
5201  if (object->UsesDetector(ND::TReconBase::kRightTECal))
5203  if (object->UsesDetector(ND::TReconBase::kSMRD))
5205  if (object->UsesDetector(ND::TReconBase::kTopHAT))
5207  if (object->UsesDetector(ND::TReconBase::kBottomHAT))
5209  if (object->UsesDetector(ND::TReconBase::kTOF))
5211  return det;
5212 }
5213 
5215  ND::THandle<ND::TReconBase> object){
5216  int count = 0;
5217  if (object->UsesDetector(ND::TReconBase::kTPC1)) ++count;
5218  if (object->UsesDetector(ND::TReconBase::kTPC2)) ++count;
5219  if (object->UsesDetector(ND::TReconBase::kTPC3)) ++count;
5220  if (object->UsesDetector(ND::TReconBase::kFGD1)) ++count;
5221  if (object->UsesDetector(ND::TReconBase::kFGD2)) ++count;
5222  if (object->UsesDetector(ND::TReconBase::kSFG)) ++count;
5223  if (object->UsesDetector(ND::TReconBase::kTopHAT)) ++count;
5224  if (object->UsesDetector(ND::TReconBase::kBottomHAT)) ++count;
5225  if (object->UsesDetector(ND::TReconBase::kTOF)) ++count;
5226  if (object->UsesDetector(ND::TReconBase::kP0D)) ++count;
5227  if (object->UsesDetector(ND::TReconBase::kDSECal)) ++count;
5228  if (object->UsesDetector(ND::TReconBase::kTopPECal)) ++count;
5229  if (object->UsesDetector(ND::TReconBase::kBottomPECal)) ++count;
5230  if (object->UsesDetector(ND::TReconBase::kLeftPECal)) ++count;
5231  if (object->UsesDetector(ND::TReconBase::kRightPECal)) ++count;
5232  if (object->UsesDetector(ND::TReconBase::kTopTECal)) ++count;
5233  if (object->UsesDetector(ND::TReconBase::kBottomTECal)) ++count;
5234  if (object->UsesDetector(ND::TReconBase::kLeftTECal)) ++count;
5235  if (object->UsesDetector(ND::TReconBase::kRightTECal)) ++count;
5236  if (object->UsesDetector(ND::TReconBase::kSMRD)) ++count;
5237  return count;
5238 }
5239 
5240 
5241 //*****************************************************
5243  ND::THandle<ND::TReconBase> object, bool dets[])
5244 {
5245 //*****************************************************
5246 
5247  // Fill the used detectors. This should be consistent with
5248  // psycheND280Utils/TreeConverterUtils::SetDetectorUsedField.
5249 
5250  for (int i = 0; i < NDETSUSED; i++) dets[i] = false;
5251 
5252  if (object->UsesDetector(ND::TReconBase::kFGD1)) dets[0] = true;
5253  if (object->UsesDetector(ND::TReconBase::kFGD2)) dets[1] = true;
5254  if (object->UsesDetector(ND::TReconBase::kTPC1)) dets[2] = true;
5255  if (object->UsesDetector(ND::TReconBase::kTPC2)) dets[3] = true;
5256  if (object->UsesDetector(ND::TReconBase::kTPC3)) dets[4] = true;
5257  if (object->UsesDetector(ND::TReconBase::kSFG)) dets[5] = true;
5258  if (object->UsesDetector(ND::TReconBase::kTopHAT)) dets[6] = true;
5259  if (object->UsesDetector(ND::TReconBase::kBottomHAT)) dets[7] = true;
5260  if (object->UsesDetector(ND::TReconBase::kTOF)) dets[8] = true;
5261  if (object->UsesDetector(ND::TReconBase::kP0D)) dets[9] = true;
5262  if (object->UsesDetector(ND::TReconBase::kDSECal)) dets[10] = true;
5263  if (object->UsesDetector(ND::TReconBase::kTopTECal)) dets[11] = true;
5264  if (object->UsesDetector(ND::TReconBase::kBottomTECal)) dets[12] = true;
5265  if (object->UsesDetector(ND::TReconBase::kLeftTECal)) dets[13] = true;
5266  if (object->UsesDetector(ND::TReconBase::kRightTECal)) dets[14] = true;
5267  if (object->UsesDetector(ND::TReconBase::kTopPECal)) dets[15] = true;
5268  if (object->UsesDetector(ND::TReconBase::kBottomPECal)) dets[16] = true;
5269  if (object->UsesDetector(ND::TReconBase::kLeftPECal)) dets[17] = true;
5270  if (object->UsesDetector(ND::TReconBase::kRightPECal)) dets[18] = true;
5271  if (object->UsesDetector(ND::TReconBase::kTopSMRD)) dets[19] = true;
5272  if (object->UsesDetector(ND::TReconBase::kBottomSMRD)) dets[20] = true;
5273  if (object->UsesDetector(ND::TReconBase::kLeftSMRD)) dets[21] = true;
5274  if (object->UsesDetector(ND::TReconBase::kRightSMRD)) dets[22] = true;
5275 
5276 }
5277 
5278 //*****************************************************
5279 void ND::TGlobalReconModule::FillTPCOther(ND::TND280Event& event)
5280 {
5281  //*****************************************************
5282 
5283  ND::THandle<ND::TAlgorithmResult> tpcRecon = event.GetFit("tpcRecon");
5284  if (tpcRecon) {
5285  ND::THandle<ND::TReconObjectContainer> otherObjects =
5286  tpcRecon->GetResultsContainer("TPCother");
5287  if (otherObjects) {
5288  for (ND::TReconObjectContainer::iterator tt = otherObjects->begin();
5289  tt != otherObjects->end(); tt++) {
5290  ND::THandle<ND::TReconBase> other = *tt;
5291 
5292  if (other && fNTPCOthers < NMAXTPCOTHER) {
5293  TTPCOtherObject* tpcOther =
5294  new ((*fTPCOthers)[fNTPCOthers++]) TTPCOtherObject;
5295 
5296  tpcOther->Detector = GetDetectorNumber(other);
5297  tpcOther->Chi2 = other->GetQuality();
5298  tpcOther->EDeposit = TrackingUtils::GetEDeposit(other);
5299  tpcOther->Charge = TrackingUtils::GetCharge(other);
5300  tpcOther->NHits = DEFAULT_MAX;
5301  if (other->GetHits()) tpcOther->NHits = other->GetHits()->size();
5302 
5303  // Set the back and front position, variance and direction
5304  ND::THandle<ND::TReconState> firstState =
5305  TrackingUtils::GetFirstState(*other);
5306  if (firstState) {
5307  tpcOther->FrontPosition = TrackingUtils::GetPosition(firstState);
5308  tpcOther->FrontDirection = TrackingUtils::GetDirection(firstState);
5309  tpcOther->Momentum = TrackingUtils::GetMomentum(firstState);
5310  } else {
5311  tpcOther->FrontPosition = TLorentzVector(DEFAULT_MAX, DEFAULT_MAX,
5313  tpcOther->FrontDirection =
5314  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5315  tpcOther->Momentum = DEFAULT_MAX;
5316  }
5317 
5318  ND::THandle<ND::TReconState> lastState =
5319  TrackingUtils::GetLastState(*other);
5320  if (lastState) {
5321  tpcOther->BackPosition = TrackingUtils::GetPosition(lastState);
5322  tpcOther->BackDirection = TrackingUtils::GetDirection(lastState);
5323  } else {
5324  tpcOther->BackPosition = TLorentzVector(DEFAULT_MAX, DEFAULT_MAX,
5326  tpcOther->BackDirection =
5327  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5328  }
5329 
5330  // Fill the true particle when it is found
5331  double pur, eff;
5332  ND::THandle<ND::TG4Trajectory> G4track =
5333  GetG4Trajectory(*other, pur, eff);
5334  FillTrueParticle(G4track, pur, eff, tpcOther->TrueParticle);
5335  }
5336  }
5337  }
5338  }
5339 }
5340 
5341 //*****************************************************
5342 void ND::TGlobalReconModule::FillUnusedHits(ND::TND280Event& event)
5343 {
5344  //*****************************************************
5345 
5346  // Now add TPC hits
5347  ND::THandle<ND::TAlgorithmResult> tpcRecon = event.GetFit("tpcRecon");
5348  if (tpcRecon) {
5349  // Get TPC unused hits
5350  ND::THandle<ND::THitSelection> tpcHits =
5351  tpcRecon->GetHitSelection("TPCunused");
5352  if (tpcHits) {
5353  fNTPCUnused = tpcHits->size();
5354  }
5355  }
5356 
5357  // Now add P0D hits
5358  ND::THandle<ND::TAlgorithmResult> p0dRecon = event.GetFit("p0dRecon");
5359  if (p0dRecon) {
5360  // Get P0D unused hits
5361  ND::THandle<ND::THitSelection> p0dHits =
5362  p0dRecon->GetHitSelection("unused");
5363  if (p0dHits) {
5364  for (ND::THitSelection::iterator hit = p0dHits->begin();
5365  hit != p0dHits->end(); hit++) {
5366  TGlobalHit* gHit = new ((*fP0DUnused)[fNP0DUnused++]) TGlobalHit;
5367  FillGlobalHit(*hit, *gHit);
5368  }
5369  }
5370  }
5371 
5372  ND::THandle<ND::TAlgorithmResult> smrdRecon = event.GetFit("smrdRecon");
5373  if (smrdRecon) {
5374  // Get SMRD unused hits
5375  ND::THandle<ND::THitSelection> smrdHits =
5376  smrdRecon->GetHitSelection("unused");
5377  if (smrdHits) {
5378  for (ND::THitSelection::iterator h = smrdHits->begin();
5379  h != smrdHits->end(); h++) {
5380  // fill info for smrd unused hit
5381  TSMRDHit* smrdHit = NULL;
5382  smrdHit = new ((*fSMRDUnused)[fNSMRDUnused++]) TSMRDHit;
5383  FillSmrdHit(*h, *smrdHit);
5384 
5385  if (ND::TGeomInfo::SMRD().IsSMRDTopWall((*h))) {
5386  fNSMRDTopUnused++;
5387  } else if (ND::TGeomInfo::SMRD().IsSMRDBottomWall((*h))) {
5389  } else if (ND::TGeomInfo::SMRD().IsSMRDLeftWall((*h))) {
5390  fNSMRDLeftUnused++;
5391  } else if (ND::TGeomInfo::SMRD().IsSMRDRightWall((*h))) {
5393  }
5394  }
5395  }
5396  }
5397 }
5398 
5399 //*****************************************************
5400 void ND::TGlobalReconModule::FillFirstLastHits(ND::THitSelection& hits,
5401  TGlobalPID& globalObject)
5402 {
5403  //*****************************************************
5404 
5405  // sort hits in increasing Z
5406  std::sort(hits.begin(), hits.end(), SortHitsInZ);
5407 
5408  TGlobalHit* hitSaved[10];
5409  bool firstX = false;
5410  bool lastX = false;
5411  bool firstY = false;
5412  bool lastY = false;
5413 
5414  for (ND::THitSelection::iterator hit = hits.begin(); hit != hits.end();
5415  hit++) {
5416  if (globalObject.NHitsSaved >= 10 || (firstX && firstY)) break;
5417 
5418  if ((*hit)->IsXHit() && !firstX) {
5419  hitSaved[globalObject.NHitsSaved] =
5420  new ((*(globalObject.HitsSaved))[globalObject.NHitsSaved]) TGlobalHit;
5421  FillGlobalHit(*hit, *hitSaved[globalObject.NHitsSaved]);
5422  globalObject.NHitsSaved++;
5423  firstX = true;
5424  if ((*hit)->IsYHit()) firstY = true;
5425  } else if ((*hit)->IsYHit() && !firstY) {
5426  hitSaved[globalObject.NHitsSaved] =
5427  new ((*(globalObject.HitsSaved))[globalObject.NHitsSaved]) TGlobalHit;
5428  FillGlobalHit(*hit, *hitSaved[globalObject.NHitsSaved]);
5429  globalObject.NHitsSaved++;
5430  firstY = true;
5431  if ((*hit)->IsXHit()) firstX = true;
5432  }
5433  }
5434 
5435  for (ND::THitSelection::reverse_iterator hit = hits.rbegin();
5436  hit != hits.rend(); hit++) {
5437  if (globalObject.NHitsSaved >= 10 || (lastX && lastY)) break;
5438 
5439  if ((*hit)->IsXHit() && !lastX) {
5440  hitSaved[globalObject.NHitsSaved] =
5441  new ((*(globalObject.HitsSaved))[globalObject.NHitsSaved]) TGlobalHit;
5442  FillGlobalHit(*hit, *hitSaved[globalObject.NHitsSaved]);
5443  globalObject.NHitsSaved++;
5444  lastX = true;
5445  if ((*hit)->IsYHit()) lastY = true;
5446  } else if ((*hit)->IsYHit() && !lastY) {
5447  hitSaved[globalObject.NHitsSaved] =
5448  new ((*(globalObject.HitsSaved))[globalObject.NHitsSaved]) TGlobalHit;
5449  FillGlobalHit(*hit, *hitSaved[globalObject.NHitsSaved]);
5450  globalObject.NHitsSaved++;
5451  lastY = true;
5452  if ((*hit)->IsXHit()) lastX = true;
5453  }
5454  }
5455 }
5456 
5457 //*****************************************************
5459  ND::THitSelection& hits,
5460  TGlobalPID& globalObject) {
5461 //*****************************************************
5462  for(ND::THitSelection::iterator hit = hits.begin();
5463  hit != hits.end(); hit++) {
5464  TGlobalHit* gHit =
5465  new ((*(globalObject.HitsSaved))[globalObject.NHitsSaved++])TGlobalHit;
5466  FillGlobalHit(*hit, *gHit);
5467  }
5468 }
5469 
5470 //*****************************************************
5471 void ND::TGlobalReconModule::FillOutermostHits(ND::THitSelection& hits,
5472  double charge_cut,
5473  TOutermostHits& outer)
5474 {
5475  //*****************************************************
5476 
5477  double minX = 1000000;
5478  double maxX = -1000000;
5479  double minY = 1000000;
5480  double maxY = -1000000;
5481  double minZ = 1000000;
5482  double maxZ = -1000000;
5483 
5484  ND::THandle<ND::THit> hitSave[6];
5485 
5486  for (ND::THitSelection::iterator hit = hits.begin(); hit != hits.end();
5487  hit++) {
5488  if ((*hit)->GetCharge() < charge_cut) continue;
5489 
5490  if ((*hit)->IsXHit()) {
5491  if ((*hit)->GetPosition().X() > maxX) {
5492  maxX = (*hit)->GetPosition().X();
5493  hitSave[0] = *hit;
5494  }
5495  if ((*hit)->GetPosition().X() < minX) {
5496  minX = (*hit)->GetPosition().X();
5497  hitSave[1] = *hit;
5498  }
5499  }
5500  if ((*hit)->IsYHit()) {
5501  if ((*hit)->GetPosition().Y() > maxY) {
5502  maxY = (*hit)->GetPosition().Y();
5503  hitSave[2] = *hit;
5504  }
5505  if ((*hit)->GetPosition().Y() < minY) {
5506  minY = (*hit)->GetPosition().Y();
5507  hitSave[3] = *hit;
5508  }
5509  }
5510  if ((*hit)->IsZHit()) {
5511  if ((*hit)->GetPosition().Z() > maxZ) {
5512  maxZ = (*hit)->GetPosition().Z();
5513  hitSave[4] = *hit;
5514  }
5515  if ((*hit)->GetPosition().Z() < minZ) {
5516  minZ = (*hit)->GetPosition().Z();
5517  hitSave[5] = *hit;
5518  }
5519  }
5520  }
5521 
5522  FillGlobalHit(hitSave[0], outer.hitMaxX);
5523  FillGlobalHit(hitSave[1], outer.hitMinX);
5524  FillGlobalHit(hitSave[2], outer.hitMaxY);
5525  FillGlobalHit(hitSave[3], outer.hitMinY);
5526  FillGlobalHit(hitSave[4], outer.hitMaxZ);
5527  FillGlobalHit(hitSave[5], outer.hitMinZ);
5528 }
5529 
5530 
5531 //*****************************************************
5532 void ND::TGlobalReconModule::FillSfgTimeBins(ND::TND280Event& event)
5533 {
5534 //*****************************************************
5535 
5536 
5537  TTrackerReconUtils trackerUtils;
5538  fNSfgTimeBins = trackerUtils.GetSFGTimeBinNumber(event);
5539  for (int ibin = 0; ibin < fNSfgTimeBins; ibin++) {
5540  TSfgTimeBin* bin = new ((*fSfgTimeBins)[ibin]) TSfgTimeBin;
5541  ND::THandle<ND::TAlgorithmResult> tbResult
5542  = trackerUtils.GetSFGTimeBinResult(event, ibin);
5543 
5544  // Initialize the bin info
5545  bin->minTime = 2.e10;
5546  bin->maxTime = -2.e10;
5547  bin->nHits = 0;
5548  bin->rawChargeSum = 0.;
5549  bin->chargeWeightedPos = TVector3(0., 0., 0.);
5550  bin->NSFGUnused = 0;
5551  bin->g4ID = 0;
5552  bin->SFGUnused->Clear();
5553  bin->SFGHitPositionX.clear();
5554  bin->SFGHitPositionY.clear();
5555  bin->SFGHitPositionZ.clear();
5556  bin->SFGHitT .clear();
5557  bin->SFGHitQ .clear();
5558  bin->SFGHitTrajID .clear();
5559 
5560  if (tbResult) {
5561  std::tie(bin->minTime, bin->maxTime)
5562  = trackerUtils.GetTimeBinBoundary(tbResult);
5563 
5564  // Fill the SFG unused hits
5565  ND::THandle<ND::THitSelection> sfgUnused =
5566  tbResult->GetHitSelection("unused");
5567  if (sfgUnused) {
5568  for (ND::THitSelection::iterator hit = sfgUnused->begin();
5569  hit != sfgUnused->end(); hit++) {
5570  TGlobalHit* gHit = NULL;
5571  if (ND::GeomId::SFG::IsCube((*hit)->GetGeomId()))
5572  gHit = new ((*bin->SFGUnused)[bin->NSFGUnused++]) TGlobalHit;
5573  else
5574  continue;
5575 
5576  FillGlobalHit(*hit, *gHit);
5577  }
5578  }
5579  // Cumulative result for all time bins
5580  fNSFGUnused += bin->NSFGUnused;
5581 
5582 
5583  // Fill information on individual SFG hits
5584  ND::THandle<ND::THitSelection> tbHits = tbResult->GetHitSelection("used");
5585  if (tbHits) {
5586  bin->nHits = tbHits->size();
5587  for (ND::THitSelection::iterator hit = tbHits->begin();
5588  hit != tbHits->end(); hit++) {
5589  // Fill the information about individual SFG hit
5590  TVector3 pos = (*hit)->GetPosition();
5591  bin->SFGHitPositionX.push_back(pos.X());
5592  bin->SFGHitPositionY.push_back(pos.Y());
5593  bin->SFGHitPositionZ.push_back(pos.Z());
5594  bin->SFGHitT .push_back((*hit)->GetTime());
5595  bin->SFGHitQ .push_back((*hit)->GetCharge());
5596  bin->rawChargeSum += (*hit)->GetCharge();
5597  ND::THitSelection thisHit;
5598  thisHit.push_back(*hit);
5599  bin->SFGHitTrajID.push_back(TrackTruthInfo::GetG4TrajIDHits(thisHit));
5600  } // End loop over hits
5601  } // Finished filling information on individual SFG hits
5602  }
5603  }
5604 }
5605 
5606 
5607 //*****************************************************
5608 void ND::TGlobalReconModule::FillFgdTimeBins(ND::TND280Event& event)
5609 {
5610  //*****************************************************
5611 
5612  bool isMC = event.GetContext().IsMC();
5613 
5614  fNFgdTimeBins = fgdUtils::getNumberTimeBins(event);
5615  for (int ibin = 0; ibin < fNFgdTimeBins; ibin++) {
5616  TFgdTimeBin* bin = new ((*fFgdTimeBins)[ibin]) TFgdTimeBin;
5617  ND::THandle<ND::TAlgorithmResult> tbResult =
5618  fgdUtils::getTimeBinResult(event, ibin);
5619 
5620  bin->minTime = 2.e10;
5621  bin->maxTime = -2.e10;
5622 
5623  for (int ifgd = 0; ifgd < 2; ifgd++) {
5624  bin->nHits[ifgd] = 0;
5625  bin->rawChargeSum[ifgd] = 0.;
5626  bin->chargeWeightedPos[ifgd] = TVector3(0., 0., 0.);
5627  for (int ilayer = 0; ilayer < 30; ilayer++) {
5628  bin->chargePerLayer[ifgd][ilayer] = 0.;
5629  }
5630  }
5631 
5632  bin->NFGD1Unused = 0;
5633  bin->NFGD2Unused = 0;
5634 
5635  bin->FGD1Unused->Clear();
5636  bin->FGD2Unused->Clear();
5637 
5638  if (tbResult) {
5639  ND::THandle<ND::TRealDatum> binStartTime =
5640  tbResult->Get<ND::TRealDatum>("binStartTime");
5641  if (binStartTime) {
5642  bin->minTime = binStartTime->GetValue();
5643  }
5644 
5645  ND::THandle<ND::TRealDatum> binEndTime =
5646  tbResult->Get<ND::TRealDatum>("binEndTime");
5647  if (binEndTime) {
5648  bin->maxTime = binEndTime->GetValue();
5649  }
5650 
5651  // Fill the FGD unused hits
5652  ND::THandle<ND::THitSelection> fgdUnused =
5653  tbResult->GetHitSelection("unused");
5654  if (fgdUnused) {
5655  for (ND::THitSelection::iterator hit = fgdUnused->begin();
5656  hit != fgdUnused->end(); hit++) {
5657  TGlobalHit* gHit = NULL;
5658  if (ND::TGeomInfo::FGD().IsInFGD1((*hit)->GetPosition()))
5659  gHit = new ((*bin->FGD1Unused)[bin->NFGD1Unused++]) TGlobalHit;
5660  else if (ND::TGeomInfo::FGD().IsInFGD2((*hit)->GetPosition()))
5661  gHit = new ((*bin->FGD2Unused)[bin->NFGD2Unused++]) TGlobalHit;
5662  else
5663  continue;
5664 
5665  FillGlobalHit(*hit, *gHit);
5666  }
5667  }
5668 
5669  // Also include hits from 2D fgdIsoRecon tracks for now
5670  ND::THandle<ND::TReconObjectContainer> xz =
5671  tbResult->GetResultsContainer("xzUnmatchedFgdReconTracks");
5672  if (xz) {
5673  for (ND::TReconObjectContainer::iterator tt = xz->begin();
5674  tt != xz->end(); tt++) {
5675  ND::THandle<ND::TReconBase> object = *tt;
5676  if (object) {
5677  ND::THandle<ND::THitSelection> hits = object->GetHits();
5678  if (hits) {
5679  for (ND::THitSelection::iterator hit = hits->begin();
5680  hit != hits->end(); hit++) {
5681  TGlobalHit* gHit = NULL;
5682  if (ND::TGeomInfo::FGD().IsInFGD1((*hit)->GetPosition()))
5683  gHit =
5684  new ((*bin->FGD1Unused)[bin->NFGD1Unused++]) TGlobalHit;
5685  else if (ND::TGeomInfo::FGD().IsInFGD2((*hit)->GetPosition()))
5686  gHit =
5687  new ((*bin->FGD2Unused)[bin->NFGD2Unused++]) TGlobalHit;
5688  else
5689  continue;
5690 
5691  FillGlobalHit(*hit, *gHit);
5692  }
5693  }
5694  }
5695  }
5696  }
5697  ND::THandle<ND::TReconObjectContainer> yz =
5698  tbResult->GetResultsContainer("yzUnmatchedFgdReconTracks");
5699  if (yz) {
5700  for (ND::TReconObjectContainer::iterator tt = yz->begin();
5701  tt != yz->end(); tt++) {
5702  ND::THandle<ND::TReconBase> object = *tt;
5703  if (object) {
5704  ND::THandle<ND::THitSelection> hits = object->GetHits();
5705  if (hits) {
5706  for (ND::THitSelection::iterator hit = hits->begin();
5707  hit != hits->end(); hit++) {
5708  TGlobalHit* gHit = NULL;
5709  if (ND::TGeomInfo::FGD().IsInFGD1((*hit)->GetPosition()))
5710  gHit =
5711  new ((*bin->FGD1Unused)[bin->NFGD1Unused++]) TGlobalHit;
5712  else if (ND::TGeomInfo::FGD().IsInFGD2((*hit)->GetPosition()))
5713  gHit =
5714  new ((*bin->FGD2Unused)[bin->NFGD2Unused++]) TGlobalHit;
5715  else
5716  continue;
5717 
5718  FillGlobalHit(*hit, *gHit);
5719  }
5720  }
5721  }
5722  }
5723  }
5724 
5725  // Cumulative result for all time bins
5726  fNFGD1Unused += bin->NFGD1Unused;
5727  fNFGD2Unused += bin->NFGD2Unused;
5728 
5729  ND::THandle<ND::THitSelection> tbHits = tbResult->GetHitSelection("fgd");
5730  if (tbHits) {
5731  // Extract FGD1 and FGD2 hits
5732  ND::THitSelection hits[2];
5733 
5734  TVector3 chargeSum[2];
5735  for (ND::THitSelection::iterator hit = tbHits->begin();
5736  hit != tbHits->end(); hit++) {
5737  // Fill the information about individual FGD hit
5738  double charge = (*hit)->GetCharge();
5739  TVector3 pos = (*hit)->GetPosition();
5740  int layer = ND::TGeomInfo::FGD().ActivePlane(pos.Z());
5741  float hit_pos = 0;
5742 
5743  // Only need to store on coordinate, since these are 2D hits
5744  if ((*hit)->IsXHit()) {
5745  hit_pos = pos.X();
5746  } else {
5747  hit_pos = pos.Y();
5748  }
5749 
5750  float time = (*hit)->GetTime();
5751 
5752  // Save separate information for FGD1 and FGD2
5753  if (ND::TGeomInfo::FGD().IsInFGD1(pos)) {
5754  bin->FGD1HitLayer.push_back(layer);
5755  bin->FGD1HitPosition.push_back(hit_pos);
5756  bin->FGD1HitQ.push_back(charge);
5757  bin->FGD1HitT.push_back(time);
5758  ND::THitSelection thisHit;
5759  thisHit.push_back(*hit);
5760  bin->FGD1HitTrajID.push_back(
5761  TrackTruthInfo::GetG4TrajIDHits(thisHit));
5762  } else {
5763  bin->FGD2HitLayer.push_back(layer);
5764  bin->FGD2HitPosition.push_back(hit_pos);
5765  bin->FGD2HitQ.push_back(charge);
5766  bin->FGD2HitT.push_back(time);
5767  ND::THitSelection thisHit;
5768  thisHit.push_back(*hit);
5769  bin->FGD2HitTrajID.push_back(
5770  TrackTruthInfo::GetG4TrajIDHits(thisHit));
5771  }
5772  // Finished filling information on individual FGD hits
5773 
5774  TVector3 isHit((*hit)->IsXHit(), (*hit)->IsYHit(), (*hit)->IsZHit());
5775  // std::cout << "isHit = (" << isHit.X() << "," << isHit.Y() <<
5776  //"," << isHit.Z() << ")" << std::endl;
5777  bool isInFgd[2];
5778  isInFgd[0] = ND::TGeomInfo::FGD().IsInFGD1((*hit)->GetPosition());
5779  isInFgd[1] = ND::TGeomInfo::FGD().IsInFGD2((*hit)->GetPosition());
5780  for (int ifgd = 0; ifgd < 2; ifgd++) {
5781  // std::cout << "isInFgd[" << ifgd << "] = " << isInFgd[ifgd]
5782  //<< std::endl;
5783  if (isInFgd[ifgd]) {
5784  hits[ifgd].push_back(*hit);
5785  bin->rawChargeSum[ifgd] += (*hit)->GetCharge();
5786 
5787  // Fill chargePerLayer
5788  ND::TGeometryId geomId = (*hit)->GetGeomId();
5789  int xory = ND::TGeomInfo::FGD().GetXorY(geomId);
5790  int module = ND::TGeomInfo::FGD().GetModule(geomId);
5791  int layer = module * 2 + xory;
5792  bin->chargePerLayer[ifgd][layer] += (*hit)->GetCharge();
5793  // std::cout << "Z, XorY, Module, Layer = " << pos.Z() << ", "
5794  // <<
5795  // xory << ", " << module << ", " << layer << std::endl;
5796 
5797  for (int ix = 0; ix < 3; ix++) {
5798  if (isHit(ix)) {
5799  // std::cout << "filling hit for component " << ix <<
5800  //" in FGD" << ifgd+1 << std::endl;
5801  bin->chargeWeightedPos[ifgd](ix) += charge * pos(ix);
5802  chargeSum[ifgd](ix) += charge;
5803  }
5804  }
5805  }
5806  }
5807  }
5808 
5809  for (int ifgd = 0; ifgd < 2; ifgd++) {
5810  for (int ix = 0; ix < 3; ix++) {
5811  if (chargeSum[ifgd](ix) > 1.e-3) {
5812  bin->chargeWeightedPos[ifgd](ix) *= 1. / chargeSum[ifgd](ix);
5813  } else {
5814  bin->chargeWeightedPos[ifgd](ix) = -1.e-10;
5815  }
5816  }
5817  bin->nHits[ifgd] = hits[ifgd].size();
5818  }
5819 
5820  // Fill outermost hits for this time bin
5821  double charge_cut = 0;
5822  FillOutermostHits(hits[0], charge_cut, bin->FGD1OutermostHits);
5823  FillOutermostHits(hits[1], charge_cut, bin->FGD2OutermostHits);
5824 
5825  if (isMC)
5826  bin->g4ID = TrackTruthInfo::GetG4TrajIDHits(*tbHits);
5827  else
5828  bin->g4ID = 0;
5829  }
5830  }
5831  }
5832 }
5833 
5834 // Helper method
5835 // Get the median FGD hit time for this track.
5836 //*************************************************************
5838  ND::THandle<ND::TReconBase> object)
5839 {
5840  //*************************************************************
5841  std::vector<double> times;
5842  ND::THandle<ND::THitSelection> hits = object->GetHits();
5843  if (hits)
5844  {
5845  // make a vector of all the times for the 'good' hits
5846  for (ND::THitSelection::iterator hit = (hits)->begin();
5847  hit != (hits)->end(); hit++)
5848  {
5849  if ((ND::TGeomInfo::FGD().IsInFGD1((*hit)->GetPosition()) ||
5850  ND::TGeomInfo::FGD().IsInFGD2((*hit)->GetPosition()))) {
5851  times.push_back((*hit)->GetTime());
5852  }
5853  }
5854  }
5855  std::sort(times.begin(), times.end());
5856 
5857  unsigned len = times.size();
5858 
5859  if (len == 0)
5860  // return 0.0;
5861  return DEFAULT_MIN;
5862  else if (len % 2 != 0) {
5863  return times[(len - 1) / 2];
5864  }
5865 
5866  ND280Debug(" end median track ");
5867 
5868  return (times[len / 2] + times[len / 2 - 1]) / 2.0;
5869 }
5870 
5871 //*************************************************************
5872 void ND::TGlobalReconModule::GetFGDSimpleVA(ND::TND280Event& event,
5873  ND::THandle<ND::TReconBase>& object,
5874  TLorentzVector& vertexPos,
5875  int globpass, int vaea)
5876 {
5877  //*************************************************************
5878 
5879  // time bin loop - match reco. time bin to track to get associated fgd hit
5880  // selection
5881  int fgdRecoBinIndex = -1;
5882  if (!fgdUtils::GetTrackRecoTimeBinIndex(event, object, fgdRecoBinIndex))
5883  return;
5884 
5885  ND::THandle<ND::TAlgorithmResult> binRecon =
5886  fgdUtils::getTimeBinResult(event, fgdRecoBinIndex);
5887  if (!binRecon) return;
5888 
5889  ND::THandle<ND::THitSelection> fgdHits = binRecon->GetHitSelection("fgd");
5890  if (!fgdHits) return;
5891 
5892  // run vertex activity measurement on track
5893  fgdUtils::SimpleVertexActivity(0, fgdHits, object, vertexPos, globpass, vaea);
5894 
5895  return;
5896 }
5897 
5898 //*************************************************************
5899 void ND::TGlobalReconModule::FillTPCPID(ND::THandle<ND::TReconBase> object)
5900 {
5901  //*************************************************************
5902 
5903  unsigned int dets = GetDetectorNumber(object);
5904 
5905  // create a new TGlobalPID
5906  TTpcPID* tpcObject = new ((*fTPCPIDs)[fNTPCPIDs++]) TTpcPID;
5907 
5908  // Fill the true particle when it is found
5909  double pur, eff;
5910  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*object, pur, eff);
5911  FillTrueParticle(G4track, pur, eff, tpcObject->TrueParticle);
5912 
5913  // extrapolate to the vertex (True vertex for the moment !!!!)
5914  tpcObject->PositionAtTrueVertex =
5915  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5916  tpcObject->PositionVarAtTrueVertex =
5917  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5918  tpcObject->DirectionAtTrueVertex =
5919  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5920  //------- copy information from TReconPID to TGlobalPID --------
5921 
5922  tpcObject->AlgorithmName = object->GetAlgorithmName();
5923  tpcObject->Status = object->CheckStatus(object->kSuccess);
5924  tpcObject->Chi2 = object->GetQuality();
5925  tpcObject->NDOF = object->GetNDOF();
5926  tpcObject->NNodes = object->GetNodes().size();
5927  tpcObject->Detectors = dets;
5928 
5929  tpcObject->NHits = DEFAULT_MAX;
5930  if (object->GetHits()) tpcObject->NHits = object->GetHits()->size();
5931 
5932  // The number of constituents. For composite objects
5933  tpcObject->NConstituents = 0;
5934  if (object->GetConstituents())
5935  tpcObject->NConstituents = object->GetConstituents()->size();
5936 
5937  tpcObject->isForward = (TrackingUtils::GetDirection(object).Z() > 0);
5938  tpcObject->MomentumAtTrueVertex = TrackingUtils::GetMomentum(object);
5939  tpcObject->MomentumErrorAtTrueVertex =
5940  TrackingUtils::GetMomentumError(object);
5941  tpcObject->Charge = TrackingUtils::GetCharge(object);
5942  tpcObject->EDeposit = TrackingUtils::GetEDeposit(object);
5943  tpcObject->Width =
5944  TrackingUtils::GetWidth(object).X(); //! take only the first component
5945  tpcObject->Cone = TrackingUtils::GetCone(object);
5946  tpcObject->Length = DEFAULT_MAX;
5947 
5948  // Set the PID back and front position, variance, direction and momentum
5949  ND::THandle<ND::TReconState> firstState =
5950  TrackingUtils::GetFirstState(*object);
5951  if (firstState) {
5952  tpcObject->FrontPosition = TrackingUtils::GetPosition(firstState);
5953  tpcObject->FrontPositionVar =
5954  TrackingUtils::GetPositionVariance(firstState);
5955  tpcObject->FrontDirection = TrackingUtils::GetDirection(firstState);
5956  tpcObject->FrontDirectionVar =
5957  TrackingUtils::GetDirectionVariance(firstState);
5958  tpcObject->FrontMomentum = TrackingUtils::GetMomentum(firstState);
5959  tpcObject->FrontMomentumError = TrackingUtils::GetMomentumError(firstState);
5960  } else {
5961  tpcObject->FrontPosition =
5962  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5963  tpcObject->FrontPositionVar =
5964  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5965  tpcObject->FrontDirection = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5966  tpcObject->FrontDirectionVar =
5967  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5968  tpcObject->FrontMomentum = DEFAULT_MAX;
5969  tpcObject->FrontMomentumError = DEFAULT_MAX;
5970  }
5971 
5972  ND::THandle<ND::TReconState> lastState = TrackingUtils::GetLastState(*object);
5973  if (lastState) {
5974  tpcObject->BackPosition = TrackingUtils::GetPosition(lastState);
5975  tpcObject->BackPositionVar = TrackingUtils::GetPositionVariance(lastState);
5976  tpcObject->BackDirection = TrackingUtils::GetDirection(lastState);
5977  tpcObject->BackDirectionVar =
5978  TrackingUtils::GetDirectionVariance(lastState);
5979  tpcObject->BackMomentum = TrackingUtils::GetMomentum(lastState);
5980  tpcObject->BackMomentumError = TrackingUtils::GetMomentumError(lastState);
5981  } else {
5982  tpcObject->BackPosition =
5983  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5984  tpcObject->BackPositionVar =
5985  TLorentzVector(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5986  tpcObject->BackDirection = TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5987  tpcObject->BackDirectionVar =
5988  TVector3(DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX);
5989  tpcObject->BackMomentum = DEFAULT_MAX;
5990  tpcObject->BackMomentumError = DEFAULT_MAX;
5991  }
5992 
5993  // Set the PID information
5994  ND::THandle<ND::TReconPID> PID = object;
5995  if (PID) {
5996  tpcObject->Likelihoods.push_back(PID->GetPIDWeight());
5997  ND::TReconObjectContainer::const_iterator it;
5998  for (it = PID->GetAlternates().begin(); it != PID->GetAlternates().end();
5999  it++) {
6000  ND::THandle<ND::TReconPID> alter = *it;
6001  tpcObject->Likelihoods.push_back(alter->GetPIDWeight());
6002  }
6003  }
6004 }
6005 
6006 //*****************************************************
6007 ND::THandle<ND::TG4Trajectory> ND::TGlobalReconModule::GetG4Trajectory(
6008  const ND::TReconBase& object, double& purity, double& eff)
6009 {
6010  //*****************************************************
6011 
6012  purity = -0xABCDEF;
6013  eff = -0xABCDEF;
6014 
6015  // std::cout<<"****** GET ASSOCIATE TRAJECTORY TO THE TRACK ******
6016  // "<<std::endl;
6017  ND::TG4Trajectory traj;
6018  ND::THandle<ND::THitSelection> hits = object.GetHits();
6019  if (!hits) {
6020  return ND::THandle<ND::TG4Trajectory>();
6021  }
6022  if (hits->size() < 1) {
6023  return ND::THandle<ND::TG4Trajectory>();
6024  }
6025 
6026  int G4TrkId = TrackTruthInfo::GetG4TrajIDHits(*hits, eff, purity);
6027  const ND::TND280Event& event = *(ND::TEventFolder::GetCurrentEvent());
6028  ND::THandle<ND::TG4TrajectoryContainer> G4trajectories =
6029  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
6030  if (!G4trajectories) {
6031  return ND::THandle<ND::TG4Trajectory>();
6032  }
6033  ND::TG4TrajectoryContainer::iterator trajIter = G4trajectories->begin();
6034  ND::TG4TrajectoryContainer::iterator trajEnd = G4trajectories->end();
6035  for (; trajIter != trajEnd; ++trajIter) {
6036  ND::TG4Trajectory* trajectory = &(trajIter->second);
6037  if (trajectory->GetTrackId() == G4TrkId) {
6038  ND::THandle<ND::TG4Trajectory> traj(new ND::TG4Trajectory((*trajectory)));
6039  return traj;
6040  }
6041  }
6042 
6043  return ND::THandle<ND::TG4Trajectory>();
6044 }
6045 
6046 //*****************************************************
6047 void ND::TGlobalReconModule::UpdateCoincidences(ND::THandle<ND::TMCHit> mch,
6048  ND::TMCDigit* mcd,
6049  std::vector<int>& coinc,
6050  int& nhits)
6051 {
6052  //*****************************************************
6053 
6054  std::vector<TG4VHit*> contrib;
6055  if (mch)
6056  contrib = mch->GetContributors();
6057  else if (mcd)
6058  contrib = mcd->GetContributors();
6059  else
6060  return;
6061 
6062  // std::cout << "loop over hit contribuitors" << std::endl;
6063  for (std::vector<ND::TG4VHit*>::const_iterator h = contrib.begin();
6064  h != contrib.end(); ++h) {
6065  if (!*h) continue;
6066  ND::TG4HitSegment* g4hitseg = dynamic_cast<ND::TG4HitSegment*>(*h);
6067  if (g4hitseg != NULL) {
6068  for (unsigned int i = 0; i != g4hitseg->GetContributors().size(); ++i) {
6069  unsigned int vv = g4hitseg->GetContributors()[i];
6070  if (vv >= coinc.size()) coinc.resize(vv + 1);
6071  coinc[vv]++;
6072  nhits++;
6073  }
6074  }
6075  }
6076 }
6077 
6078 //*****************************************************
6079 ND::THandle<ND::TG4Trajectory> ND::TGlobalReconModule::GetMainContributor(
6080  ND::THandle<ND::TMCHit> mch,
6081  ND::THandle<ND::TG4TrajectoryContainer> trajectories)
6082 {
6083  //*****************************************************
6084 
6085  if (!mch) return ND::THandle<ND::TG4Trajectory>();
6086  if (!trajectories) return ND::THandle<ND::TG4Trajectory>();
6087 
6088  std::vector<int> coinc;
6089  coinc.resize(trajectories->size());
6090 
6091  // std::cout << "loop over hit contribuitors" << std::endl;
6092  for (std::vector<ND::TG4VHit*>::const_iterator h =
6093  (mch->GetContributors()).begin();
6094  h != (mch->GetContributors()).end(); ++h) {
6095  if (!*h) continue;
6096  ND::TG4HitSegment* g4hitseg = dynamic_cast<ND::TG4HitSegment*>(*h);
6097  if (g4hitseg != NULL) {
6098  for (unsigned int i = 0; i != g4hitseg->GetContributors().size(); ++i) {
6099  unsigned int vv = g4hitseg->GetContributors()[i];
6100  if (vv >= coinc.size()) coinc.resize(vv + 1);
6101  coinc[vv]++;
6102  }
6103  }
6104  }
6105 
6106  int maxim = 0;
6107  int imax = -1;
6108  for (unsigned int i = 0; i < coinc.size(); i++) {
6109  if (coinc[i] > maxim) {
6110  maxim = coinc[i];
6111  imax = i;
6112  }
6113  }
6114 
6115  if (imax >= 0) {
6116  ND::THandle<ND::TG4Trajectory> traj(
6117  new ND::TG4Trajectory((*trajectories)[imax]));
6118  return traj;
6119  }
6120 
6121  return ND::THandle<ND::TG4Trajectory>();
6122 }
6123 
6124 //*****************************************************
6126  const ND::THitSelection& hits, ND::THandle<ND::TG4Trajectory> traj,
6127  ND::THitSelection& traj_hits)
6128 {
6129  //*****************************************************
6130 
6131  if (!traj) return;
6132 
6133  const ND::TND280Event& event = *(ND::TEventFolder::GetCurrentEvent());
6134  ND::THandle<ND::TG4TrajectoryContainer> trajectories =
6135  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
6136 
6137  if (!trajectories) return;
6138 
6139  // Loop over reconstructed hits
6140  for (ND::THitSelection::const_iterator ht = hits.begin(); ht != hits.end();
6141  ht++) {
6142  ND::THandle<ND::TComboHit> ch(*ht);
6143  if (ch) {
6144  // Loop over hits in Combo
6145  for (ND::THitSelection::const_iterator ch_member = ch->GetHits().begin();
6146  ch_member != ch->GetHits().end(); ++ch_member) {
6147  // Get monte Carlo hit associated.
6148  ND::THandle<ND::TMCHit> mch;
6149  ND::THandle<ND::TMultiHit> mhit = *ch_member;
6150  if (mhit)
6151  mch = *(mhit->begin());
6152  else
6153  mch = *ch_member;
6154 
6155  ND::THandle<ND::TG4Trajectory> mainCont =
6156  GetMainContributor(mch, trajectories);
6157  if (mainCont)
6158  if (GetPointer(mainCont) == GetPointer(traj))
6159  traj_hits.push_back(mch);
6160  }
6161  } else {
6162  ND::THandle<ND::TMultiHit> mhit = *ht;
6163  ND::THandle<ND::TMCHit> mch;
6164 
6165  if (mhit)
6166  mch = *(mhit->begin());
6167  else
6168  mch = *ht;
6169 
6170  ND::THandle<ND::TG4Trajectory> mainCont =
6171  GetMainContributor(mch, trajectories);
6172  if (mainCont)
6173  if (GetPointer(mainCont) == GetPointer(traj)) traj_hits.push_back(mch);
6174  }
6175  }
6176 }
6177 
6178 //*****************************************************
6180  ND::THandle<ND::TReconBase> object)
6181 {
6182  //*****************************************************
6183 
6184  std::string reco_class_name = "";
6185 
6186  ND::THandle<ND::TReconObjectContainer> conContainer =
6187  object->GetConstituents();
6188  if (conContainer) {
6189  ND::THandle<ND::TReconBase> object2 = *(conContainer->begin());
6190  if (object2) reco_class_name = object2->ClassName();
6191  }
6192 
6193  return reco_class_name;
6194 }
6195 
6196 //*****************************************************
6197 bool ND::TGlobalReconModule::IsTrackLike(ND::THandle<ND::TReconBase> object)
6198 {
6199  //*****************************************************
6200 
6201  ND::THandle<ND::TReconObjectContainer> conContainer =
6202  object->GetConstituents();
6203 
6204  if (!conContainer) return true;
6205 
6206  if (conContainer->size() > 1) return true;
6207 
6208  ND::THandle<ND::TReconBase> object2 = *(conContainer->begin());
6209  if (!object2) return true;
6210 
6211  std::string reco_class_name = object2->ClassName();
6212 
6213  if (reco_class_name.find("ND::TReconPID") != std::string::npos ||
6214  reco_class_name.find("ND::TReconTrack") != std::string::npos)
6215  return true;
6216  else
6217  return false;
6218 }
6219 
6220 //*****************************************************************************
6222  ND::THandle<ND::TReconBase> t1, ND::TReconObjectContainer& trackerObjects)
6223 {
6224  //*****************************************************************************
6225 
6226  // check if this object is tracker only. If so add it
6227  if (IsTrackerOnly(t1)) {
6228  trackerObjects.push_back(t1);
6229  return;
6230  }
6231 
6232  ND::THandle<ND::TReconObjectContainer> t1const = t1->GetConstituents();
6233  if (!t1const) return;
6234 
6235  // loop over constituents
6236  ND::TReconObjectContainer::const_iterator it1;
6237  for (it1 = t1const->begin(); it1 != t1const->end(); it1++) {
6238  ND::THandle<ND::TReconBase> object = *it1;
6239  if (!object) continue;
6240  GetConstituentsInTracker(object, trackerObjects);
6241  }
6242 }
6243 
6244 //*****************************************************************************
6245 bool ND::TGlobalReconModule::IsTrackerOnly(ND::THandle<ND::TReconBase> t1)
6246 {
6247  //*****************************************************************************
6248 
6249  if (t1->UsesDetector(ND::TReconBase::kP0D) ||
6250  t1->UsesDetector(ND::TReconBase::kDSECal) ||
6251  t1->UsesDetector(ND::TReconBase::kECal) ||
6252  t1->UsesDetector(ND::TReconBase::kSMRD)) {
6253  return false;
6254  }
6255 
6256  return true;
6257 }
6258 
6259 //*****************************************************************************
6261  const ND::TReconObjectContainer& globalObjects,
6262  const ND::TReconObjectContainer& trackerObjects)
6263 {
6264  //*****************************************************************************
6265 
6266  // 1. loop over all global objects
6267  for (ND::TReconObjectContainer::const_iterator tt = globalObjects.begin();
6268  tt != globalObjects.end(); tt++) {
6269  ND::THandle<ND::TReconBase> gobject = *tt;
6270  if (!gobject) continue;
6271 
6272  // 2. Get the tracker objects in the global object
6273  ND::TReconObjectContainer trackerObjects2;
6274  GetConstituentsInTracker(gobject, trackerObjects2);
6275 
6276  // 3. loop over tracker objects in the global object
6277  for (ND::TReconObjectContainer::iterator tt2 = trackerObjects2.begin();
6278  tt2 != trackerObjects2.end(); tt2++) {
6279  ND::THandle<ND::TReconBase> tobject2 = *tt2;
6280  if (!tobject2) continue;
6281 
6282  // 4. loop over objects from trackerRecon
6283  for (ND::TReconObjectContainer::const_iterator tt1 =
6284  trackerObjects.begin();
6285  tt1 != trackerObjects.end(); tt1++) {
6286  ND::THandle<ND::TReconBase> tobject1 = *tt1;
6287  if (!tobject1) continue;
6288 
6289  // 5. Associate the tracker object in the global object with the
6290  // trackerRecon object
6291  if (fabs(tobject1->GetQuality() - tobject2->GetQuality()) < 1e-6 &&
6292  tobject1->GetDetectors() == tobject2->GetDetectors()) {
6293  // this is the link between a trackerRecon object and a global
6294  // object
6295  // index
6296  fTrackerGlobalIndexMap[tobject1] = fGlobalIndexMap[gobject];
6297  break;
6298  }
6299  }
6300  }
6301  }
6302 }
6303 
6304 
6305 
6306 //*****************************************************************************
6307 ND::THandle<ND::TReconBase>
6309  ND::THandle<ND::TReconBase> object)
6310 {
6311  //*****************************************************************************
6312 
6313  ND::THandle<ND::TReconBase> trackerIsoObject;
6314  if (!object->UsesDetector(ND::TReconBase::kFGD) ||
6315  object->UsesDetector(ND::TReconBase::kTPC) ||
6316  object->UsesDetector(ND::TReconBase::kECal) ||
6317  object->UsesDetector(ND::TReconBase::kDSECal) ||
6318  object->UsesDetector(ND::TReconBase::kP0D) ||
6319  object->UsesDetector(ND::TReconBase::kSMRD)) {
6320  return trackerIsoObject;
6321  }
6322 
6323  bool printStuff = true;
6324  double objecttime = -1.e10;
6325  ND::THandle<ND::TReconObjectContainer> cons = object->GetConstituents();
6326  int ncons = cons->size();
6327  if (printStuff) {
6328  std::cout << "Found an FGD-only track" << std::endl;
6329  if (cons) {
6330  std::cout << " and has " << ncons << " constituents" << std::endl;
6331  } else {
6332  std::cout << " and has no constituents" << std::endl;
6333  }
6334  }
6335  ND::THandle<ND::TReconTrack> track = object;
6336  ND::THandle<ND::TReconPID> pid = object;
6337  if (track) {
6338  if (printStuff) std::cout << " object is a track" << std::endl;
6339  objecttime = track->GetPosition().T();
6340  } else if (pid) {
6341  if (printStuff) std::cout << " object is a PID" << std::endl;
6342  objecttime = pid->GetPosition().T();
6343  } else {
6344  std::cout << "Not a track or a PID?" << std::endl;
6345  }
6346  if (printStuff) {
6347  std::cout << "object time is " << objecttime << std::endl;
6348  for (int i = 0; i < ncons; i++) {
6349  std::cout << "cons " << i << " detectors: P"
6350  << (*cons)[i]->UsesDetector(ND::TReconBase::kP0D) << " T"
6351  << (*cons)[i]->UsesDetector(ND::TReconBase::kTPC1)
6352  << (*cons)[i]->UsesDetector(ND::TReconBase::kFGD1)
6353  << (*cons)[i]->UsesDetector(ND::TReconBase::kTPC2)
6354  << (*cons)[i]->UsesDetector(ND::TReconBase::kFGD2)
6355  << (*cons)[i]->UsesDetector(ND::TReconBase::kTPC3) << " E"
6356  << (*cons)[i]->UsesDetector(ND::TReconBase::kECal)
6357  << (*cons)[i]->UsesDetector(ND::TReconBase::kDSECal) << " S"
6358  << (*cons)[i]->UsesDetector(ND::TReconBase::kSMRD) << std::endl;
6359  }
6360  }
6361 
6362  // Find corresponding PID in trackerRecon "final" container
6363  ND::THandle<ND::TAlgorithmResult> trackerRecon =
6364  ND::TEventFolder::GetCurrentEvent()->GetFit("trackerRecon");
6365  if (trackerRecon) {
6366  // Get the results from reconstruction
6367  ND::THandle<ND::TReconObjectContainer> trackerObjects =
6368  trackerRecon->GetResultsContainer("final");
6369 
6370  if (trackerObjects) {
6371  for (ND::TReconObjectContainer::iterator tt = trackerObjects->begin();
6372  tt != trackerObjects->end(); tt++) {
6373  if ((*tt)->UsesDetector(ND::TReconBase::kFGD) &&
6374  !(*tt)->UsesDetector(ND::TReconBase::kTPC)) {
6375  ND::THandle<ND::TReconTrack> track = *tt;
6376  ND::THandle<ND::TReconPID> pid = *tt;
6377  double fgdtime = -1.e10;
6378  if (track) {
6379  std::cout << " fgd object is a track?!?!?!?" << std::endl;
6380  fgdtime = track->GetPosition().T();
6381  } else if (pid) {
6382  if (printStuff) std::cout << " fgd object is a PID" << std::endl;
6383  fgdtime = pid->GetPosition().T();
6384  } else {
6385  std::cout << "fgd not a track or a PID?" << std::endl;
6386  }
6387  if (printStuff)
6388  std::cout << "fgd object time is " << fgdtime << std::endl;
6389  if (fabs(fgdtime - objecttime) < 1.e-3) {
6390  if (printStuff) std::cout << "replacing..." << std::endl;
6391  trackerIsoObject = *tt;
6392  break;
6393  }
6394  } else {
6395  if (printStuff) std::cout << "---no TPC component" << std::endl;
6396  }
6397  }
6398  } else {
6399  std::cout
6400  << "Why doesn't trackerRecon final results container exist?!?!?!?!?"
6401  << std::endl;
6402  }
6403  } else {
6404  std::cout << "Why doesn't trackerRecon result exist?!?!?!?!? " << std::endl;
6405  }
6406  if (!trackerIsoObject && printStuff) {
6407  std::cout
6408  << "!!!!!!!!!!!!!!!! ERROR: FGD-only object NOT found!!!!!!!!!!!!!!!"
6409  << std::endl;
6410  }
6411 
6412  return trackerIsoObject;
6413 }
6414 
6415 //*****************************************************************************
6417  const ND::TReconObjectContainer& globalObjects)
6418 {
6419  //*****************************************************************************
6420 
6421  // This function find the right links between broken tracks
6422 
6423  // clear the map from the previous event
6424  fBrokenIndexMap.clear();
6425 
6426  // map of uniqueIDs for the actual broken tracks
6427  std::map<ND::THandle<ND::TReconBase>, std::vector<UInt_t> > brokenMap1;
6428 
6429  // map of uniqueIDs for the tracks associated to a broken track
6430  std::map<ND::THandle<ND::TReconBase>, std::vector<UInt_t> > brokenMap2;
6431 
6432  // loop over global objects
6433  for (ND::TReconObjectContainer::const_iterator tt = globalObjects.begin();
6434  tt != globalObjects.end(); tt++) {
6435  ND::THandle<ND::TReconBase> object = *tt;
6436  if (!object) continue;
6437 
6438  // get the broken IDs recursively
6439  std::vector<UInt_t> brokenIDs1;
6440  std::vector<UInt_t> brokenIDs2;
6441  bool found = GetBrokenIDs(object, brokenIDs1, brokenIDs2);
6442 
6443  // if this track is broken fill the maps
6444  if (found) {
6445  brokenMap1[object] = brokenIDs1;
6446  brokenMap2[object] = brokenIDs2;
6447 
6448  if (debug_broken) {
6449  std::cout << " - " << object->GetUniqueID() << " " << object
6450  << std::endl;
6451  std::cout << " --> broken IDs1: ";
6452  for (unsigned int i = 0; i < brokenIDs1.size(); i++) {
6453  std::cout << " " << brokenIDs1[i];
6454  }
6455  std::cout << std::endl;
6456  std::cout << " --> broken IDs2: ";
6457  for (unsigned int i = 0; i < brokenIDs2.size(); i++) {
6458  std::cout << " " << brokenIDs2[i];
6459  }
6460  std::cout << std::endl;
6461  }
6462  }
6463  }
6464 
6465  // now do the actual association
6466  std::map<ND::THandle<ND::TReconBase>, std::vector<UInt_t> >::const_iterator
6467  tt1;
6468  std::map<ND::THandle<ND::TReconBase>, std::vector<UInt_t> >::const_iterator
6469  tt2;
6470  for (tt1 = brokenMap1.begin(); tt1 != brokenMap1.end(); tt1++) {
6471  ND::THandle<ND::TReconBase> object1 = tt1->first;
6472  if (!object1) continue;
6473 
6474  const std::vector<UInt_t>& brokenIDs1 = tt1->second;
6475 
6476  std::vector<UInt_t> brokenIDsFinal;
6477  bool found = false;
6478  // does any of the brokenIDs of this object exist as a independent global
6479  // object ?
6480  for (tt2 = brokenMap2.begin(); tt2 != brokenMap2.end(); tt2++) {
6481  ND::THandle<ND::TReconBase> object2 = tt2->first;
6482  if (!object2) continue;
6483 
6484  const std::vector<UInt_t>& brokenIDs2 = tt2->second;
6485 
6486  for (unsigned int i = 0; i < brokenIDs1.size(); i++) {
6487  for (unsigned int j = 0; j < brokenIDs2.size(); j++) {
6488  if (brokenIDs1[i] == brokenIDs2[j]) {
6489  brokenIDsFinal.push_back(object2->GetUniqueID());
6490  found = true;
6491  break;
6492  }
6493  }
6494  if (found) break;
6495  }
6496  if (found) break;
6497  }
6498 
6499  // fill the map with top level association
6500  if (found) {
6501  fBrokenIndexMap[object1] = brokenIDsFinal;
6502 
6503  if (debug_broken) {
6504  std::cout << " - " << object1->GetUniqueID() << " " << object1
6505  << std::endl;
6506  std::cout << " --> broken IDs FINAL: ";
6507  for (unsigned int i = 0; i < brokenIDsFinal.size(); i++) {
6508  std::cout << " " << brokenIDsFinal[i];
6509  }
6510  std::cout << std::endl;
6511  }
6512  }
6513  }
6514 }
6515 
6516 //*****************************************************************************
6517 bool ND::TGlobalReconModule::GetBrokenIDs(ND::THandle<ND::TReconBase> object,
6518  std::vector<UInt_t>& brokenIDs1,
6519  std::vector<UInt_t>& brokenIDs2)
6520 {
6521  //*****************************************************************************
6522 
6523  bool found = false;
6524 
6525  // get the broken IDs for this object
6526  ND::THandle<ND::TDataVector> broken =
6527  object->Get<ND::TDataVector>("brokenID");
6528  if (broken) {
6529  brokenIDs1.push_back(object->GetUniqueID());
6530  found = true;
6531  for (unsigned int i = 0; i < broken->size(); i++) {
6532  UInt_t ID = broken->At<ND::TIntegerDatum>(i)->GetValue();
6533  brokenIDs2.push_back(ID);
6534  }
6535  }
6536 
6537  // Get The BrokenIDs for the original object
6538  if (ReconObjectUtils::GetOriginalObject(object)) {
6539  found = GetBrokenIDs(ReconObjectUtils::GetOriginalObject(object),
6540  brokenIDs1, brokenIDs2);
6541  } else {
6542  // get the broken IDs for the constituents (only if the track has no
6543  // original object)
6544  ND::THandle<ND::TReconObjectContainer> cons = object->GetConstituents();
6545  if (!cons) return found;
6546 
6547  for (ND::TReconObjectContainer::const_iterator tt = cons->begin();
6548  tt != cons->end(); tt++) {
6549  // only for PID constituents
6550  ND::THandle<ND::TReconPID> object2 = *tt;
6551  if (!object2) continue;
6552 
6553  bool found2 = GetBrokenIDs(object2, brokenIDs1, brokenIDs2);
6554  if (found2) found = true;
6555  }
6556  }
6557 
6558  if (found) brokenIDs1.push_back(object->GetUniqueID());
6559 
6560  return found;
6561 }
6562 
6563 //*************************************************************
6565  TTrackerObject* result, ND::THandle<ND::TReconBase> reco)
6566 
6567 {
6568  //*************************************************************
6569 
6570  bool useFGD1 = reco->UsesDetector(ND::TReconBase::kFGD1);
6571  bool useFGD2 = reco->UsesDetector(ND::TReconBase::kFGD2);
6572 
6573  ND::THandle<ND::TReconBase> fgdCons;
6574  ND::THandle<ND::TReconPID> fgdPid;
6575  ND::THandle<ND::TReconTrack> fgdTrack;
6576 
6577  if (useFGD1) {
6578  fgdCons =
6579  ReconObjectUtils::GetConstituentInDetector(reco, ND::TReconBase::kFGD1);
6580 
6581  if (fgdCons) {
6582  fgdPid = fgdCons;
6583  if (fgdPid) {
6584  ND::TReconObjectContainer::const_iterator it =
6585  fgdPid->GetConstituents()->begin();
6586  fgdTrack = *it;
6587  }
6588  }
6589 
6590  if (fgdTrack && fgdTrack->Has<ND::TIntegerDatum>("matchingFailure_flag")) {
6591  result->matchingFailure_flag =
6592  fgdTrack->Get<ND::TIntegerDatum>("matchingFailure_flag")->GetValue();
6593 
6594  } else
6595  result->matchingFailure_flag = 0;
6596  }
6597 
6598  else if (useFGD2) {
6599  fgdCons =
6600  ReconObjectUtils::GetConstituentInDetector(reco, ND::TReconBase::kFGD2);
6601 
6602  if (fgdCons) {
6603  fgdPid = fgdCons;
6604  if (fgdPid) {
6605  ND::TReconObjectContainer::const_iterator it =
6606  fgdPid->GetConstituents()->begin();
6607  fgdTrack = *it;
6608  }
6609  }
6610 
6611  if (fgdTrack && fgdTrack->Has<ND::TIntegerDatum>("matchingFailure_flag"))
6612  result->matchingFailure_flag =
6613  fgdTrack->Get<ND::TIntegerDatum>("matchingFailure_flag")->GetValue();
6614  else
6615  result->matchingFailure_flag = 0;
6616  }
6617 
6618  else
6619  result->matchingFailure_flag = 0;
6620 
6621  return;
6622 }
Int_t fNP0DECAL
Number of objects containing the P0DECAL.
double PIDWeightMuon
PID weights for muon hypothesis.
void FillSMRDInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
const int NDETSUSED
double PullPion
The FGD PID pull value for a pion.
double PID_FrontBackRatio
The ratio of the charge in equal length blocks at each end of the track.
bool IsTrackLike(ND::THandle< ND::TReconBase > object)
double PIDWeightProt
PID weights for proton hypothesis.
void FillGlobalPIDAlternates(ND::THandle< ND::TG4Trajectory > G4track, ND::THandle< ND::TReconBase > object, TGlobalPID &globalObject)
void FillGlobalHit(ND::THandle< ND::THit > hit, TGlobalHit &gHit)
double dEdxexpMuon
Estimated dE/dx for muon hypothesis.
double Length
The length of the track or shower, its value depends on if the object is reconstructed as track-like ...
void GetConstituentsInTracker(ND::THandle< ND::TReconBase > t1, ND::TReconObjectContainer &trackerObjects)
int NHits
The number of constituent hits.
TVector3 BackDirection
The direction of the object.
int ExitOK[NDETSEXTRAP]
Status of the subdetector exit.
Int_t NECALs
Number of ECAL objects.
void FillP0DInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
double Quality
The quality of the fit.
double PID_Circularity
Pid Variables, For more info on the Pid variable see the documentation in ecalRecon or the technical ...
Int_t NTRACKERs
Number of Tracker objects.
double PID_LLR_EM_HIP
A combined discriminator for separating protons from electrons.
double RangeMomentumEndToTPCProton
the momentum by range for the proton hypothesis (from end to a TPC)
float chargePerLayer[2][30]
Summed hit charge for layer x in FGD1 (chargePerLayer[0][x]), and 2 (chargePerLayer[1][x]) ...
int ID
G4 Trajectory Id.
double PullMuon
The FGD PID pull value for a muon.
double PullElectron
The FGD PID pull value for an electron.
TLorentzVector Position
The position of the vertex.
TClonesArray * Constituents
Constituent tracks.
Int_t fNSMRDRightUnused
Number of hits unused in the SMRDRight.
const int NMAXTPCOTHER
An object to describe a reconstructed PID.
UInt_t UniqueID
Unique identifier for global recon objects (needed fro broken association)
double SigmaEle
Sigma estimated width of TPC pid electron hypothesis.
int NDOF
The number of degrees of freedom.
double fgdEA_verNextNextNearQ_rect
FGD end activity values.
TLorentzVector BackPosition
The position of the object.
double fgdVA_verNearQ
FGD vertex activity values.
double RangeMomentumEndToTPCPion
the momentum by range for the pion hypothesis (from end to a TPC)
double ExitMomentumErr[NDETSEXTRAP]
The error of the momentum of the object at the exit of each subdetector.
virtual void InitializeBranches()
Initialize Branches. Don&#39;t do anything else in this function.
double FrontMomentumError
the error on the momentum of the object
const bool debug_pids
double fgdVA_totalQ
FGD vertex activity values.
double Length
The length of the track or shower (RMS)
double PID_ShowerAngle
The angle from the start of an object to its width at its charge centre.
std::vector< int > fgdhits_TrajID
Vector to store the ID of the Trajectory that created the hit.
TClonesArray * FGD2Unused
The vector unused hits in FGD2.
std::vector< int > TPCGasPathIDs
The IDs of the TREx paths which contributed to the object.
TLorentzVector BackPosition
The position of the object.
std::vector< std::string > fALLMODULES
std::vector< float > SFGHitPositionX
Vector to store the Xposition of each hit in SFG.
double EMEnergyFit_Uncertainty
The uncertainty of the EM energy fit to the cluster.
TTrueParticle TrueParticle
The associated true particle.
double FrontMomentumError
The uncertainty on ND::TSubBaseObject::FrontMomentum.
double Chi2
The chi2 of the fit.
#define CVSID
Int_t NDsECALs
Number of DsECAL objects.
void FillUnusedHits(ND::TND280Event &event)
std::vector< float > SFGHitPositionY
Vector to store the Y position of each hit in SFG.
TLorentzVector PositionVarAtTrueVertex
The position variance at the true vertex.
const int NDETSEXTRAP
For questions or suggestions about this module please contact the current responsible and CC in the e...
Int_t NFGDs
Number of FGD objects.
double fgdEA_verNearQ_rect
FGD end activity values.
double FrontMomentum
The momentum measurement at the &#39;front&#39; of the object.
int g4ID
The ID for the G4 trajectory that contributed most to this time bin.
double RangeMomentumProton
the momentum by range for the proton hypothesis
virtual Bool_t ProcessFirstEvent(ND::TND280Event &event)
Is called after the first event is loaded in.
unsigned long Detectors
Detectors used, defined according to the formula in GetDetectorNumber.
Int_t NSFGUnused
Number of hits unused in SFG.
double SigmaPion
Sigma estimated width of TPC pid pion hypothesis.
double PID_LLR_MIP_EM_LowMomentum
A combined discriminator for separating MIPs from EM showers. This is similar to LLR_MIP_EM but train...
An object to describe a reconstructed PID.
TTrueParticle TrueParticle
The true particle.
double Chi2
The chi2 of the fit.
double ComputeTrackLength(ND::THandle< ND::TReconBase > object)
TClonesArray * fVertices
The TGlobalVertex vector of vertices.
TVector3 FrontDirection
The direction of the object.
bool SortNodesInXReverse(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
void FillDetectorUsed(ND::THandle< ND::TReconBase > object, bool dets[])
void SetDetectorUsed(unsigned long &BitField, ESubdetector det)
int NegPionBraggCut
Bragg peak cut (only used for SFGD contained tracks)
void FillTrueParticle(ND::THandle< ND::TG4Trajectory > G4track, double pur, double eff, ND::TTrueParticle &part)
void FillSfgTimeBins(ND::TND280Event &event)
double fgdVA_verQ
FGD vertex activity values.
TLorentzVector BackPosition
The position of the object.
int EntranceOK[NDETSEXTRAP]
Status of the subdetector entrance.
double fgdVA_verNextNearQ
FGD vertex activity values.
TLorentzVector BackPositionVar
The position variance;.
ClassImp(ND::TBeamSummaryDataModule::TBeamSummaryData)
TLorentzVector FrontPosition
The global coordinate position at the &#39;front&#39; of the object.
bool GetIncomingParticle(const ND::TG4PrimaryVertex &G4vertex, ND::TG4PrimaryParticle &incoming)
int GetTrackerDetectorNumber(ND::THandle< ND::TReconBase > object)
TVector3 DirectionVarAtTrueVertex
The direction variance at the true vertex.
double Eff
The efficiency for matching the rec particle with the true particle.
bool IsTrackerOnly(ND::THandle< ND::TReconBase > t1)
unsigned long Status
The status for the fit.
void FillFgdTimeBins(ND::TND280Event &event)
std::vector< int > TPCGasPatternIDs
Variables to get the association between the global track and the gas ouptut involved The vectorS of ...
TVector3 FrontDirection
The direction of the object.
Double_t ObjectLength
Recon object length in mm.
Int_t fNDsECAL
Number of objects containing the DsECAL.
double EMEnergyFit_Result
The result from the EM energy fit to the cluster.
An object to hold specific TPC variables.
std::vector< float > FGD1HitT
Vector to store the time of each hit in FGD1.
double BackMomentum
the momentum of the object
double MomentumAtTrueVertex
Momentum at the true vertex.
std::string fDescription
A longish descrition of the analysis.
TVector3 DirectionAtTrueVertex
Direction at the true vertex.
std::vector< float > FGD1HitPosition
Vector to store the X or Y position of each hit in FGD1.
std::map< ND::THandle< ND::TReconBase >, int > fTrackerGlobalIndexMap
int TrackType
Record of why the track was refit with a kalman filter fit instead of the likelihood fit...
std::vector< TVector3 > NodeDirVariance
Vector to store the variance on the direction of each node.
int PionBraggCut
Bragg peak cut (only used for SFGD contained tracks)
int CountDetector(ND::THandle< ND::TReconBase > object)
TLorentzVector Position
The position of the vertex.
Definition: TTrueVertex.hxx:18
bool GetTPCDatum(ND::THandle< ND::TReconBase > object, const std::string &datum, std::vector< I > &vector) const
A getter for TPC Datums to work both with TREx and TPC info.
Float_t TotalCharge
The total charge deposited by the track.
Int_t fNTPCOthers
The number of TPC other objects.
Int_t NSFGs
Number of SFG objects.
double RangeMomentumEndToTPCMuon
the momentum by range for the muon hypothesis (from end to a TPC)
double fgdEA_verQ
FGD end activity values.
double PID_TruncatedMaxRatio
A truncated Max Ratio. See ecalRecon docs for the full definition.
double BackMomentum
the momentum of the object
double avgtime
Averaged corrected node time.
std::vector< int > NodeNHits
Vector to store the number of hits contributing to each node.
std::vector< std::pair< unsigned long, TVector2 > > NodeTimes
vector of pairs, sub-detecor number and time-stamps of edge nodes in this subdetector ...
void CheckMatchingFailure(TTrackerObject *result, ND::THandle< ND::TReconBase > reco)
Method to find FGD constituent track from a matching object and fill matchingFailure_flag.
An object to hold specific TRACKER variables.
int ComputeParticleId(ND::THandle< ND::TReconPID > PID)
TClonesArray * fFgdTimeBins
Information for each hit time bin (TFgdTimeBins).
std::vector< float > SFGHitPositionZ
Vector to store the X or Y position of each hit in SFG.
Int_t fNP0D
Number of objects containing the P0D.
TLorentzVector ExitPosition[NDETSEXTRAP]
The position of the object at the exit of each subdetector.
void FillSFGInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
void FillTPCPID(ND::THandle< ND::TReconBase > object)
std::vector< TLorentzVector > HitPosition
The main object that contains ECAL recon information.
Int_t MostDownStreamLayerHit
The layer furthest from the tracker that was hit by the object. This is layer number 30 (the 31st lay...
TClonesArray * fP0DUnused
The vector unused hits in the P0D (TGlobalHit).
An object to store hit information for the SMRD subdetector.
double SigmaMuon
Sigma estimated width of TPC pid muon hypothesis.
TECALReconTrack Track
Objects to store information for a track.
double Length
The length of the track or shower (RMS)
double FrontCharge
the charge of the object at the first state
TClonesArray * HitsSaved
the two first and two last hits (TGlobalHit).
TClonesArray * TRACKER
Tracker specific variables.
double RangeMomentumMuonFlip
the momentum by range for the flipped muon hypothesis
const int NMAXTRACKER
void UpdateCoincidences(ND::THandle< ND::TMCHit > mch, ND::TMCDigit *mcdigit, std::vector< int > &coinc, int &nhits)
TLorentzVector FrontPosition
The position of the object.
const bool debug_kine
int NConstituents
The number of constituents.
double PullProton
Pull for TPC pid proton hypothesis.
double TrueE
True energy in an FGD.
TVector3 FrontDirectionVar
The direction variance of the object.
double SigmaKaon
Sigma estimated width of TPC pid kaon hypothesis.
bool fPassedDetector[NDETSEXTRAP]
const bool debug_vertex_extrap
unsigned long GetDetectorNumber(ND::THandle< ND::TReconBase > object)
void FillTPCObject(ND::THandle< ND::TReconBase > object, TTPCObject &sub, int det)
std::vector< float > FGD2HitT
Vector to store the time of each hit in FGD2.
Int_t fNTrECALIso
Number of objects in the TrECAL only.
Int_t fPVInd
The last primary vertex index.
double MomentumAtTrueVertex
The momentum at the true vertex.
Double_t AverageHitTime
Average time of hits in reconstructed object.
Int_t fNTPC
Number of objects containing the TPC.
TVector3 FrontDirection
The Front direction of the object.
TLorentzVector ExitPositionErr[NDETSEXTRAP]
The error of the position of the object at the exit of each subdetector.
int NConstituents
The number of constituents.
double Momentum
the momentum of the object
TClonesArray * fSfgTimeBins
Information for each hit time bin (TSfgTimeBins).
TLorentzVector Position
Position of the correspponding object.
TVector3 FrontDirection
The direction at the &#39;front&#39; of the object.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
std::vector< double > PIDWeight
The weights for the PID hypotheses, c.f. TP0DObject::ParticleId.
Int_t FrontLayerNumber
The front layer number (closest to the tracker) of the track.
double FrontMomentumError
the error on the momentum of the object
Int_t fNVertices
The number of added primary vertices.
TECALReconShower Shower
Objects to store information for a shower.
bool GetBrokenIDs(ND::THandle< ND::TReconBase > object, std::vector< UInt_t > &brokenIDs1, std::vector< UInt_t > &brokenIDs2)
const int DEFAULT_MIN
An object to store subdetector-agnostic hit information.
int Charge
Charge of the constituent track.
double PEField
Placeholder for momentum of EField refit.
void FillKinematics(ND::THandle< ND::TReconState > state, TLorentzVector &pos, TVector3 &dir, double &mom, double &momErr, double &charge, double(&cov)[7][7])
double sigmaE_pion
Expected energy uncertainty for a pion.
double MomentumAtTrueVertex
Momentum at the true vertex.
TVector3 chargeWeightedPos[2]
Charge weighted average hit position in FGD1 chargeWeightedPos[0]) and 2 (chargeWeightedPos[1]) ...
int ParticleId
the PDG code obtained in the recon combined PID
bool SortNodesInYReverse(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
double AverageZPosition
Unweighted average Z position of object-constituent hits.
double avgtime
Average fully corrected SFG hit time.
double PID_LLR_Quality
A quality flag for the likelihood PID variables. Good quality = 0, Bad quality != 0...
int NDOF
For Vertices created using -O TGlobalReconModule=UseECalVertices the quality denotes.
bool SortHitsInY(const ND::THandle< ND::THit > &h1, const ND::THandle< ND::THit > &h2)
double BackMomentumError
the error on the momentum of the object
void FillConfigTree(TTree *configTree)
Int_t fNFgdTimeBins
Number of hit time bins in the FGD as determined by fgdRecon.
TClonesArray * TPC
TPC specific variables.
std::vector< float > FGD2HitQ
Vector to store the charge of each hit in FGD2.
unsigned long Detectors
Detectors used, defined according to the algorithm in GetDetectorNumber.
const int NMAXTPC
int PrimaryIndex
The index of the corresponding primary vertex.
TGlobalHit hitMaxZ
Hit with highest Z position.
ND::THandle< ND::TG4Trajectory > GetG4Trajectory(const ND::TReconBase &object, double &pur, double &eff)
double RangeMomentumEndToTPCElectron
the momentum by range for the electron hypothesis (from end to a TPC)
double BackCharge
the momentum of the object at the back state
TLorentzVector BackPosition
The global coordinate position at the &#39;back&#39; of the object.
double fgdEA_verNextNearQ_rect
FGD end activity values.
TLorentzVector EntrancePosition[NDETSEXTRAP]
The position of the object at the entrance of each subdetector.
bool SortNodesInY(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
double E_exp_electron
Expected energy deposit for an electron.
std::vector< int > fgdhits_Layer
Vector to store the layer number of each hit.
double sigmaE_muon
Expected energy uncertainty for a muon.
double ChargeAtTrueVertex
Charge at the true vertex.
TClonesArray * fTPCOthers
The vector of TPC other objects (TTPCOtherObject).
dict::dictionary< int > fDetIndex
double EDeposit
The deposited charge for the object.
TVector3 Direction
Direction of the corresponding object.
Int_t fNTPCUnused
Number of hits unused in the TPC.
TVector3 BackDirection
The direction at the &#39;back&#39; of the object.
bool DetectorUsed[NDETSUSED]
Detectors used (NDETSUSED = 23)
TVector3 BackDirectionVar
The direction variance of the object.
double Length
The total length of the object.
int NbFittedHorizontalClusters
The number of horizontal clusters contributed to the fit, TREx.
double FrontMomentum
the momentum of the object
Int_t fBufferSize
Buffer Size for TBranch.
double Charge
Charge from the TPC pid (+1, or -1)
int Layer
SMRD hit layer number.
Int_t fNFGD
Number of objects containing the FGD.
double fgdVA_verNextNextNearQ_rect
FGD vertex activity 2x7.
TVector3 EntranceDirection[NDETSEXTRAP]
The direction of the object at the entrance of each subdetector volume.
double PID_LLR_EM_HIP
A combined discriminator for separating protons from electrons.
double MomentumErrorAtTrueVertex
Error of the momentum at the true vertex.
Int_t fNTPCIso
Number of objects in the TPC only.
void FillTPCInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
double MomentumErrorAtTrueVertex
The error of the momentum at the true vertex.
An object to hold specific FGD variables.
double EntranceMomentum[NDETSEXTRAP]
The momentum of the object at the entrance of each subdetector.
std::vector< int > FGD1HitLayer
Vector to store the layer number of each hit in FGD1.
double fgdEA_verNextNearQ
FGD end activity values.
double fgdEA_verNextNextNearQ
FGD end activity values.
double PullNotSet
PullNotSet = 1 if the pull is not set, and 0 otherwise.
TClonesArray * FGD1Unused
The vector unused hits in FGD1.
double PID_Angle
The zenith angle with respect to each detector.
double PDist
Placeholder for momentum of BField refit.
bool SortNodesInX(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
int Type
Vertex type (0: Global vertex | 1: SFG vertex)
double fgdEA_verLayQ
FGD end activity values.
int PID
The TGlobalPID of the constituent track.
Int_t fNSFG
Number of objects containing the SFG.
Int_t fNPIDs
The number of global objects.
double PullProton
The FGD PID pull value for a proton.
std::vector< TLorentzVector > NodePosition
Vector to store the position and time of each node.
TVector3 DirVariance
Direction variance of the corresponding object.
double PullKaon
Pull for TPC pid kaon hypothesis.
double PID_LLR_MIP_EM
A combined discriminator for separating MIPs from EM showers.
Int_t fNTrECAL
Number of objects containing the TrECAL.
Int_t fNSMRD
Number of objects containing the SMRD.
Int_t fNSFGIso
Number of objects in the SFG only.
TClonesArray * fSMRDUnused
The vector unused hits in the SMRD (TSMRDHit).
Describes a reconstructed ECalObject.
double fgdVA_verNearQ_rect
FGD vertex activity 2x3.
Int_t fNSMRDLeftUnused
Number of hits unused in the SMRDLeft.
ND::THandle< ND::TReconBase > GetTrackerReconVersionOfFGDIsoTrack(ND::THandle< ND::TReconBase > object)
Int_t NSMRDs
Number of SMRD objects.
TClonesArray * SFG
SFG specific variables.
double fgdVA_otherUpQ
FGD vertex activity values.
Int_t NHitsSaved
Number of entries in the HitsSaved array.
std::vector< std::vector< int > > NodeHits
Vector to store the hits contributing to each node.
UInt_t UniqueID
Unique identifier for sub-detector recon objects.
bool DetectorUsed[NDETSUSED]
Detectors used. Index order from 0 to 26.
An object to describe a reconstructed PID.
std::vector< int > T0Source
The T0Source, the values are defined in TTPCFitStatusBranch.hxx, the TTPCT0Source enumeration...
Int_t fNSMRDTopUnused
Number of hits unused in the SMRDTop.
double MedianObjectTime(ND::THandle< ND::TReconBase > object)
const int NMAXFGD
std::vector< int > ParticleIds
the PDG codes obtained in the recon combined PID
void FillFirstLastHits(ND::THitSelection &hits, TGlobalPID &globalObject)
std::string fCVSID
Defined if an official tagged version.
double Ccorr
Corrected truncated mean charge deposit in PID.
void FillAllHits(ND::THitSelection &hits, TGlobalPID &globalObject)
double fgdVA_totalCorrE
FGD vertex activity values.
std::vector< TLorentzVector > NodePosition
FGD Node positions.
Int_t NP0DECALs
Number of P0DECAL objects.
double x
Distance traveled in an FGD.
TVector3 Momentum
3-momentum of the constituent track
An object to hold a reconstructed vertex constituent track.
TVector3 ExitDirection[NDETSEXTRAP]
The direction of the object at the exit of each subdetector.
TVector3 ExitDirectionErr[NDETSEXTRAP]
The error of the direction of the object at the exit of each subdetector.
double BackMomentum
The momentum measurement at the &#39;back&#39; of the object.
double BackStateCov[7][7]
full covariance matrix for last state: pos, dir, qp
double RangeMomentumPion
the momentum by range for the pion hypothesis
const int DEFAULT_MAX
std::vector< int > HitTrajID
Vector to store the ID of the Trajectory that created the hit.
An object to described a P0D shower.
ND::THandle< ND::TG4Trajectory > GetMainContributor(ND::THandle< ND::TMCHit > mch, ND::THandle< ND::TG4TrajectoryContainer > trajectories)
const int NMAXP0D
double Chi2
The chi2 of the fit.
void FillSFGOther(ND::TND280Event &event)
void FillGlobalPIDAlternate(ND::THandle< ND::TG4Trajectory > G4track, ND::THandle< ND::TReconBase > object, TGlobalPIDAlternate &PIDAlternate)
double EDeposit
Deposited energy. Its value depends on if the object is reconstructed as track-like or shower-like If...
TClonesArray * SMRD
SMRD specific variables.
double E_exp_pion
Expected energy deposit for a pion.
std::vector< TLorentzVector > NodePosition
Int_t fNP0DECALIso
Number of objects in the P0DECAL only.
An object to hold specific SMRD variables.
std::vector< float > fgdhits_Charge
Vector to store the charge of each hit.
std::vector< double > PIDWeights
the PID likelihoods for combined PID
int NDOF
The number of degrees of freedom in the fit.
double GetTRealDatumValue(ND::THandle< ND::TReconBase > trb, char const *name, double const &defaultValue)
int Type
Object type, 0: Particle, 1: Track, 2: Cluster, 3: Shower, 4: Vertex.
int ProtonBraggCut
Bragg peak cut (only used for SFGD contained tracks)
double PIDWeightElec
PID weights for electron hypothesis.
std::vector< double > NodeEDeposit
Vector to store the energy deposit of each node.
double PID_LLR_MIP_Pion
Discriminator for tagging showering pions in a sample of MIP-like tracks.
double sigmaE_proton
Expected energy uncertainty for a proton.
double fgdEA_verNearQ
FGD end activity values.
double PID_TransverseChargeRatio
A variable sensitive to the charge distribution in the plane transverse to a shower/track direction...
TGlobalHit hitMinX
Hit with lowest X position.
bool SortHitsInX(const ND::THandle< ND::THit > &h1, const ND::THandle< ND::THit > &h2)
double avgtime
Average fully corrected FGD hit time.
double Pur
The purity for matching the rec particle with the true particle.
void SetNameTitle(char const *name, char const *title)
double EDeposit
The energy deposited in the shower.
const int NTIMEBINS
double RangeMomentumPionFlip
the momentum by range for the flipped pion hypothesis
TVector3 Width
TrackShower width Filled depending on FilledAsShower. * Track: ND::TReconTrack::GetWidth * Shower: Al...
TECALReconObject * TECALReconObjectFactory(ND::THandle< ND::TReconTrack > track, ND::THandle< ND::TReconPID > pid, bool IsMC, void *pos, bool Allocate)
Handles Filling from a PID&#39;s track hypothesis constituent.
std::vector< int > FGD2HitLayer
Vector to store the layer number of each hit in FGD2.
Int_t fNFGDIso
Number of objects in the FGD only.
void FillVertexInfo(ND::TND280Event &event, ND::THandle< ND::TReconObjectContainer > globalObjects)
std::vector< TVector3 > NodeDirection
Vector to store the direction of each node.
double PID_LLR_MIP_EM
A combined discriminator for separating MIPs from EM showers.
virtual bool FillTree(ND::TND280Event &)
Fill all the stuff that goes in the output tree.
double PullPion
Pull for TPC pid pion hypothesis.
TClonesArray * FGD
FGD specific variables.
TVector3 Position
Hit position in global ND coordinates [mm].
Int_t NFGD2Unused
Number of hits unused in FGD2.
TVector3 BackDirection
The direction of the object.
void FillOutermostHits(ND::THitSelection &hits, double charge_cut, TOutermostHits &outer)
double Pur
Purity of reconstructed - true vertex association.
Definition: TTrueVertex.hxx:24
double FrontMomentum
the momentum of the object
double BackMomentumError
The uncertainty on ND::TSubBaseObject::BackMomentum.
bool IsCurvBack
A curving-back object.
Int_t NTrECALs
Number of TrECAL objects.
ND::THandle< ND::TG4PrimaryVertex > GetG4Vertex(const ND::TReconBase &object, double &pur, double &eff)
unsigned long Status
The status for the fit.
TVector3 BackDirectionVar
The direction variance of the object.
Int_t fNFGD1Unused
Number of hits unused in the FGD1.
void DoAssociationBetweenTrackerAndGlobalObjects(const ND::TReconObjectContainer &globalObjects, const ND::TReconObjectContainer &trackerObjects)
double dEdxexpPion
Estimated dE/dx for pion hypothesis.
virtual void InitializeModule()
Initialize Module, override if necessary.
TLorentzVector PositionVarAtTrueVertex
The position variance at the true vertex.
TVector3 DirectionAtTrueVertex
Direction at the true vertex.
TVector3 FrontDirectionVar
The direction variance of the object.
TVector3 Cone
The opening angles of the reconstructed shower cone.
double EDeposit
The deposited charge for the object.
const int NMAXP0DECAL
std::vector< float > SFGHitT
Vector to store the time of each hit in SFG.
std::string AlgorithmName
The name of the algorithm that created this object.
TLorentzVector BackPositionVar
The uncertainty on ND::TSubBaseObject::BackPosition.
TClonesArray * P0D
P0D specific variables.
An object to store the outermost hits in x,y, and z.
double Eff
Efficiency of vertex association of tracks.
Definition: TTrueVertex.hxx:27
TLorentzVector FrontPosition
The Front position of the object.
void GetFGDSimpleVA(ND::TND280Event &event, ND::THandle< ND::TReconBase > &object, TLorentzVector &vertexPos, int globpass, int vaea)
double fgdVA_downMaxZ
FGD vertex activity values.
void FillTrackerInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
double fgdVA_downCosTheta
FGD vertex activity values.
TOutermostHits FGD2OutermostHits
A named collection of the outermost hits in X,Y, and Z from FGD2.
double PullMuon
Pull for TPC pid muon hypothesis.
TLorentzVector FrontPositionVar
The position variance;.
void FillFGDInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
std::map< ND::THandle< ND::TReconBase >, int > fGlobalIndexMap
Describes a true G4 particle associated to a TGlobalPID.
double MomentumErrorAtTrueVertex
The momentum variance at the true vertex.
const int NSVERTICES
double E_exp_proton
Expected energy deposit for a proton.
std::vector< int > ParticleId
A vector of potential PIDs, sorted by weight, c.f. TP0DObject::PIDWeight.
double dEdxexpProton
Estimated dE/dx for proton hypothesis.
double fgdEA_otherDownQ
FGD end activity values.
int NDOF
The number of degrees of freedom.
void FillTrueVertex(bool, const ND::TG4PrimaryVertex &G4vertex, double pur, double eff, ND::TTrueVertex &vertex)
TClonesArray * ECAL
ECAL specific variables.
double BackMomentumError
the error on the momentum of the object
int Type
The hit &#39;type&#39;: (0=X,1=Y,2=Z)
An object to store information about an SFG Time Bin.
int GetNumberOfHits(ND::THandle< ND::TReconBase > object)
double BackMomentum
the momentum of the object
TClonesArray * Alternates
List of alternate hypotheses.
std::vector< UInt_t > BrokenUniqueIDs
the broken partners unique IDs
std::vector< double > HitCharge
Vector to store the charge of each hit.
std::string AlgorithmName
The name of the algorithm that created this object.
An object to hold specific TPC variables.
TLorentzVector FrontPositionVar
The uncertainty on ND::TSubBaseObject::FrontPosition.
double PullEle
Pull for TPC pid electron hypothesis.
Int_t fNDsECALIso
Number of objects in the DsECAL only.
TLorentzVector EntrancePositionErr[NDETSEXTRAP]
The error of the position of the object at the entrance of each subdetector.
TVector3 BackDirection
The Back direction of the object.
unsigned long Status
The status for the fit, from: object-&gt;CheckStatus(object-&gt;kSuccess).
std::vector< int > SFGHitTrajID
Vector to store the ID of the Trajectory that created the hit in SFG.
void FillECALInfo(ND::THandle< ND::TReconBase > object, TGlobalPID &pid)
TVector3 Cone
The opening angles of the cone (only for showers)
TClonesArray * fTPCPIDs
For tests only (TTpcPID).
TLorentzVector PositionAtTrueVertex
Position at true vertex.
double E_exp_muon
Expected energy deposit for a muon.
double PIDWeight
the PID weight for this hypothesis
TGlobalHit hitMinY
Hit with lowest Y position.
bool fTestTPCInfo
For tests only.
TGlobalHit hitMaxX
Hit with highest X position.
int NNodes
The number of reconstruction nodes.
bool FillVertex(ND::TND280Event &event, ND::THandle< ND::TReconVertex > vertex, bool primary)
int fgdContainment
Fully contained PID information.
double RangeMomentumElectronFlip
the momentum by range for the flipped electron hypothesis
double dEdxexpKaon
Estimated dE/dx for kaon hypothesis.
double fgdVA_verNextNearQ_rect
FGD vertex activity 2x5.
double Width
The width of the shower (perpendicular to the direction).
double fgdEA_otherUpQ
FGD end activity End (1) or Exit (2)
Int_t fSplitLevel
Split Level for TBranch.
bool SortNodesInZ(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
TVector3 BackDirectionVar
The uncertainty on ND::TSubBaseObject::BackDirection.
int Type
The hit &#39;type&#39;: (0=X,1=Y,2=Z)
TClonesArray * P0DECAL
P0DECAL specific variables.
Int_t fNSMRDBottomUnused
Number of hits unused in the SMRDBottom.
double EntranceMomentumErr[NDETSEXTRAP]
The error of the momentum of the object at the entrance of each subdetector.
std::vector< float > FGD2HitPosition
Vector to store the X or Y position of each hit in FGD2.
Int_t fNSMRDUnused
Number of all hits unused in the SMRD.
int NConstituents
The number of constituents.
std::vector< float > fgdhits_Time
Vector to store the time of each hit.
Int_t fNSVertices
Number of added secondary vertices.
Int_t fNFGD2Unused
Number of hits unused in the FGD2.
Int_t ID
The vertex ID from G4.
Definition: TTrueVertex.hxx:21
TVector3 chargeWeightedPos
Charge weighted average hit position in SFG.
double BackMomentumError
the error on the momentum of the object
Int_t fNP0DIso
Number of objects in the P0D only.
double Containment
Containment: contained = 1.0, not-contained = 0.0, default = -1.0. An object is classed as contained ...
TLorentzVector PositionAtTrueVertex
Position at the true vertex.
double Length
The length of the track or shower (RMS)
int NDOF
The number of degrees of freedom.
std::map< ND::THandle< ND::TReconBase >, std::vector< UInt_t > > fBrokenIndexMap
An object to hold specific SFG variables.
TLorentzVector BackPositionVar
The position variance;.
double Containment
Containment: contained = 1.0, not-contained = 0.0, default = -1.0.
TTrueParticle TrueParticle
The true particle.
void MatchTrueVertex(ND::THandle< ND::TG4PrimaryVertexContainer > g4PrimVert)
double PIDWeightPion
PID weights for pion hypothesis.
double FrontStateCov[7][7]
full covariance matrix for front state: pos, dir, qp
TLorentzVector PositionAtTrueVertex
The position at the true vertex.
double SigmaProton
Sigma estimated width of TPC pid proton hypothesis.
TOutermostHits FGD1OutermostHits
A named collection of the outermost hits in X,Y, and Z from FGD1.
std::vector< TLorentzVector > HitPosition
Vector to store the position of each hit.
Int_t fNTPCPIDs
For tests only.
TLorentzVector FrontPosition
The position of the object.
std::vector< int > FGD2HitTrajID
Vector to store the ID of the Trajectory that created the hit in FGD1.
double FrontMomentumError
the error on the momentum of the object
void FillSubBaseObject(ND::THandle< ND::TReconBase > object, TSubBaseObject &sub, int det)
double RangeMomentumProtonFlip
the momentum by range for the flipped proton hypothesis
bool IsFgdECalIncremental
A track created by FGD-ECal matching algorithm.
double fgdVA_upMinZ
FGD vertex activity Vertex (1) or Entrance (2)
std::string GetObjectType(ND::THandle< ND::TReconBase > object)
std::string fCVSTagName
Defined if an official tagged version.
#define CVSTAG
double RangeMomentumMuon
the momentum by range for the muon hypothesis
double StateCovAtTrueVertex[7][7]
Full covariance matrix for the state: pos, dir, qp at the true vertex.
void FillBrokenTracksMap(const ND::TReconObjectContainer &globalObjects)
double fEarliestTrackMedianHitTime
Median hit time of the earliest track.
int Wall
SMRD wall number, 0=Top, 1=Bottom, 2= Right, 3= Left.
double EDeposit
The charge deposited by the track in units of MIPs.
double Quality
Quality (chi2) of the constituent track.
TVector3 PositionError
The variance on ND::TGlobalReconModule::TSMRDHit::Position [mm].
std::vector< int > TPCGasJunctionIDs
The IDs of the TREx junctions which contributed to the object.
double sigmaE_electron
Expected energy uncertainty for an electron.
double fgdVA_upCosTheta
FGD vertex activity values.
An object to describe the true G4 vertex associated to the TGlobalVertex.
Definition: TTrueVertex.hxx:14
const bool debug_extrap
void FillTPCOther(ND::TND280Event &event)
TVector3 EntranceDirectionErr[NDETSEXTRAP]
The error of the direction of the object at the entrance of each subdetector.
Int_t NFGD1Unused
Number of hits unused in FGD1.
std::string AlgorithmName
The name of the algorithm that created this object.
TVector3 BackDirection
The direction of the object.
An object to store information about an FGD Time Bin.
TOutermostHits fP0DOutermostHits
Outermost hits in the P0D.
void CheckFGDdist(TLorentzVector &FGDPos, TVector3 fFGDActiveMin, TVector3 fFGDActiveMax)
TGlobalReconModule(const char *name="Global", const char *title="Global Recon Module")
Default Constructor.
double RangeMomentumElectron
the momentum by range for the electron hypothesis
const int NMAXECAL
double fgdVA_otherDownQ
FGD vertex activity values.
double rawChargeSum
Summed hit charge in SFG.
const int NMAXALTERNATES
const int NCONSTITUENTS
TClonesArray * TrueVertices
The true vertex.
void SetSplitLevel(Int_t splitlevel)
ROOT output parameters, usually no need to touch.
double rawChargeSum[2]
Summed hit charge in FGD1 (rawChargeSum[0]), and 2 (rawChargeSum[1])
void FillExtrapolationToDetectors(ND::THandle< ND::TReconBase > object, TGlobalPID &globalObject)
const int NMAXSFG
int nHits[2]
Number of hits in FGD1 (nHits[0]), and 2 (nHits[1])
Int_t fNSFGUnused
Number of hits unused in the SFG.
Int_t MostUpStreamLayerHit
The layer closest to the tracker that was hit by the object. 0 indexed.
std::vector< float > SFGHitQ
Vector to store the charge of each hit in SFG.
TVector3 Position
Hit position in global ND coordinates [mm].
Provides data members common to reconstructed objects from all sub detectors.
TGlobalHit hitMaxY
Hit with highest Y position.
TClonesArray * fPIDs
The vector of TGlobalPID.
TVector3 FrontDirection
The direction of the object.
std::vector< TVector3 > fgdhits_Position
Vector to store the X or Y position of each hit.
void FillGlobalPIDs(ND::TND280Event &event, ND::THandle< ND::TReconBase > object)
std::vector< int > NVerRows
The number of vertical clusters in the track.
double ExitMomentum[NDETSEXTRAP]
The momentum of the object at the exit of each subdetector.
TVector3 FrontDirectionVar
The uncertainty on ND::TSubBaseObject::FrontDirection.
TVector3 Cone
The opening angles of the cone (only for showers)
double FrontMomentum
the momentum of the object
An object to describe a reconstructed primary vertex candidate.
double fgdVA_verLayQ
FGD vertex activity values.
std::vector< float > FGD1HitQ
Vector to store the charge of each hit in FGD1.
ND::THandle< ND::TG4Trajectory > GetParent(ND::THandle< ND::TG4Trajectory > G4track)
Int_t fNSMRDIso
Number on objects in the SMRD only.
const int NMAXSMRD
TLorentzVector FrontPosition
the PID likelihoods for combined PID
Int_t NTPCs
Number of TPC objects.
void FillKinematicsAtTrueVertex(ND::THandle< ND::TG4Trajectory > G4track, ND::THandle< ND::TReconBase > object, TLorentzVector &pos, TVector3 &dir, double &mom, double &momErr, double &charge, double(&cov)[7][7])
ND::TTrueVertex Vertex
True vertex associated to this TrueParticle.
TVector3 PositionError
The variance on ND::TGlobalReconModule::TGlobalHit::Position [mm].
TVector3 DirectionAtTrueVertex
The direction at the true vertex.
Int_t fNP0DUnused
Number of hits unused in the P0D.
TGlobalHit hitMinZ
Hit with lowest Z position.
unsigned long Status
The status for the fit.
int Detector
Integer specifying which subdetector(s) the object belongs to. See TGlobalReconModule::GetDetectorNum...
void FillSmrdHit(ND::THandle< ND::THit > hit, TSMRDHit &smrdHit)
TECALReconVertexTrack * TECALReconVertexTrackFactory(ND::THandle< ND::TReconPID > trk, bool IsMC, void *pos, ND::THandle< ND::TG4TrajectoryContainer > trajectories, bool Allocate)
const bool debug_broken
unsigned long Detectors
Detectors used.
int g4ID
The ID for the G4 trajectory that contributed most to this time bin.
TLorentzVector FrontPositionVar
The position variance;.
TLorentzVector Variance
The position variance;.
double E
Measured energy in an FGD.
double dEdxexpEle
Estimated dE/dx for electron hypothesis.
double EDeposit
Deposited energy, N.B. the meaning of this is subdetector-local.
std::vector< TLorentzVector > NodePosVariance
Vector to store the variance on the position and time of each node.
double PID_Asymmetry
Ratio of the big width of an object by its small width.
double Width
The width of the shower (perpendicular to the direction)
surface_vector fDetSurfaces[NDETSEXTRAP]
std::vector< int > FGD1HitTrajID
Vector to store the ID of the Trajectory that created the hit in FGD1.
double fgdVA_verNextNextNearQ
FGD vertex activity values.
Int_t NP0Ds
Number of P0D objects.
bool SortHitsInZ(const ND::THandle< ND::THit > &h1, const ND::THandle< ND::THit > &h2)
bool SortNodesInZReverse(const ND::THandle< ND::TReconNode > &n1, const ND::THandle< ND::TReconNode > &n2)
Int_t BackLayerNumber
The back layer number (closest to the tracker) of the track.
TLorentzVector BackPosition
The Back position of the object.
Int_t NAlternates
Number of entries in the alternate hypotheses list.
double PID_LLR_MIP_HIP_VACut
A combined discriminator for separating MIPs from HIPs where the hits nearest the vertex have been ig...
double Width
The width of the shower (perpendicular to the direction)
Int_t fNSfgTimeBins
Number of hit time bins in the SFG as determined by sfgRecon.
void GetHitsAssociatedToG4Trajectory(const ND::THitSelection &hits, ND::THandle< ND::TG4Trajectory > traj, ND::THitSelection &traj_hits)
int NbFittedVerticalClusters
The number of vertical clusters contributed to the fit, TREx.
TClonesArray * SFGUnused
The vector unused hits in SFG.
double NTrun
70% of the number of cluster
TTrueParticle TrueParticle
The true particle.
virtual void FillConfigTree(TTree *)
double EDeposit
Energy deposit of the corresponding object.
Bool_t Configure(std::string &opt)
A function that allows the module to be configured from an external class without any dependencies...

Package Summary
Package Name: eventAnalysis
Package Version: 7.0-49-g0ac7482
Package Manager:

Generated on Mon Mar 25 2024 14:43:58 for eventAnalysis by doxygen 1.8.5