HighLAND
oaAnalysisTreeConverter.cxx
1 #include "oaAnalysisTreeConverter.hxx"
2 #include "InputManager.hxx"
3 #include "Versioning.hxx"
4 #include "BasicUtils.hxx"
5 #include "HighlandAnalysisUtils.hxx"
6 #include "TreeConverterUtils.hxx"
7 #include "HighlandTreeConverterUtils.hxx"
8 #include "Parameters.hxx"
9 
10 // FACTOR FOR SAND MC POT CALCULATION
11 const Float_t SANDFACTOR=2.5e17;
12 
13 // single gamma and 1pi Pauli-blocked vertices must be discarded from the truth tree
14 // but kept in the NRooTrackerVtx (see bugzilla 1011)
15 bool _discardPauliBlocked = true;
16 // unphysical coherent interaction on hydrogen are present in both prod 5 and 6
17 // because of a bug in neut (see bugzilla 1056)
18 bool _discardCohOnH = true;
19 
20 // #define DEBUG
21 
22 //****************************************************************
23 bool CompareNNodes(ND::TSubBaseObject *obj1, ND::TSubBaseObject *obj2){
24 //****************************************************************
25  //decreasing nnodes order
26 
27  if (obj1 && obj2)
28  return (obj1->NNodes > obj2->NNodes);
29  else
30  return false;
31 }
32 
33 
34 //********************************************************************
35 oaAnalysisTreeConverter::oaAnalysisTreeConverter():InputConverter("ReconDir/Global"){
36 //********************************************************************
37 
38  _firstFile = true;
39  _firstEntry = true;
40  _currentFileIndex=-1;
41 
42  _RooVtxEntryInCurrentInputFile=0;
43 
44  TrECalObjects = NULL;
45  TrECalUnmatched = NULL;
46  P0DReconVertices = NULL;
47  P0DReconParticles = NULL;
48  P0DReconClusters = NULL;
49  P0DReconTracks = NULL;
50  P0DReconShowers = NULL;
51  P0DReconNodes = NULL;
52  P0DReconHits = NULL;
53  PIDs = NULL;
54  Vertices = NULL;
55  DelayedClusters = NULL;
56  TPCOthers = NULL;
57  FgdTimeBins = NULL;
58  TruthVertices = NULL;
59  TruthTrajs = NULL;
60  GVtx = NULL;
61  NVtx = NULL;
62  XZTracks_Radon2 = NULL;
63  YZTracks_Radon2 = NULL;
64  XYZTracks_Radon2 = NULL;
65  XZTracksAllFGD_Radon2 = NULL;
66  YZTracksAllFGD_Radon2 = NULL;
67  XYZTracksAllFGD_Radon2 = NULL;
68  VtxP0DECal = NULL;
69  beamSummary = NULL;
70  beamSummaryDataStatus = -1;
71  _spill = NULL;
72 
73  AccPOTflg = false;
74 
75  cosmic_mode = false;
76  NTruthTrajs = 0;
77  NTruthVertices = 0;
78 
79  Genie = false;
80  Neut = false;
81  NeutFirstFile = false;
82  GenieFirstFile = false;
83 
84 
85  // Initialise DQ flags, which won't get read in for MC
86  fND280OffFlag = 0;
87  fTPCFlag = 0;
88  fTPC1Flag = 0;
89  fTPC2Flag = 0;
90  fTPC3Flag = 0;
91  fFGDFlag = 0;
92  fFGD1Flag = 0;
93  fFGD2Flag = 0;
94  fECALFlag = 0;
95  fDSECALFlag = 0;
96  fBarECALFlag = 0;
97  fP0DECALFlag = 0;
98  fP0DFlag = 0;
99  fSMRDFlag = 0;
100  fMAGNETFlag = 0;
101  fINGRIDFlag = 0;
102 
103  fCurrent = -999;
104  Entries = -999;
105  Counter = -999;
106  EventID = -999;
107  RunID = -999;
108  SubrunID = -999;
109  IsMC = false;
110  Preselected = -999;
111  EventTime = -999;
112  TriggerWord = -999;
113  FGDCosmicEvent = false;
114  TripTCosmicEvent = false;
115  P0DWaterStatus = false;
116  //SoftwareVersion[50];
117  NTrECalObjects = -999;
118  NP0DReconVertices = -999;
119  NP0DReconParticles = -999;
120  NP0DReconClusters = -999;
121  NP0DReconTracks = -999;
122  NP0DReconShowers = -999;
123  NP0DReconNodes = -999;
124  NP0DReconHits = -999;
125  NPIDs = -999;
126  NVertices = -999;
127  NFGD1Unused = -999;
128  NFGD2Unused = -999;
129  NP0DUnused = -999;
130  NTPCUnused = -999;
131  NDelayedClusters = -999;
132  NTPCOthers = -999;
133  NNVtx = -999;
134  NGVtx = -999;
135  NFgdTimeBins = -999;
136  NTruthVertices = -999;
137  NVtxFGD1 = -999;
138  NVtxFGD2 = -999;
139  NTruthTrajs = -999;
140  NXZTracks_Radon2 = -999;
141  NYZTracks_Radon2 = -999;
142  NXYZTracks_Radon2 = -999;
143  NXZTracksAllFGD_Radon2 = -999;
144  NYZTracksAllFGD_Radon2 = -999;
145  NXYZTracksAllFGD_Radon2 = -999;
146  ND280Spill = -999;
147  fBarECALFlag = -999;
148  fDSECALFlag = -999;
149  fECALFlag = -999;
150  fFGD1Flag = -999;
151  fFGD2Flag = -999;
152  fFGDFlag = -999;
153  fINGRIDFlag = -999;
154  fMAGNETFlag = -999;
155  fND280OffFlag = -999;
156  fP0DECALFlag = -999;
157  fP0DFlag = -999;
158  fSMRDFlag = -999;
159  fTPC1Flag = -999;
160  fTPC2Flag = -999;
161  fTPC3Flag = -999;
162  fTPCFlag = -999;
163 
164  for (int i = 0; i < 7; i++) {
165  TruthTrajsName[i] = "";
166  }
167  for (int i = 0; i < 9; i++) {
168  TruthVerticesName[i] = "";
169  }
170 
171 
172  _previousFile = "";
173  _previousRunID = -1;
174  _previousSubrunID = -1;
175  _previousRefEventID = -1;
176 
177 }
178 
179 //********************************************************************
181 //********************************************************************
182 
183  /// Use ReconDir/TrackerECal information?
184  _isUsingReconDirFGDOnly = ND::params().GetParameterI("highlandIO.FlatTree.UseReconDirFGDOnly");
185  _isUsingReconDirP0D = ND::params().GetParameterI("highlandIO.FlatTree.UseReconDirP0D");
186  _isUsingReconDirPECAL = ND::params().GetParameterI("highlandIO.FlatTree.UseReconDirP0DECal");
187  _isUsingReconDirTECAL = ND::params().GetParameterI("highlandIO.FlatTree.UseReconDirTrackerECal");
188 
189  // ---- TEST HIGHLAND2-P0D ----
190  _isUsingReconDirP0DNew = ND::params().GetParameterI("highlandIO.P0DDataClasses.UseReconDirP0DNew");
191  _p0dAlgoResName = ND::params().GetParameterS("highlandIO.P0DDataClasses.UseReconDirP0DAlgoResult");
192  _addGlobalTracksToP0DVertices = (bool)ND::params().GetParameterI("highlandIO.P0DDataClasses.AddGlobalTracksToP0DVertices");
193 
194  if (_isUsingReconDirP0D && _isUsingReconDirP0DNew){
195  std::cerr << "ERROR. oaAnalysisTreeConverter::Initialize(). 'highlandIO.FlatTree.UseReconDirP0D' and 'highlandIO.P0DRecon.UseReconDirP0DNew' are both set to 1 "
196  << "highlandIO.parameters.dat. Please switch off one of two !!!!" << std::endl;
197  exit(1);
198  }
199  // ----------------------------
200 
201  /// Ignore TrueVertices when all their true tracks are fully contained
202  _ignoreSMRDContainedTrueObjects = ND::params().GetParameterI("highlandIO.oaAnalysis.IgnoreSMRDContainedTrueObjects");
203  _ignoreP0DECalContainedTrueObjects = ND::params().GetParameterI("highlandIO.oaAnalysis.IgnoreP0DECalContainedTrueObjects");
204  _ignoreDsECalContainedTrueObjects = ND::params().GetParameterI("highlandIO.oaAnalysis.IgnoreDsECalContainedTrueObjects");
205  _ignoreBrECalContainedTrueObjects = ND::params().GetParameterI("highlandIO.oaAnalysis.IgnoreBrECalContainedTrueObjects");
206  _ignoreINGRIDContainedTrueObjects = ND::params().GetParameterI("highlandIO.oaAnalysis.IgnoreINGRIDContainedTrueObjects");
207 
208  // Remove uninteresting vertices
209  _removeTrueVerticesWithNoTrueParticles = ND::params().GetParameterI("highlandIO.oaAnalysis.RemoveTrueVerticesWithNoTrueParticles");
210 
211  AddChain("ReconDir/Global");
212  AddChain("TruthDir/Vertices");
213  AddChain("TruthDir/Trajectories");
214  AddChain("HeaderDir/BeamSummaryData");
215  AddChain("HeaderDir/BasicDataQuality");
216  AddChain("HeaderDir/BasicHeader");
217 
218  if(_isUsingReconDirFGDOnly) AddChain("ReconDir/FGDOnly");
219  if(_isUsingReconDirTECAL) AddChain("ReconDir/TrackerECal");
220  if(_isUsingReconDirP0D || _isUsingReconDirP0DNew) AddChain("ReconDir/P0D");
221 
222  reconGlobal = GetChain("ReconDir/Global");
223  mcTruthVertices = GetChain("TruthDir/Vertices");
224  mcTruthTrajectories = GetChain("TruthDir/Trajectories");
225  beamInfo = GetChain("HeaderDir/BeamSummaryData");
226  DQInfo = GetChain("HeaderDir/BasicDataQuality");
227  BasicHeader = GetChain("HeaderDir/BasicHeader");
228  accPOTInfo = NULL;//GetChain("HeaderDir/AccumulatedPOT");
229  GRooTrackerVTX = NULL;
230  NRooTrackerVTX = NULL;
231 
232  if(_isUsingReconDirFGDOnly) fgdOnly = GetChain("ReconDir/FGDOnly");
233  else fgdOnly = NULL;
234  if(_isUsingReconDirTECAL) trackerECAL = GetChain("ReconDir/TrackerECal");
235  else trackerECAL = NULL;
236  if(_isUsingReconDirP0D || _isUsingReconDirP0DNew) p0d = GetChain("ReconDir/P0D");
237  else p0d = NULL;
238 
239  fChain = reconGlobal;
240 
241  // Set branch addresses and branch pointers
242 
243  if (!fChain) return false;
244  fCurrent = -1;
245 
246  // ------------- TGlobalPIDs --------------------
247  PIDs = new TClonesArray("ND::TGlobalReconModule::TGlobalPID",20);
248  reconGlobal->SetBranchAddress("NPIDs", &NPIDs);
249  reconGlobal->SetBranchAddress("PIDs", &PIDs);
250 
251  FgdTimeBins = new TClonesArray("ND::TGlobalReconModule::TFgdTimeBin");
252  reconGlobal->SetBranchAddress("NFgdTimeBins", &NFgdTimeBins);
253  reconGlobal->SetBranchAddress("FgdTimeBins", &FgdTimeBins);
254 
255  Vertices = new TClonesArray("ND::TGlobalReconModule::TGlobalVertex",20);
256  reconGlobal->SetBranchAddress("NVertices",&NVertices);
257  reconGlobal->SetBranchAddress("Vertices",&Vertices);
258 
259  /*
260  DelayedClusters = new TClonesArray("ND::TGlobalReconModule::TFgdCluster",200);
261  reconGlobal->SetBranchAddress("DelayedClusters",&DelayedClusters);
262  reconGlobal->SetBranchAddress("NDelayedClusters",&NDelayedClusters);
263 
264  reconGlobal->SetBranchAddress("NFGD1Unused",&NFGD1Unused);
265  reconGlobal->SetBranchAddress("NFGD2Unused",&NFGD2Unused);
266  reconGlobal->SetBranchAddress("NP0DUnused",&NP0DUnused);
267  reconGlobal->SetBranchAddress("NTPCUnused",&NTPCUnused);
268 
269  TPCOthers = new TClonesArray("ND::TGlobalReconModule::TTPCOtherObject",20);
270  reconGlobal->SetBranchAddress("TPCOthers",&TPCOthers);
271  reconGlobal->SetBranchAddress("NTPCOthers",&NTPCOthers);
272  */
273 
274 
275  if( trackerECAL ) {
276  TrECalObjects = new TClonesArray("ND::TTrackerECALReconModule::TECALReconObject",20);
277  trackerECAL->SetBranchAddress("NReconObject",&NTrECalObjects);
278  trackerECAL->SetBranchAddress("ReconObject", &TrECalObjects);
279 
280  TrECalUnmatched = new TClonesArray("ND::TTrackerECALReconModule::TECALReconUnmatchedObject",20);
281  trackerECAL->SetBranchAddress("NUnmatchedObject",&NTrECalUnmatched);
282  trackerECAL->SetBranchAddress("UnmatchedObject", &TrECalUnmatched);
283  }
284 
285  if ( p0d ) {
286  // ---- TEST HIGHLAND2-P0D ----
287  P0DAlgoResults = new TClonesArray("ND::TP0DReconModule::TP0DAlgoRes",20);
288  p0d->SetBranchAddress("NAlgoResults",&NP0DAlgoResults);
289  p0d->SetBranchAddress("AlgoResults", &P0DAlgoResults);
290 
291  P0DReconVertices = new TClonesArray("ND::TP0DReconModule::TP0DVertex",100);
292  p0d->SetBranchAddress("NVertices",&NP0DReconVertices);
293  p0d->SetBranchAddress("Vertices", &P0DReconVertices);
294 
295  P0DReconParticles = new TClonesArray("ND::TP0DReconModule::TP0DParticle",100);
296  p0d->SetBranchAddress("NParticles",&NP0DReconParticles);
297  p0d->SetBranchAddress("Particles", &P0DReconParticles);
298 
299  P0DReconTracks = new TClonesArray("ND::TP0DReconModule::TP0DTrack",100);
300  p0d->SetBranchAddress("NTracks",&NP0DReconTracks);
301  p0d->SetBranchAddress("Tracks", &P0DReconTracks);
302 
303  P0DReconShowers = new TClonesArray("ND::TP0DReconModule::TP0DShower",100);
304  p0d->SetBranchAddress("NShowers",&NP0DReconShowers);
305  p0d->SetBranchAddress("Showers", &P0DReconShowers);
306 
307  P0DReconClusters = new TClonesArray("ND::TP0DReconModule::TP0DCluster",100);
308  p0d->SetBranchAddress("NClusters",&NP0DReconClusters);
309  p0d->SetBranchAddress("Clusters", &P0DReconClusters);
310 
311  P0DReconNodes = new TClonesArray("ND::TP0DReconModule::TP0DNode",100);
312  p0d->SetBranchAddress("NNodes",&NP0DReconNodes);
313  p0d->SetBranchAddress("Nodes", &P0DReconNodes);
314 
315  P0DReconHits = new TClonesArray("ND::TP0DReconModule::TP0DHit",100);
316  p0d->SetBranchAddress("NHits",&NP0DReconHits);
317  p0d->SetBranchAddress("Hits", &P0DReconHits);
318  // ------------------------------
319  }
320 
321  //--------------- True vertices -------------------
322  if (mcTruthVertices){
323  TruthVertices = new TClonesArray("ND::TTruthVerticesModule::TTruthVertex", 100);
324  mcTruthVertices->SetBranchAddress("NVtx", &NTruthVertices);
325  mcTruthVertices->SetBranchAddress("NVtxFGD1", &NVtxFGD1);
326  mcTruthVertices->SetBranchAddress("NVtxFGD2", &NVtxFGD2);
327  mcTruthVertices->SetBranchAddress("Vertices", &TruthVertices);
328  }
329 
330  //--------------- True Trajectories --------------
331  if (mcTruthTrajectories){
332  TruthTrajs = new TClonesArray("ND::TTruthTrajectoriesModule::TTruthTrajectory", 100);
333  mcTruthTrajectories->SetBranchAddress("NTraj", &NTruthTrajs);
334  mcTruthTrajectories->SetBranchAddress("Trajectories", &TruthTrajs);
335  }
336 
337  //------------- FGD information -----------------------
338  if (fgdOnly){
339  XZTracks_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd2DIsoTrack",200);
340  fgdOnly->SetBranchAddress("NXZTracks_Radon2", &NXZTracks_Radon2);
341  fgdOnly->SetBranchAddress("XZTracks_Radon2", &XZTracks_Radon2);
342 
343  YZTracks_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd2DIsoTrack",200);
344  fgdOnly->SetBranchAddress("NYZTracks_Radon2", &NYZTracks_Radon2);
345  fgdOnly->SetBranchAddress("YZTracks_Radon2", &YZTracks_Radon2);
346 
347  XYZTracks_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd3DIsoTrack",200);
348  fgdOnly->SetBranchAddress("NXYZTracks_Radon2", &NXYZTracks_Radon2);
349  fgdOnly->SetBranchAddress("XYZTracks_Radon2", &XYZTracks_Radon2);
350 
351  XZTracksAllFGD_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd2DIsoTrack",200);
352  fgdOnly->SetBranchAddress("NXZTracksAllFGD_Radon2", &NXZTracksAllFGD_Radon2);
353  fgdOnly->SetBranchAddress("XZTracksAllFGD_Radon2", &XZTracksAllFGD_Radon2);
354 
355  YZTracksAllFGD_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd2DIsoTrack",200);
356  fgdOnly->SetBranchAddress("NYZTracksAllFGD_Radon2", &NYZTracksAllFGD_Radon2);
357  fgdOnly->SetBranchAddress("YZTracksAllFGD_Radon2", &YZTracksAllFGD_Radon2);
358 
359  XYZTracksAllFGD_Radon2 = new TClonesArray("ND::TFgdOnlyModule::TFgd3DIsoTrack",200);
360  fgdOnly->SetBranchAddress("NXYZTracksAllFGD_Radon2", &NXYZTracksAllFGD_Radon2);
361  fgdOnly->SetBranchAddress("XYZTracksAllFGD_Radon2", &XYZTracksAllFGD_Radon2);
362  }
363 
364  //-------------- Beam summary --------------------
365  if (beamInfo){
366  beamSummary = new TClonesArray("ND::TBeamSummaryDataModule::TBeamSummaryData",200);
367  beamInfo->SetBranchAddress("BeamSummaryData", &beamSummary);
368  beamInfo->SetBranchAddress("BeamSummaryDataStatus", &beamSummaryDataStatus);
369  beamInfo->SetBranchAddress("ND280Spill", &ND280Spill);
370  }
371 
372  //-------------- Accumulated POT -----------------------
373  // if( AccPOTflg && accPOTInfo) {
374  // accPOTInfo->SetBranchAddress("AccPOT", &skimaccpotbtwEvt);
375  // }
376 
377 
378  //-------------- Header ---------------------------------
379  if (BasicHeader){
380  BasicHeader->SetBranchAddress("EventID", &EventID);
381  BasicHeader->SetBranchAddress("RunID", &RunID);
382  BasicHeader->SetBranchAddress("SubrunID", &SubrunID);
383  BasicHeader->SetBranchAddress("IsMC", &IsMC);
384  BasicHeader->SetBranchAddress("EventTime", &EventTime);
385  BasicHeader->SetBranchAddress("Preselected", &Preselected);
386  BasicHeader->SetBranchAddress("TriggerWord", &TriggerWord);
387  BasicHeader->SetBranchAddress("FGDCosmicEvent", &FGDCosmicEvent);
388  BasicHeader->SetBranchAddress("TripTCosmicEvent", &TripTCosmicEvent);
389  BasicHeader->SetBranchAddress("SoftwareVersion", &SoftwareVersion);
390  BasicHeader->SetBranchAddress("P0DWaterStatus", &P0DWaterStatus);
391 #if VERSION_HAS_OFFICIAL_POT
392  BasicHeader->SetBranchAddress("POTPerSpill", &POTPerSpill);
393 #endif
394  }
395 
396  //------------ DataQuality summary ----------------------
397  if (DQInfo){
398  DQInfo->SetBranchAddress("ND280OffFlag", &fND280OffFlag);
399  DQInfo->SetBranchAddress("TPCFlag", &fTPCFlag);
400  DQInfo->SetBranchAddress("TPC1Flag", &fTPC1Flag);
401  DQInfo->SetBranchAddress("TPC2Flag", &fTPC2Flag);
402  DQInfo->SetBranchAddress("TPC3Flag", &fTPC3Flag);
403  DQInfo->SetBranchAddress("FGDFlag", &fFGDFlag);
404  DQInfo->SetBranchAddress("FGD1Flag", &fFGD1Flag);
405  DQInfo->SetBranchAddress("FGD2Flag", &fFGD2Flag);
406  DQInfo->SetBranchAddress("ECALFlag", &fECALFlag);
407  DQInfo->SetBranchAddress("DSECALFlag", &fDSECALFlag);
408  DQInfo->SetBranchAddress("BarECALFlag", &fBarECALFlag);
409  DQInfo->SetBranchAddress("P0DECALFlag", &fP0DECALFlag);
410  DQInfo->SetBranchAddress("P0DFlag", &fP0DFlag);
411  DQInfo->SetBranchAddress("SMRDFlag", &fSMRDFlag);
412  DQInfo->SetBranchAddress("MAGNETFlag", &fMAGNETFlag);
413  DQInfo->SetBranchAddress("INGRIDFlag", &fINGRIDFlag);
414  }
415 
416  //Setup the TruthUtils
417  _truthUtils.SetTrajectoriesArray (TruthTrajs);
418  _truthUtils.SetVerticesArray (TruthVertices);
419  _truthUtils.SetTrajectoriesNumber(&NTruthTrajs);
420  _truthUtils.SetVerticesNumber (&NTruthVertices);
421 
422  return true;
423 }
424 
425 //********************************************************************
426 oaAnalysisTreeConverter::~oaAnalysisTreeConverter(){
427 //********************************************************************
428 
429  if (!fChain) return;
430 
431  if (reconGlobal ) delete reconGlobal ->GetCurrentFile();
432  if (trackerECAL ) delete trackerECAL ->GetCurrentFile();
433  if (p0d ) delete p0d ->GetCurrentFile();
434  if (fgdOnly ) delete fgdOnly ->GetCurrentFile();
435  if (mcTruthVertices ) delete mcTruthVertices ->GetCurrentFile();
436  if (beamInfo ) delete beamInfo ->GetCurrentFile();
437  if (DQInfo ) delete DQInfo ->GetCurrentFile();
438  if (BasicHeader ) delete BasicHeader ->GetCurrentFile();
439  if (mcTruthTrajectories ) delete mcTruthTrajectories ->GetCurrentFile();
440  if (GRooTrackerVTX ) delete GRooTrackerVTX ->GetCurrentFile();
441  if (NRooTrackerVTX ) delete NRooTrackerVTX ->GetCurrentFile();
442  if (accPOTInfo ) delete accPOTInfo ->GetCurrentFile();
443 
444  delete PIDs;
445  delete Vertices;
446  delete DelayedClusters;
447  delete TPCOthers;
448  delete FgdTimeBins;
449  delete TruthVertices;
450  delete TruthTrajs;
451  delete GVtx;
452  delete NVtx;
453  delete TrECalObjects;
454  delete TrECalUnmatched;
455  delete P0DReconVertices;
456  delete P0DReconParticles;
457  delete P0DReconTracks;
458  delete P0DReconShowers;
459  delete P0DReconClusters;
460  delete P0DReconNodes;
461  delete P0DReconHits;
462  delete XZTracks_Radon2;
463  delete YZTracks_Radon2;
464  delete XYZTracks_Radon2;
465  delete XZTracksAllFGD_Radon2;
466  delete YZTracksAllFGD_Radon2;
467  delete XYZTracksAllFGD_Radon2;
468  delete VtxP0DECal;
469  delete beamSummary;
470 }
471 
472 //****************************************************************************
473 bool oaAnalysisTreeConverter::AddFileToTChain(const std::string& inputString){
474 //****************************************************************************
475 
476  std::cout << "oaAnalysisTreeConverter::AddFileToTChain(). Adding file: " << inputString << std::endl;
477 
478  // SKIP FILE WHEN BASIC HEADER HAS 0 ENTRIES
479  TChain BasicHeaderForFile("HeaderDir/BasicHeader");
480  BasicHeaderForFile.AddFile(inputString.c_str());
481  if (BasicHeaderForFile.GetEntries() == 0){
482  std::cout << " ----> This file does not contain any entries. IGNORED !!!!" << std::endl;
483  return true;
484  }
485 
486  // Read one entry from the BasicHeaderForFile such that IsMC is available
487  BasicHeaderForFile.SetBranchAddress("IsMC", &IsMC);
488  BasicHeaderForFile.GetEntry(0);
489 
490 
491  AccPOTflg = false;
492  Genie = Neut = false;
493  if (IsMC){
494  TFile *f = TFile::Open(inputString.c_str());
495  f->cd();
496 
497  gDirectory->cd("/TruthDir");
498  if ( gDirectory->FindObjectAny("NRooTrackerVtx") ) Neut = true;
499  else if( gDirectory->FindObjectAny("GRooTrackerVtx") ) Genie = true;
500 
501 
502  if( _firstFile ) {
503  _firstFile = false;
504 
505  NeutFirstFile = Neut;
506  GenieFirstFile = Genie;
507 
508  // gDirectory->cd("/HeaderDir");
509  // if( gDirectory->FindObjectAny("AccumulatedPOT") ) AccPOTflg = true;
510 
511  //------------- Genie and Neut TRacker Vertex ---------------------
512  // These can only be initialised once we know the file type.
513  if( Neut) {
514  AddChain("NRooTrackerVtx","TruthDir/NRooTrackerVtx");
515  NRooTrackerVTX = GetChain("NRooTrackerVtx");
516  NVtx = new TClonesArray("ND::NRooTrackerVtx",100);
517  NRooTrackerVTX->SetBranchAddress("NVtx",&NNVtx);
518  NRooTrackerVTX->SetBranchAddress("Vtx",&NVtx);
519  }
520  else if( Genie) {
521  AddChain("GRooTrackerVtx","TruthDir/GRooTrackerVtx");
522  GRooTrackerVTX = GetChain("GRooTrackerVtx");
523  GVtx = new TClonesArray("ND::GRooTrackerVtx",100);
524  GRooTrackerVTX->SetBranchAddress("NVtx",&NGVtx);
525  GRooTrackerVTX->SetBranchAddress("Vtx",&GVtx);
526  }
527 
528  //if( !Neut ) delete NRooTrackerVTX;
529  // if( !Genie ) delete GRooTrackerVTX;
530 
531  if ( Neut ) std::cout << " Neut Branch " << std::endl;
532  else if ( Genie ) std::cout << " Genie Branch " << std::endl;
533  }
534  else{
535  if ((!Genie && !Neut) && (GenieFirstFile || NeutFirstFile) ){
536  std::cout << "ERROR (see https://bugzilla.nd280.org/show_bug.cgi?id=1372): This file does not contain RooTrackerVtx Tree. IGNORED !!!!" << std::endl;
537  return true;
538  }
539 
540  // STOP WHEN THE FIRST FILE DOES NOT CONTAIN RooTrackerVtx BUT SOME OTHER DOES
541  if ((Genie || Neut) && (!GenieFirstFile && !NeutFirstFile) ){
542  std::cout << "ERROR (see https://bugzilla.nd280.org/show_bug.cgi?id=1372): The first file didn't contain RooTrackerVtx tree, while this does. Please remove first file from list !!!!" << std::endl;
543  return false;
544  }
545 
546  // STOP WHEN Neut and Genie FILES ARE MIXED ON THE LIST
547  if ((Genie && NeutFirstFile)){
548  std::cout << "ERROR (see https://bugzilla.nd280.org/show_bug.cgi?id=1372): This is a Genie file. Neut and Genie files cannot be mixed !!!!" << std::endl;
549  return false;
550  }
551 
552  if ((Neut && GenieFirstFile)){
553  std::cout << "ERROR (see https://bugzilla.nd280.org/show_bug.cgi?id=1372): This is a Neut file. Neut and Genie files cannot be mixed !!!!" << std::endl;
554  return false;
555  }
556  }
557 
558  f->Close();
559  }
560 
561  // Chain only the directories we are interested in
562 
563  if (reconGlobal ) reconGlobal->AddFile(inputString.c_str());
564  if (trackerECAL ) trackerECAL->AddFile(inputString.c_str());
565  if (fgdOnly ) fgdOnly->AddFile(inputString.c_str());
566  if (p0d ) p0d->AddFile(inputString.c_str());
567  if (mcTruthVertices ) mcTruthVertices->AddFile(inputString.c_str());
568  if (mcTruthTrajectories ) mcTruthTrajectories->AddFile(inputString.c_str());
569  if (beamInfo ) beamInfo->AddFile(inputString.c_str());
570  if (DQInfo ) DQInfo->AddFile(inputString.c_str());
571  if (BasicHeader ) BasicHeader->AddFile(inputString.c_str());
572  if( AccPOTflg && accPOTInfo) accPOTInfo->AddFile(inputString.c_str());
573  if( Neut && NRooTrackerVTX ) NRooTrackerVTX->AddFile(inputString.c_str());
574  if( Genie && GRooTrackerVTX) GRooTrackerVTX->AddFile(inputString.c_str());
575 
576  // Read one entry from the BasicHeader tree such that RunID and SubrunID are available
577  BasicHeader->GetEntry(BasicHeader->GetEntries() - 1);
578 
579  // Make sure the current file has not the same run and subrun number as the previous
580  if (_previousRunID==RunID && _previousSubrunID==SubrunID && _previousRefEventID>= EventID){
581  std::cout << "-------------------------------------------------------------------------------------------------------" << std::endl;
582  std::cout << "oaAnalysisTreeConverter::AddFileToTChain(). Current file has the same run and subrun as the previous" << std::endl;
583  std::cout << " and no higher event number !!!" << std::endl;
584  std::cout << " - this file: " << inputString << std::endl;
585  std::cout << " - previous file: " << _previousFile << std::endl;
586  std::cout << "Please verify the input file list !!!" << std::endl;
587  std::cout << "-------------------------------------------------------------------------------------------------------" << std::endl;
588  exit(1);
589  }
590 
591  // The previous attributes
592  _previousFile = inputString;
593  _previousRunID = RunID;
594  _previousSubrunID = SubrunID;
595  _previousRefEventID = EventID;
596 
597  //IS SAND MC?
598  bool issand = false;
599  if(IsMC){ // IsMC is also is the BasicHeader tree
600  std::stringstream sRun; sRun << RunID;
601  issand = ((sRun.str())[4]=='7');
602  }
603 
604  if (IsMC) {
605  Double_t NPOT = GetPOTFromRooTrackerVtx();
606  bool bySpillInMC = false;
607 #if VERSION_HAS_OFFICIAL_POT
608  bySpillInMC=true;
609 #endif
610 
611  if(issand)
612  header().IncrementPOTByFile(NPOT*SANDFACTOR, bySpillInMC);
613  else //here already multiplied by 5e17
614  header().IncrementPOTByFile(NPOT, bySpillInMC);
615  }
616 
617  // Set the data/MC mode and return false when mixing data and MC files
618  if (!header().SetIsMC(IsMC)) return false;
619 
620  // Sets the software version for this file
621  return header().SetSoftwareVersion(SoftwareVersion);
622 }
623 
624 //*****************************************************************************
625 Double_t oaAnalysisTreeConverter::GetPOTFromRooTrackerVtx() {
626 //*****************************************************************************
627 
628  // ---- POT counting ------------------------------------
629  Double_t NPOT = 0;
630 
631  Int_t ientry,ilastentry;
632  if( GRooTrackerVTX) {
633 
634  // Get the POT for this file from the second last entry in the chain
635  ilastentry = GRooTrackerVTX->GetEntries() - 2;
636  ientry = ilastentry;
637  do{
638  GRooTrackerVTX->GetEntry(ientry--);
639  ND::GRooTrackerVtx *gvtx = (ND::GRooTrackerVtx*) (*GVtx)[0];
640  NPOT = gvtx->OrigTreePOT;
641  }while(NPOT==0 && ientry>=0);
642  }
643  else if(NRooTrackerVTX) {
644 
645  // Get the POT for this file from the last entry in the chain
646  ilastentry = NRooTrackerVTX->GetEntries() - 2;
647  ientry = ilastentry;
648  do{
649  NRooTrackerVTX->GetEntry(ientry--);
650  ND::NRooTrackerVtx *gvtx = (ND::NRooTrackerVtx*) (*NVtx)[0];
651  NPOT = gvtx->OrigTreePOT;
652  }while(NPOT==0 && ientry>=0);
653  }
654  else return NPOT;
655 
656  if (IsMC) {
657  if (NPOT==0) {
658  std::cout << "WARNING: This file has 0 POT but it has some entries !!!!" << std::endl;
659  } else if (ientry+1 != ilastentry) {
660  std::cout << "INFO: OrigTreePOT is 0 in the usual second last entry of RooTrackerVtx ("
661  << ilastentry << "), POT taken from entry " << ientry+1 << std::endl;
662  }
663  }
664  return NPOT;
665 }
666 
667 //*****************************************************************************
668 Int_t oaAnalysisTreeConverter::ReadEntries(Long64_t& entry) {
669 //*****************************************************************************
670 
671  Int_t entry_temp = reconGlobal->GetEntry(entry);
672 
673  if (entry_temp > 0) {
674  if (trackerECAL) trackerECAL->GetEntry(entry);
675  if (p0d ) p0d ->GetEntry(entry);
676  if (fgdOnly ) fgdOnly ->GetEntry(entry);
677  if (BasicHeader) BasicHeader->GetEntry(entry);
678  if (IsMC){
679  if (mcTruthVertices ) mcTruthVertices ->GetEntry(entry);
680  if (mcTruthTrajectories) mcTruthTrajectories->GetEntry(entry);
681 
682  if (Genie && GRooTrackerVTX) GRooTrackerVTX->GetEntry(entry);
683  if (Neut && NRooTrackerVTX ) NRooTrackerVTX->GetEntry(entry);
684  } else {
685  if (beamInfo ) beamInfo ->GetEntry(entry);
686  if (DQInfo ) DQInfo ->GetEntry(entry);
687  if (AccPOTflg && accPOTInfo) accPOTInfo->GetEntry(entry);
688  }
689  }
690 
691  //-------- Increase the cache size to speed up reading Branches ----------
692  if (_firstEntry){
693  if( reconGlobal ) {
694  reconGlobal->SetCacheSize(200000000);
695  reconGlobal->AddBranchToCache("*",kTRUE);
696  }
697  if( mcTruthTrajectories && IsMC) {
698  mcTruthTrajectories->SetCacheSize(200000000);
699  mcTruthTrajectories->AddBranchToCache("*",kTRUE);
700  }
701  if( mcTruthVertices && IsMC) {
702  mcTruthVertices->SetCacheSize(200000000);
703  mcTruthVertices->AddBranchToCache("*",kTRUE);
704  }
705  if( Neut && NRooTrackerVTX ) {
706  NRooTrackerVTX->SetCacheSize(200000000);
707  NRooTrackerVTX->AddBranchToCache("*",kTRUE);
708  }
709  if( Genie && GRooTrackerVTX ) {
710  GRooTrackerVTX->SetCacheSize(200000000);
711  GRooTrackerVTX->AddBranchToCache("*",kTRUE);
712  }
713  _firstEntry=false;
714  }
715 
716  return entry_temp;
717 }
718 
719 //*****************************************************************************
720 Int_t oaAnalysisTreeConverter::GetSpill(Long64_t& entry, AnaSpillC*& spill){
721 //*****************************************************************************
722 
723  // Read contents of entry (which correspond to one Spill)
724  if (!fChain) return 0;
725 
726  std::string filename(reconGlobal->GetFile()->GetName());
727 
728  if( filename != _currentFileName ) {
729  _currentFileIndex++;
730  _RooVtxEntryInCurrentInputFile=0;
731  std::cout << " Running on file (" << _currentFileIndex << "): " << filename << std::endl;
732  _currentFileName = filename;
733  _alreadyWarned=false;
734 
735  //load geometry
736  ND::hgman().LoadGeometry(filename);
737  }
738 
739  Int_t entry_temp = ReadEntries(entry);
740 
741  // If this is not one of the events to skim just go to the next entry (and don't process that event --> return <=0)
742  if (!anaUtils::CheckSkimmedEvent(RunID,SubrunID,EventID)){
743  entry++;
744  return 0;
745  }
746 
747  // Protection against empty spills. For those spills do not create a AnaSpill in the InputManager
748  if (((Neut && NNVtx==0) || (Genie && NGVtx==0) || EventID<0) && !FGDCosmicEvent && !TripTCosmicEvent){
749  entry_temp=0;
750  // too many of these warnings for antinu, see bugzilla 1133
751  // TODO: count them and dump the final number at the end
752 // std::cout << "INFO: NVtx=0 in RooTrackerVtx (no vertices, i.e. empty spill) for event " << RunID << "-" << EventID << " --> Skip it" << std::endl;
753  }
754  else{
755  if (entry_temp > 0) {
756 
757  // Create an instance of the Spill
758  spill = MakeSpill();
759 
760  // Cast it to AnaSpill
761  _spill = static_cast<AnaSpill*>(spill);
762 
763  FillInfo(_spill);
764  }
765  else{
766  std::cout << "Failed in reading entry " << entry << std::endl;
767  }
768  }
769 
770  entry++;
771  _RooVtxEntryInCurrentInputFile++;
772 
773 
774  return entry_temp;
775 }
776 
777 //********************************************************************
779 //********************************************************************
780 
781  bool bySpillInMC = false;
782 #if VERSION_HAS_OFFICIAL_POT
783  bySpillInMC=true;
784 #endif
785 
786  if (!IsMC || bySpillInMC)
787  // header().IncrementPOTBySpill(*_spill);
788  anaUtils::IncrementPOTBySpill(*_spill,header());
789 }
790 
791 //*****************************************************************************
792 void oaAnalysisTreeConverter::FillInfo(AnaSpill* spill){
793 //*****************************************************************************
794  spill->EventInfo = MakeEventInfo();
795  AnaEventInfo& info = *static_cast<AnaEventInfo*>(spill->EventInfo);
796 
797  info.Run = RunID;
798  info.SubRun = SubrunID;
799  info.Event = EventID;
800  info.IsMC = IsMC;
801  info.EventTime = EventTime;
802  info.SetIsSandMC();
803 
804  spill->InputFileIndex = _currentFileIndex;
805  spill->RooVtxEntry = _RooVtxEntryInCurrentInputFile;
806 
807  spill->DataQuality = MakeDataQuality();
808  spill->Beam = MakeBeam();
809 
810  spill->GeomID = (UInt_t)ND::hgman().GetCurrentGeomID();
811 
812  // beam related information
813  FillBeamInfo(IsMC, static_cast<AnaBeam*>(spill->Beam));
814 
815  // data quality info
816  FillDQInfo(static_cast<AnaDataQuality*>(spill->DataQuality));
817  // trigger information
818  FillTriggerInfo(&(spill->Trigger));
819 
820  // True vertex information
821  FillTrueInfo(spill);
822 
823  // All information about each bunch
824  FillBunchInfo(spill);
825 
826  // After filling both true and reco objects, delete those related to bad true vertices
827  if (!_isUsingReconDirP0DNew) // TODO. Temporarily disabled for P0D native objects since it is giving problems
828  DeleteBadObjects(spill);
829 
830  // Save the number of true tracks and vertices after deleting bad objects
831  spill->NTotalTrueVertices = spill->TrueVertices.size();
832  spill->NTotalTrueParticles = spill->TrueParticles.size();
833 
834  // FGD time bin info
835  FillFgdTimeBinInfo(&(spill->FgdTimeBins));
836 
837  // Delayed clusters info
838  FillDelayedClustersInfo(*spill);
839 
840  // Sort ReconParticles by momentum (to do after filling both spill and bunches)
841  /* TODO
842  std::vector<AnaTrueParticleB*>::iterator itTruePart;
843  for (itTruePart = _spill->TrueParticles.begin(); itTruePart!=_spill->TrueParticles.end(); itTruePart++) {
844  AnaTrueParticle* TruePart = static_cast<AnaTrueParticle*>(*itTruePart);
845  // std::sort(TruePart->ReconParticles.begin(), TruePart->ReconParticles.end(), AnaTrack::CompareMomentum);
846  }
847  */
848 
849  // Sort ReconVertices by PrimaryIndex (to do after filling both spill and bunches)
850  std::vector<AnaTrueVertexB*>::iterator itvtx;
851  for (itvtx = _spill->TrueVertices.begin(); itvtx != _spill->TrueVertices.end(); itvtx++) {
852  AnaTrueVertex* vertex = static_cast<AnaTrueVertex*>(*itvtx);
853  std::sort(vertex->ReconVertices.begin(), vertex->ReconVertices.end(), AnaVertex::ComparePrimaryIndex);
854  }
855 
856 }
857 
858 //*****************************************************************************
859 void oaAnalysisTreeConverter::FillBeamInfo(bool isMC, AnaBeam* beam){
860 //*****************************************************************************
861  beam->POT = 0;
862 #if !VERSION_HAS_OFFICIAL_POT
863  beam->POTCT4 = 0;
864 #endif
865  beam->Spill = ND280Spill;
866  beam->GoodSpill = 1;
867  beam->SpillNumber = 0;
868  beam->BeamRunNumber = 0;
869 
870  if (!isMC) {
871  beam->GoodSpill = 0;
872  if (beamSummaryDataStatus == 1) {
873  ND::TBeamSummaryDataModule::TBeamSummaryData *beamS = (ND::TBeamSummaryDataModule::TBeamSummaryData*) (*beamSummary)[0];
874  if (beamS) {
875  beam->GoodSpill = beamS->GoodSpillFlag;
876 #if VERSION_HAS_OFFICIAL_POT
877  beam->POT = beamS->OfficialProtonsPerSpill;
878 #else
879  beam->POT = beamS->CT5ProtonsPerSpill;
880  beam->POTCT4 = beamS->OtherData.ProtonsPerSpill[3];
881 #endif
882  beam->SpillNumber = beamS->SpillNumber;
883  beam->BeamRunNumber = beamS->BeamRunNumber;
884  } else {
885  std::cout << "WARNING: run " << RunID << ", subrun " << SubrunID << ", event " << EventID
886  << " claims to have beam summary data, but it isn't there! Event will be ignored." << std::endl;
887  }
888  } else if (EventID != -559038737 && ! cosmic_mode && ! _alreadyWarned) {
889  // Warn the user, unless this is an ODB dump, which appears as the first/last "event"
890  // in RDP oaAnalysis files. Event -559038737 is 0xDEADBEEF converted to int.
891 // std::cout << "INFO: run " << RunID << ", subrun " << SubrunID << ", event " << EventID
892  _alreadyWarned = true;
893  std::cout << "INFO: at least one event in this file has no beam summary data."
894  << " These events will be ignored if you are using the event_quality cut." << std::endl;
895  }
896  }
897 #if VERSION_HAS_OFFICIAL_POT
898  else{
899  beam->POT = POTPerSpill;
900  }
901 #endif
902 
903  // In all cases. Keep track of the POT and Number of spills, corresponding to good spills
904  if (beam->GoodSpill){
905  beam->POTSincePreviousSavedSpill = beam->POT;
907  }
908  else{
909  beam->POTSincePreviousSavedSpill = 0;
911  }
912 }
913 
914 //*****************************************************************************
915 void oaAnalysisTreeConverter::FillTriggerInfo(AnaTrigger* tr){
916 //*****************************************************************************
917 
918  tr->FGDCosmic = FGDCosmicEvent;
919  tr->TripTCosmic = TripTCosmicEvent;
920 }
921 
922 //*****************************************************************************
923 void oaAnalysisTreeConverter::FillBunchInfo(AnaSpill* spill){
924 //*****************************************************************************
925 
926  if(_isUsingReconDirTECAL || _isUsingReconDirPECAL || _isUsingReconDirFGDOnly || _isUsingReconDirP0D)
927  spill->OutOfBunch = MakeLocalReconBunch();
928  else if (_isUsingReconDirP0DNew)
929  spill->OutOfBunch = MakeP0DBunch();
930  else
931  spill->OutOfBunch = MakeBunch();
932 
933  spill->OutOfBunch->Bunch = -1;
934 
935  // Distribute all global tracks in bunches
936  GetBunchPIDs();
937 
938  // Distribute all global vertices in bunches
939  GetBunchVertices();
940 
941  // Distribute all local objects in bunches
942  GetBunchLocalObjects();
943 
944  //loop over bunches
945  for (unsigned int ibunch=0; ibunch<NBUNCHES+1; ibunch++) {
946 
947  if ( _bunchPIDs[ibunch].size() == 0 &&
948  _bunchVertices[ibunch].size() == 0 &&
949  _bunchTECALObjects[ibunch].size() == 0 &&
950  _bunchTECALUnmatchedObjects[ibunch].size() == 0 &&
951  _bunchP0DVertices[ibunch].size() == 0 &&
952  _bunchP0DParticles[ibunch].size() == 0 &&
953  _bunchP0DClusters[ibunch].size() == 0) continue;
954 
955  // warnings
956  if ((unsigned int)_bunchPIDs[ibunch].size() > NMAXPARTICLES) {
957  std::cout << "INFO: event " << EventID << " has " << (unsigned int)_bunchPIDs[ibunch].size() << " recon tracks (too many), "
958  << "only the first " << NMAXPARTICLES << " will be stored (=> some warnings might appear)" << std::endl;
959  }
960  if ((unsigned int)_bunchVertices[ibunch].size() > NMAXVERTICES) {
961  std::cout << "INFO: event " << EventID << " has " << (unsigned int)_bunchVertices[ibunch].size() << " recon vertices (too many), "
962  << "only the first " << NMAXVERTICES << " will be stored (=> some warnings might appear)" << std::endl;
963  }
964 
965  // create the bunch
966  AnaBunch* bunch = NULL;
967  if (ibunch < NBUNCHES) {
968  // This is unilateral - what if the saving of p0dRecon output is desired?
969  // An AnaLocalReconBunch is needed, which encapsulates vectors of all types of locally reconstructed objects
970  // but only fills the required ones....
971  if(_isUsingReconDirTECAL || _isUsingReconDirPECAL || _isUsingReconDirFGDOnly || _isUsingReconDirP0D)
972  bunch = static_cast<AnaLocalReconBunch*>(MakeLocalReconBunch());
973  else if (_isUsingReconDirP0DNew)
974  bunch = static_cast<AnaP0DBunch*>(MakeP0DBunch()); // ---- TEST HIGHLAND2-P0D ----
975  else
976  bunch = static_cast<AnaBunch*>(MakeBunch());
977 
978  spill->Bunches.push_back(bunch);
979  bunch->Bunch = ibunch;
980  } else {
981  if(_isUsingReconDirTECAL || _isUsingReconDirPECAL || _isUsingReconDirFGDOnly || _isUsingReconDirP0D)
982  bunch = static_cast<AnaLocalReconBunch*>(spill->OutOfBunch);
983  else if (_isUsingReconDirP0DNew)
984  bunch = static_cast<AnaP0DBunch*>(spill->OutOfBunch); // ---- TEST HIGHLAND2-P0D ----
985  else
986  bunch = static_cast<AnaBunch*>(spill->OutOfBunch);
987  }
988 
989  // Fill PIDs information
990  if(_bunchPIDs[ibunch].size()>0)
991  FillPIDs(bunch, ibunch);
992 
993  // Fill TECALReconObjects information
994  // What does a -ve Bunch mean?
995  if(_isUsingReconDirTECAL && _bunchTECALObjects[ibunch].size()>0)
996  FillTECALReconObjects(bunch, ibunch);
997 
998  // Fill TECALReconUnmatchedObjects information
999  // What does a -ve Bunch mean?
1000  if(_isUsingReconDirTECAL && _bunchTECALUnmatchedObjects[ibunch].size()>0)
1001  FillTECALReconUnmatchedObjects(bunch, ibunch);
1002 
1003  // Fill P0DRecon vertices
1004  if(_isUsingReconDirP0D && _bunchP0DVertices[ibunch].size()>0)
1005  FillP0DReconVertices(bunch, ibunch);
1006 
1007  // Fill P0DRecon particles
1008  if(_isUsingReconDirP0D && _bunchP0DParticles[ibunch].size()>0)
1009  FillP0DReconParticles(bunch, ibunch);
1010 
1011  // Fill P0DRecon clusters
1012  if(_isUsingReconDirP0D && _bunchP0DClusters[ibunch].size()>0)
1013  FillP0DReconClusters(bunch, ibunch);
1014 
1015  // ---- TEST HIGHLAND2-P0D ----
1016  // Fill P0D Bunch recursively, first the top level AlgoResult
1017  if(_isUsingReconDirP0DNew)
1018  FillP0DBunch(bunch, ibunch,_topP0DAlgoRes);
1019  // ----------------------------
1020 
1021  } // End of loop over bunches
1022 
1023  // need to loop again over bunches to fill global vertices
1024  // (allowing the global vertices to point to PIDs in other bunches)
1025  FillGlobalVertices(spill);
1026 
1027 }
1028 
1029 //*****************************************************************************
1030 void oaAnalysisTreeConverter::FillPIDs(AnaBunch* bunch, int ibunch){
1031 //*****************************************************************************
1032 
1033  // loop over global tracks in bunch
1034  unsigned int nTracks = std::min((unsigned int)_bunchPIDs[ibunch].size(), NMAXPARTICLES);
1035  for (unsigned int j=0; j<nTracks; j++) {
1036  ND::TGlobalReconModule::TGlobalPID *globalTrack = _bunchPIDs[ibunch][j];
1037 
1038  // ---- TEST HIGHLAND2-P0D ----
1039  // When the global tracks is a p0d only track, create directly a AnaP0DParticle (which does not contain segments)
1040  // We will most-likely follow a similar strategy for other detectors
1041  AnaParticleB* part = NULL;
1042  if (_isUsingReconDirP0DNew && globalTrack->Detectors==6) {
1043  part = MakeP0DParticle();
1044  // Get the p0d segment in the global PID
1045  ND::TGlobalReconModule::TP0DObject* p0dObjectInGlobal = (ND::TGlobalReconModule::TP0DObject*)(*(globalTrack->P0D))[0];
1046  // Find the P0DReconParticle (from TP0DReconModule with the same Unique ID)
1047  ND::TP0DReconModule::TP0DParticle *p0dParticle = GetP0DReconParticleWithUniqueID(p0dObjectInGlobal->UniqueID);
1048  // Fill info into the P0DParticle
1049  FillP0DParticleInfo(*p0dParticle,static_cast<AnaP0DParticle*>(part));
1050  }
1051  //-----------------------------
1052  else{
1053  part = MakeTrack();
1054  FillTrackInfo(*globalTrack,static_cast<AnaTrack*>(part));
1055  static_cast<AnaTrackB*>(part)->Index = bunch->Particles.size();
1056  }
1057 
1058  // part->Bunch = ibunch; TODO
1059 
1060  bunch->Particles.push_back(part);
1061  }
1062 
1063  // Sort tracks by momentum
1064  // std::sort(bunch->Particles.begin(), bunch->Particles.end(), AnaTrack::CompareMomentum);
1065 
1066 }
1067 
1068 //*****************************************************************************
1069 void oaAnalysisTreeConverter::FillTECALReconObjects(AnaBunch* bunch, int ibunch){
1070 //*****************************************************************************
1071 
1072  // Cast a pointer to AnaLocalReconBunch
1073  AnaLocalReconBunch* localBunch = static_cast<AnaLocalReconBunch*>(bunch);
1074 
1075  // Clear the bunch vectors of AnaTECALReconObjects
1076  localBunch->TECALReconObjects .clear();
1077 
1078  // Loop over all the TECALReconObjects in the event
1079  for (UInt_t iTECAL=0; iTECAL<_bunchTECALObjects[ibunch].size(); ++iTECAL){
1080  ND::TTrackerECALReconModule::TECALReconObject *tecalObj = _bunchTECALObjects[ibunch][iTECAL];
1081 
1082  // Make a pointer to a new AnaTECALReconObject, ready for filling
1083  AnaTECALReconObject *anaTECAL = static_cast<AnaTECALReconObject*>(MakeTECALReconObject());
1084 
1085  // Fill the AnaTECALReconObject with the TECALReconObject information
1086  FillTECALReconObjectInfo(*tecalObj,anaTECAL,localBunch);
1087 
1088  // If this object had an AverageHitTime outside the bunches, the anaTECAL pointer is null
1089  // so don't add it to the bunch or the flat tree.
1090  if(anaTECAL) localBunch->TECALReconObjects.push_back(anaTECAL);
1091 
1092  } // End of loop over TECALReconObjects
1093 
1094 }
1095 
1096 //*****************************************************************************
1097 void oaAnalysisTreeConverter::FillTECALReconUnmatchedObjects(AnaBunch* bunch, int ibunch){
1098 //*****************************************************************************
1099 
1100  // Cast a pointer to AnaLocalReconBunch
1101  AnaLocalReconBunch* localBunch = static_cast<AnaLocalReconBunch*>(bunch);
1102 
1103  // Clear the bunch vectors of AnaTECALUnmatchecObjects
1104  localBunch->TECALUnmatchedObjects.clear();
1105 
1106  // Loop over all the TECALReconUnmatchedObjects in the event
1107  for (UInt_t iTECAL=0; iTECAL<_bunchTECALUnmatchedObjects[ibunch].size(); ++iTECAL){
1108  ND::TTrackerECALReconModule::TECALReconUnmatchedObject *tecalObj = _bunchTECALUnmatchedObjects[ibunch][iTECAL];
1109 
1110  // Make a pointer to a new AnaTECALUnmatchedObject, ready for filling
1111  AnaTECALUnmatchedObject *anaTECAL = static_cast<AnaTECALUnmatchedObject*>(MakeTECALUnmatchedObject());
1112 
1113  // Fill the AnaTECALUnmatchedObject with the TECALReconUnmatchedObject information
1114  FillTECALUnmatchedObjectInfo(*tecalObj,anaTECAL,localBunch);
1115 
1116  // If this object had an AverageHitTime outside the bunches, the anaTECAL pointer is null
1117  // so don't add it to the bunch or the flat tree.
1118  if(anaTECAL) localBunch->TECALUnmatchedObjects.push_back(anaTECAL);
1119 
1120  } // End of loop over TECALReconUnmatchedObjects
1121 
1122 }
1123 
1124 //*****************************************************************************
1125 void oaAnalysisTreeConverter::FillP0DReconVertices(AnaBunch* bunch, int ibunch){
1126 //*****************************************************************************
1127 
1128  // Cast a pointer to AnaLocalReconBunch
1129  AnaLocalReconBunch* localBunch = static_cast<AnaLocalReconBunch*>(bunch);
1130 
1131  // Clear the bunch vectors of AnaP0DReconVertices
1132  localBunch->P0DReconVertices.clear();
1133 
1134  // Loop over all the P0D vertices in the event
1135  for (UInt_t iP0D=0; iP0D<_bunchP0DVertices[ibunch].size(); ++iP0D){
1136  ND::TP0DReconModule::TP0DVertex *p0dVertex = _bunchP0DVertices[ibunch][iP0D];
1137 
1138  // get the highland veranatex from the map
1139  AnaP0DReconVertex *anaP0DRecon = _P0DReconVerticesMap[p0dVertex];
1140 
1141  // Fill the AnaP0DReconVertex with the TP0DVertex information
1142  FillP0DReconVertexInfo(*p0dVertex,anaP0DRecon,localBunch);
1143 
1144  // If this object had a time outside the bunches, the anaP0DRecon pointer is null
1145  // so don't add it to the bunch or the flat tree.
1146  if(anaP0DRecon) localBunch->P0DReconVertices.push_back(anaP0DRecon);
1147 
1148  } // End of loop over P0DReconVertices
1149 
1150 }
1151 
1152 //*****************************************************************************
1153 void oaAnalysisTreeConverter::FillP0DReconParticles(AnaBunch* bunch, int ibunch){
1154 //*****************************************************************************
1155 
1156  // Cast a pointer to AnaLocalReconBunch
1157  AnaLocalReconBunch* localBunch = static_cast<AnaLocalReconBunch*>(bunch);
1158 
1159  // Clear the bunch vectors of AnaP0DReconParticles
1160  localBunch->P0DReconParticles.clear();
1161 
1162  // Loop over all the P0D particles in the event
1163  for (UInt_t iP0D=0; iP0D<_bunchP0DParticles[ibunch].size(); ++iP0D){
1164  ND::TP0DReconModule::TP0DParticle *p0dParticle = _bunchP0DParticles[ibunch][iP0D];
1165 
1166  // get the highland particle from the map
1167  AnaP0DReconParticle *anaP0DRecon = _P0DReconParticlesMap[p0dParticle];
1168  // Fill the AnaP0DReconParticle with the TP0DParticle information
1169  FillP0DReconParticleInfo(*p0dParticle,anaP0DRecon,localBunch);
1170 
1171  // If this object had a time outside the bunches, the anaP0DRecon pointer is null
1172  // so don't add it to the bunch or the flat tree.
1173  if(anaP0DRecon) localBunch->P0DReconParticles.push_back(anaP0DRecon);
1174 
1175  } // End of loop over P0DReconParticles
1176 
1177 }
1178 
1179 //*****************************************************************************
1180 void oaAnalysisTreeConverter::FillP0DReconClusters(AnaBunch* bunch, int ibunch){
1181 //*****************************************************************************
1182 
1183  // Cast a pointer to AnaLocalReconBunch
1184  AnaLocalReconBunch* localBunch = static_cast<AnaLocalReconBunch*>(bunch);
1185 
1186  // Clear the bunch vectors of AnaP0DReconClusters
1187  localBunch->P0DReconClusters.clear();
1188 
1189  // Loop over all the P0D clusters in the event
1190  for (UInt_t iP0D=0; iP0D<_bunchP0DClusters[ibunch].size(); ++iP0D){
1191  ND::TP0DReconModule::TP0DCluster *p0dCluster = _bunchP0DClusters[ibunch][iP0D];
1192 
1193  // get the highland cluster from the map
1194  AnaP0DReconCluster *anaP0D = _P0DReconClustersMap[p0dCluster];
1195 
1196  // Fill the AnaP0DReconCluster with the TP0DCluster information
1197  FillP0DReconClusterInfo(*p0dCluster,anaP0D,localBunch);
1198 
1199  // If this object had a time outside the bunches, the anaP0D pointer is null
1200  // so don't add it to the bunch or the flat tree.
1201  if(anaP0D) localBunch->P0DReconClusters.push_back(anaP0D);
1202 
1203  } // End of loop over P0DReconClusters
1204 
1205 }
1206 
1207 //*****************************************************************************
1208 void oaAnalysisTreeConverter::FillP0DReconVertexInfo(ND::TP0DReconModule::TP0DVertex& p0dVertex, AnaP0DReconVertex* anaP0DReconVertex, AnaLocalReconBunch* anaLocalBunch){
1209 //*****************************************************************************
1210 
1211  FillP0DReconVertexLinks(p0dVertex, anaP0DReconVertex);
1212 
1213  anaP0DReconVertex->Vertices = p0dVertex.Vertices;
1214  anaP0DReconVertex->Particles = p0dVertex.Particles;
1215  anaP0DReconVertex->Tracks = p0dVertex.Tracks;
1216  anaP0DReconVertex->Showers = p0dVertex.Showers;
1217  anaP0DReconVertex->Clusters = p0dVertex.Clusters;
1218  anaP0DReconVertex->Nodes = p0dVertex.Nodes;
1219  anaP0DReconVertex->Hits = p0dVertex.Hits;
1220  anaP0DReconVertex->AlgorithmName = p0dVertex.AlgorithmName;
1221  anaP0DReconVertex->Cycle = p0dVertex.Cycle;
1222  anaP0DReconVertex->NHits = p0dVertex.NHits;
1223  anaP0DReconVertex->UniqueID = p0dVertex.UniqueID;
1224  anaP0DReconVertex->Status = p0dVertex.Status;
1225  anaP0DReconVertex->Quality = p0dVertex.Quality;
1226  anaP0DReconVertex->NDOF = p0dVertex.NDOF;
1227  anaP0DReconVertex->Truth_PrimaryTrajIDs = p0dVertex.Truth_PrimaryTrajIDs;
1228  anaP0DReconVertex->Truth_TrajIDs = p0dVertex.Truth_TrajIDs;
1229  anaP0DReconVertex->Truth_HitCount = p0dVertex.Truth_HitCount;
1230  anaP0DReconVertex->Truth_ChargeShare = p0dVertex.Truth_ChargeShare;
1231  anaUtils::VectorToArray (p0dVertex.Position, anaP0DReconVertex->Position );
1232  anaUtils::VectorToArray (p0dVertex.PosVariance, anaP0DReconVertex->PosVariance);
1233  anaP0DReconVertex->ValidDimensions = p0dVertex.ValidDimensions;
1234  anaP0DReconVertex->Fiducial = p0dVertex.Fiducial;
1235 
1236  anaP0DReconVertex->Bunch = anaLocalBunch->Bunch;
1237 }
1238 
1239 
1240 //*****************************************************************************
1241 void oaAnalysisTreeConverter::FillP0DReconParticleInfo(ND::TP0DReconModule::TP0DParticle& p0dParticle, AnaP0DReconParticle* anaP0DReconParticle, AnaLocalReconBunch* anaLocalBunch){
1242 //*****************************************************************************
1243 
1244  FillP0DReconParticleLinks(p0dParticle, anaP0DReconParticle);
1245 
1246  anaP0DReconParticle->Vertices = p0dParticle.Vertices;
1247  anaP0DReconParticle->Particles = p0dParticle.Particles;
1248  anaP0DReconParticle->Tracks = p0dParticle.Tracks;
1249  anaP0DReconParticle->Showers = p0dParticle.Showers;
1250  anaP0DReconParticle->Clusters = p0dParticle.Clusters;
1251  anaP0DReconParticle->Nodes = p0dParticle.Nodes;
1252  anaP0DReconParticle->Hits = p0dParticle.Hits;
1253  anaP0DReconParticle->AlgorithmName = p0dParticle.AlgorithmName;
1254  anaP0DReconParticle->Cycle = p0dParticle.Cycle;
1255  anaP0DReconParticle->NHits = p0dParticle.NHits;
1256  anaP0DReconParticle->UniqueID = p0dParticle.UniqueID;
1257  anaP0DReconParticle->Status = p0dParticle.Status;
1258  anaP0DReconParticle->Quality = p0dParticle.Quality;
1259  anaP0DReconParticle->NDOF = p0dParticle.NDOF;
1260  anaP0DReconParticle->SideDeposit = p0dParticle.SideDeposit;
1261  anaP0DReconParticle->EndDeposit = p0dParticle.EndDeposit;
1262  anaP0DReconParticle->Truth_PrimaryTrajIDs = p0dParticle.Truth_PrimaryTrajIDs;
1263  anaP0DReconParticle->Truth_TrajIDs = p0dParticle.Truth_TrajIDs;
1264  anaP0DReconParticle->Truth_HitCount = p0dParticle.Truth_HitCount;
1265  anaP0DReconParticle->Truth_ChargeShare = p0dParticle.Truth_ChargeShare;
1266  anaUtils::VectorToArray (p0dParticle.Position, anaP0DReconParticle->Position );
1267  anaUtils::VectorToArray (p0dParticle.PosVariance, anaP0DReconParticle->PosVariance);
1268  anaP0DReconParticle->ValidDimensions = p0dParticle.ValidDimensions;
1269  anaUtils::VectorToArray (p0dParticle.Direction, anaP0DReconParticle->Direction );
1270  anaUtils::VectorToArray (p0dParticle.DirVariance, anaP0DReconParticle->DirVariance );
1271  anaP0DReconParticle->Momentum = p0dParticle.Momentum;
1272  anaP0DReconParticle->Charge = p0dParticle.Charge;
1273  anaP0DReconParticle->realPIDNames = p0dParticle.realPIDNames;
1274  anaP0DReconParticle->realPIDValues = p0dParticle.realPIDValues;
1275  anaP0DReconParticle->integerPIDNames = p0dParticle.integerPIDNames;
1276  anaP0DReconParticle->integerPIDValues = p0dParticle.integerPIDValues;
1277  anaP0DReconParticle->PID = p0dParticle.PID;
1278  anaP0DReconParticle->PID_weight = p0dParticle.PID_weight;
1279 
1280  anaP0DReconParticle->Bunch = anaLocalBunch->Bunch;
1281 
1282  if (p0dParticle.Tracks.size()==1){
1283  ND::TP0DReconModule::TP0DTrack *p0dTrack = (ND::TP0DReconModule::TP0DTrack*) (*P0DReconTracks)[p0dParticle.Tracks[0]];
1284  anaP0DReconParticle->Length = p0dTrack->Length;
1285  anaP0DReconParticle->Clusters = p0dTrack->Clusters;
1286  // anaP0DReconParticle->Nodes = p0dTrack->Nodes;
1287  }
1288  else if (p0dParticle.Tracks.size()>1){
1289  std::cout << "more than 1 track in particle" << std::endl;
1290  }
1291  if (p0dParticle.Showers.size()==1){
1292  ND::TP0DReconModule::TP0DShower *p0dShower = (ND::TP0DReconModule::TP0DShower*) (*P0DReconShowers)[p0dParticle.Showers[0]];
1293  anaP0DReconParticle->EDeposit = p0dShower->EDeposit;
1294  anaP0DReconParticle->Clusters = p0dShower->Clusters;
1295  // std::cout << p0dParticle.Clusters.size() << " " << p0dParticle.Hits.size() << " " << p0dParticle.Nodes.size() << " " << p0dShower->Clusters.size() << " " << p0dShower->Hits.size() << " " << p0dShower->Nodes.size() << std::endl;
1296  }
1297  else if (p0dParticle.Showers.size()>1){
1298  std::cout << "more than 1 shower in particle" << std::endl;
1299  }
1300 
1301 
1302  Float_t max_charge=0;
1303  Int_t max_index=-1;
1304  Float_t total_charge=0;
1305  for (UInt_t i = 0; i<p0dParticle.Truth_PrimaryTrajIDs.size();i++){
1306  if (p0dParticle.Truth_ChargeShare[i] > max_charge){
1307  max_charge = p0dParticle.Truth_ChargeShare[i];
1308  max_index = i;
1309  }
1310  total_charge += p0dParticle.Truth_ChargeShare[i];
1311  /* std::cout << p0dParticle.Truth_PrimaryTrajIDs[i] << " "
1312  << p0dParticle.Truth_TrajIDs[i] << " "
1313  << p0dParticle.Truth_HitCount[i] << " "
1314  << p0dParticle.Truth_ChargeShare[i] <<std::endl;
1315  */
1316  }
1317 
1318  anaP0DReconParticle->TrueParticle=NULL;
1319 
1320  /* Comment out temporarily since it is giving problems if DeleteBadObjects() is called
1321  if (max_index!=-1){
1322  for (std::vector<AnaTrueParticleB*>::iterator it = _spill->TrueParticles.begin(); it!=_spill->TrueParticles.end();it++){
1323  AnaTrueParticleB* trueTrack = *it;
1324 
1325  if (p0dParticle.Truth_TrajIDs[max_index] == trueTrack->ID){
1326  anaP0DReconParticle->TrueParticle = trueTrack;
1327  if (p0dParticle.Truth_ChargeShare[max_index]/total_charge!=0)
1328  static_cast<AnaTrueParticle*>(trueTrack)->Purity = p0dParticle.Truth_ChargeShare[max_index]/total_charge;
1329 
1330  break; // Stop when association is found.
1331  }
1332  }
1333  }
1334  */
1335  /*
1336  for (UInt_t i = 0; i<p0dParticle.realPIDNames.size();i++){
1337  std::cout << i << " (realPID): "
1338  << p0dParticle.realPIDNames[i] << " --> ";
1339  for (UInt_t j = 0; j<p0dParticle.realPIDValues[i].size();j++)
1340  std::cout << p0dParticle.realPIDValues[i][j] << " ";
1341  std::cout << std::endl;
1342  }
1343  for (UInt_t i = 0; i<p0dParticle.integerPIDNames.size();i++){
1344  std::cout << i << " (IntPID): "
1345  << p0dParticle.integerPIDNames[i] << " --> ";
1346  for (UInt_t j = 0; j<p0dParticle.integerPIDValues[i].size();j++)
1347  std::cout << p0dParticle.integerPIDValues[i][j] << " ";
1348  std::cout << std::endl;
1349  }
1350 
1351  for (UInt_t i = 0; i<p0dParticle.PID.size();i++)
1352  std::cout << i << " (PID) : "
1353  << p0dParticle.PID[i] << " "
1354  << p0dParticle.PID_weight[i] << std::endl;
1355  */
1356 
1357 }
1358 
1359 //*****************************************************************************
1360 void oaAnalysisTreeConverter::FillP0DReconClusterInfo(ND::TP0DReconModule::TP0DCluster& p0dCluster, AnaP0DReconCluster* anaP0DReconCluster, AnaLocalReconBunch* anaLocalBunch){
1361 //*****************************************************************************
1362 
1363  FillP0DReconClusterLinks(p0dCluster, anaP0DReconCluster);
1364 
1365  anaP0DReconCluster->Vertices = p0dCluster.Vertices;
1366  anaP0DReconCluster->Particles = p0dCluster.Particles;
1367  anaP0DReconCluster->Tracks = p0dCluster.Tracks;
1368  anaP0DReconCluster->Showers = p0dCluster.Showers;
1369  anaP0DReconCluster->Clusters = p0dCluster.Clusters;
1370  anaP0DReconCluster->Nodes = p0dCluster.Nodes;
1371  anaP0DReconCluster->Hits = p0dCluster.Hits;
1372  anaP0DReconCluster->AlgorithmName = p0dCluster.AlgorithmName;
1373  anaP0DReconCluster->Cycle = p0dCluster.Cycle;
1374  anaP0DReconCluster->NHits = p0dCluster.NHits;
1375  anaP0DReconCluster->UniqueID = p0dCluster.UniqueID;
1376  anaP0DReconCluster->Truth_PrimaryTrajIDs = p0dCluster.Truth_PrimaryTrajIDs;
1377  anaP0DReconCluster->Truth_TrajIDs = p0dCluster.Truth_TrajIDs;
1378  anaP0DReconCluster->Truth_HitCount = p0dCluster.Truth_HitCount;
1379  anaP0DReconCluster->Truth_ChargeShare = p0dCluster.Truth_ChargeShare;
1380  anaUtils::VectorToArray (p0dCluster.Position, anaP0DReconCluster->Position );
1381  anaUtils::VectorToArray (p0dCluster.PosVariance, anaP0DReconCluster->PosVariance);
1382  anaP0DReconCluster->ValidDimensions = p0dCluster.ValidDimensions;
1383  anaP0DReconCluster->NFiducialHits = p0dCluster.NFiducialHits;
1384  anaP0DReconCluster->EDeposit = p0dCluster.EDeposit;
1385 
1386 
1387  anaP0DReconCluster->Bunch = anaLocalBunch->Bunch;
1388 
1389 }
1390 
1391 //*****************************************************************************
1392 void oaAnalysisTreeConverter::FillP0DReconVertexLinks(ND::TP0DReconModule::TP0DVertex& p0dVertex, AnaP0DReconVertex* anaP0DReconVertex){
1393 //*****************************************************************************
1394 
1395 
1396  for (UInt_t i=0;i<p0dVertex.Vertices.size();i++){
1397  ND::TP0DReconModule::TP0DVertex *p0dVertex2 = (ND::TP0DReconModule::TP0DVertex*) (*P0DReconVertices)[p0dVertex.Vertices[i]];
1398  anaP0DReconVertex->VerticesP.push_back(_P0DReconVerticesMap[p0dVertex2]);
1399  }
1400 
1401  for (UInt_t i=0;i<p0dVertex.Particles.size();i++){
1402  ND::TP0DReconModule::TP0DParticle *p0dParticle2 = (ND::TP0DReconModule::TP0DParticle*) (*P0DReconParticles)[p0dVertex.Particles[i]];
1403  anaP0DReconVertex->ParticlesP.push_back(_P0DReconParticlesMap[p0dParticle2]);
1404  }
1405 
1406  for (UInt_t i=0;i<p0dVertex.Clusters.size();i++){
1407  ND::TP0DReconModule::TP0DCluster *p0dCluster2 = (ND::TP0DReconModule::TP0DCluster*) (*P0DReconClusters)[p0dVertex.Clusters[i]];
1408  anaP0DReconVertex->ClustersP.push_back(_P0DReconClustersMap[p0dCluster2]);
1409  }
1410 
1411 }
1412 
1413 //*****************************************************************************
1414 void oaAnalysisTreeConverter::FillP0DReconParticleLinks(ND::TP0DReconModule::TP0DParticle& p0dParticle, AnaP0DReconParticle* anaP0DReconParticle){
1415 //*****************************************************************************
1416 
1417  for (UInt_t i=0;i<p0dParticle.Vertices.size();i++){
1418  ND::TP0DReconModule::TP0DVertex *p0dVertex2 = (ND::TP0DReconModule::TP0DVertex*) (*P0DReconVertices)[p0dParticle.Vertices[i]];
1419  anaP0DReconParticle->VerticesP.push_back(_P0DReconVerticesMap[p0dVertex2]);
1420  }
1421 
1422  for (UInt_t i=0;i<p0dParticle.Particles.size();i++){
1423  ND::TP0DReconModule::TP0DParticle *p0dParticle2 = (ND::TP0DReconModule::TP0DParticle*) (*P0DReconParticles)[p0dParticle.Particles[i]];
1424  anaP0DReconParticle->ParticlesP.push_back(_P0DReconParticlesMap[p0dParticle2]);
1425  }
1426 
1427  for (UInt_t i=0;i<p0dParticle.Clusters.size();i++){
1428  ND::TP0DReconModule::TP0DCluster *p0dCluster2 = (ND::TP0DReconModule::TP0DCluster*) (*P0DReconClusters)[p0dParticle.Clusters[i]];
1429  anaP0DReconParticle->ClustersP.push_back(_P0DReconClustersMap[p0dCluster2]);
1430  }
1431 
1432 }
1433 
1434 //*****************************************************************************
1435 void oaAnalysisTreeConverter::FillP0DReconClusterLinks(ND::TP0DReconModule::TP0DCluster& p0dCluster, AnaP0DReconCluster* anaP0DReconCluster){
1436 //*****************************************************************************
1437 
1438  for (UInt_t i=0;i<p0dCluster.Vertices.size();i++){
1439  ND::TP0DReconModule::TP0DVertex *p0dVertex2 = (ND::TP0DReconModule::TP0DVertex*) (*P0DReconVertices)[p0dCluster.Vertices[i]];
1440  anaP0DReconCluster->VerticesP.push_back(_P0DReconVerticesMap[p0dVertex2]);
1441  }
1442 
1443  for (UInt_t i=0;i<p0dCluster.Particles.size();i++){
1444  ND::TP0DReconModule::TP0DParticle *p0dParticle2 = (ND::TP0DReconModule::TP0DParticle*) (*P0DReconParticles)[p0dCluster.Particles[i]];
1445  anaP0DReconCluster->ParticlesP.push_back(_P0DReconParticlesMap[p0dParticle2]);
1446  }
1447 
1448  for (UInt_t i=0;i<p0dCluster.Clusters.size();i++){
1449  ND::TP0DReconModule::TP0DCluster *p0dCluster2 = (ND::TP0DReconModule::TP0DCluster*) (*P0DReconClusters)[p0dCluster.Clusters[i]];
1450  anaP0DReconCluster->ClustersP.push_back(_P0DReconClustersMap[p0dCluster2]);
1451  }
1452 
1453 }
1454 
1455 //*****************************************************************************
1456 void oaAnalysisTreeConverter::FillGlobalVertices(AnaSpill* spill){
1457 //*****************************************************************************
1458 
1459  // need to loop again over bunches to fill global vertices
1460  // (allowing the global vertices to point to PIDs in other bunches)
1461  for (unsigned int ibunch=0; ibunch<NBUNCHES+1; ibunch++) {
1462 
1463  if (_bunchVertices[ibunch].size() == 0) continue;
1464 
1465  // Find the pointer to the right bunch
1466  AnaBunch* bunch = 0;
1467  if (ibunch == NBUNCHES) bunch = static_cast<AnaBunch*>(spill->OutOfBunch);
1468  else {
1469  std::vector<AnaBunchC*>::iterator itbunch;
1470  for (itbunch = spill->Bunches.begin(); itbunch != spill->Bunches.end(); itbunch++) {
1471  if (ibunch == (unsigned int)(*itbunch)->Bunch) {
1472  bunch = static_cast<AnaBunch*>(*itbunch);
1473  break;
1474  }
1475  }
1476  }
1477  if ( ! bunch)
1478  std::cout << "ERROR 1102 in oaAnalysisConverter: looking for a bunch not created!" << std::endl;
1479 
1480  // loop over global vertex in bunch
1481  unsigned int nVertices = std::min((unsigned int)_bunchVertices[ibunch].size(), NMAXVERTICES);
1482  for (unsigned int j=0; j<nVertices; j++) {
1483  ND::TGlobalReconModule::TGlobalVertex *globalVertex = _bunchVertices[ibunch][j];
1484  AnaVertex* vertex = static_cast<AnaVertex*>(MakeVertex());
1485  FillVertexInfo(*globalVertex, vertex, bunch, spill);
1486  bunch->Vertices.push_back(vertex);
1487  }
1488 
1489  // Sort vertices by PrimaryIndex
1490  std::sort(bunch->Vertices.begin(), bunch->Vertices.end(), AnaVertex::ComparePrimaryIndex);
1491 
1492  } // End of loop over bunches
1493 
1494 }
1495 
1496 //*****************************************************************************
1497 void oaAnalysisTreeConverter::FillFgdTimeBinInfo(std::vector<AnaFgdTimeBinB*>* AnaFgdTimeBins){
1498 //*****************************************************************************
1499 
1500  //loop over bunches
1501  for(Int_t ibin=0; ibin<NFgdTimeBins; ibin++) {
1502 
1503  ND::TGlobalReconModule::TFgdTimeBin *bin=(ND::TGlobalReconModule::TFgdTimeBin*)(*(FgdTimeBins))[ibin];
1504  if(!bin) continue;
1505 
1506  if (AnaFgdTimeBins->size()>=NMAXFGDTIMEBINS)
1507  break;
1508 
1509 
1510  AnaFgdTimeBin* abin = static_cast<AnaFgdTimeBin*>(MakeFgdTimeBin());
1511  AnaFgdTimeBins->push_back(abin);
1512 
1513 
1514  abin->MinTime = bin->minTime;
1515  abin->MaxTime = bin->maxTime;
1516  abin->G4ID = bin->g4ID;
1517 
1518  for (int i=0;i<2;i++){
1519  abin->NHits[i] = bin->nHits[i];
1520  abin->RawChargeSum[i] = bin->rawChargeSum[i];
1521  }
1522  }
1523 }
1524 
1525 //*****************************************************************************
1526 void oaAnalysisTreeConverter::FillTECALReconObjectInfo(ND::TTrackerECALReconModule::TECALReconObject& tecalReconObject, AnaTECALReconObject *anaTECALReconObject, AnaLocalReconBunch *anaLocalBunch){
1527 //*****************************************************************************
1528 
1529  anaTECALReconObject->AverageHitTime = tecalReconObject.AverageHitTime;
1530  anaTECALReconObject->AverageZPos = tecalReconObject.AverageZPosition;
1531  anaTECALReconObject->Containment = tecalReconObject.Containment;
1532  anaTECALReconObject->EFitResult = tecalReconObject.EMEnergyFit_Result;
1533  anaTECALReconObject->EFitUncertainty = tecalReconObject.EMEnergyFit_Uncertainty;
1534 
1535 #if !VERSION_PROD7_DEVEL
1536  anaTECALReconObject->FirstLayer = tecalReconObject.FirstLayer;
1537  anaTECALReconObject->IsShowerLike = tecalReconObject.IsShowerLike;
1538  anaTECALReconObject->IsTrackLike = tecalReconObject.IsTrackLike;
1539  anaTECALReconObject->LastLayer = tecalReconObject.LastLayer;
1540  anaTECALReconObject->MichelTagNDelayedCluster = tecalReconObject.MElectronTag_NDelayedCluster;
1541  anaTECALReconObject->PIDAMR = tecalReconObject.PID_AMR;
1542  anaTECALReconObject->PIDMaxRatio = tecalReconObject.PID_Max_Ratio;
1543  anaTECALReconObject->PIDMeanPos = tecalReconObject.PID_MeanPosition;
1544  anaTECALReconObject->PIDShowerWidth = tecalReconObject.PID_ShowerWidth;
1545  anaTECALReconObject->TimeBunch = tecalReconObject.TimeBunch;
1546 #endif
1547 
1548 #if VERSION_HAS_ECAL_LLR
1549  anaTECALReconObject->LikeEMHIP = tecalReconObject.PID_LLR_EM_HIP;
1550  anaTECALReconObject->LikeMIPEM = tecalReconObject.PID_LLR_MIP_EM;
1551  anaTECALReconObject->LikeMIPEMLow = tecalReconObject.PID_LLR_MIP_EM_LowMomentum;
1552  anaTECALReconObject->LikeMIPPion = tecalReconObject.PID_LLR_MIP_Pion;
1553 #endif
1554 
1555  anaTECALReconObject->MatchingLike = tecalReconObject.MatchingLikelihood;
1556  anaTECALReconObject->Module = tecalReconObject.Module;
1557  anaTECALReconObject->MostDownStreamLayerHit = tecalReconObject.mostDownStreamLayerHit;
1558  anaTECALReconObject->MostUpStreamLayerHit = tecalReconObject.mostUpStreamLayerHit;
1559  anaTECALReconObject->NHits = tecalReconObject.NHits;
1560  anaTECALReconObject->NLayersHit = tecalReconObject.NLayersHit;
1561  anaTECALReconObject->ObjectLength = tecalReconObject.ObjectLength;
1562  anaTECALReconObject->PIDAngle = tecalReconObject.PID_Angle;
1563  anaTECALReconObject->PIDAsymmetry = tecalReconObject.PID_Asymmetry;
1564  anaTECALReconObject->PIDCircularity = tecalReconObject.PID_Circularity;
1565  anaTECALReconObject->PIDFBR = tecalReconObject.PID_FrontBackRatio;
1566  anaTECALReconObject->PIDShowerAngle = tecalReconObject.PID_ShowerAngle;
1567  anaTECALReconObject->PIDTransverseChargeRatio = tecalReconObject.PID_TransverseChargeRatio;
1568  anaTECALReconObject->PIDTruncatedMaxRatio = tecalReconObject.PID_TruncatedMaxRatio;
1569  anaUtils::VectorToArray (tecalReconObject.Pointing, anaTECALReconObject->Pointing );
1570  anaTECALReconObject->Thrust = tecalReconObject.Thrust;
1571  anaUtils::VectorToArray (tecalReconObject.ThrustAxis, anaTECALReconObject->ThrustAxis );
1572  anaUtils::VectorToArray (tecalReconObject.ThrustOrigin, anaTECALReconObject->ThrustOrigin);
1573  anaTECALReconObject->TotalHitCharge = tecalReconObject.TotalHitCharge;
1574  anaTECALReconObject->TrueID = tecalReconObject.G4ID;
1575  anaTECALReconObject->TrueIDPrimary = tecalReconObject.G4ID_Primary;
1576  anaTECALReconObject->TrueIDRecursive = tecalReconObject.G4ID_Recursive;
1577  anaTECALReconObject->TrueIDSingle = tecalReconObject.G4ID_Single;
1578  anaTECALReconObject->UniqueID = tecalReconObject.UniqueID;
1579 
1580  anaTECALReconObject->Bunch = anaLocalBunch->Bunch;
1581 
1582 }
1583 
1584 //*****************************************************************************
1585 void oaAnalysisTreeConverter::FillTECALUnmatchedObjectInfo(ND::TTrackerECALReconModule::TECALReconUnmatchedObject& tecalUnmatchedObject, AnaTECALUnmatchedObject* anaTECALUnmatchedObject, AnaLocalReconBunch* anaLocalBunch){
1586 //*****************************************************************************
1587 
1588  anaTECALUnmatchedObject->AverageHitTime = tecalUnmatchedObject.AverageHitTime;
1589  anaUtils::VectorToArray (tecalUnmatchedObject.BackPosition, anaTECALUnmatchedObject->BackPos );
1590  anaUtils::VectorToArray (tecalUnmatchedObject.FrontPosition, anaTECALUnmatchedObject->FrontPos);
1591  anaTECALUnmatchedObject->MostDownStreamLayerHit = tecalUnmatchedObject.mostDownStreamLayerHit;
1592  anaTECALUnmatchedObject->MostUpStreamLayerHit = tecalUnmatchedObject.mostUpStreamLayerHit;
1593  anaTECALUnmatchedObject->NHits = tecalUnmatchedObject.NHits;
1594  anaTECALUnmatchedObject->TotalHitCharge = tecalUnmatchedObject.TotalHitCharge;
1595  anaTECALUnmatchedObject->TrueID = tecalUnmatchedObject.G4ID;
1596  anaTECALUnmatchedObject->TrueIDPrimary = tecalUnmatchedObject.G4ID_Primary;
1597  anaTECALUnmatchedObject->TrueIDRecursive = tecalUnmatchedObject.G4ID_Recursive;
1598  anaTECALUnmatchedObject->TrueIDSingle = tecalUnmatchedObject.G4ID_Single;
1599  anaTECALUnmatchedObject->View = tecalUnmatchedObject.View;
1600 
1601  anaTECALUnmatchedObject->Bunch = anaLocalBunch->Bunch;
1602 }
1603 
1604 
1605 
1606 //*****************************************************************************
1607 void oaAnalysisTreeConverter::FillDQInfo(AnaDataQuality* dq){
1608 //*****************************************************************************
1609 
1610  if (fND280OffFlag)
1611  dq->GoodDaq = false;
1612  else
1613  dq->GoodDaq = true;
1614 
1615  dq->ND280Flag = fND280OffFlag;
1616 
1617  dq->DetFlag[0] = fTPCFlag;
1618  dq->DetFlag[1] = fFGDFlag;
1619  dq->DetFlag[2] = fECALFlag;
1620  dq->DetFlag[3] = fDSECALFlag;
1621  dq->DetFlag[4] = fP0DFlag;
1622  dq->DetFlag[5] = fSMRDFlag;
1623  dq->DetFlag[6] = fMAGNETFlag;
1624 
1625 
1626 }
1627 
1628 //*****************************************************************************
1629 void oaAnalysisTreeConverter::FillTrackInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1630 //*****************************************************************************
1631 
1632  //-------------- Global info
1633  track->UniqueID = globalTrack.UniqueID;
1634  track->Status = globalTrack.Status;
1635  track->NNodes = globalTrack.NNodes;
1636  track->NHits = globalTrack.NHits;
1637  track->NNodes = globalTrack.NNodes;
1638  track->NDOF = globalTrack.NDOF;
1639  track->Chi2 = globalTrack.Chi2;
1640  track->Detectors = globalTrack.Detectors;
1641  track->Length = globalTrack.Length;
1642  track->Momentum = globalTrack.FrontMomentum;
1643  track->MomentumError = globalTrack.FrontMomentumError;
1644  track->Charge = globalTrack.Charge;
1645  anaUtils::VectorToArray(globalTrack.FrontDirection, track->DirectionStart);
1646  anaUtils::VectorToArray(globalTrack.BackDirection, track->DirectionEnd);
1647  anaUtils::VectorToArray(globalTrack.FrontPosition, track->PositionStart);
1648  anaUtils::VectorToArray(globalTrack.BackPosition, track->PositionEnd);
1649 
1650  FillTrackHits(globalTrack, track);
1651 
1652  track->MomentumEle = -10000;
1653  track->MomentumMuon = -10000;
1654  track->MomentumProton = -10000;
1655  track->MomentumErrorEle = -10000;
1656  track->MomentumErrorMuon = -10000;
1657  track->MomentumErrorProton = -10000;
1658 
1659 #if VERSION_HAS_PRANGE_ESTIMATES
1660  track->RangeMomentumEle = -10000;
1661  track->RangeMomentumMuon = -10000;
1662  track->RangeMomentumProton = -10000;
1663 
1664  track->RangeMomentumMuonFlip = -10000;
1665  track->RangeMomentumProtonFlip = -10000;
1666 #endif
1667 
1668  // get the PID of the main track
1669  std::map<double, int, std::greater<double> > map_pid;
1670 
1671  for (int i=0; i < (int)globalTrack.PIDWeights.size(); i++)
1672  map_pid[globalTrack.PIDWeights[i]] = globalTrack.ParticleIds[i];
1673 
1674  if (map_pid.size() > 0 )
1675  track->ReconPDG = map_pid.begin()->second;
1676 
1677 
1678 
1679  //----------------- Alternate fits assuming a given particle hypothesis
1680  for (int jj = 0; jj < globalTrack.NAlternates; jj++) {
1681  ND::TGlobalReconModule::TGlobalPIDAlternate *alt = (ND::TGlobalReconModule::TGlobalPIDAlternate*)(*(globalTrack.Alternates))[jj];
1682  if(!alt) continue;
1683 
1684  bool samedir = true;
1685 
1686 #if VERSION_HAS_REVERSED_REFITS
1687  // P6 files have refits in the backwards direction too. For now,
1688  // we just save the info about the fit in the same direction as
1689  // the default fit. In future, we may want to save the reversed
1690  // info too.
1691  samedir = ((alt->FrontDirection[2] < 0 && track->DirectionStart[2] < 0) || (alt->FrontDirection[2] >= 0 && track->DirectionStart[2] >= 0));
1692 
1693  if (!samedir && map_pid.size() > 0){
1694 
1695  // Fill the momentum and direction for the main PID hypothesis and reversed sense
1696  if (alt->ParticleId == map_pid.begin()->second){
1697  track->MomentumFlip = alt->FrontMomentum;
1698  anaUtils::VectorToArray( alt->FrontDirection, track->DirectionStartFlip);
1699  anaUtils::VectorToArray( alt->FrontDirection, track->DirectionEndFlip);
1700  }
1701 
1702  }
1703 
1704 #endif
1705 
1706  if (alt->ParticleId == 11 && samedir) {
1707  track->MomentumEle = alt->FrontMomentum;
1708  track->MomentumErrorEle = alt->FrontMomentumError;
1709  } else if (alt->ParticleId == 13 && samedir) {
1710  track->MomentumMuon = alt->FrontMomentum;
1711  track->MomentumErrorMuon = alt->FrontMomentumError;
1712  } else if (alt->ParticleId == 2212 && samedir) {
1713  track->MomentumProton = alt->FrontMomentum;
1714  track->MomentumErrorProton = alt->FrontMomentumError;
1715  }
1716 
1717  }
1718 
1719 #if VERSION_HAS_PRANGE_ESTIMATES
1720  // P6 files have momentum from range estimates for
1721  // three PID hypothesis and in the backwards direction too (six in total). For now,
1722  // we save the three values that correspond to the "original" reconstructed direction of the track
1723  track->RangeMomentumEle = globalTrack.RangeMomentumElectron;
1724  track->RangeMomentumMuon = globalTrack.RangeMomentumMuon;
1725  track->RangeMomentumProton = globalTrack.RangeMomentumProton;
1726 
1727  track->RangeMomentumMuonFlip = globalTrack.RangeMomentumMuonFlip;
1728  track->RangeMomentumProtonFlip = globalTrack.RangeMomentumProtonFlip;
1729 #endif
1730 
1731 #if VERSION_HAS_TIME_FITS
1732  for (unsigned int i=0;i<globalTrack.NodeTimes.size();i++){
1733 
1734  AnaTimeNode* node = new AnaTimeNode();
1735 
1736  node->Detector = globalTrack.NodeTimes[i].first;
1737  node->TimeStart = globalTrack.NodeTimes[i].second.X();
1738  node->TimeEnd = globalTrack.NodeTimes[i].second.Y();
1739 
1740  track->TimeNodes.push_back(node);
1741  }
1742 
1743  track->ToF.Flag_FGD1_FGD2 = false;
1744  track->ToF.Flag_P0D_FGD1 = false;
1745  track->ToF.Flag_ECal_FGD1 = false;
1746  track->ToF.Flag_ECal_FGD2 = false;
1747  track->ToF.Flag_DSECal_FGD2 = false;
1748 
1749  bool fgd1 = false, fgd2 = false, p0d = false, ecal = false, dsecal = false;
1750  float tfgd1 = 0, tfgd2 = 0, tp0d = 0, tecal = 0, tdsecal = 0;
1751 
1752  for (unsigned int i=0;i<globalTrack.NodeTimes.size();i++){
1753  double t = ( globalTrack.NodeTimes[i].second.X()+globalTrack.NodeTimes[i].second.Y() )/2.0;
1754  switch( globalTrack.NodeTimes[i].first ){
1755  case 4:
1756  if(!fgd1){tfgd1 = t;}
1757  fgd1 = true;
1758  break;
1759  case 5:
1760  if(!fgd2){tfgd2 = t;}
1761  fgd2 = true;
1762  break;
1763  case 6:
1764  if(!p0d){tp0d = t;}
1765  p0d = true;
1766  break;
1767  case 7:
1768  if(!dsecal){tdsecal = t;}
1769  dsecal = true;
1770  break;
1771  case 9:
1772  if(!ecal){tecal = t;}//take the first ecal, there can be two (example : cosmics)
1773  ecal = true;
1774  break;
1775  }
1776  }
1777 
1778  if(fgd1 && fgd2){
1779  track->ToF.Flag_FGD1_FGD2 = true;
1780  track->ToF.FGD1_FGD2 = tfgd1-tfgd2;
1781  }else{track->ToF.Flag_FGD1_FGD2 = false;}
1782  if(fgd1 && p0d){
1783  track->ToF.Flag_P0D_FGD1 = true;
1784  track->ToF.P0D_FGD1 = tp0d-tfgd1;
1785  }else{track->ToF.Flag_P0D_FGD1 = false;}
1786  if(fgd1 && ecal){
1787  track->ToF.Flag_ECal_FGD1 = true;
1788  track->ToF.ECal_FGD1 = tecal-tfgd1;
1789  }else{track->ToF.Flag_ECal_FGD1 = false;}
1790  if(fgd2 && dsecal){
1791  track->ToF.Flag_DSECal_FGD2 = true;
1792  track->ToF.DSECal_FGD2 = tdsecal-tfgd2;
1793  }else{track->ToF.Flag_DSECal_FGD2 = false;}
1794  if(fgd2 && ecal){
1795  track->ToF.Flag_ECal_FGD2 = true;
1796  track->ToF.ECal_FGD2 = tecal-tfgd2;
1797  }else{track->ToF.Flag_ECal_FGD2 = false;}
1798 
1799 #endif
1800 
1801  convUtils::ConvertTrackDetEnumToBitField(track->Detector, globalTrack.DetectorUsed);
1802 
1803 
1804  //-------------- Subdetector Constituents
1805 
1806  FillTpcInfo(globalTrack, track);
1807  FillFgdInfo(globalTrack, track);
1808  FillEcalInfo(globalTrack, track);
1809  FillSmrdInfo(globalTrack, track);
1810  FillP0dInfo(globalTrack, track);
1811  FillTrackerInfo(globalTrack, track);
1812 
1813  // Make truth-reco association
1814  FillTrueParticleRecoInfo(globalTrack.TrueParticle, track->TrueObject, true);
1815 
1816  // Save all recon tracks associated to this true track
1817  if (track->TrueObject){
1818  AnaTrueParticle* trueParticle = static_cast<AnaTrueParticle*>(track->TrueObject);
1819  trueParticle->ReconParticles.push_back(track);
1820 
1821 #ifdef DEBUG
1822  if(trueParticle->IsTruePrimaryPi0DecayPhoton)
1823  std::cout<<"oaAnalysisTreeConverter::FillTrackInfo() found a track from globalPID with UniqueID:"<<globalTrack.UniqueID
1824  <<" and appended it to ReconParticles for true pi0 decay photon with ID:"<<trueParticle->ID
1825  <<std::endl;
1826 #endif
1827 
1828 
1829  if (track->GetTrueParticle()->TrueVertex){
1830  // Save all recon tracks associated to this true vertex (track without truth association might be missing here)
1831  static_cast<AnaTrueVertex*>(track->GetTrueParticle()->TrueVertex)->ReconParticles.push_back(track);
1832 
1833  }
1834  }
1835 }
1836 
1837 //*****************************************************************************
1838 void oaAnalysisTreeConverter::FillTrackHits(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1839 //*****************************************************************************
1840 
1841  // Fill the first 2 more upstream and the first 2 more downstream hits
1842 
1843  if (globalTrack.NHitsSaved == 0) return;
1844 
1845  int ihit=0;
1846  int prevtype, thistype;
1847  ND::TGlobalReconModule::TGlobalHit* hit;
1848  // Upstream hit(s)
1849  hit = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[ihit];
1850  track->UpstreamHits_Position[0] = hit->Position;
1851  track->UpstreamHits_Charge[0] = hit->Charge;
1852  prevtype = hit->Type % 100; // ##1 has X info, #1# has Y info, 1## has Z info
1853  if (globalTrack.NHitsSaved == 4 && prevtype==11) std::cout << "Minor error in oaAnalysisConverter::FillTrackHits (ref. 4833)\n";
1854 
1855  // if X or Y info are missing, another upstream hit with the missing info is stored (if found)
1856  // if 3 HitsSaved, the 2nd is the second upstream or the first downstream?
1857  // Check if it is more downstream than the 3rd (and last) hit
1858  bool anotherupstream = false;
1859  if (globalTrack.NHitsSaved == 3 && prevtype != 11) {
1860  ND::TGlobalReconModule::TGlobalHit* hit1 = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[1];
1861  ND::TGlobalReconModule::TGlobalHit* hit2 = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[2];
1862  if (hit1->Position.Z() < hit2->Position.Z()) anotherupstream = true;
1863  // if same Z and the first has both X and Y info, it has to be another upstream
1864  if (hit1->Position.Z() == hit2->Position.Z() && (hit1->Type % 100) == 11) anotherupstream = true;
1865  // otherwise, if same Z, we don't know (in TGlobalReconModule hits are only sorted by Z)
1866  // and sometimes it happens (for very short tracks, so that also the first upstream is very near)
1867 // if (hit1->Position.Z() == hit2->Position.Z() && (hit1->Type % 100) != 11)
1868 // std::cout << "Minor error in oaAnalysisConverter (ref. 4834) with deltaZ = " << hit2->Position.Z() - hit1->Position.Z() << "\n";
1869  }
1870 
1871  if (globalTrack.NHitsSaved == 4 || anotherupstream) {
1872  hit = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[++ihit];
1873  track->UpstreamHits_Position[1] = hit->Position;
1874  track->UpstreamHits_Charge[1] = hit->Charge;
1875  thistype = hit->Type % 100;
1876  if (prevtype == thistype) std::cout << "Minor error in oaAnalysisConverter::FillTrackHits (ref. 4835) " << prevtype << " vs " << thistype << "\n";
1877  }
1878 
1879  // Downstream hit(s)
1880  hit = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[++ihit];
1881  track->DownstreamHits_Position[0] = hit->Position;
1882  track->DownstreamHits_Charge[0] = hit->Charge;
1883  prevtype = hit->Type % 100;
1884 
1885  // if X or Y info are missing, another downstream hit is stored (if found)
1886  if (ihit == globalTrack.NHitsSaved-1) return;
1887  if (prevtype==11) std::cout << "Minor error in oaAnalysisConverter::FillTrackHits (ref. 4836) " << ihit << " vs " << globalTrack.NHitsSaved << " and " << anotherupstream << "\n";
1888  hit = (ND::TGlobalReconModule::TGlobalHit*)(*(globalTrack.HitsSaved))[++ihit];
1889  track->DownstreamHits_Position[1] = hit->Position;
1890  track->DownstreamHits_Charge[1] = hit->Charge;
1891  thistype = hit->Type % 100;
1892  if (prevtype == thistype) std::cout << "Minor error in oaAnalysisConverter::FillTrackHits (ref. 4837) \n";
1893 
1894  if (ihit != globalTrack.NHitsSaved-1) std::cout << "Minor error in oaAnalysisConverter::FillTrackHits (ref. 4838) \n";
1895 }
1896 
1897 //*****************************************************************************
1898 void oaAnalysisTreeConverter::FillTpcInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1899 //*****************************************************************************
1900  track->nTPCSegments=0;
1901 
1902  std::vector<ND::TGlobalReconModule::TTPCObject*> tpcObjects;
1903 
1904  tpcObjects.reserve((unsigned int)globalTrack.NTPCs);
1905 
1906 
1907  for(int jj = 0; jj < globalTrack.NTPCs; jj++){
1908  ND::TGlobalReconModule::TTPCObject *tpcTrack=(ND::TGlobalReconModule::TTPCObject*)(*(globalTrack.TPC))[jj];
1909  if(!tpcTrack) continue;
1910  tpcObjects.push_back(tpcTrack);
1911  }
1912 
1913  //sort in decreasing NNodes order
1914  std::sort(tpcObjects.begin(), tpcObjects.end(), CompareNNodes);
1915 
1916  int nObjects = std::min((unsigned int)tpcObjects.size(), NMAXTPCS);
1917  for(int jj = 0; jj < nObjects; jj++){
1918  ND::TGlobalReconModule::TTPCObject *tpcTrack=tpcObjects[jj];
1919 
1920  AnaTPCParticle* seg = static_cast<AnaTPCParticle*>(MakeTpcTrack());
1921  FillTpcTrackInfo( *tpcTrack, seg);
1922  track->TPCSegments[track->nTPCSegments++] = seg;
1923  }
1924 }
1925 
1926 //*****************************************************************************
1927 void oaAnalysisTreeConverter::FillFgdInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1928 //*****************************************************************************
1929  track->nFGDSegments=0;
1930  for(int jj = 0; jj < globalTrack.NFGDs; jj++){
1931  if((unsigned int)track->nFGDSegments == NMAXFGDS)
1932  break;
1933 
1934  ND::TGlobalReconModule::TFGDObject *fgdTrack=(ND::TGlobalReconModule::TFGDObject*)(*(globalTrack.FGD))[jj];
1935  if(!fgdTrack) continue;
1936 
1937  AnaFGDParticle* seg = static_cast<AnaFGDParticle*>(MakeFgdTrack());
1938  FillFgdTrackInfo( *fgdTrack, seg);
1939  track->FGDSegments[track->nFGDSegments++] = seg;
1940  }
1941 }
1942 
1943 //*****************************************************************************
1944 void oaAnalysisTreeConverter::FillEcalInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1945 //*****************************************************************************
1946  track->nECALSegments=0;
1947 
1948  // Fill Tracker ECAL and DsEcal
1949  for(int jj = 0; jj < globalTrack.NECALs; jj++){
1950  if((unsigned int)track->nECALSegments==NMAXECALS)
1951  break;
1952 
1953  ND::TGlobalReconModule::TECALObject *ecalTrack=(ND::TGlobalReconModule::TECALObject*)(*(globalTrack.ECAL))[jj];
1954  if(!ecalTrack) continue;
1955 
1956  AnaECALParticle* seg = static_cast<AnaECALParticle*>(MakeEcalTrack());
1957  FillEcalTrackInfo( *ecalTrack, seg);
1958  track->ECALSegments[track->nECALSegments++] = seg;
1959  }
1960 
1961  // Fill P0DEcal
1962  for(int jj = 0; jj < globalTrack.NP0DECALs; jj++){
1963  if((unsigned int)track->nECALSegments==NMAXECALS)
1964  break;
1965 
1966  ND::TGlobalReconModule::TECALObject *ecalTrack=(ND::TGlobalReconModule::TECALObject*)(*(globalTrack.P0DECAL))[jj];
1967  if(!ecalTrack) continue;
1968 
1969  AnaECALParticle* seg = static_cast<AnaECALParticle*>(MakeEcalTrack());
1970  FillEcalTrackInfo( *ecalTrack, seg);
1971  track->ECALSegments[track->nECALSegments++] = seg;
1972  }
1973 
1974 }
1975 
1976 //*****************************************************************************
1977 void oaAnalysisTreeConverter::FillSmrdInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1978 //*****************************************************************************
1979  track->nSMRDSegments=0;
1980  for(int jj = 0; jj < globalTrack.NSMRDs; jj++){
1981  if((unsigned int)track->nSMRDSegments == NMAXSMRDS)
1982  break;
1983 
1984  ND::TGlobalReconModule::TSMRDObject *smrdTrack=(ND::TGlobalReconModule::TSMRDObject*)(*(globalTrack.SMRD))[jj];
1985  if(!smrdTrack) continue;
1986 
1987  AnaSMRDParticle* seg = static_cast<AnaSMRDParticle*>(MakeSmrdTrack());
1988  FillSmrdTrackInfo( *smrdTrack, seg);
1989  track->SMRDSegments[track->nSMRDSegments++] = seg;
1990  }
1991 }
1992 
1993 //*****************************************************************************
1994 void oaAnalysisTreeConverter::FillP0dInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
1995 //*****************************************************************************
1996  track->nP0DSegments=0;
1997  for(int jj = 0; jj < globalTrack.NP0Ds; jj++){
1998 
1999  if((unsigned int)track->nP0DSegments==NMAXP0DS)
2000  break;
2001 
2002  ND::TGlobalReconModule::TP0DObject *p0dTrack=(ND::TGlobalReconModule::TP0DObject*)(*(globalTrack.P0D))[jj];
2003  if(!p0dTrack) continue;
2004 
2005  AnaP0DParticle* seg = static_cast<AnaP0DParticle*>(MakeP0dTrack());
2006 
2007  FillP0dTrackInfo( *p0dTrack, seg);
2008  //Add P0D energy loss
2009  Float_t entrance[4] = {globalTrack.EntrancePosition[0].X(),globalTrack.EntrancePosition[0].Y(),globalTrack.EntrancePosition[0].Z(),globalTrack.EntrancePosition[0].T()};
2010 
2011  if (anaUtils::InDetVolume(SubDetId::kTPC1,entrance))
2012  seg->ELoss = track->Momentum - globalTrack.EntranceMomentum[0];
2013  else seg->ELoss = -99999;
2014 
2015  track->P0DSegments[track->nP0DSegments++] = seg;
2016 
2017 
2018  // ---- TEST HIGHLAND2-P0D ----
2019  // Put the object with info from TP0DReconModule tree as a constituent of the Global track. For the moment use the P0DSegments array to avoid modifiying psyche
2020  // Once this is validated it will be moved into the P0DSegments array in AnaTrackB
2021  if (_isUsingReconDirP0DNew){
2022  track->nP0DSegments=0;
2023  ND::TP0DReconModule::TP0DParticle *p0dParticle = GetP0DReconParticleWithUniqueID(p0dTrack->UniqueID);
2024  if (p0dParticle){
2025  AnaP0DParticle* part = MakeP0DParticle();
2026  track->P0DSegments[track->nP0DSegments++] = part;
2027  // Fill info into the P0DParticle
2028  FillP0DParticleInfo(*p0dParticle,part);
2029  }
2030  }
2031  // ----------------------------
2032  }
2033 }
2034 
2035 //*****************************************************************************
2036 void oaAnalysisTreeConverter::FillTrackerInfo(ND::TGlobalReconModule::TGlobalPID& globalTrack, AnaTrack* track){
2037 //*****************************************************************************
2038 
2039 
2040  for(int jj = 0; jj < globalTrack.NTRACKERs; jj++){
2041 
2042  if(track->TRACKERSegments.size() == NMAXTRACKERS)
2043  break;
2044 
2045  ND::TGlobalReconModule::TTrackerObject *trTrack=(ND::TGlobalReconModule::TTrackerObject*)(*(globalTrack.TRACKER))[jj];
2046  if(!trTrack) continue;
2047 
2048  AnaTrackerTrack* seg = static_cast<AnaTrackerTrack*>(MakeTrackerTrack());
2049  FillTrackerTrackInfo( *trTrack, seg);
2050  track->TRACKERSegments.push_back(seg);
2051  }
2052 }
2053 
2054 //*****************************************************************************
2055 void oaAnalysisTreeConverter::FillSubdetectorTrackInfo(ND::TSubBaseObject& subTrack, AnaParticleB* seg){
2056 //*****************************************************************************
2057 
2058  seg->NHits = subTrack.NHits;
2059 
2060 
2061  AnaSubTrack* seg2 = dynamic_cast<AnaSubTrack*>(seg);
2062  if (seg2)
2063  seg2->Length = subTrack.Length;
2064 
2065  seg->NNodes = subTrack.NNodes;
2066  anaUtils::VectorToArray(subTrack.FrontDirection,seg->DirectionStart);
2067  anaUtils::VectorToArray(subTrack.BackDirection, seg->DirectionEnd);
2068  anaUtils::VectorToArray(subTrack.FrontPosition, seg->PositionStart);
2069  anaUtils::VectorToArray(subTrack.BackPosition, seg->PositionEnd);
2070  seg->UniqueID = subTrack.UniqueID;
2071 }
2072 
2073 //*****************************************************************************
2074 void oaAnalysisTreeConverter::FillTpcTrackInfo(ND::TGlobalReconModule::TTPCObject& tpcTrack, AnaTPCParticle* seg){
2075 //*****************************************************************************
2076 
2077  FillSubdetectorTrackInfo(tpcTrack, seg);
2078 
2079  convUtils::ConvertLocalDetEnumToBitField(seg->Detector, tpcTrack.Detector-1, SubDetId::kTPC);
2080 
2081  seg->Charge = tpcTrack.Charge;
2082  seg->Momentum = tpcTrack.FrontMomentum;
2083  seg->MomentumError = tpcTrack.FrontMomentumError;
2084  seg->MomentumEnd = tpcTrack.BackMomentum;
2085 
2086 #if VERSION_HAS_BFIELD_REFIT_FULL
2087  seg->RefitCharge = tpcTrack.RefitCharge;
2088  seg->RefitMomentum = tpcTrack.RefitMomentum;
2089  anaUtils::VectorToArray(tpcTrack.RefitDirection, seg->RefitDirection);
2090  anaUtils::VectorToArray(tpcTrack.RefitPosition, seg->RefitPosition);
2091 #endif
2092 
2093 #if VERSION_HAS_BFIELD_REFIT_BASIC
2094  seg->RefitMomentum = tpcTrack.PDist;
2095 #endif
2096 
2097 #if VERSION_HAS_EFIELD_REFIT
2098  seg->EFieldRefitMomentum = tpcTrack.PEField;
2099 #endif
2100 
2101  seg->Pullmu = tpcTrack.PullMuon;
2102  seg->Pullele = tpcTrack.PullEle;
2103  seg->Pullp = tpcTrack.PullProton;
2104  seg->Pullpi = tpcTrack.PullPion;
2105  seg->Pullk = tpcTrack.PullKaon;
2106 
2107  seg->dEdxMeas = tpcTrack.Ccorr;
2108 
2109  seg->dEdxexpMuon = tpcTrack.dEdxexpMuon;
2110  seg->dEdxexpEle = tpcTrack.dEdxexpEle;
2111  seg->dEdxexpPion = tpcTrack.dEdxexpPion;
2112  seg->dEdxexpProton = tpcTrack.dEdxexpProton;
2113  seg->dEdxexpKaon = tpcTrack.dEdxexpKaon;
2114 
2115  seg->dEdxSigmaMuon = tpcTrack.SigmaMuon;
2116  seg->dEdxSigmaEle = tpcTrack.SigmaEle;
2117  seg->dEdxSigmaPion = tpcTrack.SigmaPion;
2118  seg->dEdxSigmaProton = tpcTrack.SigmaProton;
2119  seg->dEdxSigmaKaon = tpcTrack.SigmaKaon;
2120 
2121  // Make truth-reco association, but don't set the purity of the track, as
2122  // that is reserved for the global purity. Instead we record the TPC-specific
2123  // purity in seg->Purity.
2124  FillTrueParticleRecoInfo(tpcTrack.TrueParticle, seg->TrueObject, false);
2125 
2126  seg->Purity = tpcTrack.TrueParticle.Pur;
2127 
2128  // For production 7 iteration substitute the NNodes (later treated as a figure of merit for track quality)
2129  // with the actual number of horizontal and vertical clusters used in the fit (as recommended by TREx group and can be indeed
2130  // considered as a proper characteristic of track quality)
2131 #if VERSION_PROD7_DEVEL
2132  seg->NNodes = tpcTrack.NbFittedVerticalClusters +
2133  tpcTrack.NbFittedHorizontalClusters;
2134 #endif
2135 
2136 }
2137 
2138 //*****************************************************************************
2139 void oaAnalysisTreeConverter::FillFgdTrackInfo(ND::TGlobalReconModule::TFGDObject& fgdTrack, AnaFGDParticle* seg){
2140 //*****************************************************************************
2141 
2142  FillSubdetectorTrackInfo(fgdTrack, seg);
2143  convUtils::ConvertLocalDetEnumToBitField(seg->Detector, fgdTrack.Detector-1, SubDetId::kFGD);
2144 
2145  seg->E = fgdTrack.E;
2146  seg->X = fgdTrack.x;
2147  seg->Containment = fgdTrack.fgdContainment;
2148  seg->AvgTime = fgdTrack.avgtime;
2149 
2150  seg->Pullmu = fgdTrack.PullMuon;
2151  seg->Pullp = fgdTrack.PullProton;
2152  seg->Pullpi = fgdTrack.PullPion;
2153  seg->Pullno = fgdTrack.PullNotSet;
2154 
2155  seg->Vertex1x1 = fgdTrack.fgdVA_verQ;
2156  seg->Vertex3x3 = fgdTrack.fgdVA_verNearQ;
2157  seg->Vertex5x5 = fgdTrack.fgdVA_verNextNearQ;
2158  seg->Vertex7x7 = fgdTrack.fgdVA_verNextNextNearQ;
2159 
2160  // New FGD2 Vertex Activity Variables
2161  /*
2162  seg->Vertex2x3 = fgdTrack.fgdVA_verNearQ_rect;
2163  seg->Vertex2x5 = fgdTrack.fgdVA_verNextNearQ_rect;
2164  seg->Vertex2x7 = fgdTrack.fgdVA_verNextNextNearQ_rect;
2165  */
2166  seg->VertexLayer = fgdTrack.fgdVA_verLayQ;
2167 }
2168 
2169 //*****************************************************************************
2170 void oaAnalysisTreeConverter::FillTrackerTrackInfo(ND::TGlobalReconModule::TTrackerObject& trackerTrack, AnaTrackerTrack* seg){
2171 //*****************************************************************************
2172 
2173  FillSubdetectorTrackInfo(trackerTrack, seg);
2174 
2175  //seg->Detector = trackerTrack.Detector;
2176 
2177  convUtils::ConvertTrackerDetFieldToBitField(seg->Detector, trackerTrack.Detector);
2178 
2179  seg->Charge = trackerTrack.Charge;
2180  seg->Momentum = trackerTrack.FrontMomentum;
2181  seg->MomentumEnd = trackerTrack.BackMomentum;
2182 
2183 }
2184 
2185 
2186 //*****************************************************************************
2187 void oaAnalysisTreeConverter::FillEcalTrackInfo(ND::TGlobalReconModule::TECALObject& ecalTrack, AnaECALParticle* seg){
2188 //*****************************************************************************
2189 
2190  FillSubdetectorTrackInfo(ecalTrack, seg);
2191 
2192  convUtils::ConvertLocalDetEnumToBitField(seg->Detector, ecalTrack.Detector-1, SubDetId::kECAL);
2193 
2194  seg->EMEnergy = ecalTrack.EMEnergy;
2195  seg->EDeposit = ecalTrack.EDeposit;
2196  seg->IsShowerLike = ecalTrack.IsShowerLike;
2197  seg->AvgTime = ecalTrack.AverageHitTime;
2198  seg->Length = ecalTrack.Length;
2199 #if VERSION_HAS_ECAL_LLR
2200 //ecal pid variables
2201  seg->PIDMipEm = ecalTrack.LLR_MIP_EM;
2202  seg->PIDMipPion = ecalTrack.LLR_MIP_Pion;
2203  seg->PIDEmHip = ecalTrack.LLR_EM_HIP;
2204 #endif
2205 
2206  for (int i = 0; i < NTrECalObjects; i++) {
2207  ND::TTrackerECALReconModule::TECALReconObject *ecalObject = (ND::TTrackerECALReconModule::TECALReconObject*) (*TrECalObjects)[i];
2208 
2209  if (ecalTrack.UniqueID == ecalObject->UniqueID) {
2210 
2211 #if !VERSION_HAS_ECAL_LLR
2212  // In this case, we need to find the LLR values ourselves
2213  _ecalPidCalc->CalculateLikelihoodValues(*ecalObject);
2214  seg->PIDMipEm = _ecalPidCalc->GetLikelihoodValue("MipEm");
2215  seg->PIDMipPion = _ecalPidCalc->GetLikelihoodValue("MipPion");
2216  seg->PIDEmHip = _ecalPidCalc->GetLikelihoodValue("EmHip");
2217 #endif
2218  seg->Containment = ecalObject->Containment;
2219 
2220 #if !VERSION_PROD7_DEVEL
2221  seg->TrShVal = ecalObject->PID_TrShval;
2222 #endif
2223 
2224  seg->MostUpStreamLayerHit = ecalObject->mostUpStreamLayerHit;
2225  anaUtils::VectorToArray(ecalObject->Shower.Position.Vect(),seg->ShowerPosition);
2226  }
2227  }
2228 
2229 }
2230 
2231 //*****************************************************************************
2232 void oaAnalysisTreeConverter::FillSmrdTrackInfo(ND::TGlobalReconModule::TSMRDObject& smrdTrack, AnaSMRDParticle* seg){
2233 //*****************************************************************************
2234 
2235  FillSubdetectorTrackInfo(smrdTrack, seg);
2236 
2237  convUtils::ConvertLocalDetEnumToBitField(seg->Detector, smrdTrack.Detector-1, SubDetId::kSMRD);
2238 
2239  seg->AvgTime = smrdTrack.avgtime;
2240  seg->EDeposit = smrdTrack.EDeposit;
2241 
2242 }
2243 
2244 //*****************************************************************************
2245 void oaAnalysisTreeConverter::FillP0dTrackInfo(ND::TGlobalReconModule::TP0DObject& p0dTrack, AnaP0DParticle* seg){
2246 //*****************************************************************************
2247 
2248  FillSubdetectorTrackInfo(p0dTrack, seg);
2249  seg->Length = p0dTrack.Length;
2250  convUtils::ConvertLocalDetEnumToBitField(seg->Detector, p0dTrack.Detector-1, SubDetId::kP0D);
2251 }
2252 
2253 //*****************************************************************************
2254 void oaAnalysisTreeConverter::FillTrueParticleRecoInfo(ND::TTrueParticle& trueParticle, AnaTrueObjectC*& trueObj, bool setpurity){
2255 //*****************************************************************************
2256 
2257 
2258  // Compare the IDs to find the AnaTrueParticle associated with this trueParticle.
2259  // Set the Purity, which is a truth-reco quantity
2260 
2261  if (trueParticle.ID == -1) return; // particle without true particle associated
2262 
2263  std::vector<AnaTrueParticleB*>::iterator it;
2264  for (it = _spill->TrueParticles.begin(); it!=_spill->TrueParticles.end();it++){
2265  AnaTrueParticleB* truePart = *it;
2266 
2267  if (trueParticle.ID == truePart->ID){
2268  trueObj = truePart;
2269  if (setpurity) {
2270  static_cast<AnaTrueParticle*>(trueObj)->Purity = trueParticle.Pur;
2271  }
2272  break; // Stop when association is found.
2273  }
2274  }
2275  // if not found means that the correspondent Trajectories was not saved in the oaAnalysis file
2276  // this is the case when there are no G4Points
2277  // it often happens in SMRD (Detectors=8), sometimes in DSECal / ECal (Detectors=7/9), might be also P0D (Detectors=6) and TPCs (Detectors=1,2,3)
2278  // it seems it never happens in FGDs (Detectors=4,5)
2279  return;
2280 }
2281 
2282 //*****************************************************************************
2283 void oaAnalysisTreeConverter::FillTrueParticleInfo(ND::TTruthTrajectoriesModule::TTruthTrajectory* truthTraj, AnaTrueParticle* truePart, AnaSpill* spill){
2284 //*****************************************************************************
2285 
2286 
2287  // This is not known at this level We need the reco-truth association
2288  truePart->Purity = 0;
2289 
2290  if(truthTraj==NULL ){
2291  truePart->ID = 0;
2292  truePart->PDG = 0;
2293  truePart->PrimaryID = 0;
2294  truePart->ParentID = 0;
2295  anaUtils::VectorToArray(TLorentzVector(0,0,0,0),truePart->Position);
2296  truePart->Momentum = 0;
2297  anaUtils::VectorToArray(TVector3(0,0,0), truePart->Direction);
2298  truePart->Charge = 0;
2299  truePart->Bunch = -1;
2300  truePart->VertexID = -1;
2301 
2302  return;
2303  }
2304 
2305  truePart->ID = truthTraj->ID;
2306  truePart->PDG = truthTraj->PDG;
2307  truePart->PrimaryID = truthTraj->PrimaryID;
2308  truePart->ParentID = truthTraj->ParentID;
2309  anaUtils::VectorToArray(truthTraj->InitPosition, truePart->Position);
2310  anaUtils::VectorToArray(truthTraj->FinalPosition,truePart->PositionEnd);
2311  truePart->Momentum = truthTraj->InitMomentum.Vect().Mag();
2312  anaUtils::VectorToArray((1/truePart->Momentum)*truthTraj->InitMomentum.Vect(), truePart->Direction);
2313  truePart->Charge = truthTraj->Charge;
2314  truePart->VertexID = -1;
2315  truePart->VertexIndex = -1;
2316 
2317  truePart->Bunch = _bunching.GetBunch(truthTraj->InitPosition.T() + _trueBunchShift, spill->EventInfo->Run, IsMC, cosmic_mode);
2318 
2319  //0=FGD1,1=FGD2,2=P0D,3=DsEcal,4=BrlEcal,5=P0DEcal,6=TPC1,7=TPC2,8=TPC3,9=MRD,10=Ingrid,11=cavern
2320 
2321  unsigned int nCrossers = std::min((unsigned int)truthTraj->TraceSubdetectors.size(), NMAXCROSSEDDET);
2322 
2323  truePart->nDetCrossings = 0;
2324  anaUtils::CreateArray(truePart->DetCrossings, nCrossers);
2325  for(unsigned int i=0;i<nCrossers;i++){
2326 
2327  AnaDetCrossingB* cross = new AnaDetCrossingB();
2328 
2329  convUtils::ConvertTrueParticleDetEnumToBitField(cross->Detector, truthTraj->TraceSubdetectors[i]);
2330  cross->InActive = truthTraj->TraceInActive[i];
2331  anaUtils::VectorToArray(truthTraj->TraceEntrancePosition[i], cross->EntrancePosition);
2332  anaUtils::VectorToArray(truthTraj->TraceExitPosition[i], cross->ExitPosition);
2333  anaUtils::VectorToArray(truthTraj->TraceEntranceMomentum[i], cross->EntranceMomentum);
2334  anaUtils::VectorToArray(truthTraj->TraceExitMomentum[i], cross->ExitMomentum);
2335 
2336  truePart->DetCrossings[truePart->nDetCrossings] = cross;
2337  truePart->nDetCrossings++;
2338  }
2339 
2340  // TEMPORARILY set the VertexIndex to the ID of the true vertex. This will
2341  // be overwritten in FillTrueVertexInfo() to point to the actual index in the
2342  // spill.TrueVertices vector that the vertex is saved at.
2343 
2344  ND::TTruthVerticesModule::TTruthVertex* vtx = _truthUtils.GetVertexOfTrajectory(truthTraj);
2345  if (vtx) {
2346  truePart->VertexIndex =vtx->ID;
2347  truePart->VertexID = vtx->ID;
2348  }
2349 
2350  ND::TTruthTrajectoriesModule::TTruthTrajectory* parentTraj = _truthUtils.GetParentTrajectory(truthTraj->ID);
2351  ND::TTruthTrajectoriesModule::TTruthTrajectory* grandparentTraj = NULL;
2352 
2353  if(parentTraj!=NULL){
2354  truePart->ParentPDG = parentTraj->PDG;
2355 
2356  grandparentTraj = _truthUtils.GetParentTrajectory(parentTraj->ID);
2357 
2358  if(grandparentTraj!=NULL){
2359  truePart->GParentPDG = grandparentTraj->PDG;
2360  }
2361  }
2362 
2363  // is this track a decay photon from an FGD or P0D pi0?
2364  if (parentTraj==NULL) return; // give up if parentTraj is undefined
2365  if (truePart->PDG == ParticleId::kPhotonPDG and // this is a photon
2366  truePart->ParentPDG == ParticleId::kPi0PDG and // its parent is a pi0
2367  truePart->PrimaryID == truePart->ParentID and // its primary is its parent pi0
2368  parentTraj->ParentID == 0 and // the parent pi0 was produced at the vertex (and hence has no parent of its own)
2369  parentTraj->TraceSubdetectors[0] < 3){ // the parent pi0 was produced in FGD1, FGD2 or P0D
2370 
2371  truePart->IsTruePrimaryPi0DecayPhoton = true;
2372 
2373 #ifdef DEBUG
2374  std::cout<<"oaAnalysisTreeConverter::FillTrueParticleInfo() truePart with ID:"<<setw(6)<<truePart->ID
2375  <<" and ParentID:"<<setw(6)<<parentTraj->ID
2376  <<" is a true subdet:"<<parentTraj->TraceSubdetectors[0]<<" pi0 decay photon"<<std::endl;
2377 #endif
2378 
2379  } else {
2380  // is this track the child of an existing pi0 decay photon?
2381  // loop over TrueParticles
2382  for (std::vector<AnaTrueParticleB*>::iterator it = spill->TrueParticles.begin(); it!=spill->TrueParticles.end(); it++){
2383 
2384  // give up if TrueParticle is not a pi0 decay photon
2385  if (not static_cast<AnaTrueParticle*>(*it)->IsTruePrimaryPi0DecayPhoton)
2386  continue;
2387 
2388  // if true particle is a pi0 decay photon does the ParentID of PrimaryID of this track match it?
2389  if (truePart->ParentID == (*it)->ID or
2390  truePart->PrimaryID == (*it)->ID){
2391 
2392  truePart->IsTruePrimaryPi0DecayPhotonChild = true;
2393 
2394 #ifdef DEBUG
2395  std::cout<<"oaAnalysisTreeConverter::FillTrueParticleInfo() truePart with ID:"<<setw(6)<<truePart->ID
2396  <<" and ParentID:"<<setw(6)<<parentTraj->ID
2397  <<" is a true subdet:"<<parentTraj->TraceSubdetectors[0]<<" pi0 decay photon child"<<std::endl;
2398 #endif
2399  }
2400  }
2401  }
2402 
2403 
2404  return;
2405 }
2406 
2407 //*****************************************************************************
2408 void oaAnalysisTreeConverter::FillTrueInfo(AnaSpill* spill){
2409 //*****************************************************************************
2410 
2411  _containedTrueParticles.clear();
2412 
2413  if (!spill->GetIsMC()) return;
2414 
2415  // First create all the true trajectories
2416  for (int i = 0; i < NTruthTrajs; i++) {
2417 
2418  if(spill->TrueParticles.size() == NMAXTRUEPARTICLES) {
2419  std::cout << "INFO: event " << EventID << " has " << NTruthTrajs << " true trajectories (too many), ";
2420  std::cout << "only the first " << NMAXTRUEPARTICLES << " will be stored (=> some warnings might appear)" << std::endl;
2421  break;
2422  }
2423 
2424  ND::TTruthTrajectoriesModule::TTruthTrajectory* traj = (ND::TTruthTrajectoriesModule::TTruthTrajectory*) (*TruthTrajs)[i];
2425 
2426  if(!traj)
2427  continue;
2428 
2429 
2430  // Create an AnaTrueParticle for each TruthTrajectory
2431  AnaTrueParticle* trueParticle = static_cast<AnaTrueParticle*>(MakeTrueParticle());
2432  FillTrueParticleInfo(traj, trueParticle, spill);
2433  if (trueParticle->PDG == 0) {
2434  delete trueParticle;
2435  } else {
2436  // Ignore fully contained trajectories in some subdetectors. Numbering follows ToaAnalysisUtils convention
2437  int InitSubdetector = (traj->TraceSubdetectors.empty()) ? -1 : traj->TraceSubdetectors.front();
2438  if (_ignoreDsECalContainedTrueObjects && InitSubdetector==3 && traj->TraceSubdetectors.size()==1) _containedTrueParticles.push_back(trueParticle);
2439  if (_ignoreBrECalContainedTrueObjects && InitSubdetector==4 && traj->TraceSubdetectors.size()==1) _containedTrueParticles.push_back(trueParticle);
2440  if (_ignoreP0DECalContainedTrueObjects && InitSubdetector==5 && traj->TraceSubdetectors.size()==1) _containedTrueParticles.push_back(trueParticle);
2441  if (_ignoreSMRDContainedTrueObjects && InitSubdetector==9 && traj->TraceSubdetectors.size()==1) _containedTrueParticles.push_back(trueParticle);
2442  if (_ignoreINGRIDContainedTrueObjects && InitSubdetector==10 && traj->TraceSubdetectors.size()==1) _containedTrueParticles.push_back(trueParticle);
2443  spill->TrueParticles.push_back(trueParticle);
2444  }
2445  }
2446 
2447 
2448  // VERTICES
2449  if (Neut && NNVtx != NTruthVertices)
2450  std::cout<< "ERROR: NNVtx (in TTruthVerticesModule) = " << NNVtx
2451  << " vs NTruthVertices (in rooTrackerVtx) = " << NTruthVertices
2452  << " in EventID " << EventID << std::endl;
2453  if (Genie && NGVtx != NTruthVertices)
2454  std::cout<< "ERROR: NGVtx (in TTruthVerticesModule) = " << NGVtx
2455  << " vs NTruthVertices (in rooTrackerVtx) " << NTruthVertices
2456  << " in EventID " << EventID << std::endl;
2457 
2458  //Loop over true vertices
2459  _foundPauliBlocked = false;
2460  _foundCohOnH = false;
2461  std::vector<AnaTrueVertexB*>& vertices = spill->TrueVertices;
2462  ND::TTruthVerticesModule::TTruthVertex *true_vertex = NULL;
2463  for(int v = 0; v < NTruthVertices; v++){
2464 
2465  if(vertices.size() == NMAXTRUEVERTICES) {
2466  std::cout << "INFO: event " << EventID << " has " << NTruthVertices << " true vertices (too many), ";
2467  std::cout << "only the first " << NMAXTRUEVERTICES << " will be stored (=> some warnings might appear)" << std::endl;
2468  break;
2469  }
2470 
2471 
2472  true_vertex = (ND::TTruthVerticesModule::TTruthVertex*) TruthVertices->UncheckedAt(v);
2473 
2474  if( ! true_vertex) continue;
2475 
2476  AnaTrueVertex* vertex = static_cast<AnaTrueVertex*>(MakeTrueVertex());
2477  // currently this returns always true, bad vertices will be deleted afterward in DeleteBadObjects
2478  // in order to remove first also the associated reconstructed particles and vertices
2479  bool goodVtx = FillTrueVertexInfo(true_vertex, vertex, v, spill);
2480  if ( ! goodVtx) {
2481  delete vertex;
2482  continue;
2483  } else {
2484  vertices.push_back(vertex);
2485  }
2486 
2487  } //End loop over vertices
2488 
2489 }
2490 
2491 
2492 //*****************************************************************************
2493 bool oaAnalysisTreeConverter::FillTrueVertexInfo(ND::TTruthVerticesModule::TTruthVertex* true_vertex, AnaTrueVertex* vertex, int v, AnaSpill* spill) {
2494 //*****************************************************************************
2495 
2496  vertex->RooVtxEntry = _RooVtxEntryInCurrentInputFile;
2497 
2498  if((true_vertex->ReactionCode).find(":") != std::string::npos) {
2499  // local conversion from Genie to Neut convention. This value will be overwritten in FillTrueVertexRooInfo if the GRooTrackerVertex exists
2500  vertex->ReacCode = GetGenieReactionCode(true_vertex->ReactionCode);
2501  } else {
2502  // Neut convention
2503  vertex->ReacCode = atoi((true_vertex->ReactionCode).c_str());
2504  }
2505 
2506  vertex->ID = true_vertex->ID; // this needs to be before calling FillTrueVertexRooInfo
2507 
2508  // The detector info provided by oaAnalysis should be converted into psyche definitions
2509  vertex->Detector = 0;
2510  convUtils::ConvertTrueParticleDetEnumToBitField(vertex->Detector, true_vertex->Subdetector);
2511 
2512 
2513  vertex->NuPDG = true_vertex->NeutrinoPDG; // also this, but just for some cout
2514  vertex->NuEnergy = true_vertex->NeutrinoMomentum.E(); // will be replaced in FillTrueVertexRooInfo if rooTrackerVtx exists
2515 
2516  // currently this returns always true, bad vertices will be deleted afterward in DeleteBadObjects
2517  // in order to remove first also the associated reconstructed tracks and vertices
2518  //
2519  bool goodRooVtx = anaUtils::FillTrueVertexRooInfo(vertex,RunID,Neut,Genie,NNVtx,NVtx,NGVtx,GVtx,_foundCohOnH,_foundPauliBlocked);
2520  if ( ! goodRooVtx) return false;
2521 
2522  vertex->TargetMom = true_vertex->TargetMomentum.Vect().Mag();
2523  vertex->TargetPDG = true_vertex->TargetPDG;
2524  anaUtils::VectorToArray(true_vertex->Position, vertex->Position);
2525  vertex->Bunch = _bunching.GetBunch(true_vertex->Position.T() + _trueBunchShift, spill->EventInfo->Run, IsMC, cosmic_mode);
2526 
2527  // get the number of true vertices per bunch
2528  // nvtxPerBunch[ _std_TrueVertexBunch[_std_NTrueVertices] ] ++;
2529 
2530  if(true_vertex->NeutrinoMomentum.Vect().Mag() > 0)
2531  anaUtils::VectorToArray((1/true_vertex->NeutrinoMomentum.Vect().Mag())*true_vertex->NeutrinoMomentum.Vect(),vertex->NuDir);
2532 
2533  if(true_vertex->TargetMomentum.Vect().Mag() > 0)
2534  anaUtils::VectorToArray((1/true_vertex->TargetMomentum.Vect().Mag())*true_vertex->TargetMomentum.Vect(),vertex->TargetDir);
2535 
2536  // check (temporarily) that the neutrino energy corresponds in RooTrackerVtx and in TruthTrajectoryModule
2537  // (even right after the assignement vertex-> they are not exactly equal)
2538  // (even in the assignement of vertex->NuEnergy itself, some differences are introduced)
2539  if (fabs(vertex->NuEnergy - true_vertex->NeutrinoMomentum[3] > 0.001))
2540  std::cout << "Error: the neutrino energy differs between TruthTrajectoryModule and RooTrackerVtx!!! ID " << true_vertex->ID << std::endl;
2541 
2542  std::stringstream ssRun; ssRun << RunID;
2543  bool issand = ((ssRun.str())[4]=='7');
2544 
2545  // Loop over TruthTrajectories
2546  bool found = false;
2547  for (int i = 0; i < true_vertex->NPrimaryTraj; i++) {
2548  ND::TTruthTrajectoriesModule::TTruthTrajectory* truthTraj = _truthUtils.GetTrajectoryById(true_vertex->PrimaryTrajIDs[i]);
2549  if (truthTraj == NULL) continue;
2550 
2551  // Sometimes FSI produces a lepton pair (listed secondly)
2552  if ( (vertex->NuPDG == 14 && truthTraj->PDG == 13) ||
2553  (vertex->NuPDG == 12 && truthTraj->PDG == 11) ||
2554  (vertex->NuPDG == -14 && truthTraj->PDG == -13) ||
2555  (vertex->NuPDG == -12 && truthTraj->PDG == -11) ) {
2556  // if already filled do not overwrite (the first lepton listed is the one coming from the neutrino)
2557  if ( ! found) {
2558  found = true;
2559 
2560  // If no rooTrackerVtx, fill lepton vars in the old way, using the TruthTrajectoryModule
2561  if ( ! Neut && ! Genie) {
2562  vertex->LeptonPDG = truthTraj->PDG;
2563  vertex->Q2 = - (truthTraj->InitMomentum - true_vertex->NeutrinoMomentum).Mag2();
2564  vertex->LeptonMom = truthTraj->InitMomentum.Vect().Mag();
2565  if (vertex->LeptonMom > 0)
2566  anaUtils::VectorToArray((1 / vertex->LeptonMom) * truthTraj->InitMomentum.Vect(), vertex->LeptonDir);
2567  }
2568 
2569  // check that LeptonMom corresponds in RooTrackerVtx and in TruthTrajectoryModule
2570  // (even in the assignement of vertex->LeptonMom itself some differences are introduced)
2571  else if (truthTraj->InitMomentum.Vect().Mag() > 0) { // if lepton found (might not be saved if without G4 points)
2572  if ( ! issand) { // for sand muons, the momentum at nd280 is always different from the one at the vertex
2573  if (fabs(vertex->LeptonMom - truthTraj->InitMomentum.Vect().Mag()) > 0.005) { // seen differences up to 0.002 (in Genie)
2574  if (vertex->NPrimaryParticles[ParticleId::kLeptons] > 1) {
2575  std::cout << "INFO: LeptonMom differs between TruthTrajectoryModule and RooTrackerVtx: there is a lepton pair produced by FSI and probably the lepton coming from the neutrino is not saved in TruthTrajectoryModule because it didn't have G4 points (we use RooTrackerVtx info anyway): Nmuon " << vertex->NPrimaryParticles[ParticleId::kMuon] << ", Nantimuon " << vertex->NPrimaryParticles[ParticleId::kAntiMuon] << ", NuPDG " << vertex->NuPDG << std::endl;
2576 
2577  } else if (vertex->LeptonMom == -999) { // happens in Genie... to be debugged
2578  std::cout << "ERROR: LeptonMom is -999 (something wrong in RooTrackerVtx ?), setting it from TruthTrajectoryModule (" << truthTraj->InitMomentum.Vect().Mag() << "), for vertex ID " << true_vertex->ID << std::endl;
2579  vertex->LeptonMom = truthTraj->InitMomentum.Vect().Mag();
2580  vertex->LeptonPDG = truthTraj->PDG;
2581  vertex->Q2 = - (truthTraj->InitMomentum - true_vertex->NeutrinoMomentum).Mag2();
2582  vertex->LeptonMom = truthTraj->InitMomentum.Vect().Mag();
2583  if (vertex->LeptonMom > 0)
2584  anaUtils::VectorToArray((1 / vertex->LeptonMom) * truthTraj->InitMomentum.Vect(), vertex->LeptonDir);
2585 
2586  } else {
2587  std::cout << "ERROR: LeptonMom differs between RooTrackerVtx and TruthTrajectoryModule! " << vertex->LeptonMom << " - " << truthTraj->InitMomentum.Vect().Mag() << " = " << vertex->LeptonMom - truthTraj->InitMomentum.Vect().Mag() << ", for vertex ID " << true_vertex->ID << std::endl;
2588  }
2589 /*
2590  } else if (fabs(vertex->Q2 - ( - (truthTraj->InitMomentum - true_vertex->NeutrinoMomentum).Mag2())) > 20) {
2591  // they differ even more than 10 (Q2 differs from its formula right after the assignement)
2592  std::cout << "Error: NeutrinoMomentum differs between TruthTrajectoryModule and RooTrackerVtx!!! " << vertex->Q2 - ( - (truthTraj->InitMomentum - true_vertex->NeutrinoMomentum).Mag2()) << std::endl;
2593 */
2594  }
2595  }
2596  }
2597 
2598  break; // break when the lepton is found
2599  }
2600 
2601  } // end if lepton
2602 
2603  // If no rooTrackerVtx, fill true proton vars, using the TruthTrajectoryModule (old way)
2604  else if ( ! Neut && ! Genie && truthTraj->PDG == 2212 && truthTraj->ParentID == 0) {
2605  // if many, take the first one, that should be the first primary one (not from FSI)
2606  if (vertex->ProtonMom < 0) {
2607  vertex->ProtonMom = truthTraj->InitMomentum.Vect().Mag();
2608  if (vertex->ProtonMom > 0)
2609  anaUtils::VectorToArray((1. / vertex->ProtonMom) * truthTraj->InitMomentum.Vect(), vertex->ProtonDir);
2610  }
2611  } // end if proton
2612 
2613  // If no rooTrackerVtx, fill true pion vars, using the TruthTrajectoryModule (old way)
2614  else if ( ! Neut && ! Genie && truthTraj->PDG == 211 && truthTraj->ParentID == 0) {
2615  // if many, take the highest momentum one, that should be most likely to be reconstructed
2616  if (vertex->PionMom < truthTraj->InitMomentum.Vect().Mag()) {
2617  vertex->PionMom = truthTraj->InitMomentum.Vect().Mag();
2618  if (vertex->PionMom > 0)
2619  anaUtils::VectorToArray((1. / vertex->PionMom) * truthTraj->InitMomentum.Vect(), vertex->PionDir);
2620  }
2621  } // end if pion
2622 
2623  } // end loop over TruthTrajectories
2624 
2625  // Notify that the lepton was not found in TruthTrajectoryModule, but only for CC in FGDs (too many otherwise)
2626  // (it happens when it doesn't have G4 points, see bugzilla 1051)
2627  if ( ! found && ! vertex->IsPauliBlocked) {
2628  if (anaUtils::InFiducialVolume(SubDetId::kFGD,vertex->Position) && abs(vertex->ReacCode) < 30) {
2629  std::cout << "INFO: true lepton not found in TruthTrajectoryModule (probably no G4 points, but we use RooTrackerVtx info), ";
2630  std::cout << "ReacCode " << vertex->ReacCode << ", in FV FGD" << true_vertex->Subdetector+1 << ", NuPDG " << vertex->NuPDG << "" << std::endl;
2631  }
2632  }
2633 
2634  // Loop over all the true particles to find the ones that belong to this vertex,
2635  // and set up particle<->vertex links.
2636  vertex->nTrueParticles = 0;
2637  // allocate a big array. Once it is filled we will resize it
2638  anaUtils::CreateArray(vertex->TrueParticles, NMAXTRUEPARTICLES);
2639  for (unsigned int jj=0; jj<spill->TrueParticles.size(); jj++) {
2640 
2641  if((unsigned int)vertex->nTrueParticles==NMAXTRUEPARTICLES) break;
2642 
2643  AnaTrueParticle* particle = static_cast<AnaTrueParticle*>(spill->TrueParticles[jj]);
2644  if (particle->VertexID == true_vertex->ID) {
2645 
2646  particle->TrueVertex = vertex;
2647  particle->VertexIndex = v;
2648  particle->VertexID = true_vertex->ID;
2649  vertex->TrueParticles[vertex->nTrueParticles++] = particle;
2650  }
2651  }
2652 
2653  // Give the proper size to the array
2654  anaUtils::ResizeArray(vertex->TrueParticles, vertex->nTrueParticles);
2655 
2656 
2657  //Fill primary trajectory info for each type of vertices
2658  //----------------------------------------------------------
2659  // for(int ll = 0; ll < true_vertex->NPrimaryTraj; ll ++){
2660  // std_truePrimaryID[_std_NTrueVertices][std_nPrimTraj] = true_vertex->PrimaryTrajIDs[ll];
2661  // std_nPrimTraj ++;
2662  // }
2663 
2664  // remove vertices with no TrueParticles. This happens when some uninteresting particles are removed
2665  if (_removeTrueVerticesWithNoTrueParticles && vertex->nTrueParticles==0){
2666  return false;
2667  }
2668 
2669  return true;
2670 }
2671 
2672 //*****************************************************************************
2673 double oaAnalysisTreeConverter::GetVertexTime(ND::TGlobalReconModule::TGlobalPID& globalTrack){
2674 //*****************************************************************************
2675 
2676  return globalTrack.FrontPosition.T();
2677 }
2678 
2679 //*****************************************************************************
2680 void oaAnalysisTreeConverter::GetBunchPIDs(){
2681 //*****************************************************************************
2682 
2683  for (unsigned int i=0;i<NBUNCHES+1;i++)
2684  _bunchPIDs[i].clear();
2685 
2686  for( int j=0; j<NPIDs; j++) {
2687 
2688  ND::TGlobalReconModule::TGlobalPID *globalTrack = (ND::TGlobalReconModule::TGlobalPID*)PIDs->UncheckedAt(j);
2689  if(!globalTrack) std::cout << "debug error 1100 in oaAnalysisConverter" << std::endl; // shouldn't happen!
2690  if(!globalTrack) continue; // if no global track is found, go to the next PID
2691 
2692  // check that the track is valid (the momentum is not NaN nor 0, etc)
2693  // if (!IsValidTrack(globalTrack)) continue;
2694 
2695  // --- Get the bunch number -----
2696  double tTrack = GetVertexTime(*globalTrack);
2697  int ibunch = _bunching.GetBunch(tTrack,RunID,IsMC, cosmic_mode);
2698 
2699  if (ibunch==-1){
2700  ibunch = NBUNCHES;
2701  }
2702 
2703  _bunchPIDs[ibunch].push_back(globalTrack);
2704  }
2705 }
2706 
2707 //*****************************************************************************
2708 void oaAnalysisTreeConverter::GetBunchLocalObjects(){
2709 //*****************************************************************************
2710 
2711 
2712  for (unsigned int i=0;i<NBUNCHES+1;i++){
2713  _bunchTECALObjects[i].clear();
2714  _bunchTECALUnmatchedObjects[i].clear();
2715  _bunchP0DVertices[i].clear();
2716  _bunchP0DParticles[i].clear();
2717  _bunchP0DClusters[i].clear();
2718  }
2719 
2720  if(_isUsingReconDirTECAL) {
2721 
2722  // Loop over all the TECALReconUnmatchedObjects in the event
2723  for (int iTECAL=0; iTECAL<NTrECalUnmatched; ++iTECAL){
2724  ND::TTrackerECALReconModule::TECALReconUnmatchedObject *tecalObj = (ND::TTrackerECALReconModule::TECALReconUnmatchedObject*) (*TrECalUnmatched)[iTECAL];
2725 
2726  // Is this object in this bunch?
2727  Int_t ibunch = _bunching.GetBunch(tecalObj->AverageHitTime, RunID, IsMC, cosmic_mode);
2728 
2729  if (ibunch==-1){
2730  ibunch = NBUNCHES;
2731  }
2732 
2733  _bunchTECALUnmatchedObjects[ibunch].push_back(tecalObj);
2734  }
2735 
2736 
2737  // Loop over all the TECALReconObjects in the event
2738  for (int iTECAL=0; iTECAL<NTrECalObjects; ++iTECAL){
2739  ND::TTrackerECALReconModule::TECALReconObject *tecalObj = (ND::TTrackerECALReconModule::TECALReconObject*) (*TrECalObjects)[iTECAL];
2740 
2741  Int_t ibunch = _bunching.GetBunch(tecalObj->AverageHitTime, RunID, IsMC, cosmic_mode);
2742 
2743  if (ibunch==-1){
2744  ibunch = NBUNCHES;
2745  }
2746 
2747  _bunchTECALObjects[ibunch].push_back(tecalObj);
2748  }
2749  }
2750 
2751 
2752  if(_isUsingReconDirP0D) {
2753 
2754  // Clear the maps used to create links between the local p0d recon objects: indices --> pointers
2755  _P0DReconVerticesMap.clear();
2756  _P0DReconParticlesMap.clear();
2757  _P0DReconClustersMap.clear();
2758 
2759  // Loop over all the P0D vertices in the selected AlgorithmResult
2760  for (int iP0D=0; iP0D<NP0DReconVertices; ++iP0D){
2761  ND::TP0DReconModule::TP0DVertex *p0dVertex = (ND::TP0DReconModule::TP0DVertex*) (*P0DReconVertices)[iP0D];
2762 
2763  Int_t ibunch = _bunching.GetBunch(p0dVertex->Position.T(), RunID, IsMC, cosmic_mode);
2764  if (ibunch==-1){
2765  ibunch = NBUNCHES;
2766  }
2767 
2768  _bunchP0DVertices[ibunch].push_back(p0dVertex);
2769 
2770  // Make a pointer to a new AnaP0DReconVertex, ready for filling
2771  AnaP0DReconVertex *anaP0DRecon = static_cast<AnaP0DReconVertex*>(MakeP0DReconVertex());
2772  _P0DReconVerticesMap[p0dVertex] = anaP0DRecon;
2773  }
2774 
2775  // Loop over all the P0D particles in the event
2776  // (not in a given AlgorithmResult since the index in the vector of particles in each vertex follows that convention)
2777  for (Int_t iP0D=0; iP0D<NP0DReconParticles; ++iP0D){
2778  ND::TP0DReconModule::TP0DParticle *p0dParticle = (ND::TP0DReconModule::TP0DParticle*) (*P0DReconParticles)[iP0D];
2779 
2780  // Is this object in this bunch?
2781  Int_t ibunch = _bunching.GetBunch(p0dParticle->Position.T(), RunID, IsMC, cosmic_mode);
2782 
2783  if (ibunch==-1){
2784  ibunch = NBUNCHES;
2785  }
2786 
2787  _bunchP0DParticles[ibunch].push_back(p0dParticle);
2788 
2789  // Make a pointer to a new AnaP0DReconParticle, ready for filling
2790  AnaP0DReconParticle *anaP0DRecon = static_cast<AnaP0DReconParticle*>(MakeP0DReconParticle());
2791  _P0DReconParticlesMap[p0dParticle] = anaP0DRecon;
2792  }
2793 
2794  // Loop over all the P0D clusters in the event
2795  // (not in a given AlgorithmResult since the index in the vector of clusters in each track/shower follows that convention)
2796  for (Int_t iP0D=0; iP0D<NP0DReconClusters; ++iP0D){
2797  ND::TP0DReconModule::TP0DCluster *p0dCluster = (ND::TP0DReconModule::TP0DCluster*) (*P0DReconClusters)[iP0D];
2798 
2799  // Is this object in this bunch?
2800  Int_t ibunch = _bunching.GetBunch(p0dCluster->Position.T(), RunID, IsMC, cosmic_mode);
2801 
2802  if (ibunch==-1){
2803  ibunch = NBUNCHES;
2804  }
2805 
2806  _bunchP0DClusters[ibunch].push_back(p0dCluster);
2807 
2808  // Make a pointer to a new AnaP0DReconCluster, ready for filling
2809  AnaP0DReconCluster *anaP0DRecon = static_cast<AnaP0DReconCluster*>(MakeP0DReconCluster());
2810  _P0DReconClustersMap[p0dCluster] = anaP0DRecon;
2811  }
2812  }
2813 
2814  //---- TEST HIGHLAND2-P0D ----
2815  if(_isUsingReconDirP0DNew) {
2816  GetBunchLocalP0DObjects();
2817  }
2818  //------------------------
2819 }
2820 
2821 //*****************************************************************************
2822 int oaAnalysisTreeConverter::GetGenieReactionCode(const std::string& reactionCode){
2823 //*****************************************************************************
2824 
2825  int code = 0;
2826 
2827  //if(!p_silent) cout << "3: " << reactionCode << endl;
2828  if(reactionCode.find("charm") == string::npos && reactionCode.find("Weak[CC],QES") != string::npos){
2829  code = 1;
2830  }
2831  else if(reactionCode.find("Weak[CC],RES") != string::npos){
2832  code = 11;
2833  }
2834  else if(reactionCode.find("charm") == string::npos && reactionCode.find("Weak[CC],DIS") != string::npos){
2835  code = 21;
2836  }
2837  else if(reactionCode.find("Weak[CC],COH") != string::npos){
2838  code = 16;
2839  }
2840  else if(reactionCode.find("Weak[NC],RES") != string::npos){
2841  code = 31;
2842  }
2843  else if(reactionCode.find("Weak[NC],QES") != string::npos){
2844  code = 51;
2845  }
2846  else if(reactionCode.find("Weak[NC],COH") != string::npos){
2847  code = 36;
2848  }
2849  else if(reactionCode.find("Weak[NC],DIS") != string::npos){
2850  code = 41;
2851  }
2852 
2853  return code;
2854 }
2855 
2856 //*****************************************************************************
2857 void oaAnalysisTreeConverter::GetBunchVertices(){
2858 //*****************************************************************************
2859 
2860  for (unsigned int i=0;i<NBUNCHES+1;i++) _bunchVertices[i].clear();
2861 
2862  for( int j=0; j<NVertices; j++) {
2863  ND::TGlobalReconModule::TGlobalVertex *globalVertex = (ND::TGlobalReconModule::TGlobalVertex*)Vertices->UncheckedAt(j);
2864  if(!globalVertex) std::cout << "debug error 1101 in oaAnalysisConverter" << std::endl; // shouldn't happen!
2865  if(!globalVertex) continue; // if no global vertex is found, go to the next vertex
2866 
2867  // check that the track is valid (the momentum is not NaN nor 0, etc)
2868  // if (!IsValidTrack(globalTrack)) continue;
2869 
2870  // --- Get the bunch number -----
2871  double tVertex = (*globalVertex).Position.T();
2872  int ibunch = _bunching.GetBunch(tVertex,RunID,IsMC, cosmic_mode);
2873 
2874  if (ibunch==-1){
2875  ibunch = NBUNCHES;
2876  }
2877 
2878  _bunchVertices[ibunch].push_back(globalVertex);
2879  }
2880 }
2881 
2882 //*****************************************************************************
2883 void oaAnalysisTreeConverter::FillVertexInfo(ND::TGlobalReconModule::TGlobalVertex& globalVertex, AnaVertex* vertex, AnaBunch* bunch, AnaSpill* spill) {
2884 //*****************************************************************************
2885 
2886  vertex->PrimaryIndex = globalVertex.PrimaryIndex;
2887  anaUtils::VectorToArray(globalVertex.Position,vertex->Position);
2888  vertex->Bunch = bunch->Bunch;
2889  anaUtils::VectorToArray(globalVertex.Variance,vertex->Variance);
2890  vertex->Chi2 = globalVertex.Quality;
2891  vertex->NDOF = globalVertex.NDOF;
2892 
2893  // Save all recon particles associated to this vertex.
2894  // Loop over the constituent particles of this global vertex.
2895  vertex->nParticles = 0;
2896  anaUtils::CreateArray(vertex->Particles, globalVertex.NConstituents);
2897  for (int i=0; i<globalVertex.NConstituents; i++) {
2898  ND::TGlobalReconModule::TVertexConstituent* vConst = (ND::TGlobalReconModule::TVertexConstituent*)(*(globalVertex.Constituents))[i];
2899 
2900  // this should never happen (except when masking FGD layers)
2901  if (vConst->PID<0) // it happens a lot in NuWro... why?
2902  std::cout << "WARNING: a reconstructed global vertex (position "
2903  << globalVertex.Position.X() << "," << globalVertex.Position.Y() << "," << globalVertex.Position.Z() << ")"
2904  << " is supposed to have an associated particle (PID = " << vConst->PID << ") which cannot be found (see bug 1161)" << std::endl;
2905  if (vConst->PID<0) continue;
2906 
2907  ND::TGlobalReconModule::TGlobalPID* globalTrack = (ND::TGlobalReconModule::TGlobalPID*)(*PIDs)[vConst->PID];
2908 
2909  // Find AnaTrack associated with this global vertex
2910  AnaTrack* track = FindTrack(globalTrack->UniqueID, bunch, spill);
2911 
2912  // Fill even with a NULL pointer, to know that somewhere there is this consituent
2913  vertex->Particles[vertex->nParticles++] = track;
2914 
2915  // Save vertices info in AnaTrack
2916  if (track) {
2917  track->ReconVertices.push_back(vertex);
2918  // choose the vertex more primary
2919  if ( ! track->ReconVertex || track->ReconVertex->PrimaryIndex > vertex->PrimaryIndex) {
2920  // also check it is in the same bunch, so it will be the same in the flattree
2921  if ( vertex->Bunch == track->Bunch) {
2922  track->ReconVertex = vertex;
2923  track->MomentumAtVertex = vConst->Momentum.Mag();
2924  anaUtils::VectorToArray((1 / track->MomentumAtVertex) * vConst->Momentum, track->DirectionAtVertex);
2925  }
2926  }
2927  }
2928  }
2929  // Sort tracks by momentum
2930  // std::sort(vertex->Particles, vertex->Particles + vertex->nParticles, AnaTrack::CompareMomentum);
2931 
2932  // Make truth-reco association
2933  // Loop over true vertices matched with this global vertex.
2934  for ( int i=0; i<globalVertex.NTrueVertices; i++) {
2935  ND::TTrueVertex* matchedTrueVertex = (ND::TTrueVertex*)((*(globalVertex.TrueVertices))[i]);
2936  FillTrueVerticesMatchInfo(matchedTrueVertex, vertex, bunch);
2937  }
2938  // Sort true vertices by cleanliness
2939  std::sort(vertex->TrueVerticesMatch.begin(), vertex->TrueVerticesMatch.end(), CompareCleanliness(vertex));
2940 
2941  // Let's keep also vertex->TrueVertex by now (the user could just called GetMainTrueVertex instead)
2942  vertex->TrueVertex = vertex->GetMainTrueVertex(false); // argument false to suppress warnings
2943 }
2944 
2945 //*****************************************************************************
2946 AnaTrack* oaAnalysisTreeConverter::FindTrack(int ID, AnaBunch* bunch, AnaSpill* spill){
2947 //*****************************************************************************
2948 
2949  // Compare the UniqueID to find the corresponding AnaTrack
2950  // AnaTrack already exists because it is saved for first
2951 
2952  std::vector<AnaParticleB*>::iterator ittrack;
2953 
2954  // Look first in the same bunch of the vertex
2955  for (ittrack = bunch->Particles.begin(); ittrack != bunch->Particles.end(); ittrack++) {
2956  if (ID == (*ittrack)->UniqueID) return static_cast<AnaTrack*>(*ittrack);
2957  }
2958 
2959  // If not found, look into OutOfBunch
2960  for (ittrack = spill->OutOfBunch->Particles.begin(); ittrack != spill->OutOfBunch->Particles.end(); ittrack++) {
2961  if (ID == (*ittrack)->UniqueID) return static_cast<AnaTrack*>(*ittrack);
2962  }
2963 
2964  // If not found, look into all bunches
2965  // in prod 5 this could happens only when the vertex is OutOfBunch
2966 #if ! VERSION_HAS_TIME_FITS
2967  if (bunch->Bunch != -1) {
2968  if ((int)NPIDs > (int)NMAXPARTICLES) std::cout << "minor error: track to be associated to a global vertex not found (UniqueID " << ID << "), likely because this event has too many tracks (" << NPIDs << ") and highland saves maximum " << NMAXPARTICLES << " tracks." << std::endl;
2969  else std::cout << "minor error in oaAnalysisConverter (ref 6056)" << std::endl;
2970  return NULL;
2971  }
2972 #endif
2973 
2974  // Look into all bunches
2975  std::vector<AnaBunchC*>::iterator itbunch;
2976  for (itbunch = spill->Bunches.begin(); itbunch != spill->Bunches.end(); itbunch++) {
2977  AnaBunchB* bunch0 = static_cast<AnaBunchB*>(*itbunch);
2978  for (ittrack = bunch0->Particles.begin(); ittrack != bunch0->Particles.end(); ittrack++) {
2979  if (ID == (*ittrack)->UniqueID) {
2980  if (bunch->Bunch != -1) { // often a global vertex out of bunch has constituent tracks in the near bunch
2981  int bunchStart = _bunching.GetBunch((*ittrack)->PositionStart[3],RunID,IsMC, cosmic_mode);
2982  int bunchEnd = _bunching.GetBunch((*ittrack)->PositionEnd[3],RunID,IsMC, cosmic_mode);
2983  std::cout << "INFO: this global vertex (in bunch " << bunch->Bunch << ") has an associated track stored in another bunch, which starts in bunch " << bunchStart << " and ends in bunch " << bunchEnd << std::endl;
2984  }
2985  return static_cast<AnaTrack*>(*ittrack);
2986  }
2987  }
2988  }
2989 
2990  if ((int)NPIDs > (int)NMAXPARTICLES) std::cout << "minor error: track to be associated to a global vertex not found (UniqueID " << ID << "), likely because this event has too many tracks (" << NPIDs << ") and highland saves maximum " << NMAXPARTICLES << " tracks." << std::endl;
2991  else std::cout << "minor error: track to be associated to a global vertex not found in bunch " << bunch->Bunch << ": in prod6 it should be a flipped track with start position in a bunch not yet loaded!" << std::endl;
2992 
2993  return NULL;
2994 }
2995 
2996 //*****************************************************************************
2997 void oaAnalysisTreeConverter::FillTrueVerticesMatchInfo(ND::TTrueVertex* matchedTrueVertex, AnaVertex* vertex, AnaBunch* bunch){
2998 //*****************************************************************************
2999 
3000  // Compare the ID to find the corresponding AnaTrueVertex.
3001  // Set Cleanliness and Completeness that are truth-reco quantities.
3002 
3003  // Loop over all AnaTrueVertex
3004  std::vector<AnaTrueVertexB*>::iterator it;
3005  for (it = _spill->TrueVertices.begin(); it != _spill->TrueVertices.end(); it++) {
3006  if (matchedTrueVertex->ID != (*it)->ID) continue;
3007 
3008  // Cleanliness and Completenss were wrong in TGlobalReconModule, fixed from oaAnalysis v5r30
3009  // anyway it is better to re-evaluate them here where objects are "bunched"
3010 // AnaRecTrueMatch* thisRecTrueMatch = new AnaRecTrueMatch;
3011 // thisRecTrueMatch->Cleanliness = matchedTrueVertex->Pur;
3012 // thisRecTrueMatch->Completeness = matchedTrueVertex->Eff;
3013  AnaRecTrueMatch* thisRecTrueMatch = FillCompletenessCleanliness(vertex, bunch, *it);
3014 
3015  AnaTrueVertex* tvertex = static_cast<AnaTrueVertex*>(*it);
3016  pair<AnaTrueVertexB*, AnaRecTrueMatch> myPair(tvertex, *thisRecTrueMatch);
3017  vertex->TrueVerticesMatch.push_back(myPair);
3018  tvertex->ReconVertices.push_back(vertex);
3019  return; // Stop when association is found.
3020  }
3021 
3022  std::cout << "minor error: matchedTrueVertex not found, ID:" << matchedTrueVertex->ID << std::endl;
3023 }
3024 
3025 //*************************************************************
3026 AnaRecTrueMatch* oaAnalysisTreeConverter::FillCompletenessCleanliness(AnaVertex* vertex, AnaBunch* bunch, AnaTrueVertexB* truevertex){
3027 //*************************************************************
3028 
3029  // Cleanliness and Completenss were wrong in TGlobalReconModule, fixed from oaAnalysis v5r30
3030  // anyway it is better to re-evaluate them here where objects are "bunched"
3031  // Let's evalutate completeness and cleanliness only with in-bunch tracks, so it will be the same for flat trees
3032 
3033  // trueV constituent track: loop over all PIDs, and store those that come from this true vertex
3034  std::vector<AnaTrackB*> trueVconst;
3035  std::set<AnaTrueObjectC*> trueVconst_true;
3036  AnaTrackB* tracks[NMAXPARTICLES];
3037  // Only tracks in FGD OR TPC are used by the global vertex algorithm
3038  int ntracks = anaUtils::GetAllTracksUsingFGDorTPC(*bunch, tracks);
3039  for (int i = 0; i < ntracks; i++) {
3040 
3041  AnaTrack* track = static_cast<AnaTrack*>(tracks[i]);
3042 
3043  if ( ! track->TrueObject) continue; // track without true
3044  if (track->GetTrueParticle()->ParentID != 0) continue; // true track not primary
3045  if (track->NNodes > 0) ; else continue; // track not used in vertexing algorithm
3046  if (track->Status != 1) continue; // track not used in vertexing algorithm
3047 
3048  // double counting broken tracks
3049  if(track->GetTrueParticle()->TrueVertex == truevertex) trueVconst.push_back(track);
3050  // NOT double counting broken tracks
3051  if(track->GetTrueParticle()->TrueVertex == truevertex) trueVconst_true.insert(track->TrueObject);
3052  }
3053 
3054  int nTrueVconst = (int)trueVconst.size();
3055  int nTrueVconst_true = (int)trueVconst_true.size();
3056  int nRecoVconst = 0; // count only those in this bunch, as for the trueV
3057  int nCommonConst = 0;
3058  int nRecoVconst_true = 0; // count only those in this bunch, as for the trueV
3059  int nCommonConst_true = 0;
3060 
3061  //Loop over vertex constituent tracks
3062  std::set<AnaTrueObjectC*> recoVconst_true;
3063  std::vector<AnaTrackB*>::iterator itrecoVconst;
3064  for (int i = 0; i < vertex->nParticles; i++) {
3065  AnaTrack* itrecoVconst = static_cast<AnaTrack*>(vertex->Particles[i]);
3066  if ( ! itrecoVconst) continue;
3067 
3068  if (itrecoVconst->Bunch != bunch->Bunch) continue;
3069 
3070  nRecoVconst++;
3071 
3072  //Check if they match true vertex constituent tracks
3073  std::vector<AnaTrackB*>::iterator ittrueVconst;
3074  for (ittrueVconst = trueVconst.begin(); ittrueVconst != trueVconst.end(); ittrueVconst++) {
3075  if (itrecoVconst->UniqueID == (*ittrueVconst)->UniqueID) {
3076  nCommonConst++;
3077  break;
3078  }
3079  }
3080 
3081  //Check if they match true vertex constituent tracks NOT BROKEN
3082  if ( ! itrecoVconst->TrueObject) {
3083  nRecoVconst_true++;
3084  continue;
3085  }
3086 
3087  double checkBroken=recoVconst_true.size();
3088  recoVconst_true.insert(itrecoVconst->TrueObject);
3089  if (checkBroken == recoVconst_true.size()) continue;
3090 
3091  std::set<AnaTrueObjectC*>::iterator ittrueVconst_true;
3092  for (ittrueVconst_true = trueVconst_true.begin(); ittrueVconst_true != trueVconst_true.end(); ittrueVconst_true++) {
3093  if (itrecoVconst->TrueObject->ID == (*ittrueVconst_true)->ID) {
3094  nCommonConst_true++;
3095  break;
3096  }
3097  }
3098 
3099  }
3100  nRecoVconst_true += (int)recoVconst_true.size();
3101 
3102  AnaRecTrueMatch* thisRecTrueMatch = new AnaRecTrueMatch;
3103  if (nRecoVconst==0) thisRecTrueMatch->Cleanliness = 0;
3104 // else thisRecTrueMatch->Cleanliness = (double)nCommonConst/nRecoVconst; // double counting broken tracks
3105  else thisRecTrueMatch->Cleanliness = (double)nCommonConst_true/nRecoVconst_true; // NOT double counting broken tracks
3106  if (nTrueVconst==0) thisRecTrueMatch->Completeness = 0;
3107 // else thisRecTrueMatch->Completeness = (double)nCommonConst/nTrueVconst; // double counting broken tracks
3108  else thisRecTrueMatch->Completeness = (double)nCommonConst_true/nTrueVconst_true; // NOT double counting broken tracks
3109 
3110  return thisRecTrueMatch;
3111 }
3112 
3113 //*****************************************************************************
3114 void oaAnalysisTreeConverter::DeleteBadObjects(AnaSpill* spill){
3115 //*****************************************************************************
3116 
3117  // Delete all the objects associated with a Pauli blocked vertices
3118  // (single gamma and 1pi Pauli-blocked vertices must be discarded from the truth tree
3119  // but kept in the NRooTrackerVtx, see bugzilla 1011)
3120  // or with a coherent interaction on hydrogen, wrongly produced because of a bug in neut,
3121  // both in prod 5 and 6, see bugzilla 1056:
3122 
3123  // Also Delete true vertices with all true tracks (and their associated recon tracks)
3124  // fully contained in the specified subdetectors. Also deletes the true tracks and the recon tracks in that case
3125 
3126  if ( ! _foundCohOnH && ! _foundPauliBlocked && _containedTrueParticles.size() == 0) return;
3127 
3128  if ( ! _discardPauliBlocked && _foundPauliBlocked)
3129  std::cout << "There is a Pauli blocked vertices but their deletion is not enabled, why?!? (see bugzilla 1011)" << std::endl;
3130  if ( ! _discardCohOnH && _foundCohOnH)
3131  std::cout << "There is a coherent interaction on hydrogen but their deletion is not enabled, why?!? (see bugzilla 1056)" << std::endl;
3132  if ( ! _discardPauliBlocked && ! _discardCohOnH && _containedTrueParticles.size() == 0) return;
3133 
3134  // loop over true vertices (without deleting them, by now)
3135  std::vector<AnaTrueVertexB*>::iterator truevertexB;
3136  for (truevertexB = spill->TrueVertices.begin(); truevertexB != spill->TrueVertices.end();) {
3137  AnaTrueVertex* truevertex = static_cast<AnaTrueVertex*>(*truevertexB);
3138 
3139  // if not fully contained and not bad vertex, continue
3140  if ( ! IsFullyContained(*truevertex)){
3141  if ( ( ! truevertex->IsCohOnH && ! truevertex->IsPauliBlocked) ||
3142  (truevertex->IsPauliBlocked && ! _discardPauliBlocked) ||
3143  (truevertex->IsCohOnH && ! _discardCohOnH) ) {
3144  truevertexB++;
3145  continue;
3146  }
3147  }
3148 
3149 // if (truevertex->nTrueParticles > 0) std::cout << "OK, let's remove ID " << truevertex->ID << " , " << truevertex->IsPauliBlocked << " , " << truevertex->IsCohOnH << "\n";
3150 
3151  // loop over global vertices of this truevertex (and delete them at the end)
3152  std::vector<AnaVertexB*>::iterator vertexB;
3153  for (vertexB = truevertex->ReconVertices.begin(); vertexB != truevertex->ReconVertices.end(); vertexB++) {
3154  // loop over ReconParticles of this global vertex (they might be associated to a different true vertex);
3155  for (int i=0; i < (*vertexB)->nParticles; i++) { // (this is a **, cannot be done with the iterator)
3156  AnaTrack* track = dynamic_cast<AnaTrack*>((*vertexB)->Particles[i]);
3157  if (!track) continue;
3158  if ( ! track) std::cout << std::endl << "ERROR: this track has to exist otherwise something is wrong somewhere else!"
3159  << " The process will now crash (see bug 1172)." << std::endl << std::endl;
3160 
3161  // delete the pointer between this track and this global vertex (which will be deleted)
3162  int size_orig = (int)track->ReconVertices.size(); (void)size_orig;
3163  std::vector<AnaVertexB*>::iterator vertexB2;
3164  for (vertexB2 = track->ReconVertices.begin(); vertexB2 != track->ReconVertices.end(); vertexB2++) {
3165  if (*vertexB2 == *vertexB) {
3166 // std::cout << "INFO: yes it happens! ref. 9885" << std::endl; // yes it happens!
3167  vertexB2 = track->ReconVertices.erase(vertexB2);
3168  break;
3169  }
3170  }
3171 // std::cout << size_orig << " ReconVertices vs " << track->ReconVertices.size() << std::endl;
3172  // If a global vertex (associated to a bad true vertex) has a track without truth association,
3173  // better not deleting that track, since it has a loose relation with the true vertex:
3174  // we cannot assume the global vertex is correct in the association in that case (see bug 1056).
3175  // (And also, even though it's unlikely, the TrueParticle might be missing only because was not saved, for not having G4 points)
3176  if ( ! track->TrueObject) continue;
3177 
3178  // do not delete the tracks here to allow the next loop truevertex->ReconParticles
3179  if (track->GetTrueParticle()->TrueVertex == (*truevertexB)) continue;
3180 
3181  // if this track is associated to another truevertex,
3182  // delete the pointer between this global vertex and that other true vertex
3183  AnaTrueVertex* anothertrueV = static_cast<AnaTrueVertex*>(track->GetTrueParticle()->TrueVertex);
3184  size_orig = (int)anothertrueV->ReconVertices.size(); (void)size_orig;
3185  for (vertexB2 = anothertrueV->ReconVertices.begin(); vertexB2 != anothertrueV->ReconVertices.end(); vertexB2++) {
3186  if (*vertexB2 == *vertexB) {
3187 // std::cout << "INFO: yes it happens! ref. 9886" << std::endl; // yes it happens!
3188  vertexB2 = anothertrueV->ReconVertices.erase(vertexB2);
3189  break;
3190  }
3191  }
3192 // std::cout << size_orig << " ReconVertices vs " << anothertrueV->ReconVertices.size() << std::endl;
3193 
3194  }
3195 
3196  // now delete this global vertex
3197  DeleteRecoVertex(spill,*vertexB);
3198  }
3199 
3200  // loop over ReconParticles of this truevertex and delete them
3201  // (they might not have had a global vertex associated)
3202  std::vector<AnaParticleB*>::iterator part;
3203  for (part = truevertex->ReconParticles.begin(); part != truevertex->ReconParticles.end(); part++) {
3204  DeleteRecoParticle(spill,*part);
3205  }
3206 
3207  // loop over TrueParticles of this true vertex and delete them
3208  // (this is a **, cannot be done with the iterator)
3209  for (int i=0; i < truevertex->nTrueParticles; i++) {
3210  AnaTrueParticleB* truePartB = truevertex->TrueParticles[i];
3211  DeleteTrueParticle(spill,truePartB);
3212  }
3213 
3214  // delete the bunch of this true vertex if it is empty (not if OutOfBunch)
3215  if ((*truevertexB)->Bunch != -1) {
3216 
3217  std::vector<AnaBunchC*>::iterator bunchC;
3218  for (bunchC = spill->Bunches.begin(); bunchC != spill->Bunches.end();) {
3219  AnaBunch* bunch = static_cast<AnaBunch*>(*bunchC);
3220 
3221  if ((*bunchC)->Bunch != (*truevertexB)->Bunch) {
3222  bunchC++;
3223  continue;
3224  }
3225 
3226  // if emptied, delete this bunch
3227  if (bunch->IsEmpty()) {
3228  int size_orig = (int)spill->Bunches.size(); (void)size_orig;
3229  delete *bunchC;
3230  bunchC = spill->Bunches.erase(bunchC);
3231 // std::cout << size_orig << " bunches vs " << spill->Bunches.size() << std::endl;
3232  }
3233 
3234  // break when bunch is found
3235  break;
3236  } // end loop over bunches
3237 
3238  }
3239 
3240  // Delete this bad true vertex (maybe it would be better to put
3241  // a bad quality cut in baseAnalysis to show and remind what's going on)
3242  delete *truevertexB;
3243  truevertexB = spill->TrueVertices.erase(truevertexB);
3244 // truevertexB++; // if not deleted, go to next iterator
3245 
3246  } // endl loop over true vertices
3247 
3248 }
3249 
3250 //*****************************************************************************
3251 void oaAnalysisTreeConverter::DeleteTrueParticle(AnaSpill* spill, AnaTrueParticleB* trackToDelete){
3252 //*****************************************************************************
3253 
3254  // first set to null TPCsegment->trackToDelete
3255  // since they might belong to a globaltrack associated to another good true track (very rare)
3256 
3257  //------ create outofbunch+bunches --------------
3258  std::vector<AnaBunchC*> outplusbunches;
3259  for (int b = 0; b < (int)spill->Bunches.size(); b++) {
3260  outplusbunches.push_back(spill->Bunches[b]);
3261  }
3262  // loop also in OutOfBunch, for last since it is unlikely
3263  outplusbunches.push_back(spill->OutOfBunch);
3264 
3265  //------ Loop over outofbunch+bunches --------------
3266  for (int b = 0; b < (int)outplusbunches.size(); b++) {
3267 
3268  AnaBunchB* bunch = static_cast<AnaBunchB*>(outplusbunches[b]);
3269 
3270  int size_orig = (int)bunch->Particles.size(); (void) size_orig;
3271 
3272  // loop over Tracks
3273  std::vector<AnaParticleB*>::iterator it;
3274  for (it = bunch->Particles.begin(); it != bunch->Particles.end(); it++) {
3275  AnaTrack* track = dynamic_cast<AnaTrack*>(*it);
3276  if (!track) continue;
3277 
3278  // loop over TPCSegments
3279  for (int i=0; i<track->nTPCSegments; i++) {
3280  if (track->TPCSegments[i]->TrueObject == trackToDelete && track->TrueObject != trackToDelete) {
3281  std::cout << "INFO: found a TPCsegment associated to a trueTrack to be deleted (see bug 1011 and 1056) and to a reconTrack not to be deleted (which is associated to a different trueTrack)! Keep the segment but set to NULL the link to its trueTrack." << std::endl;
3282  track->TPCSegments[i]->TrueObject = NULL;
3283  }
3284  }
3285 
3286  // ---- TEST HIGHLAND2-P0D ----
3287  // now P0DSegments have also a TrueParticle associated
3288  for (int i=0; i<track->nP0DSegments; i++) {
3289  if (track->P0DSegments[i]->TrueObject == trackToDelete && track->TrueObject != trackToDelete) {
3290  std::cout << "INFO: found a P0Dsegment2 associated to a trueTrack to be deleted (see bug 1011 and 1056) and to a reconTrack not to be deleted (which is associated to a different trueTrack)! Keep the segment but set to NULL the link to its trueTrack." << std::endl;
3291  track->P0DSegments[i]->TrueObject = NULL;
3292  }
3293  }
3294  // ----------------------------
3295 
3296  } // end of loop over Tracks
3297 
3298  } // end of loop over bunches
3299 
3300 
3301  // now find the true track in the spill and delete it there
3302  int size_orig = (int)spill->TrueParticles.size(); (void)size_orig;
3303  bool found = false;
3304  // loop over true tracks
3305  std::vector<AnaTrueParticleB*>::iterator part;
3306  for (part = spill->TrueParticles.begin(); part != spill->TrueParticles.end();) {
3307 
3308  if (*part != trackToDelete) {
3309  part++;
3310  continue;
3311  }
3312 
3313  // perform deleting
3314  delete *part;
3315  part = spill->TrueParticles.erase(part);
3316  found = true;
3317  break;
3318  }
3319 
3320 // std::cout << size_orig << " truetracks vs " << spill->TrueParticles.size() << std::endl;
3321  if ( ! found) std::cout << "error in oaAnalysisTreeConverter::DeleteTrueParticle: track to delete not found!!!" << std::endl;
3322 
3323 }
3324 
3325 //*****************************************************************************
3326 void oaAnalysisTreeConverter::DeleteRecoParticle(AnaSpill* spill, AnaParticleB* particleToDelete){
3327 //*****************************************************************************
3328 
3329  // All global vertices should be also linked to the true vertices, and should have been already deleted
3330  AnaTrack* track = dynamic_cast<AnaTrack*>(particleToDelete);
3331  if (!track) return;
3332  if ((int)track->ReconVertices.size()>0) {
3333  std::cout << "ERROR in DeleteRecoParticle (ref. 9884): particleToDelete->ReconVertices.size = "
3334  << track->ReconVertices.size() << std::endl;
3335  }
3336 
3337  //------ create outofbunch+bunches --------------
3338  std::vector<AnaBunchC*> outplusbunches;
3339  for (int b = 0; b < (int)spill->Bunches.size(); b++) {
3340  outplusbunches.push_back(spill->Bunches[b]);
3341  }
3342  // loop also in OutOfBunch, for last since it is unlikely
3343  outplusbunches.push_back(spill->OutOfBunch);
3344 
3345  //------ Loop over outofbunch+bunches --------------
3346  bool found = false;
3347  for (int b = 0; b < (int)outplusbunches.size(); b++) {
3348 
3349  AnaBunchB* bunch = static_cast<AnaBunchB*>(outplusbunches[b]);
3350 
3351  int size_orig = (int)bunch->Particles.size(); (void) size_orig;
3352 
3353  // loop over Particles
3354  std::vector<AnaParticleB*>::iterator part;
3355  for (part = bunch->Particles.begin(); part != bunch->Particles.end();) {
3356 
3357  if (*part != particleToDelete) {
3358  part++;
3359  continue;
3360  }
3361 
3362  // perform deleting
3363  delete *part;
3364  part = bunch->Particles.erase(part);
3365 
3366  found = true;
3367  break;
3368 
3369  } // end of loop over Particles
3370 
3371 // if (found) std::cout << size_orig << " reco particles vs " << bunch->Particles.size() << std::endl;
3372 
3373  if (found) break;
3374 
3375  } // end of loop over outofbunch+bunches
3376 
3377  if ( ! found) std::cout << "error in oaAnalysisTreeConverter::DeleteRecoParticle: particle to delete not found!!!" << std::endl;
3378 
3379 }
3380 
3381 //*****************************************************************************
3382 void oaAnalysisTreeConverter::DeleteRecoVertex(AnaSpill* spill, AnaVertexB* vertexToDelete){
3383 //*****************************************************************************
3384 
3385  //------ create outofbunch+bunches --------------
3386  std::vector<AnaBunchC*> outplusbunches;
3387  for (int b = 0; b < (int)spill->Bunches.size(); b++) {
3388  outplusbunches.push_back(spill->Bunches[b]);
3389  }
3390  // loop also in OutOfBunch, for last since it is unlikely
3391  outplusbunches.push_back(spill->OutOfBunch);
3392 
3393  //------ Loop over outofbunch+bunches --------------
3394  bool found = false;
3395  for (int b = 0; b < (int)outplusbunches.size(); b++) {
3396 
3397  AnaBunchB* bunch = static_cast<AnaBunchB*>(outplusbunches[b]);
3398 
3399  int size_orig = (int)bunch->Vertices.size(); (void) size_orig;
3400 
3401  // loop over Vertices
3402  std::vector<AnaVertexB*>::iterator vertexB;
3403  for (vertexB = bunch->Vertices.begin(); vertexB != bunch->Vertices.end();) {
3404 
3405  if (*vertexB != vertexToDelete) {
3406  vertexB++;
3407  continue;
3408  }
3409 
3410  // perform deleting
3411  delete *vertexB;
3412  vertexB = bunch->Vertices.erase(vertexB);
3413 
3414  found = true;
3415  break;
3416 
3417  } // end of loop over Vertices
3418 
3419 // if (found) std::cout << size_orig << " reco vertices vs " << bunch->Vertices.size() << std::endl;
3420 
3421  if (found) break;
3422 
3423  } // end of loop over outofbunch+bunches
3424 
3425  if ( ! found) std::cout << "error in oaAnalysisTreeConverter::DeleteRecoVertex: vertex to delete not found!!!" << std::endl;
3426 }
3427 
3428 //*****************************************************************************
3429 bool oaAnalysisTreeConverter::HasNonContainedReconParticles(AnaTrueParticleB* trueParticleB){
3430 //*****************************************************************************
3431 
3432  AnaTrueParticle* trueParticle = static_cast<AnaTrueParticle*>(trueParticleB);
3434 
3435  // find in which det the true particle is fully contained
3436  for(Int_t idet=0;idet<trueParticle->nDetCrossings;idet++){
3437  if (SubDetId::GetDetectorUsed(trueParticle->DetCrossings[idet]->Detector, SubDetId::kDSECAL)) det = SubDetId::kDSECAL;
3438  else if(SubDetId::GetDetectorUsed(trueParticle->DetCrossings[idet]->Detector, SubDetId::kTECAL)) det = SubDetId::kTECAL;
3439  else if(SubDetId::GetDetectorUsed(trueParticle->DetCrossings[idet]->Detector, SubDetId::kPECAL)) det = SubDetId::kPECAL;
3440  else if(SubDetId::GetDetectorUsed(trueParticle->DetCrossings[idet]->Detector, SubDetId::kSMRD)) det = SubDetId::kSMRD;
3441  }
3442 
3443  // loop over trueParticle->ReconParticles
3444  for (std::vector<AnaParticleB*>::iterator it=trueParticle->ReconParticles.begin();it!=trueParticle->ReconParticles.end();it++){
3445  // if this recon particle is not fully contained in the same det, return true
3446  if (!anaUtils::TrackUsesOnlyDet(**it,det)) return true;
3447  }
3448 
3449  // should we check also global vertices? see bug 1174
3450  // loop over global vertices of AnaTrueParticle::AnaTrueVertex
3451  AnaTrueVertex* trueVertex = static_cast<AnaTrueVertex*>(trueParticleB->TrueVertex);
3452  for (std::vector<AnaVertexB*>::iterator it=trueVertex->ReconVertices.begin(); it!=trueVertex->ReconVertices.end(); it++){
3453  // if this global vertex is not in the same det, return true
3454  if (!anaUtils::InDetVolume(det,(*it)->Position)) return true;
3455  }
3456 
3457  return false;
3458 }
3459 
3460 //*****************************************************************************
3461 bool oaAnalysisTreeConverter::IsFullyContained(const AnaTrueVertexB& trueVertex){
3462 //*****************************************************************************
3463 
3464  // Check that all true particles (and the recon particles associated) in the vertex are fully contained in a detector
3465 
3466  bool contained=true;
3467  // loop over true particles in the true trueVertex
3468  for (Int_t j1=0;j1<trueVertex.nTrueParticles;j1++){
3469  bool found=false;
3470  // and over fully contained true particles
3471  for (size_t j2=0;j2<_containedTrueParticles.size();j2++){
3472  if (trueVertex.TrueParticles[j1] == _containedTrueParticles[j2] && !HasNonContainedReconParticles(_containedTrueParticles[j2])){
3473  found=true;
3474  break;
3475  }
3476  }
3477  // if the trueVertex contains not fully contained particles, it is not fully contained
3478  if (!found){
3479  contained=false;
3480  break;
3481  }
3482  }
3483 
3484  return contained;
3485 }
3486 
Float_t dEdxexpMuon
Expected dE/dx for a muon, based on the reconstructed momentum.
Float_t Pullmu
Muon pull of the segment: (dEdxMeas-dEdxexpMuon)/dEdxSigmaMuon.
Float_t Completeness
The completeness of the true-reco matching.
bool InActive
If the particle passes through an active part of the subdetector.
AnaTrueVertexB * TrueVertex
Pointer to the AnaTrueVertexB of the interaction that created this AnaTrueParticleB.
Float_t DirectionStartFlip[3]
Direction at the start for the main PID hypothesis and reverse sense.
int nP0DSegments
How many P0D tracks are associated with this track.
Float_t PositionStart[4]
The reconstructed start position of the particle.
Float_t MomentumAtVertex
The reconstructed momentum of the track, at the most primary global vertex (if exists).
Representation of a global track.
AnaTrueVertexB * TrueVertex
AnaP0DParticleB * P0DSegments[NMAXP0DS]
The P0D segments that contributed to this global track.
unsigned long Detector
Int_t InputFileIndex
Index of the input file producing this spill.
Int_t NuPDG
The PDG code of the incoming neutrino.
Int_t LeptonPDG
The PDG code of the primary outgoing electron/muon.
unsigned long Detector
int nDetCrossings
The number of DetCrossing objects.
int GetParameterI(std::string)
Get parameter. Value is returned as integer.
Definition: Parameters.cxx:217
Float_t MomentumEle
Momentum from refitting the track assuming the electron hypothesis.
bool IsTruePrimaryPi0DecayPhoton
Is this a true primary pi0 decay photon or the child of one?
int nTrueParticles
How many true particles are associated with this vertex.
Int_t NDOF
The number of degrees of freedom of the fit using a Kalman filter.
Float_t ExitPosition[4]
for each subdetector tell the exit position
Float_t Cleanliness
The cleanliness of the true-reco matching.
Int_t Detector
Definition: DataClasses.hxx:40
bool FGDCosmic
FGD cosmic trigger flag.
Int_t DetFlag[7]
Float_t dEdxexpProton
Expected dE/dx for a proton, based on the reconstructed momentum.
P0DRecon Vertex.
AnaECALParticleB * ECALSegments[NMAXECALS]
The ECAL segments that contributed to this global track.
int nECALSegments
How many ECAL tracks are associated with this track.
std::vector< std::pair< AnaTrueVertexB *, AnaRecTrueMatchB > > TrueVerticesMatch
The true vertices that are associated with this global vertex, with the related cleanliness and compl...
Int_t Status
The Status of the fit of this reconstructed object.
Float_t LeptonDir[3]
The direction of the primary outgoing electron/muon.
void SetIsSandMC()
Set whether this event is from Sand MC.
Representation of the ND280 trigger bits.
Int_t NDOF
The number of degrees of freedom when the track was fitted with a Kalman filter.
Float_t Pullp
Proton pull, according to FGD information.
AnaSMRDParticleB * SMRDSegments[NMAXSMRDS]
The SMRD segments that contributed to this global track.
Float_t Variance[4]
The variance values of the fit using a Kalman filter.
bool SetSoftwareVersion(const std::string &ver)
Set the software version.
Definition: Header.cxx:257
void ConvertLocalDetEnumToBitField(unsigned long &det, int index, SubDetId::SubDetEnum subdet_enum)
Convert the detector used array to the bit field used by psyche given a SubDetEnum.
Representation of a true Monte Carlo vertex.
Float_t DirectionEnd[3]
The reconstructed end direction of the particle.
Float_t E
Input to the pull calculations. Needs to be documented properly in oaAnalysis.
Float_t Position[4]
The identified position of the global vertex.
Float_t Pullpi
Pion pull of the segment: (dEdxMeas-dEdxexpPion)/dEdxSigmaPion.
std::vector< AnaTrueVertexB * > TrueVertices
The true MC vertices used in this spill.
std::vector< AnaBunchC * > Bunches
The reconstructed objects, split into timing bunches.
Float_t Pullno
Dummy pull. If the FGD pulls weren&#39;t set, this is set to 1.
Int_t NNodes
The number of nodes in the reconstructed object.
virtual Int_t GetSpill(Long64_t &entry, AnaSpillC *&spill)
Float_t ProtonDir[3]
The direction of the primary outgoing protons listed first (likely the interacted one)...
Int_t GParentPDG
The PDG code of this particle&#39;s grandparent, or 0 if there is no grandparent.
Float_t TargetDir[3]
The direction of the target nucleus.
Float_t Pullpi
Pion pull, according to FGD information.
AnaTPCParticleB * TPCSegments[NMAXTPCS]
The TPC segments that contributed to this global track.
Representation of the ND280 data quality flags.
Float_t Vertex1x1
Vertex activity variables.
Float_t AvgTime
Time charged averaged over hits.
Int_t SpillsSincePreviousSavedSpill
Int_t Bunch
The bunch of the track, based on the PositionStart.T()
Float_t dEdxSigmaProton
Expected error on the dE/dx measurement, for the proton hypothesis.
P0DRecon Particle.
AnaTrueObjectC * TrueObject
The link to the true oject that most likely generated this reconstructed object.
Float_t Length
The number of hits in the reconstructed object.
AnaToF ToF
Times of flight between pairs of detectors.
Int_t GetCurrentGeomID() const
Retrieve current geometry ID.
AnaEventInfoB * EventInfo
Run, sunrun, event, time stamp, etc.
static bool GetDetectorUsed(unsigned long BitField, SubDetId::SubDetEnum det)
Method to see if a certain subdetector or subdetector system is used.
Definition: SubDetId.cxx:40
Float_t Momentum
The initial momentum of the true particle.
virtual bool AddFileToTChain(const std::string &inputString)
Add the file specified to fChain, and any friend chains that were set up.
AnaTrueParticleB ** TrueParticles
The true particles associated with this vertex.
This Ana* object is used to flatten TECALReconObjects from ReconDir/TrackerECal.
Float_t MomentumErrorProton
Error on momentum from refitting the track assuming the proton hypothesis.
void IncrementPOTByFile(Double_t pot, bool bySpillPOT=true)
Definition: Header.cxx:150
Float_t AvgTime
Average Time for the iso FGD hits.
AnaBunchB * OutOfBunch
Reconstructed objects that didn&#39;t fit into one of the timing bunches.
Int_t Bunch
The bunch of the global vertex, based on the Position.T()
Int_t TargetPDG
The PDG code of the target nucleus.
Definition: DataClasses.hxx:85
Float_t RangeMomentumMuon
Momentum by range calculated with muon hypothesis.
std::vector< AnaParticleB * > ReconParticles
Vector of pointers to AnaParticle&#39;s associated with this true particle.
Float_t Chi2
The chi2 value of the fit using a Kalman filter.
void AddChain(const std::string &name, const std::string &name_path="")
std::string GetParameterS(std::string)
Get parameter. Value is returned as string.
Definition: Parameters.cxx:242
Float_t dEdxexpPion
Expected dE/dx for a pion, based on the reconstructed momentum.
Int_t VertexID
The TruthVertexID of the AnaTrueVertexB of the interaction that created this AnaTrueParticleB.
int GetAllTracksUsingFGDorTPC(const AnaBunchB &bunch, AnaTrackB *selTracks[])
Int_t UniqueID
The UniqueID of this reconstructed object.
Float_t dEdxexpEle
Expected dE/dx for an electron, based on the reconstructed momentum.
Float_t Pullmu
Muon pull, according to FGD information.
Float_t Charge
The reconstructed charge of the particle.
Int_t ID
The ID of the trueObj, which corresponds to the ID of the TTruthParticle that created it...
Int_t SubRun
The subrun number.
std::vector< AnaVertexB * > Vertices
Int_t Spill
Spill number from BeamSummaryDataModule::ND280Spill.
Float_t Chi2
The chi2 value when the track was fitted using a Kalman filter.
int nSMRDSegments
How many SMRD tracks are associated with this track.
Representation of detector time info.
Definition: DataClasses.hxx:11
Int_t fCurrent
current Tree number in a TChain
Float_t POTCT4
The POT from CT4 for this spill. This is only needed for P5 files.
Float_t MomentumError
Error of the momentum at the start of the segment.
Float_t ProtonMom
The momentum of the primary outgoing protons listed first (likely the interacted one).
Float_t MomentumFlip
Momentum for the main PID hypothesis and reverse sense.
Float_t ShowerPosition[3]
The position of the shower-fit to this object by ecalRecon.
Float_t LeptonMom
The momentum of the primary outgoing electron/muon.
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
Representation of a true Monte Carlo vertex.
Definition: DataClasses.hxx:50
int nTPCSegments
How many TPC tracks are associated with this track.
Representation of a true Monte Carlo trajectory/particle.
TVector3 UpstreamHits_Position[2]
Float_t NuEnergy
The true energy of the incoming neutrino.
virtual bool IsEmpty() const
Returns true if the bunch is completely empty.
TChain * GetChain(const std::string &name="")
UInt_t GeomID
Is this the original Spill or a clone.
Float_t Position[4]
The position the true interaction happened at.
Float_t dEdxSigmaKaon
Expected error on the dE/dx measurement, for the proton hypothesis.
Float_t dEdxSigmaEle
Expected error on the dE/dx measurement, for the electron hypothesis.
Float_t EntrancePosition[4]
for each subdetector tell the entrance position
AnaBeamB * Beam
The beam quality flags for this spill.
std::vector< AnaVertexB * > ReconVertices
Vector of pointers to AnaVertexB (global vertices) associated with this true vertex.
AnaDetCrossingB ** DetCrossings
Representation of a detector crossing info for a true particle (G4 trajectory).
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
Float_t DirectionAtVertex[3]
The reconstructed direction of the track at the most primary global vertex (if exists).
Float_t EFieldRefitMomentum
Reconstructed momentum with the E-field distortion corrections.
Int_t PDG
The PDG code of this particle.
Int_t SpillNumber
Spill number from BeamSummaryDataModule::BeamSummaryData::SpillNumber.
Float_t MomentumErrorMuon
Error on momentum from refitting the track assuming the muon hypothesis.
unsigned long Detector
Int_t Detectors
Int_t NHits
The number of hits in the particle.
Int_t ParentPDG
The PDG code of this particle&#39;s immediate parent, or 0 if there is no parent.
Int_t BeamRunNumber
bool GetIsMC() const
Return whether this spill is from Monte Carlo or not.
std::vector< AnaFgdTimeBinB * > FgdTimeBins
The FGD time bins.
Float_t MomentumErrorEle
Error on momentum from refitting the track assuming the electron hypothesis.
Float_t dEdxMeas
dE/dx as measured by the TPC.
Float_t TimeEnd
End time.
Definition: DataClasses.hxx:46
Representation of a global track.
bool TripTCosmic
TripT cosmic trigger flag.
AnaTrueVertexB * GetMainTrueVertex(bool warning=true)
The main true vertex that is associated with this global vertex.
Float_t MomentumEnd
The reconstructed momentum of the particle, at the end position.
Int_t EventTime
The ND280 subrun number.
AnaParticleB ** Particles
Float_t ExitMomentum[3]
for each subdetector tell the exit momentum
UInt_t NTotalTrueVertices
Float_t Pullk
Kaon pull of the segment: (dEdxMeas-dEdxexpPion)/dEdxSigmaKaon.
std::vector< AnaTrackerTrackB * > TRACKERSegments
The TRACKER segments that contributed to this global track.
Float_t Pullp
Proton pull of the segment: (dEdxMeas-dEdxexpProton)/dEdxSigmaProton.
std::vector< AnaTrueParticleB * > TrueParticles
The true MC particles used in this spill.
Representation of a global vertex.
AnaVertexB * ReconVertex
The pointer to the most primary AnaVertexB (global vertex) associated with this track.
Double_t POTSincePreviousSavedSpill
bool InDetVolume(SubDetId::SubDetEnum det, const Float_t *pos)
Float_t Length
The length of the ECal segment.
Int_t RooVtxEntry
Not in the MiniTree for the Moment since it produces a seg fault.
Float_t Length
The length of this global track.
Float_t MomentumError
The error on the reconstructed momentum.
Float_t DirectionStart[3]
The reconstructed start direction of the particle.
void ConvertTrueParticleDetEnumToBitField(unsigned long &det, int DetUsed)
Convert the detector used array to the bit field used by psyche for truth trueParts.
Int_t Bunch
The index of this bunch (0-7).
std::vector< AnaVertexB * > ReconVertices
Vector of pointers to AnaVertexB (global vertices) associated with this track.
void ConvertTrackerDetFieldToBitField(unsigned long &det, int Detectors)
Convert tracker detector field to bit field.
This Ana* object is used to flatten TECALUnmatchedObjects from ReconDir/TrackerECal.
Int_t PrimaryIndex
Index of the global vertex.
Int_t GoodSpill
Good spill flag, as defined in Beam Summary Data. 0 is bad.
Int_t Event
The ND280 event number.
Float_t Pullele
Electron pull of the segment: (dEdxMeas-dEdxexpEle)/dEdxSigmaEle.
int nFGDSegments
How many FGD tracks are associated with this track.
Float_t PionDir[3]
The direction of the primary outgoing pions listed first (likely the interacted one).
Float_t Q2
The Q2 of the true interaction.
Definition: DataClasses.hxx:97
AnaTrigger Trigger
Not in the MiniTree for the Moment since it produces a seg fault.
Float_t dEdxSigmaMuon
Expected error on the dE/dx measurement, for the muon hypothesis.
Int_t RooVtxEntry
Entry in the RooTrackerVtx tree (not set directly)
Definition: DataClasses.hxx:72
Int_t ParentID
The ID of this particle&#39;s immediate parent, or 0 if there is no parent.
Float_t PositionEnd[4]
The end position of the true particle.
Float_t Purity
The purity with which this particle was matched to a reconstructed object.
Float_t Position[4]
The initial position of the true particle.
Int_t Containment
Containment flag required for proper PID analysis.
std::vector< AnaParticleB * > Particles
Int_t MostUpStreamLayerHit
Innermost layer hit of the ecal object (used in ecal pi0 veto)
Representation of a TPC segment of a global track.
Float_t TimeStart
Start time.
Definition: DataClasses.hxx:43
void ConvertTrackDetEnumToBitField(unsigned long &det, int DetUsed[])
Convert the detector used array to the bit field used by psyche for ana tracks.
Header & header()
Returns the Header manager.
TChain * fChain
The main TChain used to read events from the input file.
Float_t NuDir[3]
The true (unit) direction of the incoming neutrino.
Definition: DataClasses.hxx:82
Float_t dEdxSigmaPion
Expected error on the dE/dx measurement, for the pion hypothesis.
AnaTrueParticleB * GetTrueParticle() const
Return a casted version of the AnaTrueObject associated.
Float_t Charge
The true charge of the particle.
bool InFiducialVolume(SubDetId::SubDetEnum det, const Float_t *pos, const Float_t *FVdefmin, const Float_t *FVdefmax)
Representation of a reconstructed particle (track or shower).
AnaDataQualityB * DataQuality
The ND280 data quality flags for this spill.
Int_t ReconPDG
PDG of the most probable particle hypothesis used at reconstruction level.
bool IsMC
Says if the event is MC or data.
Float_t Direction[3]
The initial direction of the true particle.
static bool ComparePrimaryIndex(const AnaVertexB *t1, const AnaVertexB *t2)
Function used to sort PrimaryIndex in increasing order.
UInt_t NTotalTrueParticles
Representation of a true Monte Carlo trajectory/particle.
Float_t MomentumMuon
Momentum from refitting the track assuming the muon hypothesis.
bool TrackUsesOnlyDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
Representation of the beam information, including POT and quality.
AnaFGDParticleB * FGDSegments[NMAXFGDS]
The FGD segments that contributed to this global track.
Float_t POT
The POT for this spill. For data, this comes from the Beam Summary Data.
Float_t dEdxexpKaon
Expected dE/dx for a proton, based on the reconstructed momentum.
Float_t EntranceMomentum[3]
for each subdetector tell the entrance momentum
Float_t TargetMom
The momentum of the target nucleus.
Float_t PionMom
The momentum of the primary outgoing pions listed first (likely the interacted one).
Int_t NPrimaryParticles[Int_t(ParticleId::kLast)+1]
Array to count the outgoing primary particles of each type (.
std::vector< AnaParticleB * > ReconParticles
Float_t PositionEnd[4]
The reconstructed end position of the particle.
Float_t RefitMomentum
Reconstructed momentum with the empirical distortion corrections.
Float_t MomentumProton
Momentum from refitting the track assuming the proton hypothesis.
bool LoadGeometry(const std::string &file="", Int_t geomID=-1, const std::string &geomDir="")
Load the TGeoManager from the input root file. Returns true when the new geometry was loaded...
Int_t Run
The ND280 run number.