eventAnalysis  7.0-49-g0ac7482
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
TSFGReconModule.cxx
Go to the documentation of this file.
1 #include "TSFGReconModule.hxx"
2 
3 #include <TAlgorithmResult.hxx>
4 #include <TG4PrimaryVertex.hxx>
5 #include <TGeomInfo.hxx>
6 #include <TGeometryId.hxx>
7 #include <THandle.hxx>
8 #include <THitSelection.hxx>
9 #include <TND280Event.hxx>
10 #include <TND280Log.hxx>
11 #include <TSFGGeom.hxx>
12 #include <TReconNode.hxx>
13 #include <TReconCluster.hxx>
14 #include <TReconShower.hxx>
15 #include <TReconTrack.hxx>
16 #include <TReconVertex.hxx>
17 #include <TReconPID.hxx>
18 #include <TReconState.hxx>
19 #include <TShowerState.hxx>
20 #include <TTrackState.hxx>
21 #include <TVertexState.hxx>
22 #include <TPIDState.hxx>
23 #include "TEventFolder.hxx"
24 #include <TrackTruthInfo.hxx>
25 
26 #if (oaEvent_MAJOR_VERSION>8)
27 #include "TReconStateUtilities.hxx"
28 #include "TShowerState.hxx"
29 #include "TPIDState.hxx"
30 using ND::TReconStateUtilities::GetPosition;
31 using ND::TReconStateUtilities::GetPositionVariance;
32 using ND::TReconStateUtilities::GetPositionIndex;
33 #endif
34 
35 #include <TG4VHit.hxx>
36 #include <TG4HitSegment.hxx>
37 #include <retrieveHitTruthInfo.hxx>
38 #include <TG4Trajectory.hxx>
39 
40 #include <TString.h>
41 #include <TVector3.h>
42 
43 #include <functional>
44 #include <algorithm>
45 #include <cassert>
46 #include <string>
47 
50 
53 
56 
59 
62 
65 
68 
71 
73  const char *title) {
74 
75  SetNameTitle(name, title);
76 
77  // Enable this module by default:
78  fIsEnabled = kTRUE;
79  fDescription = "SFG Recon Output";
80  fCVSTagName = "FromGit";
81  fCVSID = "FromGit";
82 
83  fAlgoResults = new TClonesArray("ND::TSFGReconModule::TSFGAlgoRes");
84  fVertices = new TClonesArray("ND::TSFGReconModule::TSFGVertex");
85  fParticles = new TClonesArray("ND::TSFGReconModule::TSFGParticle");
86  fTracks = new TClonesArray("ND::TSFGReconModule::TSFGTrack");
87  fShowers = new TClonesArray("ND::TSFGReconModule::TSFGShower");
88  fClusters = new TClonesArray("ND::TSFGReconModule::TSFGCluster");
89  fNodes = new TClonesArray("ND::TSFGReconModule::TSFGNode");
90  fHits = new TClonesArray("ND::TSFGReconModule::TSFGHit");
91  fTrueHits = new TClonesArray("ND::TSFGReconModule::TSFGHit");
92  fFibers = new TClonesArray("ND::TSFGReconModule::TSFGHit");
93 
94  fRejectAlgoResultList.clear();
95  fRejectAlgoResultList.push_back(TPRegexp("TSFGBogusExample$"));
96 }
97 
98 
100 
102 
103  TBranch* branch = fOutputTree->Branch("NAlgoResults", &fNAlgoResults,
104  "NAlgoResults/I", fBufferSize);
105  branch ->SetTitle("The number of Algorithm Results ");
106 
107  branch = fOutputTree->Branch("AlgoResults", &fAlgoResults,
109  branch ->SetTitle("The TSFGAlgoRes vector of Algorithm Results");
110 
111  branch = fOutputTree->Branch("NVertices", &fNVertices,
112  "NVertices/I", fBufferSize);
113  branch->SetTitle(" The number of added vertices");
114 
115  branch = fOutputTree->Branch("Vertices", &fVertices,
117  branch->SetTitle(" The vector of vertices");
118 
119  branch = fOutputTree->Branch("NParticles", &fNParticles,
120  "NParticles/I", fBufferSize);
121  branch->SetTitle(" The number of particles ");
122 
123  branch = fOutputTree->Branch("Particles", &fParticles,
125  branch->SetTitle("The vector of particles");
126 
127  branch = fOutputTree->Branch("NTracks", &fNTracks,
128  "NTracks/I", fBufferSize);
129  branch->SetTitle(" The number of tracks");
130 
131  branch = fOutputTree->Branch("Tracks", &fTracks,
133  branch->SetTitle(" The vector of tracks");
134 
135  branch = fOutputTree->Branch("NShowers", &fNShowers,
136  "NShowers/I", fBufferSize);
137  branch->SetTitle(" The number of showers");
138 
139  branch = fOutputTree->Branch("Showers", &fShowers,
141  branch->SetTitle("The vector of showers");
142 
143  branch = fOutputTree->Branch("NClusters", &fNClusters,
144  "NClusters/I", fBufferSize);
145  branch ->SetTitle("The number of clusters ");
146 
147  branch = fOutputTree->Branch("Clusters", &fClusters,
149  branch->SetTitle("The vector of clusters");
150 
151  branch = fOutputTree->Branch("NNodes", &fNNodes,
152  "NNodes/I", fBufferSize);
153  branch->SetTitle(" The number of track nodes");
154 
155  branch = fOutputTree->Branch("Nodes", &fNodes,
157  branch->SetTitle("The vector of nodes");
158 
159  branch = fOutputTree->Branch("NHits", &fNHits,
160  "NHits/I", fBufferSize);
161  branch->SetTitle("The number of hits that are saved ");
162 
163  branch = fOutputTree->Branch("Hits", &fHits,
165  branch->SetTitle("The vector of reconstructed hits");
166 
167  branch = fOutputTree->Branch("NFibers", &fNFibers,
168  "NFiber/I", fBufferSize);
169  branch->SetTitle("The number of fiber hits");
170 
171  branch = fOutputTree->Branch("Fibers", &fFibers,
173  branch->SetTitle("The vector of fiber hits");
174 
175  branch = fOutputTree->Branch("NTrueHits", &fNTrueHits,
176  "NTrueHits/I", fBufferSize);
177  branch->SetTitle("The energy deposition from the simulation");
178 
179  branch = fOutputTree->Branch("TrueHits", &fTrueHits,
181  branch->SetTitle("The vector of true hits");
182 
183 }
184 
185 
186 bool ND::TSFGReconModule::FillTree(ND::TND280Event& event) {
187 
188  fNAlgoResults = 0;
189  fNVertices = 0;
190  fNParticles = 0;
191  fNTracks = 0;
192  fNShowers = 0;
193  fNClusters = 0;
194  fNNodes = 0;
195  fNHits = 0;
196  fNFibers = 0;
197  fNTrueHits = 0;
198 
199  fAlgoResults->Clear();
200  fVertices->Clear();
201  fParticles->Clear();
202  fTracks->Clear();
203  fShowers->Clear();
204  fClusters->Clear();
205  fNodes->Clear();
206  fHits->Clear();
207  fFibers->Clear();
208  fTrueHits->Clear();
209 
210  ND::THandle<ND::THitSelection> sfgFibers(event.GetHitSelection("sfg"));
211  if (sfgFibers) {
212  for (ND::THitSelection::iterator h = sfgFibers->begin();
213  h != sfgFibers->end(); ++h) {
214  AddHit(*h,fNFibers,fFibers);
215  }
216  }
217  else {
218  ND280Info("Missing fiber hits");
219  }
220 
221  ND::THandle<ND::THitSelection> sfgTruth(event.GetHitSelection("sfg_truth"));
222  if (sfgTruth) {
223  for (ND::THitSelection::iterator h = sfgTruth->begin();
224  h != sfgTruth->end(); ++h) {
226  }
227  }
228  else {
229  ND280Info("Missing truth hits");
230  }
231 
232  // Get the true trajectories
233  fTrueTraj = event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
234  if(!fTrueTraj){
235  ND280Log("Missing truth trajectories");
236  }
237 
238  // Get the main result to save.
239  ND::THandle<ND::TAlgorithmResult> sfgRecon = event.GetFit("TSFGRecon");
240  if (!sfgRecon) {
241  sfgRecon = event.GetFit("sfgRecon");
242  if (!sfgRecon) {
243  ND280Info("No sfgRecon in Event");
244  return true;
245  }
246  }
247 
248  // Fill the trees.
249  fTempHitMap.clear();
250  FillAlgorithmResult(sfgRecon, -1);
251  fTempHitMap.clear();
252 
253  return true;
254 }
255 
256 template <class T>
258  ND::THandle<ND::TReconBase> baseObject,
259  bool saveHits) {
260  // Algorithm Name
261  basePtr->AlgorithmName = baseObject->GetAlgorithmName();
262 
263  // Hit Based Information
264  ND::THandle<ND::THitSelection> baseHits = baseObject->GetHits();
265 
266  if (baseHits) {
267  basePtr->NHits = (int)baseHits->size();
268 
269  if (saveHits) {
270  for (ND::THitSelection::const_iterator hit = baseHits->begin();
271  hit != baseHits->end(); ++hit) {
272  int hitId = FillHit(*hit);
273  if (hitId < 0) continue;
274  basePtr->Hits.push_back(hitId);
275  }
276  }
277  }
278  else {
279  basePtr->NHits = -1;
280  }
281 
282  // Unique Id
283  basePtr->UniqueId = baseObject->GetUniqueID();
284 
285  // Daughter objects
286  ND::THandle<ND::TReconObjectContainer> objCont =
287  baseObject->GetConstituents();
288  if (objCont) {
289  ND::TReconObjectContainer::const_iterator constituent;
290  for (constituent = objCont->begin();
291  constituent != objCont->end();
292  ++constituent) {
293 
294  ObjectId conId = FillReconObject(*constituent, saveHits);
295  if (conId.type == ObjectId::kVertex) {
296  basePtr->Vertices.push_back(conId.id);
297  }
298  else if (conId.type == ObjectId::kParticle) {
299  basePtr->Particles.push_back(conId.id);
300  }
301  else if (conId.type == ObjectId::kTrack) {
302  basePtr->Tracks.push_back(conId.id);
303  }
304  else if (conId.type == ObjectId::kShower) {
305  basePtr->Showers.push_back(conId.id);
306  }
307  else if (conId.type == ObjectId::kCluster) {
308  basePtr->Clusters.push_back(conId.id);
309  }
310  }
311  }
312 
313  // Nodes (probably only used by tracks, showers and particles, but
314  // technically valid for all TReconBase objects.
315  const ND::TReconNodeContainer& nodeCont = baseObject->GetNodes();
316  ND::TReconNodeContainer::const_iterator node;
317  for (node = nodeCont.begin();
318  node != nodeCont.end();
319  ++node) {
320 
321  int nodeId = FillNode(*node, saveHits);
322  basePtr->Nodes.push_back(nodeId);
323  }
324 
325 };
326 
327 int
329  const ND::THandle<ND::TAlgorithmResult> algoRes,
330  int parent) {
331 
332  TString fullName = algoRes->GetFullName();
333  TString baseName = fullName;
334  baseName.Remove(0,baseName.Last('/') + 1);
335 
336  // To save space, we're not going to save a number of the lower level
337  // algorithm results. It is important to remember, that as soon as
338  // a result is not saved, none of it's daughter results will be
339  // saved either.
340  for (std::vector<TPRegexp>::iterator cut = fRejectAlgoResultList.begin();
341  cut != fRejectAlgoResultList.end(); ++cut) {
342 
343  if (cut->MatchB(fullName, "", 0, 1)) {
344  ND280Verbose("Rejecting: " << baseName
345  << " (" << cut->GetPattern() << ")");
346  return -1;
347  }
348  }
349 
350  ND280Verbose("Fill Algorithm Result: " << baseName);
351 
352  int algoResId = fNAlgoResults;
353  TSFGAlgoRes *sfgAlgoResult
354  = new ((*fAlgoResults)[fNAlgoResults++]) TSFGAlgoRes;
355 
356  sfgAlgoResult->FullName = fullName;
357  sfgAlgoResult->AlgorithmName = baseName;
358  sfgAlgoResult->Parent = parent;
359 
360  // Get the final recon object container and save all of the objects. This
361  // needs to be first so that the objects for the main algorithm are the
362  // first thing in all of the vectors.
363  ND::THandle<ND::TReconObjectContainer> final
364  = algoRes->GetResultsContainer("final");
365  if (final) {
366  ND::TReconObjectContainer::const_iterator reconObject;
367  for (reconObject = final->begin();
368  reconObject != final->end(); ++reconObject) {
369  ObjectId objId = FillReconObject(*reconObject, true);
370  if (objId.type == ObjectId::kVertex) {
371  sfgAlgoResult->Vertices.push_back(objId.id);
372  }
373  else if (objId.type == ObjectId::kParticle) {
374  sfgAlgoResult->Particles.push_back(objId.id);
375  }
376  else if (objId.type == ObjectId::kTrack) {
377  sfgAlgoResult->Tracks.push_back(objId.id);
378  }
379  else if (objId.type == ObjectId::kShower) {
380  sfgAlgoResult->Showers.push_back(objId.id);
381  }
382  else if (objId.type == ObjectId::kCluster) {
383  sfgAlgoResult->Clusters.push_back(objId.id);
384  }
385  }
386  }
387 
388  // Get the used hits from the algo result, and save them as a cluster.
389  // This ends up right after the reconstructed clusters in the cluster
390  // vector.
391  ND::THandle<ND::THitSelection> usedHits = algoRes->GetHitSelection("used");
392  if (usedHits && (!usedHits->empty())) {
393  ND::THitSelection::const_iterator hit;
394 
395  for (hit = usedHits->begin();
396  hit != usedHits->end(); ++hit) {
397  int hitId = FillHit(*hit);
398  if (hitId < 0) continue;
399  sfgAlgoResult->Hits.push_back(hitId);
400  }
401  ND::THandle<ND::TReconCluster> usedCluster(new ND::TReconCluster);
402  usedCluster->FillFromHits((baseName+"Used").Data(), *usedHits);
403 
404  ObjectId clusterId = FillReconObject(usedCluster, true);
405  sfgAlgoResult->UsedHitCluster = clusterId.id;
406  }
407  else {
408  sfgAlgoResult->UsedHitCluster = -1;
409  }
410 
411  // Get the unused hits from the algo result, and save them as a cluster.
412  // This ends up right after the used hit cluster in the cluster
413  // vector.
414  ND::THandle<ND::THitSelection> unusedHits
415  = algoRes->GetHitSelection("unused");
416  if (unusedHits && (!unusedHits->empty())) {
417  ND::THandle<ND::TReconCluster> unusedCluster(new ND::TReconCluster);
418  unusedCluster->FillFromHits((baseName+"Unused").Data(), *unusedHits);
419 
420  // We don't want to save the unused hits. The 'false' prevents the
421  ObjectId clusterId = FillReconObject(unusedCluster, false);
422  sfgAlgoResult->UnusedHitCluster = clusterId.id;
423  }
424  else {
425  sfgAlgoResult->UnusedHitCluster = -1;
426  }
427 
428  // Handle any daughter algorithms. They are processed in reverse order so
429  // that the "most important one" is first.
430  for (TDataVector::reverse_iterator d = algoRes->rbegin();
431  d != algoRes->rend(); ++d) {
432  if (!(*d)) continue;
433 
434  std::string class_name = (*d)->ClassName();
435  if (class_name.find("ND::TAlgorithmResult")
436  == std::string::npos) continue;
437 
438  ND::THandle<ND::TAlgorithmResult>
439  subResult = (*d)->Get<ND::TAlgorithmResult>(".");
440  if (!subResult) continue;
441 
442  int daughterId = FillAlgorithmResult(subResult, algoResId);
443 
444  if (daughterId < 0) continue;
445 
446  sfgAlgoResult->AlgoResults.push_back(daughterId);
447  }
448 
449  return algoResId;
450 }
451 
454  const ND::THandle<ND::TReconBase> reconObject,
455  bool saveHits = true) {
456 
457  std::string reco_class_name = reconObject->ClassName();
458 
459  if (reco_class_name.find("ND::TReconVertex") != std::string::npos) {
460  return FillVertexObject(reconObject, saveHits);
461  }
462  else if (reco_class_name.find("ND::TReconPID") != std::string::npos) {
463  return FillParticleObject(reconObject, saveHits);
464  }
465  else if (reco_class_name.find("ND::TReconTrack") != std::string::npos) {
466  return FillTrackObject(reconObject, saveHits);
467  }
468  else if (reco_class_name.find("ND::TReconShower") != std::string::npos) {
469  return FillShowerObject(reconObject, saveHits);
470  }
471  else if (reco_class_name.find("ND::TReconCluster") != std::string::npos) {
472  return FillClusterObject(reconObject, saveHits);
473  }
474 
475  ND280Error("Unknown object passed to TSFGReconModule");
476  ObjectId blank;
477  return blank;
478 }
479 
482  const ND::THandle<ND::TReconVertex> vertex,
483  bool saveHits = true) {
484 
485  ObjectId vertexId;
486  vertexId.id = fNVertices;
487  vertexId.type = ObjectId::kVertex;
488  TSFGVertex* sfgVertex = new ((*fVertices)[fNVertices++]) TSFGVertex;
489 
490  FillBaseObject(sfgVertex, vertex, saveHits);
491 
492  ND::THandle<ND::TVertexState> vertexState = vertex->GetState();
493 
494  sfgVertex->Status = vertex->GetStatus();
495  sfgVertex->Quality = vertex->GetQuality();
496  sfgVertex->NDOF = vertex->GetNDOF();
497  sfgVertex->Position = vertexState->GetPosition();
498  sfgVertex->PosVariance = vertexState->GetPositionVariance();
499 
500  sfgVertex->Truth_TrajIds.clear();
501  sfgVertex->Truth_HitCount.clear();
502  sfgVertex->Truth_ChargeShare.clear();
503 
504  ND::THandle<ND::THitSelection> vertexHits = vertex->GetHits();
505  if (vertexHits) {
506 
507  std::map< int, std::pair<int, float> > hitInfo
508  = HitTruthInfo(vertexHits);
509  std::map< int, std::pair< int, float > >::iterator parentId;
510 
511  for (parentId = hitInfo.begin();
512  parentId != hitInfo.end(); ++parentId) {
513  sfgVertex->Truth_TrajIds.push_back((*parentId).first);
514  sfgVertex->Truth_HitCount.push_back((*parentId).second.first);
515  sfgVertex->Truth_ChargeShare.push_back((*parentId).second.second);
516  }
517 
518  sfgVertex->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(vertexHits);
519  }
520 
521  return vertexId;
522 }
523 
526  const ND::THandle<ND::TReconPID> particle,
527  bool saveHits = true) {
528 
529  ObjectId particleId;
530  particleId.id = fNParticles;
531  particleId.type = ObjectId::kParticle;
532  TSFGParticle* sfgParticle = new ((*fParticles)[fNParticles++]) TSFGParticle;
533 
534  FillBaseObject(sfgParticle, particle, saveHits);
535 
536  ND::THandle<ND::TPIDState> particleState = particle->GetState();
537 
538  sfgParticle->Status = particle->GetStatus();
539  sfgParticle->Quality = particle->GetQuality();
540  sfgParticle->NDOF = particle->GetNDOF();
541  sfgParticle->Position = particleState->GetPosition();
542  sfgParticle->PosVariance = particleState->GetPositionVariance();
543  sfgParticle->Direction = particleState->GetDirection();
544  sfgParticle->DirVariance = particleState->GetDirectionVariance();
545  sfgParticle->Momentum = particle->GetMomentum();
546  sfgParticle->Charge = particle->GetCharge();
547 
548  const ND::THandle<ND::THitSelection> particleHits = particle->GetHits();
549  if (particleHits) {
550 
551  std::map< int, std::pair<int, float> > hitInfo
552  = HitTruthInfo(particleHits);
553  std::map< int, std::pair< int, float > >::iterator parentId;
554 
555  for (parentId = hitInfo.begin();
556  parentId != hitInfo.end(); ++parentId) {
557  sfgParticle->Truth_TrajIds.push_back((*parentId).first);
558  sfgParticle->Truth_HitCount.push_back((*parentId).second.first);
559  sfgParticle->Truth_ChargeShare.push_back((*parentId).second.second);
560  }
561 
562  sfgParticle->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(particleHits);
563  }
564 
565  // The most likely PID is available through particle->GetParticle,
566  // but it is also stored as one of the alternates. These are sorted
567  // in order of PID, so copy them directly into the TTree.
568  ND::TReconObjectContainer::const_iterator alternate;
569 
570  for (alternate = particle->GetAlternates().begin();
571  alternate != particle->GetAlternates().end();
572  ++alternate) {
573 
574  ND::THandle<ND::TReconPID> alt = (*alternate);
575  if (alt) {
576  sfgParticle->PID.push_back(alt->GetParticleId());
577  sfgParticle->PID_weight.push_back(alt->GetPIDWeight());
578  }
579  else {
580  ND280Warn("TReconPID alternate is not a TReconPID - Ignored");
581  }
582  }
583 
584  // Fill the true particle when it is found
585  double pur, eff;
586  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*particle, pur, eff);
587  if(G4track){
588  sfgParticle->TrueParticleID = G4track->GetTrackId();
589  sfgParticle->TrueParticlePur = pur;
590  sfgParticle->TrueParticleEff = eff;
591  }
592  else{
593  sfgParticle->TrueParticleID = -1;
594  sfgParticle->TrueParticlePur = -1;
595  sfgParticle->TrueParticleEff = -1;
596  }
597 
598  return particleId;
599 }
600 
602 ND::TSFGReconModule::FillTrackObject(const ND::THandle<ND::TReconTrack> track,
603  bool saveHits = true) {
604  ObjectId trackId;
605  trackId.id = fNTracks;
606  trackId.type = ObjectId::kTrack;
607  TSFGTrack* sfgTrack = new ((*fTracks)[fNTracks++]) TSFGTrack;
608 
609  FillBaseObject(sfgTrack, track, saveHits);
610 
611  ND::THandle<ND::TTrackState> trackState = track->GetState();
612 
613  sfgTrack->Status = track->GetStatus();
614  sfgTrack->Quality = track->GetQuality();
615  sfgTrack->NDOF = track->GetNDOF();
616  sfgTrack->Position = trackState->GetPosition();
617  sfgTrack->PosVariance = trackState->GetPositionVariance();
618  sfgTrack->Direction = trackState->GetDirection();
619  sfgTrack->DirVariance = trackState->GetDirectionVariance();
620  sfgTrack->EDeposit = trackState->GetEDeposit();
621 
622  const ND::THandle<ND::THitSelection> trackHits = track->GetHits();
623  if (trackHits) {
624 
625  std::map< int, std::pair<int, float> > hitInfo
626  = HitTruthInfo(trackHits);
627  std::map< int, std::pair< int, float > >::iterator parentId;
628 
629  for (parentId = hitInfo.begin();
630  parentId != hitInfo.end(); ++parentId) {
631  sfgTrack->Truth_TrajIds.push_back((*parentId).first);
632  sfgTrack->Truth_HitCount.push_back((*parentId).second.first);
633  sfgTrack->Truth_ChargeShare.push_back((*parentId).second.second);
634  }
635 
636  sfgTrack->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(trackHits);
637  }
638 
639  const ND::TReconNodeContainer& nodeCont = track->GetNodes();
640 
641  // Get the track length from the nodes
642  sfgTrack->Length = 0.0;
643  if (nodeCont.size() < 1) return trackId;
644 
645  ND::TReconNodeContainer::const_iterator node = nodeCont.begin();
646  ND::THandle<ND::TTrackState> nodeState = (*node)->GetState();
647  TVector3 frontPos = nodeState->GetPosition().Vect();
648  ++node;
649 
650  while (node != nodeCont.end()) {
651 
652  // Check the node is valid
653  if (!(*node)) {
654  ++node;
655  continue;
656  }
657  nodeState = (*node)->GetState();
658 
659  sfgTrack->Length += (frontPos - nodeState->GetPosition().Vect()).Mag();
660  frontPos = nodeState->GetPosition().Vect();
661 
662  ++node;
663  }
664 
665  // Fill the true particle when it is found
666  double pur, eff;
667  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*track, pur, eff);
668  if(G4track){
669  sfgTrack->TrueParticleID = G4track->GetTrackId();
670  sfgTrack->TrueParticlePur = pur;
671  sfgTrack->TrueParticleEff = eff;
672  }
673  else{
674  sfgTrack->TrueParticleID = -1;
675  sfgTrack->TrueParticlePur = -1;
676  sfgTrack->TrueParticleEff = -1;
677  }
678 
679  return trackId;
680 }
681 
684  const ND::THandle<ND::TReconShower> shower,
685  bool saveHits = true) {
686 
687  ObjectId showerId;
688  showerId.id = fNShowers;
689  showerId.type = ObjectId::kShower;
690  TSFGShower* sfgShower = new ((*fShowers)[fNShowers++]) TSFGShower;
691 
692  FillBaseObject(sfgShower, shower, saveHits);
693 
694  // For Shower objects, the cluster information of the nodes is vital for
695  // the pi0 analysis. However, the cluster information for most nodes is
696  // useless. Therefore, rather than adding a "FillClusterObject" to each
697  // "FillNode", we will do a parallel fill, within the
698  // FillShowerObject. N.B. FillNode has already been run within
699  // FillBaseObject.
700 
701  const ND::TReconNodeContainer& nodeCont = shower->GetNodes();
702  for (ND::TReconNodeContainer::const_iterator node = nodeCont.begin();
703  node != nodeCont.end(); ++node) {
704  ND::THandle<ND::TReconCluster> cluster = (*node)->GetObject();
705  ObjectId clusterId = FillClusterObject(cluster, saveHits);
706  sfgShower->Clusters.push_back(clusterId.id);
707  }
708 
709  ND::THandle<ND::TShowerState> showerState = shower->GetState();
710 
711  sfgShower->Status = shower->GetStatus();
712  sfgShower->Quality = shower->GetQuality();
713  sfgShower->NDOF = shower->GetNDOF();
714  sfgShower->Position = showerState->GetPosition();
715  sfgShower->PosVariance = showerState->GetPositionVariance();
716  sfgShower->Direction = showerState->GetDirection();
717  sfgShower->DirVariance = showerState->GetDirectionVariance();
718  sfgShower->EDeposit = showerState->GetEDeposit();
719  sfgShower->Cone = showerState->GetCone()[0];
720 
721  sfgShower->Width = 0.0;
722  sfgShower->Length = 0.0;
723 
724  const ND::THandle<ND::THitSelection> showerHits = shower->GetHits();
725 
726  double totalCharge = 0.0;
727  float avgLen = 0.0;
728  float avgLen2 = 0.0;
729 
730  if (showerHits) {
731  std::map< int, std::pair<int, float> > hitInfo
732  = HitTruthInfo(showerHits);
733 
734  for (std::map< int, std::pair< int, float > >::iterator parentId
735  = hitInfo.begin();
736  parentId != hitInfo.end(); ++parentId) {
737  sfgShower->Truth_TrajIds.push_back((*parentId).first);
738  sfgShower->Truth_HitCount.push_back((*parentId).second.first);
739  sfgShower->Truth_ChargeShare.push_back((*parentId).second.second);
740  }
741 
742  sfgShower->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(showerHits);
743 
744 
745  for (ND::THitSelection::const_iterator hit = showerHits->begin();
746  hit != showerHits->end(); ++hit) {
747 
748  // The distance vector between the hit and the shower position
749  TVector3 diff = (*hit)->GetPosition() - sfgShower->Position.Vect();
750 
751  // The distance vector along the shower direction
752  TVector3 para = (diff*sfgShower->Direction)*sfgShower->Direction;
753 
754  // The distance vector normal to the shower direction
755  TVector3 perp = diff - para;
756 
757  float q = (*hit)->GetCharge();
758  totalCharge += q;
759 
760  sfgShower->Width += q * perp.Mag();
761 
762  avgLen += q * para.Mag();
763  avgLen2 += q * (para * para);
764 
765  }
766  }
767 
768  sfgShower->Width /= std::max(totalCharge,1.0);
769 
770  avgLen /= std::max(totalCharge,1.0);
771  avgLen2 /= std::max(totalCharge,1.0);
772  double len2 = avgLen2 - avgLen*avgLen;
773 
774  sfgShower->Length = std::sqrt(std::max(0.0, len2));
775 
776  return showerId;
777 }
778 
781  const ND::THandle<ND::TReconCluster> cluster,
782  bool saveHits = true) {
783 
784  ObjectId clusterId;
785  clusterId.id = fNClusters;
786  clusterId.type = ObjectId::kCluster;
787  TSFGCluster* sfgCluster = new ((*fClusters)[fNClusters++]) TSFGCluster;
788 
789  FillBaseObject(sfgCluster, cluster, saveHits);
790 
791  sfgCluster->EDeposit = cluster->GetEDeposit();
792  sfgCluster->Position = cluster->GetPosition();
793  sfgCluster->PosVariance = cluster->GetPositionVariance();
794 
795  TMatrixF moments = cluster->GetMoments();
796  if (sfgCluster->arraySize ==
797  (moments.GetNrows() * moments.GetNcols()) ) {
798  std::copy(moments.GetMatrixArray(),
799  moments.GetMatrixArray()+sfgCluster->arraySize,
800  sfgCluster->Moments);
801  }
802 
803  const ND::THandle<ND::THitSelection> clusterHits = cluster->GetHits();
804  if (clusterHits) {
805  std::map< int, std::pair<int, float> > hitInfo
806  = HitTruthInfo(clusterHits);
807  std::map< int, std::pair< int, float > >::iterator parentId;
808 
809  for (parentId = hitInfo.begin();
810  parentId != hitInfo.end(); ++parentId) {
811  sfgCluster->Truth_TrajIds.push_back((*parentId).first);
812  sfgCluster->Truth_HitCount.push_back((*parentId).second.first);
813  sfgCluster->Truth_ChargeShare.push_back((*parentId).second.second);
814  }
815 
816  sfgCluster->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(clusterHits);
817  }
818 
819  // Fill the true particle when it is found
820  double pur, eff;
821  ND::THandle<ND::TG4Trajectory> G4track = GetG4Trajectory(*cluster, pur, eff);
822  if(G4track){
823  sfgCluster->TrueParticleID = G4track->GetTrackId();
824  sfgCluster->TrueParticlePur = pur;
825  sfgCluster->TrueParticleEff = eff;
826  }
827  else{
828  sfgCluster->TrueParticleID = -1;
829  sfgCluster->TrueParticlePur = -1;
830  sfgCluster->TrueParticleEff = -1;
831  }
832 
833  return clusterId;
834 }
835 
837  const ND::THandle<ND::TReconNode> node,
838  bool saveHits) {
839 
840  int nodeId = fNNodes;
841  TSFGNode* sfgNode = new ((*fNodes)[fNNodes++]) TSFGNode;
842 
843 
844 
845 
846 
847  // The node state may be a PIDState, TrackState or ShowerState, but
848  // they are all TMPositionDirectionStates, so we access the position
849  // and direction regardless.
850  ND::THandle<ND::TReconState> s1 = node->GetState();
851  if (s1) {
852  #if BEFORE_oaEvent(9,0,0)
853  const ND::TMPositionDirectionState* posDirState = NULL;
854  posDirState =
855  dynamic_cast<const ND::TMPositionDirectionState*>(ND::GetPointer(s1));
856  if(posDirState){
857  sfgNode->Position = posDirState->GetPosition();
858  sfgNode->PosVariance = posDirState->GetPositionVariance();
859  sfgNode->Direction = posDirState->GetDirection();
860  sfgNode->DirVariance = posDirState->GetDirectionVariance();
861 
862  /*const ND::TMEDepositState* eDepState = NULL;
863  eDepState = dynamic_cast<const ND::TMEDepositState*>(ND::GetPointer(s1));
864  if(eDepState){
865  sfgNode->EDeposit_fit = eDepState->GetEDeposit();
866  }*/
867  }
868  #else
869  sfgNode->Position = GetPosition(s1);
870  sfgNode->PosVariance = GetPositionVariance(s1);
871  sfgNode->Direction = ND::TPIDState::GetStateDirection(s1);
872  sfgNode->DirVariance = ND::TPIDState::GetStateDirectionVariance(s1);
873 
874  //sfgNode->EDeposit_fit = ND::TPIDState::GetStateEDeposit(s1);
875  #endif
876 
877  }
878 
879  // Get fitted energy deposit from node state
880  ND::THandle<ND::TTrackState> s2 = node->GetState();
881  if(s2){
882  sfgNode->EDeposit_fit = s2->GetEDeposit();
883  }
884 
885  // Every node should have an object
886  ND::THandle<ND::TReconBase> nodeObject = node->GetObject();
887  if (nodeObject) {
888  ND::THandle<ND::TReconState> objState = nodeObject->GetState();
889  if (objState) {
890 #if BEFORE_oaEvent(9,0,0)
891  const ND::TMEDepositState* eDepState = NULL;
892  eDepState =
893  dynamic_cast<const ND::TMEDepositState*>(ND::GetPointer(s1));
894  if (eDepState) {
895  sfgNode->EDeposit = eDepState->GetEDeposit();
896  }
897 
898  }
899  #else
900  sfgNode->EDeposit = ND::TPIDState::GetStateEDeposit(objState);
901  #endif
902 
903 
904  }
905 
906  const ND::THandle<ND::THitSelection> nodeHits = nodeObject->GetHits();
907  if (nodeHits) {
908  ND::THitSelection::const_iterator hit;
909 
910  for (hit = nodeHits->begin();
911  hit != nodeHits->end(); ++hit) {
912 
913  int hitId = FillHit(*hit);
914  if (hitId >= 0) {
915  sfgNode->Hits.push_back(hitId);
916  }
917  }
918 
919  std::map< int, std::pair<int, float> > hitInfo
920  = HitTruthInfo(nodeHits);
921  std::map< int, std::pair< int, float > >::iterator parentId;
922 
923  for (parentId = hitInfo.begin();
924  parentId != hitInfo.end(); ++parentId) {
925  sfgNode->Truth_TrajIds.push_back((*parentId).first);
926  sfgNode->Truth_HitCount.push_back((*parentId).second.first);
927  sfgNode->Truth_ChargeShare.push_back((*parentId).second.second);
928  }
929 
930  sfgNode->Truth_PrimaryTrajIds = HitTruthPrimaryInfo(nodeHits);
931 
932  }
933  }
934 
935  return nodeId;
936 }
937 
938 int
939 ND::TSFGReconModule::FillHit(const ND::THandle<ND::THit> hit) {
940  if (!hit) {
941  ND280Error("Trying to handle illegal hit");
942  return -1;
943  }
944 
945  // Check if this Hit has already been filled, if so pass back the
946  // index, instead of creating a new one.
947  HitMap::const_iterator mapIter;
948  mapIter = fTempHitMap.find(hit);
949  if ( mapIter != fTempHitMap.end() ) {
950  return mapIter->second;
951  }
952 
953  // Save the index of the location for the new hit.
954  int hitId = AddHit(hit,fNHits,fHits);
955  if (hitId < 0) return hitId;
956  fTempHitMap[hit] = hitId;
957 
958  return hitId;
959 }
960 
961 int
962 ND::TSFGReconModule::AddHit(const ND::THandle<ND::THit> hit,
963  int& nDest,
965  if (!hit) {
966  ND280Error("Trying to handle illegal hit");
967  return -1;
968  }
969 
970  int hitId = nDest;
971  TSFGHit *sfgHit = new ((*dest)[nDest++]) TSFGHit;
972 
973  sfgHit->GeomId = hit->GetGeomId().AsInt();
974  sfgHit->Charge = hit->GetCharge();
975  sfgHit->Time = hit->GetTime();
976  sfgHit->Position = hit->GetPosition();
977 
978  // Add information that is needed for neural network study
979  // For the moment need track hit tagging and hit segment
980  FillHitInfoNeededForNN(hit,sfgHit);
981 
982  return hitId;
983 }
984 
985 std::map< int, std::pair<int, float> >
986 ND::TSFGReconModule::HitTruthInfo(const ND::THandle<ND::THitSelection> hits) {
987  std::map< int, std::pair<int, float> > result;
988 
989  // then loop over everything and log the trajectory ids.
990  for (ND::THitSelection::const_iterator hit = hits->begin();
991  hit != hits->end(); ++hit) {
992 
993  float hitCharge = (*hit)->GetCharge();
994  std::map< int, int > hitCount;
995  std::map< int, float > chargeShare;
996 
997  std::vector<ND::TG4VHit*> hitContribs
998  = HitTruthInfo::GetHitTruthInfo(*hit);
999 
1000  for (std::vector<ND::TG4VHit*>::const_iterator g4Hit
1001  = hitContribs.begin();
1002  g4Hit != hitContribs.end(); ++g4Hit) {
1003 
1004  ND::TG4HitSegment* g4HitCast
1005  = dynamic_cast<ND::TG4HitSegment*>(*g4Hit);
1006 
1007  // For each contributing trajectory, increase the hit count and
1008  // give it an equal share of the energy deposit (the share may
1009  // not be equal, but that information is not currently
1010  // available).
1011  std::vector<int>::const_iterator trajIdIter;
1012  for (trajIdIter = g4HitCast->GetContributors().begin();
1013  trajIdIter != g4HitCast->GetContributors().end();
1014  ++trajIdIter) {
1015 
1016  ++hitCount[(*trajIdIter)];
1017  chargeShare[(*trajIdIter)] +=
1018  g4HitCast->GetEnergyDeposit()
1019  / g4HitCast->GetContributors().size();
1020  }
1021  }
1022 
1023  for (std::map< int, int >::const_iterator hC = hitCount.begin();
1024  hC != hitCount.end(); ++hC) {
1025  // If this hit had a contribution from a given Id, then increment
1026  // that Id's hitcount.
1027  if ((*hC).second > 0) {
1028  result[(*hC).first].first;
1029  }
1030  }
1031 
1032  // Count up the contributed charge (this won't necessarily match the
1033  // hit Charge).
1034  float totalChargeShare = 0;
1035  for (std::map< int, float >::const_iterator cS = chargeShare.begin();
1036  cS != chargeShare.end(); ++cS) {
1037  totalChargeShare += (*cS).second;
1038  }
1039 
1040  // For each entry, determine the contributed share.
1041  for (std::map< int, float >::const_iterator cS = chargeShare.begin();
1042  cS != chargeShare.end(); ++cS) {
1043  result[(*cS).first].second +=
1044  hitCharge * (*cS).second / totalChargeShare;
1045  }
1046  }
1047  return result;
1048 }
1049 
1050 std::vector<int>
1052  const ND::THandle<ND::THitSelection> hits) {
1053 
1054  std::vector<int> result;
1055  // Loop over all hits, storing each primary Id which contributed
1056  for (ND::THitSelection::const_iterator hit = hits->begin();
1057  hit != hits->end(); ++hit) {
1058  std::vector<ND::TG4VHit*> hitContribs
1059  = HitTruthInfo::GetHitTruthInfo(*hit);
1060 
1061  for (std::vector<ND::TG4VHit*>::const_iterator
1062  g4Hit = hitContribs.begin();
1063  g4Hit != hitContribs.end(); ++g4Hit) {
1064  ND::TG4HitSegment* g4HitCast
1065  = dynamic_cast<ND::TG4HitSegment*>(*g4Hit);
1066  result.push_back(g4HitCast->GetPrimaryId());
1067  }
1068  }
1069 
1070  // Sort the list of primary Ids
1071  std::sort(result.begin(), result.end());
1072 
1073  // Remove duplicate Ids
1074  std::vector<int>::iterator newEnd =
1075  std::unique(result.begin(), result.end());
1076  result.erase(newEnd, result.end());
1077 
1078  return result;
1079 }
1080 
1081 // ---- For SFGD neural network study ----
1082 
1083 void ND::TSFGReconModule::FillHitInfoNeededForNN(const ND::THandle<ND::THit> hit, TSFGHit *sfgHit){
1084 
1085  // Clean the vectors
1086  sfgHit->HitSegPosition.clear();
1087  sfgHit->HitSegDirection.clear();
1088  sfgHit->HitSegTruePDG.clear();
1089  sfgHit->HitSegTrueP.clear();
1090  sfgHit->HitSegTrueEdepo.clear();
1091 
1092  // First get number of contributing MPPCs to this hit
1093  int NumContrMPPCs = hit->GetContributorCount();
1094 
1095  // Hit segments contributing to MPPC readout (3 2D planes)
1096  std::vector<ND::TG4HitSegment*> HitSegXYPlane;
1097  std::vector<ND::TG4HitSegment*> HitSegXZPlane;
1098  std::vector<ND::TG4HitSegment*> HitSegYZPlane;
1099 
1100  // One vector containing all of hit segments
1101  std::vector<ND::TG4HitSegment*> HitSegAllPlanes;
1102 
1103  // Then loop over all MPPCs
1104  for (int MPPCHit = 0; MPPCHit < NumContrMPPCs; MPPCHit++) {
1105 
1106  // Get the true hits contributing to the hit segments
1107  ND::THandle<ND::THit> currContrMPPC = hit->GetContributor(MPPCHit);
1108  std::vector<ND::TG4VHit*> TrueG4Hit = HitTruthInfo::GetHitTruthInfo(currContrMPPC);
1109 
1110  // Loop over all G4VHits
1111  for (auto G4Hit : TrueG4Hit) {
1112 
1113  // Cast G4VHit to hit segment
1114  ND::TG4HitSegment* G4HitSeg = dynamic_cast<ND::TG4HitSegment*>(G4Hit);
1115  if (G4HitSeg == NULL) {
1116  ND280Log("Cast of TG4Hit to TG4HitSegments unsuccessful");
1117  continue;
1118  }
1119 
1120  if (MPPCHit == 1) HitSegXZPlane.push_back(G4HitSeg);
1121  if (MPPCHit == 2) HitSegYZPlane.push_back(G4HitSeg);
1122  if (MPPCHit == 3) HitSegXYPlane.push_back(G4HitSeg);
1123 
1124  } // End of G4VHits loop
1125 
1126  } // End of MPPC loop
1127 
1128  // The number of true tracks contributed to the hit
1129  std::vector<int> TrueTrkID;
1130  std::vector<int> TrueTrkParentID;
1131  std::vector<int> InCubeTag;
1132 
1133  std::vector<ND::TG4HitSegment*> XZandYZIntersection; // intermediate result
1134  std::vector<ND::TG4HitSegment*> XZandXYIntersection; // intermediate result
1135  std::vector<ND::TG4HitSegment*> XYandYZIntersection; // intermediate result
1136 
1137  // intersection of hit segments from all three planes
1138  // i.e. the hit segments contributing to the current cube
1139  std::vector<ND::TG4HitSegment*> currContrHitSegV;
1140 
1141  // compare the three sets of hit segments contributing to the MPPCs, and
1142  // find the intersection - these are the hit segments contributing to current cube
1143  std::sort(HitSegXZPlane.begin(), HitSegXZPlane.end());
1144  std::sort(HitSegYZPlane.begin(), HitSegYZPlane.end());
1145  std::sort(HitSegXYPlane.begin(), HitSegXYPlane.end());
1146 
1147  std::set_intersection(HitSegXZPlane.begin(), HitSegXZPlane.end(), HitSegYZPlane.begin(), HitSegYZPlane.end(), back_inserter(XZandYZIntersection));
1148  std::sort(XZandYZIntersection.begin(), XZandYZIntersection.end());
1149  std::set_intersection(XZandYZIntersection.begin(), XZandYZIntersection.end(), HitSegXYPlane.begin(), HitSegXYPlane.end(), back_inserter(currContrHitSegV));
1150 
1151  // loop over all hit segments contributing to the current cube (true hit + xtalk)
1152  // i.e. those hit segments in the intersection of all three planes
1153  for (auto HitSeg : currContrHitSegV) {
1154 
1155  // for true hits (hitSegDistanceI < 5 mm for I = X, Y, and Z),
1156  // sum their energy deposit in the current cube
1157  if (checkHitSegInCube(hit, HitSeg) == true) {
1158  // get primary track ID
1159  ND::THandle<ND::TG4Trajectory> traj_temp = fTrueTraj->GetTrajectory(HitSeg->GetPrimaryId());
1160  if(!traj_temp) continue;
1161  TrueTrkID.push_back(traj_temp->GetTrackId());
1162  TrueTrkParentID.push_back(traj_temp->GetParentId());
1163  InCubeTag.push_back(1);
1164 
1165  // Fill true trajectory information
1166  FillTrueTrajInfoForHit(HitSeg,sfgHit);
1167  }
1168  else{
1169  ND::THandle<ND::TG4Trajectory> traj_temp = fTrueTraj->GetTrajectory(HitSeg->GetPrimaryId());
1170  if(!traj_temp) continue;
1171  TrueTrkID.push_back(traj_temp->GetTrackId());
1172  TrueTrkParentID.push_back(traj_temp->GetParentId());
1173  InCubeTag.push_back(0);
1174  }
1175 
1176  } // end hit segment loop
1177 
1178  // Check the length of TrueTrkID, if >= 1 then determine the single or multiple tag
1179  if(TrueTrkID.size()==0){
1180  sfgHit->TrkHitTag = 3;
1181  }
1182  else{
1183  // Only select tracks with ParentID = 0
1184  std::vector<int> PassTrkID;
1185 
1186  for(size_t i = 0; i < TrueTrkID.size(); i++){
1187  if(TrueTrkParentID[i]==0) PassTrkID.push_back(TrueTrkID[i]);
1188  }
1189 
1190  if(PassTrkID.size()>=1){
1191  std::sort(PassTrkID.begin(),PassTrkID.end());
1192  int NElement = PassTrkID.size();
1193 
1194  if(PassTrkID[0]!=PassTrkID[NElement-1]) sfgHit->TrkHitTag = 1;
1195  else{
1196  sfgHit->TrkHitTag = 2;
1197  bool trackhit = false;
1198  for(size_t i = 0; i < TrueTrkID.size(); i++){
1199  if(InCubeTag[i]==1) trackhit = true;
1200  }
1201  if(trackhit==false) sfgHit->TrkHitTag = 3;
1202  }
1203  }
1204  else{
1205  sfgHit->TrkHitTag = 2;
1206  bool trackhit = false;
1207  for(size_t i = 0; i < TrueTrkID.size(); i++){
1208  if(InCubeTag[i]==1) trackhit = true;
1209  }
1210  if(trackhit==false) sfgHit->TrkHitTag = 3;
1211  }
1212 
1213  }
1214 
1215  // Then check the nearby cubes if there are multiple tracks
1216  if(checkNearbyMultiTrk(hit,HitSegAllPlanes,fTrueTraj)==true) sfgHit->TrkHitTag = 1;
1217 
1218 }
1219 
1220 bool ND::TSFGReconModule::checkHitSegInCube(ND::THandle<ND::THit> hit, ND::TG4HitSegment* HitSeg) {
1221 // check if a hit segment is inside the cube corresponding to the hit
1222 
1223  //i.e. check if the hit segment midpoint is +/- 5 mm away from the cube position
1224  int dist = 5;
1225  int negdist = -5;
1226  bool isInside = false;
1227 
1228  // define position of hit segment as the midpoint
1229  double HitSegPosX = 0.5*(HitSeg->GetStartX() + HitSeg->GetStopX());
1230  double HitSegPosY = 0.5*(HitSeg->GetStartY() + HitSeg->GetStopY());
1231  double HitSegPosZ = 0.5*(HitSeg->GetStartZ() + HitSeg->GetStopZ());
1232 
1233  // distance of hit segment position to cube center (= position of reco hit)
1234  // (if < 5 mm from cube center, it is a true hit)
1235  double HitSegDistanceX = hit->GetPosition().X() - HitSegPosX;
1236  double HitSegDistanceY = hit->GetPosition().Y() - HitSegPosY;
1237  double HitSegDistanceZ = hit->GetPosition().Z() - HitSegPosZ;
1238 
1239  bool HitSegXIn = HitSegDistanceX > negdist && HitSegDistanceX < dist;
1240  bool HitSegYIn = HitSegDistanceY > negdist && HitSegDistanceY < dist;
1241  bool HitSegZIn = HitSegDistanceZ > negdist && HitSegDistanceZ < dist;
1242 
1243  // for true hits (hitSegDistanceI < 5 mm for I = X, Y, and Z),
1244  // sum their energy deposit in the current cube
1245  if (HitSegXIn && HitSegYIn && HitSegZIn) {
1246  isInside = true;
1247  }
1248  return isInside;
1249 }
1250 
1251 bool ND::TSFGReconModule::checkNearbyMultiTrk(ND::THandle<ND::THit> hit, std::vector<ND::TG4HitSegment*> HitSegAllPlanes, ND::THandle<ND::TG4TrajectoryContainer> true_traj){
1252 
1253  // Get the center position of the cube
1254  double cube_posx = hit->GetPosition().X();
1255  double cube_posy = hit->GetPosition().Y();
1256  double cube_posz = hit->GetPosition().Z();
1257 
1258  // A vector to save the hit segment primary ID in adjacent cubes
1259  std::vector<int> nearby_trkid;
1260  std::vector<int> nearby_trkparentid;
1261 
1262  bool InAdjacent;
1263 
1264  // Loop over all hit segments
1265  for (auto HitSeg : HitSegAllPlanes) {
1266 
1267  // Estimate hit segment position
1268  double hitseg_posx = 0.5*(HitSeg->GetStartX() + HitSeg->GetStopX());
1269  double hitseg_posy = 0.5*(HitSeg->GetStartY() + HitSeg->GetStopY());
1270  double hitseg_posz = 0.5*(HitSeg->GetStartZ() + HitSeg->GetStopZ());
1271 
1272  // Check if the hit segment is in the adjacent cube
1273  // Along X direction
1274  if(TMath::Abs(cube_posx-hitseg_posx)>5 && TMath::Abs(cube_posx-hitseg_posx)<15 &&
1275  TMath::Abs(cube_posy-hitseg_posy)<5 && TMath::Abs(cube_posz-hitseg_posz)<5){
1276  InAdjacent = true;
1277  }
1278  // Along Y direction
1279  else if(TMath::Abs(cube_posy-hitseg_posy)>5 && TMath::Abs(cube_posy-hitseg_posy)<15 &&
1280  TMath::Abs(cube_posx-hitseg_posx)<5 && TMath::Abs(cube_posz-hitseg_posz)<5){
1281  InAdjacent = true;
1282  }
1283  // Along Z direction
1284  else if(TMath::Abs(cube_posz-hitseg_posz)>5 && TMath::Abs(cube_posz-hitseg_posz)<15 &&
1285  TMath::Abs(cube_posx-hitseg_posx)<5 && TMath::Abs(cube_posy-hitseg_posy)<5){
1286  InAdjacent = true;
1287  }
1288  else{
1289  InAdjacent = false;
1290  }
1291 
1292  if(InAdjacent==true){
1293  ND::THandle<ND::TG4Trajectory> traj_temp = true_traj->GetTrajectory(HitSeg->GetPrimaryId());
1294  if(!traj_temp) continue;
1295  nearby_trkid.push_back(traj_temp->GetTrackId());
1296  nearby_trkparentid.push_back(traj_temp->GetParentId());
1297  }
1298 
1299  }
1300 
1301  // Check the track ID
1302  int N = nearby_trkid.size();
1303 
1304  if(N<1) return false;
1305  else{
1306 
1307  // Only select tracks with ParentID = 0
1308  std::vector<int> pass_trkid;
1309  for(int i = 0; i < N; i++){
1310  if(nearby_trkparentid[i]==0) pass_trkid.push_back(nearby_trkid[i]);
1311  }
1312 
1313  int n = pass_trkid.size();
1314 
1315  if(n<1) return false;
1316  else{
1317  std::sort(pass_trkid.begin(),pass_trkid.end());
1318 
1319  if(pass_trkid[0]!=pass_trkid[n-1]) return true;
1320  else return false;
1321  }
1322 
1323  }
1324 
1325 }
1326 
1327 void ND::TSFGReconModule::FillTrueTrajInfoForHit(ND::TG4HitSegment *HitSeg, TSFGHit *sfgHit){
1328 
1329  // Compute hit segment center position
1330  TLorentzVector hitseg_pos;
1331  hitseg_pos.SetXYZT(0.5*(HitSeg->GetStartX() + HitSeg->GetStopX()),
1332  0.5*(HitSeg->GetStartY() + HitSeg->GetStopY()),
1333  0.5*(HitSeg->GetStartZ() + HitSeg->GetStopZ()),
1334  0.5*(HitSeg->GetStartT() + HitSeg->GetStopT()));
1335 
1336  // Compute hit segment direction
1337  TVector3 hitseg_dir;
1338  hitseg_dir.SetXYZ(HitSeg->GetStopX() - HitSeg->GetStartX(),
1339  HitSeg->GetStopY() - HitSeg->GetStartY(),
1340  HitSeg->GetStopZ() - HitSeg->GetStartZ());
1341 
1342  if(hitseg_dir.Mag() > 0) hitseg_dir *= (1. / hitseg_dir.Mag());
1343 
1344  // Get the IDs of the true trajectory contributing to this hit segment
1345  std::vector<int> traj_ids = HitSeg->GetContributors();
1346 
1347  // Loop over true trajectory IDs to save their information
1348  int curr_id = traj_ids[0];
1349  for(size_t i = 0; i < traj_ids.size(); i++){
1350 
1351  if(i != 0 && traj_ids[i] == curr_id) continue;
1352  curr_id = traj_ids[i];
1353 
1354  ND::THandle<ND::TG4Trajectory> traj_temp = fTrueTraj->GetTrajectory(traj_ids[i]);
1355  if(!traj_temp) continue;
1356 
1357  // Fill the position (same for the same hit segment)
1358  sfgHit->HitSegPosition.push_back(hitseg_pos);
1359 
1360  // Fill the direction
1361  sfgHit->HitSegDirection.push_back(hitseg_dir);
1362 
1363  // True particle PDG of the trajectory
1364  sfgHit->HitSegTruePDG.push_back(traj_temp->GetPDGEncoding());
1365 
1366  // True momentum of the trajectory
1367  int traj_mom = (traj_temp->GetInitialMomentum().Vect()).Mag();
1368  sfgHit->HitSegTrueP.push_back(traj_mom);
1369 
1370  // True energy loss from this hit segment
1371  sfgHit->HitSegTrueEdepo.push_back(HitSeg->GetSecondaryDeposit());
1372 
1373  }
1374 
1375 }
1376 
1377 template <class T>
1378 ND::THandle<ND::TG4Trajectory> ND::TSFGReconModule::GetG4Trajectory(
1379  const T& object, double& purity, double& eff){
1380 
1381  purity = -0xABCDEF;
1382  eff = -0xABCDEF;
1383 
1384  ND::TG4Trajectory traj;
1385  ND::THandle<ND::THitSelection> hits = object.GetHits();
1386  if (!hits) {
1387  return ND::THandle<ND::TG4Trajectory>();
1388  }
1389  if (hits->size() < 1) {
1390  return ND::THandle<ND::TG4Trajectory>();
1391  }
1392 
1393  int G4TrkId = TrackTruthInfo::GetG4TrajIDHits(*hits, eff, purity);
1394  const ND::TND280Event& event = *(ND::TEventFolder::GetCurrentEvent());
1395  ND::THandle<ND::TG4TrajectoryContainer> G4trajectories =
1396  event.Get<ND::TG4TrajectoryContainer>("truth/G4Trajectories");
1397  if (!G4trajectories) {
1398  return ND::THandle<ND::TG4Trajectory>();
1399  }
1400  ND::TG4TrajectoryContainer::iterator trajIter = fTrueTraj->begin();
1401  ND::TG4TrajectoryContainer::iterator trajEnd = fTrueTraj->end();
1402  for (; trajIter != trajEnd; ++trajIter) {
1403  ND::TG4Trajectory* trajectory = &(trajIter->second);
1404  if (trajectory->GetTrackId() == G4TrkId) {
1405  ND::THandle<ND::TG4Trajectory> traj(new ND::TG4Trajectory((*trajectory)));
1406  return traj;
1407  }
1408  }
1409 
1410  return ND::THandle<ND::TG4Trajectory>();
1411 
1412 }
std::vector< int > Truth_TrajIds
The vector of primary true trajectory Ids which contribute to the ND::THits which are constituents of...
std::vector< int > Truth_HitCount
The vector of true trajectory Ids which contribute to the ND::THits which are constituents of this ve...
std::vector< int > Truth_TrajIds
True trajectory Ids See the TSFGVertex object for documentation.
virtual int FillNode(const ND::THandle< ND::TReconNode >, bool saveHits)
Fill the next node for any type of object.
virtual std::map< int, std::pair< int, float > > HitTruthInfo(const ND::THandle< ND::THitSelection >)
For each hit, go through and find the energy generated for each trajectory.
float EDeposit
The total reconstructed energy deposit of the corresponding track. This is usually just the sum of th...
float Charge
The reconstructed particle charge of the corresponding TReconPID.
std::vector< float > Truth_ChargeShare
Carge share o true trajectory.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
virtual ObjectId FillParticleObject(const ND::THandle< ND::TReconPID >, bool saveHits)
Fill the next TSFGParticle entry from a TReconPID.
std::vector< float > HitSegTrueEdepo
True energy loss of the current hit segment.
std::vector< float > Truth_ChargeShare
Carge share o true trajectory.
std::vector< int > Truth_HitCount
Nmber of hits contributed by each true trajectory.
bool checkHitSegInCube(ND::THandle< ND::THit > hit, ND::TG4HitSegment *HitSeg)
int FillHit(const ND::THandle< ND::THit >)
Fill the Hits container and return the index of the new hit.
int TrueParticlePur
Purity of Geant4 particle associated to a TSFGTrack.
int fNTracks
The TSFGTrack vector of results.
ClassImp(ND::TBeamSummaryDataModule::TBeamSummaryData)
TSFGClusterContainer * fClusters
The TSFGCluster vector of results.
int NDOF
The Number of Degrees of Freedom in the reconstruction of the corresponding object. Retrieved from ND::TReconBase::GetNDOF.
TVector3 Direction
Direction of the corresponding object.
int fNNodes
The TSFGNode vector of results.
std::vector< int > Truth_TrajIds
True trajectory Ids.
float Quality
ND::TReconBase::StateBits to check the which status flags are set.
std::string fDescription
A longish descrition of the analysis.
TSFGAlgoResContainer * fAlgoResults
The TSFGAlgoRes vector of results.
int TrueParticleID
True Geant4 particle associated to a TSFGTrack.
int fNShowers
The TSFGShower vector of results.
virtual ObjectId FillShowerObject(const ND::THandle< ND::TReconShower >, bool saveHits)
Fill the next TSFGShower entry from a TReconShower.
int TrueParticleID
True Geant4 particle associated to a TSFGTrack.
TVector3 Position
Hit position.
TVector3 Direction
Direction of the corresponding object.
Contains a summary of the reconstruction information in a TReconShower.
int Status
The reported status of the corresponding object. Use ND::TReconBase::StateBits to check the which sta...
TLorentzVector Position
Position of the corresponding object.
static const int arraySize
Size of the TSFGCluster::Moments array.
std::vector< int > Truth_TrajIds
True trajectory Ids.
TSFGHitContainer * fTrueHits
int TrueParticleID
True G4 particle associated to a TSFGParticle.
int TrueParticlePur
Purity of the True G4 particle associated to a TSFGParticle.
int fNAlgoResults
The TSFGAlgoRes vector of results.
void FillTrueTrajInfoForHit(ND::TG4HitSegment *, TSFGHit *)
int fNVertices
The TSFGVertex vector of results.
void FillBaseObject(T basePtr, ND::THandle< ND::TReconBase > baseObject, bool saveHits)
Fill the header for TSFGAlgoRes, TSFGVertex, TSFGParticle, TSFGTrack, TSFGVertex, and TSFGCluster...
TLorentzVector Position
Position of the corresponding object.
std::vector< float > Truth_ChargeShare
Carge share o true trajectory See the TSFGVertex object for documentation.
virtual ObjectId FillClusterObject(const ND::THandle< ND::TReconCluster >, bool saveHits)
Fill the next TSFGCluster entry from a TReconCluster.
ND::THandle< ND::TG4Trajectory > GetG4Trajectory(const T &object, double &pur, double &eff)
bool checkNearbyMultiTrk(ND::THandle< ND::THit > hit, std::vector< ND::TG4HitSegment * > HitSegAllPlanes, ND::THandle< ND::TG4TrajectoryContainer > true_traj)
std::vector< int > Truth_HitCount
Nmber of hits contributed by each true trajectory.
TVector3 Direction
Direction of the corresponding object.
void FillHitInfoNeededForNN(const ND::THandle< ND::THit >, TSFGHit *)
TLorentzVector PosVariance
Variance on the position of the corresponding object.
virtual std::vector< int > HitTruthPrimaryInfo(const ND::THandle< ND::THitSelection >)
For each hit, go through and find the primary particles that are depositing energy.
float Quality
The reported reconstruction &#39;quality&#39; of the corresponding object. Uses ND::TReconBase::GetQuality.
std::vector< int > Clusters
Holds index of the TSFGShower objects that are pertinent to this algorithm result.
virtual ObjectId FillTrackObject(const ND::THandle< ND::TReconTrack >, bool saveHits)
Fill the next TSFGTrack entry from a TReconTrack.
TLorentzVector Position
Position of the corresponding object.
float Time
Reconstructed hit time from the corresponding TSingleHit.
Int_t fBufferSize
Buffer Size for TBranch.
std::vector< TPRegexp > fRejectAlgoResultList
If an incoming TAlgorithmResult&#39;s name matches a pattern within this vector it will not be summarised...
virtual bool FillTree(ND::TND280Event &)
Called by the main loop to fill an event.
float EDeposit
The total reconstructed energy deposit of the corresponding track. This is usually just the sum of th...
int UsedHitCluster
The index of the cluster that contains all of the hits used by this algorithm result. This is -1 if the hits are not saved.
TLorentzVector Position
corresponding object.
std::vector< int > Truth_PrimaryTrajIds
Primary Ids of truth trajectories.
float Quality
The reported reconstruction &#39;quality&#39; of the vertex. Retrieved from ND::TReconBase::GetQuality.
float EDeposit
The total reconstructed energy deposit of the corresponding track. This is usually just the sum of th...
virtual ObjectId FillVertexObject(const ND::THandle< ND::TReconVertex >, bool saveHits)
Fill the next TSFGVertex entry from a TReconVertex.
TSFGReconModule(const char *name="SFG", const char *title="SFG Recon Module")
TLorentzVector Position
Position of the correspponding object.
TSFGHitContainer * fHits
The TSFGHit vector of hits.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
std::vector< TLorentzVector > HitSegPosition
True hit segments inside the cube position (3D + time)
std::string fCVSID
Defined if an official tagged version.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
std::vector< int > Truth_HitCount
Nmber of hits contributed by each true trajectory.
int fNTrueHits
The TSFGHit vector of hits based on the number of photons generated in each cube. ...
Contains a summary of the reconstruction information for each cube.
virtual ObjectId FillReconObject(const ND::THandle< ND::TReconBase >, bool saveHits)
This is a switch yard to take any sort of reconstruction object, and farm it out to the right specifi...
int Status
The reported Status of the corresponding object. Use ND::TReconBase::StateBits to check the which sta...
std::vector< int > Truth_TrajIds
True trajectory Ids.
std::vector< float > Truth_ChargeShare
Carge share o true trajectory.
int TrueParticleEff
Efficiency of Geant4 particle associated to a TSFGTrack.
TVector3 Direction
Direction of the corresponding object.
void SetNameTitle(char const *name, char const *title)
TVector3 DirVariance
Direction variance of the corresponding object.
std::vector< int > Truth_HitCount
Nmber of hits contributed by each true trajectory.
TVector3 DirVariance
Direction variance of the corresponding object.
float Cone
The opening angle of the TShowerState cone of the corresponding TReconShower.
A summary of the reconstruction information in a TReconPID.
std::string FullName
A unique Id used for reconstruction objects.
virtual void InitializeBranches()
Called to let the module setup the appropriate branches.
Contains a summary of the reconstruction information in a TReconTrack.
int fNClusters
The TSFGCluster vector of results.
std::vector< int > Hits
Holds internal Ids of Hits pertinent to this reconstruction node.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
int Parent
The index of the parent algorithm for this algorithm result. This will be -1 if this doesn&#39;t have a p...
TSFGPartContainer * fParticles
The TSFGParticle vector of results.
Contains a summary of the reconstruction information in a TReconNode.
std::vector< int > Clusters
The indices of the clusters contained by the current object.
virtual int FillAlgorithmResult(const ND::THandle< ND::TAlgorithmResult >, int)
Fill an algorithm result and all of it&#39;s subsidiary reconstruction objects.
float Width
The &#39;width&#39; of the shower, the extent perpendicular to the direction.
TSFGNodeContainer * fNodes
The TSFGNode vector of results.
std::vector< int > HitSegTruePDG
True particle PDG of the track contributing to the hit segment.
int id
An internal Id for each Reconstruction object.
int Status
The reported Status of the corresponding ND::TReconPID.
float EDeposit
Holds internal Ids of Hits pertinent to this reconstruction node.
int NDOF
object. Uses ND::TReconBase::GetQuality
Contains a summary of the reconstruction information in a TReconCluster.
std::vector< float > HitSegTrueP
True momentum of the track contributing to the hit segment.
std::vector< float > Truth_ChargeShare
The number of THits that each truth trajectory contributed to.
std::vector< int > Hits
Holds index of the TSFGNode objects that are pertinent to this algorithm result.
The representation of the information store in each SFG TReconVertex object.
std::vector< int > Vertices
Holds index of the TSFGVertex objects that are pertinent to this algorithm result.
ND::THandle< ND::TG4TrajectoryContainer > fTrueTraj
std::vector< int > Particles
Holds index of the TSFGVertex objects that are pertinent to this algorithm result.
std::vector< int > Truth_PrimaryTrajIds
The vector of primary true trajectory Ids which contribute to the ND::THits which are constituents of...
std::vector< float > PID_weight
PID weights for each PID in TSFGParticle::PID.
Int_t fSplitLevel
Split Level for TBranch.
int NDOF
The Number of Degrees of Freedom in the reconstruction of the corresponding object. Retrieved from ND::TReconBase::GetNDOF.
std::string AlgorithmName
The name of the algorithm that generated this object.
int Status
The reported Status of the corresponding object. Use ND::TReconBase::StateBits to check the which sta...
int NDOF
The Number of Degrees of Freedom in the vertex. Retrieved from ND::TReconBase::GetNDOF.
TVector3 DirVariance
Direction variance of the corresponding object.
UInt_t GeomId
Geometry Id of the TSingleHit.
float Quality
The reported reconstruction &#39;quality&#39; of the corresponding object. Uses ND::TReconBase::GetQuality.
TLorentzVector Position
Position of the corresponding object.
float Charge
Reconstructed hit charge without attenuation correction from thE corresponding TSingleHit.
int TrueParticleEff
Efficiency of Geant4 particle associated to a TSFGTrack.
std::vector< int > PID
Potential PIDs (ND::TReconPID::ParticleId) matching with TSFGParticle::PID_Weight values...
std::vector< TVector3 > HitSegDirection
True hit segments inside the cube direction (3D)
int fNHits
The TSFGHit vector of hits.
TVector3 DirVariance
Direction variance of the corresponding object.
An internal Id and object type for each Reconstruction object.
std::vector< int > Truth_PrimaryTrajIds
Primary Ids of truth trajectories See the TSFGVertex object for documentation.
int TrueParticleEff
Efficiency of the True G4 particle associated to a TSFGParticle.
std::string fCVSTagName
Defined if an official tagged version.
TLorentzVector PosVariance
Variance on the position of the corresponding object.
std::vector< int > Truth_PrimaryTrajIds
Primary Ids of truth trajectories.
std::vector< int > Showers
Holds index of the TSFGTrack objects that are pertinent to this algorithm result. ...
TSFGHitContainer * fFibers
The TSFGHit vector of hits for each fiber.
std::vector< int > Truth_TrajIds
True trajectory Ids.
TSFGTrackContainer * fTracks
The TSFGTrack vector of results.
std::vector< int > AlgoResults
The path to the result inside the event.
int UnusedHitCluster
The index of the cluster that contains all of the hits not used by this algorithm result...
float Moments[arraySize]
Moments of the cluster stored as a flat 3x3 matrix.
std::vector< float > Truth_ChargeShare
Carge share o true trajectory.
TSFGVertexContainer * fVertices
The TSFGVertex vector of results.
std::vector< int > Tracks
Holds index of the TSFGParticle objects that are pertinent to this algorithm result.
std::vector< int > Truth_PrimaryTrajIds
Primary Ids of truth trajectories.
float Length
The &#39;width&#39; of the shower, the extent perpendicular to the direction.
float Length
The length of the track calculated by summing over the distances between the constituent TReconNodes...
float Momentum
The reconstructed momentum of the corresponding TReconPID.
TClonesArray TSFGHitContainer
int TrkHitTag
Single/multiple track hit tagging Notation: 1 = multiple track hits, 2 = single track hits...
TSFGShowerContainer * fShowers
The TSFGShower vector of results.
int fNFibers
The TSFGHit vector of hits for each fiber.
The representation of the information store in each SFG TAlgorithmResult object.
int AddHit(const ND::THandle< ND::THit >, int &nDest, ND::TSFGReconModule::TSFGHitContainer *dest)
Add a hit to the destination container and return the index.
std::vector< int > Truth_HitCount
Nmber of hits contributed by each true trajectory See the TSFGVertex object for documentation.
std::vector< int > Truth_PrimaryTrajIds
The RMS length of the shower, the extent parallel to the direction.
double EDeposit_fit
Fitted energy deposit for each node.
int fNParticles
The TSFGParticle vector of results.
int TrueParticlePur
Purity of Geant4 particle associated to a TSFGTrack.

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