eventAnalysis  7.0-49-g0ac7482
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
TTrackerECALReconModule.cxx
Go to the documentation of this file.
1 #include <sstream>
2 
3 #include "TDatum.hxx"
4 #include "TGeomInfo.hxx"
5 #include "TPrincipal.h"
6 #include "TRealDatum.hxx"
7 #include "TShowerTruthInfo.hxx"
8 #include "TrackTruthInfo.hxx"
9 
11 
20 
21 #ifdef TTRACKERECALRECONMODULE_USE_EXP
22 ClassImp(ND::TTrackerECALReconModule::TECALReconHit);
23 #endif
24 
26 
27 #define CVSTAG \
28  "\
29  $Name: 7.0$"
30 #define CVSID \
31  "\
32  $Id: eventAnalysis TTrackerECALReconModule.cxx,2024/03/20:09:46:11,Alexander_J_Finch,lapw.lancs.ac.uk $"
33 
34 namespace {
35 std::ostream& operator<<(std::ostream& os, const TVector3& tv3) {
36  return os << "[" << tv3[0] << ", " << tv3[1] << ", " << tv3[2] << "]";
37 }
38 std::ostream& operator<<(std::ostream& os, const TLorentzVector& tlv) {
39  return os << "[" << tlv[0] << ", " << tlv[1] << ", " << tlv[2] << ", "
40  << tlv[3] << "]";
41 }
42 
43 #ifdef TTRACKERECALRECONMODULE_USE_EXP
44 
45 const int MAXHITSTOSAVE = 1000;
46 
47 /// Pretty prints TECALReconHits
48 inline std::ostream& operator<<(
49  std::ostream& os, const ND::TTrackerECALReconModule::TECALReconHit& hit) {
50  return os << "{ Pos: " << hit.Position << ", Charge: " << hit.ChargeDeposit
51  << ", GID: " << hit.GeomId << ", IsXYZ: " << hit.IsXYZ
52  << " UsedBy: " << hit.UsedByNObjs << " objects }";
53 }
54 
55 #endif
56 }
57 
58 namespace ND {
59 namespace TTrackerECALReconModule {
60 
61 OutputManager::OutputManager(const char* name, const char* title) {
62  SetNameTitle(name, title);
63  // Enable this module by default:
64  fIsEnabled = kTRUE;
65  fDoSaveHoughResults = false;
66  fDoVertexing = false;
67  fDescription = "Tracker ECAL recon output";
69  fCVSID = CVSID;
70  fIsMC = false;
71  fTotal = 0;
72  fVertexRecon = NULL;
73  // Tree variables
75  new TClonesArray("ND::TTrackerECALReconModule::TECALReconObject", 200);
76  fUnmatchedObjects = new TClonesArray(
77  "ND::TTrackerECALReconModule::TECALReconUnmatchedObject", 200);
78  fReconVertexClusters = new TClonesArray(
79  "ND::TTrackerECALReconModule::TECALReconVertexCluster", 200);
80 #ifdef TTRACKERECALRECONMODULE_USE_EXP
81  fDoSaveHitInfo = false;
82  fUsedHits = new TClonesArray("ND::TTrackerECALReconModule::TECALReconHit",
83  MAXHITSTOSAVE);
84 #endif
86  fVertexCandidates = new TClonesArray(
87  "ND::TTrackerECALReconModule::TECALReconVertexCandidate", 100);
88  fVertexCandidateTracks = new TClonesArray(
89  "ND::TTrackerECALReconModule::TECALReconVertexTrack", 100);
90 }
91 
93 
94 Bool_t OutputManager::Configure(std::string& option) {
95 #ifdef TTRACKERECALRECONMODULE_USE_EXP
96  if (option == "SaveHitInfo") {
97  fDoSaveHitInfo = true;
98  ND280NamedLog("TTrackerECALReconModule", "Will save hit info");
99  return true;
100  }
101 #endif
102  if (option == "RunVertexing") {
103  fDoVertexing = true;
104  ND280NamedLog("TTrackerECALReconModule",
105  "Will re-run vertexing code reconstruction.");
106  return true;
107  }
108  if (option == "SaveTheHoff") {
109  fDoSaveHoughResults = true;
110  ND280NamedLog("TTrackerECALReconModule",
111  "Will save raw Hough transform results for this run.");
112  return true;
113  }
114  if (option == "SaveVertexCandy") {
116  ND280NamedLog("TTrackerECALReconModule",
117  "Will save reconstructed vertex "
118  "candidate info");
119  return true;
120  }
121  return false;
122 }
123 
124 Bool_t OutputManager::ProcessFirstEvent(ND::TND280Event& event) {
125 #ifdef TTRACKERECALRECONMODULE_USE_EXP
126  if (fDoSaveHitInfo) {
127  ND280NamedLog("TTrackerECALReconModule", "Saving Hit Info for this run.");
128  }
129 #endif
131  ND280NamedLog("TTrackerECALReconModule",
132  "Saving reconstructed vertex "
133  "candidates for this run.");
134  }
135  if (fDoSaveHoughResults) {
136  ND280NamedLog("TTrackerECALReconModule",
137  "Saving raw Hough transform results for this run.");
138  }
139  if (fDoVertexing) {
140  ND280NamedLog("TTrackerECALReconModule", "Running ECal-iso vertexing");
141 
142  // Initialise the vertex recon
143  fVertexRecon = new ND::TECalVertexing();
144  }
145 
146  return true;
147 }
148 
149 bool OutputManager::IsFullEventWorthSaving(ND::TND280Event& event) {
150  return fNReconObjects;
151 }
152 
155  fOutputTree->Branch("NReconObject", &fNReconObjects, "NReconObjects/I",
156  fBufferSize)
157  ->SetTitle(" Number of TECALRecon Objects");
158 
159  fOutputTree->Branch("NReconTrackLike", &fNReconTrackLike, "NReconTrackLike/I",
160  fBufferSize)
161  ->SetTitle("Number of TrackLike objects ");
162 
163  fOutputTree->Branch("NReconShowerLike", &fNReconShowerLike,
164  "NReconShowerLike/I", fBufferSize)
165  ->SetTitle("Number of ShowerLike objects ");
166 
167  fOutputTree->Branch("NUnmatchedObject", &fNUnmatchedObjects,
168  "NUnmatchedObjects/I", fBufferSize)
169  ->SetTitle("Number of Unmatched Objects ");
170 
171  // A TClonesArray of TECALReconObject objects
172  fOutputTree->Branch("ReconObject", &fReconObjects, fBufferSize, fSplitLevel)
173  ->SetTitle(" The TECALRecon Objects");
174 
175  fOutputTree->Branch("UnmatchedObject", &fUnmatchedObjects, fBufferSize,
176  fSplitLevel)
177  ->SetTitle("The Unmatched Objects ");
178 
179  if (fDoSaveHoughResults) {
180  fOutputTree->Branch("NVertexCluster", &fNReconVertexClusters,
181  "NVertexCluster/I", fBufferSize)
182  ->SetTitle(" ");
183 
184  fOutputTree->Branch("VertexCluster", &fReconVertexClusters, fBufferSize,
185  fSplitLevel)
186  ->SetTitle("The Reconstructed Vertices ");
187 
188  }
189 
190 #ifdef TTRACKERECALRECONMODULE_USE_EXP
191  fOutputTree->Branch("NUsedHits", &fNUsedHits, "NUsedHits/I", fBufferSize);
192  fOutputTree->Branch("UsedHits", &fUsedHits, fBufferSize, fSplitLevel);
193 #endif
194 
196  fOutputTree->Branch("NVertexCandidates", &fNVertexCandidates,
197  "NVertexCandidates/I", fBufferSize);
198  fOutputTree->Branch("VertexCandidates", &fVertexCandidates, fBufferSize,
199  fSplitLevel);
200  fOutputTree->Branch("NVertexCandidateTracks", &fNVertexCandidateTracks,
201  "NVertexCandidateTracks/I", fBufferSize);
202  fOutputTree->Branch("VertexCandidateTracks", &fVertexCandidateTracks,
204  }
205 }
206 
208  ND::THandle<ND::TAlgorithmResult> ecalFinalResult,
209  ND::THandle<ND::TG4TrajectoryContainer> trajectories)
210 {
211  ND::THandle<ND::TReconObjectContainer> vertices_container =
212  ecalFinalResult->GetResultsContainer("ECalHoughResults");
213  if (!vertices_container) {
214  ND280NamedInfo("TTrackerECALReconModule", "No vertex recon container.");
215  return;
216  }
217  for (ND::TReconObjectContainer::iterator vertIt = vertices_container->begin();
218  vertIt != vertices_container->end(); vertIt++) {
219  ND::THandle<ND::TReconVertex> top_vertex = (*vertIt);
220  if (!top_vertex) {
221  continue;
222  }
223 
224  ND280NamedInfo("TTrackerECALReconModule",
225  "============================================");
226  ND280NamedInfo("TTrackerECALReconModule",
227  "======Processing Hough Vertex Cluster("
228  << top_vertex->GetUniqueID() << ")=======");
229  ND280NamedInfo("TTrackerECALReconModule",
230  "============================================");
231 
232  TECALReconVertex vd;
233  if (fDoVertexing) { // If we are saving the vertex candidates
234  vd = fVertexRecon->ProcessHoughResult(top_vertex);
235 
236  if (vd.IsValid()) { // If this is a valid reconstructed vertex candidate
238  vd, top_vertex, fIsMC, (*fVertexCandidates)[fNVertexCandidates++]);
239 
240  for (UInt_t trki = 0; trki < vd.NTracks(); ++trki) {
241  ND::THandle<ND::TReconPID> trk = vd.Tracks_at(trki);
242  if (!trk) {
243  continue;
244  }
245  if (!fSavedVertexTrackIds.count(trk->GetUniqueID())) {
246  fSavedVertexTrackIds.insert(
247  std::make_pair(trk->GetUniqueID(), fNVertexCandidateTracks));
249  trk, fIsMC,
251  trajectories);
252  ND280NamedVerbose(
253  "TTrackerECALReconModule",
254  "Saved track constituent of vertex candidate with ID: "
255  << trk->GetUniqueID());
256  }
257  }
258 
259  // Flatten and add any secondary vertex candidates in this cluster.
260  for (std::vector<TECALReconVertex>::iterator rv_it =
261  vd.SecondaryVertices_begin();
262  rv_it != vd.SecondaryVertices_end(); ++rv_it) {
264  (*rv_it), top_vertex, fIsMC,
265  (*fVertexCandidates)[fNVertexCandidates++]);
266 
267  for (UInt_t trki = 0; trki < (*rv_it).NTracks(); ++trki) {
268  ND::THandle<ND::TReconPID> trk = (*rv_it).Tracks_at(trki);
269  if (!trk) {
270  continue;
271  }
272  if (!fSavedVertexTrackIds.count(trk->GetUniqueID())) {
273  fSavedVertexTrackIds.insert(
274  std::make_pair(trk->GetUniqueID(), fNVertexCandidateTracks));
276  trk, fIsMC,
278  trajectories);
279  ND280NamedVerbose("TTrackerECALReconModule",
280  "Saved track constituent of secondary vertex "
281  "candidate with ID: "
282  << trk->GetUniqueID());
283  }
284  }
285  }
286  }
287  } // end Do vertexing
288 
289  //**************************************************************************
290  // Do Hough
291  //**************************************************************************
292  // Now organise the constituents (tracks and crossings) into
293  // TReconObjectContainers
294  ND::THandle<ND::TReconObjectContainer> constituents =
295  top_vertex->GetConstituents();
296  double ClusterTotalCharge = 0;
297  for (ND::THitSelection::iterator hitIt = top_vertex->GetHits()->begin();
298  hitIt != top_vertex->GetHits()->end(); hitIt++) {
299  ClusterTotalCharge += (*hitIt)->GetCharge();
300  }
301  if (!constituents) {
302  // There was not enough information in the 2 views to reconstruct
303  // anything useful. Record NTracks and NCrossings as 0 and move on
304  continue;
305  }
306  ND::THandle<ND::TReconObjectContainer> tracks(
307  new ND::TReconObjectContainer("vertexRecon_tracks"));
308  ND::THandle<ND::TReconObjectContainer> crossings(
309  new ND::TReconObjectContainer("vertexRecon_crossings"));
310  for (ND::TReconObjectContainer::iterator rocIt = constituents->begin();
311  rocIt != constituents->end(); rocIt++) {
312  ND::THandle<ND::TReconPID> track = (*rocIt);
313  ND::THandle<ND::TReconVertex> vertex = (*rocIt);
314  if (track) {
315  tracks->push_back(track);
316  } else if (vertex) {
317  crossings->push_back(vertex);
318  } else {
319  ND280NamedError("TTrackerECALReconModule",
320  "Found a VertexCluster "
321  "constituent that is not a track or vertex :(");
322  }
323  }
324 
325  TECALReconVertexCluster* vertex_cluster = NULL;
326  if (fDoSaveHoughResults) {
327  // Create the TClonesArray member
328  vertex_cluster = new ((*fReconVertexClusters)[fNReconVertexClusters++])
330  // Now fill it from the top level 'vertex'
331  vertex_cluster->UniqueID = top_vertex->GetUniqueID();
332  vertex_cluster->NHits = top_vertex->GetHits()->size();
333  // Calculate the total charge
334  vertex_cluster->TotalCharge = ClusterTotalCharge;
335  for (ND::THitSelection::iterator hitIt = top_vertex->GetHits()->begin();
336  hitIt != top_vertex->GetHits()->end(); hitIt++) {
337 #ifdef TTRACKERECALRECONMODULE_USE_EXP
338  SaveUsedHit(*hitIt, top_vertex->GetUniqueID());
339 #endif
340  }
341  vertex_cluster->Position = top_vertex->GetPosition();
342  vertex_cluster->Module = ND::TGeomInfo::Get()
343  .ECAL()
344  .GetModule(top_vertex->GetHits()->front())
345  .GetName();
346  vertex_cluster->N2DTracksMax =
347  top_vertex->Get<ND::TIntegerDatum>("N2DProngsMax")->GetValue();
348  vertex_cluster->N2DTracksMin =
349  top_vertex->Get<ND::TIntegerDatum>("N2DProngsMin")->GetValue();
350  // Calculate the hit level information
351  // Use sets to easily organise the hit information
352  std::set<Int_t> layer_numbers, para_bar_numbers, perp_bar_numbers;
353  // Grab the TGeomInfo ECal geometry now as we are going to make repeated
354  // calls to it.
355  ND::TECALGeom* ecal_geom = &(ND::TGeomInfo::Get().ECAL());
356  for (ND::THitSelection::iterator hitIt = top_vertex->GetHits()->begin();
357  hitIt != top_vertex->GetHits()->end(); hitIt++) {
358  ND::THandle<ND::THit> hit = (*hitIt);
359  Int_t layer_number = ecal_geom->GetLayerNumber(hit);
360  Int_t bar_number = ecal_geom->GetBarNumber(hit);
361 
362  // insert the layer number into the set
363  layer_numbers.insert(layer_number);
364  // Do the same for the bars
365  if (hit->IsZHit())
366  perp_bar_numbers.insert(bar_number);
367  else
368  para_bar_numbers.insert(bar_number);
369  }
370  // The bar and layer numbers should be automatically organised
371  // Remember to check that the sets have entries
372  if (layer_numbers.size() == 0) {
373  vertex_cluster->MinLayerHit = -9999;
374  vertex_cluster->MaxLayerHit = -9999;
375  } else {
376  std::set<Int_t>::iterator setIt = layer_numbers.begin();
377  vertex_cluster->MinLayerHit = (*setIt);
378  setIt = layer_numbers.end();
379  setIt--;
380  vertex_cluster->MaxLayerHit = (*setIt);
381  }
382  if (perp_bar_numbers.size() == 0) {
383  vertex_cluster->MinPerpBarHit = -9999;
384  vertex_cluster->MaxPerpBarHit = -9999;
385  } else {
386  std::set<Int_t>::iterator setIt = perp_bar_numbers.begin();
387  vertex_cluster->MinPerpBarHit = (*setIt);
388  setIt = perp_bar_numbers.end();
389  setIt--;
390  vertex_cluster->MaxPerpBarHit = (*setIt);
391  }
392  if (para_bar_numbers.size() == 0) {
393  vertex_cluster->MinParaBarHit = -9999;
394  vertex_cluster->MaxParaBarHit = -9999;
395  } else {
396  std::set<Int_t>::iterator setIt = para_bar_numbers.begin();
397  vertex_cluster->MinParaBarHit = (*setIt);
398  setIt = para_bar_numbers.end();
399  setIt--;
400  vertex_cluster->MaxParaBarHit = (*setIt);
401  }
402 
403  // Get the truth information for the cluster
404  ND::TShowerTruthInfo shower_truth(top_vertex->GetHits(),
405  ND::TShowerTruthInfo::kXYZ, 1, 1, 1);
406  // Start with single trajectories
407  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
408  shower_truth.GetSingleTrajectories();
409  if (results.size() > 0) {
410  vertex_cluster->G4IDSingle = results[0].ParticleID;
411  vertex_cluster->CompletenessSingle = results[0].Completeness_NumHits;
412  vertex_cluster->CleanlinessSingle = results[0].Cleanliness_NumHits;
413  } else {
414  vertex_cluster->G4IDSingle = -1;
415  vertex_cluster->CompletenessSingle = -1.;
416  vertex_cluster->CleanlinessSingle = -1.;
417  }
418  // Now the primary trajectories
419  results = shower_truth.GetPrimaryTrajectories();
420  if (results.size() > 0) {
421  vertex_cluster->G4IDPrimary = results[0].ParticleID;
422  vertex_cluster->CompletenessPrimary = results[0].Completeness_NumHits;
423  vertex_cluster->CleanlinessPrimary = results[0].Cleanliness_NumHits;
424  } else {
425  vertex_cluster->G4IDPrimary = -1;
426  vertex_cluster->CompletenessPrimary = -1.;
427  vertex_cluster->CleanlinessPrimary = -1.;
428  }
429  // Finally the recursive trajectories
430  results = shower_truth.GetRecursiveTrajectories();
431  if (results.size() > 0) {
432  vertex_cluster->G4IDRecursive = results[0].ParticleID;
433  vertex_cluster->CompletenessRecursive = results[0].Completeness_NumHits;
434  vertex_cluster->CleanlinessRecursive = results[0].Cleanliness_NumHits;
435  } else {
436  vertex_cluster->G4IDRecursive = -1;
437  vertex_cluster->CompletenessRecursive = -1.;
438  vertex_cluster->CleanlinessRecursive = -1.;
439  }
440 
441  // Initialise the number of tracks and crossings to 0
442  vertex_cluster->NTracks = 0;
443  vertex_cluster->NCrossings = 0;
444 
445  // Now process the crossings
446  vertex_cluster->NCrossings = 0;
447 
448  for (ND::TReconObjectContainer::iterator crossIt = crossings->begin();
449  crossIt != crossings->end(); crossIt++) {
450  ND::THandle<ND::TReconVertex> input_crossing = (*crossIt);
451  TECALReconVertexCrossing* vertex_crossing =
452  new (((*vertex_cluster->Crossings))[vertex_cluster->NCrossings++])
454 
455  vertex_crossing->UniqueID = input_crossing->GetUniqueID();
456  Int_t NHits = input_crossing->GetHits()->size();
457  vertex_crossing->NHits = NHits;
458  vertex_crossing->HitCharges = new Float_t[NHits];
459  vertex_crossing->HitPositionsX = new Float_t[NHits];
460  vertex_crossing->HitPositionsY = new Float_t[NHits];
461  vertex_crossing->HitPositionsZ = new Float_t[NHits];
462  vertex_crossing->HitTimes = new Float_t[NHits];
463  vertex_crossing->HitLayerNumbers = new Int_t[NHits];
464  vertex_crossing->HitBarNumbers = new Int_t[NHits];
465 
466  for (ND::THitSelection::iterator hitIt =
467  input_crossing->GetHits()->begin();
468  hitIt != input_crossing->GetHits()->end(); hitIt++) {
469  int index = std::distance(input_crossing->GetHits()->begin(), hitIt);
470  vertex_crossing->HitCharges[index] = (*hitIt)->GetCharge();
471  TVector3 hit_position = (*hitIt)->GetPosition();
472 
473  vertex_crossing->HitPositionsX[index] = hit_position.X();
474  vertex_crossing->HitPositionsY[index] = hit_position.Y();
475  vertex_crossing->HitPositionsZ[index] = hit_position.Z();
476  vertex_crossing->HitTimes[index] = (*hitIt)->GetTime();
477  vertex_crossing->HitLayerNumbers[index] =
478  ecal_geom->GetLayerNumber((*hitIt));
479  vertex_crossing->HitBarNumbers[index] =
480  ecal_geom->GetBarNumber((*hitIt));
481 
482  // Now get the track IDs which created this crossing
483  vertex_crossing->NTracks = input_crossing->GetConstituents()->size();
484  vertex_crossing->TrackIDs = new UInt_t[vertex_crossing->NTracks];
485 
486  for (ND::TReconObjectContainer::iterator trackIt =
487  input_crossing->GetConstituents()->begin();
488  trackIt != input_crossing->GetConstituents()->end(); trackIt++) {
489  int index = std::distance(
490  input_crossing->GetConstituents()->begin(), trackIt);
491  vertex_crossing->TrackIDs[index] = (*trackIt)->GetUniqueID();
492  }
493  }
494  vertex_crossing->Position = input_crossing->GetPosition();
495  vertex_crossing->DOCA =
496  input_crossing->Get<ND::TRealDatum>("distance_of_closest_approach")
497  ->GetValue();
498  }
499  // Now start processing the tracks
500  vertex_cluster->NTracks = 0;
501  }
502 
503  double sumAllTracksCharge = 0;
504 
505  for (ND::TReconObjectContainer::iterator trackIt = tracks->begin();
506  trackIt != tracks->end(); trackIt++) {
507  ND::THandle<ND::TReconPID> input_track = (*trackIt);
508  // Create the TReconVertexTrack member on the TClonesArray
509 
510  if (fDoVertexing) {
511  if (!fSavedVertexTrackIds.count(input_track->GetUniqueID())) {
512  fSavedVertexTrackIds.insert(std::make_pair(input_track->GetUniqueID(),
514 
516  input_track, fIsMC,
518  trajectories);
519  ND280NamedVerbose("TTrackerECALReconModule",
520  "Saved track constituent of vertex "
521  "cluster with ID: "
522  << input_track->GetUniqueID());
523  }
524  } // end save vertexing tracks
525 
526  if (fDoSaveHoughResults) {
527  TECALReconVertexTrack* vertex_track = NULL;
528  if (fDoVertexing) {
529  vertex_track = new (
530  ((*vertex_cluster->Tracks))[vertex_cluster->NTracks++])
532  static_cast<ND::TTrackerECALReconModule::
533  TECALReconVertexTrack const&>(
535  fSavedVertexTrackIds[input_track->GetUniqueID()])));
536  } else {
538  input_track, fIsMC,
539  (*vertex_cluster->Tracks)[vertex_cluster->NTracks++],
540  trajectories);
541 
542  vertex_track =
544  vertex_cluster->Tracks->At(vertex_cluster->NTracks - 1));
545  }
546 
547  sumAllTracksCharge += vertex_track->TotalCharge;
548 
549 // Now we need to get the crossing IDs to associate to the track
550 // This is a little more complicated than the reverse situation we
551 // handled in the vertex_crossing section as crossings are NOT stored as
552 // constituents of the track
553 // The chosen method is to loop through all of the crossing and see if
554 // their constituent tracks match the track we are looking at :(
555 // You can work out how many crossings there are based on how many
556 // tracks
557 // are reconstructed but the below method gives you this number
558 // automatically
559 
560 #ifdef USE_FULL_VERTEX_TRACK_INFO
561  // Store the IDs in a temporary vector
562  std::vector<int> tempIDs;
563  // Loop over the crossings
564  for (ND::TReconObjectContainer::iterator crossIt = crossings->begin();
565  crossIt != crossings->end(); crossIt++) {
566  ND::THandle<ND::TReconVertex> crossing = (*crossIt);
567  // Now loop over the crossing constituents
568  for (ND::TReconObjectContainer::iterator trackIt =
569  crossing->GetConstituents()->begin();
570  trackIt != crossing->GetConstituents()->end(); trackIt++) {
571  ND::THandle<ND::TReconPID> track = (*trackIt);
572  // If the constituent unique id matches the track we are currently
573  // processing, the crossing was created using the track
574  if (track->GetUniqueID() == vertex_track->UniqueID) {
575  tempIDs.push_back(crossing->GetUniqueID()); // Store the crossing
576  // ID
577  break; // Track won't be more than one constituent of the
578  // crossing
579  }
580  }
581  }
582  // Now that we have stored the IDs in a vector, we can easily store the
583  // IDs in the TECALReconVertexTrack
584  vertex_track->NCrossings = tempIDs.size();
585  vertex_track->CrossingIDs = new UInt_t[vertex_track->NCrossings];
586  for (unsigned int i = 0; i < tempIDs.size(); i++) {
587  vertex_track->CrossingIDs[i] = tempIDs[i];
588  }
589 #endif
590 
591  if (sumAllTracksCharge >= vertex_cluster->TotalCharge) {
592  ND280NamedWarn(
593  "TTrackerECALReconModule",
594  "Vertex cluster charge: " << vertex_cluster->TotalCharge
595  << ", is less than the sum of the "
596  "constituent track charge: "
597  << sumAllTracksCharge);
598  vertex_cluster->TotalCharge = sumAllTracksCharge;
599  }
600  } // end if save hough result
601 
602  if (fDoVertexing) {
603  for (std::map<UInt_t, int>::iterator ts_it = vd.tracksStatus.begin();
604  ts_it != vd.tracksStatus.end(); ++ts_it) {
605  std::pair<UInt_t, int> const& trkSt = (*ts_it);
606 
607  /// This track was an intermediate object created during prong
608  /// merging.
609  if (trkSt.second == TECalVertexing::kReMergedTr) {
610  continue;
611  }
612 
613  if (fSavedVertexTrackIds.count(trkSt.first)) {
615  static_cast<
618  fSavedVertexTrackIds[trkSt.first]));
619  VT.Status = trkSt.second;
620  ND280NamedVerbose("TTrackerECALReconModule",
621  "Assigning saved track status: " << trkSt.second);
622 
623  } else {
624  ND280NamedSevere(
625  "TTrackerECALReconModule",
626  "Failed to find vertex track with ID: " << trkSt.first);
627  throw;
628  }
629  }
630  } // end fDoVertexing
631  } // end vertex tracks loop
632  } // end vertex loop
633 }
634 
635 int GetTIntegerDatumValue(ND::THandle<ND::TReconBase> trb, char const* name,
636  int const& defaultValue) {
637  if (!trb->Get<ND::TIntegerDatum>(name)) {
638  ND280NamedWarn("TTrackerECALReconModule",
639  "Could not retrieve TIntegerDatum: \"" << name << "\".");
640  return defaultValue;
641  }
642  return trb->Get<ND::TIntegerDatum>(name)->GetValue();
643 }
644 
646  ND::THandle<ND::TAlgorithmResult> ecalFinalResult,
647  ND::THandle<ND::TG4TrajectoryContainer> trajectories) {
648  ND::THandle<ND::TReconObjectContainer> ECalVertices =
649  ecalFinalResult->GetResultsContainer("ECalVertexingResults");
650 
651  if ((!ECalVertices) || (!ECalVertices->size())) {
652  return;
653  }
654 
655  for (size_t vd_it = 0; vd_it < ECalVertices->size(); ++vd_it) {
656  ND::THandle<ND::TReconVertex> ECalVtx = ECalVertices->at(vd_it);
657 
658  if (!ECalVtx->GetConstituents() || !ECalVtx->GetConstituents()->size()) {
659  return;
660  }
661 
662  UInt_t VCUID = GetTIntegerDatumValue(ECalVtx, "OVCUID", -1);
663 
665  ECalVtx, VCUID, fIsMC, (*fVertexCandidates)[fNVertexCandidates++]);
666 
667  for (UInt_t const_it = 0; const_it < ECalVtx->GetConstituents()->size();
668  ++const_it) {
669  ND::THandle<ND::TReconPID> trk = ECalVtx->GetConstituents()->at(const_it);
670  if (trk) {
671  if (!fSavedVertexTrackIds.count(trk->GetUniqueID())) {
672  fSavedVertexTrackIds.insert(
673  std::make_pair(trk->GetUniqueID(), fNVertexCandidateTracks));
676  trajectories);
677  ND280NamedVerbose(
678  "TTrackerECALReconModule",
679  "Saved track constituent of vertex candidate with ID: "
680  << trk->GetUniqueID());
681  }
682  continue;
683  }
684  ND::THandle<ND::TReconVertex> vtx =
685  ECalVtx->GetConstituents()->at(const_it);
686  if (vtx) {
688  ECalVtx, VCUID, fIsMC, (*fVertexCandidates)[fNVertexCandidates++]);
689 
690  for (UInt_t const_it = 0; const_it < ECalVtx->GetConstituents()->size();
691  ++const_it) {
692  ND::THandle<ND::TReconPID> trk =
693  ECalVtx->GetConstituents()->at(const_it);
694  if (trk) {
695  if (!fSavedVertexTrackIds.count(trk->GetUniqueID())) {
696  fSavedVertexTrackIds.insert(
697  std::make_pair(trk->GetUniqueID(), fNVertexCandidateTracks));
699  trk, fIsMC,
701  trajectories);
702  ND280NamedVerbose(
703  "TTrackerECALReconModule",
704  "Saved track constituent of vertex candidate with ID: "
705  << trk->GetUniqueID());
706  }
707  }
708  }
709  } // end if secondary vertex
710  }
711  }
712 }
713 
715  ND::THandle<ND::TAlgorithmResult> ecalFinalResult,
716  ND::THandle<ND::TG4TrajectoryContainer> trajectories) {
718  FillHoughTransformInformation(ecalFinalResult, trajectories);
719  }
721  FillECalIsoVertexingInformation(ecalFinalResult, trajectories);
722  }
723 }
724 
726  ND::THandle<ND::TReconCluster> cluster, bool IsMC, void* pos) {
727  if (!cluster) {
728  ND280NamedWarn("TTrackerECALReconModule",
729  "Attempting to fill "
730  "TECALReconUnmatchedObject from bad TReconCluster.");
731  return NULL;
732  }
733  TECALReconUnmatchedObject* unmatchedObject = NULL;
734  if (pos != NULL) {
735  unmatchedObject = new (pos) TECALReconUnmatchedObject;
736  } else {
737  unmatchedObject = new TECALReconUnmatchedObject;
738  }
739 
740  FillHitInfo(unmatchedObject, cluster->GetHits());
741 
742  if (IsMC) { // Fill the truth-matching info.
743  ND::TShowerTruthInfo showerTruth(cluster);
744 
745  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
746  showerTruth.GetPrimaryTrajectories();
747  if (results.size()) {
748  unmatchedObject->G4ID_Primary = results[0].ParticleID;
749  }
750 
751  results = showerTruth.GetRecursiveTrajectories();
752  if (results.size()) {
753  unmatchedObject->G4ID_Recursive = results[0].ParticleID;
754  }
755 
756  results = showerTruth.GetSingleTrajectories();
757  if (results.size()) {
758  unmatchedObject->G4ID_Single = results[0].ParticleID;
759  }
760  }
761  return unmatchedObject;
762 }
763 
765  ND::THandle<ND::TReconObjectContainer> other) {
766  if (!other) {
767  ND280NamedWarn("TTrackerECALReconModule",
768  "Recieved bad \"other\" container.");
769  return;
770  }
771 
772  for (ND::TReconObjectContainer::iterator cl_it = other->begin();
773  cl_it != other->end(); ++cl_it) {
774  ND::THandle<ND::TReconCluster> clust = (*cl_it);
775 
776  if (!clust) {
777  ND280NamedWarn("TTrackerECALReconModule",
778  "Found an invalid "
779  "TReconCluster in the \"other\" container.");
780  continue;
781  }
782 
783  if (clust->GetHits() && clust->GetHits()->size()) {
786  }
787  }
788 }
789 
790 TECALReconObject* TECALReconObjectFactory(ND::THandle<ND::TReconTrack> track,
791  ND::THandle<ND::TReconPID> pid,
792  bool IsMC, void* pos, bool Allocate) {
793  ND280NamedInfo("TTrackerECALReconModule",
794  "Found " << track->GetConstituents()->size()
795  << " PID-track-constituent cluster constituent(s).");
796 
797  TECALReconObject* obj = NULL;
798  if (Allocate) {
799  if (pos != NULL) {
800  obj = new (pos) TECALReconObject;
801  } else {
802  obj = new TECALReconObject;
803  }
804  } else {
805  obj = static_cast<TECALReconObject*>(pos);
806  }
807 
808  obj->FilledAsTrack = true;
809  obj->FilledAsShower = false;
810 
811  /// This is to identically emulate previous functionality, but it seems
812  /// a bit odd, if this is ever more than one then info has been thrown away
813  /// without any regard to which set is better.
814  int NReconClusters = 0;
815  for (ND::TReconObjectContainer::iterator constit_clus_tit =
816  track->GetConstituents()->begin();
817  constit_clus_tit != track->GetConstituents()->end();
818  ++constit_clus_tit) {
819  ND::THandle<ND::TReconCluster> cluster = (*constit_clus_tit);
820  if (!cluster) {
821  ND280NamedWarn("TTrackerECALReconModule",
822  "PID-track-constituent cluster constituent was bad.");
823  continue;
824  }
825  obj->Cluster.NDOF = cluster->GetNDOF();
826  obj->Cluster.Position = cluster->GetPosition();
827  obj->Cluster.PositionVar = cluster->GetPositionVariance();
828  obj->Cluster.EDeposit = cluster->GetEDeposit();
829 
830  NReconClusters++;
831  }
832 
833  // If tracks have hits grab some hit lvl information. It may
834  // make sense in the future to remove some of this info when
835  // we have a working hit lvl information module.
836 
837  // Save the unique object ID to allow matching to global recon objects
838  obj->UniqueID = pid->GetUniqueID();
839 
840  // Calculate the pointing vector.
841  TVector3 Pointing(-9999, -9999, -9999);
842  if (track->GetHits()) {
843  ND::THandle<ND::THitSelection> hitsel = track->GetHits();
844 
845  FillHitInfo(obj, hitsel);
846  Pointing = CalculatePointing(hitsel);
847  if (IsMC) {
848  obj->G4ID = TrackTruthInfo::GetG4TrajIDHits(*hitsel);
849 
850  // Fill the truth-matching information from the new truth-matching
851  // algorithms.
852  ND::TShowerTruthInfo showerTruth(pid);
853 
854  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
855  showerTruth.GetPrimaryTrajectories();
856  if (results.size() > 0) {
857  obj->G4ID_Primary = results[0].ParticleID;
858  obj->Completeness_Primary = results[0].Completeness_NumHits;
859  obj->Cleanliness_Primary = results[0].Cleanliness_NumHits;
860  }
861 
862  results = showerTruth.GetRecursiveTrajectories();
863  if (results.size() > 0) {
864  obj->G4ID_Recursive = results[0].ParticleID;
865  obj->Completeness_Recursive = results[0].Completeness_NumHits;
866  obj->Cleanliness_Recursive = results[0].Cleanliness_NumHits;
867  }
868  if (results.size() > 1) {
869  obj->G4ID_Recursive2 = results[1].ParticleID;
870  }
871  if (results.size() > 2) {
872  obj->G4ID_Recursive3 = results[2].ParticleID;
873  }
874  if (results.size() > 3) {
875  obj->G4ID_Recursive4 = results[3].ParticleID;
876  }
877 
878  results = showerTruth.GetSingleTrajectories();
879  if (results.size() > 0) {
880  obj->G4ID_Single = results[0].ParticleID;
881  obj->Completeness_Single = results[0].Completeness_NumHits;
882  obj->Cleanliness_Single = results[0].Cleanliness_NumHits;
883  }
884  }
885  }
886  obj->Pointing = Pointing;
887 
888  // Collecting information stored in a TReconTrack..
889  obj->Track.Direction = track->GetDirection();
890  obj->Track.EDeposit = track->GetEDeposit();
891  obj->Track.Position = track->GetPosition();
892  obj->Track.PositionVar = track->GetPositionVariance();
893  obj->Track.BackPosition =
894  FindBackPosition(track->GetHits(), obj->MostDownStreamLayerHit);
895  obj->Track.Width = track->GetWidth();
896 
897  // Adding the Information stored in Datums in the Track
898  // This for example includes parametres used in the Pid and
899  // Energy Recon.
900  FillDatumInfo(obj, track);
901 
902  // Adding properties of the Alternative EMShower Hypothesis
903  ND280NamedInfo("TTrackerECALReconModule", "Track PID had "
904  << pid->GetAlternates().size()
905  << " alternates.");
906  for (ND::TReconObjectContainer::const_iterator altIter =
907  pid->GetAlternates().begin();
908  altIter != pid->GetAlternates().end(); ++altIter) {
909  ND::THandle<ND::TReconPID> altPID = (*altIter);
910  if (!altPID) {
911  ND280NamedWarn("TTrackerECALReconModule", "Alternate PID is invalid.");
912  continue;
913  }
914 
915  if (!altPID->GetConstituents() || !altPID->GetConstituents()->size()) {
916  ND280NamedWarn("TTrackerECALReconModule",
917  "Alternate Shower PID has no constituents.");
918  continue;
919  }
920 
921  for (ND::TReconObjectContainer::iterator alt_constit_it =
922  altPID->GetConstituents()->begin();
923  alt_constit_it != altPID->GetConstituents()->end(); ++alt_constit_it) {
924  ND::THandle<ND::TReconShower> shower_alt = (*alt_constit_it);
925  if (!shower_alt || !shower_alt->GetEDeposit()) {
926  continue;
927  }
928 
929  obj->Shower.ConeAngle = shower_alt->GetConeAngle();
930  obj->Shower.Direction = shower_alt->GetDirection();
931  obj->Shower.EDeposit = shower_alt->GetEDeposit();
932  obj->Shower.Position = shower_alt->GetPosition();
933  obj->Shower.PositionVar = shower_alt->GetPositionVariance();
934  obj->Shower.BackPosition =
935  FindBackPosition(shower_alt->GetHits(), obj->MostDownStreamLayerHit);
936  }
937  }
938  return obj;
939 }
940 
941 TECALReconObject* TECALReconObjectFactory(ND::THandle<ND::TReconShower> shower,
942  ND::THandle<ND::TReconPID> pid,
943  bool IsMC, void* pos, bool Allocate) {
944  ND280NamedInfo("TTrackerECALReconModule",
945  "Found " << shower->GetConstituents()->size()
946  << " PID-shower-constituent cluster constituent(s).");
947 
948  TECALReconObject* obj = NULL;
949  if (Allocate) {
950  if (pos != NULL) {
951  obj = new (pos) TECALReconObject;
952  } else {
953  obj = new TECALReconObject;
954  }
955  } else {
956  obj = static_cast<TECALReconObject*>(pos);
957  }
958 
959  obj->FilledAsTrack = false;
960  obj->FilledAsShower = true;
961 
962  /// This is to identically emulate previous functionality, but it seems
963  /// a bit odd, if this is ever more than one then info has been thrown away
964  /// without any regard to which set is better.
965  int NReconClusters = 0;
966  for (ND::TReconObjectContainer::iterator constit_clus_tit =
967  shower->GetConstituents()->begin();
968  constit_clus_tit != shower->GetConstituents()->end();
969  ++constit_clus_tit) {
970  ND::THandle<ND::TReconCluster> cluster = (*constit_clus_tit);
971  if (!cluster) {
972  ND280NamedWarn("TTrackerECALReconModule",
973  "PID-shower-constituent cluster constituent was bad.");
974  continue;
975  }
976  obj->Cluster.NDOF = cluster->GetNDOF();
977  obj->Cluster.Position = cluster->GetPosition();
978  obj->Cluster.PositionVar = cluster->GetPositionVariance();
979  obj->Cluster.EDeposit = cluster->GetEDeposit();
980 
981  NReconClusters++;
982  }
983 
984  // If showers has hits grab some hit lvl information. It may
985  // make sense in the future to remove some of this info when
986  // we have a working hit lvl information module.
987 
988  // Save the unique object ID to allow matching to global recon objects
989  obj->UniqueID = pid->GetUniqueID();
990 
991  // Calculate the pointing vector.
992  TVector3 Pointing(-9999, -9999, -9999);
993 
994  if (shower->GetHits()) {
995  ND::THandle<ND::THitSelection> hitsel = shower->GetHits();
996 
997  FillHitInfo(obj, hitsel);
998  Pointing = CalculatePointing(hitsel);
999  if (IsMC) {
1000  obj->G4ID = TrackTruthInfo::GetG4TrajIDHits(*hitsel);
1001 
1002  // Fill the truth-matching information from the new truth-matching
1003  // algorithms.
1004  ND::TShowerTruthInfo showerTruth(pid);
1005 
1006  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
1007  showerTruth.GetPrimaryTrajectories();
1008  if (results.size() > 0) {
1009  obj->G4ID_Primary = results[0].ParticleID;
1010  obj->Completeness_Primary = results[0].Completeness_NumHits;
1011  obj->Cleanliness_Primary = results[0].Cleanliness_NumHits;
1012  }
1013  results = showerTruth.GetRecursiveTrajectories();
1014  if (results.size() > 0) {
1015  obj->G4ID_Recursive = results[0].ParticleID;
1016  obj->Completeness_Recursive = results[0].Completeness_NumHits;
1017  obj->Cleanliness_Recursive = results[0].Cleanliness_NumHits;
1018  }
1019  if (results.size() > 1) {
1020  obj->G4ID_Recursive2 = results[1].ParticleID;
1021  }
1022  if (results.size() > 2) {
1023  obj->G4ID_Recursive3 = results[2].ParticleID;
1024  }
1025  if (results.size() > 3) {
1026  obj->G4ID_Recursive4 = results[3].ParticleID;
1027  }
1028  results = showerTruth.GetSingleTrajectories();
1029  if (results.size() > 0) {
1030  obj->G4ID_Single = results[0].ParticleID;
1031  obj->Completeness_Single = results[0].Completeness_NumHits;
1032  obj->Cleanliness_Single = results[0].Cleanliness_NumHits;
1033  }
1034  }
1035  }
1036 
1037  obj->Pointing = Pointing;
1038  obj->Shower.ConeAngle = shower->GetConeAngle();
1039  obj->Shower.Direction = shower->GetDirection();
1040  obj->Shower.EDeposit = shower->GetEDeposit();
1041  obj->Shower.Position = shower->GetPosition();
1042  obj->Shower.PositionVar = shower->GetPositionVariance();
1043  obj->Shower.BackPosition =
1044  FindBackPosition(shower->GetHits(), obj->MostDownStreamLayerHit);
1045 
1046  // Adding the Information stored in Datums in the Shower
1047  // This for example includes parametres using in TMVA and Energy
1048  // fitting.
1049  FillDatumInfo(obj, shower);
1050 
1051  ND280NamedInfo("TTrackerECALReconModule", "Shower PID had "
1052  << pid->GetAlternates().size()
1053  << " alternates.");
1054  for (ND::TReconObjectContainer::const_iterator altIter =
1055  pid->GetAlternates().begin();
1056  altIter != pid->GetAlternates().end(); ++altIter) {
1057  ND::THandle<ND::TReconPID> altPID = (*altIter);
1058  if (!altPID) {
1059  ND280NamedWarn("TTrackerECALReconModule", "Alternate PID is invalid.");
1060  continue;
1061  }
1062 
1063  if (!altPID->GetConstituents() || !altPID->GetConstituents()->size()) {
1064  ND280NamedWarn("TTrackerECALReconModule",
1065  "Alternate Track PID has no constituents.");
1066  continue;
1067  }
1068 
1069  for (ND::TReconObjectContainer::iterator alt_constit_it =
1070  altPID->GetConstituents()->begin();
1071  alt_constit_it != altPID->GetConstituents()->end(); ++alt_constit_it) {
1072  ND::THandle<ND::TReconTrack> track_alt = (*alt_constit_it);
1073  if (!track_alt || !track_alt->GetEDeposit()) {
1074  continue;
1075  }
1076 
1077  obj->Track.Direction = track_alt->GetDirection();
1078  obj->Track.EDeposit = track_alt->GetEDeposit();
1079  obj->Track.Position = track_alt->GetPosition();
1080  obj->Track.PositionVar = track_alt->GetPositionVariance();
1081  obj->Track.BackPosition =
1082  FindBackPosition(track_alt->GetHits(), obj->MostDownStreamLayerHit);
1083  obj->Track.Width = track_alt->GetWidth();
1084  }
1085  }
1086  return obj;
1087 }
1088 
1090  ND::THandle<ND::TReconObjectContainer> final) {
1091  if (!final) {
1092  ND280NamedWarn("TTrackerECALReconModule",
1093  "Recieved bad \"final\" container.");
1094  return;
1095  }
1096 
1097  // Loop looking for TReconPID's in the top recon conatiner
1098  for (ND::TReconObjectContainer::iterator pid_it = final->begin();
1099  pid_it != final->end(); ++pid_it) {
1100  ND::THandle<ND::TReconPID> pid = (*pid_it);
1101 
1102  if (!pid) {
1103  ND280NamedWarn("TTrackerECALReconModule",
1104  "Found bad PID in the "
1105  "\"final\" container.");
1106  continue;
1107  }
1108  if (!pid->GetConstituents() || !pid->GetConstituents()->size()) {
1109  ND280NamedWarn("TTrackerECALReconModule", "PID has no constituents.");
1110  continue;
1111  }
1112  ND280NamedInfo("TTrackerECALReconModule",
1113  "PID has " << pid->GetConstituents()->size()
1114  << " constituents.");
1115 
1116  for (ND::TReconObjectContainer::iterator constit_it =
1117  pid->GetConstituents()->begin();
1118  constit_it != pid->GetConstituents()->end(); ++constit_it) {
1119  ND::THandle<ND::TReconTrack> track_constit = (*constit_it);
1120  ND::THandle<ND::TReconShower> shower_constit = (*constit_it);
1121 
1122  // Only the implicit dynamic casts that are valid will result in a new
1123  // object.
1124  if (track_constit) {
1125  if (!track_constit->GetEDeposit()) {
1126  ND280NamedWarn("TTrackerECALReconModule",
1127  "PID-constituent track deposited no energy.");
1128  continue;
1129  }
1130  // Making a TECALReconObject ClonesArray entry...
1131  TECALReconObjectFactory(track_constit, pid, fIsMC,
1133  fTotal++;
1134  fNReconTrackLike++;
1135 
1136  ND280NamedInfo("TTrackerECALReconModule",
1137  "Added information about a Track PID constituent.");
1138  } else if (shower_constit) {
1139  if (!shower_constit->GetEDeposit()) {
1140  ND280NamedWarn("TTrackerECALReconModule",
1141  "PID-constituent shower deposited no energy.");
1142  continue;
1143  }
1144 
1145  TECALReconObjectFactory(shower_constit, pid, fIsMC,
1147  fTotal++;
1149 
1150  ND280NamedInfo("TTrackerECALReconModule",
1151  "Added information about a Shower PID constituent.");
1152  }
1153  }
1154  }
1155 }
1156 
1158  fNReconObjects = 0;
1159  fNUnmatchedObjects = 0;
1160  fNReconTrackLike = 0;
1161  fNReconShowerLike = 0;
1163 
1164 #ifdef TTRACKERECALRECONMODULE_USE_EXP
1165  fNUsedHits = 0;
1166  fSavedHitMap.clear();
1167  fUsedHits->Clear();
1168 #endif
1169  fNVertexCandidates = 0;
1171  fSavedVertexTrackIds.clear();
1172  fVertexCandidates->Clear();
1173  fVertexCandidateTracks->Clear();
1174  fReconObjects->Clear();
1175  fUnmatchedObjects->Clear();
1176  fReconVertexClusters->Clear();
1177  ND280NamedInfo("TTrackerECALReconModule", "===============================");
1178  ND280NamedInfo("TTrackerECALReconModule", "=========Clearing Event========");
1179  ND280NamedInfo("TTrackerECALReconModule", "===============================");
1180 }
1181 
1182 bool OutputManager::FillTree(ND::TND280Event& event) {
1183  ND280NamedInfo("TTrackerECALReconModule",
1184  "Processing event: " << event.GetContext().GetEvent());
1185  PerEvReset();
1186 
1187  // Getting the final Algorithm Result from ecalRecon.
1188  ND::THandle<ND::TAlgorithmResult> ecalReconResult = event.GetFit("ecalRecon");
1189 
1190  if (!ecalReconResult) {
1191  ND280NamedWarn("TTrackerECALReconModule",
1192  "Couldn't find the ecalRecon algorithm result.");
1193  return true;
1194  }
1195  ND::THandle<ND::TReconObjectContainer> ecalFinal =
1196  ecalReconResult->GetResultsContainer("final");
1197 
1198  if (!ecalFinal) {
1199  ND280NamedWarn("TTrackerECALReconModule",
1200  "Couldn't find a valid ecalRecon \"final\" container");
1201  } else {
1202  ProcessFinalContainer(ecalFinal);
1203  }
1204  ND::THandle<ND::TReconObjectContainer> ecalOther =
1205  ecalReconResult->GetResultsContainer("other");
1206  if (!ecalOther) {
1207  ND280NamedWarn("TTrackerECALReconModule",
1208  "Couldn't find a valid ecalRecon \"other\" container");
1209  } else {
1210  ProcessOtherContainer(ecalOther);
1211  }
1212 
1213  ND::THandle<ND::TG4TrajectoryContainer> trajectories(NULL);
1214  if (fIsMC) {
1215  trajectories =
1216  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
1217  }
1218 
1219  FillVertexingInformation(ecalReconResult, trajectories);
1220  return true;
1221 }
1222 
1224  G4ID_Primary = -1;
1225  Completeness_Primary = -1;
1226  Cleanliness_Primary = -1;
1227  G4ID_Recursive = -1;
1229  Cleanliness_Recursive = -1;
1230  G4ID_Single = -1;
1231  Completeness_Single = -1;
1232  Cleanliness_Single = -1;
1233 }
1234 
1235 void FillHitInfo(TECALReconObject* obj, ND::THandle<ND::THitSelection> hitsel) {
1236  // Setting hit lvl quantities to appropriate start values
1237  obj->MostUpStreamLayerHit = 36;
1238  obj->MostDownStreamLayerHit = -1;
1239  obj->MaxPerpBarHit = -1;
1240  obj->MaxParaBarHit = -1;
1241  obj->MinBarHit = 100;
1242  obj->NLayersHit = 0;
1243  obj->NHits = 0;
1244  obj->TotalHitCharge = 0;
1245  obj->AverageHitTime = 0;
1246  obj->NIsXHits = 0;
1247  obj->NIsYHits = 0;
1248  obj->NIsZHits = 0;
1249  obj->ObjectLength = 0.0;
1250  obj->AverageZPosition = 0.0;
1251 
1252  std::string module;
1253 
1254  bool layer[36] = {false};
1255  std::vector<TVector3> layerHitPos(36);
1256  std::vector<double> layerCharge(36, 0.0);
1257 
1258  // Vector to store the layer for each hit
1259  std::vector<int> layerhits;
1260  layerhits.reserve(hitsel->size());
1261  double HitCharge = -1;
1262 
1263  // Looping through hits and filling the Hit info
1264  for (ND::THitSelection::iterator hit_it = hitsel->begin();
1265  hit_it != hitsel->end(); ++hit_it) {
1266  ND::THandle<ND::TReconHit> reconHit = (*hit_it);
1267 
1268  if (!reconHit) {
1269  ND280NamedWarn("TTrackerECALReconModule", "TReconHit is invalid.");
1270  continue;
1271  }
1272 
1273  TVector3 HitPos = reconHit->GetContributor(0)->GetPosition();
1274  ND::TGeometryId HitGID = reconHit->GetContributor(0)->GetGeomId();
1275 
1276  Int_t layerHit = ND::TGeomInfo::Get().ECAL().GetLayerNumber(HitGID);
1277  Int_t barHit = ND::TGeomInfo::Get().ECAL().GetBarNumber(HitGID);
1278 
1279  layerhits.push_back(layerHit);
1280 
1281  if (hit_it == hitsel->begin()) {
1282  module = ND::TGeomInfo::Get().ECAL().GetModule(HitGID).GetName();
1283  }
1284 
1285  // Average Z Position
1286  obj->AverageZPosition += HitPos.Z();
1287 
1288  // Charge weighted layer positon
1289  TVector3 chargePos = reconHit->GetPosition() * reconHit->GetCharge();
1290  layerHitPos[layerHit] += chargePos;
1291  layerCharge[layerHit] += reconHit->GetCharge();
1292 
1293  // Using the array to collect the number of layers hit.
1294  if (!layer[layerHit]) {
1295  layer[layerHit] = true;
1296  obj->NLayersHit++;
1297  }
1298  // Filling numbers on hits in different types of bars.
1299  if (reconHit->GetContributor(0)->IsXHit()) {
1300  obj->NIsXHits++;
1301  }
1302  if (reconHit->GetContributor(0)->IsYHit()) {
1303  obj->NIsYHits++;
1304  }
1305  if (reconHit->GetContributor(0)->IsZHit()) {
1306  obj->NIsZHits++;
1307  }
1308  // Obtaining the max and min bars hit
1309  if (barHit < obj->MinBarHit) {
1310  obj->MinBarHit = barHit;
1311  }
1312  if ((barHit > obj->MaxParaBarHit) &&
1313  (!reconHit->GetContributor(0)->IsZHit())) {
1314  obj->MaxParaBarHit = barHit;
1315  }
1316  if ((barHit > obj->MaxPerpBarHit) &&
1317  reconHit->GetContributor(0)->IsZHit()) {
1318  obj->MaxPerpBarHit = barHit;
1319  }
1320  // Obtaining the first and last layers hit.
1321  if (layerHit < obj->MostUpStreamLayerHit) {
1322  obj->MostUpStreamLayerHit = layerHit;
1323  }
1324  if (layerHit > obj->MostDownStreamLayerHit) {
1325  obj->MostDownStreamLayerHit = layerHit;
1326  }
1327  // Collecting other useful hit information
1328  obj->NHits++;
1329  obj->TotalHitCharge += reconHit->GetCharge();
1330  obj->AverageHitTime += (reconHit->GetTime() * reconHit->GetCharge());
1331  // Save the layer with the highest hit charge
1332  if (reconHit->GetCharge() > HitCharge) {
1333  HitCharge = reconHit->GetCharge();
1334  obj->MaxHitChargeLayer = (layerHit + 1);
1335  }
1336  } // End hit loop
1337 
1338  obj->Module = module;
1339  obj->AverageHitTime /= obj->TotalHitCharge;
1340  obj->AverageZPosition /= obj->NHits;
1341 
1342  // Charge weighted layer position
1343  for (int i = 0; i < 36; ++i) {
1344  if (layerCharge[i] != 0.0) {
1345  layerHitPos[i] *= (1 / layerCharge[i]);
1346  }
1347  }
1348 
1349  // Now calculate object length
1350  TVector3 objLength = (layerHitPos[obj->MostDownStreamLayerHit] -
1351  layerHitPos[obj->MostUpStreamLayerHit]);
1352  obj->ObjectLength = objLength.Mag();
1353 
1354  // Sort the layer for each hit by increasing order
1355  sort(layerhits.begin(), layerhits.end());
1356  // Temporary variables to be used
1357  // used to calculate the number of hits in the same layer.
1358  // This is used to count the number of layers with 1,2,3,4,5,6 or 7 hits
1359  int seclayer = -1;
1360  // used to calculate the exact number of hits in the same layer.
1361  // This is used to know the number of hits in a layer with many hits
1362  int doublelayer = -1;
1363  // used as a flag to count the first,second,third and last layer with many
1364  // hits
1365  int doublelayersec = -1;
1366  // counts the first layer with two or more hits
1367  int layertwohits = -1;
1368  // counts the last layer with two or more hits
1369  int lastlayermanyhits = -1;
1370  // used as a flag to find when there are more than one hit in a layer
1371  int layerA = -1;
1372  // used as a flag to stop multiple counting of first,second third and last
1373  // layer with many hits
1374  int layerB = -1;
1375  // counts the number of layers with at least two hits
1376  int NLayers2Hits = -1;
1377  // counts the number of layers with at least three hits
1378  int NLayers3Hits = -1;
1379  // the number of hits in the layer that received the most hits
1380  int maxhits = -1;
1381 
1382  // loop over all the ordered hits
1383  for (unsigned int i = 0; i < layerhits.size(); i++) {
1384  int layer = layerhits.at(i);
1385 
1386  // this hit is in a different layer to the previous hit
1387  if (layer > layerA) {
1388  layerA = layer;
1389  seclayer = -1;
1390  } else { // found a hit in the same layer as the previous hit
1391  // count the number of hits in this layer
1392  seclayer++;
1393  // do the same again (this time so we know exactly how many hits there
1394  // were in this layer
1395  doublelayer++;
1396  lastlayermanyhits = layer;
1397  // Now we just want to know if this is the first,second or third layer
1398  // which had two or more hits
1399  if (layer > layerB) {
1400  layerB = layer;
1401  doublelayersec++;
1402  if (doublelayersec == 0) {
1403  layertwohits = layer;
1404  }
1405  }
1406 
1407  // see if this layer has had the most hits
1408  if (seclayer > maxhits) {
1409  maxhits = seclayer;
1410  }
1411 
1412  // see if this layer has at least 2,3,4,5,6 or 7 hits
1413  if (seclayer == 0) {
1414  NLayers2Hits++;
1415  } else if (seclayer == 1) {
1416  NLayers3Hits++;
1417  }
1418  }
1419  }
1420 
1421  // Save the variables - The first layer is always starting from 1
1422  obj->NHitsAtLayersWithManyHits = (doublelayer + 1);
1423  obj->NLayersTwoHits = (NLayers2Hits + 1);
1424  obj->NLayersThreeHits = (NLayers3Hits + 1);
1425  obj->FirstLayerManyHits = (layertwohits + 1);
1426  obj->LastLayerManyHits = (lastlayermanyhits + 1);
1427  obj->MaxHitsInALayer = (maxhits + 1);
1428 }
1429 
1430 double GetTRealDatumValue(ND::THandle<ND::TReconBase> trb, char const* name,
1431  double const& defaultValue) {
1432  if (!trb->Get<ND::TRealDatum>(name)) {
1433  ND280NamedWarn("TTrackerECALReconModule",
1434  "Could not retrieve TRealDatum: \"" << name << "\".");
1435  return defaultValue;
1436  }
1437  return trb->Get<ND::TRealDatum>(name)->GetValue();
1438 }
1439 
1440 void FillDatumInfo(TECALReconObject* obj, ND::THandle<ND::TReconBase> trb) {
1441  if (!trb) {
1442  ND280NamedWarn("TTrackerECALReconModule",
1443  "TReconBase was invalid in FillDatumInfo.");
1444  return;
1445  }
1446 
1447  // =========================Pid Vars==========================
1448  // ----------
1449 
1450  // Circularity
1451  // Combined and in each view
1452  obj->PID_Circularity = GetTRealDatumValue(trb, "Circularity", -1);
1453 
1454  // Containment
1455  // This isn't a PID variable, but it's easy to save it the same way.
1456  obj->Containment = GetTRealDatumValue(trb, "Containment", -1);
1457 
1458  obj->PID_Angle = GetTRealDatumValue(trb, "Angle", -1);
1459 
1460  obj->PID_TruncatedMaxRatio = GetTRealDatumValue(trb, "TruncatedMaxRatio", -1);
1461 
1463  GetTRealDatumValue(trb, "TransverseChargeRatio", -1);
1464 
1465  // FrontBackRatio. Note - Assumes particle is coming from the
1466  // tracker into the ECal
1467  if (trb->Get<ND::TRealDatum>("FrontBackRatio")) {
1468  obj->PID_FrontBackRatio =
1469  trb->Get<ND::TRealDatum>("FrontBackRatio")->GetValue();
1470  } else {
1471  ND::THandle<ND::THitSelection> hits = trb->Get<ND::THitSelection>("hits");
1472  double FrontBackRatio = -1;
1473  if (hits) {
1474  FrontBackRatio = CalculateFrontBackRatio(hits);
1475  }
1476  obj->PID_FrontBackRatio = FrontBackRatio;
1477  }
1478 
1479  obj->PID_ShowerAngle = GetTRealDatumValue(trb, "ShowerAngle", -1);
1480 
1481  obj->PID_Asymmetry = GetTRealDatumValue(trb, "Asymmetry", -1);
1482 
1483  obj->PID_LLR_Quality = GetTRealDatumValue(trb, "LLR_Quality", -9999.0);
1484 
1485  obj->PID_LLR_MIP_EM = GetTRealDatumValue(trb, "LLR_MIP_EM", -9999.0);
1486 
1487  obj->PID_LLR_MIP_Pion = GetTRealDatumValue(trb, "LLR_MIP_Pion", -9999.0);
1488 
1489  obj->PID_LLR_EM_HIP = GetTRealDatumValue(trb, "LLR_EM_HIP", -9999.0);
1490 
1492  GetTRealDatumValue(trb, "LLR_MIP_EM_LowMomentum", -9999.0);
1493 
1494  ND280NamedInfo("TTrackerECALReconModule",
1495  "TReconBase has " << trb->GetConstituents()->size()
1496  << " constituents.");
1497  for (ND::TReconObjectContainer::iterator trb_it =
1498  trb->GetConstituents()->begin();
1499  trb_it != trb->GetConstituents()->end(); ++trb_it) {
1500  ND::THandle<ND::TReconCluster> cluster_constit = (*trb_it);
1501  if (!cluster_constit) {
1502  ND280NamedWarn("TTrackerECALReconModule",
1503  "TReconBase cluster constituent"
1504  " is invalid.");
1505  continue;
1506  }
1507 
1508  // ====================3D Clustering Variables========================
1509  // ------------------
1510 
1511  // 3D Clustering Seed Type
1512  if (cluster_constit->Get<ND::TIntegerDatum>("3DSeedType")) {
1513  obj->Clustering_3DSeedType =
1514  cluster_constit->Get<ND::TIntegerDatum>("3DSeedType")->GetValue();
1515  } else {
1516  obj->Clustering_3DSeedType = -1; // not a 3D cluster, sed to minus 1.
1517  }
1518 
1519  // ====================Energy Variables========================
1520  // ------------------
1521 
1522  // EM Energy Fit Result
1523  if (cluster_constit->Get<ND::TRealDatum>("EMEnergyFitResult_Corrected")) {
1524  obj->EMEnergyFit_Result =
1525  (*cluster_constit->Get<ND::TRealDatum>("EMEnergyFitResult_Corrected")
1526  ->begin());
1527  } else {
1528  obj->EMEnergyFit_Result = -1;
1529  }
1530 
1532  GetTRealDatumValue(trb, "EMEnergyFitUncertainty_Corrected", -1);
1533 
1534  // EM Energy Fit Likelihoods
1535  ND::THandle<ND::TRealDatum> emefl =
1536  cluster_constit->Get<ND::TRealDatum>("EMEnergyFitLikelihood");
1537  if (emefl && (emefl->size() >= 3)) {
1538  obj->EMEnergyFit_Likelihood_energyGrad = emefl->at(0);
1539  obj->EMEnergyFit_Likelihood_qsum_like = emefl->at(1);
1540  obj->EMEnergyFit_Likelihood_energy_qsumGrad = emefl->at(2);
1541  } else {
1545  }
1546 
1547  // EM Energy Fit Parameters
1548  ND::THandle<ND::TRealDatum> emefp =
1549  cluster_constit->Get<ND::TRealDatum>("EMEnergyFitParameters");
1550  if (emefp && (emefp->size() >= 5)) {
1551  obj->EMEnergyFit_Para_QSum = emefp->at(0);
1552  obj->EMEnergyFit_Para_QMean = emefp->at(1);
1553  obj->EMEnergyFit_Para_QRMS = emefp->at(2);
1554  obj->EMEnergyFit_Para_QSkew = emefp->at(3);
1555  obj->EMEnergyFit_Para_QMax = emefp->at(4);
1556  } else {
1557  obj->EMEnergyFit_Para_QSum = -1;
1558  obj->EMEnergyFit_Para_QMean = -1;
1559  obj->EMEnergyFit_Para_QRMS = -1;
1560  obj->EMEnergyFit_Para_QSkew = -1;
1561  obj->EMEnergyFit_Para_QMax = -1;
1562  }
1563 
1564  // ====================Thrust Variables========================
1565  // ------------------
1566  ND::THandle<ND::TRealDatum> thrustVect =
1567  cluster_constit->Get<ND::TRealDatum>("Thrust");
1568  if (thrustVect && (thrustVect->size() >= 7)) {
1569  obj->Thrust = thrustVect->at(0);
1570  obj->ThrustOrigin.SetXYZ(thrustVect->at(1), thrustVect->at(2),
1571  thrustVect->at(3));
1572  obj->ThrustAxis.SetXYZ(thrustVect->at(4), thrustVect->at(5),
1573  thrustVect->at(6));
1574  } else {
1575  obj->Thrust = -1.;
1576  }
1577 
1578  // ====================Matching Likelihood========================
1579  // ------------------
1580 
1581  obj->MatchingLikelihood = GetTRealDatumValue(trb, "Likelihood", -1);
1582  break; // Only care about the first (good) cluster constituent.
1583  }
1584 }
1585 
1586 TLorentzVector FindBackPosition(ND::THandle<ND::THitSelection> hits,
1587  int MostDownStreamLayerHit) {
1588  TLorentzVector pos;
1589  double totalCharge(0);
1590 
1591  // Iterate over hits to get the total charge in the back layer.
1592  for (ND::THitSelection::iterator hit_it = hits->begin();
1593  hit_it != hits->end(); ++hit_it) {
1594  int layer =
1595  ND::TGeomInfo::Get().ECAL().GetLayerNumber((*hit_it)->GetGeomId());
1596 
1597  if (layer == MostDownStreamLayerHit) {
1598  totalCharge += (*hit_it)->GetCharge();
1599  }
1600  }
1601 
1602  // Iterate over hits again to find a charge weighted position.
1603  for (ND::THitSelection::iterator hit_it = hits->begin();
1604  hit_it != hits->end(); ++hit_it) {
1605  int layer =
1606  ND::TGeomInfo::Get().ECAL().GetLayerNumber((*hit_it)->GetGeomId());
1607 
1608  if (layer == MostDownStreamLayerHit) {
1609  TLorentzVector temp((*hit_it)->GetPosition(), (*hit_it)->GetTime());
1610  temp *= ((*hit_it)->GetCharge() / totalCharge);
1611  pos += temp;
1612  }
1613  }
1614  return pos;
1615 }
1616 
1617 TVector3 CalculatePointing(ND::THandle<ND::THitSelection> hits) {
1618  TPrincipal pca(3, "ND");
1619 
1620  // Add the charge weighted hits to the pca.
1621  for (ND::THitSelection::iterator hit_it = hits->begin();
1622  hit_it != hits->end(); ++hit_it) {
1623  double row[3] = {(*hit_it)->GetPosition().X(), (*hit_it)->GetPosition().Y(),
1624  (*hit_it)->GetPosition().Z()};
1625  for (double q = 0; q < (*hit_it)->GetCharge(); q += 1.0) {
1626  pca.AddRow(row);
1627  }
1628  }
1629 
1630  // Find the principal components of the shower.
1631  pca.MakePrincipals();
1632 
1633  // Find the centre of the shower.
1634  // The P2X function does this:
1635  // Get the mean position of the shower.
1636  // for (Int_t i = 0; i < fNumberOfVariables; i++){
1637  // x[i] = fMeanValues(i);
1638  // for (Int_t j = 0; j < nTest; j++)
1639  // x[i] += p[j] * (fIsNormalised ? fSigmas(i) : 1)
1640  // * fEigenVectors(i,j);
1641  // }
1642  // Give p[j] = 0, so actually just return x[i], which is the
1643  // mean value over all data points for x, y and z.
1644  double posP[] = {0., 0., 0.};
1645  double posX[3];
1646  pca.P2X(posP, posX, 3);
1647  TVector3 pcaCentre;
1648  pcaCentre.SetXYZ(posX[0], posX[1], posX[2]);
1649 
1650  // Set the primary pca axis.
1651  TVector3 pcaAxis;
1652  pcaAxis.SetXYZ((*pca.GetEigenVectors())[0][0], (*pca.GetEigenVectors())[1][0],
1653  (*pca.GetEigenVectors())[2][0]);
1654 
1655  // Use the PCA info to calcualte pointing.
1656  double sumcharge = 0;
1657  double numerator = 0;
1658  for (ND::THitSelection::iterator hit = hits->begin(); hit != hits->end();
1659  ++hit) {
1660  sumcharge += (*hit)->GetCharge();
1661  numerator +=
1662  ((*hit)->GetCharge() * pcaAxis.Dot((*hit)->GetPosition() - pcaCentre));
1663  }
1664 
1665  TVector3 pointing;
1666  pointing = ((numerator / sumcharge) * pcaAxis);
1667 
1668  return pointing;
1669 }
1670 
1672  G4ID_Primary = -1;
1673  G4ID_Recursive = -1;
1674  G4ID_Single = -1;
1675 }
1676 
1678  ND::THandle<ND::THitSelection> hits) {
1679  // Initialise the variables.
1680  obj->NHits = 0;
1681  obj->View = -1;
1682  obj->TotalHitCharge = 0.0;
1683  obj->AverageHitTime = 0.0;
1684  obj->MostUpStreamLayerHit = 0;
1685  obj->MostDownStreamLayerHit = 0;
1686 
1687  obj->NHits = hits->size();
1688 
1689  int MinLayer(34);
1690  int MaxLayer(-1);
1691 
1692  // Loop through the hits.
1693  for (ND::THitSelection::iterator hit_it = hits->begin();
1694  hit_it != hits->end(); ++hit_it) {
1695  int layer =
1696  ND::TGeomInfo::Get().ECAL().GetLayerNumber((*hit_it)->GetGeomId());
1697 
1698  if (layer < MinLayer) {
1699  MinLayer = layer;
1700  }
1701  if (layer > MaxLayer) {
1702  MaxLayer = layer;
1703  }
1704 
1705  obj->TotalHitCharge += (*hit_it)->GetCharge();
1706  obj->AverageHitTime += ((*hit_it)->GetTime() * (*hit_it)->GetCharge());
1707  }
1708 
1709  // Finish charge weighting the time.
1710  obj->AverageHitTime /= obj->TotalHitCharge;
1711 
1712  // Layer Info
1713  obj->MostUpStreamLayerHit = MinLayer;
1714  obj->MostDownStreamLayerHit = MaxLayer;
1715 
1716  double MinLayerCharge(0.0);
1717  double MaxLayerCharge(0.0);
1718 
1719  // Find Charge Weighted Front and Back Positions
1720  for (ND::THitSelection::iterator hit_it = hits->begin();
1721  hit_it != hits->end(); ++hit_it) {
1722  TVector3 hitPos = (*hit_it)->GetPosition();
1723  int layer =
1724  ND::TGeomInfo::Get().ECAL().GetLayerNumber((*hit_it)->GetGeomId());
1725 
1726  if (layer == MinLayer) {
1727  obj->FrontPosition += (hitPos * (*hit_it)->GetCharge());
1728  MinLayerCharge += (*hit_it)->GetCharge();
1729  }
1730  if (layer == MaxLayer) {
1731  obj->BackPosition += (hitPos * (*hit_it)->GetCharge());
1732  MaxLayerCharge += (*hit_it)->GetCharge();
1733  }
1734  }
1735  obj->FrontPosition *= (1.0 / MinLayerCharge);
1736  obj->BackPosition *= (1.0 / MaxLayerCharge);
1737 
1738  // Find the view from one of the layers used.
1739  if (!(MinLayer % 2)) {
1740  obj->View = 1;
1741  } else {
1742  obj->View = 0;
1743  }
1744 
1745  obj->G4ID = TrackTruthInfo::GetG4TrajIDHits(*hits);
1746 }
1747 
1748 double CalculateFrontBackRatio(ND::THandle<ND::THitSelection> hits) {
1749  // create a vector to store the hits in
1750  std::vector<std::pair<TVector3, double> > positionAndCharge;
1751  double FrontBackRatio = 0;
1752  if (hits && hits->size()) {
1753  // determine principal PCA axis
1754  TPrincipal pca(3, "");
1755 
1756  for (ND::THitSelection::iterator hit_it = hits->begin();
1757  hit_it != hits->end(); ++hit_it) {
1758  const TVector3& pos = (*hit_it)->GetPosition();
1759  double charge = (*hit_it)->GetCharge();
1760  int repeatEntries = static_cast<int>(charge / 0.1);
1761  for (int i = 0; i < repeatEntries; ++i) {
1762  double row[3] = {pos.X(), pos.Y(), pos.Z()};
1763  pca.AddRow(row);
1764  }
1765  }
1766  pca.MakePrincipals();
1767 
1768  // Rotate hits into PCA space, and fill vector with the new positions
1769  for (ND::THitSelection::iterator hit_it = hits->begin();
1770  hit_it != hits->end(); ++hit_it) {
1771  TVector3 position = (*hit_it)->GetPosition();
1772  ND::THandle<ND::THit> h = *hit_it;
1773  double charge = h->GetCharge();
1774 
1775  double x[3] = {position.X(), position.Y(), position.Z()};
1776  double p[3];
1777  pca.X2P(x, p);
1778  // define Z-axis of new co-ordinate system to be the direction along the
1779  // principal PCA axis
1780  position.SetZ(p[0]);
1781  position.SetY(p[1]);
1782  position.SetX(p[2]);
1783 
1784  std::pair<TVector3, double> p_c(position, charge);
1785  positionAndCharge.push_back(p_c);
1786  }
1787 
1788  // define four blocks, first to fourth
1789  double first(0);
1790  double second(0);
1791  double third(0);
1792  double fourth(0);
1793 
1794  int size = positionAndCharge.size();
1795  // set initial values for the ends
1796  double zmin = positionAndCharge.at(0).first.Z();
1797  double zmax = positionAndCharge.at(0).first.Z();
1798 
1799  // find the actual maximum and minimum "z" values
1800  //(i.e. the ends of the track)
1801  for (int i(0); i < size; i++) {
1802  if (positionAndCharge.at(i).first.Z() > zmax) {
1803  zmax = positionAndCharge.at(i).first.Z();
1804  }
1805  if (positionAndCharge.at(i).first.Z() < zmin) {
1806  zmin = positionAndCharge.at(i).first.Z();
1807  }
1808  }
1809 
1810  // calculate the lengh of the track along the PCA axis
1811  double length = zmax - zmin;
1812 
1813  // loop through the hits, calculating which block it falls in, and adding
1814  // its charge to that block
1815  for (int i = 0; i < size; i++) {
1816  if ((positionAndCharge.at(i).first.Z() - zmin) > (3 * length / 4)) {
1817  fourth += positionAndCharge.at(i).second;
1818  } else if ((positionAndCharge.at(i).first.z() - zmin) > (length / 2)) {
1819  third += positionAndCharge.at(i).second;
1820  } else if ((positionAndCharge.at(i).first.z() - zmin) > (length / 4)) {
1821  second += positionAndCharge.at(i).second;
1822  } else {
1823  first += positionAndCharge.at(i).second;
1824  }
1825  }
1826 
1827  // if the filling has succeeded, calculate the ratio
1828  if (first != 0 && fourth != 0) {
1829  FrontBackRatio = fourth / first;
1830  }
1831  }
1832  return FrontBackRatio;
1833 }
1834 
1836  : UniqueID(0),
1837  NHits(0),
1838  TotalCharge(0),
1839  Position(0, 0, 0, 0),
1840  Module(""),
1841  MinLayerHit(0),
1842  MaxLayerHit(0),
1843  MinParaBarHit(0),
1844  MaxParaBarHit(0),
1845  MinPerpBarHit(0),
1846  MaxPerpBarHit(0),
1847  N2DTracksMax(0),
1848  N2DTracksMin(0),
1849  G4IDSingle(0),
1850  CompletenessSingle(0),
1851  CleanlinessSingle(0),
1852  G4IDPrimary(0),
1853  CompletenessPrimary(0),
1854  CleanlinessPrimary(0),
1855  G4IDRecursive(0),
1856  CompletenessRecursive(0),
1857  CleanlinessRecursive(0) {
1858  NTracks = 0;
1859  NCrossings = 0;
1860  Tracks = new TClonesArray(
1861  "ND::TTrackerECALReconModule::TECALReconVertexTrack", 50);
1862  Crossings = new TClonesArray(
1863  "ND::TTrackerECALReconModule::TECALReconVertexCrossing", 200);
1864 }
1865 
1867  : Status(-1),
1868  UniqueID(0),
1869  NHits(0),
1870  MatchingLikelihood(0),
1871  FrontPosition(0, 0, 0, 0),
1872  FrontDirection(0, 0, 0),
1873  FrontLayerNumber(0),
1874  BackPosition(0, 0, 0, 0),
1875  BackDirection(0, 0, 0),
1876  BackLayerNumber(0),
1877  TotalCharge(0),
1878  AverageHitTime(0),
1879  G4IDSingle(0),
1880 #ifdef USE_FULL_VERTEX_TRACK_INFO
1881  CompletenessSingle(0),
1882  CleanlinessSingle(0),
1883  Single_FrontPosition(0, 0, 0),
1884  Single_FrontDirection(0, 0, 0),
1885  Single_FrontG4PointDist(0),
1886  Single_BackPosition(0, 0, 0),
1887  Single_BackDirection(0, 0, 0),
1888  Single_BackG4PointDist(0),
1889  G4IDPrimary(0),
1890  CompletenessPrimary(0),
1891  CleanlinessPrimary(0),
1892  G4IDRecursive(0),
1893  CompletenessRecursive(0),
1894  CleanlinessRecursive(0),
1895 #endif
1896  PID_LLR_MIP_HIP(-9999),
1897  PID_LLR_MIP_HIP_VACut(-9999) {
1898 #ifdef USE_FULL_VERTEX_TRACK_INFO
1899  SubTrack_UniqueID[0] = 0;
1900  SubTrack_UniqueID[1] = 0;
1901  SubTrack_NHits[0] = 0;
1902  SubTrack_NHits[1] = 0;
1903  SubTrack_Angle[0] = 0;
1904  SubTrack_Angle[1] = 0;
1905  SubTrack_FrontLayerNumber[0] = 0;
1906  SubTrack_FrontLayerNumber[1] = 0;
1907  SubTrack_BackLayerNumber[0] = 0;
1908  SubTrack_BackLayerNumber[1] = 0;
1909  SubTrack_DOCA[0] = 0;
1910  SubTrack_DOCA[1] = 0;
1911  SubTrack_TotalCharge[0] = 0;
1912  SubTrack_TotalCharge[1] = 0;
1913  SubTrack_G4IDSingle[0] = 0;
1914  SubTrack_G4IDSingle[1] = 0;
1915  SubTrack_CompletenessSingle[0] = 0;
1916  SubTrack_CompletenessSingle[1] = 0;
1917  SubTrack_CleanlinessSingle[0] = 0;
1918  SubTrack_CleanlinessSingle[1] = 0;
1919  SubTrack_G4IDPrimary[0] = 0;
1920  SubTrack_G4IDPrimary[1] = 0;
1921  SubTrack_CompletenessPrimary[0] = 0;
1922  SubTrack_CompletenessPrimary[1] = 0;
1923  SubTrack_CleanlinessPrimary[0] = 0;
1924  SubTrack_CleanlinessPrimary[1] = 0;
1925  SubTrack_G4IDRecursive[0] = 0;
1926  SubTrack_G4IDRecursive[1] = 0;
1927  SubTrack_CompletenessRecursive[0] = 0;
1928  SubTrack_CompletenessRecursive[1] = 0;
1929  SubTrack_CleanlinessRecursive[0] = 0;
1930  SubTrack_CleanlinessRecursive[1] = 0;
1931  NCrossings = 0;
1932  CrossingIDs = NULL;
1933 #endif
1934 }
1935 
1937  : TObject(other),
1938  Status(other.Status),
1939  UniqueID(other.UniqueID),
1940  NHits(other.NHits),
1941  MatchingLikelihood(other.MatchingLikelihood),
1942  FrontPosition(other.FrontPosition),
1943  FrontDirection(other.FrontDirection),
1944  FrontLayerNumber(other.FrontLayerNumber),
1945  BackPosition(other.BackPosition),
1946  BackDirection(other.BackDirection),
1947  BackLayerNumber(other.BackLayerNumber),
1948  TotalCharge(other.TotalCharge),
1949  AverageHitTime(other.AverageHitTime),
1950  G4IDSingle(other.G4IDSingle),
1951 #ifdef USE_FULL_VERTEX_TRACK_INFO
1952  CompletenessSingle(other.CompletenessSingle),
1953  CleanlinessSingle(other.CleanlinessSingle),
1954  Single_FrontPosition(other.Single_FrontPosition),
1955  Single_FrontDirection(other.Single_FrontDirection),
1956  Single_FrontG4PointDist(other.Single_FrontG4PointDist),
1957  Single_BackPosition(other.Single_BackPosition),
1958  Single_BackDirection(other.Single_BackDirection),
1959  Single_BackG4PointDist(other.Single_BackG4PointDist),
1960  G4IDPrimary(other.G4IDPrimary),
1961  CompletenessPrimary(other.CompletenessPrimary),
1962  CleanlinessPrimary(other.CleanlinessPrimary),
1963  G4IDRecursive(other.G4IDRecursive),
1964  CompletenessRecursive(other.CompletenessRecursive),
1965  CleanlinessRecursive(other.CleanlinessRecursive),
1966 #endif
1967  PID_LLR_MIP_HIP(other.PID_LLR_MIP_HIP),
1968  PID_LLR_MIP_HIP_VACut(other.PID_LLR_MIP_HIP_VACut) {
1969 #ifdef USE_FULL_VERTEX_TRACK_INFO
1970  SubTrack_UniqueID[0] = other.SubTrack_UniqueID[0];
1971  SubTrack_UniqueID[1] = other.SubTrack_UniqueID[1];
1972  SubTrack_NHits[0] = other.SubTrack_NHits[0];
1973  SubTrack_NHits[1] = other.SubTrack_NHits[1];
1974  SubTrack_Angle[0] = other.SubTrack_Angle[0];
1975  SubTrack_Angle[1] = other.SubTrack_Angle[1];
1976  SubTrack_FrontLayerNumber[0] = other.SubTrack_FrontLayerNumber[0];
1977  SubTrack_FrontLayerNumber[1] = other.SubTrack_FrontLayerNumber[1];
1978  SubTrack_BackLayerNumber[0] = other.SubTrack_BackLayerNumber[0];
1979  SubTrack_BackLayerNumber[1] = other.SubTrack_BackLayerNumber[1];
1980  SubTrack_DOCA[0] = other.SubTrack_DOCA[0];
1981  SubTrack_DOCA[1] = other.SubTrack_DOCA[1];
1982  SubTrack_TotalCharge[0] = other.SubTrack_TotalCharge[0];
1983  SubTrack_TotalCharge[1] = other.SubTrack_TotalCharge[1];
1984  SubTrack_G4IDSingle[0] = other.SubTrack_G4IDSingle[0];
1985  SubTrack_G4IDSingle[1] = other.SubTrack_G4IDSingle[1];
1986  SubTrack_CompletenessSingle[0] = other.SubTrack_CompletenessSingle[0];
1987  SubTrack_CompletenessSingle[1] = other.SubTrack_CompletenessSingle[1];
1988  SubTrack_CleanlinessSingle[0] = other.SubTrack_CleanlinessSingle[0];
1989  SubTrack_CleanlinessSingle[1] = other.SubTrack_CleanlinessSingle[1];
1990  SubTrack_G4IDPrimary[0] = other.SubTrack_G4IDPrimary[0];
1991  SubTrack_G4IDPrimary[1] = other.SubTrack_G4IDPrimary[1];
1992  SubTrack_CompletenessPrimary[0] = other.SubTrack_CompletenessPrimary[0];
1993  SubTrack_CompletenessPrimary[1] = other.SubTrack_CompletenessPrimary[1];
1994  SubTrack_CleanlinessPrimary[0] = other.SubTrack_CleanlinessPrimary[0];
1995  SubTrack_CleanlinessPrimary[1] = other.SubTrack_CleanlinessPrimary[1];
1996  SubTrack_G4IDRecursive[0] = other.SubTrack_G4IDRecursive[0];
1997  SubTrack_G4IDRecursive[1] = other.SubTrack_G4IDRecursive[1];
1998  SubTrack_CompletenessRecursive[0] = other.SubTrack_CompletenessRecursive[0];
1999  SubTrack_CompletenessRecursive[1] = other.SubTrack_CompletenessRecursive[1];
2000  SubTrack_CleanlinessRecursive[0] = other.SubTrack_CleanlinessRecursive[0];
2001  SubTrack_CleanlinessRecursive[1] = other.SubTrack_CleanlinessRecursive[1];
2002  NCrossings = other.NCrossings;
2003  if (NCrossings) {
2004  CrossingIDs = new UInt_t[NCrossings];
2005  for (Int_t c_it = 0; c_it < NCrossings; ++c_it) {
2006  CrossingIDs[c_it] = other.CrossingIDs[c_it];
2007  }
2008  } else {
2009  CrossingIDs = NULL;
2010  }
2011 #endif
2012 }
2013 
2015  ND::THandle<ND::TReconPID> trk, bool IsMC, void* pos,
2016  ND::THandle<ND::TG4TrajectoryContainer> trajectories, bool Allocate) {
2017  TECALReconVertexTrack* obj = NULL;
2018  if (Allocate) {
2019  if (pos != NULL) {
2020  obj = new (pos) TECALReconVertexTrack;
2021  } else {
2022  obj = new TECALReconVertexTrack;
2023  }
2024  } else {
2025  obj = static_cast<TECALReconVertexTrack*>(pos);
2026  }
2027 
2028  obj->UniqueID = trk->GetUniqueID();
2029  obj->NHits = trk->GetHits()->size();
2030  obj->MatchingLikelihood =
2031  GetTRealDatumValue(trk, "matching_likelihood", -9999);
2032 
2033  // Get the positions and directions of the track
2034  // Get the start first
2035  ND::THandle<ND::TPIDState> front_state = trk->GetNodes().front()->GetState();
2036  obj->FrontPosition = front_state->GetPosition();
2037  obj->FrontDirection = front_state->GetDirection();
2038  obj->FrontLayerNumber = ND::TGeomInfo::Get().ECAL().GetLayerNumber(
2039  trk->GetNodes().front()->GetObject()->GetHits()->front());
2040 
2041  // Now the end
2042  ND::THandle<ND::TPIDState> back_state = trk->GetNodes().back()->GetState();
2043  obj->BackPosition = back_state->GetPosition();
2044  obj->BackDirection = back_state->GetDirection();
2045  obj->BackLayerNumber = ND::TGeomInfo::Get().ECAL().GetLayerNumber(
2046  trk->GetNodes().back()->GetObject()->GetHits()->front());
2047 
2048  // Calculate the total charge
2049  obj->TotalCharge = 0;
2050  obj->AverageHitTime = 0;
2051  for (ND::THitSelection::iterator hitIt = trk->GetHits()->begin();
2052  hitIt != trk->GetHits()->end(); hitIt++) {
2053  obj->TotalCharge += (*hitIt)->GetCharge();
2054  obj->AverageHitTime += ((*hitIt)->GetTime() * (*hitIt)->GetCharge());
2055  }
2056  obj->AverageHitTime /= obj->TotalCharge;
2057 
2058  obj->StraightTrackLength =
2059  (obj->FrontPosition - obj->BackPosition).Vect().Mag();
2060  obj->NodeTrackLength = 0;
2061 
2062  TLorentzVector LastPos;
2063  for (ND::TReconNodeContainer::iterator n_it = trk->GetNodes().begin();
2064  n_it != trk->GetNodes().end(); ++n_it) {
2065  if (n_it != trk->GetNodes().begin()) {
2066  obj->NodeTrackLength +=
2067  (LastPos -
2068  ND::THandle<ND::TPIDState>((*n_it)->GetState())->GetPosition())
2069  .Vect()
2070  .Mag();
2071  }
2072  LastPos = ND::THandle<ND::TPIDState>((*n_it)->GetState())->GetPosition();
2073  }
2074 
2075 // Now lets get the 2D constituents of the track and store those bits of
2076 // information. The current set up is that each 3D track has TWO 2D
2077 // constituents. To keep the file size increase to a minimum we are
2078 // going to store all 2D information as direct data members of the
2079 // TECALReconVertexTracks, rather than creating entirely new classes
2080 // to store the info
2081 // Lets get the constituents and fill
2082 
2083 #ifdef USE_FULL_VERTEX_TRACK_INFO
2084  for (ND::TReconObjectContainer::iterator rocIt =
2085  trk->GetConstituents()->begin();
2086  rocIt != trk->GetConstituents()->end(); rocIt++) {
2087  // We are going to need an index to fill the arrays, so get one now
2088  int index = std::distance(trk->GetConstituents()->begin(), rocIt);
2089 
2090  // This is meant to be a loop over the two 1D hough tracks.
2091  if (index > 1) {
2092  break;
2093  }
2094 
2095  // All 2D constituents are stored as TReconClusters
2096  ND::THandle<ND::TReconCluster> input_constituent = (*rocIt);
2097 
2098  // This will happen if the track is a merged track as its constituents are
2099  // TReconTracks
2100  if (!input_constituent) {
2101  continue;
2102  }
2103 
2104  obj->SubTrack_UniqueID[index] = input_constituent->GetUniqueID();
2105  obj->SubTrack_NHits[index] = input_constituent->GetHits()->size();
2106  obj->SubTrack_Angle[index] =
2107  input_constituent->Get<ND::TIntegerDatum>("hough_angle")->GetValue();
2108  obj->SubTrack_DOCA[index] =
2109  input_constituent->Get<ND::TIntegerDatum>("hough_distance")->GetValue();
2110  obj->SubTrack_TotalCharge[index] = 0;
2111  obj->SubTrack_FrontLayerNumber[index] = 9999;
2112  obj->SubTrack_BackLayerNumber[index] = -9999;
2113  for (ND::THitSelection::iterator hitIt =
2114  input_constituent->GetHits()->begin();
2115  hitIt != input_constituent->GetHits()->end(); hitIt++) {
2116  // Calculate the total charge
2117  obj->SubTrack_TotalCharge[index] += (*hitIt)->GetCharge();
2118  // Calculate the front and back layer numbers
2119  int Hit_LayerNumber = ND::TGeomInfo::Get().ECAL().GetLayerNumber(*hitIt);
2120  if (Hit_LayerNumber < obj->SubTrack_FrontLayerNumber[index]) {
2121  obj->SubTrack_FrontLayerNumber[index] = Hit_LayerNumber;
2122  }
2123  if (Hit_LayerNumber > obj->SubTrack_BackLayerNumber[index]) {
2124  obj->SubTrack_BackLayerNumber[index] = Hit_LayerNumber;
2125  }
2126  }
2127 
2128  if (!IsMC) {
2129  continue;
2130  }
2131 
2132  ND::TShowerTruthInfo showerTruth(input_constituent);
2133  // Start with single trajectories
2134  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
2135  showerTruth.GetSingleTrajectories();
2136  if (results.size() > 0) {
2137  obj->SubTrack_G4IDSingle[index] = results[0].ParticleID;
2138  obj->SubTrack_CompletenessSingle[index] = results[0].Completeness_NumHits;
2139  obj->SubTrack_CleanlinessSingle[index] = results[0].Cleanliness_NumHits;
2140 
2141  } else {
2142  obj->SubTrack_G4IDSingle[index] = -1;
2143  obj->SubTrack_CompletenessSingle[index] = -1.;
2144  obj->SubTrack_CleanlinessSingle[index] = -1.;
2145  }
2146  // Now the primary trajectories
2147  results = showerTruth.GetPrimaryTrajectories();
2148  if (results.size() > 0) {
2149  obj->SubTrack_G4IDPrimary[index] = results[0].ParticleID;
2150  obj->SubTrack_CompletenessPrimary[index] =
2151  results[0].Completeness_NumHits;
2152  obj->SubTrack_CleanlinessPrimary[index] = results[0].Cleanliness_NumHits;
2153  } else {
2154  obj->SubTrack_G4IDPrimary[index] = -1;
2155  obj->SubTrack_CompletenessPrimary[index] = -1.;
2156  obj->SubTrack_CleanlinessPrimary[index] = -1.;
2157  }
2158  // Now the recursive trajectories
2159  results = showerTruth.GetRecursiveTrajectories();
2160  if (results.size() > 0) {
2161  obj->SubTrack_G4IDRecursive[index] = results[0].ParticleID;
2162  obj->SubTrack_CompletenessRecursive[index] =
2163  results[0].Completeness_NumHits;
2164  obj->SubTrack_CleanlinessRecursive[index] =
2165  results[0].Cleanliness_NumHits;
2166  } else {
2167  obj->SubTrack_G4IDRecursive[index] = -1;
2168  obj->SubTrack_CompletenessRecursive[index] = -1.;
2169  obj->SubTrack_CleanlinessRecursive[index] = -1.;
2170  }
2171  } // End loop ovr 2D constituents
2172 
2173  // For what this is used for, we don't care
2174  obj->NCrossings = 0;
2175  obj->CrossingIDs = 0;
2176 #endif
2177 
2178  obj->PID_LLR_MIP_EM = GetTRealDatumValue(trk, "LLR_MIP_EM", -9999);
2179  obj->PID_LLR_EM_HIP = GetTRealDatumValue(trk, "LLR_EM_HIP", -9999);
2180 
2181  obj->PID_LLR_MIP_HIP = GetTRealDatumValue(trk, "LLR_MIP_HIP", -9999);
2182  obj->PID_LLR_MIP_HIP_VACut =
2183  GetTRealDatumValue(trk, "LLR_MIP_HIP_VACut", -9999);
2184 
2185  // Containment
2186  // This isn't a PID variable, but it's easy to save it the same way.
2187  obj->Containment = GetTRealDatumValue(trk, "Containment", -1);
2188 
2189  if (!IsMC) {
2190  return obj;
2191  }
2192 
2193  // Get the truth information for the track
2194  ND::TShowerTruthInfo showerTruth(trk);
2195  // Start with single trajectories
2196  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
2197  showerTruth.GetSingleTrajectories();
2198  if (results.size() > 0) {
2199  obj->G4IDSingle = results[0].ParticleID;
2200 
2201 #ifdef USE_FULL_VERTEX_TRACK_INFO
2202  obj->CompletenessSingle = results[0].Completeness_NumHits;
2203  obj->CleanlinessSingle = results[0].Cleanliness_NumHits;
2204 
2205  if (trajectories) {
2206  ND::THandle<ND::TG4Trajectory> traj =
2207  trajectories->GetTrajectory(results[0].ParticleID);
2208  if (traj) {
2209  TVector3 Scratch = obj->FrontPosition.Vect();
2210  ND::TG4TrajectoryPoint const& g4pointF =
2211  TrackTruthInfo::GetCloserG4Point(traj, &Scratch,
2212  obj->Single_FrontG4PointDist);
2213  obj->Single_FrontPosition = g4pointF.GetPosition().Vect();
2214  obj->Single_FrontDirection = g4pointF.GetMomentum().Unit();
2215 
2216  Scratch = obj->BackPosition.Vect();
2217  ND::TG4TrajectoryPoint const& g4pointB =
2218  TrackTruthInfo::GetCloserG4Point(traj, &Scratch,
2219  obj->Single_BackG4PointDist);
2220  obj->Single_BackPosition = g4pointB.GetPosition().Vect();
2221  obj->Single_BackDirection = g4pointB.GetMomentum().Unit();
2222  }
2223  }
2224 #endif
2225  } else {
2226  obj->G4IDSingle = -1;
2227 #ifdef USE_FULL_VERTEX_TRACK_INFO
2228  obj->CompletenessSingle = -1.;
2229  obj->CleanlinessSingle = -1.;
2230 #endif
2231  }
2232 #ifdef USE_FULL_VERTEX_TRACK_INFO
2233  // Now the primary trajectories
2234  results = showerTruth.GetPrimaryTrajectories();
2235  if (results.size() > 0) {
2236  obj->G4IDPrimary = results[0].ParticleID;
2237  obj->CompletenessPrimary = results[0].Completeness_NumHits;
2238  obj->CleanlinessPrimary = results[0].Cleanliness_NumHits;
2239  } else {
2240  obj->G4IDPrimary = -1;
2241  obj->CompletenessPrimary = -1.;
2242  obj->CleanlinessPrimary = -1.;
2243  }
2244  // Finally the recursive trajectories
2245  results = showerTruth.GetRecursiveTrajectories();
2246  if (results.size() > 0) {
2247  obj->G4IDRecursive = results[0].ParticleID;
2248  obj->CompletenessRecursive = results[0].Completeness_NumHits;
2249  obj->CleanlinessRecursive = results[0].Cleanliness_NumHits;
2250  } else {
2251  obj->G4IDRecursive = -1;
2252  obj->CompletenessRecursive = -1.;
2253  obj->CleanlinessRecursive = -1.;
2254  }
2255 #endif
2256  return obj;
2257 }
2258 
2260  : UniqueID(0),
2261  NHits(0),
2262  HitCharges(NULL),
2263  HitPositionsX(NULL),
2264  HitPositionsY(NULL),
2265  HitPositionsZ(NULL),
2266  HitTimes(NULL),
2267  HitLayerNumbers(NULL),
2268  HitBarNumbers(NULL),
2269  Position(0, 0, 0, 0),
2270  DOCA(0),
2271  NTracks(0),
2272  TrackIDs(NULL) {}
2273 
2274 #ifdef TTRACKERECALRECONMODULE_USE_EXP
2275 
2276 void OutputManager::SaveUsedHit(ND::THandle<ND::THit> hit, unsigned int UID,
2277  bool overwritePrevious) {
2278  if (!fDoSaveHitInfo) {
2279  return;
2280  }
2281  if (fNUsedHits == MAXHITSTOSAVE) {
2282  ND280NamedWarn("TTrackerECALReconModule", "Recieved too many ecalHits...");
2283  return;
2284  }
2285  unsigned long hitHash = TECALHitHasher(hit);
2286  ND280NamedInfo("TTrackerECALReconModule", "HH: " << hitHash);
2287 
2288  TECALReconHit* trHit = 0;
2289  if (fSavedHitMap.count(hitHash)) { // already have the hit, then get it.
2290  trHit = static_cast<TECALReconHit*>(fUsedHits->At(fSavedHitMap[hitHash]));
2291  }
2292 
2293  // If we do not want to overwrite previous versions of this hit, then bail if
2294  // we see it again
2295  if (trHit && (!overwritePrevious)) {
2296  ND280NamedDebug("TTrackerECALReconModule",
2297  "Already have Hit info (Hash:"
2298  << hitHash << " ), Adding this association: " << UID);
2299  trHit->AddAssocUID(UID);
2300  ND280NamedInfo("TTrackerECALReconModule", "\t" << trHit->Position << ", "
2301  << trHit->ChargeDeposit);
2302  return;
2303  }
2304 
2305  if (!trHit) { // We don't already have it, make a new one
2306  trHit = new ((*fUsedHits)[fNUsedHits++]) TECALReconHit();
2307  fSavedHitMap.insert(std::make_pair(hitHash, fNUsedHits - 1));
2308  trHit->GeomId = hit->GetGeomId().AsInt();
2309  trHit->IsXYZ =
2310  ((hit->IsXHit()) | (hit->IsYHit() << 1) | (hit->IsZHit() << 2));
2311  } else {
2312  ND280NamedInfo("TTrackerECALReconModule", "overwriting hit: " << (*trHit));
2313  }
2314 
2315  // Overwrite old info or write to a new hit
2316  trHit->AddAssocUID(UID);
2317  trHit->Position = TLorentzVector(hit->GetPosition(), hit->GetTime());
2318  trHit->PosUncertainty = hit->GetUncertainty();
2319  trHit->ChargeDeposit = hit->GetCharge();
2320  trHit->IsXYZ =
2321  ((hit->IsXHit()) | (hit->IsYHit() << 1) | (hit->IsZHit() << 2));
2322 
2323  ND280NamedInfo("TTrackerECALReconModule",
2324  "Adding hit info Hit(#" << (fNUsedHits - 1) << "), "
2325  << (*trHit) << " to UID: " << UID);
2326  ND280NamedDebug("TTrackerECALReconModule", "\tHitHash (" << hitHash << ")");
2327 }
2328 
2329 TECALReconHit::TECALReconHit()
2330  : GeomId(-1),
2331  UsedByNObjs(0),
2332  ObjUIDs(NULL),
2333  Position(0, 0, 0, 0),
2334  PosUncertainty(0, 0, 0),
2335  ChargeDeposit(0),
2336  IsXYZ(0) {
2337  ObjUIDs = new UInt_t[TECALReconHit::MaxAssocs];
2338 }
2339 
2340 TECALReconHit::~TECALReconHit() {
2341  if (ObjUIDs) {
2342  delete ObjUIDs;
2343  }
2344 }
2345 
2346 void TECALReconHit::AddAssocUID(unsigned int tuid) {
2347  if (UsedByNObjs == MaxAssocs) {
2348  ND280NamedWarn("TTrackerECALReconModule",
2349  "Attempting to add more object"
2350  " associations than we have space for: "
2351  << MaxAssocs << ".");
2352  return;
2353  }
2354  if (UsedByNObjs == 2) {
2355  ND280NamedWarn(
2356  "TTrackerECALReconModule",
2357  "This hit is already in use"
2358  " by two objects, likely one VertexCluster and one VertexTrack.");
2359  ND280NamedWarn("TTrackerECALReconModule",
2360  "+Attempting to add associat"
2361  "ion: "
2362  << tuid);
2363  for (int it = 0; it < UsedByNObjs; ++it) {
2364  ND280NamedWarn("TTrackerECALReconModule", "Used By: " << ObjUIDs[it]);
2365  }
2366  }
2367  ObjUIDs[UsedByNObjs++] = tuid;
2368 }
2369 
2370 #endif
2371 
2373  VertexClusterUID = 0;
2374  Position = TLorentzVector(0, 0, 0, 0);
2375  ECalModule = "";
2376  NTracks = 0;
2377  NHits = 0;
2378  G4IDSingle = -1;
2379  CompletenessSingle = -1;
2380  CleanlinessSingle = -1;
2381  G4IDPrimary = -1;
2382  CompletenessPrimary = -1;
2383  CleanlinessPrimary = -1;
2384  G4IDRecursive = -1;
2385  CompletenessRecursive = -1;
2386  CleanlinessRecursive = -1;
2387 }
2388 
2390  const TECALReconVertex& rv, ND::THandle<ND::TReconVertex> top_vertex,
2391  bool IsMC, void* pos) {
2392  UInt_t VCUID = top_vertex->GetUniqueID();
2393  ND280NamedInfo("TTrackerECALReconModule",
2394  "Adding vertex candidate info:"
2395  " Association: "
2396  << VCUID << ", Pos: " << rv.GetPosition() << ", uses "
2397  << rv.NTracks() << " tracks.");
2398 
2399  TECALReconVertexCandidate* obj = NULL;
2400  if (pos != NULL) {
2401  obj = new (pos) TECALReconVertexCandidate;
2402  } else {
2403  ND280NamedWarn("TTrackerECALReconModule",
2404  "TECALVertexCandidateFactory making new "
2405  "TECALReconVertexCandidate instance with non-positional new "
2406  "operator.");
2407  obj = new TECALReconVertexCandidate;
2408  }
2409 
2410  obj->NHits = rv.VertCandyHits->size();
2411  obj->ECalModule = ND::TGeomInfo::Get()
2412  .ECAL()
2413  .GetModule(rv.VertCandyHits->front())
2414  .GetName();
2415 
2416  obj->NTracks = rv.NTracks();
2417  obj->TrackUIDs = new UInt_t[obj->NTracks];
2418 
2419  int tctr = 0;
2420  for (std::vector<ND::THandle<ND::TReconPID> >::const_iterator
2421  trk_it = rv.Tracks_cbegin();
2422  trk_it != rv.Tracks_cend(); ++trk_it, ++tctr) {
2423  obj->TrackUIDs[tctr] = (*trk_it)->GetUniqueID();
2424  }
2425 
2426  obj->Position = rv.GetPosition();
2427  obj->VertexClusterUID = VCUID;
2428 
2429  // Here be truth matching routines.
2430  if (!IsMC) {
2431  return obj;
2432  }
2433 
2434  // Now we have semi-sensibly separate vertex candidate hits
2435  // Get the truth information for the cluster
2436  ND::TShowerTruthInfo shower_truth(rv.VertCandyHits,
2437  ND::TShowerTruthInfo::kXYZ, 1, 1, 1);
2438  // Start with single trajectories
2439  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
2440  shower_truth.GetSingleTrajectories();
2441  if (results.size()) {
2442  obj->G4IDSingle = results[0].ParticleID;
2443  obj->CompletenessSingle = results[0].Completeness_NumHits;
2444  obj->CleanlinessSingle = results[0].Cleanliness_NumHits;
2445  } else {
2446  obj->G4IDSingle = -1;
2447  obj->CompletenessSingle = -1;
2448  obj->CleanlinessSingle = -1;
2449  }
2450  // Now the primary trajectories
2451  results = shower_truth.GetPrimaryTrajectories();
2452  if (results.size()) {
2453  obj->G4IDPrimary = results[0].ParticleID;
2454  obj->CompletenessPrimary = results[0].Completeness_NumHits;
2455  obj->CleanlinessPrimary = results[0].Cleanliness_NumHits;
2456  } else {
2457  obj->G4IDPrimary = -1;
2458  obj->CompletenessPrimary = -1;
2459  obj->CleanlinessPrimary = -1;
2460  }
2461  // Now the primary trajectories
2462  results = shower_truth.GetRecursiveTrajectories();
2463  if (results.size()) {
2464  obj->G4IDRecursive = results[0].ParticleID;
2465  obj->CompletenessRecursive = results[0].Completeness_NumHits;
2466  obj->CleanlinessRecursive = results[0].Cleanliness_NumHits;
2467  } else {
2468  obj->G4IDRecursive = -1;
2469  obj->CompletenessRecursive = -1;
2470  obj->CleanlinessRecursive = -1;
2471  }
2472  return obj;
2473 }
2474 
2476  ND::THandle<ND::TReconVertex> ECalVtx, UInt_t VCUID, bool IsMC, void* pos) {
2477  ND280NamedInfo("TTrackerECALReconModule",
2478  "Adding vertex candidate info:"
2479  " Association: "
2480  << VCUID << ", Pos: " << ECalVtx->GetPosition());
2481 
2482  TECALReconVertexCandidate* obj = NULL;
2483  if (pos != NULL) {
2484  obj = new (pos) TECALReconVertexCandidate;
2485  } else {
2486  ND280NamedWarn("TTrackerECALReconModule",
2487  "TECALVertexCandidateFactory making new "
2488  "TECALReconVertexCandidate instance with non-positional new "
2489  "operator.");
2490  obj = new TECALReconVertexCandidate;
2491  }
2492 
2493  obj->NHits = ECalVtx->GetHits()->size();
2494  obj->ECalModule = ND::TGeomInfo::Get()
2495  .ECAL()
2496  .GetModule(ECalVtx->GetHits()->front())
2497  .GetName();
2498 
2499  obj->NTracks = 0;
2500  for (UInt_t const_it = 0; const_it < ECalVtx->GetConstituents()->size();
2501  ++const_it) {
2502  ND::THandle<ND::TReconPID> trk = ECalVtx->GetConstituents()->at(const_it);
2503  if (trk) {
2504  obj->NTracks++;
2505  }
2506  }
2507  obj->TrackUIDs = new UInt_t[obj->NTracks];
2508  size_t tit = 0;
2509  for (UInt_t const_it = 0; const_it < ECalVtx->GetConstituents()->size();
2510  ++const_it) {
2511  ND::THandle<ND::TReconPID> trk = ECalVtx->GetConstituents()->at(const_it);
2512  if (trk) {
2513  obj->TrackUIDs[tit++] = trk->GetUniqueID();
2514  }
2515  }
2516 
2517  obj->Position = ECalVtx->GetPosition();
2518  obj->VertexClusterUID = VCUID;
2519 
2520  // Here be truth matching routines.
2521  if (!IsMC) {
2522  return obj;
2523  }
2524 
2525  // Get the truth information for the cluster
2526  ND::TShowerTruthInfo shower_truth(ECalVtx->GetHits(),
2527  ND::TShowerTruthInfo::kXYZ, 1, 1, 1);
2528  // Start with single trajectories
2529  std::vector<ND::TShowerTruthInfo::TruthInfo> results =
2530  shower_truth.GetSingleTrajectories();
2531  if (results.size()) {
2532  obj->G4IDSingle = results[0].ParticleID;
2533  obj->CompletenessSingle = results[0].Completeness_NumHits;
2534  obj->CleanlinessSingle = results[0].Cleanliness_NumHits;
2535  } else {
2536  obj->G4IDSingle = -1;
2537  obj->CompletenessSingle = -1;
2538  obj->CleanlinessSingle = -1;
2539  }
2540  // Now the primary trajectories
2541  results = shower_truth.GetPrimaryTrajectories();
2542  if (results.size()) {
2543  obj->G4IDPrimary = results[0].ParticleID;
2544  obj->CompletenessPrimary = results[0].Completeness_NumHits;
2545  obj->CleanlinessPrimary = results[0].Cleanliness_NumHits;
2546  } else {
2547  obj->G4IDPrimary = -1;
2548  obj->CompletenessPrimary = -1;
2549  obj->CleanlinessPrimary = -1;
2550  }
2551  // Now the primary trajectories
2552  results = shower_truth.GetRecursiveTrajectories();
2553  if (results.size()) {
2554  obj->G4IDRecursive = results[0].ParticleID;
2555  obj->CompletenessRecursive = results[0].Completeness_NumHits;
2556  obj->CleanlinessRecursive = results[0].Cleanliness_NumHits;
2557  } else {
2558  obj->G4IDRecursive = -1;
2559  obj->CompletenessRecursive = -1;
2560  obj->CleanlinessRecursive = -1;
2561  }
2562  return obj;
2563 }
2564 
2570 }
2571 }
double PID_FrontBackRatio
The ratio of the charge in equal length blocks at each end of the track.
Int_t MinPerpBarHit
The minimum bar number hit perpendicular to the beam axis.
void FillHitInfo(TECALReconObject *obj, ND::THandle< ND::THitSelection > hitsel)
Method to fill hit info is seperate to help keep things tidy.
double EMEnergyFit_Likelihood_energyGrad
Energy fit experts please fill this in.
double EMEnergyFit_Para_QSum
The summed charge present in the cluster in units of MIPs.
Int_t G4IDPrimary
The G4ID of the primary contributor to the cluster.
double EMEnergyFit_Likelihood_qsum_like
Energy fit experts please fill this in.
void FillHoughTransformInformation(ND::THandle< ND::TAlgorithmResult > ecalFinalResult, ND::THandle< ND::TG4TrajectoryContainer > trajectories)
Handles saving of the results of the ecalRecon Hough transform.
Float_t CleanlinessRecursive
The cleanliness (hit purity) of the recursive contributor to the cluster.
double PID_Circularity
Pid Variables, For more info on the Pid variable see the documentation in ecalRecon or the technical ...
double PID_LLR_EM_HIP
A combined discriminator for separating protons from electrons.
Int_t G4ID_Single
The single true particle that contributed most hits to this object. Should be the same as G4ID in mos...
void FillVertexingInformation(ND::THandle< ND::TAlgorithmResult > ecalFinalResult, ND::THandle< ND::TG4TrajectoryContainer > trajectories)
TClonesArray * fUnmatchedObjects
The Unmatched Objects.
int NLayersTwoHits
The number of layers which have at least 2 hits.
Int_t G4IDRecursive
The G4ID of the recursive contributor to the cluster.
Double_t Completeness_Primary
Truth-matching completeness for G4ID_Primary.
The main object that contains ECAL shower information.
double PID_ShowerAngle
The angle from the start of an object to its width at its charge centre.
Int_t NTracks
The number of tracks that contributed to the fitted position.
int FirstLayerManyHits
The number of the first layer in which there are at least 2 hits.
double EMEnergyFit_Uncertainty
The uncertainty of the EM energy fit to the cluster.
TECalVertexing * fVertexRecon
Helper object which performs vertex candidate reconstruction.
double PID_LLR_MIP_HIP
A combined discriminator for separating MIPs from HIPs.
double PID_LLR_MIP_EM_LowMomentum
A combined discriminator for separating MIPs from EM showers. This is similar to LLR_MIP_EM but train...
UInt_t VertexClusterUID
The UID of the associated TECALReconVertexCluster.
TVector3 FrontPosition
Position of the end of the cluster closest to the tracker.
virtual Bool_t ProcessFirstEvent(ND::TND280Event &event)
Is called after the first event is loaded in.
Double_t Completeness_Recursive
Truth-matching completeness for G4ID_Recursive.
Double_t Cleanliness_Single
Truth-matching cleanliness for G4ID_Single.
Float_t StraightTrackLength
Distance between the two track end positions.
virtual void InitializeBranches()
Initialize Branches. Don&#39;t do anything else in this function.
Int_t G4ID_Primary
G4ID of the primary particle associated with this object. See TShowerTruthInfo in oaUtility for detai...
Double_t TotalHitCharge
Sum of charges of the consitituent hits in reconstructed object.
void ProcessOtherContainer(ND::THandle< ND::TReconObjectContainer > other)
Processes any results in the ecalRecon other container.
TVector3 CalculatePointing(ND::THandle< ND::THitSelection > hits)
Calculates the pointing vector.
ClassImp(ND::TBeamSummaryDataModule::TBeamSummaryData)
Int_t NHits
Number of hits directly associated with the crossing.
bool fDoSaveVertexCandidates
Whether to calcluate and save the reconstructed vertx candidaties. [false].
Double_t ObjectLength
Recon object length in mm.
double EMEnergyFit_Result
The result from the EM energy fit to the cluster.
TLorentzVector BackPosition
The back position (furthest from the tracker) of the track.
Float_t CleanlinessPrimary
The cleanliness (hit purity) of the primary contributor to the cluster.
std::string fDescription
A longish descrition of the analysis.
void ProcessFinalContainer(ND::THandle< ND::TReconObjectContainer > final)
Processes any results in the ecalRecon final container.
double TotalHitCharge
Summed hit charge in the cluster in units of MIPs.
std::string Module
Name of ECal module the cluster is reconstructed in.
Float_t CompletenessRecursive
The Completeness of the Recursive contributor to the cluster.
Float_t TotalCharge
The total charge deposited by the track.
Int_t Clustering_3DSeedType
The 3D seed type from the 3D clustering algorithm (-1 means was not created by 3D clustering...
double PID_TruncatedMaxRatio
A truncated Max Ratio. See ecalRecon docs for the full definition.
TClonesArray * fReconObjects
The TECALRecon Objects.
OutputManager(const char *name="TrackerECal", const char *title="Tracker ECal Recon Module")
#define CVSID
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...
#define CVSTAG
Int_t G4ID_Single
The single true particle that contributed most hits to this object. Should be the same as G4ID in mos...
Int_t N2DTracksMin
The minimum number of 2D tracks found in a view.
double EMEnergyFit_Likelihood_energy_qsumGrad
Energy fit experts please fill this in.
Double_t AverageHitTime
Average time of hits in reconstructed object.
int MaxHitChargeLayer
The layer which received the highest hit charge.
Int_t NHits
The number of hits that were included in fitted tracks or were closer to this vertex candidate than a...
TLorentzVector Position
The reconstruction position of the crossing.
Int_t FrontLayerNumber
The front layer number (closest to the tracker) of the track.
Object containing information about 2D unmatched clusters from the ECALs.
double AverageHitTime
Average time of the cluster in ns.
Int_t G4IDSingle
The G4ID of the single biggest contributor to the cluster.
bool fDoVertexing
Whether to re-run the vertexing (N.B.
void FillDatumInfo(TECALReconObject *obj, ND::THandle< ND::TReconBase > trb)
Method to add information in RealDatums stored in the tracks or showers.
Int_t G4ID_Recursive
G4ID of the highest-level parent particle that enters the ECal module, and which had a daughter that ...
TClonesArray * Tracks
The constituent tracks TClonesArray.
double AverageZPosition
Unweighted average Z position of object-constituent hits.
double PID_LLR_Quality
A quality flag for the likelihood PID variables. Good quality = 0, Bad quality != 0...
int MostDownStreamLayerHit
The layer furthest from the tracker that was hit by the cluster.
TLorentzVector Position
The fitted position of the vertex candidate.
Int_t G4IDSingle
The G4ID of the single biggest contributor to the track.
Double_t Cleanliness_Recursive
Truth-matching cleanliness for G4ID_Recursive.
Int_t G4IDRecursive
The G4ID of the Recursive contributor to the cluster.
Int_t MinBarHit
The minimum bar number hit in a cluster The minimum value of this is 0 for all ECals.
Int_t fBufferSize
Buffer Size for TBranch.
double PID_LLR_EM_HIP
A combined discriminator for separating protons from electrons.
double EMEnergyFit_Para_QRMS
The RMS of the hit charges for the cluster in units of MIPs.
Int_t NLayersHit
Number of layers hit by this object.
TECALReconUnmatchedObject * TECALReconUnmatchedObjectFactory(ND::THandle< ND::TReconCluster > cluster, bool IsMC, void *pos)
Method that fills the data members from the unmatched cluster hits.
double PID_Angle
The zenith angle with respect to each detector.
TLorentzVector FrontPosition
The front position (closest to the tracker) of the track.
Float_t CleanlinessSingle
The cleanliness (hit purity) of the single biggest contributor to the cluster.
Float_t TotalCharge
The total charge of the cluster.
double PID_LLR_MIP_EM
A combined discriminator for separating MIPs from EM showers.
Float_t DOCA
The distance of closest approach of the two lines.
Float_t CleanlinessPrimary
The cleanliness (hit purity) of the primary contributor to the cluster.
std::string fCVSID
Defined if an official tagged version.
double EMEnergyFit_Para_QSkew
The skew of hit charges for the cluster in units of MIPs.
Bool_t Configure(std::string &option)
Provides CLI for enabling fDoSaveHitInfo and fDoSaveVertexCandidates.
Float_t MatchingLikelihood
The matching likelihood of the track.
Int_t N2DTracksMax
The maximum number of 2D tracks found in a view.
virtual void InitializeModule()
Initialize Module, override if necessary.
The main object that contains ECAL cluster information.
double GetTRealDatumValue(ND::THandle< ND::TReconBase > trb, char const *name, double const &defaultValue)
double PID_LLR_MIP_Pion
Discriminator for tagging showering pions in a sample of MIP-like tracks.
double PID_TransverseChargeRatio
A variable sensitive to the charge distribution in the plane transverse to a shower/track direction...
virtual bool IsFullEventWorthSaving(ND::TND280Event &event)
Returns true if there is at least one Recon object in the Tracker ECals.
bool FilledAsTrack
Was filled by a Track-like TReconPID.
void SetNameTitle(char const *name, char const *title)
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.
Int_t NIsZHits
Number of hits with precise Z information in the object.
double PID_LLR_MIP_EM
A combined discriminator for separating MIPs from EM showers.
TVector3 BackDirection
The back direction (furthest from the tracker) of the track.
void FillECalIsoVertexingInformation(ND::THandle< ND::TAlgorithmResult > ecalFinalResult, ND::THandle< ND::TG4TrajectoryContainer > trajectories)
Just saves the final ECal-iso vertexing results.
Float_t CompletenessPrimary
The Completeness of the primary contributor to the cluster.
Float_t CompletenessRecursive
The Completeness of the recursive contributor to the cluster.
TClonesArray * fReconVertexClusters
The Reconstructed Vertices.
TVector3 BackPosition
Position in end of the cluster furthest from the tracker.
Reconstructed ECal vertex candidate, contains fitted position and associated track UIDs...
Float_t NodeTrackLength
Distance integrating along the track representation nodes.
TClonesArray * Crossings
The constituent crossings TClonesArray.
Int_t G4ID_Primary
G4ID of the primary particle associated with this object.
The main object that contains ECAL track information.
int MostUpStreamLayerHit
The layer closest to the tracker that was hit by the cluster.
TClonesArray * fVertexCandidates
The reconstructed vertex candidates.
std::string ECalModule
The ECalModule that this vertex was reconstructed in.
Float_t CompletenessSingle
The Completeness of the single biggest contributor to the cluster.
TClonesArray * fVertexCandidateTracks
The tracks associated with the reconstructed vertex candidates.
TVector3 FrontDirection
The front direction (closest to the tracker) of the track.
Int_t fSplitLevel
Split Level for TBranch.
Int_t G4ID_Recursive
G4ID of the highest-level parent particle that enters the ECal module, and which had a daughter that ...
double Containment
Containment: contained = 1.0, not-contained = 0.0, default = -1.0. An object is classed as contained ...
Int_t MaxParaBarHit
The maximum bar number hit in a cluster, for layers parallel to the beam axis.
Float_t CompletenessSingle
The Completeness of the single biggest contributor to the cluster.
double Containment
Containment: contained = 1.0, not-contained = 0.0, default = -1.0.
TECALReconVertexCandidate * TECALVertexCandidateFactory(const TECALReconVertex &rv, ND::THandle< ND::TReconVertex > top_vertex, bool IsMC, void *pos)
Int_t MaxParaBarHit
The maximum bar number hit parallel to the beam axis.
Int_t MaxPerpBarHit
\ The maximum bar number hit in a cluster, for layers perpendicular to the beam axis ...
std::string fCVSTagName
Defined if an official tagged version.
Int_t G4IDPrimary
The G4ID of the primary contributor to the cluster.
Int_t MinParaBarHit
The minimum bar number hit parallel to the beam axis.
double EMEnergyFit_Para_QMax
The maximum hit charge in units of MIPs.
Double_t Cleanliness_Primary
Truth-matching cleanliness for G4ID_Primary.
void PerEvReset()
Handles clearing and resetting of event level variables/arrays.
Int_t G4IDSingle
The G4ID of the single biggest contributor to the cluster.
virtual bool FillTree(ND::TND280Event &)
Fill all the stuff that goes in the output tree.
bool fDoSaveHoughResults
Whether to output the bare Hough transform results.
Float_t CleanlinessSingle
The cleanliness (hit purity) of the single biggest contributor to the cluster.
Float_t CleanlinessRecursive
The cleanliness (hit purity) of the Recursive contributor to the cluster.
std::string Module
Name of ECAL module in which object was reconstructed.
int View
View of the cluster. View 0 - Y measuring (odd) Layers and View 1 - X measuring (even) layers...
Int_t NTracks
The number of tracks which created this crossing.
int NLayersThreeHits
The number of layers which have at least 3 hits.
int NHitsAtLayersWithManyHits
The number of hits in a layer when there are at least 2 hits.
int MaxHitsInALayer
The layer which received the maximum number of hits.
int GetTIntegerDatumValue(ND::THandle< ND::TReconBase > trb, char const *name, int const &defaultValue)
Int_t MostUpStreamLayerHit
The layer closest to the tracker that was hit by the object. 0 indexed.
Int_t NIsXHits
Number of hits with precise X information in the object.
std::map< UInt_t, Int_t > fSavedVertexTrackIds
Which tracks have already been saved.
Int_t NIsYHits
Number of hits with precise Y information in the object.
Double_t Completeness_Single
Truth-matching completeness for G4ID_Single.
TECALReconVertexTrack * TECALReconVertexTrackFactory(ND::THandle< ND::TReconPID > trk, bool IsMC, void *pos, ND::THandle< ND::TG4TrajectoryContainer > trajectories, bool Allocate)
TLorentzVector FindBackPosition(ND::THandle< ND::THitSelection > hits, int MostDownStreamLayerHit)
Method to calculate the position in the last layer reached by the particle.
double PID_Asymmetry
Ratio of the big width of an object by its small width.
int LastLayerManyHits
The last layer in which there are at least 2 hits.
double EMEnergyFit_Para_QMean
The mean charge of hits in the cluster in units of MIPs.
Float_t CompletenessPrimary
The Completeness of the primary contributor to the cluster.
Int_t BackLayerNumber
The back layer number (closest to the tracker) of the track.
double CalculateFrontBackRatio(ND::THandle< ND::THitSelection > hits)
Method to calculate the FrontBackRatio variable.
Int_t MaxPerpBarHit
The maximum bar number hit perpendicular to the beam axis.
double PID_LLR_MIP_HIP_VACut
A combined discriminator for separating MIPs from HIPs where the hits nearest the vertex have been ig...

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

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