NeutronDecayN2Ana_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: NeutronDecayN2Ana
3 // Module Type: analyzer
4 // File: NeutronDecayN2Ana_module.cc
5 //
6 // Generated at Sun Mar 24 09:05:02 2013 by Tingjun Yang using artmod
7 // from art v1_02_06.
8 //
9 // Having a look at FD reconstruction quantities
10 //
11 // Thomas Karl Warburton
12 // k.warburton@sheffield.ac.uk
13 //
14 ////////////////////////////////////////////////////////////////////////
15 
16 // Framework includes
21 #include "fhiclcpp/ParameterSet.h"
22 #include "art_root_io/TFileService.h"
24 
25 // LArSoft includes
29 
32 
33 // ROOT includes
34 #include "TTree.h"
35 
36 //standard library includes
37 #include <map>
38 #include <iostream>
39 #include <iomanip>
40 #include <sstream>
41 #include <cmath>
42 #include <memory>
43 #include <limits> // std::numeric_limits<>
44 
45 struct IDEYLess {
46  bool operator()(const sim::IDE& first, const sim::IDE& second) {
47  return first.y < second.y;
48  }
49 };
50 
51 #define MaxPart 100
52 #define MaxParent 25
53 #define MaxPrim 10
54 #define HolderVal 9999
55 
56 namespace NeutronDecayN2Ana {
57  class NeutronDecayN2Ana;
58 }
59 
61 public:
62  explicit NeutronDecayN2Ana(fhicl::ParameterSet const & p);
63  virtual ~NeutronDecayN2Ana();
64 
65  void analyze(art::Event const & e) override;
66 
67  void beginRun(art::Run const& run) override;
68  void beginJob() override;
69  void endJob() override;
70  void endRun(art::Run const&) override;
71  //void reconfigure(fhicl::ParameterSet const & p) ;
72 
73 private:
74  // ------ My functions ------
75  void ResetVars();
76  void FillVars( std::vector<int> &TrackIDVec, int &numParts, float EDep[MaxPart], float DaughtEDep[MaxPart], float DecayEDep[MaxPart], float Start[MaxPart][4], float End[MaxPart][4],
77  int nParents[MaxPart], int Parent[MaxPart][MaxParent], int ParTrID[MaxPart][MaxParent], int PDG[MaxPart], int TrID[MaxPart], int Cont[MaxPart], int FromDecay[MaxPart],
78  int ThisID, unsigned int ThisTDC, sim::IDE ThisIDE, const simb::MCParticle& MCPart, bool Decay, bool OrigParticle, bool &Written );
79  bool UnAssignLoop( int nPart, float St[MaxPart][4], sim::IDE thisIDE, float NearE[MaxPart] );
80  float CalcDist( float X1, float Y1, float Z1, float X2, float Y2, float Z2 );
81  bool IsInTPC( float X1, float Y1, float Z1 , float Bound[6]);
82  // Handles
84 
85  // Parameter List
86  int Verbosity;
87  int NearEDeps;
88  float ActiveBounds[6]; // Cryostat boundaries ( neg x, pos x, neg y, pos y, neg z, pos z )
89 
90  std::map<int, const simb::MCParticle*> truthmap; // A map of the truth particles.
91  std::vector<int> AllTrackIDs; // A vector of all of my stored TrackIDs
92  bool BadEvent;
93  int NEvent;
94 
95  TTree* fDecayTree;
96  int Run;
97  int Event;
98  float DistEdge[3][2];
99  float TotalEDep;
103 
104  float TopX, TopY, TopZ, BotX, BotY, BotZ;
105 
106  // Primary particles
107  int nPrim, PrimPDG[MaxPrim];
108  float PrimEn[MaxPrim], PrimMom[MaxPrim];
109  // NumParts
110  int nMuon, nPion, nPi0, nKaon, nElec, nProt;
111  // PdgCode
112  int MuonPDG[MaxPart], PionPDG[MaxPart], Pi0PDG[MaxPart], KaonPDG[MaxPart], ElecPDG[MaxPart], ProtPDG[MaxPart];
113  // TrackID
114  int MuonTrID[MaxPart], PionTrID[MaxPart], Pi0TrID[MaxPart], KaonTrID[MaxPart], ElecTrID[MaxPart], ProtTrID[MaxPart];
115  // TrackID
116  int MuonCont[MaxPart], PionCont[MaxPart], Pi0Cont[MaxPart], KaonCont[MaxPart], ElecCont[MaxPart], ProtCont[MaxPart];
117  // From a decay?
118  int MuonFromDecay[MaxPart], PionFromDecay[MaxPart], Pi0FromDecay[MaxPart], KaonFromDecay[MaxPart], ElecFromDecay[MaxPart], ProtFromDecay[MaxPart];
119  // NumParents
120  int nParentMuon[MaxPart], nParentPion[MaxPart], nParentPi0[MaxPart], nParentKaon[MaxPart], nParentElec[MaxPart], nParentProt[MaxPart];
121  // Muon Parent PDGs
122  int MuonParents[MaxPart][MaxParent], PionParents[MaxPart][MaxParent], Pi0Parents[MaxPart][MaxParent], KaonParents[MaxPart][MaxParent], ElecParents[MaxPart][MaxParent], ProtParents[MaxPart][MaxParent];
123  // Muon Parent IDs
124  int MuonParTrID[MaxPart][MaxParent], PionParTrID[MaxPart][MaxParent], Pi0ParTrID[MaxPart][MaxParent], KaonParTrID[MaxPart][MaxParent], ElecParTrID[MaxPart][MaxParent], ProtParTrID[MaxPart][MaxParent];
125  // EDep
126  float MuonEDep[MaxPart], PionEDep[MaxPart], Pi0EDep[MaxPart], KaonEDep[MaxPart], ElecEDep[MaxPart], ProtEDep[MaxPart];
127  // Daughter EDep
128  float MuonDaughtersEDep[MaxPart], PionDaughtersEDep[MaxPart], Pi0DaughtersEDep[MaxPart], KaonDaughtersEDep[MaxPart], ElecDaughtersEDep[MaxPart], ProtDaughtersEDep[MaxPart];
129  // Decay EDep
130  float MuonDecayEDep[MaxPart], PionDecayEDep[MaxPart], Pi0DecayEDep[MaxPart], KaonDecayEDep[MaxPart], ElecDecayEDep[MaxPart], ProtDecayEDep[MaxPart];
131  // Near EDep
132  float MuonNearEDep[MaxPart] , PionNearEDep[MaxPart] , Pi0NearEDep[MaxPart] , KaonNearEDep[MaxPart] , ElecNearEDep[MaxPart], ProtNearEDep[MaxPart];
133  // Start
134  float MuonStart[MaxPart][4], PionStart[MaxPart][4], Pi0Start[MaxPart][4], KaonStart[MaxPart][4], ElecStart[MaxPart][4], ProtStart[MaxPart][4];
135  // End
136  float MuonEnd[MaxPart][4] , PionEnd[MaxPart][4] , Pi0End[MaxPart][4] , KaonEnd[MaxPart][4] , ElecEnd[MaxPart][4], ProtEnd[MaxPart][4];
137 };
138 // ******************************** Reset Variables *****************************************************
140  BadEvent = false;
141  Run = Event = 0;
142  TotalEDep = EDepNearEdge2 = EDepNearEdge5 = EDepNearEdge10 = 0;
143  // DistEdge
144  for (int i=0; i<3; i++)
145  for (int j=0; j<2; j++)
146  DistEdge[i][j]=HolderVal;
147  //Primary particles
148  nPrim = 0;
149  for (int pr=0; pr<MaxPrim; ++pr) {
150  PrimPDG[pr] = PrimEn[pr] = PrimMom[pr] = 0;
151  }
152  // Each particle type
153  nMuon = nPion = nPi0 = nKaon = nElec = nProt = 0;
154  for (int i=0; i<MaxPart; ++i) {
155  MuonPDG[i] = PionPDG[i] = Pi0PDG[i] = KaonPDG[i] = ElecPDG[i] = ProtPDG[i] = 0;
156  MuonTrID[i] = PionTrID[i] = Pi0TrID[i] = KaonTrID[i] = ElecTrID[i] = ProtTrID[i] = 0;
157  MuonCont[i] = PionCont[i] = Pi0Cont[i] = KaonCont[i] = ElecCont[i] = ProtCont[i] = -1;
158  MuonEDep[i] = PionEDep[i] = Pi0EDep[i] = KaonEDep[i] = ElecEDep[i] = ProtEDep[i] = 0;
159  nParentMuon[i] = nParentPion[i] = nParentPi0[i] = nParentKaon[i] = nParentElec[i] = nParentProt[i] = 0;
160  for (int j=0; j<MaxParent; ++j) {
161  MuonParents[i][j] = PionParents[i][j] = Pi0Parents[i][j] = KaonParents[i][j] = ElecParents[i][j] = ProtParents[i][j] = 0;
162  MuonParTrID[i][j] = PionParTrID[i][j] = Pi0ParTrID[i][j] = KaonParTrID[i][j] = ElecParTrID[i][j] = ProtParTrID[i][j] = 0;
163  }
164  MuonDaughtersEDep[i] = PionDaughtersEDep[i] = Pi0DaughtersEDep[i] = KaonDaughtersEDep[i] = ElecDaughtersEDep[i] = ProtDaughtersEDep[i] = 0;
165  MuonDecayEDep[i] = PionDecayEDep[i] = Pi0DecayEDep[i] = KaonDecayEDep[i] = ElecDecayEDep[i] = ProtDecayEDep[i] = 0;
166  MuonNearEDep[i] = PionNearEDep[i] = Pi0NearEDep[i] = KaonNearEDep[i] = ElecNearEDep[i] = ProtNearEDep[i] = 0;
167  for (int j=0; j<4; ++j) {
168  MuonStart[i][j] = PionStart[i][j] = Pi0Start[i][j] = KaonStart[i][j] = ElecStart[i][j] = ProtStart[i][j] = HolderVal;
169  MuonEnd[i][j] = PionEnd[i][j] = Pi0End[i][j] = KaonEnd[i][j] = ElecEnd[i][j] = ProtEnd[i][j] = HolderVal;
170  }
171  }
172 }
173 // ********************************** Begin Run *******************************************************
175 }
176 // *********************************** Begin Job ********************************************************
178 {
179  NEvent = 0;
180  // Build my Cryostat boundaries array...Taken from Tyler Alion in Geometry Core. Should still return the same values for uBoone.
181  ActiveBounds[0] = ActiveBounds[2] = ActiveBounds[4] = DBL_MAX;
182  ActiveBounds[1] = ActiveBounds[3] = ActiveBounds[5] = -DBL_MAX;
183 
184  TopX = TopY = TopZ = -DBL_MAX;
185  BotX = BotY = BotZ = DBL_MAX;
186 
187  // ----- FixMe: Assume single cryostats ------
188  auto const* geom = lar::providerFrom<geo::Geometry>();
189  for (geo::TPCGeo const& TPC: geom->IterateTPCs()) {
190  // get center in world coordinates
191  const double origin[3] = {0.};
192  double center[3] = {0.};
193  TPC.LocalToWorld(origin, center);
194  //double tpcDim[3] = {TPC.ActiveHalfWidth(), TPC.ActiveHalfHeight(), 0.5*TPC.ActiveLength() };
195  double tpcDim[3] = {TPC.HalfWidth(), TPC.HalfHeight(), 0.5*TPC.Length() }; // Gives same result as what Matt has
196  if( center[0] - tpcDim[0] < ActiveBounds[0] ) ActiveBounds[0] = center[0] - tpcDim[0];
197  if( center[0] + tpcDim[0] > ActiveBounds[1] ) ActiveBounds[1] = center[0] + tpcDim[0];
198  if( center[1] - tpcDim[1] < ActiveBounds[2] ) ActiveBounds[2] = center[1] - tpcDim[1];
199  if( center[1] + tpcDim[1] > ActiveBounds[3] ) ActiveBounds[3] = center[1] + tpcDim[1];
200  if( center[2] - tpcDim[2] < ActiveBounds[4] ) ActiveBounds[4] = center[2] - tpcDim[2];
201  if( center[2] + tpcDim[2] > ActiveBounds[5] ) ActiveBounds[5] = center[2] + tpcDim[2];
202  } // for all TPC
203 
204  // Going from what I see in the event displays...
205  ActiveBounds[0] = -723;
206  ActiveBounds[1] = 723;
207  ActiveBounds[2] = -600;
208  ActiveBounds[3] = 600;
209  ActiveBounds[4] = -1;
210  ActiveBounds[5] = 5809;
211  std::cout << "Active Boundaries: "
212  << "\n\tx: " << ActiveBounds[0] << " to " << ActiveBounds[1]
213  << "\n\ty: " << ActiveBounds[2] << " to " << ActiveBounds[3]
214  << "\n\tz: " << ActiveBounds[4] << " to " << ActiveBounds[5]
215  << std::endl;
216  /*
217  std::cout << "\n\n******Total World*******\n\n" << std::endl;
218  std::cout << "The total mass is " << geom->TotalMass() << std::endl;
219 
220  std::cout << "\n\n******vol TPC Active Inner*******\n\n" << std::endl;
221  std::cout << "The total mass is " << geom->TotalMass("volTPCActiveInner") << std::endl;
222 
223  std::cout << "\n\n******vol TPC Inner*******\n\n" << std::endl;
224  std::cout << "The total mass is " << geom->TotalMass("volTPCInner") << std::endl;
225 
226  std::cout << "\n\n******vol TPC Active Outer*******\n\n" << std::endl;
227  std::cout << "The total mass is " << geom->TotalMass("volTPCActiveOuter") << std::endl;
228 
229  std::cout << "\n\n******vol TPC Outer*******\n\n" << std::endl;
230  std::cout << "The total mass is " << geom->TotalMass("volTPCOuter") << std::endl;
231 
232  std::cout << "\n\n******vol Cryostat*******\n\n" << std::endl;
233  std::cout << "The total mass is " << geom->TotalMass("volCryostat") << std::endl;
234 
235  std::cout << "\n\n*************\n\n" << std::endl;
236  */
237  /*
238  double minx_, maxx_, miny_, maxy_, minz_, maxz_;
239  minx_ = miny_ = minz_ = DBL_MAX;
240  maxx_ = maxy_ = maxz_ = -DBL_MAX;
241  for (unsigned int c=0; c<geom->Ncryostats(); c++) {
242  const geo::CryostatGeo& cryostat=geom->Cryostat(c);
243  for (unsigned int t=0; t<cryostat.NTPC(); t++) {
244  geo::TPCID id;
245  id.Cryostat=c;
246  id.TPC=t;
247  id.isValid=true;
248  const geo::TPCGeo& tpc=cryostat.TPC(id);
249  //std::cout << t << "\t" << (tpc.Length()/2) << ", " << (tpc.ActiveLength()/2) << std::endl;
250  if (tpc.MinX()<minx_) minx_=tpc.MinX();
251  if (tpc.MaxX()>maxx_) maxx_=tpc.MaxX();
252  if (tpc.MinY()<miny_) miny_=tpc.MinY();
253  if (tpc.MaxY()>maxy_) maxy_=tpc.MaxY();
254  if (tpc.MinZ()<minz_) minz_=tpc.MinZ();
255  if (tpc.MaxZ()>maxz_) maxz_=tpc.MaxZ();
256  }
257  }
258  std::cout << "Using Matt's method " << minx_ << ", " << maxx_ << "\t" << miny_ << ", " << maxy_ << "\t" << minz_ << ", " << maxz_ << std::endl;
259  */
260 
261  // Implementation of optional member function here.
263  fDecayTree = tfs->make<TTree>("ReconstructedTree","analysis tree");
264 
265  fDecayTree->Branch("Run" , &Run , "Run/I" );
266  fDecayTree->Branch("Event" , &Event , "Event/I" );
267  fDecayTree->Branch("DistEdge" , &DistEdge , "DistEdge[3][2]/F" );
268  fDecayTree->Branch("TotalEDep" , &TotalEDep , "TotalEDep/F" );
269  fDecayTree->Branch("EDepNearEdge2" , &EDepNearEdge2 , "EDepNearEdge2/F" );
270  fDecayTree->Branch("EDepNearEdge5" , &EDepNearEdge5 , "EDepNearEdge5/F" );
271  fDecayTree->Branch("EDepNearEdge10", &EDepNearEdge10, "EDepNearEdge10/F" );
272 
273  // Primary particles
274  fDecayTree->Branch("nPrim" , &nPrim , "nPrim/I" );
275  fDecayTree->Branch("PrimPDG" , &PrimPDG , "PrimPDG[nPrim]/I" );
276  fDecayTree->Branch("PrimEn" , &PrimEn , "PrimEn[nPrim]/F" );
277  fDecayTree->Branch("PrimMom" , &PrimMom , "PrimMom[nPrim]/F" );
278  // Muon
279  fDecayTree->Branch("nMuon" ,&nMuon ,"nMuon/I" );
280  fDecayTree->Branch("nParentMuon" ,&nParentMuon ,"nParentMuon[nMuon]/I" );
281  fDecayTree->Branch("MuonParents" ,&MuonParents ,"MuonParents[nMuon][25]/I" );
282  fDecayTree->Branch("MuonParTrID" ,&MuonParTrID ,"MuonParTrID[nMuon][25]/I" );
283  fDecayTree->Branch("MuonPDG" ,&MuonPDG ,"MuonPDG[nMuon]/I" );
284  fDecayTree->Branch("MuonTrID" ,&MuonTrID ,"MuonTrID[nMuon]/I" );
285  fDecayTree->Branch("MuonCont" ,&MuonCont ,"MuonCont[nMuon]/I" );
286  fDecayTree->Branch("MuonFromDecay" ,&MuonFromDecay ,"MuonFromDecay[nMuon]/I" );
287  fDecayTree->Branch("MuonEDep" ,&MuonEDep ,"MuonEDep[nMuon]/F" );
288  fDecayTree->Branch("MuonStart" ,&MuonStart ,"MuonStart[nMuon][4]/F" );
289  fDecayTree->Branch("MuonEnd" ,&MuonEnd ,"MuonEnd[nMuon][4]/F" );
290  fDecayTree->Branch("MuonDaughtersEDep",&MuonDaughtersEDep,"MuonDaughtersEDep[nMuon]/F");
291  fDecayTree->Branch("MuonDecayEDep" ,&MuonDecayEDep ,"MuonDecayEDep[nMuon]/F" );
292  fDecayTree->Branch("MuonNearEDep" ,&MuonNearEDep ,"MuonNearEDep[nMuon]/F" );
293  // Pion
294  fDecayTree->Branch("nPion" ,&nPion ,"nPion/I" );
295  fDecayTree->Branch("nParentPion" ,&nParentPion ,"nParentPion[nPion]/I" );
296  fDecayTree->Branch("PionParents" ,&PionParents ,"PionParents[nPion][25]/I" );
297  fDecayTree->Branch("PionParTrID" ,&PionParTrID ,"PionParTrID[nPion][25]/I" );
298  fDecayTree->Branch("PionPDG" ,&PionPDG ,"PionPDG[nPion]/I" );
299  fDecayTree->Branch("PionTrID" ,&PionTrID ,"PionTrID[nPion]/I" );
300  fDecayTree->Branch("PionCont" ,&PionCont ,"PionCont[nPion]/I" );
301  fDecayTree->Branch("PionFromDecay" ,&PionFromDecay ,"PionFromDecay[nPion]/I" );
302  fDecayTree->Branch("PionEDep" ,&PionEDep ,"PionEDep[nPion]/F" );
303  fDecayTree->Branch("PionStart" ,&PionStart ,"PionStart[nPion][4]/F" );
304  fDecayTree->Branch("PionEnd" ,&PionEnd ,"PionEnd[nPion][4]/F" );
305  fDecayTree->Branch("PionDaughtersEDep",&PionDaughtersEDep,"PionDaughtersEDep[nPion]/F");
306  fDecayTree->Branch("PionDecayEDep" ,&PionDecayEDep ,"PionDecayEDep[nPion]/F" );
307  fDecayTree->Branch("PionNearEDep" ,&PionNearEDep ,"PionNearEDep[nPion]/F" );
308  // Pi0
309  fDecayTree->Branch("nPi0" ,&nPi0 ,"nPi0/I" );
310  fDecayTree->Branch("nParentPi0" ,&nParentPi0 ,"nParentPi0[nPi0]/I" );
311  fDecayTree->Branch("Pi0Parents" ,&Pi0Parents ,"Pi0Parents[nPi0][25]/I" );
312  fDecayTree->Branch("Pi0ParTrID" ,&Pi0ParTrID ,"Pi0ParTrID[nPi0][25]/I" );
313  fDecayTree->Branch("Pi0PDG" ,&Pi0PDG ,"Pi0PDG[nPi0]/I" );
314  fDecayTree->Branch("Pi0TrID" ,&Pi0TrID ,"Pi0TrID[nPi0]/I" );
315  fDecayTree->Branch("Pi0Cont" ,&Pi0Cont ,"Pi0Cont[nPi0]/I" );
316  fDecayTree->Branch("Pi0FromDecay" ,&Pi0FromDecay ,"Pi0FromDecay[nPi0]/I" );
317  fDecayTree->Branch("Pi0EDep" ,&Pi0EDep ,"Pi0EDep[nPi0]/F" );
318  fDecayTree->Branch("Pi0Start" ,&Pi0Start ,"Pi0Start[nPi0][4]/F" );
319  fDecayTree->Branch("Pi0End" ,&Pi0End ,"Pi0End[nPi0][4]/F" );
320  fDecayTree->Branch("Pi0DaughtersEDep",&Pi0DaughtersEDep,"Pi0DaughtersEDep[nPi0]/F");
321  fDecayTree->Branch("Pi0DecayEDep" ,&Pi0DecayEDep ,"Pi0DecayEDep[nPi0]/F" );
322  fDecayTree->Branch("Pi0NearEDep" ,&Pi0NearEDep ,"Pi0NearEDep[nPi0]/F" );
323  // Kaon
324  fDecayTree->Branch("nKaon" ,&nKaon ,"nKaon/I" );
325  fDecayTree->Branch("nParentKaon" ,&nParentKaon ,"nParentKaon[nKaon]/I" );
326  fDecayTree->Branch("KaonParents" ,&KaonParents ,"KaonParents[nKaon][25]/I" );
327  fDecayTree->Branch("KaonParTrID" ,&KaonParTrID ,"KaonParTrID[nKaon][25]/I" );
328  fDecayTree->Branch("KaonPDG" ,&KaonPDG ,"KaonPDG[nKaon]/I" );
329  fDecayTree->Branch("KaonTrID" ,&KaonTrID ,"KaonTrID[nKaon]/I" );
330  fDecayTree->Branch("KaonCont" ,&KaonCont ,"KaonCont[nKaon]/I" );
331  fDecayTree->Branch("KaonFromDecay" ,&KaonFromDecay ,"KaonFromDecay[nKaon]/I" );
332  fDecayTree->Branch("KaonEDep" ,&KaonEDep ,"KaonEDep[nKaon]/F" );
333  fDecayTree->Branch("KaonStart" ,&KaonStart ,"KaonStart[nKaon][4]/F" );
334  fDecayTree->Branch("KaonEnd" ,&KaonEnd ,"KaonEnd[nKaon][4]/F" );
335  fDecayTree->Branch("KaonDaughtersEDep",&KaonDaughtersEDep,"KaonDaughtersEDep[nKaon]/F");
336  fDecayTree->Branch("KaonDecayEDep" ,&KaonDecayEDep ,"KaonDecayEDep[nKaon]/F" );
337  fDecayTree->Branch("KaonNearEDep" ,&KaonNearEDep ,"KaonNearEDep[nKaon]/F" );
338  // Electron
339  fDecayTree->Branch("nElec" ,&nElec ,"nElec/I" );
340  fDecayTree->Branch("nParentElec" ,&nParentElec ,"nParentElec[nElec]/I" );
341  fDecayTree->Branch("ElecParents" ,&ElecParents ,"ElecParents[nElec][25]/I" );
342  fDecayTree->Branch("ElecParTrID" ,&ElecParTrID ,"ElecParTrID[nElec][25]/I" );
343  fDecayTree->Branch("ElecFromDecay" ,&ElecFromDecay ,"ElecFromDecay[nElec]/I" );
344  fDecayTree->Branch("ElecPDG" ,&ElecPDG ,"ElecPDG[nElec]/I" );
345  fDecayTree->Branch("ElecTrID" ,&ElecTrID ,"ElecTrID[nElec]/I" );
346  fDecayTree->Branch("ElecCont" ,&ElecCont ,"ElecCont[nElec]/I" );
347  fDecayTree->Branch("ElecEDep" ,&ElecEDep ,"ElecEDep[nElec]/F" );
348  fDecayTree->Branch("ElecStart" ,&ElecStart ,"ElecStart[nElec][4]/F" );
349  fDecayTree->Branch("ElecEnd" ,&ElecEnd ,"ElecEnd[nElec][4]/F" );
350  fDecayTree->Branch("ElecDaughtersEDep",&ElecDaughtersEDep,"ElecDaughtersEDep[nElec]/F");
351  fDecayTree->Branch("ElecDecayEDep" ,&ElecDecayEDep ,"ElecDecayEDep[nElec]/F" );
352  fDecayTree->Branch("ElecNearEDep" ,&ElecNearEDep ,"ElecNearEDep[nElec]/F" );
353  // Proton
354  fDecayTree->Branch("nProt" ,&nProt ,"nProt/I" );
355  fDecayTree->Branch("nParentProt" ,&nParentProt ,"nParentProt[nProt]/I" );
356  fDecayTree->Branch("ProtParents" ,&ProtParents ,"ProtParents[nProt][25]/I" );
357  fDecayTree->Branch("ProtParTrID" ,&ProtParTrID ,"ProtParTrID[nProt][25]/I" );
358  fDecayTree->Branch("ProtFromDecay" ,&ProtFromDecay ,"ProtFromDecay[nProt]/I" );
359  fDecayTree->Branch("ProtPDG" ,&ProtPDG ,"ProtPDG[nProt]/I" );
360  fDecayTree->Branch("ProtTrID" ,&ProtTrID ,"ProtTrID[nProt]/I" );
361  fDecayTree->Branch("ProtCont" ,&ProtCont ,"ProtCont[nProt]/I" );
362  fDecayTree->Branch("ProtEDep" ,&ProtEDep ,"ProtEDep[nProt]/F" );
363  fDecayTree->Branch("ProtStart" ,&ProtStart ,"ProtStart[nProt][4]/F" );
364  fDecayTree->Branch("ProtEnd" ,&ProtEnd ,"ProtEnd[nProt][4]/F" );
365  fDecayTree->Branch("ProtDaughtersEDep",&ProtDaughtersEDep,"ProtDaughtersEDep[nProt]/F");
366  fDecayTree->Branch("ProtDecayEDep" ,&ProtDecayEDep ,"ProtDecayEDep[nProt]/F" );
367  fDecayTree->Branch("ProtNearEDep" ,&ProtNearEDep ,"ProtNearEDep[nProt]/F" );
368 }
369 // ************************************ End Job *********************************************************
371  std::cout << "\nAfter all of that Top = " << TopX << ", " << TopY << ", " << TopZ << ". Bot = " << BotX << ", " << BotY << ", " << BotZ << std::endl;
372 }
373 // ************************************ End Run *********************************************************
375 }
376 
377 // ********************************** pset param *******************************************************
379  : EDAnalyzer(pset)
380  , Verbosity( pset.get< int >( "Verbosity" ))
381  , NearEDeps( pset.get< int >( "NearEDeps" ))
382 {
383 
384 }
385 // ******************************************************************************************************
387 {
388  // Clean up dynamic memory and other resources here.
389 
390 }
391 // ************************************ Analyse *********************************************************
393  ++NEvent;
394  ResetVars();
395  Run = evt.run();
396  Event = evt.event();
397 
398  //if ( Event != 39 ) return;
399 
400  if (Verbosity)
401  std::cout << "\n\n************* New Event / Module running - Run " << Run << ", Event " << Event << ", NEvent " << NEvent << " *************\n\n" << std::endl;
402 
403  // Any providers I need.
404  auto const* geo = lar::providerFrom<geo::Geometry>();
405  /*
406  // Implementation of required member function here.
407  std::vector<art::Ptr<recob::Track> > tracklist;
408  auto trackListHandle = evt.getHandle< std::vector<recob::Track> >(fTrackModuleLabel);
409  if (trackListHandle)
410  art::fill_ptr_vector(tracklist, trackListHandle);
411  */
412  // Make a map of MCParticles which I can access later.
413  auto truth = evt.getHandle<std::vector<simb::MCParticle> >("largeant");
414  truthmap.clear();
415  for (size_t i=0; i<truth->size(); i++) {
416  truthmap[truth->at(i).TrackId()]=&((*truth)[i]);
417  if (truth->at(i).Mother() == 0) {
418  PrimPDG[nPrim] = truth->at(i).PdgCode();
419  PrimEn [nPrim] = truth->at(i).E(0);
420  PrimMom[nPrim] = truth->at(i).P(0);
421  ++nPrim;
422  if (Verbosity) {
423  std::cout << "The primary particle in this event was a " << PrimPDG[nPrim-1]<<" with Energy " << PrimEn[nPrim-1]
424  << ", momentum " << PrimMom[nPrim-1]<< ", process " << truth->at(i).Process() << std::endl;
425  }
426  }
427  }
428  if (Verbosity)
429  std::cout << "There were " << nPrim << " primary particles." << std::endl;
430 
431  // Get a vector of sim channels.
432  auto simchannels = evt.getHandle<std::vector<sim::SimChannel> >("largeant");
433 
434  // Make vectors to hold all of my particle TrackIDs
435  std::vector<int> MuonVec, PionVec, Pi0Vec, KaonVec, ElecVec, ProtVec;
436  AllTrackIDs.clear();
437 
438  // Want to loop through the simchannels, and the ides.
439  int chanIt = 0;
440 
441  std::vector< sim::IDE > UnAssignVec;
442  UnAssignVec.clear();
443 
444  for (auto const& simchannel:*simchannels) {
445  // ------ Only want to look at collection plane hits ------
446  //std::cout << "Looking at a new SimChannel, it was on channel " << simchannel.Channel() << ", which is plane " << geo->SignalType(simchannel.Channel()) << std::endl;
447  if (geo->SignalType(simchannel.Channel()) != geo::kCollection) continue;
448  int tdcideIt = 0;
449  // ------ Loop through all the IDEs for this channel ------
450  for (auto const& tdcide:simchannel.TDCIDEMap()) {
451  unsigned int tdc = tdcide.first;
452  auto const& idevec=tdcide.second;
453  if (Verbosity>1)
454  std::cout << "TDC IDE " << tdcideIt << " of " << simchannel.TDCIDEMap().size() << ", has tdc " << tdc << ", and idevec of size " << idevec.size() << std::endl;
455  int ideIt = 0;
456  // ------ Look at each individual IDE ------
457  for (auto const& ide:idevec) {
458  int ideTrackID = ide.trackID;
459  float ideEnergy = ide.energy;
460  double idePos[3];
461  idePos[0] = ide.x;
462  idePos[1] = ide.y;
463  idePos[2] = ide.z;
464  /*
465  if (ideTrackID == 1 && Verbosity == 2) {
466  float ideNumEl = ide.numElectrons;
467  std::cout << " IDE " << ideIt << " of " << idevec.size() << " has TrackId " << ideTrackID << ", energy " << ideEnergy << ", NumEl " << ideNumEl << ", tdc " << tdc << ". ";
468  std::cout << "Position " << idePos[0] << ", " << idePos[1] << ", " << idePos[2] << std::endl;
469  }
470  //*/
471 
472  // ***** Find out what particle the ide is due to...
473  const simb::MCParticle& Origpart=*( truthmap[ abs(ideTrackID) ] );
474  int OrigPdgCode = Origpart.PdgCode();
475 
476  geo::TPCID tpcid=geo->FindTPCAtPosition(idePos);
477  if (!(geo->HasTPC(tpcid)) ) {
478  if (Verbosity)
479  std::cout << "Outside the Active volume I found at the top!" << std::endl;
480  continue;
481  }
482 
483  // ------ I want to work the closest IDE to an edge of the active volume ------
484  // If I am writing out the distance to the edge of the active volume
485  if ( DistEdge[0][0] > ( ide.x - ActiveBounds[0]) ) DistEdge[0][0] = ide.x - ActiveBounds[0];
486  if ( DistEdge[0][1] > (-ide.x + ActiveBounds[1]) ) DistEdge[0][1] = -ide.x + ActiveBounds[1];
487  if ( DistEdge[1][0] > ( ide.y - ActiveBounds[2]) ) DistEdge[1][0] = ide.y - ActiveBounds[2];
488  if ( DistEdge[1][1] > (-ide.y + ActiveBounds[3]) ) DistEdge[1][1] = -ide.y + ActiveBounds[3];
489  if ( DistEdge[2][0] > ( ide.z - ActiveBounds[4]) ) DistEdge[2][0] = ide.z - ActiveBounds[4];
490  if ( DistEdge[2][1] > (-ide.z + ActiveBounds[5]) ) DistEdge[2][1] = -ide.z + ActiveBounds[5];
491 
492  // Work out the EDeps within a distance to the detector edge.
493  float XEDep = std::min( ide.x - ActiveBounds[0], -ide.x + ActiveBounds[1] );
494  float YEDep = std::min( ide.y - ActiveBounds[2], -ide.y + ActiveBounds[3] );
495  float ZEDep = std::min( ide.z - ActiveBounds[4], -ide.z + ActiveBounds[5] );
496  float MEDep = std::min( XEDep, std::min( YEDep, ZEDep ) );
497  // If the deposition was outside my active volume continue...
498  if ( MEDep < 0 ) {
499  //std::cout << "Deposition outside active vol ("<<ide.x<<", " << ide.y<< ", "<< ide.z<<")." << std::endl;
500  continue;
501  }
502  if ( MEDep < 2 ) {
503  //std::cout << "Edep at " << ide.x << ", " << ide.y << " " << ide.z << "..." << MEDep << ", from a " << OrigPdgCode
504  // << ", Energy = " << ide.energy << " ==>> " << EDepNearEdge2+ide.energy << std::endl;
505  EDepNearEdge2 += ide.energy;
506  }
507  if ( MEDep < 5 ) {
508  EDepNearEdge5 += ide.energy;
509  }
510  if ( MEDep < 10 ) {
511  EDepNearEdge10 += ide.energy;
512  }
513 
514  if (ide.x > TopX) {
515  TopX = ide.x;
516  //std::cout << "Changed TopX to " << TopX << std::endl;
517  }
518  if (ide.y > TopY) {
519  TopY = ide.y;
520  //std::cout << "Changed TopY to " << TopY << std::endl;
521  }
522  if (ide.z > TopZ) {
523  TopZ = ide.z;
524  //std::cout << "Changed TopZ to " << TopZ << std::endl;
525  }
526  if (ide.x < BotX) BotX = ide.x;
527  if (ide.y < BotY) BotY = ide.y;
528  if (ide.z < BotZ) BotZ = ide.z;
529 
530  // ------ Add the energy deposition from this IDE to the sum of IDEs
531  TotalEDep += ideEnergy;
532 
533  //std::cout << "IDE is at (" << ide.x << ", " << ide.y << ", " << ide.z << "). MinX is " << XEDep << ", MinY is " << YEDep << ", MinZ is " << ZEDep << "===> MinDist is " << MEDep
534  // << "...is this less than DistToEdge? " << IsClose << " ====> EDepNearEdge is now " << EDepNearEdge
535  // << std::endl;
536 
537  // If I am writing out the most +- depositions in X, Y, Z
538  /*
539  if ( DistEdge[0][0] > ide.x ) DistEdge[0][0] = ide.x;
540  if ( DistEdge[0][1] < ide.x ) DistEdge[0][1] = ide.x;
541  if ( DistEdge[1][0] > ide.y ) DistEdge[1][0] = ide.y;
542  if ( DistEdge[1][1] < ide.y ) DistEdge[1][1] = ide.y;
543  if ( DistEdge[2][0] > ide.z ) DistEdge[2][0] = ide.z;
544  if ( DistEdge[2][1] < ide.z ) DistEdge[2][1] = ide.z;
545  */
546  // ------ Now to work out which particles in particular I want to save more information about... ------
547  // ----------------- I want to write out the IDE to the relevant parent particle type -----------------
548  // ------- This means looping back through the IDE's parents until I find an interesting TrackID ------
549  bool isDecay = false;
550  bool WrittenOut = false;
551  bool OrigPart = true;
552  if (Verbosity>1)
553  std::cout << "\nLooking at IDE " << ideIt << ", ideTrackID is " << ideTrackID << ", it was due to a "
554  << truthmap[ abs(ideTrackID) ]->PdgCode() << ", process " << truthmap[ abs(ideTrackID) ]->Process()
555  << std::endl;
556  while ( ideTrackID != 0 && !WrittenOut ) {
557  const simb::MCParticle& part=*( truthmap[ abs(ideTrackID) ] );
558  int PdgCode=part.PdgCode();
559  if ( PdgCode != OrigPdgCode || ideTrackID < 0 )
560  OrigPart = false;
561  // ========== Muons ==========
562  if ( (PdgCode == -13 || PdgCode == 13) )
563  FillVars( MuonVec, nMuon, MuonEDep, MuonDaughtersEDep, MuonDecayEDep, MuonStart, MuonEnd, nParentMuon, MuonParents, MuonParTrID, MuonPDG, MuonTrID, MuonCont, MuonFromDecay,
564  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut );
565  // ========== Pions ==========
566  else if ( (PdgCode == -211 || PdgCode == 211) && part.Process() != "pi+Inelastic" && part.Process() != "pi-Inelastic" )
567  FillVars( PionVec, nPion, PionEDep, PionDaughtersEDep, PionDecayEDep, PionStart, PionEnd, nParentPion, PionParents, PionParTrID, PionPDG, PionTrID, PionCont, PionFromDecay,
568  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut);
569  // ========== Pi0s ==========
570  else if ( PdgCode == 111 )
571  FillVars( Pi0Vec , nPi0 , Pi0EDep , Pi0DaughtersEDep , Pi0DecayEDep , Pi0Start , Pi0End , nParentPi0 , Pi0Parents , Pi0ParTrID , Pi0PDG , Pi0TrID , Pi0Cont , Pi0FromDecay ,
572  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut );
573  // ========== Kaons ===========
574  else if ( (PdgCode == 321 || PdgCode == -321) && part.Process() != "kaon+Inelastic" && part.Process() != "kaon-Inelastic" )
575  FillVars( KaonVec, nKaon, KaonEDep, KaonDaughtersEDep, KaonDecayEDep, KaonStart, KaonEnd, nParentKaon, KaonParents, KaonParTrID, KaonPDG, KaonTrID, KaonCont, KaonFromDecay,
576  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut );
577  // ========== Elecs ===========
578  else if ( (PdgCode == -11 || PdgCode == 11) ) {
579  // Electrons can shower straight away, so I want to treat all deposits as if it was from the electron.
580  OrigPart = true;
581  FillVars( ElecVec, nElec, ElecEDep, ElecDaughtersEDep, ElecDecayEDep, ElecStart, ElecEnd, nParentElec, ElecParents, ElecParTrID, ElecPDG, ElecTrID, ElecCont, ElecFromDecay,
582  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut );
583  // ========== Prots ===========
584  } else if ( PdgCode == 2212 )
585  FillVars( ProtVec, nProt, ProtEDep, ProtDaughtersEDep, ProtDecayEDep, ProtStart, ProtEnd, nParentProt, ProtParents, ProtParTrID, ProtPDG, ProtTrID, ProtCont, ProtFromDecay,
586  ideTrackID, tdc, ide, part, OrigPart, isDecay, WrittenOut );
587  // ========== If still not one of my intersting particles I need to find this particles parent ==========
588  else {
589  ideTrackID = part.Mother();
590  if (ideTrackID==0) {
591  if (Verbosity > 1) {
592  int ThrowIDE = ide.trackID;
593  std::cout << "None of the particles in this chain are interesting, so skipping. It was due to TrackID " << ThrowIDE << ", PdGCode " << truthmap[ abs(ThrowIDE) ]->PdgCode()
594  << ", energy " << ide.energy << ", and pos ("<<ide.x<<", "<<ide.y<<", "<<ide.z<<").\n"
595  << " The ide parentage was PdG (TrackID) " << truthmap[ abs(ThrowIDE) ]->PdgCode() << " (" << ThrowIDE << ") ";
596  while ( ThrowIDE != 0 ) {
597  ThrowIDE = truthmap[ abs(ThrowIDE) ]->Mother();
598  if ( ThrowIDE == 0)
599  std::cout << ". end." << std::endl;
600  else
601  std::cout << " <-- " << truthmap[ abs(ThrowIDE) ]->PdgCode() << " (" << ThrowIDE << ") ";
602  }
603  }
604  UnAssignVec.push_back( ide );
605  break;
606  }
607  PdgCode = truthmap[ abs(ideTrackID) ]->PdgCode();
608  // === Work out if a decay I care about ===
609  if ( part.PdgCode() != PdgCode ) isDecay = false; // Only reset to false if not a daughter of the same particle type eg not K+ -> K+
610  if ( ideTrackID > 0 && part.Process() == "Decay" &&
611  ( PdgCode == -13 || PdgCode == 13 || PdgCode == -211 || PdgCode == 211 || // muon or pion
612  PdgCode == 321 || PdgCode == -321 || PdgCode == -11 || PdgCode == 11 || // kaon or elec
613  PdgCode == 111 || // pi0
614  PdgCode == 2212 // proton
615  )
616  )
617  { // If decay I care about.
618  //std::cout << "This particle was from a decay!" << std::endl;
619  isDecay = true;
620  }
621  if (Verbosity > 1) {
622  std::cout << "Not something interesting so moving backwards. The parent of that particle had trackID " << ideTrackID
623  << ", was from a " << PdgCode << ", from a decay? " << isDecay << std::endl;
624  }
625  } // If not one of chosen particles.
626  } // While loop
627  if (BadEvent) {
628  if (Verbosity) {
629  std::cout << "Had too many of one particle type, voiding this event now...nKaon " << nKaon << ", nElec " << nElec << ", nMuon " << nMuon
630  << ", nPion " << nPion << ", nPi0 " << nPi0 << ", nProt " << nProt << "....Up to now there was " << TotalEDep << " energy deposited." << std::endl;
631  }
632  return;
633  }
634  ideIt++;
635  } // Each IDE ( ide:idevec )
636  ++tdcideIt;
637  } // IDE vector for SimChannel ( tdcide:simcahnnel.TPCIDEMap() )
638  ++chanIt;
639  } // Loop through simchannels
640 
641  // ------------------------------------- Now loop through all of my unassigned IDEs -------------------------------------
642  std::cout << "\nLooked through all of my IDEs, my UnAssignVec has size " << UnAssignVec.size() << std::endl;
643  int StillUnassign = 0;
644  for (auto const& ide:UnAssignVec) {
645  if (Verbosity > 1) {
646  std::cout << "Going through my uninteresting particles...this IDE was due to TrackID " << ide.trackID << ", energy " << ide.energy
647  << ", and pos ("<<ide.x<<", "<<ide.y<<", "<<ide.z<<"). " << std::endl;
648  int ideTrId = ide.trackID;
649  std::cout << " The ide parentage was PdG (TrackID) " << truthmap[ abs(ideTrId) ]->PdgCode() << " (" << ideTrId << ") ";
650  while ( ideTrId != 0 ) {
651  ideTrId = truthmap[ abs(ideTrId) ]->Mother();
652  if ( ideTrId == 0)
653  std::cout << ". end." << std::endl;
654  else
655  std::cout << " <-- " << truthmap[ abs(ideTrId) ]->PdgCode() << " (" << ideTrId << ") ";
656  }
657  }
658  bool FoundDep = false;
659  // ==== Loop through kaons
660  FoundDep = UnAssignLoop( nKaon, KaonStart, ide, KaonNearEDep );
661  if (FoundDep) continue;
662  // ==== Loop through elecs
663  FoundDep = UnAssignLoop( nElec, ElecStart, ide, ElecNearEDep );
664  if (FoundDep) continue;
665  // ==== Loop through muons
666  FoundDep = UnAssignLoop( nMuon, MuonStart, ide, MuonNearEDep );
667  if (FoundDep) continue;
668  // ==== Loop through pions
669  FoundDep = UnAssignLoop( nPion, PionStart, ide, PionNearEDep );
670  if (FoundDep) continue;
671  // ==== Loop through pi0s
672  FoundDep = UnAssignLoop( nPi0, Pi0Start, ide, Pi0NearEDep );
673  if (FoundDep) continue;
674  // ==== Loop through protons
675  FoundDep = UnAssignLoop( nProt, ProtStart, ide, ProtNearEDep );
676  if (FoundDep) continue;
677  // ==== If still not assigned this IDE
678  if (Verbosity > 1) std::cout << "!!!This IDE was nowhere near anything...." << std::endl;
679  ++StillUnassign;
680  }
681  std::cout << "There were still " << StillUnassign << " unassigned IDEs." << std::endl;
682  // ------------------------------------- Now loop through all of my unassigned IDEs -------------------------------------
683 
684  // ------------------------------------- Output some information about my particles -------------------------------------
685  if (Verbosity) {
686  if (nKaon) {
687  std::cout << "\nThere are kaons in this event!!" << std::endl;
688  for (int KL=0; KL<nKaon; ++KL) {
689  std::cout << "Kaon " << KL << " had properties: PDG " << KaonPDG[KL] << ", TrackID " << KaonTrID[KL] << ", EDep " << KaonEDep[KL]
690  << ", DaughtEDep " << KaonDaughtersEDep[KL] << ", DecayEDep " << KaonDecayEDep[KL] << ", NearEDep " << KaonNearEDep[KL] << std::endl;
691  }
692  }
693  if (nElec) {
694  std::cout << "There are electrons in this event!!" << std::endl;
695  for (int EL=0; EL<nElec; ++EL) {
696  std::cout << "Elec " << EL << " had properties: PDG " << ElecPDG[EL] << ", TrackID " << ElecTrID[EL] << ", EDep " << ElecEDep[EL]
697  << ", DaughtEDep " << ElecDaughtersEDep[EL] << ", DecayEDep " << ElecDecayEDep[EL] << ", NearEDep " << ElecNearEDep[EL]
698  << "\nStart pos " << ElecStart[EL][0] << ", " << ElecStart[EL][1] << ", " << ElecStart[EL][2]
699  << ". + End pos " << ElecEnd [EL][0] << ", " << ElecEnd [EL][1] << ", " << ElecEnd [EL][2]
700  << "\nThe parents of this electron were: ";
701  for (int zz=0; zz<nParentElec[EL]; ++zz) {
702  std::cout << ElecParents[EL][zz] << " ("<<ElecParTrID[EL][zz]<<"), ";
703  }
704  std::cout << "."<< std::endl;
705  }
706  }
707  if (nMuon) {
708  std::cout << "There are " << nMuon << " muons in this event!!" << std::endl;
709  }
710  if (nPion) {
711  std::cout << "There are " << nPion << " pions in this event!!" << std::endl;
712  }
713  if (nPi0) {
714  std::cout << "There are " << nPi0 << " pi0's in this event!!" << std::endl;
715  }
716  if (nProt) {
717  std::cout << "There are " << nProt << " protons in this event!!" << std::endl;
718  }
719 
720  std::cout << "\nThere was " << EDepNearEdge2 << ", (" << EDepNearEdge5 << "), [" << EDepNearEdge10 << "] MeV EDep within 2, (5), [10] cm of walls" << std::endl;
721  }
722  // ------------------------------------- Output some information about my particles -------------------------------------
723 
724  // ------ Fill the Tree ------
725  if (nKaon) {
726  if (Verbosity)
727  std::cout << "There were Kaons in the detector so writing out this event." << std::endl;
728  fDecayTree->Fill();
729  }
730  return;
731 } // Analyse
732 // ******************************** Fill variables *****************************************************
733 void NeutronDecayN2Ana::NeutronDecayN2Ana::FillVars( std::vector<int> &TrackIDVec, int &numParts, float EDep[MaxPart], float DaughtEDep[MaxPart],
734  float DecayEDep[MaxPart], float Start[MaxPart][4], float End[MaxPart][4],
735  int nParents[MaxPart], int Parent[MaxPart][MaxParent], int ParTrID[MaxPart][MaxParent],
736  int PDG[MaxPart], int TrID[MaxPart], int Cont[MaxPart], int FromDecay[MaxPart],
737  int ThisID, unsigned int ThisTDC, sim::IDE ThisIDE, const simb::MCParticle& MCPart,
738  bool OrigParticle, bool Decay, bool &Written ) {
739  if (numParts+1 > MaxPart-1) {
740  BadEvent = true;
741  Written=true;
742  return;
743  }
744 
745  std::vector<int>::iterator it=std::find( TrackIDVec.begin(), TrackIDVec.end(), abs(ThisID) );
746  int partNum = 0;
747  // ------- Figure out which partNum I want to use --------
748  if ( it==TrackIDVec.end() ) {
749  TrackIDVec.push_back ( abs(ThisID) ); // Push back this particle type IDVec
750  AllTrackIDs.push_back( abs(ThisID) ); // Push back all particle type IDVec
751  PDG[numParts] = MCPart.PdgCode();
752  TrID[numParts] = abs( MCPart.TrackId() );
753  if ( MCPart.Process() == "Decay" ) FromDecay[numParts] = 1;
754  else FromDecay[numParts] = 0;
755  // Work out if contained within TPC...
756  bool StartIn = IsInTPC( MCPart.Vx(0) , MCPart.Vy(0) , MCPart.Vz(0) , ActiveBounds );
757  bool EndIn = IsInTPC( MCPart.EndX(), MCPart.EndY(), MCPart.EndZ(), ActiveBounds );
758  if(!StartIn && !EndIn ) Cont[numParts] = 0; // through track
759  if(!StartIn && EndIn ) Cont[numParts] = 1; // entering track
760  if( StartIn && !EndIn ) Cont[numParts] = 2; // escaping track
761  if( StartIn && EndIn ) Cont[numParts] = 3; // contained track
762  if (Verbosity)
763  std::cout << "\nPushing back a new ideTrackID " << abs(ThisID) << ", it was from a " << MCPart.PdgCode() << ", process " << MCPart.Process()
764  << ", PartDecay? " << FromDecay[numParts] << ", deposition from a decay? " << Decay << "\n"
765  << "Starting location is " << MCPart.Vx(0) << ", " << MCPart.Vy(0) << ", " << MCPart.Vz(0) << "==> InTPC? " << StartIn
766  << ". Ending location is " << MCPart.EndX()<< ", " << MCPart.EndY()<< ", " << MCPart.EndZ() << "==> InTPC? " << EndIn
767  << " =====>>> Cont? " << Cont[numParts]
768  << std::endl;
769  // ---- Work out the particles ancestry ----
770  Parent[numParts][0] = MCPart.Mother();
771  int NumParent = 0;
772  int ParentID = Parent[numParts][0];
773  while ( ParentID > 0 && NumParent < MaxParent) {
774  int pdg = truthmap[ ParentID ]->PdgCode();
775  if (Verbosity==2)
776  std::cout << "The particles parent was TrackID " << ParentID << ", PdgCode " << pdg << ", it was from process " << truthmap[ ParentID ]->Process() << std::endl;
777  // If this particle had same parent as previously, then put this TrackID in my array instead
778  if ( pdg == Parent[numParts][NumParent-1] ) {
779  if (Verbosity==2)
780  std::cout << "Overwriting what was in ParentID as same particle." << std::endl;
781  ParTrID[numParts][NumParent-1] = ParentID;
782  } else {
783  Parent [numParts][NumParent] = pdg;
784  ParTrID[numParts][NumParent] = ParentID;
785  ++NumParent;
786  }
787  ParentID = truthmap[ ParentID ]->Mother();
788  }
789 
790  if (Verbosity)
791  std::cout << "There were a total of " << NumParent << " parents of this particle. The parentage was: " << PDG[numParts] << " ("<< TrID[numParts] <<") ";
792  for (int aa=0; aa<NumParent; ++aa)
793  if (Verbosity)
794  std::cout << " <- " << Parent[numParts][aa] << " ("<<ParTrID[numParts][aa] << ") ";
795  if (Verbosity) std::cout << "." << std::endl;
796 
797  nParents[numParts] = NumParent;
798  partNum = numParts;
799  ++numParts;
800  } else {
801  partNum = it - TrackIDVec.begin();
802  }
803 
804  // ----------- If TrackID is positive add it to the EDep from this track, if negative then it has to be from a daughter --------------
805  if ( Verbosity > 1 ) {
806  std::cout << "OrigParticle " << OrigParticle << ", TrackID " << ThisID << ", " << ThisIDE.trackID
807  << ", PDgCode " << PDG[numParts-1] << ", " << MCPart.PdgCode() << ", decay " << Decay
808  << std::endl;
809  }
810  if ( OrigParticle ) {
811  EDep[partNum] += ThisIDE.energy;
812 
813  bool RepSt = false;
814  if (Start[partNum][1] == HolderVal)
815  RepSt = true;
816  else {
817  float St_Ar = CalcDist( MCPart.Vx(0), MCPart.Vy(0), MCPart.Vz(0), Start[partNum][0], Start[partNum][1], Start[partNum][2] );
818  float St_ID = CalcDist( MCPart.Vx(0), MCPart.Vy(0), MCPart.Vz(0), ThisIDE.x , ThisIDE.y , ThisIDE.z );
819  if ( St_ID < St_Ar )
820  RepSt = true;
821  }
822  if (RepSt) {
823  Start[partNum][0] = ThisIDE.x;
824  Start[partNum][1] = ThisIDE.y;
825  Start[partNum][2] = ThisIDE.z;
826  Start[partNum][3] = ThisTDC;
827  }
828  // ------- Do I want to replace the end array?
829  bool RepEn = false;
830  if (End[partNum][1] == HolderVal)
831  RepEn = true;
832  else {
833  float En_Ar = CalcDist( MCPart.EndX(), MCPart.EndY(), MCPart.EndZ(), End[partNum][0], End[partNum][1], End[partNum][2] );
834  float En_ID = CalcDist( MCPart.EndX(), MCPart.EndY(), MCPart.EndZ(), ThisIDE.x , ThisIDE.y , ThisIDE.z );
835  if ( En_ID < En_Ar )
836  RepEn = true;
837  }
838  if (RepEn) {
839  End[partNum][0] = ThisIDE.x;
840  End[partNum][1] = ThisIDE.y;
841  End[partNum][2] = ThisIDE.z;
842  End[partNum][3] = ThisTDC;
843  }
844  // --------- Work out the start / end of this track ----------
845  } else if (Decay) {
846  DecayEDep[partNum] += ThisIDE.energy;
847  } else {
848  DaughtEDep[partNum] += ThisIDE.energy;
849  }
850 
851  Written=true;
852 } // FillVars
853 // ******************************** UnAssignLoop *****************************************************
854 bool NeutronDecayN2Ana::NeutronDecayN2Ana::UnAssignLoop( int nPart, float St[MaxPart][4], sim::IDE thisIDE, float NearE[MaxPart] ) {
855  for (int nP=0; nP < nPart; ++nP) {
856  float ThisDist = CalcDist( St[nP][0], St[nP][1], St[nP][2], thisIDE.x, thisIDE.y, thisIDE.z );
857  if (Verbosity > 1) {
858  std::cout << " Particle " << nP << " had initial position ("<<St[nP][0]<<", "<<St[nP][1]<<", "<<St[nP][2] <<")...How close was this to the IDE in question? " << ThisDist << std::endl;
859  }
860  if (ThisDist < NearEDeps) {
861  NearE[nP] += thisIDE.energy;
862  return true;
863  }
864  }
865  return false;
866 } // UnAssignLoop
867 // ******************************** Define Module *****************************************************
868 float NeutronDecayN2Ana::NeutronDecayN2Ana::CalcDist( float X1, float Y1, float Z1, float X2, float Y2, float Z2 ) {
869  float Sq = TMath::Power( X1-X2 , 2 ) + TMath::Power( Y1-Y2 , 2 ) + TMath::Power( Z1-Z2 , 2 );
870  float Va = TMath::Power( Sq, 0.5 );
871  return Va;
872 }
873 // ******************************** Define Module *****************************************************
874 bool NeutronDecayN2Ana::NeutronDecayN2Ana::IsInTPC( float X1, float Y1, float Z1, float Bound[6] ) {
875  bool InX = ( X1 > Bound[0] && X1 < Bound[1] );
876  bool InY = ( Y1 > Bound[2] && Y1 < Bound[3] );
877  bool InZ = ( Z1 > Bound[4] && Z1 < Bound[5] );
878  bool Within = (InX && InY && InZ );
879  /*
880  std::cout << "Is ("<<X1<<", "<<Y1<<", "<<Z1<<") within the TPC? InX " << InX << ", InY " << InY << ", InZ " << InZ << ", within = " << Within
881  << " X "<<Bound[0]<<" to "<<Bound[1]
882  << ", X "<<Bound[2]<<" to "<<Bound[3]
883  << ", X "<<Bound[4]<<" to "<<Bound[5]
884  <<std::endl;
885  */
886  return Within;
887 }
888 // ******************************** Define Module *****************************************************
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
TrackID_t trackID
Geant4 supplied track ID.
Definition: SimChannel.h:112
intermediate_table::iterator iterator
#define MaxPart
float z
z position of ionization [cm]
Definition: SimChannel.h:117
int PdgCode() const
Definition: MCParticle.h:212
float CalcDist(float X1, float Y1, float Z1, float X2, float Y2, float Z2)
EventNumber_t event() const
Definition: DataViewImpl.cc:85
art::ServiceHandle< geo::Geometry > geom
Verbosity
Definition: Verbosity.h:5
double EndZ() const
Definition: MCParticle.h:228
#define MaxParent
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
int Mother() const
Definition: MCParticle.h:213
Geometry information for a single TPC.
Definition: TPCGeo.h:38
void Decay(const Decayer *decayer, int pdgc, double E, int ndecays)
Definition: gtestDecay.cxx:179
std::string Process() const
Definition: MCParticle.h:215
Particle class.
double EndY() const
Definition: MCParticle.h:227
float x
x position of ionization [cm]
Definition: SimChannel.h:115
art framework interface to geometry description
Definition: Run.h:17
int TrackId() const
Definition: MCParticle.h:210
const uint PDG
Definition: qregexp.cpp:140
T abs(T value)
NeutronDecayN2Ana(fhicl::ParameterSet const &p)
const double e
int PdgCode(Resonance_t res, int Q)
(resonance id, charge) -> PDG code
bool UnAssignLoop(int nPart, float St[MaxPart][4], sim::IDE thisIDE, float NearE[MaxPart])
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
void endRun(art::Run const &) override
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:84
#define HolderVal
float energy
energy deposited by ionization by this track ID and time [MeV]
Definition: SimChannel.h:114
p
Definition: test.py:223
RunNumber_t run() const
Definition: DataViewImpl.cc:71
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
std::map< int, const simb::MCParticle * > truthmap
void analyze(art::Event const &e) override
float y
y position of ionization [cm]
Definition: SimChannel.h:116
double Vx(const int i=0) const
Definition: MCParticle.h:221
bool operator()(const sim::IDE &first, const sim::IDE &second)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
void End(void)
Definition: gXSecComp.cxx:210
Definition: types.h:32
def center(depos, point)
Definition: depos.py:117
bool IsInTPC(float X1, float Y1, float Z1, float Bound[6])
double Vz(const int i=0) const
Definition: MCParticle.h:223
void FillVars(std::vector< int > &TrackIDVec, int &numParts, float EDep[MaxPart], float DaughtEDep[MaxPart], float DecayEDep[MaxPart], float Start[MaxPart][4], float End[MaxPart][4], int nParents[MaxPart], int Parent[MaxPart][MaxParent], int ParTrID[MaxPart][MaxParent], int PDG[MaxPart], int TrID[MaxPart], int Cont[MaxPart], int FromDecay[MaxPart], int ThisID, unsigned int ThisTDC, sim::IDE ThisIDE, const simb::MCParticle &MCPart, bool Decay, bool OrigParticle, bool &Written)
void beginRun(art::Run const &run) override
TCEvent evt
Definition: DataStructs.cxx:7
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
double EndX() const
Definition: MCParticle.h:226
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
if(!yymsg) yymsg
LArSoft geometry interface.
Definition: ChannelGeo.h:16
double Vy(const int i=0) const
Definition: MCParticle.h:222
#define MaxPrim
#define Start
Definition: config.cpp:1229
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
QTextStream & endl(QTextStream &s)
Signal from collection planes.
Definition: geo_types.h:146