AnalysisTree_module.cc
Go to the documentation of this file.
1 // For information about how to use the module see the txt file in this directory.
2 //
3 // This code was imported by Karl Warburton, with help from Tingjun Yang - April 2016
4 // k.warburton@sheffield.ac.uk, tjyang@fnal.gov
5 // This code was imported from the uboone analysis tree re-written by Gianluca Petrillo
6 //
7 // To add a new structure of things eg OpHits follow the example of recob::OpFlash
8 // * Define max size of array around line 90
9 // * Define the bit set around line 440
10 // * Define your variable in tree around line 560
11 // * Define a bool function around line 910
12 // * Make your fcl pset bools around line 1160 and 1190
13 // * Add your structure to the tree around line 1230
14 // * Fill the tree with you struct around line 2130
15 // * Create branch in the tree around line 2730
16 // * Access your fcl pset bools around line 3070
17 // * Make your art handles around line 3270
18 // * Figure out how big they are around line 3390
19 // * Actually get your variables around line 3770
20 //
21 // To just add a new varible to an exisiting tree just adapt the relevant steps.
22 
23 // Framework includes
33 #include "art_root_io/TFileService.h"
34 #include "art_root_io/TFileDirectory.h"
35 #include "canvas/Persistency/Common/FindMany.h"
37 #include "fhiclcpp/ParameterSet.h"
39 
52 #include "lardataobj/RawData/raw.h"
79 
82 
84 
85 #include <cstddef> // std::ptrdiff_t
86 #include <cstring> // std::memcpy()
87 #include <vector>
88 #include <map>
89 #include <iterator> // std::begin(), std::end()
90 #include <string>
91 #include <sstream>
92 #include <fstream>
93 #include <algorithm>
94 #include <functional> // std::mem_fun_ref
95 #include <typeinfo>
96 #include <memory> // std::unique_ptr<>
97 
98 #include "TTree.h"
99 #include "TTimeStamp.h"
100 
101 #define MVA_LENGTH 4
102 
103 constexpr int kNplanes = 3; //number of wire planes
104 constexpr int kMaxHits = 100000; //maximum number of hits;
105 constexpr int kMaxTrackHits = 2000; //maximum number of hits on a track
106 constexpr int kMaxTrackers = 15; //number of trackers passed into fTrackModuleLabel
107 constexpr int kMaxVertices = 500; //max number of 3D vertices
108 constexpr int kMaxVertexAlgos = 10; //max number of vertex algorithms
109 constexpr unsigned short kMaxAuxDets = 4; ///< max number of auxiliary detector cells per MC particle
110 constexpr int kMaxFlashes = 1000; //maximum number of flashes
111 constexpr int kMaxExternCounts = 1000; //maximum number of External Counters
112 constexpr int kMaxShowerHits = 10000; //maximum number of hits on a shower
113 constexpr int kMaxTruth = 10; //maximum number of neutrino truth interactions
114 constexpr int kMaxClusters = 2000; //maximum number of clusters;
115 
116 constexpr int kMaxNDaughtersPerPFP = 10; //maximum number of daughters per PFParticle
117 constexpr int kMaxNClustersPerPFP = 10; //maximum number of clusters per PFParticle
118 constexpr int kMaxNPFPNeutrinos = 5; //maximum number of reconstructed neutrino PFParticles
119 
120 /// total_extent<T>::value has the total number of elements of an array
121 template <typename T>
122 struct total_extent {
123  using value_type = size_t;
124  static constexpr value_type value
125  = sizeof(T) / sizeof(typename std::remove_all_extents<T>::type);
126 }; // total_extent<>
127 
128 
129 namespace dune {
130 
131  /// Data structure with all the tree information.
132  ///
133  /// Can connect to a tree, clear its fields and resize its data.
135  public:
136 
137  /// A wrapper to a C array (needed to embed an array into a vector)
138  template <typename Array_t>
139  class BoxedArray {
140  protected:
141  Array_t array; // actual data
142 
143  public:
146 
147  BoxedArray() {} // no initialization
148  BoxedArray(const This_t& from)
149  { std::memcpy((char*) &(data()), (char*) &(from.data()), sizeof(Array_t)); }
150 
151  Array_t& data() { return array; }
152  const Array_t& data() const { return array; }
153 
154  //@{
155  /// begin/end interface
156  static constexpr size_t size() { return total_extent<Array_t>::value; }
157  Data_t* begin() { return reinterpret_cast<Data_t*>(&array); }
158  const Data_t* begin() const { return reinterpret_cast<const Data_t*>(&array); }
159  Data_t* end() { return begin() + size(); }
160  const Data_t* end() const { return begin() + size(); }
161  //@}
162 
163  //@{
164  /// Array interface
165  auto operator[] (size_t index) -> decltype(*array) { return array[index]; }
166  auto operator[] (size_t index) const -> decltype(*array) { return array[index]; }
167  auto operator+ (ptrdiff_t index) -> decltype(&*array) { return array + index; }
168  auto operator+ (ptrdiff_t index) const -> decltype(&*array) { return array + index; }
169  auto operator- (ptrdiff_t index) -> decltype(&*array) { return array - index; }
170  auto operator- (ptrdiff_t index) const -> decltype(&*array) { return array - index; }
171  auto operator* () -> decltype(*array) { return *array; }
172  auto operator* () const -> decltype(*array) { return *array; }
173 
174  operator decltype(&array[0]) () { return &array[0]; }
175  operator decltype(&array[0]) () const { return &array[0]; }
176  //@}
177 
178  }; // BoxedArray
179 
180  /// Tracker algorithm result
181  ///
182  /// Can connect to a tree, clear its fields and resize its data.
184  public:
185  /* Data structure size:
186  *
187  * TrackData_t<Short_t> : 2 bytes/track
188  * TrackData_t<Float_t> : 4 bytes/track
189  * PlaneData_t<Float_t>, PlaneData_t<Int_t>: 12 bytes/track
190  * HitData_t<Float_t> : 24k bytes/track
191  * HitCoordData_t<Float_t> : 72k bytes/track
192  */
193  template <typename T>
194  using TrackData_t = std::vector<T>;
195  template <typename T>
196  using PlaneData_t = std::vector<BoxedArray<T[kNplanes]>>;
197  template <typename T>
198  using HitData_t = std::vector<BoxedArray<T[kNplanes][kMaxTrackHits]>>;
199  template <typename T>
200  using HitCoordData_t = std::vector<BoxedArray<T[kNplanes][kMaxTrackHits][3]>>;
201 
202  size_t MaxTracks; ///< maximum number of storable tracks
203 
204  Short_t ntracks; //number of reconstructed tracks
207  PlaneData_t<Int_t> trkidtruth; //true geant trackid
208  PlaneData_t<Short_t> trkorigin; //_ev_origin 0: unknown, 1: neutrino, 2: cosmic, 3: supernova, 4: singles
219 
220  // more track info
231  TrackData_t<Float_t> trkstartx; // starting x position.
232  TrackData_t<Float_t> trkstarty; // starting y position.
233  TrackData_t<Float_t> trkstartz; // starting z position.
234  TrackData_t<Float_t> trkstartd; // starting distance to boundary.
235  TrackData_t<Float_t> trkendx; // ending x position.
236  TrackData_t<Float_t> trkendy; // ending y position.
237  TrackData_t<Float_t> trkendz; // ending z position.
238  TrackData_t<Float_t> trkendd; // ending distance to boundary.
239  TrackData_t<Float_t> trkflashT0; // t0 per track from matching tracks to flashes (in ns)
240  TrackData_t<Float_t> trktrueT0; // t0 per track from truth information (in ns)
241  TrackData_t<Float_t> trkpurity; // track purity based on hit information
242  TrackData_t<Float_t> trkcompleteness; //track completeness based on hit information
243  TrackData_t<int> trkg4id; //true g4 track id for the reconstructed track
244  TrackData_t<int> trkorig; //origin of the track
257  TrackData_t<Float_t> trkmomrange; // track momentum from range using CSDA tables
258  TrackData_t<Float_t> trkmommschi2; // track momentum from multiple scattering Chi2 method
259  TrackData_t<Float_t> trkmommsllhd; // track momentum from multiple scattering LLHD method
260  TrackData_t<Short_t> trksvtxid; // Vertex ID associated with the track start
261  TrackData_t<Short_t> trkevtxid; // Vertex ID associated with the track end
262  PlaneData_t<Int_t> trkpidpdg; // particle PID pdg code
264  PlaneData_t<Float_t> trkpidchipr; // particle PID chisq for proton
265  PlaneData_t<Float_t> trkpidchika; // particle PID chisq for kaon
266  PlaneData_t<Float_t> trkpidchipi; // particle PID chisq for pion
267  PlaneData_t<Float_t> trkpidchimu; // particle PID chisq for muon
269  TrackData_t<Float_t> trkpidmvamu; // particle MVA value for muon PID
270  TrackData_t<Float_t> trkpidmvae; // particle MVA value for electron PID
271  TrackData_t<Float_t> trkpidmvapich; // particle MVA value for charged pion PID
272  TrackData_t<Float_t> trkpidmvaphoton; // particle MVA value for photon PID
273  TrackData_t<Float_t> trkpidmvapr; // particle MVA value for proton PID
274  TrackData_t<Short_t> trkpidbestplane; // this is defined as the plane with most hits
275 
276  TrackData_t<Short_t> trkhasPFParticle; // whether this belongs to a PFParticle
277  TrackData_t<Short_t> trkPFParticleID; // if hasPFParticle, its ID
278 
279  /// Creates an empty tracker data structure
280  TrackDataStruct(): MaxTracks(0) { Clear(); }
281  /// Creates a tracker data structure allowing up to maxTracks tracks
282  TrackDataStruct(size_t maxTracks): MaxTracks(maxTracks) { Clear(); }
283  void Clear();
284  void SetMaxTracks(size_t maxTracks)
285  { MaxTracks = maxTracks; Resize(MaxTracks); }
286  void Resize(size_t nTracks);
287  void SetAddresses(TTree* pTree, std::string tracker, bool isCosmics);
288 
289  size_t GetMaxTracks() const { return MaxTracks; }
290  size_t GetMaxPlanesPerTrack(int /* iTrack */ = 0) const
291  { return (size_t) kNplanes; }
292  size_t GetMaxHitsPerTrack(int /* iTrack */ = 0, int /* ipl */ = 0) const
293  { return (size_t) kMaxTrackHits; }
294 
295  }; // class TrackDataStruct
296 
297  //Vertex data struct
299  public:
300  template <typename T>
301  using VertexData_t = std::vector<T>;
302 
303  size_t MaxVertices; ///< maximum number of storable vertices
304 
305  Short_t nvtx; //number of reconstructed tracks
306  VertexData_t<Short_t> vtxId; // the vertex ID.
307  VertexData_t<Float_t> vtxx; // x position.
308  VertexData_t<Float_t> vtxy; // y position.
309  VertexData_t<Float_t> vtxz; // z position.
310 
311  VertexData_t<Short_t> vtxhasPFParticle; // whether this belongs to a PFParticle
312  VertexData_t<Short_t> vtxPFParticleID; // if hasPFParticle, its ID
313 
314  VertexDataStruct(): MaxVertices(0) { Clear(); }
315  VertexDataStruct(size_t maxVertices): MaxVertices(maxVertices) { Clear(); }
316  void Clear();
317  void SetMaxVertices(size_t maxVertices)
318  { MaxVertices = maxVertices; Resize(MaxVertices); }
319  void Resize(size_t nVertices);
320  void SetAddresses(TTree* pTree, std::string tracker, bool isCosmics);
321 
322  size_t GetMaxVertices() const { return MaxVertices; }
323  }; // class VertexDataStruct
324 
325 
326  /// Shower algorithm result
327  ///
328  /// Can connect to a tree, clear its fields and resize its data.
330  public:
331  /* Data structure size:
332  *
333  * ShowerData_t<Short_t> : 2 bytes/shower
334  * ShowerData_t<Float_t> : 4 bytes/shower
335  * PlaneData_t<Float_t>, PlaneData_t<Int_t>: 12 bytes/shower
336  * HitData_t<Float_t> : 24k bytes/shower
337  * HitCoordData_t<Float_t> : 72k bytes/shower
338  */
339  template <typename T>
340  using ShowerData_t = std::vector<T>;
341  template <typename T>
342  using PlaneData_t = std::vector<BoxedArray<T[kNplanes]>>;
343  template <typename T>
344  using HitData_t = std::vector<BoxedArray<T[kNplanes][kMaxShowerHits]>>;
345  template <typename T>
346  using HitCoordData_t = std::vector<BoxedArray<T[kNplanes][kMaxShowerHits][3]>>;
347 
348  std::string name; ///< name of the shower algorithm (for branch names)
349 
350  size_t MaxShowers; ///< maximum number of storable showers
351 
352  /// @{
353  /// @name Branch data structures
354  Short_t nshowers; ///< number of showers
356  ShowerData_t<Short_t> shwr_bestplane; ///< Shower best plane
357  ShowerData_t<Float_t> shwr_length; ///< Shower length
358  ShowerData_t<Float_t> shwr_startdcosx; ///< X directional cosine at start of shower
359  ShowerData_t<Float_t> shwr_startdcosy; ///< Y directional cosine at start of shower
360  ShowerData_t<Float_t> shwr_startdcosz; ///< Z directional cosine at start of shower
361  ShowerData_t<Float_t> shwr_startx; ///< startx of shower
362  ShowerData_t<Float_t> shwr_starty; ///< starty of shower
363  ShowerData_t<Float_t> shwr_startz; ///< startz of shower
364  PlaneData_t<Float_t> shwr_totEng; ///< Total energy of the shower per plane
365  PlaneData_t<Float_t> shwr_dedx; ///< dE/dx of the shower per plane
366  PlaneData_t<Float_t> shwr_mipEng; ///< Total MIP energy of the shower per plane
367 
368  ShowerData_t<Float_t> shwr_pidmvamu; // particle MVA value for muon PID
369  ShowerData_t<Float_t> shwr_pidmvae; // particle MVA value for electron PID
370  ShowerData_t<Float_t> shwr_pidmvapich; // particle MVA value for charged pion PID
371  ShowerData_t<Float_t> shwr_pidmvaphoton; // particle MVA value for photon PID
372  ShowerData_t<Float_t> shwr_pidmvapr; // particle MVA value for proton PID
373 
374 
375  ShowerData_t<Short_t> shwr_hasPFParticle; // whether this belongs to a PFParticle
376  ShowerData_t<Short_t> shwr_PFParticleID; // if hasPFParticle, its ID
377  /// @}
378 
379  /// Creates a shower data structure allowing up to maxShowers showers
380  ShowerDataStruct(std::string new_name = "", size_t maxShowers = 0):
381  name(new_name), MaxShowers(maxShowers) { Clear(); }
382 
383  std::string Name() const { return name; }
384 
385  void Clear();
386 
387  /// Applies a special prescription to mark shower information as missing
388  void MarkMissing(TTree* pTree);
389  void SetName(std::string new_name) { name = new_name; }
390  void SetMaxShowers(size_t maxShowers)
391  { MaxShowers = maxShowers; Resize(MaxShowers); }
392  void Resize(size_t nShowers);
393  void SetAddresses(TTree* pTree);
394 
395  size_t GetMaxShowers() const { return MaxShowers; }
396  size_t GetMaxPlanesPerShower(int /* iShower */ = 0) const
397  { return (size_t) kNplanes; }
398  size_t GetMaxHitsPerShower(int /* iShower */ = 0, int /* ipl */ = 0) const
399  { return (size_t) kMaxShowerHits; }
400 
401  }; // class ShowerDataStruct
402 
404  public:
405  /* Data structure size:
406  *
407  * PFParticleData_t<Short_t> : 2 bytes/PFParticle
408  * PFParticleData_t<Int_t> : 4 bytes/PFParticle
409  * DaughterData_t<Short_t> : 20 bytes/PFParticle
410  * ClusterData_t<Short_t> : 20 bytes/PFParticle
411  * Short_t [kMaxNPFPNeutrinos] : 10 bytes in total
412  */
413  template <typename T>
414  using PFParticleData_t = std::vector<T>;
415  template <typename T>
416  using DaughterData_t = std::vector<BoxedArray<T[kMaxNDaughtersPerPFP]>>;
417  template <typename T>
418  using ClusterData_t = std::vector<BoxedArray<T[kMaxNClustersPerPFP]>>;
419 
420  size_t MaxPFParticles; ///< maximum number of storable PFParticles
421 
422  /// @{
423  /// @name Branch data structures
424  Short_t nPFParticles; ///< the total number of PFParticles
425  PFParticleData_t<Short_t> pfp_selfID; ///< the PFParticles' own IDs
426  PFParticleData_t<Short_t> pfp_isPrimary; ///< whether the PFParticle is a primary particle
427 
428  PFParticleData_t<Short_t> pfp_numDaughters; ///< the number of daughters belonging to this PFParticle
429  DaughterData_t<Short_t> pfp_daughterIDs; ///< the IDs of the daughter PFParticles
430  PFParticleData_t<Short_t> pfp_parentID; ///< the ID of this PFParticle's immediate parent
431 
432  PFParticleData_t<Short_t> pfp_vertexID; ///< the ID of the vertex belonging to this PFParticle
433  PFParticleData_t<Short_t> pfp_isShower; ///< whether this PFParticle corresponds to a shower
434  PFParticleData_t<Short_t> pfp_isTrack; ///< whether this PFParticle corresponds to a track
435  PFParticleData_t<Short_t> pfp_trackID; ///< the ID of the track object corresponding to this PFParticle, if !isShower
436  PFParticleData_t<Short_t> pfp_showerID; ///< the ID of the shower object corresponding to this PFParticle, if isShower
437 
438  PFParticleData_t<Short_t> pfp_isNeutrino; ///< whether this PFParticle is a neutrino
439  PFParticleData_t<Int_t> pfp_pdgCode; ///< the preliminary estimate of the PFParticle type using the PDG code
440 
441  PFParticleData_t<Short_t> pfp_numClusters; ///< the number of associated clusters
442  ClusterData_t<Short_t> pfp_clusterIDs; ///< the IDs of any associated clusters
443 
444  Short_t pfp_numNeutrinos; ///< the number of reconstructed neutrinos
445  Short_t pfp_neutrinoIDs[kMaxNPFPNeutrinos]; ///< the PFParticle IDs of the neutrinos
446  /// @}
447 
448  /// Creates a PFParticle data structure allowing up to maxPFParticles PFParticles
449  PFParticleDataStruct(size_t maxPFParticles = 0):
450  MaxPFParticles(maxPFParticles) { Clear(); }
451 
452  void Clear();
453  void SetMaxPFParticles(size_t maxPFParticles)
454  { MaxPFParticles = maxPFParticles; Resize(MaxPFParticles); }
455  void Resize(size_t numPFParticles);
456  void SetAddresses(TTree* pTree);
457 
458  size_t GetMaxPFParticles() const { return MaxPFParticles; }
459  size_t GetMaxDaughtersPerPFParticle(int /* iPFParticle */ = 0) const
460  { return (size_t) kMaxNDaughtersPerPFP; }
461  size_t GetMaxClustersPerPFParticle(int /* iPFParticle */ = 0) const
462  { return (size_t) kMaxNClustersPerPFP; }
463 
464  }; // class PFParticleDataStruct
465 
466  enum DataBits_t: unsigned int {
467  tdAuxDet = 0x01,
468  tdCry = 0x02,
469  tdGenie = 0x04,
470  tdGeant = 0x08,
471  tdHit = 0x10,
472  tdTrack = 0x20,
473  tdVertex = 0x40,
474  tdFlash = 0x80,
475  tdShower = 0x100,
476  tdMCshwr = 0x200,
477  tdMCtrk = 0x400,
478  tdCluster = 0x800,
479  tdRawDigit = 0x1000,
480  tdPandoraNuVertex = 0x2000,
481  tdPFParticle = 0x4000,
482  tdCount = 0x8000,
483  tdProto = 0x10000,
484  tdSpacePoint = 0x20000,
485  tdCnn = 0x40000,
486  tdDefault = 0
487  }; // DataBits_t
488 
489  /* /// information from the run
490  struct RunData_t {
491  public:
492  RunData_t() { Clear(); }
493  void Clear() {}
494  }; // struct RunData_t
495  */
496  /// information from the subrun
497  struct SubRunData_t {
498  SubRunData_t() { Clear(); }
499  void Clear() {
500  pot = -99999.;
501  potbnbETOR860 = -99999.;
502  potbnbETOR875 = -99999.;
503  potnumiETORTGT = -99999.;
504  }
505  Double_t pot; //protons on target
506  Double_t potbnbETOR860;
507  Double_t potbnbETOR875;
508  Double_t potnumiETORTGT;
509  }; // struct SubRunData_t
510 
511  // RunData_t RunData; ///< run data collected at begin of run
512  SubRunData_t SubRunData; ///< subrun data collected at begin of subrun
513 
514  //run information
515  Int_t run; //run number
516  Int_t subrun; //subrun number
517  Int_t event; //event number
518  Double_t evttime; //event time in sec
519  Double_t beamtime; //beam time
520  // Double_t pot; //protons on target moved in subrun data
521  Double_t taulife; //electron lifetime
522  Char_t isdata; //flag, 0=MC 1=data
523  unsigned int triggernumber; //trigger counter
524  Double_t triggertime; //trigger time w.r.t. electronics clock T0
525  Double_t beamgatetime; //beamgate time w.r.t. electronics clock T0
526  unsigned int triggerbits; //trigger bits
527  Double_t potbnb; //pot per event (BNB E:TOR860)
528  Double_t potnumitgt; //pot per event (NuMI E:TORTGT)
529  Double_t potnumi101; //pot per event (NuMI E:TOR101)
530 
531  // hit information (non-resizeable, 45x kMaxHits = 900k bytes worth)
532  Int_t no_hits; //number of hits
533  Int_t no_hits_stored; //number of hits actually stored in the tree
534  Short_t hit_tpc[kMaxHits]; //tpc number
535  Short_t hit_plane[kMaxHits]; //plane number
536  Short_t hit_wire[kMaxHits]; //wire number
537  Short_t hit_channel[kMaxHits]; //channel ID
538  Float_t hit_peakT[kMaxHits]; //peak time
539  Float_t hit_charge[kMaxHits]; //charge (area)
540  Float_t hit_ph[kMaxHits]; //amplitude
541  Float_t hit_startT[kMaxHits]; //hit start time
542  Float_t hit_endT[kMaxHits]; //hit end time
543  Float_t hit_rms[kMaxHits]; //hit rms from the hit object
544  Float_t hit_goodnessOfFit[kMaxHits]; //chi2/dof goodness of fit
545  Short_t hit_multiplicity[kMaxHits]; //multiplicity of the given hit
546  Float_t hit_trueX[kMaxHits]; // hit true X (cm)
547  Float_t hit_nelec[kMaxHits]; //hit number of electrons
548  Float_t hit_energy[kMaxHits]; //hit energy
549  Short_t hit_trkid[kMaxHits]; //is this hit associated with a reco track?
550  Short_t hit_trkKey[kMaxHits]; //is this hit associated with a reco track, if so associate a unique track key ID?
551  Short_t hit_clusterid[kMaxHits]; //is this hit associated with a reco cluster?
552  Short_t hit_clusterKey[kMaxHits]; //is this hit associated with a reco cluster, if so associate a unique cluster key ID?
553  Short_t hit_spacepointid[kMaxHits];
554  Short_t hit_spacepointKey[kMaxHits];
555 
556  Float_t rawD_ph[kMaxHits];
557  Float_t rawD_peakT[kMaxHits];
558  Float_t rawD_charge[kMaxHits];
559  Float_t rawD_fwhh[kMaxHits];
560  Double_t rawD_rms[kMaxHits];
561 
562  //Pandora Nu Vertex information
563  Short_t nnuvtx;
564  Float_t nuvtxx[kMaxVertices];
565  Float_t nuvtxy[kMaxVertices];
566  Float_t nuvtxz[kMaxVertices];
567  Short_t nuvtxpdg[kMaxVertices];
568 
569  //Cluster Information
570  Short_t nclusters; //number of clusters in a given event
571  Short_t clusterId[kMaxClusters]; //ID of this cluster
572  Short_t clusterView[kMaxClusters]; //which plane this cluster belongs to
573  Int_t cluster_isValid[kMaxClusters]; //is this cluster valid? will have a value of -1 if it is not valid
574  Float_t cluster_StartCharge[kMaxClusters]; //charge on the first wire of the cluster in ADC
575  Float_t cluster_StartAngle[kMaxClusters]; //starting angle of the cluster
576  Float_t cluster_EndCharge[kMaxClusters]; //charge on the last wire of the cluster in ADC
577  Float_t cluster_EndAngle[kMaxClusters]; //ending angle of the cluster
578  Float_t cluster_Integral[kMaxClusters]; //returns the total charge of the cluster from hit shape in ADC
579  Float_t cluster_IntegralAverage[kMaxClusters]; //average charge of the cluster hits in ADC
580  Float_t cluster_SummedADC[kMaxClusters]; //total charge of the cluster from signal ADC counts
581  Float_t cluster_SummedADCaverage[kMaxClusters]; //average signal ADC counts of the cluster hits.
582  Float_t cluster_MultipleHitDensity[kMaxClusters]; //Density of wires in the cluster with more than one hit.
583  Float_t cluster_Width[kMaxClusters]; //cluster width in ? units
584  Short_t cluster_NHits[kMaxClusters]; //Number of hits in the cluster
585  Short_t cluster_StartWire[kMaxClusters]; //wire coordinate of the start of the cluster
586  Short_t cluster_StartTick[kMaxClusters]; //tick coordinate of the start of the cluster in time ticks
587  Short_t cluster_EndWire[kMaxClusters]; //wire coordinate of the end of the cluster
588  Short_t cluster_EndTick[kMaxClusters]; //tick coordinate of the end of the cluster in time ticks
589  //Cluster cosmic tagging information
590  Short_t cluncosmictags_tagger[kMaxClusters]; //No. of cosmic tags associated to this cluster
591  Float_t clucosmicscore_tagger[kMaxClusters]; //Cosmic score associated to this cluster. In the case of more than one tag, the first one is associated.
592  Short_t clucosmictype_tagger[kMaxClusters]; //Cosmic tag type for this cluster.
593 
594  // SpacePointSolver data
595  Short_t nspacepoints;
596  std::vector<Float_t> SpacePointX; // X position of this SpacePoint
597  std::vector<Float_t> SpacePointY; // Y position of this SpacePoint
598  std::vector<Float_t> SpacePointZ; // Z position of this SpacePoint
599  std::vector<Float_t> SpacePointQ; // charge of this SpacePoint
600  std::vector<Float_t> SpacePointErrX; // X error of this SpacePoint
601  std::vector<Float_t> SpacePointErrY; // Y error of this SpacePoint
602  std::vector<Float_t> SpacePointErrZ; // Z error of this SpacePoint
603  std::vector<Int_t> SpacePointID;
604  std::vector<Float_t> SpacePointChisq;
605 
606  // CNN data
607  std::vector<Float_t> SpacePointEmScore;
608 
609  // flash information
610  Int_t no_flashes; //number of flashes
611  Float_t flash_time[kMaxFlashes]; //flash time
612  Float_t flash_pe[kMaxFlashes]; //flash total PE
613  Float_t flash_ycenter[kMaxFlashes];//y center of flash
614  Float_t flash_zcenter[kMaxFlashes];//z center of flash
615  Float_t flash_ywidth[kMaxFlashes]; //y width of flash
616  Float_t flash_zwidth[kMaxFlashes]; //z width of flash
617  Float_t flash_timewidth[kMaxFlashes]; //time of flash
618 
619  // External Counter information
620  Int_t no_ExternCounts; // Number of External Triggers
621  Float_t externcounts_time[kMaxExternCounts]; // Time of External Trigger
622  Float_t externcounts_id[kMaxExternCounts]; // ID of External Trigger
623 
624  //track information
625  Char_t kNTracker;
626  std::vector<TrackDataStruct> TrackData;
627 
628  //vertex information
630  std::vector<VertexDataStruct> VertexData;
631 
632  // shower information
634  std::vector<ShowerDataStruct> ShowerData;
635 
636  // PFParticle information
638 
639  //mctruth information
640  Int_t mcevts_truth; //number of neutrino Int_teractions in the spill
641  Int_t nuPDG_truth[kMaxTruth]; //neutrino PDG code
642  Int_t ccnc_truth[kMaxTruth]; //0=CC 1=NC
643  Int_t mode_truth[kMaxTruth]; //0=QE/El, 1=RES, 2=DIS, 3=Coherent production
644  Float_t enu_truth[kMaxTruth]; //true neutrino energy
645  Float_t Q2_truth[kMaxTruth]; //Momentum transfer squared
646  Float_t W_truth[kMaxTruth]; //hadronic invariant mass
647  Float_t X_truth[kMaxTruth];
648  Float_t Y_truth[kMaxTruth];
649  Int_t hitnuc_truth[kMaxTruth]; //hit nucleon
650  Float_t nuvtxx_truth[kMaxTruth]; //neutrino vertex x
651  Float_t nuvtxy_truth[kMaxTruth]; //neutrino vertex y
652  Float_t nuvtxz_truth[kMaxTruth]; //neutrino vertex z
653  Float_t nu_dcosx_truth[kMaxTruth]; //neutrino dcos x
654  Float_t nu_dcosy_truth[kMaxTruth]; //neutrino dcos y
655  Float_t nu_dcosz_truth[kMaxTruth]; //neutrino dcos z
656  Float_t lep_mom_truth[kMaxTruth]; //lepton momentum
657  Float_t lep_dcosx_truth[kMaxTruth]; //lepton dcos x
658  Float_t lep_dcosy_truth[kMaxTruth]; //lepton dcos y
659  Float_t lep_dcosz_truth[kMaxTruth]; //lepton dcos z
660 
661  //flux information
662  Float_t vx_flux[kMaxTruth]; //X position of hadron/muon decay (cm)
663  Float_t vy_flux[kMaxTruth]; //Y position of hadron/muon decay (cm)
664  Float_t vz_flux[kMaxTruth]; //Z position of hadron/muon decay (cm)
665  Float_t pdpx_flux[kMaxTruth]; //Parent X momentum at decay point (GeV)
666  Float_t pdpy_flux[kMaxTruth]; //Parent Y momentum at decay point (GeV)
667  Float_t pdpz_flux[kMaxTruth]; //Parent Z momentum at decay point (GeV)
668  Float_t ppdxdz_flux[kMaxTruth]; //Parent dxdz direction at production
669  Float_t ppdydz_flux[kMaxTruth]; //Parent dydz direction at production
670  Float_t pppz_flux[kMaxTruth]; //Parent Z momentum at production (GeV)
671 
672  Int_t ptype_flux[kMaxTruth]; //Parent GEANT code particle ID
673  Float_t ppvx_flux[kMaxTruth]; //Parent production vertex X (cm)
674  Float_t ppvy_flux[kMaxTruth]; //Parent production vertex Y (cm)
675  Float_t ppvz_flux[kMaxTruth]; //Parent production vertex Z (cm)
676  Float_t muparpx_flux[kMaxTruth]; //Muon neutrino parent production vertex X (cm)
677  Float_t muparpy_flux[kMaxTruth]; //Muon neutrino parent production vertex Y (cm)
678  Float_t muparpz_flux[kMaxTruth]; //Muon neutrino parent production vertex Z (cm)
679  Float_t mupare_flux[kMaxTruth]; //Muon neutrino parent energy (GeV)
680 
681  Int_t tgen_flux[kMaxTruth]; //Parent generation in cascade. (1 = primary proton,
682  //2=particles produced by proton interaction, 3 = particles
683  //produced by interactions of the 2's, ...
684  Int_t tgptype_flux[kMaxTruth]; //Type of particle that created a particle flying of the target
685  Float_t tgppx_flux[kMaxTruth]; //X Momentum of a particle, that created a particle that flies
686  //off the target, at the interaction point. (GeV)
687  Float_t tgppy_flux[kMaxTruth]; //Y Momentum of a particle, that created a particle that flies
688  //off the target, at the interaction point. (GeV)
689  Float_t tgppz_flux[kMaxTruth]; //Z Momentum of a particle, that created a particle that flies
690  //off the target, at the interaction point. (GeV)
691  Float_t tprivx_flux[kMaxTruth]; //Primary particle interaction vertex X (cm)
692  Float_t tprivy_flux[kMaxTruth]; //Primary particle interaction vertex Y (cm)
693  Float_t tprivz_flux[kMaxTruth]; //Primary particle interaction vertex Z (cm)
694  Float_t dk2gen_flux[kMaxTruth]; //distance from decay to ray origin (cm)
695  Float_t gen2vtx_flux[kMaxTruth]; //distance from ray origin to event vtx (cm)
696 
697  Float_t tpx_flux[kMaxTruth]; //Px of parent particle leaving BNB/NuMI target (GeV)
698  Float_t tpy_flux[kMaxTruth]; //Py of parent particle leaving BNB/NuMI target (GeV)
699  Float_t tpz_flux[kMaxTruth]; //Pz of parent particle leaving BNB/NuMI target (GeV)
700  Int_t tptype_flux[kMaxTruth]; //Type of parent particle leaving BNB target
701 
702  //genie information
703  size_t MaxGeniePrimaries = 0;
705  std::vector<Int_t> genie_primaries_pdg;
706  std::vector<Float_t> genie_Eng;
707  std::vector<Float_t> genie_Px;
708  std::vector<Float_t> genie_Py;
709  std::vector<Float_t> genie_Pz;
710  std::vector<Float_t> genie_P;
711  std::vector<Int_t> genie_status_code;
712  std::vector<Float_t> genie_mass;
713  std::vector<Int_t> genie_trackID;
714  std::vector<Int_t> genie_ND;
715  std::vector<Int_t> genie_mother;
716 
717  //cosmic cry information
718  Int_t mcevts_truthcry; //number of neutrino Int_teractions in the spill
720  std::vector<Int_t> cry_primaries_pdg;
721  std::vector<Float_t> cry_Eng;
722  std::vector<Float_t> cry_Px;
723  std::vector<Float_t> cry_Py;
724  std::vector<Float_t> cry_Pz;
725  std::vector<Float_t> cry_P;
726  std::vector<Float_t> cry_StartPointx;
727  std::vector<Float_t> cry_StartPointy;
728  std::vector<Float_t> cry_StartPointz;
729  std::vector<Float_t> cry_StartPointt;
730  std::vector<Int_t> cry_status_code;
731  std::vector<Float_t> cry_mass;
732  std::vector<Int_t> cry_trackID;
733  std::vector<Int_t> cry_ND;
734  std::vector<Int_t> cry_mother;
735 
736  // ProtoDUNE Beam generator information
738  std::vector<Int_t> proto_isGoodParticle;
739  std::vector<Float_t> proto_vx;
740  std::vector<Float_t> proto_vy;
741  std::vector<Float_t> proto_vz;
742  std::vector<Float_t> proto_t;
743  std::vector<Float_t> proto_px;
744  std::vector<Float_t> proto_py;
745  std::vector<Float_t> proto_pz;
746  std::vector<Float_t> proto_momentum;
747  std::vector<Float_t> proto_energy;
748  std::vector<Int_t> proto_pdg;
749  std::vector<Int_t> proto_geantTrackID; // The TrackID assigned by GEANT
750  std::vector<Int_t> proto_geantIndex; // The index of this particle in the truth array
751 
752  //G4 MC Particle information
753  size_t MaxGEANTparticles = 0; ///! how many particles there is currently room for
754  Int_t no_primaries; //number of primary geant particles
755  Int_t geant_list_size; //number of all geant particles
757  std::vector<Int_t> pdg;
758  std::vector<Int_t> status;
759  std::vector<Float_t> Eng;
760  std::vector<Float_t> EndE;
761  std::vector<Float_t> Mass;
762  std::vector<Float_t> Px;
763  std::vector<Float_t> Py;
764  std::vector<Float_t> Pz;
765  std::vector<Float_t> P;
766  std::vector<Float_t> StartPointx;
767  std::vector<Float_t> StartPointy;
768  std::vector<Float_t> StartPointz;
769  std::vector<Float_t> StartT;
770  std::vector<Float_t> EndT;
771  std::vector<Float_t> EndPointx;
772  std::vector<Float_t> EndPointy;
773  std::vector<Float_t> EndPointz;
774  std::vector<Float_t> theta;
775  std::vector<Float_t> phi;
776  std::vector<Float_t> theta_xz;
777  std::vector<Float_t> theta_yz;
778  std::vector<Float_t> pathlen;
779  std::vector<Int_t> inTPCActive;
780  std::vector<Float_t> StartPointx_tpcAV;
781  std::vector<Float_t> StartPointy_tpcAV;
782  std::vector<Float_t> StartPointz_tpcAV;
783  std::vector<Float_t> StartT_tpcAV;
784  std::vector<Float_t> StartE_tpcAV;
785  std::vector<Float_t> StartP_tpcAV;
786  std::vector<Float_t> StartPx_tpcAV;
787  std::vector<Float_t> StartPy_tpcAV;
788  std::vector<Float_t> StartPz_tpcAV;
789  std::vector<Float_t> EndPointx_tpcAV;
790  std::vector<Float_t> EndPointy_tpcAV;
791  std::vector<Float_t> EndPointz_tpcAV;
792  std::vector<Float_t> EndT_tpcAV;
793  std::vector<Float_t> EndE_tpcAV;
794  std::vector<Float_t> EndP_tpcAV;
795  std::vector<Float_t> EndPx_tpcAV;
796  std::vector<Float_t> EndPy_tpcAV;
797  std::vector<Float_t> EndPz_tpcAV;
798  std::vector<Float_t> pathlen_drifted;
799  std::vector<Int_t> inTPCDrifted;
800  std::vector<Float_t> StartPointx_drifted;
801  std::vector<Float_t> StartPointy_drifted;
802  std::vector<Float_t> StartPointz_drifted;
803  std::vector<Float_t> StartT_drifted;
804  std::vector<Float_t> StartE_drifted;
805  std::vector<Float_t> StartP_drifted;
806  std::vector<Float_t> StartPx_drifted;
807  std::vector<Float_t> StartPy_drifted;
808  std::vector<Float_t> StartPz_drifted;
809  std::vector<Float_t> EndPointx_drifted;
810  std::vector<Float_t> EndPointy_drifted;
811  std::vector<Float_t> EndPointz_drifted;
812  std::vector<Float_t> EndT_drifted;
813  std::vector<Float_t> EndE_drifted;
814  std::vector<Float_t> EndP_drifted;
815  std::vector<Float_t> EndPx_drifted;
816  std::vector<Float_t> EndPy_drifted;
817  std::vector<Float_t> EndPz_drifted;
818  std::vector<Int_t> NumberDaughters;
819  std::vector<Int_t> TrackId;
820  std::vector<Int_t> Mother;
821  std::vector<Int_t> process_primary;
822  std::vector<std::string> processname;
823  std::vector<Int_t> MergedId; //geant track segments, which belong to the same particle, get the same
824  std::vector<Int_t> origin; ////0: unknown, 1: cosmic, 2: neutrino, 3: supernova, 4: singles
825  std::vector<Int_t> MCTruthIndex; //this geant particle comes from the neutrino interaction of the _truth variables with this index
826 
827  //MC Shower information
828  Int_t no_mcshowers; //number of MC Showers in this event.
829  //MC Shower particle information
830  std::vector<Int_t> mcshwr_origin; //MC Shower origin information.
831  std::vector<Int_t> mcshwr_pdg; //MC Shower particle PDG code.
832  std::vector<Int_t> mcshwr_TrackId; //MC Shower particle G4 track ID.
833  std::vector<std::string> mcshwr_Process; //MC Shower particle's creation process.
834  std::vector<Float_t> mcshwr_startX; //MC Shower particle G4 startX
835  std::vector<Float_t> mcshwr_startY; //MC Shower particle G4 startY
836  std::vector<Float_t> mcshwr_startZ; //MC Shower particle G4 startZ
837  std::vector<Float_t> mcshwr_endX; //MC Shower particle G4 endX
838  std::vector<Float_t> mcshwr_endY; //MC Shower particle G4 endY
839  std::vector<Float_t> mcshwr_endZ; //MC Shower particle G4 endZ
840  std::vector<Float_t> mcshwr_CombEngX; //MC Shower Combined energy deposition information, Start Point X Position.
841  std::vector<Float_t> mcshwr_CombEngY; //MC Shower Combined energy deposition information, Start Point Y Position.
842  std::vector<Float_t> mcshwr_CombEngZ; //MC Shower Combined energy deposition information, Start Point Z Position.
843  std::vector<Float_t> mcshwr_CombEngPx; //MC Shower Combined energy deposition information, Momentum X direction.
844  std::vector<Float_t> mcshwr_CombEngPy; //MC Shower Combined energy deposition information, Momentum X direction.
845  std::vector<Float_t> mcshwr_CombEngPz; //MC Shower Combined energy deposition information, Momentum X direction.
846  std::vector<Float_t> mcshwr_CombEngE; //MC Shower Combined energy deposition information, Energy
847  std::vector<Float_t> mcshwr_dEdx; //MC Shower dEdx, MeV/cm
848  std::vector<Float_t> mcshwr_StartDirX; //MC Shower Direction of begining of shower, X direction
849  std::vector<Float_t> mcshwr_StartDirY; //MC Shower Direction of begining of shower, Y direction
850  std::vector<Float_t> mcshwr_StartDirZ; //MC Shower Direction of begining of shower, Z direction
851  std::vector<Int_t> mcshwr_isEngDeposited; //tells whether if this shower deposited energy in the detector or not.
852  //yes = 1; no =0;
853  //MC Shower mother information
854  std::vector<Int_t> mcshwr_Motherpdg; //MC Shower's mother PDG code.
855  std::vector<Int_t> mcshwr_MotherTrkId; //MC Shower's mother G4 track ID.
856  std::vector<std::string> mcshwr_MotherProcess; //MC Shower's mother creation process.
857  std::vector<Float_t> mcshwr_MotherstartX; //MC Shower's mother G4 startX .
858  std::vector<Float_t> mcshwr_MotherstartY; //MC Shower's mother G4 startY .
859  std::vector<Float_t> mcshwr_MotherstartZ; //MC Shower's mother G4 startZ .
860  std::vector<Float_t> mcshwr_MotherendX; //MC Shower's mother G4 endX .
861  std::vector<Float_t> mcshwr_MotherendY; //MC Shower's mother G4 endY .
862  std::vector<Float_t> mcshwr_MotherendZ; //MC Shower's mother G4 endZ .
863  //MC Shower ancestor information
864  std::vector<Int_t> mcshwr_Ancestorpdg; //MC Shower's ancestor PDG code.
865  std::vector<Int_t> mcshwr_AncestorTrkId; //MC Shower's ancestor G4 track ID.
866  std::vector<std::string> mcshwr_AncestorProcess; //MC Shower's ancestor creation process.
867  std::vector<Float_t> mcshwr_AncestorstartX; //MC Shower's ancestor G4 startX
868  std::vector<Float_t> mcshwr_AncestorstartY; //MC Shower's ancestor G4 startY
869  std::vector<Float_t> mcshwr_AncestorstartZ; //MC Shower's ancestor G4 startZ
870  std::vector<Float_t> mcshwr_AncestorendX; //MC Shower's ancestor G4 endX
871  std::vector<Float_t> mcshwr_AncestorendY; //MC Shower's ancestor G4 endY
872  std::vector<Float_t> mcshwr_AncestorendZ; //MC Shower's ancestor G4 endZ
873 
874  //MC track information
875  Int_t no_mctracks; //number of MC tracks in this event.
876  //MC track particle information
877  std::vector<Int_t> mctrk_origin; //MC track origin information.
878  std::vector<Int_t> mctrk_pdg; //MC track particle PDG code.
879  std::vector<Int_t> mctrk_TrackId; //MC track particle G4 track ID.
880  std::vector<std::string> mctrk_Process; //MC track particle's creation process.
881  std::vector<Float_t> mctrk_startX; //MC track particle G4 startX
882  std::vector<Float_t> mctrk_startY; //MC track particle G4 startY
883  std::vector<Float_t> mctrk_startZ; //MC track particle G4 startZ
884  std::vector<Float_t> mctrk_endX; //MC track particle G4 endX
885  std::vector<Float_t> mctrk_endY; //MC track particle G4 endY
886  std::vector<Float_t> mctrk_endZ; //MC track particle G4 endZ
887  std::vector<Float_t> mctrk_startX_drifted; //MC track particle first step in TPC x
888  std::vector<Float_t> mctrk_startY_drifted; //MC track particle first step in TPC y
889  std::vector<Float_t> mctrk_startZ_drifted; //MC track particle first step in TPC z
890  std::vector<Float_t> mctrk_endX_drifted; //MC track particle last step in TPC x
891  std::vector<Float_t> mctrk_endY_drifted; //MC track particle last step in TPC y
892  std::vector<Float_t> mctrk_endZ_drifted; //MC track particle last step in TPC z
893  std::vector<Float_t> mctrk_len_drifted; //MC track length within TPC
894  std::vector<Float_t> mctrk_p_drifted; //MC track momentum at start point in TPC
895  std::vector<Float_t> mctrk_px_drifted; //MC track x momentum at start point in TPC
896  std::vector<Float_t> mctrk_py_drifted; //MC track y momentum at start point in TPC
897  std::vector<Float_t> mctrk_pz_drifted; //MC track z momentum at start point in TPC
898  //MC Track mother information
899  std::vector<Int_t> mctrk_Motherpdg; //MC Track's mother PDG code.
900  std::vector<Int_t> mctrk_MotherTrkId; //MC Track's mother G4 track ID.
901  std::vector<std::string> mctrk_MotherProcess; //MC Track's mother creation process.
902  std::vector<Float_t> mctrk_MotherstartX; //MC Track's mother G4 startX .
903  std::vector<Float_t> mctrk_MotherstartY; //MC Track's mother G4 startY .
904  std::vector<Float_t> mctrk_MotherstartZ; //MC Track's mother G4 startZ .
905  std::vector<Float_t> mctrk_MotherendX; //MC Track's mother G4 endX .
906  std::vector<Float_t> mctrk_MotherendY; //MC Track's mother G4 endY .
907  std::vector<Float_t> mctrk_MotherendZ; //MC Track's mother G4 endZ .
908  //MC Track ancestor information
909  std::vector<Int_t> mctrk_Ancestorpdg; //MC Track's ancestor PDG code.
910  std::vector<Int_t> mctrk_AncestorTrkId; //MC Track's ancestor G4 track ID.
911  std::vector<std::string> mctrk_AncestorProcess; //MC Track's ancestor creation process.
912  std::vector<Float_t> mctrk_AncestorstartX; //MC Track's ancestor G4 startX
913  std::vector<Float_t> mctrk_AncestorstartY; //MC Track's ancestor G4 startY
914  std::vector<Float_t> mctrk_AncestorstartZ; //MC Track's ancestor G4 startZ
915  std::vector<Float_t> mctrk_AncestorendX; //MC Track's ancestor G4 endX
916  std::vector<Float_t> mctrk_AncestorendY; //MC Track's ancestor G4 endY
917  std::vector<Float_t> mctrk_AncestorendZ; //MC Track's ancestor G4 endZ
918 
919  // Auxiliary detector variables saved for each geant track
920  // This data is saved as a vector (one item per GEANT particle) of C arrays
921  // (wrapped in a BoxedArray for technical reasons), one item for each
922  // affected detector cell (which one is saved in AuxDetID
923  template <typename T>
924  using AuxDetMCData_t = std::vector<BoxedArray<T[kMaxAuxDets]>>;
925 
926  std::vector<UShort_t> NAuxDets; ///< Number of AuxDets crossed by this particle
927  AuxDetMCData_t<Short_t> AuxDetID; ///< Which AuxDet this particle went through
928  AuxDetMCData_t<Float_t> entryX; ///< Entry X position of particle into AuxDet
929  AuxDetMCData_t<Float_t> entryY; ///< Entry Y position of particle into AuxDet
930  AuxDetMCData_t<Float_t> entryZ; ///< Entry Z position of particle into AuxDet
931  AuxDetMCData_t<Float_t> entryT; ///< Entry T position of particle into AuxDet
932  AuxDetMCData_t<Float_t> exitX; ///< Exit X position of particle out of AuxDet
933  AuxDetMCData_t<Float_t> exitY; ///< Exit Y position of particle out of AuxDet
934  AuxDetMCData_t<Float_t> exitZ; ///< Exit Z position of particle out of AuxDet
935  AuxDetMCData_t<Float_t> exitT; ///< Exit T position of particle out of AuxDet
936  AuxDetMCData_t<Float_t> exitPx; ///< Exit x momentum of particle out of AuxDet
937  AuxDetMCData_t<Float_t> exitPy; ///< Exit y momentum of particle out of AuxDet
938  AuxDetMCData_t<Float_t> exitPz; ///< Exit z momentum of particle out of AuxDet
939  AuxDetMCData_t<Float_t> CombinedEnergyDep; ///< Sum energy of all particles with this trackID (+ID or -ID) in AuxDet
940 
941  unsigned int bits; ///< complementary information
942 
943  /// Returns whether we have auxiliary detector data
944  bool hasAuxDetector() const { return bits & tdAuxDet; }
945 
946  /// Returns whether we have Cry data
947  bool hasCryInfo() const { return bits & tdCry; }
948 
949  /// Returns whether we have Genie data
950  bool hasGenieInfo() const { return bits & tdGenie; }
951 
952  /// Returns whether we have MCShower data
953  bool hasMCShowerInfo() const { return bits & tdMCshwr; }
954 
955  /// Returns whether we have MCTrack data
956  bool hasMCTrackInfo() const { return bits & tdMCtrk; }
957 
958  /// Returns whether we have Hit data
959  bool hasHitInfo() const { return bits & tdHit; }
960 
961  /// Returns whether we have Hit data
962  bool hasRawDigitInfo() const { return bits & tdRawDigit; }
963 
964  /// Returns whether we have Track data
965  bool hasTrackInfo() const { return bits & tdTrack; }
966 
967  /// Returns whether we have Shower data
968  bool hasShowerInfo() const { return bits & tdShower; }
969 
970  /// Returns whether we have Vertex data
971  bool hasVertexInfo() const { return bits & tdVertex; }
972 
973  /// Returns whether we have PFParticle data
974  bool hasPFParticleInfo() const { return bits & tdPFParticle; }
975 
976  /// Returns whether we have Cluster data
977  bool hasClusterInfo() const { return bits & tdCluster; }
978 
979  /// Returns whether we have Pandora Nu Vertex data
980  bool hasPandoraNuVertexInfo() const { return bits & tdPandoraNuVertex; }
981 
982  /// Returns whether we have Geant data
983  bool hasGeantInfo() const { return bits & tdGeant; }
984 
985  /// Returns whether we have Flash data
986  bool hasFlashInfo() const { return bits & tdFlash; }
987 
988  /// Returns whether we have External Counter data
989  bool hasExternCountInfo() const { return bits & tdCount; }
990 
991  /// Returns whether we have protoDUNE beam primaries
992  bool hasProtoInfo() const { return bits & tdProto; }
993 
994  /// Returns whether we have SpacePointSolver data
995  bool hasSpacePointSolverInfo() const { return bits & tdSpacePoint; }
996 
997  /// Returns whether we have CNN data
998  bool hasCnnInfo() const { return bits & tdCnn; }
999 
1000  /// Sets the specified bits
1001  void SetBits(unsigned int setbits, bool unset = false)
1002  { if (unset) bits &= ~setbits; else bits |= setbits; }
1003 
1004  /// Constructor; clears all fields
1005  AnalysisTreeDataStruct(size_t nTrackers = 0, size_t nVertexAlgos = 0,
1006  std::vector<std::string> const& ShowerAlgos = {}):
1007  bits(tdDefault)
1008  { SetTrackers(nTrackers); SetVertexAlgos(nVertexAlgos); SetShowerAlgos(ShowerAlgos); Clear(); }
1009 
1011  { return TrackData.at(iTracker); }
1012  const TrackDataStruct& GetTrackerData(size_t iTracker) const
1013  { return TrackData.at(iTracker); }
1014 
1016  { return ShowerData.at(iShower); }
1017  ShowerDataStruct const& GetShowerData(size_t iShower) const
1018  { return ShowerData.at(iShower); }
1019 
1021  { return VertexData.at(iVertex); }
1022  const VertexDataStruct& GetVertexData(size_t iVertex) const
1023  { return VertexData.at(iVertex); }
1024 
1026  { return PFParticleData; }
1028  { return PFParticleData; }
1029 
1030  /// Clear all fields if this object (not the tracker algorithm data)
1031  void ClearLocalData();
1032 
1033  /// Clear all fields
1034  void Clear();
1035 
1036 
1037  /// Allocates data structures for the given number of trackers (no Clear())
1038  void SetTrackers(size_t nTrackers) { TrackData.resize(nTrackers); }
1039 
1040  /// Allocates data structures for the given number of vertex algos (no Clear())
1041  void SetVertexAlgos(size_t nVertexAlgos) { VertexData.resize(nVertexAlgos); }
1042 
1043  /// Allocates data structures for the given number of trackers (no Clear())
1044  void SetShowerAlgos(std::vector<std::string> const& ShowerAlgos);
1045 
1046  /// Resize the data strutcure for GEANT particles
1047  void ResizeGEANT(int nParticles);
1048 
1049  /// Resize the data strutcure for Genie primaries
1050  void ResizeGenie(int nPrimaries);
1051 
1052  /// Resize the data strutcure for Cry primaries
1053  void ResizeCry(int nPrimaries);
1054 
1055  /// Resize the data structure for ProtoDUNE primaries
1056  void ResizeProto(int nPrimaries);
1057 
1058  /// Resize the data strutcure for MC Showers
1059  void ResizeMCShower(int nMCShowers);
1060 
1061  /// Resize the data strutcure for MC Tracks
1062  void ResizeMCTrack(int nMCTracks);
1063 
1064  /// Resize the data structure for SpacePointSolver
1065  void ResizeSpacePointSolver(int nSpacePoints);
1066 
1067  /// Connect this object with a tree
1068  void SetAddresses(
1069  TTree* pTree,
1070  std::vector<std::string> const& trackers,
1071  std::vector<std::string> const& vertexalgos,
1072  std::vector<std::string> const& showeralgos,
1073  bool isCosmics
1074  );
1075 
1076 
1077  /// Returns the number of trackers for which data structures are allocated
1078  size_t GetNTrackers() const { return TrackData.size(); }
1079 
1080  /// Returns the number of Vertex algos for which data structures are allocated
1081  size_t GetNVertexAlgos() const { return VertexData.size(); }
1082 
1083  /// Returns the number of trackers for which data structures are allocated
1084  size_t GetNShowerAlgos() const { return ShowerData.size(); }
1085 
1086  /// Returns the number of hits for which memory is allocated
1087  size_t GetMaxHits() const { return kMaxHits; }
1088 
1089  /// Returns the number of trackers for which memory is allocated
1090  size_t GetMaxTrackers() const { return TrackData.capacity(); }
1091 
1092  /// Returns the number of trackers for which memory is allocated
1093  size_t GetMaxVertexAlgos() const { return VertexData.capacity(); }
1094 
1095  /// Returns the number of trackers for which memory is allocated
1096  size_t GetMaxShowers() const { return ShowerData.capacity(); }
1097 
1098  /// Returns the number of GEANT particles for which memory is allocated
1099  size_t GetMaxGEANTparticles() const { return MaxGEANTparticles; }
1100 
1101  /// Returns the number of GENIE primaries for which memory is allocated
1102  size_t GetMaxGeniePrimaries() const { return MaxGeniePrimaries; }
1103 
1104 
1105  private:
1106  /// Little helper functor class to create or reset branches in a tree
1108  public:
1109  TTree* pTree; ///< the tree to be worked on
1110  BranchCreator(TTree* tree): pTree(tree) {}
1111 
1112  //@{
1113  /// Create a branch if it does not exist, and set its address
1114  void operator()
1115  (std::string name, void* address, std::string leaflist /*, int bufsize = 32000 */)
1116  {
1117  if (!pTree) return;
1118  TBranch* pBranch = pTree->GetBranch(name.c_str());
1119  if (!pBranch) {
1120  pTree->Branch(name.c_str(), address, leaflist.c_str() /*, bufsize */);
1121  MF_LOG_DEBUG("AnalysisTreeStructure")
1122  << "Creating branch '" << name << " with leaf '" << leaflist << "'";
1123  }
1124  else if (pBranch->GetAddress() != address) {
1125  pBranch->SetAddress(address);
1126  MF_LOG_DEBUG("AnalysisTreeStructure")
1127  << "Reassigning address to branch '" << name << "'";
1128  }
1129  else {
1130  MF_LOG_DEBUG("AnalysisTreeStructure")
1131  << "Branch '" << name << "' is fine";
1132  }
1133  } // operator()
1134  void operator()
1135  (std::string name, void* address, const std::stringstream& leaflist /*, int bufsize = 32000 */)
1136  { return this->operator() (name, address, leaflist.str() /*, int bufsize = 32000 */); }
1137  template <typename T>
1138  void operator()
1139  (std::string name, std::vector<T>& data, std::string leaflist /*, int bufsize = 32000 */)
1140  { return this->operator() (name, (void*) data.data(), leaflist /*, int bufsize = 32000 */); }
1141 
1142  template <typename T>
1143  void operator() (std::string name, std::vector<T>& data)
1144  {
1145  // overload for a generic object expressed directly by reference
1146  // (as opposed to a generic object expressed by a pointer or
1147  // to a simple leaf sequence specification);
1148  // TTree::Branch(name, T* obj, Int_t bufsize, splitlevel) and
1149  // TTree::SetObject() are used.
1150  if (!pTree) return;
1151  TBranch* pBranch = pTree->GetBranch(name.c_str());
1152  if (!pBranch) {
1153  pTree->Branch(name.c_str(), &data);
1154  // ROOT needs a TClass definition for T in order to create a branch,
1155  // se we are sure that at this point the TClass exists
1156  MF_LOG_DEBUG("AnalysisTreeStructure")
1157  << "Creating object branch '" << name
1158  << " with " << TClass::GetClass(typeid(T))->ClassName();
1159  }
1160  else if
1161  (*(reinterpret_cast<std::vector<T>**>(pBranch->GetAddress())) != &data)
1162  {
1163  // when an object is provided directly, the address of the object
1164  // is assigned in TBranchElement::fObject (via TObject::SetObject())
1165  // and the address itself is set to the address of the fObject
1166  // member. Here we check that the address of the object in fObject
1167  // is the same as the address of our current data type
1168  pBranch->SetObject(&data);
1169  MF_LOG_DEBUG("AnalysisTreeStructure")
1170  << "Reassigning object to branch '" << name << "'";
1171  }
1172  else {
1173  MF_LOG_DEBUG("AnalysisTreeStructure")
1174  << "Branch '" << name << "' is fine";
1175  }
1176  } // operator()
1177  //@}
1178  }; // class BranchCreator
1179 
1180  }; // class AnalysisTreeDataStruct
1181 
1182 
1183  /// Contains ROOTTreeCode<>::code, ROOT tree character for branch of type T
1184  template <typename T> struct ROOTTreeCode; // generally undefined
1185 
1186  template<> struct ROOTTreeCode<Short_t> { static constexpr char code = 'S'; };
1187  template<> struct ROOTTreeCode<Int_t> { static constexpr char code = 'I'; };
1188  template<> struct ROOTTreeCode<Double_t> { static constexpr char code = 'D'; };
1189 
1190 
1191  /// Class whose "type" contains the base data type of the container
1192  template <typename C> struct ContainerValueType; // generally undefined
1193 
1194  template <typename A>
1195  struct ContainerValueType<std::vector<AnalysisTreeDataStruct::BoxedArray<A>>>
1197 
1198  template <typename T>
1200  { using type = typename std::vector<T>::value_type; };
1201 
1202 
1203  /**
1204  * @brief Creates a simple ROOT tree with tracking and calorimetry information
1205  *
1206  * <h2>Configuration parameters</h2>
1207  * - <b>UseBuffers</b> (default: false): if enabled, memory is allocated for
1208  * tree data for all the run; otherwise, it's allocated on each event, used
1209  * and freed; use "true" for speed, "false" to save memory
1210  * - <b>SaveAuxDetInfo</b> (default: false): if enabled, auxiliary detector
1211  * data will be extracted and included in the tree
1212  */
1214 
1215  public:
1216 
1217  explicit AnalysisTree(fhicl::ParameterSet const& pset);
1218  virtual ~AnalysisTree();
1219 
1220  /// read access to event
1221  void analyze(const art::Event& evt);
1222  // void beginJob() {}
1223  void beginSubRun(const art::SubRun& sr);
1224  void endSubRun(const art::SubRun& sr);
1225 
1226  private:
1227 
1228  void HitsPurity(detinfo::DetectorClocksData const& clockData,
1229  std::vector< art::Ptr<recob::Hit> > const& hits, Int_t& trackid, Float_t& purity, double& maxe);
1230  double length(const recob::Track& track);
1231  double driftedLength(detinfo::DetectorPropertiesData const& detProp,
1232  const simb::MCParticle& part, TLorentzVector& start, TLorentzVector& end, unsigned int &starti, unsigned int &endi);
1233  double driftedLength(detinfo::DetectorPropertiesData const& detProp,
1234  const sim::MCTrack& mctrack, TLorentzVector& tpcstart, TLorentzVector& tpcend, TLorentzVector& tpcmom);
1235  double length(const simb::MCParticle& part, TLorentzVector& start, TLorentzVector& end, unsigned int &starti, unsigned int &endi);
1236  double bdist(const TVector3& pos);
1237 
1238  TTree* fTree;
1239  TTree* fPOT;
1240  // event information is huge and dynamic;
1241  // run information is much smaller and we still store it statically
1242  // in the event
1243  std::unique_ptr<AnalysisTreeDataStruct> fData;
1244  // AnalysisTreeDataStruct::RunData_t RunData;
1246 
1263  std::vector<std::string> fTrackModuleLabel;
1265  std::vector<std::string> fVertexModuleLabel;
1266  std::vector<std::string> fShowerModuleLabel;
1267  std::vector<std::string> fCalorimetryModuleLabel;
1268  std::vector<std::string> fParticleIDModuleLabel;
1269  std::vector<std::string> fMVAPIDShowerModuleLabel;
1270  std::vector<std::string> fMVAPIDTrackModuleLabel;
1271  std::vector<std::string> fFlashT0FinderLabel;
1272  std::vector<std::string> fMCT0FinderLabel;
1275  bool fUseBuffer; ///< whether to use a permanent buffer (faster, huge memory)
1276  bool fSaveAuxDetInfo; ///< whether to extract and save auxiliary detector data
1277  bool fSaveCryInfo; ///whether to extract and save CRY particle data
1278  bool fSaveGenieInfo; ///whether to extract and save Genie information
1279  bool fSaveProtoInfo; ///whether to extract and save ProtDUNE beam simulation information
1280  bool fSaveGeantInfo; ///whether to extract and save Geant information
1281  bool fSaveMCShowerInfo; ///whether to extract and save MC Shower information
1282  bool fSaveMCTrackInfo; ///whether to extract and save MC Track information
1283  bool fSaveHitInfo; ///whether to extract and save Hit information
1284  bool fSaveRawDigitInfo; ///whether to extract and save Raw Digit information
1285  bool fSaveTrackInfo; ///whether to extract and save Track information
1286  bool fSaveVertexInfo; ///whether to extract and save Vertex information
1287  bool fSaveClusterInfo; ///whether to extract and save Cluster information
1288  bool fSavePandoraNuVertexInfo; ///whether to extract and save nu vertex information from Pandora
1289  bool fSaveFlashInfo; ///whether to extract and save Flash information
1290  bool fSaveExternCounterInfo; ///whether to extract and save External Counter information
1291  bool fSaveShowerInfo; ///whether to extract and save Shower information
1292  bool fSavePFParticleInfo; ///whether to extract and save PFParticle information
1293  bool fSaveSpacePointSolverInfo; ///whether to extract and save SpacePointSolver information
1294  bool fSaveCnnInfo; ///whether to extract and save CNN information
1295 
1296  std::vector<std::string> fCosmicTaggerAssocLabel;
1297  std::vector<std::string> fContainmentTaggerAssocLabel;
1298  std::vector<std::string> fFlashMatchAssocLabel;
1299 
1300  bool bIgnoreMissingShowers; ///< whether to ignore missing shower information
1301 
1302  bool isCosmics; ///< if it contains cosmics
1303  bool fSaveCaloCosmics; ///< save calorimetry information for cosmics
1304  float fG4minE; ///< Energy threshold to save g4 particle info
1305 
1306  double ActiveBounds[6]; // Cryostat boundaries ( neg x, pos x, neg y, pos y, neg z, pos z )
1307 
1308  /// Returns the number of trackers configured
1309  size_t GetNTrackers() const { return fTrackModuleLabel.size(); }
1310 
1311  size_t GetNVertexAlgos() const { return fVertexModuleLabel.size(); }
1312 
1313  /// Returns the number of shower algorithms configured
1314  size_t GetNShowerAlgos() const { return fShowerModuleLabel.size(); }
1315 
1316  /// Returns the name of configured shower algorithms (converted to string)
1317  std::vector<std::string> GetShowerAlgos() const
1318  { return { fShowerModuleLabel.begin(), fShowerModuleLabel.end() }; }
1319 
1320  /// Creates the structure for the tree data; optionally initializes it
1321  void CreateData(bool bClearData = false)
1322  {
1323  if (!fData) {
1324  fData.reset
1325  (new AnalysisTreeDataStruct(GetNTrackers(), GetNVertexAlgos(), GetShowerAlgos()));
1326  fData->SetBits(AnalysisTreeDataStruct::tdCry, !fSaveCryInfo);
1327  fData->SetBits(AnalysisTreeDataStruct::tdGenie, !fSaveGenieInfo);
1328  fData->SetBits(AnalysisTreeDataStruct::tdProto, !fSaveProtoInfo);
1329  fData->SetBits(AnalysisTreeDataStruct::tdGeant, !fSaveGeantInfo);
1330  fData->SetBits(AnalysisTreeDataStruct::tdMCshwr, !fSaveMCShowerInfo);
1331  fData->SetBits(AnalysisTreeDataStruct::tdMCtrk, !fSaveMCTrackInfo);
1332  fData->SetBits(AnalysisTreeDataStruct::tdHit, !fSaveHitInfo);
1333  fData->SetBits(AnalysisTreeDataStruct::tdRawDigit, !fSaveRawDigitInfo);
1334  fData->SetBits(AnalysisTreeDataStruct::tdFlash, !fSaveFlashInfo);
1335  fData->SetBits(AnalysisTreeDataStruct::tdCount, !fSaveExternCounterInfo);
1336  fData->SetBits(AnalysisTreeDataStruct::tdShower, !fSaveShowerInfo);
1337  fData->SetBits(AnalysisTreeDataStruct::tdCluster,!fSaveClusterInfo);
1338  fData->SetBits(AnalysisTreeDataStruct::tdPandoraNuVertex,!fSavePandoraNuVertexInfo);
1339  fData->SetBits(AnalysisTreeDataStruct::tdTrack, !fSaveTrackInfo);
1340  fData->SetBits(AnalysisTreeDataStruct::tdVertex, !fSaveVertexInfo);
1341  fData->SetBits(AnalysisTreeDataStruct::tdAuxDet, !fSaveAuxDetInfo);
1342  fData->SetBits(AnalysisTreeDataStruct::tdPFParticle, !fSavePFParticleInfo);
1343  fData->SetBits(AnalysisTreeDataStruct::tdSpacePoint, !fSaveSpacePointSolverInfo);
1344  fData->SetBits(AnalysisTreeDataStruct::tdCnn, !fSaveCnnInfo);
1345  }
1346  else {
1347  fData->SetTrackers(GetNTrackers());
1348  fData->SetVertexAlgos(GetNVertexAlgos());
1349  fData->SetShowerAlgos(GetShowerAlgos());
1350 
1351  if (bClearData) fData->Clear();
1352  }
1353  } // CreateData()
1354 
1355  /// Sets the addresses of all the tree branches, creating the missing ones
1357  {
1358  CheckData(__func__); CheckTree(__func__);
1359  fData->SetAddresses
1360  (fTree, fTrackModuleLabel, fVertexModuleLabel, fShowerModuleLabel, isCosmics);
1361  } // SetAddresses()
1362 
1363  /// Sets the addresses of all the tree branches of the specified tracking algo,
1364  /// creating the missing ones
1365  void SetTrackerAddresses(size_t iTracker)
1366  {
1367  CheckData(__func__); CheckTree(__func__);
1368  if (iTracker >= fData->GetNTrackers()) {
1370  << "AnalysisTree::SetTrackerAddresses(): no tracker #" << iTracker
1371  << " (" << fData->GetNTrackers() << " available)";
1372  }
1373  fData->GetTrackerData(iTracker)
1374  .SetAddresses(fTree, fTrackModuleLabel[iTracker], isCosmics);
1375  } // SetTrackerAddresses()
1376 
1377 
1378  void SetVertexAddresses(size_t iVertexAlg)
1379  {
1380  CheckData(__func__); CheckTree(__func__);
1381  if (iVertexAlg >= fData->GetNVertexAlgos()) {
1383  << "AnalysisTree::SetVertexAddresses(): no vertex alg #" << iVertexAlg
1384  << " (" << fData->GetNVertexAlgos() << " available)";
1385  }
1386  fData->GetVertexData(iVertexAlg)
1387  .SetAddresses(fTree, fVertexModuleLabel[iVertexAlg], isCosmics);
1388  } // SetVertexAddresses()
1389 
1390  /// Sets the addresses of all the tree branches of the specified shower algo,
1391  /// creating the missing ones
1392  void SetShowerAddresses(size_t iShower)
1393  {
1394  CheckData(__func__); CheckTree(__func__);
1395  if (iShower >= fData->GetNShowerAlgos()) {
1397  << "AnalysisTree::SetShowerAddresses(): no shower algo #" << iShower
1398  << " (" << fData->GetNShowerAlgos() << " available)";
1399  }
1400  fData->GetShowerData(iShower).SetAddresses(fTree);
1401  } // SetShowerAddresses()
1402 
1403  /// Sets the addresses of the tree branch of the PFParticle,
1404  /// creating it if missing
1406  {
1407  CheckData(__func__); CheckTree(__func__);
1408  fData->GetPFParticleData().SetAddresses(fTree);
1409  } // SetPFParticleAddress()
1410 
1411  /// Create the output tree and the data structures, if needed
1412  void CreateTree(bool bClearData = false);
1413 
1414  /// Destroy the local buffers (existing branches will point to invalid address!)
1415  void DestroyData() { fData.reset(); }
1416 
1417  /// Helper function: throws if no data structure is available
1418  void CheckData(std::string caller) const
1419  {
1420  if (fData) return;
1422  << "AnalysisTree::" << caller << ": no data";
1423  } // CheckData()
1424  /// Helper function: throws if no tree is available
1425  void CheckTree(std::string caller) const
1426  {
1427  if (fTree) return;
1429  << "AnalysisTree::" << caller << ": no tree";
1430  } // CheckData()
1431 
1432  /// Stores the information of shower in slot iShower of showerData
1433  void FillShower(
1435  size_t iShower, recob::Shower const& showers, const bool fSavePFParticleInfo,
1436  const std::map<Short_t, Short_t> &showerIDtoPFParticleIDMap
1437  ) const;
1438 
1439  /// Stores the information of all showers into showerData
1440  void FillShowers(
1442  std::vector<recob::Shower> const& showers, const bool fSavePFParticleInfo,
1443  const std::map<Short_t, Short_t> &showerIDtoPFParticleIDMap
1444  ) const;
1445 
1446  }; // class dune::AnalysisTree
1447 } // namespace dune
1448 
1449 
1450 namespace { // local namespace
1451  /// Simple stringstream which empties its buffer on operator() call
1452  class AutoResettingStringSteam: public std::ostringstream {
1453  public:
1454  AutoResettingStringSteam& operator() () { str(""); return *this; }
1455  }; // class AutoResettingStringSteam
1456 
1457  /// Fills a sequence of TYPE elements
1458  template <typename ITER, typename TYPE>
1459  inline void FillWith(ITER from, ITER to, TYPE value)
1460  { std::fill(from, to, value); }
1461 
1462  /// Fills a sequence of TYPE elements
1463  template <typename ITER, typename TYPE>
1464  inline void FillWith(ITER from, size_t n, TYPE value)
1465  { std::fill(from, from + n, value); }
1466 
1467  /// Fills a container with begin()/end() interface
1468  template <typename CONT, typename V>
1469  inline void FillWith(CONT& data, const V& value)
1470  { FillWith(std::begin(data), std::end(data), value); }
1471 
1472 } // local namespace
1473 
1474 
1475 //------------------------------------------------------------------------------
1476 //--- AnalysisTreeDataStruct::TrackDataStruct
1477 //---
1478 
1480 {
1481  MaxTracks = nTracks;
1482 
1483  trkId.resize(MaxTracks);
1484  trkncosmictags_tagger.resize(MaxTracks);
1485  trkcosmicscore_tagger.resize(MaxTracks);
1486  trkcosmictype_tagger.resize(MaxTracks);
1487  trkncosmictags_containmenttagger.resize(MaxTracks);
1488  trkcosmicscore_containmenttagger.resize(MaxTracks);
1489  trkcosmictype_containmenttagger.resize(MaxTracks);
1490  trkncosmictags_flashmatch.resize(MaxTracks);
1491  trkcosmicscore_flashmatch.resize(MaxTracks);
1492  trkcosmictype_flashmatch.resize(MaxTracks);
1493  trkstartx.resize(MaxTracks);
1494  trkstarty.resize(MaxTracks);
1495  trkstartz.resize(MaxTracks);
1496  trkstartd.resize(MaxTracks);
1497  trkendx.resize(MaxTracks);
1498  trkendy.resize(MaxTracks);
1499  trkendz.resize(MaxTracks);
1500  trkendd.resize(MaxTracks);
1501  trkflashT0.resize(MaxTracks);
1502  trktrueT0.resize(MaxTracks);
1503  trktheta.resize(MaxTracks);
1504  trkphi.resize(MaxTracks);
1505  trkstartdcosx.resize(MaxTracks);
1506  trkstartdcosy.resize(MaxTracks);
1507  trkstartdcosz.resize(MaxTracks);
1508  trkenddcosx.resize(MaxTracks);
1509  trkenddcosy.resize(MaxTracks);
1510  trkenddcosz.resize(MaxTracks);
1511  trkthetaxz.resize(MaxTracks);
1512  trkthetayz.resize(MaxTracks);
1513  trkmom.resize(MaxTracks);
1514  trkmomrange.resize(MaxTracks);
1515  trkmommschi2.resize(MaxTracks);
1516  trkmommsllhd.resize(MaxTracks);
1517  trklen.resize(MaxTracks);
1518  trksvtxid.resize(MaxTracks);
1519  trkevtxid.resize(MaxTracks);
1520  // PID variables
1521  trkpidpdg.resize(MaxTracks);
1522  trkpidchi.resize(MaxTracks);
1523  trkpidchipr.resize(MaxTracks);
1524  trkpidchika.resize(MaxTracks);
1525  trkpidchipi.resize(MaxTracks);
1526  trkpidchimu.resize(MaxTracks);
1527  trkpidpida.resize(MaxTracks);
1528  trkpidbestplane.resize(MaxTracks);
1529  trkpidmvamu.resize(MaxTracks);
1530  trkpidmvae.resize(MaxTracks);
1531  trkpidmvapich.resize(MaxTracks);
1532  trkpidmvaphoton.resize(MaxTracks);
1533  trkpidmvapr.resize(MaxTracks);
1534 
1535  trkke.resize(MaxTracks);
1536  trkrange.resize(MaxTracks);
1537  trkidtruth.resize(MaxTracks);
1538  trkorigin.resize(MaxTracks);
1539  trkpdgtruth.resize(MaxTracks);
1540  trkefftruth.resize(MaxTracks);
1541  trkpurtruth.resize(MaxTracks);
1542  trkpurity.resize(MaxTracks);
1543  trkcompleteness.resize(MaxTracks);
1544  trkg4id.resize(MaxTracks);
1545  trkorig.resize(MaxTracks);
1546  trkpitchc.resize(MaxTracks);
1547  ntrkhits.resize(MaxTracks);
1548 
1549  trkdedx.resize(MaxTracks);
1550  trkdqdx.resize(MaxTracks);
1551  trkresrg.resize(MaxTracks);
1552  trktpc.resize(MaxTracks);
1553  trkxyz.resize(MaxTracks);
1554 
1555  trkhasPFParticle.resize(MaxTracks);
1556  trkPFParticleID.resize(MaxTracks);
1557 
1558 } // dune::AnalysisTreeDataStruct::TrackDataStruct::Resize()
1559 
1561  Resize(MaxTracks);
1562  ntracks = 0;
1563 
1564  FillWith(trkId , -9999 );
1565  FillWith(trkncosmictags_tagger, -9999 );
1566  FillWith(trkcosmicscore_tagger, -99999.);
1567  FillWith(trkcosmictype_tagger, -9999 );
1568  FillWith(trkncosmictags_containmenttagger, -9999 );
1569  FillWith(trkcosmicscore_containmenttagger, -99999.);
1570  FillWith(trkcosmictype_containmenttagger, -9999 );
1571  FillWith(trkncosmictags_flashmatch, -9999 );
1572  FillWith(trkcosmicscore_flashmatch, -99999.);
1573  FillWith(trkcosmictype_flashmatch, -9999 );
1574  FillWith(trkstartx , -99999.);
1575  FillWith(trkstarty , -99999.);
1576  FillWith(trkstartz , -99999.);
1577  FillWith(trkstartd , -99999.);
1578  FillWith(trkendx , -99999.);
1579  FillWith(trkendy , -99999.);
1580  FillWith(trkendz , -99999.);
1581  FillWith(trkendd , -99999.);
1582  FillWith(trkflashT0 , -99999.);
1583  FillWith(trktrueT0 , -99999.);
1584  FillWith(trkg4id , -99999 );
1585  FillWith(trkpurity , -99999.);
1586  FillWith(trkcompleteness, -99999.);
1587  FillWith(trkorig , -99999 );
1588  FillWith(trktheta , -99999.);
1589  FillWith(trkphi , -99999.);
1590  FillWith(trkstartdcosx, -99999.);
1591  FillWith(trkstartdcosy, -99999.);
1592  FillWith(trkstartdcosz, -99999.);
1593  FillWith(trkenddcosx , -99999.);
1594  FillWith(trkenddcosy , -99999.);
1595  FillWith(trkenddcosz , -99999.);
1596  FillWith(trkthetaxz , -99999.);
1597  FillWith(trkthetayz , -99999.);
1598  FillWith(trkmom , -99999.);
1599  FillWith(trkmomrange , -99999.);
1600  FillWith(trkmommschi2 , -99999.);
1601  FillWith(trkmommsllhd , -99999.);
1602  FillWith(trklen , -99999.);
1603  FillWith(trksvtxid , -1);
1604  FillWith(trkevtxid , -1);
1605  FillWith(trkpidbestplane, -1);
1606  FillWith(trkpidmvamu , -99999.);
1607  FillWith(trkpidmvae , -99999.);
1608  FillWith(trkpidmvapich, -99999.);
1609  FillWith(trkpidmvaphoton , -99999.);
1610  FillWith(trkpidmvapr , -99999.);
1611 
1612  FillWith(trkhasPFParticle, -1);
1613  FillWith(trkPFParticleID , -1);
1614 
1615  for (size_t iTrk = 0; iTrk < MaxTracks; ++iTrk){
1616 
1617  // the following are BoxedArray's;
1618  // their iterators traverse all the array dimensions
1619  FillWith(trkke[iTrk] , -99999.);
1620  FillWith(trkrange[iTrk] , -99999.);
1621  FillWith(trkidtruth[iTrk] , -99999 );
1622  FillWith(trkorigin[iTrk] , -1 );
1623  FillWith(trkpdgtruth[iTrk], -99999 );
1624  FillWith(trkefftruth[iTrk], -99999.);
1625  FillWith(trkpurtruth[iTrk], -99999.);
1626  FillWith(trkpitchc[iTrk] , -99999.);
1627  FillWith(ntrkhits[iTrk] , -9999 );
1628 
1629  FillWith(trkdedx[iTrk], 0.);
1630  FillWith(trkdqdx[iTrk], 0.);
1631  FillWith(trkresrg[iTrk], 0.);
1632  FillWith(trktpc[iTrk], -1);
1633  FillWith(trkxyz[iTrk], 0.);
1634 
1635  FillWith(trkpidpdg[iTrk] , -1);
1636  FillWith(trkpidchi[iTrk] , -99999.);
1637  FillWith(trkpidchipr[iTrk] , -99999.);
1638  FillWith(trkpidchika[iTrk] , -99999.);
1639  FillWith(trkpidchipi[iTrk] , -99999.);
1640  FillWith(trkpidchimu[iTrk] , -99999.);
1641  FillWith(trkpidpida[iTrk] , -99999.);
1642  } // for track
1643 
1644 } // dune::AnalysisTreeDataStruct::TrackDataStruct::Clear()
1645 
1646 
1648  TTree* pTree, std::string tracker, bool isCosmics
1649  ) {
1650  if (MaxTracks == 0) return; // no tracks, no tree!
1651 
1652  dune::AnalysisTreeDataStruct::BranchCreator CreateBranch(pTree);
1653 
1654  AutoResettingStringSteam sstr;
1655  sstr() << kMaxTrackHits;
1656  std::string MaxTrackHitsIndexStr("[" + sstr.str() + "]");
1657 
1658  std::string TrackLabel = tracker;
1659  std::string BranchName;
1660 
1661  BranchName = "ntracks_" + TrackLabel;
1662  CreateBranch(BranchName, &ntracks, BranchName + "/S");
1663  std::string NTracksIndexStr = "[" + BranchName + "]";
1664 
1665  BranchName = "trkId_" + TrackLabel;
1666  CreateBranch(BranchName, trkId, BranchName + NTracksIndexStr + "/S");
1667 
1668  BranchName = "trkncosmictags_tagger_" + TrackLabel;
1669  CreateBranch(BranchName, trkncosmictags_tagger, BranchName + NTracksIndexStr + "/S");
1670 
1671  BranchName = "trkcosmicscore_tagger_" + TrackLabel;
1672  CreateBranch(BranchName, trkcosmicscore_tagger, BranchName + NTracksIndexStr + "/F");
1673 
1674  BranchName = "trkcosmictype_tagger_" + TrackLabel;
1675  CreateBranch(BranchName, trkcosmictype_tagger, BranchName + NTracksIndexStr + "/S");
1676 
1677  BranchName = "trkncosmictags_containmenttagger_" + TrackLabel;
1678  CreateBranch(BranchName, trkncosmictags_containmenttagger, BranchName + NTracksIndexStr + "/S");
1679 
1680  BranchName = "trkcosmicscore_containmenttagger_" + TrackLabel;
1681  CreateBranch(BranchName, trkcosmicscore_containmenttagger, BranchName + NTracksIndexStr + "/F");
1682 
1683  BranchName = "trkcosmictype_containmenttagger_" + TrackLabel;
1684  CreateBranch(BranchName, trkcosmictype_containmenttagger, BranchName + NTracksIndexStr + "/S");
1685 
1686  BranchName = "trkncosmictags_flashmatch_" + TrackLabel;
1687  CreateBranch(BranchName, trkncosmictags_flashmatch, BranchName + NTracksIndexStr + "/S");
1688 
1689  BranchName = "trkcosmicscore_flashmatch_" + TrackLabel;
1690  CreateBranch(BranchName, trkcosmicscore_flashmatch, BranchName + NTracksIndexStr + "/F");
1691 
1692  BranchName = "trkcosmictype_flashmatch_" + TrackLabel;
1693  CreateBranch(BranchName, trkcosmictype_flashmatch, BranchName + NTracksIndexStr + "/S");
1694 
1695  BranchName = "trkke_" + TrackLabel;
1696  CreateBranch(BranchName, trkke, BranchName + NTracksIndexStr + "[3]/F");
1697 
1698  BranchName = "trkrange_" + TrackLabel;
1699  CreateBranch(BranchName, trkrange, BranchName + NTracksIndexStr + "[3]/F");
1700 
1701  BranchName = "trkidtruth_" + TrackLabel;
1702  CreateBranch(BranchName, trkidtruth, BranchName + NTracksIndexStr + "[3]/I");
1703 
1704  BranchName = "trkorigin_" + TrackLabel;
1705  CreateBranch(BranchName, trkorigin, BranchName + NTracksIndexStr + "[3]/S");
1706 
1707  BranchName = "trkpdgtruth_" + TrackLabel;
1708  CreateBranch(BranchName, trkpdgtruth, BranchName + NTracksIndexStr + "[3]/I");
1709 
1710  BranchName = "trkefftruth_" + TrackLabel;
1711  CreateBranch(BranchName, trkefftruth, BranchName + NTracksIndexStr + "[3]/F");
1712 
1713  BranchName = "trkpurtruth_" + TrackLabel;
1714  CreateBranch(BranchName, trkpurtruth, BranchName + NTracksIndexStr + "[3]/F");
1715 
1716  BranchName = "trkpitchc_" + TrackLabel;
1717  CreateBranch(BranchName, trkpitchc, BranchName + NTracksIndexStr + "[3]/F");
1718 
1719  BranchName = "ntrkhits_" + TrackLabel;
1720  CreateBranch(BranchName, ntrkhits, BranchName + NTracksIndexStr + "[3]/S");
1721 
1722  if (!isCosmics){
1723  BranchName = "trkdedx_" + TrackLabel;
1724  CreateBranch(BranchName, trkdedx, BranchName + NTracksIndexStr + "[3]" + MaxTrackHitsIndexStr + "/F");
1725 
1726  BranchName = "trkdqdx_" + TrackLabel;
1727  CreateBranch(BranchName, trkdqdx, BranchName + NTracksIndexStr + "[3]" + MaxTrackHitsIndexStr + "/F");
1728 
1729  BranchName = "trkresrg_" + TrackLabel;
1730  CreateBranch(BranchName, trkresrg, BranchName + NTracksIndexStr + "[3]" + MaxTrackHitsIndexStr + "/F");
1731 
1732  BranchName = "trktpc_" + TrackLabel;
1733  CreateBranch(BranchName, trktpc, BranchName + NTracksIndexStr + "[3]" + MaxTrackHitsIndexStr + "/I");
1734 
1735  BranchName = "trkxyz_" + TrackLabel;
1736  CreateBranch(BranchName, trkxyz, BranchName + NTracksIndexStr + "[3]" + MaxTrackHitsIndexStr + "[3]" + "/F");
1737  }
1738 
1739  BranchName = "trkstartx_" + TrackLabel;
1740  CreateBranch(BranchName, trkstartx, BranchName + NTracksIndexStr + "/F");
1741 
1742  BranchName = "trkstarty_" + TrackLabel;
1743  CreateBranch(BranchName, trkstarty, BranchName + NTracksIndexStr + "/F");
1744 
1745  BranchName = "trkstartz_" + TrackLabel;
1746  CreateBranch(BranchName, trkstartz, BranchName + NTracksIndexStr + "/F");
1747 
1748  BranchName = "trkstartd_" + TrackLabel;
1749  CreateBranch(BranchName, trkstartd, BranchName + NTracksIndexStr + "/F");
1750 
1751  BranchName = "trkendx_" + TrackLabel;
1752  CreateBranch(BranchName, trkendx, BranchName + NTracksIndexStr + "/F");
1753 
1754  BranchName = "trkendy_" + TrackLabel;
1755  CreateBranch(BranchName, trkendy, BranchName + NTracksIndexStr + "/F");
1756 
1757  BranchName = "trkendz_" + TrackLabel;
1758  CreateBranch(BranchName, trkendz, BranchName + NTracksIndexStr + "/F");
1759 
1760  BranchName = "trkendd_" + TrackLabel;
1761  CreateBranch(BranchName, trkendd, BranchName + NTracksIndexStr + "/F");
1762 
1763  BranchName = "trkflashT0_" + TrackLabel;
1764  CreateBranch(BranchName, trkflashT0, BranchName + NTracksIndexStr + "/F");
1765 
1766  BranchName = "trktrueT0_" + TrackLabel;
1767  CreateBranch(BranchName, trktrueT0, BranchName + NTracksIndexStr + "/F");
1768 
1769  BranchName = "trkg4id_" + TrackLabel;
1770  CreateBranch(BranchName, trkg4id, BranchName + NTracksIndexStr + "/I");
1771 
1772  BranchName = "trkorig_" + TrackLabel;
1773  CreateBranch(BranchName, trkorig, BranchName + NTracksIndexStr + "/I");
1774 
1775  BranchName = "trkpurity_" + TrackLabel;
1776  CreateBranch(BranchName, trkpurity, BranchName + NTracksIndexStr + "/F");
1777 
1778  BranchName = "trkcompleteness_" + TrackLabel;
1779  CreateBranch(BranchName, trkcompleteness, BranchName + NTracksIndexStr + "/F");
1780 
1781  BranchName = "trktheta_" + TrackLabel;
1782  CreateBranch(BranchName, trktheta, BranchName + NTracksIndexStr + "/F");
1783 
1784  BranchName = "trkphi_" + TrackLabel;
1785  CreateBranch(BranchName, trkphi, BranchName + NTracksIndexStr + "/F");
1786 
1787  BranchName = "trkstartdcosx_" + TrackLabel;
1788  CreateBranch(BranchName, trkstartdcosx, BranchName + NTracksIndexStr + "/F");
1789 
1790  BranchName = "trkstartdcosy_" + TrackLabel;
1791  CreateBranch(BranchName, trkstartdcosy, BranchName + NTracksIndexStr + "/F");
1792 
1793  BranchName = "trkstartdcosz_" + TrackLabel;
1794  CreateBranch(BranchName, trkstartdcosz, BranchName + NTracksIndexStr + "/F");
1795 
1796  BranchName = "trkenddcosx_" + TrackLabel;
1797  CreateBranch(BranchName, trkenddcosx, BranchName + NTracksIndexStr + "/F");
1798 
1799  BranchName = "trkenddcosy_" + TrackLabel;
1800  CreateBranch(BranchName, trkenddcosy, BranchName + NTracksIndexStr + "/F");
1801 
1802  BranchName = "trkenddcosz_" + TrackLabel;
1803  CreateBranch(BranchName, trkenddcosz, BranchName + NTracksIndexStr + "/F");
1804 
1805  BranchName = "trkthetaxz_" + TrackLabel;
1806  CreateBranch(BranchName, trkthetaxz, BranchName + NTracksIndexStr + "/F");
1807 
1808  BranchName = "trkthetayz_" + TrackLabel;
1809  CreateBranch(BranchName, trkthetayz, BranchName + NTracksIndexStr + "/F");
1810 
1811  BranchName = "trkmom_" + TrackLabel;
1812  CreateBranch(BranchName, trkmom, BranchName + NTracksIndexStr + "/F");
1813 
1814  BranchName = "trkmomrange_" + TrackLabel;
1815  CreateBranch(BranchName, trkmomrange, BranchName + NTracksIndexStr + "/F");
1816 
1817  BranchName = "trkmommschi2_" + TrackLabel;
1818  CreateBranch(BranchName, trkmommschi2, BranchName + NTracksIndexStr + "/F");
1819 
1820  BranchName = "trkmommsllhd_" + TrackLabel;
1821  CreateBranch(BranchName, trkmommsllhd, BranchName + NTracksIndexStr + "/F");
1822 
1823  BranchName = "trklen_" + TrackLabel;
1824  CreateBranch(BranchName, trklen, BranchName + NTracksIndexStr + "/F");
1825 
1826  BranchName = "trksvtxid_" + TrackLabel;
1827  CreateBranch(BranchName, trksvtxid, BranchName + NTracksIndexStr + "/S");
1828 
1829  BranchName = "trkevtxid_" + TrackLabel;
1830  CreateBranch(BranchName, trkevtxid, BranchName + NTracksIndexStr + "/S");
1831 
1832  BranchName = "trkpidmvamu_" + TrackLabel;
1833  CreateBranch(BranchName, trkpidmvamu, BranchName + NTracksIndexStr + "/F");
1834 
1835  BranchName = "trkpidmvae_" + TrackLabel;
1836  CreateBranch(BranchName, trkpidmvae, BranchName + NTracksIndexStr + "/F");
1837 
1838  BranchName = "trkpidmvapich_" + TrackLabel;
1839  CreateBranch(BranchName, trkpidmvapich, BranchName + NTracksIndexStr + "/F");
1840 
1841  BranchName = "trkpidmvaphoton_" + TrackLabel;
1842  CreateBranch(BranchName, trkpidmvaphoton, BranchName + NTracksIndexStr + "/F");
1843 
1844  BranchName = "trkpidmvapr_" + TrackLabel;
1845  CreateBranch(BranchName, trkpidmvapr, BranchName + NTracksIndexStr + "/F");
1846 
1847  BranchName = "trkpidpdg_" + TrackLabel;
1848  CreateBranch(BranchName, trkpidpdg, BranchName + NTracksIndexStr + "[3]/I");
1849 
1850  BranchName = "trkpidchi_" + TrackLabel;
1851  CreateBranch(BranchName, trkpidchi, BranchName + NTracksIndexStr + "[3]/F");
1852 
1853  BranchName = "trkpidchipr_" + TrackLabel;
1854  CreateBranch(BranchName, trkpidchipr, BranchName + NTracksIndexStr + "[3]/F");
1855 
1856  BranchName = "trkpidchika_" + TrackLabel;
1857  CreateBranch(BranchName, trkpidchika, BranchName + NTracksIndexStr + "[3]/F");
1858 
1859  BranchName = "trkpidchipi_" + TrackLabel;
1860  CreateBranch(BranchName, trkpidchipi, BranchName + NTracksIndexStr + "[3]/F");
1861 
1862  BranchName = "trkpidchimu_" + TrackLabel;
1863  CreateBranch(BranchName, trkpidchimu, BranchName + NTracksIndexStr + "[3]/F");
1864 
1865  BranchName = "trkpidpida_" + TrackLabel;
1866  CreateBranch(BranchName, trkpidpida, BranchName + NTracksIndexStr + "[3]/F");
1867 
1868  BranchName = "trkpidbestplane_" + TrackLabel;
1869  CreateBranch(BranchName, trkpidbestplane, BranchName + NTracksIndexStr + "/S");
1870 
1871  BranchName = "trkhasPFParticle_" + TrackLabel;
1872  CreateBranch(BranchName, trkhasPFParticle, BranchName + NTracksIndexStr + "/S");
1873 
1874  BranchName = "trkPFParticleID_" + TrackLabel;
1875  CreateBranch(BranchName, trkPFParticleID, BranchName + NTracksIndexStr + "/S");
1876 
1877 } // dune::AnalysisTreeDataStruct::TrackDataStruct::SetAddresses()
1878 
1879 
1880 
1882 {
1883  MaxVertices = nVertices;
1884  vtxId.resize(MaxVertices);
1885  vtxx.resize(MaxVertices);
1886  vtxy.resize(MaxVertices);
1887  vtxz.resize(MaxVertices);
1888 
1889  vtxhasPFParticle.resize(MaxVertices);
1890  vtxPFParticleID.resize(MaxVertices);
1891 }
1892 
1894  Resize(MaxVertices);
1895  nvtx = -9999;
1896 
1897  FillWith(vtxId , -9999 );
1898  FillWith(vtxx , -9999 );
1899  FillWith(vtxy , -9999 );
1900  FillWith(vtxz , -9999 );
1901  FillWith(vtxhasPFParticle, -1 );
1902  FillWith(vtxPFParticleID , -1 );
1903 }
1904 
1906  TTree* pTree, std::string alg, bool isCosmics
1907  ) {
1908  if (MaxVertices == 0) return; // no tracks, no tree!
1909 
1910  dune::AnalysisTreeDataStruct::BranchCreator CreateBranch(pTree);
1911 
1912  AutoResettingStringSteam sstr;
1913 
1914  std::string VertexLabel = alg;
1915  std::string BranchName;
1916 
1917  BranchName = "nvtx_" + VertexLabel;
1918  CreateBranch(BranchName, &nvtx, BranchName + "/S");
1919  std::string NVertexIndexStr = "[" + BranchName + "]";
1920 
1921  BranchName = "vtxId_" + VertexLabel;
1922  CreateBranch(BranchName, vtxId, BranchName + NVertexIndexStr + "/S");
1923 
1924  BranchName = "vtxx_" + VertexLabel;
1925  CreateBranch(BranchName, vtxx, BranchName + NVertexIndexStr + "/F");
1926 
1927  BranchName = "vtxy_" + VertexLabel;
1928  CreateBranch(BranchName, vtxy, BranchName + NVertexIndexStr + "/F");
1929 
1930  BranchName = "vtxz_" + VertexLabel;
1931  CreateBranch(BranchName, vtxz, BranchName + NVertexIndexStr + "/F");
1932 
1933  BranchName = "vtxhasPFParticle_" + VertexLabel;
1934  CreateBranch(BranchName, vtxhasPFParticle, BranchName + NVertexIndexStr + "/S");
1935 
1936  BranchName = "vtxPFParticleID_" + VertexLabel;
1937  CreateBranch(BranchName, vtxPFParticleID, BranchName + NVertexIndexStr + "/S");
1938 }
1939 
1940 //------------------------------------------------------------------------------
1941 //--- AnalysisTreeDataStruct::PFParticleDataStruct
1942 //---
1943 
1945 {
1946  MaxPFParticles = nPFParticles;
1947 
1948  pfp_selfID.resize(MaxPFParticles);
1949  pfp_isPrimary.resize(MaxPFParticles);
1950  pfp_numDaughters.resize(MaxPFParticles);
1951  pfp_daughterIDs.resize(MaxPFParticles);
1952  pfp_parentID.resize(MaxPFParticles);
1953  pfp_vertexID.resize(MaxPFParticles);
1954  pfp_isShower.resize(MaxPFParticles);
1955  pfp_isTrack.resize(MaxPFParticles);
1956  pfp_trackID.resize(MaxPFParticles);
1957  pfp_showerID.resize(MaxPFParticles);
1958  pfp_pdgCode.resize(MaxPFParticles);
1959  pfp_numClusters.resize(MaxPFParticles);
1960  pfp_clusterIDs.resize(MaxPFParticles);
1961  pfp_isNeutrino.resize(MaxPFParticles);
1962 }
1963 
1965  Resize(MaxPFParticles);
1966 
1967  nPFParticles = -9999;
1968  FillWith(pfp_selfID, -9999);
1969  FillWith(pfp_isPrimary, -9999);
1970  FillWith(pfp_numDaughters, -9999);
1971  FillWith(pfp_parentID, -9999);
1972  FillWith(pfp_vertexID, -9999);
1973  FillWith(pfp_isShower, -9999);
1974  FillWith(pfp_isTrack, -9999);
1975  FillWith(pfp_trackID, -9999);
1976  FillWith(pfp_showerID, -9999);
1977  FillWith(pfp_pdgCode, -9999);
1978  FillWith(pfp_isNeutrino, -9999);
1979  pfp_numNeutrinos = -9999;
1980  FillWith(pfp_neutrinoIDs, -9999);
1981 
1982  for (size_t iPFParticle = 0; iPFParticle < MaxPFParticles; ++iPFParticle){
1983  // the following are BoxedArrays;
1984  // their iterators traverse all the array dimensions
1985  FillWith(pfp_daughterIDs[iPFParticle], -9999);
1986  FillWith(pfp_clusterIDs[iPFParticle], -9999);
1987  }
1988 }
1989 
1991  TTree* pTree
1992 ) {
1993 
1994  if (MaxPFParticles == 0) { return; } // no PFParticles, no tree
1995 
1996  dune::AnalysisTreeDataStruct::BranchCreator CreateBranch(pTree);
1997 
1998  AutoResettingStringSteam sstr;
1999  sstr() << kMaxNDaughtersPerPFP;
2000  std::string MaxNDaughtersIndexStr("[" + sstr.str() + "]");
2001 
2002  sstr.str("");
2003  sstr() << kMaxNClustersPerPFP;
2004  std::string MaxNClustersIndexStr("[" + sstr.str() + "]");
2005 
2006  sstr.str("");
2007  sstr() << kMaxNPFPNeutrinos;
2008  std::string MaxNNeutrinosIndexStr("[" + sstr.str() + "]");
2009 
2010  std::string BranchName;
2011 
2012  BranchName = "nPFParticles";
2013  CreateBranch(BranchName, &nPFParticles, BranchName + "/S");
2014  std::string NPFParticleIndexStr = "[" + BranchName + "]";
2015 
2016  BranchName = "pfp_selfID";
2017  CreateBranch(BranchName, pfp_selfID, BranchName + NPFParticleIndexStr + "/S");
2018 
2019  BranchName = "pfp_isPrimary";
2020  CreateBranch(BranchName, pfp_isPrimary, BranchName + NPFParticleIndexStr + "/S");
2021 
2022  BranchName = "pfp_numDaughters";
2023  CreateBranch(BranchName, pfp_numDaughters, BranchName + NPFParticleIndexStr + "/S");
2024 
2025  BranchName = "pfp_daughterIDs";
2026  CreateBranch(BranchName, pfp_daughterIDs, BranchName + NPFParticleIndexStr + MaxNDaughtersIndexStr + "/S");
2027 
2028  BranchName = "pfp_parentID";
2029  CreateBranch(BranchName, pfp_parentID, BranchName + NPFParticleIndexStr + "/S");
2030 
2031  BranchName = "pfp_vertexID";
2032  CreateBranch(BranchName, pfp_vertexID, BranchName + NPFParticleIndexStr + "/S");
2033 
2034  BranchName = "pfp_isShower";
2035  CreateBranch(BranchName, pfp_isShower, BranchName + NPFParticleIndexStr + "/S");
2036 
2037  BranchName = "pfp_isTrack";
2038  CreateBranch(BranchName, pfp_isTrack, BranchName + NPFParticleIndexStr + "/S");
2039 
2040  BranchName = "pfp_trackID";
2041  CreateBranch(BranchName, pfp_trackID, BranchName + NPFParticleIndexStr + "/S");
2042 
2043  BranchName = "pfp_showerID";
2044  CreateBranch(BranchName, pfp_showerID, BranchName + NPFParticleIndexStr + "/S");
2045 
2046  BranchName = "pfp_pdgCode";
2047  CreateBranch(BranchName, pfp_pdgCode, BranchName + NPFParticleIndexStr + "/I");
2048 
2049  BranchName = "pfp_numClusters";
2050  CreateBranch(BranchName, pfp_numClusters, BranchName + NPFParticleIndexStr + "/S");
2051 
2052  BranchName = "pfp_clusterIDs";
2053  CreateBranch(BranchName, pfp_clusterIDs, BranchName + NPFParticleIndexStr + MaxNClustersIndexStr + "/S");
2054 
2055  BranchName = "pfp_isNeutrino";
2056  CreateBranch(BranchName, pfp_isNeutrino, BranchName + NPFParticleIndexStr + "/S");
2057 
2058  BranchName = "pfp_numNeutrinos";
2059  CreateBranch(BranchName, &pfp_numNeutrinos, BranchName + "/S");
2060 
2061  BranchName = "pfp_neutrinoIDs";
2062  CreateBranch(BranchName, pfp_neutrinoIDs, BranchName + MaxNNeutrinosIndexStr + "/S");
2063 }
2064 
2065 //------------------------------------------------------------------------------
2066 //--- AnalysisTreeDataStruct::ShowerDataStruct
2067 //---
2068 
2070 (size_t nShowers)
2071 {
2072  MaxShowers = nShowers;
2073 
2074  showerID.resize(MaxShowers);
2075  shwr_bestplane.resize(MaxShowers);
2076  shwr_length.resize(MaxShowers);
2077  shwr_startdcosx.resize(MaxShowers);
2078  shwr_startdcosy.resize(MaxShowers);
2079  shwr_startdcosz.resize(MaxShowers);
2080  shwr_startx.resize(MaxShowers);
2081  shwr_starty.resize(MaxShowers);
2082  shwr_startz.resize(MaxShowers);
2083  shwr_totEng.resize(MaxShowers);
2084  shwr_dedx.resize(MaxShowers);
2085  shwr_mipEng.resize(MaxShowers);
2086  shwr_pidmvamu.resize(MaxShowers);
2087  shwr_pidmvae.resize(MaxShowers);
2088  shwr_pidmvapich.resize(MaxShowers);
2089  shwr_pidmvaphoton.resize(MaxShowers);
2090  shwr_pidmvapr.resize(MaxShowers);
2091 
2092  shwr_hasPFParticle.resize(MaxShowers);
2093  shwr_PFParticleID.resize(MaxShowers);
2094 
2095 } // dune::AnalysisTreeDataStruct::ShowerDataStruct::Resize()
2096 
2098  Resize(MaxShowers);
2099  nshowers = 0;
2100 
2101  FillWith(showerID, -9999 );
2102  FillWith(shwr_bestplane, -9999 );
2103  FillWith(shwr_length, -99999.);
2104  FillWith(shwr_startdcosx, -99999.);
2105  FillWith(shwr_startdcosy, -99999.);
2106  FillWith(shwr_startdcosz, -99999.);
2107  FillWith(shwr_startx, -99999.);
2108  FillWith(shwr_starty, -99999.);
2109  FillWith(shwr_startz, -99999.);
2110  FillWith(shwr_pidmvamu, -99999.);
2111  FillWith(shwr_pidmvae, -99999.);
2112  FillWith(shwr_pidmvapich, -99999.);
2113  FillWith(shwr_pidmvaphoton, -99999.);
2114  FillWith(shwr_pidmvapr, -99999.);
2115 
2116  FillWith(shwr_hasPFParticle, -1);
2117  FillWith(shwr_PFParticleID, -1);
2118 
2119  for (size_t iShw = 0; iShw < MaxShowers; ++iShw){
2120  // the following are BoxedArray's;
2121  // their iterators traverse all the array dimensions
2122  FillWith(shwr_totEng[iShw], -99999.);
2123  FillWith(shwr_dedx[iShw], -99999.);
2124  FillWith(shwr_mipEng[iShw], -99999.);
2125  } // for shower
2126 
2127 } // dune::AnalysisTreeDataStruct::ShowerDataStruct::Clear()
2128 
2129 
2131 (TTree* pTree)
2132 {
2133  // here we implement the policy prescription for a missing set of showers;
2134  // this means that no shower data product was found in the event,
2135  // yet the user has accepted to go on.
2136  // We now need to mark this product in a unmistakably clear way, so that it
2137  // is not confused with a valid collection of an event where no showers
2138  // were reconstructed, not as a list of valid showers.
2139  // The prescription currently implemented is:
2140  // - have only one shower in the list;
2141  // - set the ID of that shower as -9999
2142  //
2143 
2144  // first set the data structures to contain one invalid shower:
2145  SetMaxShowers(1); // includes resize to a set of one shower
2146  Clear(); // initializes all the showers in the set (one) as invalid
2147  // now set the tree addresses to the newly allocated memory;
2148  // this creates the tree branches in case they are not there yet
2149  SetAddresses(pTree);
2150 
2151  // then, set the variables so that ROOT tree knows there is one shower only
2152  nshowers = 1;
2153 
2154 } // dune::AnalysisTreeDataStruct::ShowerDataStruct::MarkMissing()
2155 
2156 
2158 (TTree* pTree)
2159 {
2160  if (MaxShowers == 0) return; // no showers, no tree!
2161 
2162  dune::AnalysisTreeDataStruct::BranchCreator CreateBranch(pTree);
2163 
2164  AutoResettingStringSteam sstr;
2165  sstr() << kMaxShowerHits;
2166  std::string MaxShowerHitsIndexStr("[" + sstr.str() + "]");
2167 
2168  std::string ShowerLabel = Name();
2169  std::string BranchName;
2170 
2171  BranchName = "nshowers_" + ShowerLabel;
2172  CreateBranch(BranchName, &nshowers, BranchName + "/S");
2173  std::string NShowerIndexStr = "[" + BranchName + "]";
2174 
2175  BranchName = "showerID_" + ShowerLabel;
2176  CreateBranch(BranchName, showerID, BranchName + NShowerIndexStr + "/S");
2177 
2178  BranchName = "shwr_bestplane_" + ShowerLabel;
2179  CreateBranch(BranchName, shwr_bestplane, BranchName + NShowerIndexStr + "/S");
2180 
2181  BranchName = "shwr_length_" + ShowerLabel;
2182  CreateBranch(BranchName, shwr_length, BranchName + NShowerIndexStr + "/F");
2183 
2184  BranchName = "shwr_startdcosx_" + ShowerLabel;
2185  CreateBranch(BranchName, shwr_startdcosx, BranchName + NShowerIndexStr + "/F");
2186 
2187  BranchName = "shwr_startdcosy_" + ShowerLabel;
2188  CreateBranch(BranchName, shwr_startdcosy, BranchName + NShowerIndexStr + "/F");
2189 
2190  BranchName = "shwr_startdcosz_" + ShowerLabel;
2191  CreateBranch(BranchName, shwr_startdcosz, BranchName + NShowerIndexStr + "/F");
2192 
2193  BranchName = "shwr_startx_" + ShowerLabel;
2194  CreateBranch(BranchName, shwr_startx, BranchName + NShowerIndexStr + "/F");
2195 
2196  BranchName = "shwr_starty_" + ShowerLabel;
2197  CreateBranch(BranchName, shwr_starty, BranchName + NShowerIndexStr + "/F");
2198 
2199  BranchName = "shwr_startz_" + ShowerLabel;
2200  CreateBranch(BranchName, shwr_startz, BranchName + NShowerIndexStr + "/F");
2201 
2202  BranchName = "shwr_totEng_" + ShowerLabel;
2203  CreateBranch(BranchName, shwr_totEng, BranchName + NShowerIndexStr + "[3]/F");
2204 
2205  BranchName = "shwr_dedx_" + ShowerLabel;
2206  CreateBranch(BranchName, shwr_dedx, BranchName + NShowerIndexStr + "[3]/F");
2207 
2208  BranchName = "shwr_mipEng_" + ShowerLabel;
2209  CreateBranch(BranchName, shwr_mipEng, BranchName + NShowerIndexStr + "[3]/F");
2210 
2211  BranchName = "shwr_hasPFParticle_" + ShowerLabel;
2212  CreateBranch(BranchName, shwr_hasPFParticle, BranchName + NShowerIndexStr + "/S");
2213 
2214  BranchName = "shwr_PFParticleID_" + ShowerLabel;
2215  CreateBranch(BranchName, shwr_PFParticleID, BranchName + NShowerIndexStr + "/S");
2216 
2217  BranchName = "shwr_pidmvamu_" + ShowerLabel;
2218  CreateBranch(BranchName, shwr_pidmvamu, BranchName + NShowerIndexStr + "/F");
2219 
2220  BranchName = "shwr_pidmvae_" + ShowerLabel;
2221  CreateBranch(BranchName, shwr_pidmvae, BranchName + NShowerIndexStr + "/F");
2222 
2223  BranchName = "shwr_pidmvapich_" + ShowerLabel;
2224  CreateBranch(BranchName, shwr_pidmvapich, BranchName + NShowerIndexStr + "/F");
2225 
2226  BranchName = "shwr_pidmvaphoton_" + ShowerLabel;
2227  CreateBranch(BranchName, shwr_pidmvaphoton, BranchName + NShowerIndexStr + "/F");
2228 
2229  BranchName = "shwr_pidmvapr_" + ShowerLabel;
2230  CreateBranch(BranchName, shwr_pidmvapr, BranchName + NShowerIndexStr + "/F");
2231 
2232 } // dune::AnalysisTreeDataStruct::ShowerDataStruct::SetAddresses()
2233 
2234 //------------------------------------------------------------------------------
2235 //--- AnalysisTreeDataStruct
2236 //---
2237 
2239 
2240  // RunData.Clear();
2241  SubRunData.Clear();
2242 
2243  run = -99999;
2244  subrun = -99999;
2245  event = -99999;
2246  evttime = -99999;
2247  beamtime = -99999;
2248  isdata = -99;
2249  taulife = -99999;
2250  triggernumber = 0;
2251  triggertime = -99999;
2252  beamgatetime = -99999;
2253  triggerbits = 0;
2254  potbnb = 0;
2255  potnumitgt = 0;
2256  potnumi101 = 0;
2257 
2258  no_hits = 0;
2259  no_hits_stored = 0;
2260 
2261  std::fill(hit_tpc, hit_tpc + sizeof(hit_tpc)/sizeof(hit_tpc[0]), -9999);
2262  std::fill(hit_plane, hit_plane + sizeof(hit_plane)/sizeof(hit_plane[0]), -9999);
2263  std::fill(hit_wire, hit_wire + sizeof(hit_wire)/sizeof(hit_wire[0]), -9999);
2264  std::fill(hit_channel, hit_channel + sizeof(hit_channel)/sizeof(hit_channel[0]), -9999);
2265  std::fill(hit_peakT, hit_peakT + sizeof(hit_peakT)/sizeof(hit_peakT[0]), -99999.);
2266  std::fill(hit_charge, hit_charge + sizeof(hit_charge)/sizeof(hit_charge[0]), -99999.);
2267  std::fill(hit_ph, hit_ph + sizeof(hit_ph)/sizeof(hit_ph[0]), -99999.);
2268  std::fill(hit_startT, hit_startT + sizeof(hit_startT)/sizeof(hit_startT[0]), -99999.);
2269  std::fill(hit_endT, hit_endT + sizeof(hit_endT)/sizeof(hit_endT[0]), -99999.);
2270  std::fill(hit_rms, hit_rms + sizeof(hit_rms)/sizeof(hit_rms[0]), -99999.);
2271  std::fill(hit_trueX, hit_trueX + sizeof(hit_trueX)/sizeof(hit_trueX[0]), -99999.);
2272  std::fill(hit_goodnessOfFit, hit_goodnessOfFit + sizeof(hit_goodnessOfFit)/sizeof(hit_goodnessOfFit[0]), -99999.);
2273  std::fill(hit_multiplicity, hit_multiplicity + sizeof(hit_multiplicity)/sizeof(hit_multiplicity[0]), -99999.);
2274  std::fill(hit_trkid, hit_trkid + sizeof(hit_trkid)/sizeof(hit_trkid[0]), -9999);
2275  std::fill(hit_trkKey, hit_trkKey + sizeof(hit_trkKey)/sizeof(hit_trkKey[0]), -9999);
2276  std::fill(hit_clusterid, hit_clusterid + sizeof(hit_clusterid)/sizeof(hit_clusterid[0]), -99999);
2277  std::fill(hit_clusterKey, hit_clusterKey + sizeof(hit_clusterKey)/sizeof(hit_clusterKey[0]), -9999);
2278  std::fill(hit_spacepointid, hit_spacepointid + sizeof(hit_spacepointid)/sizeof(hit_spacepointid[0]), -99999);
2279  std::fill(hit_spacepointKey, hit_spacepointKey + sizeof(hit_spacepointKey)/sizeof(hit_spacepointKey[0]), -9999);
2280  std::fill(hit_nelec, hit_nelec + sizeof(hit_nelec)/sizeof(hit_nelec[0]), -99999.);
2281  std::fill(hit_energy, hit_energy + sizeof(hit_energy)/sizeof(hit_energy[0]), -99999.);
2282  //raw digit information
2283  std::fill(rawD_ph, rawD_ph + sizeof(rawD_ph)/sizeof(rawD_ph[0]), -99999.);
2284  std::fill(rawD_peakT, rawD_peakT + sizeof(rawD_peakT)/sizeof(rawD_peakT[0]), -99999.);
2285  std::fill(rawD_charge, rawD_charge + sizeof(rawD_charge)/sizeof(rawD_charge[0]), -99999.);
2286  std::fill(rawD_fwhh, rawD_fwhh + sizeof(rawD_fwhh)/sizeof(rawD_fwhh[0]), -99999.);
2287  std::fill(rawD_rms, rawD_rms + sizeof(rawD_rms)/sizeof(rawD_rms[0]), -99999.);
2288 
2289  no_flashes = 0;
2290  std::fill(flash_time, flash_time + sizeof(flash_time)/sizeof(flash_time[0]), -9999);
2291  std::fill(flash_pe, flash_pe + sizeof(flash_pe)/sizeof(flash_pe[0]), -9999);
2292  std::fill(flash_ycenter, flash_ycenter + sizeof(flash_ycenter)/sizeof(flash_ycenter[0]), -9999);
2293  std::fill(flash_zcenter, flash_zcenter + sizeof(flash_zcenter)/sizeof(flash_zcenter[0]), -9999);
2294  std::fill(flash_ywidth, flash_ywidth + sizeof(flash_ywidth)/sizeof(flash_ywidth[0]), -9999);
2295  std::fill(flash_zwidth, flash_zwidth + sizeof(flash_zwidth)/sizeof(flash_zwidth[0]), -9999);
2296  std::fill(flash_timewidth, flash_timewidth + sizeof(flash_timewidth)/sizeof(flash_timewidth[0]), -9999);
2297 
2298  no_ExternCounts = 0;
2299  std::fill(externcounts_time, externcounts_time + sizeof(externcounts_time)/sizeof(externcounts_time[0]), -9999);
2300  std::fill(externcounts_id, externcounts_id + sizeof(externcounts_id)/sizeof(externcounts_id[0]), -9999);
2301 
2302  nclusters = 0;
2303  std::fill(clusterId, clusterId + sizeof(clusterId)/sizeof(clusterId[0]), -9999);
2304  std::fill(clusterView, clusterView + sizeof(clusterView)/sizeof(clusterView[0]), -9999);
2305  std::fill(cluster_isValid, cluster_isValid + sizeof(cluster_isValid)/sizeof(cluster_isValid[0]), -1);
2306  std::fill(cluster_StartCharge, cluster_StartCharge + sizeof(cluster_StartCharge)/sizeof(cluster_StartCharge[0]), -99999.);
2307  std::fill(cluster_StartAngle, cluster_StartAngle + sizeof(cluster_StartAngle)/sizeof(cluster_StartAngle[0]), -99999.);
2308  std::fill(cluster_EndCharge, cluster_EndCharge + sizeof(cluster_EndCharge)/sizeof(cluster_EndCharge[0]), -99999.);
2309  std::fill(cluster_EndAngle , cluster_EndAngle + sizeof(cluster_EndAngle)/sizeof(cluster_EndAngle[0]), -99999.);
2310  std::fill(cluster_Integral , cluster_Integral + sizeof(cluster_Integral)/sizeof(cluster_Integral[0]), -99999.);
2311  std::fill(cluster_IntegralAverage, cluster_IntegralAverage + sizeof(cluster_IntegralAverage)/sizeof(cluster_IntegralAverage[0]), -99999.);
2312  std::fill(cluster_SummedADC, cluster_SummedADC + sizeof(cluster_SummedADC)/sizeof(cluster_SummedADC[0]), -99999.);
2313  std::fill(cluster_SummedADCaverage, cluster_SummedADCaverage + sizeof(cluster_SummedADCaverage)/sizeof(cluster_SummedADCaverage[0]), -99999.);
2314  std::fill(cluster_MultipleHitDensity, cluster_MultipleHitDensity + sizeof(cluster_MultipleHitDensity)/sizeof(cluster_MultipleHitDensity[0]), -99999.);
2315  std::fill(cluster_Width, cluster_Width + sizeof(cluster_Width)/sizeof(cluster_Width[0]), -99999.);
2316  std::fill(cluster_NHits, cluster_NHits + sizeof(cluster_NHits)/sizeof(cluster_NHits[0]), -9999);
2317  std::fill(cluster_StartWire, cluster_StartWire + sizeof(cluster_StartWire)/sizeof(cluster_StartWire[0]), -9999);
2318  std::fill(cluster_StartTick, cluster_StartTick + sizeof(cluster_StartTick)/sizeof(cluster_StartTick[0]), -9999);
2319  std::fill(cluster_EndWire, cluster_EndWire + sizeof(cluster_EndWire)/sizeof(cluster_EndWire[0]), -9999);
2320  std::fill(cluster_EndTick, cluster_EndTick + sizeof(cluster_EndTick)/sizeof(cluster_EndTick[0]), -9999);
2321  std::fill(cluncosmictags_tagger, cluncosmictags_tagger + sizeof(cluncosmictags_tagger)/sizeof(cluncosmictags_tagger[0]), -9999);
2322  std::fill(clucosmicscore_tagger, clucosmicscore_tagger + sizeof(clucosmicscore_tagger)/sizeof(clucosmicscore_tagger[0]), -99999.);
2323  std::fill(clucosmictype_tagger , clucosmictype_tagger + sizeof(clucosmictype_tagger )/sizeof(clucosmictype_tagger [0]), -9999);
2324 
2325  // SpacePointSolver information
2326  nspacepoints = 0;
2327  FillWith(SpacePointX, -99999.);
2328  FillWith(SpacePointY, -99999.);
2329  FillWith(SpacePointZ, -99999.);
2330  FillWith(SpacePointQ, -99999.);
2331  FillWith(SpacePointErrX, -99999.);
2332  FillWith(SpacePointErrY, -99999.);
2333  FillWith(SpacePointErrZ, -99999.);
2334  FillWith(SpacePointID, -99999);
2335  FillWith(SpacePointChisq, -99999.);
2336 
2337  // CNN information
2338  FillWith(SpacePointEmScore, -99999.);
2339 
2340  nnuvtx = 0;
2341  std::fill(nuvtxx, nuvtxx + sizeof(nuvtxx)/sizeof(nuvtxx[0]), -99999.);
2342  std::fill(nuvtxy, nuvtxy + sizeof(nuvtxy)/sizeof(nuvtxy[0]), -99999.);
2343  std::fill(nuvtxz, nuvtxz + sizeof(nuvtxz)/sizeof(nuvtxz[0]), -99999.);
2344  std::fill(nuvtxpdg, nuvtxpdg + sizeof(nuvtxpdg)/sizeof(nuvtxpdg[0]), -99999);
2345 
2346  mcevts_truth = -99999;
2347  mcevts_truthcry = -99999;
2348  std::fill(nuPDG_truth, nuPDG_truth + sizeof(nuPDG_truth)/sizeof(nuPDG_truth[0]), -99999.);
2349  std::fill(ccnc_truth, ccnc_truth + sizeof(ccnc_truth)/sizeof(ccnc_truth[0]), -99999.);
2350  std::fill(mode_truth, mode_truth + sizeof(mode_truth)/sizeof(mode_truth[0]), -99999.);
2351  std::fill(enu_truth, enu_truth + sizeof(enu_truth)/sizeof(enu_truth[0]), -99999.);
2352  std::fill(Q2_truth, Q2_truth + sizeof(Q2_truth)/sizeof(Q2_truth[0]), -99999.);
2353  std::fill(W_truth, W_truth + sizeof(W_truth)/sizeof(W_truth[0]), -99999.);
2354  std::fill(X_truth, X_truth + sizeof(X_truth)/sizeof(X_truth[0]), -99999.);
2355  std::fill(Y_truth, Y_truth + sizeof(Y_truth)/sizeof(Y_truth[0]), -99999.);
2356  std::fill(hitnuc_truth, hitnuc_truth + sizeof(hitnuc_truth)/sizeof(hitnuc_truth[0]), -99999.);
2357  std::fill(nuvtxx_truth, nuvtxx_truth + sizeof(nuvtxx_truth)/sizeof(nuvtxx_truth[0]), -99999.);
2358  std::fill(nuvtxy_truth, nuvtxy_truth + sizeof(nuvtxy_truth)/sizeof(nuvtxy_truth[0]), -99999.);
2359  std::fill(nuvtxz_truth, nuvtxz_truth + sizeof(nuvtxz_truth)/sizeof(nuvtxz_truth[0]), -99999.);
2360  std::fill(nu_dcosx_truth, nu_dcosx_truth + sizeof(nu_dcosx_truth)/sizeof(nu_dcosx_truth[0]), -99999.);
2361  std::fill(nu_dcosy_truth, nu_dcosy_truth + sizeof(nu_dcosy_truth)/sizeof(nu_dcosy_truth[0]), -99999.);
2362  std::fill(nu_dcosz_truth, nu_dcosz_truth + sizeof(nu_dcosz_truth)/sizeof(nu_dcosz_truth[0]), -99999.);
2363  std::fill(lep_mom_truth, lep_mom_truth + sizeof(lep_mom_truth)/sizeof(lep_mom_truth[0]), -99999.);
2364  std::fill(lep_dcosx_truth, lep_dcosx_truth + sizeof(lep_dcosx_truth)/sizeof(lep_dcosx_truth[0]), -99999.);
2365  std::fill(lep_dcosy_truth, lep_dcosy_truth + sizeof(lep_dcosy_truth)/sizeof(lep_dcosy_truth[0]), -99999.);
2366  std::fill(lep_dcosz_truth, lep_dcosz_truth + sizeof(lep_dcosz_truth)/sizeof(lep_dcosz_truth[0]), -99999.);
2367 
2368  //Flux information
2369  std::fill(vx_flux, vx_flux + sizeof(vx_flux)/sizeof(vx_flux[0]), -99999.);
2370  std::fill(vy_flux, vy_flux + sizeof(vy_flux)/sizeof(vy_flux[0]), -99999.);
2371  std::fill(vz_flux, vz_flux + sizeof(vz_flux)/sizeof(vz_flux[0]), -99999.);
2372  std::fill(pdpx_flux, pdpx_flux + sizeof(pdpx_flux)/sizeof(pdpx_flux[0]), -99999.);
2373  std::fill(pdpy_flux, pdpy_flux + sizeof(pdpy_flux)/sizeof(pdpy_flux[0]), -99999.);
2374  std::fill(pdpz_flux, pdpz_flux + sizeof(pdpz_flux)/sizeof(pdpz_flux[0]), -99999.);
2375  std::fill(ppdxdz_flux, ppdxdz_flux + sizeof(ppdxdz_flux)/sizeof(ppdxdz_flux[0]), -99999.);
2376  std::fill(ppdydz_flux, ppdydz_flux + sizeof(ppdydz_flux)/sizeof(ppdydz_flux[0]), -99999.);
2377  std::fill(pppz_flux, pppz_flux + sizeof(pppz_flux)/sizeof(pppz_flux[0]), -99999.);
2378  std::fill(ptype_flux, ptype_flux + sizeof(ptype_flux)/sizeof(ptype_flux[0]), -9999);
2379  std::fill(ppvx_flux, ppvx_flux + sizeof(ppvx_flux)/sizeof(ppvx_flux[0]), -99999.);
2380  std::fill(ppvy_flux, ppvy_flux + sizeof(ppvy_flux)/sizeof(ppvy_flux[0]), -99999.);
2381  std::fill(ppvz_flux, ppvz_flux + sizeof(ppvz_flux)/sizeof(ppvz_flux[0]), -99999.);
2382  std::fill(muparpx_flux, muparpx_flux + sizeof(muparpx_flux)/sizeof(muparpx_flux[0]), -99999.);
2383  std::fill(muparpy_flux, muparpy_flux + sizeof(muparpy_flux)/sizeof(muparpy_flux[0]), -99999.);
2384  std::fill(muparpz_flux, muparpz_flux + sizeof(muparpz_flux)/sizeof(muparpz_flux[0]), -99999.);
2385  std::fill(mupare_flux, mupare_flux + sizeof(mupare_flux)/sizeof(mupare_flux[0]), -99999.);
2386  std::fill(tgen_flux, tgen_flux + sizeof(tgen_flux)/sizeof(tgen_flux[0]), -9999);
2387  std::fill(tgptype_flux, tgptype_flux + sizeof(tgptype_flux)/sizeof(tgptype_flux[0]), -9999);
2388  std::fill(tgppx_flux, tgppx_flux + sizeof(tgppx_flux)/sizeof(tgppx_flux[0]), -99999.);
2389  std::fill(tgppy_flux, tgppy_flux + sizeof(tgppy_flux)/sizeof(tgppy_flux[0]), -99999.);
2390  std::fill(tgppz_flux, tgppz_flux + sizeof(tgppz_flux)/sizeof(tgppz_flux[0]), -99999.);
2391  std::fill(tprivx_flux, tprivx_flux + sizeof(tprivx_flux)/sizeof(tprivx_flux[0]), -99999.);
2392  std::fill(tprivy_flux, tprivy_flux + sizeof(tprivy_flux)/sizeof(tprivy_flux[0]), -99999.);
2393  std::fill(tprivz_flux, tprivz_flux + sizeof(tprivz_flux)/sizeof(tprivz_flux[0]), -99999.);
2394  std::fill(dk2gen_flux, dk2gen_flux + sizeof(dk2gen_flux)/sizeof(dk2gen_flux[0]), -99999.);
2395  std::fill(gen2vtx_flux, gen2vtx_flux + sizeof(gen2vtx_flux)/sizeof(gen2vtx_flux[0]), -99999.);
2396  std::fill(tpx_flux, tpx_flux + sizeof(tpx_flux)/sizeof(tpx_flux[0]), -99999.);
2397  std::fill(tpy_flux, tpy_flux + sizeof(tpy_flux)/sizeof(tpy_flux[0]), -99999.);
2398  std::fill(tpz_flux, tpz_flux + sizeof(tpz_flux)/sizeof(tpz_flux[0]), -99999.);
2399  std::fill(tptype_flux, tptype_flux + sizeof(tptype_flux)/sizeof(tptype_flux[0]), -99999.);
2400 
2401  genie_no_primaries = 0;
2402  cry_no_primaries = 0;
2403  proto_no_primaries = 0;
2404  no_primaries = 0;
2405  geant_list_size=0;
2406  geant_list_size_in_tpcAV = 0;
2407  no_mcshowers = 0;
2408  no_mctracks = 0;
2409 
2410  FillWith(pdg, -99999);
2411  FillWith(status, -99999);
2412  FillWith(Mass, -99999.);
2413  FillWith(Eng, -99999.);
2414  FillWith(EndE, -99999.);
2415  FillWith(Px, -99999.);
2416  FillWith(Py, -99999.);
2417  FillWith(Pz, -99999.);
2418  FillWith(P, -99999.);
2419  FillWith(StartPointx, -99999.);
2420  FillWith(StartPointy, -99999.);
2421  FillWith(StartPointz, -99999.);
2422  FillWith(StartT, -99e7);
2423  FillWith(EndT, -99999.);
2424  FillWith(EndPointx, -99999.);
2425  FillWith(EndPointy, -99999.);
2426  FillWith(EndPointz, -99999.);
2427  FillWith(EndT, -99e7);
2428  FillWith(theta, -99999.);
2429  FillWith(phi, -99999.);
2430  FillWith(theta_xz, -99999.);
2431  FillWith(theta_yz, -99999.);
2432  FillWith(pathlen, -99999.);
2433  FillWith(inTPCActive, -99999);
2434  FillWith(StartPointx_tpcAV, -99999.);
2435  FillWith(StartPointy_tpcAV, -99999.);
2436  FillWith(StartPointz_tpcAV, -99999.);
2437  FillWith(StartT_tpcAV, -99e7);
2438  FillWith(StartE_tpcAV, -99999.);
2439  FillWith(StartP_tpcAV, -99999.);
2440  FillWith(StartPx_tpcAV, -99999.);
2441  FillWith(StartPy_tpcAV, -99999.);
2442  FillWith(StartPz_tpcAV, -99999.);
2443  FillWith(EndPointx_tpcAV, -99999.);
2444  FillWith(EndPointy_tpcAV, -99999.);
2445  FillWith(EndPointz_tpcAV, -99999.);
2446  FillWith(EndT_tpcAV, -99e7);
2447  FillWith(EndE_tpcAV, -99999.);
2448  FillWith(EndP_tpcAV, -99999.);
2449  FillWith(EndPx_tpcAV, -99999.);
2450  FillWith(EndPy_tpcAV, -99999.);
2451  FillWith(EndPz_tpcAV, -99999.);
2452  FillWith(pathlen_drifted, -99999.);
2453  FillWith(inTPCDrifted, -99999);
2454  FillWith(StartPointx_drifted, -99999.);
2455  FillWith(StartPointy_drifted, -99999.);
2456  FillWith(StartPointz_drifted, -99999.);
2457  FillWith(StartT_drifted, -99e7);
2458  FillWith(StartE_drifted, -99999.);
2459  FillWith(StartP_drifted, -99999.);
2460  FillWith(StartPx_drifted, -99999.);
2461  FillWith(StartPy_drifted, -99999.);
2462  FillWith(StartPz_drifted, -99999.);
2463  FillWith(EndPointx_drifted, -99999.);
2464  FillWith(EndPointy_drifted, -99999.);
2465  FillWith(EndPointz_drifted, -99999.);
2466  FillWith(EndT_drifted, -99e7);
2467  FillWith(EndE_drifted, -99999.);
2468  FillWith(EndP_drifted, -99999.);
2469  FillWith(EndPx_drifted, -99999.);
2470  FillWith(EndPy_drifted, -99999.);
2471  FillWith(EndPz_drifted, -99999.);
2472  FillWith(NumberDaughters, -99999);
2473  FillWith(Mother, -99999);
2474  FillWith(TrackId, -99999);
2475  FillWith(process_primary, -99999);
2476  FillWith(processname, "noname");
2477  FillWith(MergedId, -99999);
2478  FillWith(origin, -99999);
2479  FillWith(MCTruthIndex, -99999);
2480  FillWith(genie_primaries_pdg, -99999);
2481  FillWith(genie_Eng, -99999.);
2482  FillWith(genie_Px, -99999.);
2483  FillWith(genie_Py, -99999.);
2484  FillWith(genie_Pz, -99999.);
2485  FillWith(genie_P, -99999.);
2486  FillWith(genie_status_code, -99999);
2487  FillWith(genie_mass, -99999.);
2488  FillWith(genie_trackID, -99999);
2489  FillWith(genie_ND, -99999);
2490  FillWith(genie_mother, -99999);
2491  FillWith(cry_primaries_pdg, -99999);
2492  FillWith(cry_Eng, -99999.);
2493  FillWith(cry_Px, -99999.);
2494  FillWith(cry_Py, -99999.);
2495  FillWith(cry_Pz, -99999.);
2496  FillWith(cry_P, -99999.);
2497  FillWith(cry_StartPointx, -99999.);
2498  FillWith(cry_StartPointy, -99999.);
2499  FillWith(cry_StartPointz, -99999.);
2500  FillWith(cry_StartPointt, -99999.);
2501  FillWith(cry_status_code, -99999);
2502  FillWith(cry_mass, -99999.);
2503  FillWith(cry_trackID, -99999);
2504  FillWith(cry_ND, -99999);
2505  FillWith(cry_mother, -99999);
2506  // Start of ProtoDUNE Beam generator section
2507  FillWith(proto_isGoodParticle,-99999);
2508  FillWith(proto_vx,-99999.);
2509  FillWith(proto_vy,-99999.);
2510  FillWith(proto_vz,-99999.);
2511  FillWith(proto_t,-99999.);
2512  FillWith(proto_px,-99999.);
2513  FillWith(proto_py,-99999.);
2514  FillWith(proto_pz,-99999.);
2515  FillWith(proto_momentum,-99999.);
2516  FillWith(proto_energy,-99999.);
2517  FillWith(proto_pdg,-99999);
2518  FillWith(proto_geantTrackID,-99999);
2519  FillWith(proto_geantIndex,-99999);
2520  // End of ProtoDUNE Beam generator section
2521  FillWith(mcshwr_origin, -1);
2522  FillWith(mcshwr_pdg, -99999);
2523  FillWith(mcshwr_TrackId, -99999);
2524  FillWith(mcshwr_Process, "noname");
2525  FillWith(mcshwr_startX, -99999.);
2526  FillWith(mcshwr_startY, -99999.);
2527  FillWith(mcshwr_startZ, -99999.);
2528  FillWith(mcshwr_endX, -99999.);
2529  FillWith(mcshwr_endY, -99999.);
2530  FillWith(mcshwr_endZ, -99999.);
2531  FillWith(mcshwr_CombEngX, -99999.);
2532  FillWith(mcshwr_CombEngY, -99999.);
2533  FillWith(mcshwr_CombEngZ, -99999.);
2534  FillWith(mcshwr_CombEngPx, -99999.);
2535  FillWith(mcshwr_CombEngPy, -99999.);
2536  FillWith(mcshwr_CombEngPz, -99999.);
2537  FillWith(mcshwr_CombEngE, -99999.);
2538  FillWith(mcshwr_dEdx, -99999.);
2539  FillWith(mcshwr_StartDirX, -99999.);
2540  FillWith(mcshwr_StartDirY, -99999.);
2541  FillWith(mcshwr_StartDirZ, -99999.);
2542  FillWith(mcshwr_isEngDeposited, -9999);
2543  FillWith(mcshwr_Motherpdg, -99999);
2544  FillWith(mcshwr_MotherTrkId, -99999);
2545  FillWith(mcshwr_MotherProcess, "noname");
2546  FillWith(mcshwr_MotherstartX, -99999.);
2547  FillWith(mcshwr_MotherstartY, -99999.);
2548  FillWith(mcshwr_MotherstartZ, -99999.);
2549  FillWith(mcshwr_MotherendX, -99999.);
2550  FillWith(mcshwr_MotherendY, -99999.);
2551  FillWith(mcshwr_MotherendZ, -99999.);
2552  FillWith(mcshwr_Ancestorpdg, -99999);
2553  FillWith(mcshwr_AncestorTrkId, -99999);
2554  FillWith(mcshwr_AncestorProcess, "noname");
2555  FillWith(mcshwr_AncestorstartX, -99999.);
2556  FillWith(mcshwr_AncestorstartY, -99999.);
2557  FillWith(mcshwr_AncestorstartZ, -99999.);
2558  FillWith(mcshwr_AncestorendX, -99999.);
2559  FillWith(mcshwr_AncestorendY, -99999.);
2560  FillWith(mcshwr_AncestorendZ, -99999.);
2561 
2562  // auxiliary detector information;
2563  FillWith(NAuxDets, 0);
2564  // - set to -9999 all the values of each of the arrays in AuxDetID;
2565  // this auto is BoxedArray<Short_t>
2566  for (auto& partInfo: AuxDetID) FillWith(partInfo, -9999);
2567  // - pythonish C++: as the previous line, for each one in a list of containers
2568  // of the same type (C++ is not python yet), using pointers to avoid copy;
2569  for (AuxDetMCData_t<Float_t>* cont: {
2570  &entryX, &entryY, &entryZ, &entryT,
2571  &exitX , &exitY , &exitZ, &exitT, &exitPx, &exitPy, &exitPz,
2572  &CombinedEnergyDep
2573  })
2574  {
2575  // this auto is BoxedArray<Float_t>
2576  for (auto& partInfo: *cont) FillWith(partInfo, -99999.);
2577  } // for container
2578 
2579 } // dune::AnalysisTreeDataStruct::ClearLocalData()
2580 
2581 
2583  ClearLocalData();
2584  std::for_each
2585  (TrackData.begin(), TrackData.end(), std::mem_fn(&TrackDataStruct::Clear));
2586  std::for_each
2587  (VertexData.begin(), VertexData.end(), std::mem_fn(&VertexDataStruct::Clear));
2588  std::for_each
2589  (ShowerData.begin(), ShowerData.end(), std::mem_fn(&ShowerDataStruct::Clear));
2590 } // dune::AnalysisTreeDataStruct::Clear()
2591 
2592 
2594 (std::vector<std::string> const& ShowerAlgos)
2595 {
2596 
2597  size_t const nShowerAlgos = ShowerAlgos.size();
2598  ShowerData.resize(nShowerAlgos);
2599  for (size_t iAlgo = 0; iAlgo < nShowerAlgos; ++iAlgo)
2600  ShowerData[iAlgo].SetName(ShowerAlgos[iAlgo]);
2601 
2602 } // dune::AnalysisTreeDataStruct::SetShowerAlgos()
2603 
2604 
2606 
2607  // minimum size is 1, so that we always have an address
2608  MaxGEANTparticles = (size_t) std::max(nParticles, 1);
2609 
2610  pdg.resize(MaxGEANTparticles);
2611  status.resize(MaxGEANTparticles);
2612  Mass.resize(MaxGEANTparticles);
2613  Eng.resize(MaxGEANTparticles);
2614  EndE.resize(MaxGEANTparticles);
2615  Px.resize(MaxGEANTparticles);
2616  Py.resize(MaxGEANTparticles);
2617  Pz.resize(MaxGEANTparticles);
2618  P.resize(MaxGEANTparticles);
2619  StartPointx.resize(MaxGEANTparticles);
2620  StartPointy.resize(MaxGEANTparticles);
2621  StartPointz.resize(MaxGEANTparticles);
2622  StartT.resize(MaxGEANTparticles);
2623  EndT.resize(MaxGEANTparticles);
2624  EndPointx.resize(MaxGEANTparticles);
2625  EndPointy.resize(MaxGEANTparticles);
2626  EndPointz.resize(MaxGEANTparticles);
2627  EndT.resize(MaxGEANTparticles);
2628  theta.resize(MaxGEANTparticles);
2629  phi.resize(MaxGEANTparticles);
2630  theta_xz.resize(MaxGEANTparticles);
2631  theta_yz.resize(MaxGEANTparticles);
2632  pathlen.resize(MaxGEANTparticles);
2633  inTPCActive.resize(MaxGEANTparticles);
2634  StartPointx_tpcAV.resize(MaxGEANTparticles);
2635  StartPointy_tpcAV.resize(MaxGEANTparticles);
2636  StartPointz_tpcAV.resize(MaxGEANTparticles);
2637  StartT_tpcAV.resize(MaxGEANTparticles);
2638  StartE_tpcAV.resize(MaxGEANTparticles);
2639  StartP_tpcAV.resize(MaxGEANTparticles);
2640  StartPx_tpcAV.resize(MaxGEANTparticles);
2641  StartPy_tpcAV.resize(MaxGEANTparticles);
2642  StartPz_tpcAV.resize(MaxGEANTparticles);
2643  EndPointx_tpcAV.resize(MaxGEANTparticles);
2644  EndPointy_tpcAV.resize(MaxGEANTparticles);
2645  EndPointz_tpcAV.resize(MaxGEANTparticles);
2646  EndT_tpcAV.resize(MaxGEANTparticles);
2647  EndE_tpcAV.resize(MaxGEANTparticles);
2648  EndP_tpcAV.resize(MaxGEANTparticles);
2649  EndPx_tpcAV.resize(MaxGEANTparticles);
2650  EndPy_tpcAV.resize(MaxGEANTparticles);
2651  EndPz_tpcAV.resize(MaxGEANTparticles);
2652  pathlen_drifted.resize(MaxGEANTparticles);
2653  inTPCDrifted.resize(MaxGEANTparticles);
2654  StartPointx_drifted.resize(MaxGEANTparticles);
2655  StartPointy_drifted.resize(MaxGEANTparticles);
2656  StartPointz_drifted.resize(MaxGEANTparticles);
2657  StartT_drifted.resize(MaxGEANTparticles);
2658  StartE_drifted.resize(MaxGEANTparticles);
2659  StartP_drifted.resize(MaxGEANTparticles);
2660  StartPx_drifted.resize(MaxGEANTparticles);
2661  StartPy_drifted.resize(MaxGEANTparticles);
2662  StartPz_drifted.resize(MaxGEANTparticles);
2663  EndPointx_drifted.resize(MaxGEANTparticles);
2664  EndPointy_drifted.resize(MaxGEANTparticles);
2665  EndPointz_drifted.resize(MaxGEANTparticles);
2666  EndT_drifted.resize(MaxGEANTparticles);
2667  EndE_drifted.resize(MaxGEANTparticles);
2668  EndP_drifted.resize(MaxGEANTparticles);
2669  EndPx_drifted.resize(MaxGEANTparticles);
2670  EndPy_drifted.resize(MaxGEANTparticles);
2671  EndPz_drifted.resize(MaxGEANTparticles);
2672  NumberDaughters.resize(MaxGEANTparticles);
2673  Mother.resize(MaxGEANTparticles);
2674  TrackId.resize(MaxGEANTparticles);
2675  process_primary.resize(MaxGEANTparticles);
2676  processname.resize(MaxGEANTparticles);
2677  MergedId.resize(MaxGEANTparticles);
2678  origin.resize(MaxGEANTparticles);
2679  MCTruthIndex.resize(MaxGEANTparticles);
2680 
2681  // auxiliary detector structure
2682  NAuxDets.resize(MaxGEANTparticles);
2683  AuxDetID.resize(MaxGEANTparticles);
2684  entryX.resize(MaxGEANTparticles);
2685  entryY.resize(MaxGEANTparticles);
2686  entryZ.resize(MaxGEANTparticles);
2687  entryT.resize(MaxGEANTparticles);
2688  exitX.resize(MaxGEANTparticles);
2689  exitY.resize(MaxGEANTparticles);
2690  exitZ.resize(MaxGEANTparticles);
2691  exitT.resize(MaxGEANTparticles);
2692  exitPx.resize(MaxGEANTparticles);
2693  exitPy.resize(MaxGEANTparticles);
2694  exitPz.resize(MaxGEANTparticles);
2695  CombinedEnergyDep.resize(MaxGEANTparticles);
2696 
2697 } // dune::AnalysisTreeDataStruct::ResizeGEANT()
2698 
2700 
2701  // minimum size is 1, so that we always have an address
2702  MaxGeniePrimaries = (size_t) std::max(nPrimaries, 1);
2703  genie_primaries_pdg.resize(MaxGeniePrimaries);
2704  genie_Eng.resize(MaxGeniePrimaries);
2705  genie_Px.resize(MaxGeniePrimaries);
2706  genie_Py.resize(MaxGeniePrimaries);
2707  genie_Pz.resize(MaxGeniePrimaries);
2708  genie_P.resize(MaxGeniePrimaries);
2709  genie_status_code.resize(MaxGeniePrimaries);
2710  genie_mass.resize(MaxGeniePrimaries);
2711  genie_trackID.resize(MaxGeniePrimaries);
2712  genie_ND.resize(MaxGeniePrimaries);
2713  genie_mother.resize(MaxGeniePrimaries);
2714 } // dune::AnalysisTreeDataStruct::ResizeGenie()
2715 
2717 
2718  cry_primaries_pdg.resize(nPrimaries);
2719  cry_Eng.resize(nPrimaries);
2720  cry_Px.resize(nPrimaries);
2721  cry_Py.resize(nPrimaries);
2722  cry_Pz.resize(nPrimaries);
2723  cry_P.resize(nPrimaries);
2724  cry_StartPointx.resize(nPrimaries);
2725  cry_StartPointy.resize(nPrimaries);
2726  cry_StartPointz.resize(nPrimaries);
2727  cry_StartPointt.resize(nPrimaries);
2728  cry_status_code.resize(nPrimaries);
2729  cry_mass.resize(nPrimaries);
2730  cry_trackID.resize(nPrimaries);
2731  cry_ND.resize(nPrimaries);
2732  cry_mother.resize(nPrimaries);
2733 
2734 } // dune::AnalysisTreeDataStruct::ResizeCry()
2735 
2737 
2738  proto_isGoodParticle.resize(nPrimaries);
2739  proto_vx.resize(nPrimaries);
2740  proto_vy.resize(nPrimaries);
2741  proto_vz.resize(nPrimaries);
2742  proto_t.resize(nPrimaries);
2743  proto_px.resize(nPrimaries);
2744  proto_py.resize(nPrimaries);
2745  proto_pz.resize(nPrimaries);
2746  proto_momentum.resize(nPrimaries);
2747  proto_energy.resize(nPrimaries);
2748  proto_pdg.resize(nPrimaries);
2749  proto_geantTrackID.resize(nPrimaries);
2750  proto_geantIndex.resize(nPrimaries);
2751 
2752 } // dune::AnalysisTreeDataStruct::ResizeProto()
2753 
2755  mcshwr_origin.resize(nMCShowers);
2756  mcshwr_pdg.resize(nMCShowers);
2757  mcshwr_TrackId.resize(nMCShowers);
2758  mcshwr_Process.resize(nMCShowers);
2759  mcshwr_startX.resize(nMCShowers);
2760  mcshwr_startY.resize(nMCShowers);
2761  mcshwr_startZ.resize(nMCShowers);
2762  mcshwr_endX.resize(nMCShowers);
2763  mcshwr_endY.resize(nMCShowers);
2764  mcshwr_endZ.resize(nMCShowers);
2765  mcshwr_CombEngX.resize(nMCShowers);
2766  mcshwr_CombEngY.resize(nMCShowers);
2767  mcshwr_CombEngZ.resize(nMCShowers);
2768  mcshwr_CombEngPx.resize(nMCShowers);
2769  mcshwr_CombEngPy.resize(nMCShowers);
2770  mcshwr_CombEngPz.resize(nMCShowers);
2771  mcshwr_CombEngE.resize(nMCShowers);
2772  mcshwr_dEdx.resize(nMCShowers);
2773  mcshwr_StartDirX.resize(nMCShowers);
2774  mcshwr_StartDirY.resize(nMCShowers);
2775  mcshwr_StartDirZ.resize(nMCShowers);
2776  mcshwr_isEngDeposited.resize(nMCShowers);
2777  mcshwr_Motherpdg.resize(nMCShowers);
2778  mcshwr_MotherTrkId.resize(nMCShowers);
2779  mcshwr_MotherProcess.resize(nMCShowers);
2780  mcshwr_MotherstartX.resize(nMCShowers);
2781  mcshwr_MotherstartY.resize(nMCShowers);
2782  mcshwr_MotherstartZ.resize(nMCShowers);
2783  mcshwr_MotherendX.resize(nMCShowers);
2784  mcshwr_MotherendY.resize(nMCShowers);
2785  mcshwr_MotherendZ.resize(nMCShowers);
2786  mcshwr_Ancestorpdg.resize(nMCShowers);
2787  mcshwr_AncestorTrkId.resize(nMCShowers);
2788  mcshwr_AncestorProcess.resize(nMCShowers);
2789  mcshwr_AncestorstartX.resize(nMCShowers);
2790  mcshwr_AncestorstartY.resize(nMCShowers);
2791  mcshwr_AncestorstartZ.resize(nMCShowers);
2792  mcshwr_AncestorendX.resize(nMCShowers);
2793  mcshwr_AncestorendY.resize(nMCShowers);
2794  mcshwr_AncestorendZ.resize(nMCShowers);
2795 
2796 } // dune::AnalysisTreeDataStruct::ResizeMCShower()
2797 
2799  mctrk_origin.resize(nMCTracks);
2800  mctrk_pdg.resize(nMCTracks);
2801  mctrk_TrackId.resize(nMCTracks);
2802  mctrk_Process.resize(nMCTracks);
2803  mctrk_startX.resize(nMCTracks);
2804  mctrk_startY.resize(nMCTracks);
2805  mctrk_startZ.resize(nMCTracks);
2806  mctrk_endX.resize(nMCTracks);
2807  mctrk_endY.resize(nMCTracks);
2808  mctrk_endZ.resize(nMCTracks);
2809  mctrk_startX_drifted.resize(nMCTracks);
2810  mctrk_startY_drifted.resize(nMCTracks);
2811  mctrk_startZ_drifted.resize(nMCTracks);
2812  mctrk_endX_drifted.resize(nMCTracks);
2813  mctrk_endY_drifted.resize(nMCTracks);
2814  mctrk_endZ_drifted.resize(nMCTracks);
2815  mctrk_len_drifted.resize(nMCTracks);
2816  mctrk_p_drifted.resize(nMCTracks);
2817  mctrk_px_drifted.resize(nMCTracks);
2818  mctrk_py_drifted.resize(nMCTracks);
2819  mctrk_pz_drifted.resize(nMCTracks);
2820  mctrk_Motherpdg.resize(nMCTracks);
2821  mctrk_MotherTrkId.resize(nMCTracks);
2822  mctrk_MotherProcess.resize(nMCTracks);
2823  mctrk_MotherstartX.resize(nMCTracks);
2824  mctrk_MotherstartY.resize(nMCTracks);
2825  mctrk_MotherstartZ.resize(nMCTracks);
2826  mctrk_MotherendX.resize(nMCTracks);
2827  mctrk_MotherendY.resize(nMCTracks);
2828  mctrk_MotherendZ.resize(nMCTracks);
2829  mctrk_Ancestorpdg.resize(nMCTracks);
2830  mctrk_AncestorTrkId.resize(nMCTracks);
2831  mctrk_AncestorProcess.resize(nMCTracks);
2832  mctrk_AncestorstartX.resize(nMCTracks);
2833  mctrk_AncestorstartY.resize(nMCTracks);
2834  mctrk_AncestorstartZ.resize(nMCTracks);
2835  mctrk_AncestorendX.resize(nMCTracks);
2836  mctrk_AncestorendY.resize(nMCTracks);
2837  mctrk_AncestorendZ.resize(nMCTracks);
2838 
2839 } // dune::AnalysisTreeDataStruct::ResizeMCTrack()
2840 
2842  SpacePointX.resize(nSpacePoints);
2843  SpacePointY.resize(nSpacePoints);
2844  SpacePointZ.resize(nSpacePoints);
2845  SpacePointQ.resize(nSpacePoints);
2846  SpacePointErrX.resize(nSpacePoints);
2847  SpacePointErrY.resize(nSpacePoints);
2848  SpacePointErrZ.resize(nSpacePoints);
2849  SpacePointID.resize(nSpacePoints);
2850  SpacePointChisq.resize(nSpacePoints);
2851 
2852  SpacePointEmScore.resize(nSpacePoints);
2853 } // dune::AnalysisTreeDataStruct::ResizeSpacePointSolver()
2854 
2855 
2856 
2858  TTree* pTree,
2859  const std::vector<std::string>& trackers,
2860  const std::vector<std::string>& vertexalgos,
2861  const std::vector<std::string>& showeralgos,
2862  bool isCosmics
2863  ) {
2864  BranchCreator CreateBranch(pTree);
2865 
2866  CreateBranch("run",&run,"run/I");
2867  CreateBranch("subrun",&subrun,"subrun/I");
2868  CreateBranch("event",&event,"event/I");
2869  CreateBranch("evttime",&evttime,"evttime/D");
2870  CreateBranch("beamtime",&beamtime,"beamtime/D");
2871  CreateBranch("pot",&SubRunData.pot,"pot/D");
2872  CreateBranch("isdata",&isdata,"isdata/B");
2873  CreateBranch("taulife",&taulife,"taulife/D");
2874  CreateBranch("triggernumber",&triggernumber,"triggernumber/i");
2875  CreateBranch("triggertime",&triggertime,"triggertime/D");
2876  CreateBranch("beamgatetime",&beamgatetime,"beamgatetime/D");
2877  CreateBranch("triggerbits",&triggerbits,"triggerbits/i");
2878  CreateBranch("potbnb",&potbnb,"potbnb/D");
2879  CreateBranch("potnumitgt",&potnumitgt,"potnumitgt/D");
2880  CreateBranch("potnumi101",&potnumi101,"potnumi101/D");
2881 
2882  if (hasHitInfo()){
2883  CreateBranch("no_hits",&no_hits,"no_hits/I");
2884  CreateBranch("no_hits_stored",&no_hits_stored,"no_hits_stored/I");
2885  CreateBranch("hit_tpc",hit_tpc,"hit_tpc[no_hits_stored]/S");
2886  CreateBranch("hit_plane",hit_plane,"hit_plane[no_hits_stored]/S");
2887  CreateBranch("hit_wire",hit_wire,"hit_wire[no_hits_stored]/S");
2888  CreateBranch("hit_channel",hit_channel,"hit_channel[no_hits_stored]/S");
2889  CreateBranch("hit_peakT",hit_peakT,"hit_peakT[no_hits_stored]/F");
2890  CreateBranch("hit_charge",hit_charge,"hit_charge[no_hits_stored]/F");
2891  CreateBranch("hit_ph",hit_ph,"hit_ph[no_hits_stored]/F");
2892  CreateBranch("hit_startT",hit_startT,"hit_startT[no_hits_stored]/F");
2893  CreateBranch("hit_endT",hit_endT,"hit_endT[no_hits_stored]/F");
2894  CreateBranch("hit_rms",hit_rms,"hit_rms[no_hits_stored]/F");
2895  CreateBranch("hit_trueX",hit_trueX,"hit_trueX[no_hits_stored]/F");
2896  CreateBranch("hit_goodnessOfFit",hit_goodnessOfFit,"hit_goodnessOfFit[no_hits_stored]/F");
2897  CreateBranch("hit_multiplicity",hit_multiplicity,"hit_multiplicity[no_hits_stored]/S");
2898  CreateBranch("hit_trkid",hit_trkid,"hit_trkid[no_hits_stored]/S");
2899  CreateBranch("hit_trkKey",hit_trkKey,"hit_trkKey[no_hits_stored]/S");
2900  CreateBranch("hit_clusterid",hit_clusterid,"hit_clusterid[no_hits_stored]/S");
2901  CreateBranch("hit_clusterKey",hit_clusterKey,"hit_clusterKey[no_hits_stored]/S");
2902  CreateBranch("hit_spacepointid",hit_spacepointid,"hit_spacepointid[no_hits_stored]/S");
2903  CreateBranch("hit_spacepointKey",hit_spacepointKey,"hit_spacepointKey[no_hits_stored]/S");
2904  if (!isCosmics){
2905  CreateBranch("hit_nelec",hit_nelec,"hit_nelec[no_hits_stored]/F");
2906  CreateBranch("hit_energy",hit_energy,"hit_energy[no_hits_stored]/F");
2907  }
2908  if (hasRawDigitInfo()){
2909  CreateBranch("rawD_ph",rawD_ph,"rawD_ph[no_hits_stored]/F");
2910  CreateBranch("rawD_peakT",rawD_peakT,"rawD_peakT[no_hits_stored]/F");
2911  CreateBranch("rawD_charge",rawD_charge,"rawD_charge[no_hits_stored]/F");
2912  CreateBranch("rawD_fwhh",rawD_fwhh,"rawD_fwhh[no_hits_stored]/F");
2913  CreateBranch("rawD_rms",rawD_rms,"rawD_rms[no_hits_stored]/D");
2914  }
2915  }
2916 
2917  if (hasPandoraNuVertexInfo()){
2918  CreateBranch("nnuvtx", &nnuvtx, "nnuvtx/S");
2919  CreateBranch("nuvtxx", nuvtxx, "nuvtxx[nnuvtx]/F");
2920  CreateBranch("nuvtxy", nuvtxy, "nuvtxy[nnuvtx]/F");
2921  CreateBranch("nuvtxz", nuvtxz, "nuvtxz[nnuvtx]/F");
2922  CreateBranch("nuvtxpdg", nuvtxpdg, "nuvtxpdg[nnuvtx]/S");
2923  }
2924 
2925  if (hasClusterInfo()){
2926  CreateBranch("nclusters",&nclusters,"nclusters/S");
2927  CreateBranch("clusterId", clusterId, "clusterId[nclusters]/S");
2928  CreateBranch("clusterView", clusterView, "clusterView[nclusters]/S");
2929  CreateBranch("cluster_StartCharge", cluster_StartCharge, "cluster_StartCharge[nclusters]/F");
2930  CreateBranch("cluster_StartAngle", cluster_StartAngle, "cluster_StartAngle[nclusters]/F");
2931  CreateBranch("cluster_EndCharge", cluster_EndCharge, "cluster_EndCharge[nclusters]/F");
2932  CreateBranch("cluster_EndAngle", cluster_EndAngle, "cluster_EndAngle[nclusters]/F");
2933  CreateBranch("cluster_Integral", cluster_Integral, "cluster_Integral[nclusters]/F");
2934  CreateBranch("cluster_IntegralAverage", cluster_IntegralAverage, "cluster_IntegralAverage[nclusters]/F");
2935  CreateBranch("cluster_SummedADC", cluster_SummedADC, "cluster_SummedADC[nclusters]/F");
2936  CreateBranch("cluster_SummedADCaverage", cluster_SummedADCaverage, "cluster_SummedADCaverage[nclusters]/F");
2937  CreateBranch("cluster_MultipleHitDensity", cluster_MultipleHitDensity, "cluster_MultipleHitDensity[nclusters]/F");
2938  CreateBranch("cluster_Width", cluster_Width, "cluster_Width[nclusters]/F");
2939  CreateBranch("cluster_NHits", cluster_NHits, "cluster_NHits[nclusters]/S");
2940  CreateBranch("cluster_StartWire", cluster_StartWire, "cluster_StartWire[nclusters]/S");
2941  CreateBranch("cluster_StartTick", cluster_StartTick, "cluster_StartTick[nclusters]/S");
2942  CreateBranch("cluster_EndWire", cluster_EndWire, "cluster_EndWire[nclusters]/S");
2943  CreateBranch("cluster_EndTick", cluster_EndTick, "cluster_EndTick[nclusters]/S");
2944  CreateBranch("cluncosmictags_tagger", cluncosmictags_tagger, "cluncosmictags_tagger[nclusters]/S");
2945  CreateBranch("clucosmicscore_tagger", clucosmicscore_tagger, "clucosmicscore_tagger[nclusters]/F");
2946  CreateBranch("clucosmictype_tagger", clucosmictype_tagger, "clucosmictype_tagger[nclusters]/S");
2947  }
2948 
2949  if (hasFlashInfo()){
2950  CreateBranch("no_flashes",&no_flashes,"no_flashes/I");
2951  CreateBranch("flash_time",flash_time,"flash_time[no_flashes]/F");
2952  CreateBranch("flash_pe",flash_pe,"flash_pe[no_flashes]/F");
2953  CreateBranch("flash_ycenter",flash_ycenter,"flash_ycenter[no_flashes]/F");
2954  CreateBranch("flash_zcenter",flash_zcenter,"flash_zcenter[no_flashes]/F");
2955  CreateBranch("flash_ywidth",flash_ywidth,"flash_ywidth[no_flashes]/F");
2956  CreateBranch("flash_zwidth",flash_zwidth,"flash_zwidth[no_flashes]/F");
2957  CreateBranch("flash_timewidth",flash_timewidth,"flash_timewidth[no_flashes]/F");
2958  }
2959 
2960  if (hasExternCountInfo()){
2961  CreateBranch("no_ExternCounts",&no_ExternCounts,"no_ExternCounts/I");
2962  CreateBranch("externcounts_time",externcounts_time,"externcounts_time[no_ExternCounts]/F");
2963  CreateBranch("externcounts_id",externcounts_id,"externcounts_id[no_ExternCounts]/F");
2964  }
2965 
2966  if (hasTrackInfo()){
2967  kNTracker = trackers.size();
2968  CreateBranch("kNTracker",&kNTracker,"kNTracker/B");
2969  for(int i=0; i<kNTracker; i++){
2970  std::string TrackLabel = trackers[i];
2971 
2972  // note that if the tracker data has maximum number of tracks 0,
2973  // nothing is initialized (branches are not even created)
2974  TrackData[i].SetAddresses(pTree, TrackLabel, isCosmics);
2975  } // for trackers
2976  }
2977 
2978  if (hasVertexInfo()){
2979  kNVertexAlgos = vertexalgos.size();
2980  CreateBranch("kNVertexAlgos",&kNVertexAlgos,"kNVertexAlgos/B");
2981  for(int i=0; i<kNVertexAlgos; i++){
2982  std::string VertexLabel = vertexalgos[i];
2983 
2984  // note that if the tracker data has maximum number of tracks 0,
2985  // nothing is initialized (branches are not even created)
2986  VertexData[i].SetAddresses(pTree, VertexLabel, isCosmics);
2987  } // for trackers
2988  }
2989 
2990  if (hasShowerInfo()){
2991  kNShowerAlgos = showeralgos.size();
2992  CreateBranch("kNShowerAlgos",&kNShowerAlgos,"kNShowerAlgos/B");
2993  for(int i=0; i<kNShowerAlgos; i++){
2994  // note that if the shower data has maximum number of showers 0,
2995  // nothing is initialized (branches are not even created)
2996  ShowerData[i].SetAddresses(pTree);
2997  } // for showers
2998  } // if we have shower algos
2999 
3000  if (hasPFParticleInfo()){
3001  //CreateBranch("kNVertexAlgos",&kNVertexAlgos,"kNVertexAlgos/B"); // What would be the PFParticle equivalent of this? There's only 1 algo!
3002  PFParticleData.SetAddresses(pTree);
3003  }
3004 
3005  if (hasGenieInfo()){
3006  CreateBranch("mcevts_truth",&mcevts_truth,"mcevts_truth/I");
3007  CreateBranch("nuPDG_truth",nuPDG_truth,"nuPDG_truth[mcevts_truth]/I");
3008  CreateBranch("ccnc_truth",ccnc_truth,"ccnc_truth[mcevts_truth]/I");
3009  CreateBranch("mode_truth",mode_truth,"mode_truth[mcevts_truth]/I");
3010  CreateBranch("enu_truth",enu_truth,"enu_truth[mcevts_truth]/F");
3011  CreateBranch("Q2_truth",Q2_truth,"Q2_truth[mcevts_truth]/F");
3012  CreateBranch("W_truth",W_truth,"W_truth[mcevts_truth]/F");
3013  CreateBranch("X_truth",X_truth,"X_truth[mcevts_truth]/F");
3014  CreateBranch("Y_truth",Y_truth,"Y_truth[mcevts_truth]/F");
3015  CreateBranch("hitnuc_truth",hitnuc_truth,"hitnuc_truth[mcevts_truth]/I");
3016  CreateBranch("nuvtxx_truth",nuvtxx_truth,"nuvtxx_truth[mcevts_truth]/F");
3017  CreateBranch("nuvtxy_truth",nuvtxy_truth,"nuvtxy_truth[mcevts_truth]/F");
3018  CreateBranch("nuvtxz_truth",nuvtxz_truth,"nuvtxz_truth[mcevts_truth]/F");
3019  CreateBranch("nu_dcosx_truth",nu_dcosx_truth,"nu_dcosx_truth[mcevts_truth]/F");
3020  CreateBranch("nu_dcosy_truth",nu_dcosy_truth,"nu_dcosy_truth[mcevts_truth]/F");
3021  CreateBranch("nu_dcosz_truth",nu_dcosz_truth,"nu_dcosz_truth[mcevts_truth]/F");
3022  CreateBranch("lep_mom_truth",lep_mom_truth,"lep_mom_truth[mcevts_truth]/F");
3023  CreateBranch("lep_dcosx_truth",lep_dcosx_truth,"lep_dcosx_truth[mcevts_truth]/F");
3024  CreateBranch("lep_dcosy_truth",lep_dcosy_truth,"lep_dcosy_truth[mcevts_truth]/F");
3025  CreateBranch("lep_dcosz_truth",lep_dcosz_truth,"lep_dcosz_truth[mcevts_truth]/F");
3026 
3027  CreateBranch("vx_flux",vx_flux,"vx_flux[mcevts_truth]/F");
3028  CreateBranch("vy_flux",vy_flux,"vy_flux[mcevts_truth]/F");
3029  CreateBranch("vz_flux",vz_flux,"vz_flux[mcevts_truth]/F");
3030  CreateBranch("pdpx_flux",pdpx_flux,"pdpx_flux[mcevts_truth]/F");
3031  CreateBranch("pdpy_flux",pdpy_flux,"pdpy_flux[mcevts_truth]/F");
3032  CreateBranch("pdpz_flux",pdpz_flux,"pdpz_flux[mcevts_truth]/F");
3033  CreateBranch("ppdxdz_flux",ppdxdz_flux,"ppdxdz_flux[mcevts_truth]/F");
3034  CreateBranch("ppdydz_flux",ppdydz_flux,"ppdydz_flux[mcevts_truth]/F");
3035  CreateBranch("pppz_flux",pppz_flux,"pppz_flux[mcevts_truth]/F");
3036  CreateBranch("ptype_flux",ptype_flux,"ptype_flux[mcevts_truth]/I");
3037  CreateBranch("ppvx_flux",ppvx_flux,"ppvx_flux[mcevts_truth]/F");
3038  CreateBranch("ppvy_flux",ppvy_flux,"ppvy_flux[mcevts_truth]/F");
3039  CreateBranch("ppvz_flux",ppvz_flux,"ppvz_flux[mcevts_truth]/F");
3040  CreateBranch("muparpx_flux",muparpx_flux,"muparpx_flux[mcevts_truth]/F");
3041  CreateBranch("muparpy_flux",muparpy_flux,"muparpy_flux[mcevts_truth]/F");
3042  CreateBranch("muparpz_flux",muparpz_flux,"muparpz_flux[mcevts_truth]/F");
3043  CreateBranch("mupare_flux",mupare_flux,"mupare_flux[mcevts_truth]/F");
3044  CreateBranch("tgen_flux",tgen_flux,"tgen_flux[mcevts_truth]/I");
3045  CreateBranch("tgptype_flux",tgptype_flux,"tgptype_flux[mcevts_truth]/I");
3046  CreateBranch("tgppx_flux",tgppx_flux,"tgppx_flux[mcevts_truth]/F");
3047  CreateBranch("tgppy_flux",tgppy_flux,"tgppy_flux[mcevts_truth]/F");
3048  CreateBranch("tgppz_flux",tgppz_flux,"tgppz_flux[mcevts_truth]/F");
3049  CreateBranch("tprivx_flux",tprivx_flux,"tprivx_flux[mcevts_truth]/F");
3050  CreateBranch("tprivy_flux",tprivy_flux,"tprivy_flux[mcevts_truth]/F");
3051  CreateBranch("tprivz_flux",tprivz_flux,"tprivz_flux[mcevts_truth]/F");
3052  CreateBranch("dk2gen_flux",dk2gen_flux,"dk2gen_flux[mcevts_truth]/F");
3053  CreateBranch("gen2vtx_flux",gen2vtx_flux,"gen2vtx_flux[mcevts_truth]/F");
3054  CreateBranch("tpx_flux",tpx_flux,"tpx_flux[mcevts_truth]/F");
3055  CreateBranch("tpy_flux",tpy_flux,"tpy_flux[mcevts_truth]/F");
3056  CreateBranch("tpz_flux",tpz_flux,"tpz_flux[mcevts_truth]/F");
3057  CreateBranch("tptype_flux",tptype_flux,"tptype_flux[mcevts_truth]/I");
3058 
3059  CreateBranch("genie_no_primaries",&genie_no_primaries,"genie_no_primaries/I");
3060  CreateBranch("genie_primaries_pdg",genie_primaries_pdg,"genie_primaries_pdg[genie_no_primaries]/I");
3061  CreateBranch("genie_Eng",genie_Eng,"genie_Eng[genie_no_primaries]/F");
3062  CreateBranch("genie_Px",genie_Px,"genie_Px[genie_no_primaries]/F");
3063  CreateBranch("genie_Py",genie_Py,"genie_Py[genie_no_primaries]/F");
3064  CreateBranch("genie_Pz",genie_Pz,"genie_Pz[genie_no_primaries]/F");
3065  CreateBranch("genie_P",genie_P,"genie_P[genie_no_primaries]/F");
3066  CreateBranch("genie_status_code",genie_status_code,"genie_status_code[genie_no_primaries]/I");
3067  CreateBranch("genie_mass",genie_mass,"genie_mass[genie_no_primaries]/F");
3068  CreateBranch("genie_trackID",genie_trackID,"genie_trackID[genie_no_primaries]/I");
3069  CreateBranch("genie_ND",genie_ND,"genie_ND[genie_no_primaries]/I");
3070  CreateBranch("genie_mother",genie_mother,"genie_mother[genie_no_primaries]/I");
3071  }
3072 
3073  if (hasCryInfo()){
3074  CreateBranch("mcevts_truthcry",&mcevts_truthcry,"mcevts_truthcry/I");
3075  CreateBranch("cry_no_primaries",&cry_no_primaries,"cry_no_primaries/I");
3076  CreateBranch("cry_primaries_pdg",cry_primaries_pdg,"cry_primaries_pdg[cry_no_primaries]/I");
3077  CreateBranch("cry_Eng",cry_Eng,"cry_Eng[cry_no_primaries]/F");
3078  CreateBranch("cry_Px",cry_Px,"cry_Px[cry_no_primaries]/F");
3079  CreateBranch("cry_Py",cry_Py,"cry_Py[cry_no_primaries]/F");
3080  CreateBranch("cry_Pz",cry_Pz,"cry_Pz[cry_no_primaries]/F");
3081  CreateBranch("cry_P",cry_P,"cry_P[cry_no_primaries]/F");
3082  CreateBranch("cry_StartPointx",cry_StartPointx,"cry_StartPointx[cry_no_primaries]/F");
3083  CreateBranch("cry_StartPointy",cry_StartPointy,"cry_StartPointy[cry_no_primaries]/F");
3084  CreateBranch("cry_StartPointz",cry_StartPointz,"cry_StartPointz[cry_no_primaries]/F");
3085  CreateBranch("cry_StartPointt",cry_StartPointt,"cry_StartPointt[cry_no_primaries]/F");
3086  CreateBranch("cry_status_code",cry_status_code,"cry_status_code[cry_no_primaries]/I");
3087  CreateBranch("cry_mass",cry_mass,"cry_mass[cry_no_primaries]/F");
3088  CreateBranch("cry_trackID",cry_trackID,"cry_trackID[cry_no_primaries]/I");
3089  CreateBranch("cry_ND",cry_ND,"cry_ND[cry_no_primaries]/I");
3090  CreateBranch("cry_mother",cry_mother,"cry_mother[cry_no_primaries]/I");
3091  }
3092 
3093  if (hasProtoInfo()) {
3094  CreateBranch("proto_no_primaries",&proto_no_primaries,"proto_no_primaries/I");
3095  CreateBranch("proto_isGoodParticle",proto_isGoodParticle,"proto_isGoodParticle[proto_no_primaries]/I");
3096  CreateBranch("proto_vx",proto_vx,"proto_vx[proto_no_primaries]/F");
3097  CreateBranch("proto_vy",proto_vy,"proto_vy[proto_no_primaries]/F");
3098  CreateBranch("proto_vz",proto_vz,"proto_vz[proto_no_primaries]/F");
3099  CreateBranch("proto_t",proto_t,"proto_t[proto_no_primaries]/F");
3100  CreateBranch("proto_px",proto_px,"proto_px[proto_no_primaries]/F");
3101  CreateBranch("proto_py",proto_py,"proto_py[proto_no_primaries]/F");
3102  CreateBranch("proto_pz",proto_pz,"proto_pz[proto_no_primaries]/F");
3103  CreateBranch("proto_momentum",proto_momentum,"proto_momentum[proto_no_primaries]/F");
3104  CreateBranch("proto_energy",proto_energy,"proto_energy[proto_no_primaries]/F");
3105  CreateBranch("proto_pdg",proto_pdg,"proto_pdg[proto_no_primaries]/I");
3106  CreateBranch("proto_geantTrackID",proto_geantTrackID,"proto_geantTrackID[proto_no_primaries]/I");
3107  CreateBranch("proto_geantIndex",proto_geantIndex,"proto_geantIndex[proto_no_primaries]/I");
3108  }
3109 
3110  if (hasGeantInfo()){
3111  CreateBranch("no_primaries",&no_primaries,"no_primaries/I");
3112  CreateBranch("geant_list_size",&geant_list_size,"geant_list_size/I");
3113  CreateBranch("geant_list_size_in_tpcAV",&geant_list_size_in_tpcAV,"geant_list_size_in_tpcAV/I");
3114  CreateBranch("pdg",pdg,"pdg[geant_list_size]/I");
3115  CreateBranch("status",status,"status[geant_list_size]/I");
3116  CreateBranch("Mass",Mass,"Mass[geant_list_size]/F");
3117  CreateBranch("Eng",Eng,"Eng[geant_list_size]/F");
3118  CreateBranch("EndE",EndE,"EndE[geant_list_size]/F");
3119  CreateBranch("Px",Px,"Px[geant_list_size]/F");
3120  CreateBranch("Py",Py,"Py[geant_list_size]/F");
3121  CreateBranch("Pz",Pz,"Pz[geant_list_size]/F");
3122  CreateBranch("P",P,"P[geant_list_size]/F");
3123  CreateBranch("StartPointx",StartPointx,"StartPointx[geant_list_size]/F");
3124  CreateBranch("StartPointy",StartPointy,"StartPointy[geant_list_size]/F");
3125  CreateBranch("StartPointz",StartPointz,"StartPointz[geant_list_size]/F");
3126  CreateBranch("StartT",StartT,"StartT[geant_list_size]/F");
3127  CreateBranch("EndPointx",EndPointx,"EndPointx[geant_list_size]/F");
3128  CreateBranch("EndPointy",EndPointy,"EndPointy[geant_list_size]/F");
3129  CreateBranch("EndPointz",EndPointz,"EndPointz[geant_list_size]/F");
3130  CreateBranch("EndT",EndT,"EndT[geant_list_size]/F");
3131  CreateBranch("theta",theta,"theta[geant_list_size]/F");
3132  CreateBranch("phi",phi,"phi[geant_list_size]/F");
3133  CreateBranch("theta_xz",theta_xz,"theta_xz[geant_list_size]/F");
3134  CreateBranch("theta_yz",theta_yz,"theta_yz[geant_list_size]/F");
3135  CreateBranch("pathlen",pathlen,"pathlen[geant_list_size]/F");
3136  CreateBranch("inTPCActive",inTPCActive,"inTPCActive[geant_list_size]/I");
3137  CreateBranch("StartPointx_tpcAV",StartPointx_tpcAV,"StartPointx_tpcAV[geant_list_size]/F");
3138  CreateBranch("StartPointy_tpcAV",StartPointy_tpcAV,"StartPointy_tpcAV[geant_list_size]/F");
3139  CreateBranch("StartPointz_tpcAV",StartPointz_tpcAV,"StartPointz_tpcAV[geant_list_size]/F");
3140  CreateBranch("StartT_tpcAV",StartT_tpcAV,"StartT_tpcAV[geant_list_size]/F");
3141  CreateBranch("StartE_tpcAV",StartE_tpcAV,"StartE_tpcAV[geant_list_size]/F");
3142  CreateBranch("StartP_tpcAV",StartP_tpcAV,"StartP_tpcAV[geant_list_size]/F");
3143  CreateBranch("StartPx_tpcAV",StartPx_tpcAV,"StartPx_tpcAV[geant_list_size]/F");
3144  CreateBranch("StartPy_tpcAV",StartPy_tpcAV,"StartPy_tpcAV[geant_list_size]/F");
3145  CreateBranch("StartPz_tpcAV",StartPz_tpcAV,"StartPz_tpcAV[geant_list_size]/F");
3146  CreateBranch("EndPointx_tpcAV",EndPointx_tpcAV,"EndPointx_tpcAV[geant_list_size]/F");
3147  CreateBranch("EndPointy_tpcAV",EndPointy_tpcAV,"EndPointy_tpcAV[geant_list_size]/F");
3148  CreateBranch("EndPointz_tpcAV",EndPointz_tpcAV,"EndPointz_tpcAV[geant_list_size]/F");
3149  CreateBranch("EndT_tpcAV",EndT_tpcAV,"EndT_tpcAV[geant_list_size]/F");
3150  CreateBranch("EndE_tpcAV",EndE_tpcAV,"EndE_tpcAV[geant_list_size]/F");
3151  CreateBranch("EndP_tpcAV",EndP_tpcAV,"EndP_tpcAV[geant_list_size]/F");
3152  CreateBranch("EndPx_tpcAV",EndPx_tpcAV,"EndPx_tpcAV[geant_list_size]/F");
3153  CreateBranch("EndPy_tpcAV",EndPy_tpcAV,"EndPy_tpcAV[geant_list_size]/F");
3154  CreateBranch("EndPz_tpcAV",EndPz_tpcAV,"EndPz_tpcAV[geant_list_size]/F");
3155  CreateBranch("pathlen_drifted",pathlen_drifted,"pathlen_drifted[geant_list_size]/F");
3156  CreateBranch("inTPCDrifted",inTPCDrifted,"inTPCDrifted[geant_list_size]/I");
3157  CreateBranch("StartPointx_drifted",StartPointx_drifted,"StartPointx_drifted[geant_list_size]/F");
3158  CreateBranch("StartPointy_drifted",StartPointy_drifted,"StartPointy_drifted[geant_list_size]/F");
3159  CreateBranch("StartPointz_drifted",StartPointz_drifted,"StartPointz_drifted[geant_list_size]/F");
3160  CreateBranch("StartT_drifted",StartT_drifted,"StartT_drifted[geant_list_size]/F");
3161  CreateBranch("StartE_drifted",StartE_drifted,"StartE_drifted[geant_list_size]/F");
3162  CreateBranch("StartP_drifted",StartP_drifted,"StartP_drifted[geant_list_size]/F");
3163  CreateBranch("StartPx_drifted",StartPx_drifted,"StartPx_drifted[geant_list_size]/F");
3164  CreateBranch("StartPy_drifted",StartPy_drifted,"StartPy_drifted[geant_list_size]/F");
3165  CreateBranch("StartPz_drifted",StartPz_drifted,"StartPz_drifted[geant_list_size]/F");
3166  CreateBranch("EndPointx_drifted",EndPointx_drifted,"EndPointx_drifted[geant_list_size]/F");
3167  CreateBranch("EndPointy_drifted",EndPointy_drifted,"EndPointy_drifted[geant_list_size]/F");
3168  CreateBranch("EndPointz_drifted",EndPointz_drifted,"EndPointz_drifted[geant_list_size]/F");
3169  CreateBranch("EndT_drifted",EndT_drifted,"EndT_drifted[geant_list_size]/F");
3170  CreateBranch("EndE_drifted",EndE_drifted,"EndE_drifted[geant_list_size]/F");
3171  CreateBranch("EndP_drifted",EndP_drifted,"EndP_drifted[geant_list_size]/F");
3172  CreateBranch("EndPx_drifted",EndPx_drifted,"EndPx_drifted[geant_list_size]/F");
3173  CreateBranch("EndPy_drifted",EndPy_drifted,"EndPy_drifted[geant_list_size]/F");
3174  CreateBranch("EndPz_drifted",EndPz_drifted,"EndPz_drifted[geant_list_size]/F");
3175  CreateBranch("NumberDaughters",NumberDaughters,"NumberDaughters[geant_list_size]/I");
3176  CreateBranch("Mother",Mother,"Mother[geant_list_size]/I");
3177  CreateBranch("TrackId",TrackId,"TrackId[geant_list_size]/I");
3178  CreateBranch("MergedId", MergedId, "MergedId[geant_list_size]/I");
3179  CreateBranch("origin", origin, "origin[geant_list_size]/I");
3180  CreateBranch("MCTruthIndex", MCTruthIndex, "MCTruthIndex[geant_list_size]/I");
3181  CreateBranch("process_primary",process_primary,"process_primary[geant_list_size]/I");
3182  CreateBranch("processname", processname);
3183  }
3184 
3185  if (hasMCShowerInfo()){
3186  CreateBranch("no_mcshowers",&no_mcshowers,"no_mcshowers/I");
3187  CreateBranch("mcshwr_origin",mcshwr_origin,"mcshwr_origin[no_mcshowers]/I");
3188  CreateBranch("mcshwr_pdg",mcshwr_pdg,"mcshwr_pdg[no_mcshowers]/I");
3189  CreateBranch("mcshwr_TrackId",mcshwr_TrackId,"mcshwr_TrackId[no_mcshowers]/I");
3190  CreateBranch("mcshwr_Process",mcshwr_Process);
3191  CreateBranch("mcshwr_startX",mcshwr_startX,"mcshwr_startX[no_mcshowers]/F");
3192  CreateBranch("mcshwr_startY",mcshwr_startY,"mcshwr_startY[no_mcshowers]/F");
3193  CreateBranch("mcshwr_startZ",mcshwr_startZ,"mcshwr_startZ[no_mcshowers]/F");
3194  CreateBranch("mcshwr_endX",mcshwr_endX,"mcshwr_endX[no_mcshowers]/F");
3195  CreateBranch("mcshwr_endY",mcshwr_endY,"mcshwr_endY[no_mcshowers]/F");
3196  CreateBranch("mcshwr_endZ",mcshwr_endZ,"mcshwr_endZ[no_mcshowers]/F");
3197  CreateBranch("mcshwr_CombEngX",mcshwr_CombEngX,"mcshwr_CombEngX[no_mcshowers]/F");
3198  CreateBranch("mcshwr_CombEngY",mcshwr_CombEngY,"mcshwr_CombEngY[no_mcshowers]/F");
3199  CreateBranch("mcshwr_CombEngZ",mcshwr_CombEngZ,"mcshwr_CombEngZ[no_mcshowers]/F");
3200  CreateBranch("mcshwr_CombEngPx",mcshwr_CombEngPx,"mcshwr_CombEngPx[no_mcshowers]/F");
3201  CreateBranch("mcshwr_CombEngPy",mcshwr_CombEngPy,"mcshwr_CombEngPy[no_mcshowers]/F");
3202  CreateBranch("mcshwr_CombEngPz",mcshwr_CombEngPz,"mcshwr_CombEngPz[no_mcshowers]/F");
3203  CreateBranch("mcshwr_CombEngE",mcshwr_CombEngE,"mcshwr_CombEngE[no_mcshowers]/F");
3204  CreateBranch("mcshwr_dEdx",mcshwr_dEdx,"mcshwr_dEdx[no_mcshowers]/F");
3205  CreateBranch("mcshwr_StartDirX",mcshwr_StartDirX,"mcshwr_StartDirX[no_mcshowers]/F");
3206  CreateBranch("mcshwr_StartDirY",mcshwr_StartDirY,"mcshwr_StartDirY[no_mcshowers]/F");
3207  CreateBranch("mcshwr_StartDirZ",mcshwr_StartDirZ,"mcshwr_StartDirZ[no_mcshowers]/F");
3208  CreateBranch("mcshwr_isEngDeposited",mcshwr_isEngDeposited,"mcshwr_isEngDeposited[no_mcshowers]/I");
3209  CreateBranch("mcshwr_Motherpdg",mcshwr_Motherpdg,"mcshwr_Motherpdg[no_mcshowers]/I");
3210  CreateBranch("mcshwr_MotherTrkId",mcshwr_MotherTrkId,"mcshwr_MotherTrkId[no_mcshowers]/I");
3211  CreateBranch("mcshwr_MotherProcess",mcshwr_MotherProcess);
3212  CreateBranch("mcshwr_MotherstartX",mcshwr_MotherstartX,"mcshwr_MotherstartX[no_mcshowers]/F");
3213  CreateBranch("mcshwr_MotherstartY",mcshwr_MotherstartY,"mcshwr_MotherstartY[no_mcshowers]/F");
3214  CreateBranch("mcshwr_MotherstartZ",mcshwr_MotherstartZ,"mcshwr_MotherstartZ[no_mcshowers]/F");
3215  CreateBranch("mcshwr_MotherendX",mcshwr_MotherendX,"mcshwr_MotherendX[no_mcshowers]/F");
3216  CreateBranch("mcshwr_MotherendY",mcshwr_MotherendY,"mcshwr_MotherendY[no_mcshowers]/F");
3217  CreateBranch("mcshwr_MotherendZ",mcshwr_MotherendZ,"mcshwr_MotherendZ[no_mcshowers]/F");
3218  CreateBranch("mcshwr_Ancestorpdg",mcshwr_Ancestorpdg,"mcshwr_Ancestorpdg[no_mcshowers]/I");
3219  CreateBranch("mcshwr_AncesotorTrkId",mcshwr_AncestorTrkId,"mcshwr_AncestorTrkId[no_mcshowers]/I");
3220  CreateBranch("mcshwr_AncesotorProcess",mcshwr_AncestorProcess);
3221  CreateBranch("mcshwr_AncestorstartX",mcshwr_AncestorstartX,"mcshwr_AncestorstartX[no_mcshowers]/F");
3222  CreateBranch("mcshwr_AncestorstartY",mcshwr_AncestorstartY,"mcshwr_AncestorstartY[no_mcshowers]/F");
3223  CreateBranch("mcshwr_AncestorstartZ",mcshwr_AncestorstartZ,"mcshwr_AncestorstartZ[no_mcshowers]/F");
3224  CreateBranch("mcshwr_AncestorendX",mcshwr_AncestorendX,"mcshwr_AncestorendX[no_mcshowers]/F");
3225  CreateBranch("mcshwr_AncestorendY",mcshwr_AncestorendY,"mcshwr_AncestorendY[no_mcshowers]/F");
3226  CreateBranch("mcshwr_AncestorendZ",mcshwr_AncestorendZ,"mcshwr_AncestorendZ[no_mcshowers]/F");
3227  }
3228 
3229  if (hasMCTrackInfo()){
3230  CreateBranch("no_mctracks",&no_mctracks,"no_mctracks/I");
3231  CreateBranch("mctrk_origin",mctrk_origin,"mctrk_origin[no_mctracks]/I");
3232  CreateBranch("mctrk_pdg",mctrk_pdg,"mctrk_pdg[no_mctracks]/I");
3233  CreateBranch("mctrk_TrackId",mctrk_TrackId,"mctrk_TrackId[no_mctracks]/I");
3234  CreateBranch("mctrk_Process",mctrk_Process);
3235  CreateBranch("mctrk_startX",mctrk_startX,"mctrk_startX[no_mctracks]/F");
3236  CreateBranch("mctrk_startY",mctrk_startY,"mctrk_startY[no_mctracks]/F");
3237  CreateBranch("mctrk_startZ",mctrk_startZ,"mctrk_startZ[no_mctracks]/F");
3238  CreateBranch("mctrk_endX",mctrk_endX,"mctrk_endX[no_mctracks]/F");
3239  CreateBranch("mctrk_endY",mctrk_endY,"mctrk_endY[no_mctracks]/F");
3240  CreateBranch("mctrk_endZ",mctrk_endZ,"mctrk_endZ[no_mctracks]/F");
3241  CreateBranch("mctrk_startX_drifted",mctrk_startX_drifted,"mctrk_startX_drifted[no_mctracks]/F");
3242  CreateBranch("mctrk_startY_drifted",mctrk_startY_drifted,"mctrk_startY_drifted[no_mctracks]/F");
3243  CreateBranch("mctrk_startZ_drifted",mctrk_startZ_drifted,"mctrk_startZ_drifted[no_mctracks]/F");
3244  CreateBranch("mctrk_endX_drifted",mctrk_endX_drifted,"mctrk_endX_drifted[no_mctracks]/F");
3245  CreateBranch("mctrk_endY_drifted",mctrk_endY_drifted,"mctrk_endY_drifted[no_mctracks]/F");
3246  CreateBranch("mctrk_endZ_drifted",mctrk_endZ_drifted,"mctrk_endZ_drifted[no_mctracks]/F");
3247  CreateBranch("mctrk_len_drifted",mctrk_len_drifted,"mctrk_len_drifted[no_mctracks]/F");
3248  CreateBranch("mctrk_p_drifted",mctrk_p_drifted,"mctrk_p_drifted[no_mctracks]/F");
3249  CreateBranch("mctrk_px_drifted",mctrk_px_drifted,"mctrk_px_drifted[no_mctracks]/F");
3250  CreateBranch("mctrk_py_drifted",mctrk_py_drifted,"mctrk_py_drifted[no_mctracks]/F");
3251  CreateBranch("mctrk_pz_drifted",mctrk_pz_drifted,"mctrk_pz_drifted[no_mctracks]/F");
3252  CreateBranch("mctrk_Motherpdg",mctrk_Motherpdg,"mctrk_Motherpdg[no_mctracks]/I");
3253  CreateBranch("mctrk_MotherTrkId",mctrk_MotherTrkId,"mctrk_MotherTrkId[no_mctracks]/I");
3254  CreateBranch("mctrk_MotherProcess",mctrk_MotherProcess);
3255  CreateBranch("mctrk_MotherstartX",mctrk_MotherstartX,"mctrk_MotherstartX[no_mctracks]/F");
3256  CreateBranch("mctrk_MotherstartY",mctrk_MotherstartY,"mctrk_MotherstartY[no_mctracks]/F");
3257  CreateBranch("mctrk_MotherstartZ",mctrk_MotherstartZ,"mctrk_MotherstartZ[no_mctracks]/F");
3258  CreateBranch("mctrk_MotherendX",mctrk_MotherendX,"mctrk_MotherendX[no_mctracks]/F");
3259  CreateBranch("mctrk_MotherendY",mctrk_MotherendY,"mctrk_MotherendY[no_mctracks]/F");
3260  CreateBranch("mctrk_MotherendZ",mctrk_MotherendZ,"mctrk_MotherendZ[no_mctracks]/F");
3261  CreateBranch("mctrk_Ancestorpdg",mctrk_Ancestorpdg,"mctrk_Ancestorpdg[no_mctracks]/I");
3262  CreateBranch("mctrk_AncesotorTrkId",mctrk_AncestorTrkId,"mctrk_AncestorTrkId[no_mctracks]/I");
3263  CreateBranch("mctrk_AncesotorProcess",mctrk_AncestorProcess);
3264  CreateBranch("mctrk_AncestorstartX",mctrk_AncestorstartX,"mctrk_AncestorstartX[no_mctracks]/F");
3265  CreateBranch("mctrk_AncestorstartY",mctrk_AncestorstartY,"mctrk_AncestorstartY[no_mctracks]/F");
3266  CreateBranch("mctrk_AncestorstartZ",mctrk_AncestorstartZ,"mctrk_AncestorstartZ[no_mctracks]/F");
3267  CreateBranch("mctrk_AncestorendX",mctrk_AncestorendX,"mctrk_AncestorendX[no_mctracks]/F");
3268  CreateBranch("mctrk_AncestorendY",mctrk_AncestorendY,"mctrk_AncestorendY[no_mctracks]/F");
3269  CreateBranch("mctrk_AncestorendZ",mctrk_AncestorendZ,"mctrk_AncestorendZ[no_mctracks]/F");
3270  }
3271 
3272  if (hasAuxDetector()) {
3273  // Geant information is required to fill aux detector information.
3274  // if fSaveGeantInfo is not set to true, show an error message and quit!
3275  if (!hasGeantInfo()){
3277  << "Saving Auxiliary detector information requies saving GEANT information, "
3278  <<"please set fSaveGeantInfo flag to true in your fhicl file and rerun.\n";
3279  }
3280  std::ostringstream sstr;
3281  sstr << "[" << kMaxAuxDets << "]";
3282  std::string MaxAuxDetIndexStr = sstr.str();
3283  CreateBranch("NAuxDets", NAuxDets, "NAuxDets[geant_list_size]/s");
3284  CreateBranch("AuxDetID", AuxDetID, "AuxDetID[geant_list_size]" + MaxAuxDetIndexStr + "/S");
3285  CreateBranch("AuxDetEntryX", entryX, "AuxDetEntryX[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3286  CreateBranch("AuxDetEntryY", entryY, "AuxDetEntryY[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3287  CreateBranch("AuxDetEntryZ", entryZ, "AuxDetEntryZ[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3288  CreateBranch("AuxDetEntryT", entryT, "AuxDetEntryT[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3289  CreateBranch("AuxDetExitX", exitX, "AuxDetExitX[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3290  CreateBranch("AuxDetExitY", exitY, "AuxDetExitY[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3291  CreateBranch("AuxDetExitZ", exitZ, "AuxDetExitZ[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3292  CreateBranch("AuxDetExitT", exitT, "AuxDetExitT[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3293  CreateBranch("AuxDetExitPx", exitPx, "AuxDetExitPx[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3294  CreateBranch("AuxDetExitPy", exitPy, "AuxDetExitPy[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3295  CreateBranch("AuxDetExitPz", exitPz, "AuxDetExitPz[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3296  CreateBranch("CombinedEnergyDep", CombinedEnergyDep,
3297  "CombinedEnergyDep[geant_list_size]" + MaxAuxDetIndexStr + "/F");
3298  } // if hasAuxDetector
3299 
3300  if(hasSpacePointSolverInfo()) {
3301  std::cout << "Creating branches.\n\n";
3302  CreateBranch("nspacepoints", &nspacepoints, "nspacepoints/S");
3303  CreateBranch("SpacePointX", SpacePointX, "SpacePointX[nspacepoints]/F");
3304  CreateBranch("SpacePointY", SpacePointY, "SpacePointY[nspacepoints]/F");
3305  CreateBranch("SpacePointZ", SpacePointZ, "SpacePointZ[nspacepoints]/F");
3306  CreateBranch("SpacePointQ", SpacePointQ, "SpacePointQ[nspacepoints]/F");
3307  CreateBranch("SpacePointErrX", SpacePointErrX, "SpacePointErrX[nspacepoints]/F");
3308  CreateBranch("SpacePointErrY", SpacePointErrY, "SpacePointErrY[nspacepoints]/F");
3309  CreateBranch("SpacePointErrZ", SpacePointErrZ, "SpacePointErrZ[nspacepoints]/F");
3310  CreateBranch("SpacePointID", SpacePointID, "SpacePointID[nspacepoints]/I");
3311  CreateBranch("SpacePointChisq", SpacePointChisq, "SpacePointChisq[nspacepoints]/F");
3312 
3313  if(hasCnnInfo()) {
3314  CreateBranch("SpacePointEmScore", SpacePointEmScore, "SpacePointEmScore[nspacepoints]/F");
3315  } // if hasCnnInfo
3316  } // if hasSpacePointSolverInfo
3317 
3318 
3319 } // dune::AnalysisTreeDataStruct::SetAddresses()
3320 
3321 
3322 //------------------------------------------------------------------------------
3323 //--- AnalysisTree
3324 //---
3325 
3327  EDAnalyzer(pset),
3328  fTree(nullptr), fPOT(nullptr),
3329  fDigitModuleLabel (pset.get< std::string >("DigitModuleLabel") ),
3330  fHitsModuleLabel (pset.get< std::string >("HitsModuleLabel") ),
3331  fLArG4ModuleLabel (pset.get< std::string >("LArGeantModuleLabel") ),
3332  fCalDataModuleLabel (pset.get< std::string >("CalDataModuleLabel") ),
3333  fGenieGenModuleLabel (pset.get< std::string >("GenieGenModuleLabel") ),
3334  fCryGenModuleLabel (pset.get< std::string >("CryGenModuleLabel") ),
3335  fProtoGenModuleLabel (pset.get< std::string >("ProtoGenModuleLabel") ),
3336  fG4ModuleLabel (pset.get< std::string >("G4ModuleLabel") ),
3337  fClusterModuleLabel (pset.get< std::string >("ClusterModuleLabel") ),
3338  fPandoraNuVertexModuleLabel (pset.get< std::string >("PandoraNuVertexModuleLabel") ),
3339  fOpFlashModuleLabel (pset.get< std::string >("OpFlashModuleLabel") ),
3340  fExternalCounterModuleLabel (pset.get< std::string >("ExternalCounterModuleLabel") ),
3341  fMCShowerModuleLabel (pset.get< std::string >("MCShowerModuleLabel") ),
3342  fMCTrackModuleLabel (pset.get< std::string >("MCTrackModuleLabel") ),
3343  fSpacePointSolverModuleLabel (pset.get< std::string >("SpacePointSolverModuleLabel")),
3344  fCnnModuleLabel (pset.get< std::string >("CnnModuleLabel")),
3345  fTrackModuleLabel (pset.get< std::vector<std::string> >("TrackModuleLabel")),
3346  fVertexModuleLabel (pset.get< std::vector<std::string> >("VertexModuleLabel")),
3347  fShowerModuleLabel (pset.get< std::vector<std::string> >("ShowerModuleLabel")),
3348  fCalorimetryModuleLabel (pset.get< std::vector<std::string> >("CalorimetryModuleLabel")),
3349  fParticleIDModuleLabel (pset.get< std::vector<std::string> >("ParticleIDModuleLabel") ),
3350  fMVAPIDShowerModuleLabel (pset.get< std::vector<std::string> >("MVAPIDShowerModuleLabel") ),
3351  fMVAPIDTrackModuleLabel (pset.get< std::vector<std::string> >("MVAPIDTrackModuleLabel") ),
3352  fFlashT0FinderLabel (pset.get< std::vector<std::string> >("FlashT0FinderLabel") ),
3353  fMCT0FinderLabel (pset.get< std::vector<std::string> >("MCT0FinderLabel") ),
3354  fPOTModuleLabel (pset.get< std::string >("POTModuleLabel")),
3355  fCosmicClusterTaggerAssocLabel (pset.get< std::string >("CosmicClusterTaggerAssocLabel")),
3356  fUseBuffer (pset.get< bool >("UseBuffers", false)),
3357  fSaveAuxDetInfo (pset.get< bool >("SaveAuxDetInfo", false)),
3358  fSaveCryInfo (pset.get< bool >("SaveCryInfo", false)),
3359  fSaveGenieInfo (pset.get< bool >("SaveGenieInfo", false)),
3360  fSaveProtoInfo (pset.get< bool >("SaveProtoInfo", false)),
3361  fSaveGeantInfo (pset.get< bool >("SaveGeantInfo", false)),
3362  fSaveMCShowerInfo (pset.get< bool >("SaveMCShowerInfo", false)),
3363  fSaveMCTrackInfo (pset.get< bool >("SaveMCTrackInfo", false)),
3364  fSaveHitInfo (pset.get< bool >("SaveHitInfo", false)),
3365  fSaveRawDigitInfo (pset.get< bool >("SaveRawDigitInfo", false)),
3366  fSaveTrackInfo (pset.get< bool >("SaveTrackInfo", false)),
3367  fSaveVertexInfo (pset.get< bool >("SaveVertexInfo", false)),
3368  fSaveClusterInfo (pset.get< bool >("SaveClusterInfo", false)),
3369  fSavePandoraNuVertexInfo (pset.get< bool >("SavePandoraNuVertexInfo", false)),
3370  fSaveFlashInfo (pset.get< bool >("SaveFlashInfo", false)),
3371  fSaveExternCounterInfo (pset.get< bool >("SaveExternCounterInfo", false)),
3372  fSaveShowerInfo (pset.get< bool >("SaveShowerInfo", false)),
3373  fSavePFParticleInfo (pset.get< bool >("SavePFParticleInfo", false)),
3374  fSaveSpacePointSolverInfo (pset.get< bool >("SaveSpacePointSolverInfo", false)),
3375  fSaveCnnInfo (pset.get< bool >("SaveCnnInfo", false)),
3376  fCosmicTaggerAssocLabel (pset.get<std::vector< std::string > >("CosmicTaggerAssocLabel") ),
3377  fContainmentTaggerAssocLabel (pset.get<std::vector< std::string > >("ContainmentTaggerAssocLabel") ),
3378  fFlashMatchAssocLabel (pset.get<std::vector< std::string > >("FlashMatchAssocLabel") ),
3379  bIgnoreMissingShowers (pset.get< bool >("IgnoreMissingShowers", false)),
3380  isCosmics(false),
3381  fSaveCaloCosmics (pset.get< bool >("SaveCaloCosmics",false)),
3382  fG4minE (pset.get< float>("G4minE",0.01))
3383 {
3384 
3385  if (fSavePFParticleInfo) fPFParticleModuleLabel = pset.get<std::string>("PFParticleModuleLabel");
3386 
3387  if (fSaveAuxDetInfo == true) fSaveGeantInfo = true;
3388  if (fSaveRawDigitInfo == true) fSaveHitInfo = true;
3389  mf::LogInfo("AnalysisTree") << "Configuration:"
3390  << "\n UseBuffers: " << std::boolalpha << fUseBuffer
3391  ;
3392  if (GetNTrackers() > kMaxTrackers) {
3394  << "AnalysisTree currently supports only up to " << kMaxTrackers
3395  << " tracking algorithms, but " << GetNTrackers() << " are specified."
3396  << "\nYou can increase kMaxTrackers and recompile.";
3397  } // if too many trackers
3398  if (fTrackModuleLabel.size() != fCalorimetryModuleLabel.size()){
3400  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3401  << "fCalorimetryModuleLabel.size() = "<<fCalorimetryModuleLabel.size();
3402  }
3403  if (fTrackModuleLabel.size() != fParticleIDModuleLabel.size()){
3405  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3406  << "fParticleIDModuleLabel.size() = "<<fParticleIDModuleLabel.size();
3407  }
3408  if (fTrackModuleLabel.size() != fFlashT0FinderLabel.size()){
3410  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3411  << "fFlashT0FinderLabel.size() = "<<fFlashT0FinderLabel.size();
3412  }
3413  if (fTrackModuleLabel.size() != fMCT0FinderLabel.size()){
3415  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3416  << "fMCT0FinderLabel.size() = "<<fMCT0FinderLabel.size();
3417  }
3418  if (fTrackModuleLabel.size() != fCosmicTaggerAssocLabel.size()) {
3420  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3421  << "fCosmicTaggerAssocLabel.size() = "<<fCosmicTaggerAssocLabel.size();
3422  }
3423  if (fTrackModuleLabel.size() != fContainmentTaggerAssocLabel.size()) {
3425  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3426  << "fCosmicTaggerAssocLabel.size() = "<<fContainmentTaggerAssocLabel.size();
3427  }
3428  if (fTrackModuleLabel.size() != fFlashMatchAssocLabel.size()) {
3430  << "fTrackModuleLabel.size() = "<<fTrackModuleLabel.size()<<" does not match "
3431  << "fCosmicTaggerAssocLabel.size() = "<<fFlashMatchAssocLabel.size();
3432  }
3433  if (GetNVertexAlgos() > kMaxVertexAlgos) {
3435  << "AnalysisTree currently supports only up to " << kMaxVertexAlgos
3436  << " tracking algorithms, but " << GetNVertexAlgos() << " are specified."
3437  << "\nYou can increase kMaxVertexAlgos and recompile.";
3438  } // if too many trackers
3439 
3440  // Build my Cryostat boundaries array...Taken from Tyler Alion in Geometry Core. Should still return the same values for uBoone.
3441  ActiveBounds[0] = ActiveBounds[2] = ActiveBounds[4] = DBL_MAX;
3442  ActiveBounds[1] = ActiveBounds[3] = ActiveBounds[5] = -DBL_MAX;
3443  // assume single cryostats
3444  auto const* geom = lar::providerFrom<geo::Geometry>();
3445  for (geo::TPCGeo const& TPC: geom->IterateTPCs()) {
3446  // get center in world coordinates
3447  double origin[3] = {0.};
3448  double center[3] = {0.};
3449  TPC.LocalToWorld(origin, center);
3450  double tpcDim[3] = {TPC.HalfWidth(), TPC.HalfHeight(), 0.5*TPC.Length() };
3451 
3452  if( center[0] - tpcDim[0] < ActiveBounds[0] ) ActiveBounds[0] = center[0] - tpcDim[0];
3453  if( center[0] + tpcDim[0] > ActiveBounds[1] ) ActiveBounds[1] = center[0] + tpcDim[0];
3454  if( center[1] - tpcDim[1] < ActiveBounds[2] ) ActiveBounds[2] = center[1] - tpcDim[1];
3455  if( center[1] + tpcDim[1] > ActiveBounds[3] ) ActiveBounds[3] = center[1] + tpcDim[1];
3456  if( center[2] - tpcDim[2] < ActiveBounds[4] ) ActiveBounds[4] = center[2] - tpcDim[2];
3457  if( center[2] + tpcDim[2] > ActiveBounds[5] ) ActiveBounds[5] = center[2] + tpcDim[2];
3458  } // for all TPC
3459  std::cout << "Active Boundaries: "
3460  << "\n\tx: " << ActiveBounds[0] << " to " << ActiveBounds[1]
3461  << "\n\ty: " << ActiveBounds[2] << " to " << ActiveBounds[3]
3462  << "\n\tz: " << ActiveBounds[4] << " to " << ActiveBounds[5]
3463  << std::endl;
3464 } // dune::AnalysisTree::AnalysisTree()
3465 
3466 //-------------------------------------------------
3468 {
3469  DestroyData();
3470 }
3471 
3472 void dune::AnalysisTree::CreateTree(bool bClearData /* = false */) {
3473  if (!fTree) {
3475  fTree = tfs->make<TTree>("anatree","analysis tree");
3476  }
3477  if (!fPOT) {
3479  fPOT = tfs->make<TTree>("pottree","pot tree");
3480  fPOT->Branch("pot",&SubRunData.pot,"pot/D");
3481  fPOT->Branch("potbnbETOR860",&SubRunData.potbnbETOR860,"potbnbETOR860/D");
3482  fPOT->Branch("potbnbETOR875",&SubRunData.potbnbETOR875,"potbnbETOR875/D");
3483  fPOT->Branch("potnumiETORTGT",&SubRunData.potnumiETORTGT,"potnumiETORTGT/D");
3484  }
3485  CreateData(bClearData);
3486  SetAddresses();
3487 } // dune::AnalysisTree::CreateTree()
3488 
3489 
3491 {
3492 
3493 // auto potListHandle = sr.getHandle< sumdata::POTSummary >(fPOTModuleLabel);
3494 // if (potListHandle)
3495 // SubRunData.pot=potListHandle->totpot;
3496 // else
3497 // SubRunData.pot=0.;
3498 
3499 }
3500 
3502 {
3503 
3504  auto potListHandle = sr.getHandle< sumdata::POTSummary >(fPOTModuleLabel);
3505  if (potListHandle)
3506  SubRunData.pot=potListHandle->totpot;
3507  else
3508  SubRunData.pot=0.;
3509 
3510  art::InputTag itag1("beamdata","bnbETOR860");
3511  auto potSummaryHandlebnbETOR860 = sr.getHandle<sumdata::POTSummary>(itag1);
3512  if (potSummaryHandlebnbETOR860){
3513  SubRunData.potbnbETOR860 = potSummaryHandlebnbETOR860->totpot;
3514  }
3515  else
3517 
3518  art::InputTag itag2("beamdata","bnbETOR875");
3519  auto potSummaryHandlebnbETOR875 = sr.getHandle<sumdata::POTSummary>(itag2);
3520  if (potSummaryHandlebnbETOR875){
3521  SubRunData.potbnbETOR875 = potSummaryHandlebnbETOR875->totpot;
3522  }
3523  else
3525 
3526  art::InputTag itag3("beamdata","numiETORTGT");
3527  auto potSummaryHandlenumiETORTGT = sr.getHandle<sumdata::POTSummary>(itag3);
3528  if (potSummaryHandlenumiETORTGT){
3529  SubRunData.potnumiETORTGT = potSummaryHandlenumiETORTGT->totpot;
3530  }
3531  else
3533 
3534  if (fPOT) fPOT->Fill();
3535 
3536 }
3537 
3539 {
3540  std::cout << "Analysing.\n\n";
3541  //services
3544 
3545  // collect the sizes which might me needed to resize the tree data structure:
3546  bool isMC = !evt.isRealData();
3547 
3548  // * hits
3549  std::vector<art::Ptr<recob::Hit> > hitlist;
3550  auto hitListHandle = evt.getHandle< std::vector<recob::Hit> >(fHitsModuleLabel);
3551  if (hitListHandle)
3552  art::fill_ptr_vector(hitlist, hitListHandle);
3553 
3554  // * clusters
3555  art::Handle< std::vector<recob::Cluster> > clusterListHandle;
3556  std::vector<art::Ptr<recob::Cluster> > clusterlist;
3557  if (fSaveClusterInfo){
3558  clusterListHandle = evt.getHandle< std::vector<recob::Cluster> >(fClusterModuleLabel);
3559  if (clusterListHandle)
3560  art::fill_ptr_vector(clusterlist, clusterListHandle);
3561  }
3562 
3563  // * spacepoints
3564  art::Handle<std::vector<recob::SpacePoint>> spacepointListHandle;
3565  art::Handle<std::vector<recob::PointCharge>> pointchargeListHandle;
3567  std::cout << "Saving SpacepointSolver info.";
3568  spacepointListHandle = evt.getHandle<std::vector<recob::SpacePoint>>(fSpacePointSolverModuleLabel);
3569  pointchargeListHandle = evt.getHandle<std::vector<recob::PointCharge>>(fSpacePointSolverModuleLabel);
3570  if (spacepointListHandle->size() != pointchargeListHandle->size()) {
3571  throw cet::exception("tutorial::ReadSpacePointAndCnn")
3572  << "size of point and charge containers must be equal" << std::endl;
3573  }
3574  }
3575 
3576  // * flashes
3577  std::vector<art::Ptr<recob::OpFlash> > flashlist;
3578  auto flashListHandle = evt.getHandle< std::vector<recob::OpFlash> >(fOpFlashModuleLabel);
3579  if (flashListHandle)
3580  art::fill_ptr_vector(flashlist, flashListHandle);
3581 
3582  // * External Counters
3583  std::vector<art::Ptr<raw::ExternalTrigger> > countlist;
3584  auto countListHandle = evt.getHandle< std::vector<raw::ExternalTrigger> >(fExternalCounterModuleLabel);
3585  if (countListHandle)
3586  art::fill_ptr_vector(countlist, countListHandle);
3587 
3588  // * MC truth information
3589  art::Handle< std::vector<simb::MCTruth> > mctruthListHandle;
3590  std::vector<art::Ptr<simb::MCTruth> > mclist;
3591  if (isMC){
3592  mctruthListHandle = evt.getHandle< std::vector<simb::MCTruth> >(fGenieGenModuleLabel);
3593  if (mctruthListHandle)
3594  art::fill_ptr_vector(mclist, mctruthListHandle);
3595  }
3596 
3597  // *MC truth cosmic generator information
3598  art::Handle< std::vector<simb::MCTruth> > mctruthcryListHandle;
3599  std::vector<art::Ptr<simb::MCTruth> > mclistcry;
3600  if (isMC && fSaveCryInfo){
3601  mctruthcryListHandle = evt.getHandle< std::vector<simb::MCTruth> >(fCryGenModuleLabel);
3602  if (mctruthcryListHandle) {
3603  art::fill_ptr_vector(mclistcry, mctruthcryListHandle);
3604  }
3605  else{
3606  // If we requested this info but it doesn't exist, don't use it.
3607  fSaveCryInfo = false;
3608  mf::LogError("AnalysisTree") << "Requested CRY information but none exists, hence not saving CRY information.";
3609  }
3610  }
3611 
3612  // ProtoDUNE beam generator information
3613  art::Handle< std::vector<simb::MCTruth> > mctruthprotoListHandle;
3614  std::vector<art::Ptr<simb::MCTruth> > mclistproto;
3615  if (isMC && fSaveProtoInfo){
3616  mctruthprotoListHandle = evt.getHandle< std::vector<simb::MCTruth> >(fProtoGenModuleLabel);
3617  if (mctruthprotoListHandle) {
3618  art::fill_ptr_vector(mclistproto,mctruthprotoListHandle);
3619  }
3620  else{
3621  // If we requested this info but it doesn't exist, don't use it.
3622  fSaveProtoInfo = false;
3623  mf::LogError("AnalysisTree") << "Requested protoDUNE beam generator information but none exists, hence not saving protoDUNE beam generator information.";
3624  }
3625  }
3626 
3627  // *MC Shower information
3629  if (isMC)
3630  mcshowerh = evt.getHandle< std::vector<sim::MCShower> >(fMCShowerModuleLabel);
3631 
3632  int nMCShowers = 0;
3633  if (fSaveMCShowerInfo && mcshowerh.isValid())
3634  nMCShowers = mcshowerh->size();
3635 
3636  // *MC Track information
3638  if (isMC)
3639  mctrackh = evt.getHandle< std::vector<sim::MCTrack> >(fMCTrackModuleLabel);
3640 
3641  int nMCTracks = 0;
3642  if (fSaveMCTrackInfo && mctrackh.isValid())
3643  nMCTracks = mctrackh->size();
3644 
3645  art::Ptr<simb::MCTruth> mctruthcry;
3646  int nCryPrimaries = 0;
3647 
3648  if (fSaveCryInfo){
3649  mctruthcry = mclistcry[0];
3650  nCryPrimaries = mctruthcry->NParticles();
3651  }
3652 
3653  art::Ptr<simb::MCTruth> mctruthproto;
3654  int nProtoPrimaries = 0;
3655  if( fSaveProtoInfo){
3656  mctruthproto = mclistproto[0];
3657  nProtoPrimaries = mctruthproto->NParticles();
3658  }
3659 
3660  int nGeniePrimaries = 0, nGEANTparticles = 0;
3661 
3662  art::Ptr<simb::MCTruth> mctruth;
3663 
3664 
3665  if (isMC) { //is MC
3666 
3667  //find origin
3668  auto const allmclists = evt.getMany<std::vector<simb::MCTruth>>();
3669  for(size_t mcl = 0; mcl < allmclists.size(); ++mcl){
3670  art::Handle< std::vector<simb::MCTruth> > mclistHandle = allmclists[mcl];
3671  for(size_t m = 0; m < mclistHandle->size(); ++m){
3672  art::Ptr<simb::MCTruth> mct(mclistHandle, m);
3673  if (mct->Origin() == simb::kCosmicRay) isCosmics = true;
3674  }
3675  }
3676  if (fSaveCaloCosmics) isCosmics = false; //override to save calo info
3677 
3678  // GENIE
3679  if (!mclist.empty()){//at least one mc record
3680 
3681  // double maxenergy = -1;
3682  // int imc0 = 0;
3683  // for (std::map<art::Ptr<simb::MCTruth>,double>::iterator ii=mctruthemap.begin(); ii!=mctruthemap.end(); ++ii){
3684  // if ((ii->second)>maxenergy){
3685  // maxenergy = ii->second;
3686  // mctruth = ii->first;
3687  // imc = imc0;
3688  // }
3689  // imc0++;
3690  // }
3691 
3692  //imc = 0; //set imc to 0 to solve a confusion for BNB+cosmic files where there are two MCTruth
3693  mctruth = mclist[0];
3694 
3695  if (mctruth->NeutrinoSet()) nGeniePrimaries = mctruth->NParticles();
3696  //} //end (fSaveGenieInfo)
3697 
3698  const sim::ParticleList& plist = pi_serv->ParticleList();
3699  nGEANTparticles = plist.size();
3700 
3701  // to know the number of particles in AV would require
3702  // looking at all of them; so we waste some memory here
3703  } // if have MC truth
3704  MF_LOG_DEBUG("AnalysisTree") << "Expected "
3705  << nGEANTparticles << " GEANT particles, "
3706  << nGeniePrimaries << " GENIE particles";
3707  } // if MC
3708 
3709  // SpacePointSolver information
3710  int nSpacePoints = 0;
3711  if (fSaveSpacePointSolverInfo && spacepointListHandle.isValid())
3712  nSpacePoints = spacepointListHandle->size();
3713 
3714  CreateData(); // tracker data is created with default constructor
3715  if (fSaveGenieInfo)
3716  fData->ResizeGenie(nGeniePrimaries);
3717  if (fSaveCryInfo)
3718  fData->ResizeCry(nCryPrimaries);
3719  if (fSaveProtoInfo)
3720  fData->ResizeProto(nProtoPrimaries);
3721  if (fSaveGeantInfo)
3722  fData->ResizeGEANT(nGEANTparticles);
3723  if (fSaveMCShowerInfo)
3724  fData->ResizeMCShower(nMCShowers);
3725  if (fSaveMCTrackInfo)
3726  fData->ResizeMCTrack(nMCTracks);
3728  fData->ResizeSpacePointSolver(nSpacePoints);
3729 
3730  fData->ClearLocalData(); // don't bother clearing tracker data yet
3731 
3732  const size_t NTrackers = GetNTrackers(); // number of trackers passed into fTrackModuleLabel
3733  const size_t NShowerAlgos = GetNShowerAlgos(); // number of shower algorithms into fShowerModuleLabel
3734  const size_t NHits = hitlist.size(); // number of hits
3735  const size_t NVertexAlgos = GetNVertexAlgos(); // number of vertex algos
3736  const size_t NClusters = clusterlist.size(); //number of clusters
3737  const size_t NFlashes = flashlist.size(); // number of flashes
3738  const size_t NExternCounts = countlist.size(); // number of External Counters
3739  // make sure there is the data, the tree and everything;
3740  CreateTree();
3741 
3742  /// transfer the run and subrun data to the tree data object
3743  // fData->RunData = RunData;
3744  fData->SubRunData = SubRunData;
3745 
3746  fData->isdata = int(!isMC);
3747 
3748  // * raw trigger
3749  std::vector<art::Ptr<raw::Trigger>> triggerlist;
3750  auto triggerListHandle = evt.getHandle< std::vector<raw::Trigger>>(fDigitModuleLabel);
3751  if (triggerListHandle)
3752  art::fill_ptr_vector(triggerlist, triggerListHandle);
3753 
3754  if (triggerlist.size()){
3755  fData->triggernumber = triggerlist[0]->TriggerNumber();
3756  fData->triggertime = triggerlist[0]->TriggerTime();
3757  fData->beamgatetime = triggerlist[0]->BeamGateTime();
3758  fData->triggerbits = triggerlist[0]->TriggerBits();
3759  }
3760 
3761  // * vertices
3762  std::vector< art::Handle< std::vector<recob::Vertex> > > vertexListHandle(NVertexAlgos);
3763  std::vector< std::vector<art::Ptr<recob::Vertex> > > vertexlist(NVertexAlgos);
3764  for (unsigned int it = 0; it < NVertexAlgos; ++it){
3765  vertexListHandle[it] = evt.getHandle< std::vector<recob::Vertex> >(fVertexModuleLabel[it]);
3766  if (vertexListHandle[it])
3767  art::fill_ptr_vector(vertexlist[it], vertexListHandle[it]);
3768  }
3769 
3770  // * PFParticles
3771  lar_pandora::PFParticleVector pfparticlelist;
3772  lar_pandora::PFParticlesToClusters pfParticleToClusterMap;
3773  lar_pandora::LArPandoraHelper::CollectPFParticles(evt, fPFParticleModuleLabel, pfparticlelist, pfParticleToClusterMap);
3774 
3775  // * tracks
3776  std::vector< art::Handle< std::vector<recob::Track> > > trackListHandle(NTrackers);
3777  std::vector< std::vector<art::Ptr<recob::Track> > > tracklist(NTrackers);
3778  for (unsigned int it = 0; it < NTrackers; ++it){
3779  trackListHandle[it] = evt.getHandle< std::vector<recob::Track> >(fTrackModuleLabel[it]);
3780  if (trackListHandle[it])
3781  art::fill_ptr_vector(tracklist[it], trackListHandle[it]);
3782  }
3783 
3784  // * showers
3785  // It seems that sometimes the shower data product does not exist;
3786  // in that case, we store a nullptr in place of the pointer to the vector;
3787  // the data structure itself is owned by art::Event and we should not try
3788  // to manage its memory
3789  std::vector<std::vector<recob::Shower> const*> showerList;
3790  std::vector< art::Handle< std::vector<recob::Shower> > > showerListHandle;
3791  showerList.reserve(fShowerModuleLabel.size());
3792  if (fSaveShowerInfo) {
3793  for (art::InputTag ShowerInputTag: fShowerModuleLabel) {
3794  auto ShowerHandle = evt.getHandle<std::vector<recob::Shower>>(ShowerInputTag);
3795  if (!ShowerHandle) {
3796  showerList.push_back(nullptr);
3797  if (!bIgnoreMissingShowers) {
3799  << "Showers with input tag '" << ShowerInputTag.encode()
3800  << "' were not found in the event."
3801  " If you really know what you are doing,"
3802  " set AnalysisTree's configuration parameter IgnoreMissingShowers"
3803  " to \"true\"; the lack of any shower set will be tolerated,"
3804  " and the shower list in the corresponding event will be set to"
3805  " a list of one shower, with an invalid ID.\n";
3806  } // if bIgnoreMissingShowers
3807  else {
3808  // this message is more alarming than strictly necessary; by design.
3809  mf::LogError("AnalysisTree")
3810  << "No showers found for input tag '" << ShowerInputTag.encode()
3811  << "' ; FILLING WITH FAKE DATA AS FOR USER'S REQUEST";
3812  }
3813  }
3814 
3815  else showerList.push_back(ShowerHandle.product());
3816 
3817  showerListHandle.push_back(ShowerHandle); // either way, put it into the handle list
3818 
3819  }
3820 
3821  } // for shower input tag
3822 
3823 
3824 
3825  std::vector<const sim::AuxDetSimChannel*> fAuxDetSimChannels;
3826  if (fSaveAuxDetInfo){
3827  evt.getView(fLArG4ModuleLabel, fAuxDetSimChannels);
3828  }
3829 
3830  std::vector<const sim::SimChannel*> fSimChannels;
3831  if (isMC && fSaveGeantInfo)
3832  evt.getView(fLArG4ModuleLabel, fSimChannels);
3833 
3834  fData->run = evt.run();
3835  fData->subrun = evt.subRun();
3836  fData->event = evt.id().event();
3837 
3838  art::Timestamp ts = evt.time();
3839  TTimeStamp tts(ts.timeHigh(), ts.timeLow());
3840  fData->evttime = tts.AsDouble();
3841 
3842  //copied from MergeDataPaddles.cxx
3843  auto beam = evt.getHandle< raw::BeamInfo >("beamdata");
3844  if (beam){
3845  fData->beamtime = (double)beam->get_t_ms();
3846  fData->beamtime/=1000.; //in second
3847  std::map<std::string, std::vector<double>> datamap = beam->GetDataMap();
3848  if (datamap["E:TOR860"].size()){
3849  fData->potbnb = datamap["E:TOR860"][0];
3850  }
3851  if (datamap["E:TORTGT"].size()){
3852  fData->potnumitgt = datamap["E:TORTGT"][0];
3853  }
3854  if (datamap["E:TOR101"].size()){
3855  fData->potnumi101 = datamap["E:TOR101"][0];
3856  }
3857  }
3858 
3859 
3860  // std::cout<<detProp.NumberTimeSamples()<<" "<<detProp.ReadOutWindowSize()<<std::endl;
3861  // std::cout<<geom->DetHalfHeight()*2<<" "<<geom->DetHalfWidth()*2<<" "<<geom->DetLength()<<std::endl;
3862  // std::cout<<geom->Nwires(0)<<" "<<geom->Nwires(1)<<" "<<geom->Nwires(2)<<std::endl;
3863  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
3864  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
3865 
3866  //hit information
3867  if (fSaveHitInfo){
3868  fData->no_hits = (int) NHits;
3869  fData->no_hits_stored = TMath::Min( (int) NHits, (int) kMaxHits);
3870  if (NHits > kMaxHits) {
3871  // got this error? consider increasing kMaxHits
3872  // (or ask for a redesign using vectors)
3873  mf::LogError("AnalysisTree:limits") << "event has " << NHits
3874  << " hits, only kMaxHits=" << kMaxHits << " stored in tree";
3875  }
3876  for (size_t i = 0; i < NHits && i < kMaxHits ; ++i){//loop over hits
3877  fData->hit_channel[i] = hitlist[i]->Channel();
3878  fData->hit_tpc[i] = hitlist[i]->WireID().TPC;
3879  fData->hit_plane[i] = hitlist[i]->WireID().Plane;
3880  fData->hit_wire[i] = hitlist[i]->WireID().Wire;
3881  fData->hit_peakT[i] = hitlist[i]->PeakTime();
3882  fData->hit_charge[i] = hitlist[i]->Integral();
3883  fData->hit_ph[i] = hitlist[i]->PeakAmplitude();
3884  fData->hit_startT[i] = hitlist[i]->PeakTimeMinusRMS();
3885  fData->hit_endT[i] = hitlist[i]->PeakTimePlusRMS();
3886  fData->hit_rms[i] = hitlist[i]->RMS();
3887  fData->hit_goodnessOfFit[i] = hitlist[i]->GoodnessOfFit();
3888  fData->hit_multiplicity[i] = hitlist[i]->Multiplicity();
3889  //std::vector<double> xyz = bt_serv->HitToXYZ(hitlist[i]);
3890  //when the size of simIDEs is zero, the above function throws an exception
3891  //and crashes, so check that the simIDEs have non-zero size before
3892  //extracting hit true XYZ from simIDEs
3893  if (isMC){
3894  std::vector<const sim::IDE*> ides;
3895  try{
3896  ides= bt_serv->HitToSimIDEs_Ps(clockData, hitlist[i]);
3897  }
3898  catch(...){}
3899  if (ides.size()>0){
3900  std::vector<double> xyz = bt_serv->SimIDEsToXYZ(ides);
3901  fData->hit_trueX[i] = xyz[0];
3902  }
3903  }
3904 
3905  /*
3906  for (unsigned int it=0; it<fTrackModuleLabel.size();++it){
3907  art::FindManyP<recob::Track> fmtk(hitListHandle,evt,fTrackModuleLabel[it]);
3908  if (fmtk.at(i).size()!=0){
3909  hit_trkid[it][i] = fmtk.at(i)[0]->ID();
3910  }
3911  else
3912  hit_trkid[it][i] = 0;
3913  }
3914  */
3915 
3916  if (fSaveRawDigitInfo){
3917  //Hit to RawDigit information
3918  art::FindManyP<raw::RawDigit> fmrd(hitListHandle,evt,fHitsModuleLabel);
3919  if (hitlist[i]->WireID().Plane==2)
3920  {
3921  int dataSize = fmrd.at(i)[0]->Samples();
3922  short ped = fmrd.at(i)[0]->GetPedestal();
3923 
3924  std::vector<short> rawadc(dataSize);
3925  raw::Uncompress(fmrd.at(i)[0]->ADCs(), rawadc, fmrd.at(i)[0]->Compression());
3926  int t0 = hitlist[i]->PeakTime() - 3*(hitlist[i]->RMS());
3927  if (t0<0) t0 = 0;
3928  int t1 = hitlist[i]->PeakTime() + 3*(hitlist[i]->RMS());
3929  if (t1>=dataSize) t1 = dataSize-1;
3930  fData->rawD_ph[i] = -1;
3931  fData->rawD_peakT[i] = -1;
3932  for (int j = t0; j<=t1; ++j){
3933  if (rawadc[j]-ped>fData->rawD_ph[i]){
3934  fData->rawD_ph[i] = rawadc[j]-ped;
3935  fData->rawD_peakT[i] = j;
3936  }
3937  }
3938  fData->rawD_charge[i] = 0;
3939  fData->rawD_fwhh[i] = 0;
3940  double mean_t = 0.0;
3941  double mean_t2 = 0.0;
3942  for (int j = t0; j<=t1; ++j){
3943  if (rawadc[j]-ped>=0.5*fData->rawD_ph[i]){
3944  ++fData->rawD_fwhh[i];
3945  }
3946  if (rawadc[j]-ped>=0.1*fData->rawD_ph[i]){
3947  fData->rawD_charge[i] += rawadc[j]-ped;
3948  mean_t += (double)j*(rawadc[j]-ped);
3949  mean_t2 += (double)j*(double)j*(rawadc[j]-ped);
3950  }
3951  }
3952  mean_t/=fData->rawD_charge[i];
3953  mean_t2/=fData->rawD_charge[i];
3954  fData->rawD_rms[i] = sqrt(mean_t2-mean_t*mean_t);
3955  }
3956  } // Save RawDigitInfo
3957 
3958  if (!evt.isRealData()&&!isCosmics){
3959  fData -> hit_nelec[i] = 0;
3960  fData -> hit_energy[i] = 0;
3961  const sim::SimChannel* chan = 0;
3962  for(size_t sc = 0; sc < fSimChannels.size(); ++sc){
3963  if(fSimChannels[sc]->Channel() == hitlist[i]->Channel()) chan = fSimChannels[sc];
3964  }
3965  if (chan){
3966  for(auto const& mapitr : chan->TDCIDEMap()){
3967  // loop over the vector of IDE objects.
3968  for(auto const& ide : mapitr.second){
3969  fData -> hit_nelec[i] += ide.numElectrons;
3970  fData -> hit_energy[i] += ide.energy;
3971  }
3972  }
3973  }
3974  }
3975  } // Loop over hits
3976 
3977  hitListHandle = evt.getHandle< std::vector<recob::Hit> >(fHitsModuleLabel);
3978  if (hitListHandle) {
3979  //Find tracks associated with hits
3980  art::FindManyP<recob::Track> fmtk(hitListHandle,evt,fTrackModuleLabel[0]);
3981  for (size_t i = 0; i < NHits && i < kMaxHits ; ++i){//loop over hits
3982  if (fmtk.isValid()){
3983  if (fmtk.at(i).size()!=0){
3984  fData->hit_trkid[i] = fmtk.at(i)[0]->ID();
3985  fData->hit_trkKey[i] = fmtk.at(i)[0].key();
3986 
3987  }
3988  else
3989  fData->hit_trkid[i] = -1;
3990  }
3991  }
3992  }
3993 
3994  //In the case of ClusterCrawler or linecluster, use "linecluster or clustercrawler" as HitModuleLabel.
3995  //using cchit will not make this association. In the case of gaushit, just use gaushit
3996  //Not initializing clusterID to -1 since some clustering algorithms assign negative IDs!
3997 
3998  hitListHandle = evt.getHandle< std::vector<recob::Hit> >(fHitsModuleLabel);
3999  if (hitListHandle) {
4000  //Find clusters and spacepoints associated with hits
4001  art::FindManyP<recob::Cluster> fmcl(hitListHandle,evt,fClusterModuleLabel);
4002  art::FindManyP<recob::SpacePoint> fmsp(hitListHandle,evt,fSpacePointSolverModuleLabel);
4003  for (size_t i = 0; i < NHits && i < kMaxHits ; ++i){//loop over hits
4004  if (fmcl.isValid() && fmcl.at(i).size()!=0){
4005  fData->hit_clusterid[i] = fmcl.at(i)[0]->ID();
4006  fData->hit_clusterKey[i] = fmcl.at(i)[0].key();
4007  // std::cout << "ClusterID " <<
4008  }
4009  if(fmsp.isValid() && fmsp.at(i).size()!=0){
4010  fData->hit_spacepointid[i] = fmsp.at(i)[0]->ID();
4011  fData->hit_spacepointKey[i] = fmsp.at(i)[0].key();
4012  }
4013  }
4014  }
4015  }// end (fSaveHitInfo)
4016 
4017 
4019  lar_pandora::PFParticleVector particleVector;
4021  lar_pandora::VertexVector vertexVector;
4022  lar_pandora::PFParticlesToVertices particlesToVertices;
4023  lar_pandora::LArPandoraHelper::CollectVertices(evt, fPandoraNuVertexModuleLabel, vertexVector, particlesToVertices);
4024 
4025  short nprim = 0;
4026  for (unsigned int n = 0; n < particleVector.size(); ++n) {
4027  const art::Ptr<recob::PFParticle> particle = particleVector.at(n);
4028  if(particle->IsPrimary()) nprim++;
4029  }
4030 
4031  if (nprim > kMaxVertices){
4032  // got this error? consider increasing kMaxClusters
4033  // (or ask for a redesign using vectors)
4034  mf::LogError("AnalysisTree:limits") << "event has " << nprim
4035  << " nu neutrino vertices, only kMaxVertices=" << kMaxVertices << " stored in tree";
4036  }
4037 
4038  fData->nnuvtx = nprim;
4039 
4040  short iv = 0;
4041  for (unsigned int n = 0; n < particleVector.size(); ++n) {
4042  const art::Ptr<recob::PFParticle> particle = particleVector.at(n);
4043  if(particle->IsPrimary()) {
4044  lar_pandora::PFParticlesToVertices::const_iterator vIter = particlesToVertices.find(particle);
4045  if (particlesToVertices.end() != vIter) {
4046  const lar_pandora::VertexVector &vertexVector = vIter->second;
4047  if (!vertexVector.empty()) {
4048  if (vertexVector.size() == 1) {
4049  const art::Ptr<recob::Vertex> vertex = *(vertexVector.begin());
4050  double xyz[3] = {0.0, 0.0, 0.0} ;
4051  vertex->XYZ(xyz);
4052  fData->nuvtxx[iv] = xyz[0];
4053  fData->nuvtxy[iv] = xyz[1];
4054  fData->nuvtxz[iv] = xyz[2];
4055  fData->nuvtxpdg[iv] = particle->PdgCode();
4056  iv++;
4057  }
4058  }
4059  }
4060  }
4061  }
4062  } // save PandoraNuVertexInfo
4063 
4064 
4065  if (fSaveClusterInfo){
4066  fData->nclusters = (int) NClusters;
4067  if (NClusters > kMaxClusters){
4068  // got this error? consider increasing kMaxClusters
4069  // (or ask for a redesign using vectors)
4070  mf::LogError("AnalysisTree:limits") << "event has " << NClusters
4071  << " clusters, only kMaxClusters=" << kMaxClusters << " stored in tree";
4072  }
4073  for(unsigned int ic=0; ic<NClusters;++ic){//loop over clusters
4074  art::Ptr<recob::Cluster> clusterholder(clusterListHandle, ic);
4075  const recob::Cluster& cluster = *clusterholder;
4076  fData->clusterId[ic] = cluster.ID();
4077  fData->clusterView[ic] = cluster.View();
4078  fData->cluster_isValid[ic] = cluster.isValid();
4079  fData->cluster_StartCharge[ic] = cluster.StartCharge();
4080  fData->cluster_StartAngle[ic] = cluster.StartAngle();
4081  fData->cluster_EndCharge[ic] = cluster.EndCharge();
4082  fData->cluster_EndAngle[ic] = cluster.EndAngle();
4083  fData->cluster_Integral[ic] = cluster.Integral();
4084  fData->cluster_IntegralAverage[ic] = cluster.IntegralAverage();
4085  fData->cluster_SummedADC[ic] = cluster.SummedADC();
4086  fData->cluster_SummedADCaverage[ic] = cluster.SummedADCaverage();
4087  fData->cluster_MultipleHitDensity[ic] = cluster.MultipleHitDensity();
4088  fData->cluster_Width[ic] = cluster.Width();
4089  fData->cluster_NHits[ic] = cluster.NHits();
4090  fData->cluster_StartWire[ic] = cluster.StartWire();
4091  fData->cluster_StartTick[ic] = cluster.StartTick();
4092  fData->cluster_EndWire[ic] = cluster.EndWire();
4093  fData->cluster_EndTick[ic] = cluster.EndTick();
4094 
4095  //Cosmic Tagger information for cluster
4096  art::FindManyP<anab::CosmicTag> fmcct(clusterListHandle,evt,fCosmicClusterTaggerAssocLabel);
4097  if (fmcct.isValid()){
4098  fData->cluncosmictags_tagger[ic] = fmcct.at(ic).size();
4099  if (fmcct.at(ic).size()>0){
4100  if(fmcct.at(ic).size()>1)
4101  std::cerr << "\n Warning : more than one cosmic tag per cluster in module! assigning the first tag to the cluster" << fCosmicClusterTaggerAssocLabel;
4102  fData->clucosmicscore_tagger[ic] = fmcct.at(ic).at(0)->CosmicScore();
4103  fData->clucosmictype_tagger[ic] = fmcct.at(ic).at(0)->CosmicType();
4104  }
4105  }
4106  }//end loop over clusters
4107  }//end fSaveClusterInfo
4108 
4110  fData->nspacepoints = (unsigned int) nSpacePoints;
4111 
4112  // Largely copied from Robert Sulej's ReadSpacePointAndCnn_module.cc
4113  if(fSaveCnnInfo) {
4115  if(cluResults) {
4116  size_t emLikeIdx = cluResults->getIndex("em"); // at which index EM-like is stored in CNN output vector
4117 
4118  const art::FindManyP<recob::Hit> hitsFromClusters(cluResults->dataHandle(), evt, cluResults->dataTag());
4119  const art::FindManyP<recob::SpacePoint> spFromHits(hitListHandle, evt, fSpacePointSolverModuleLabel);
4120 
4121  std::vector<size_t> sizeScore(nSpacePoints, 0); // keep track of the max size of a cluster containing hit associated to spacepoint
4122 
4123  for(size_t c = 0; c < cluResults->size(); ++c) {
4124  const std::vector< art::Ptr<recob::Hit> > & hits = hitsFromClusters.at(c);
4125  std::array<float, MVA_LENGTH> cnn_out = cluResults->getOutput(c);
4126 
4127  for (auto& hptr : hits) {
4128  const std::vector< art::Ptr<recob::SpacePoint> > & sp = spFromHits.at(hptr.key());
4129  for(const auto & spptr : sp) { // Should always be just one associated spacepoint
4130  if(hits.size() > sizeScore[spptr.key()]) {
4131  sizeScore[spptr.key()] = hits.size();
4132  fData->SpacePointEmScore[spptr.key()] = cnn_out[emLikeIdx];
4133  }
4134  } // Loop over associated spacepoints
4135  } // Loop over hits
4136  } // Loop over cluResults
4137  } // If cluResults
4138  }
4139 
4140  for (unsigned int is = 0; is < (unsigned int)nSpacePoints;
4141  ++is) { // loop over spacepoints
4142  fData->SpacePointX[is] = (*spacepointListHandle)[is].XYZ()[0];
4143  fData->SpacePointY[is] = (*spacepointListHandle)[is].XYZ()[1];
4144  fData->SpacePointZ[is] = (*spacepointListHandle)[is].XYZ()[2];
4145 
4146  fData->SpacePointQ[is] = (*pointchargeListHandle)[is].charge();
4147 
4148  fData->SpacePointErrX[is] = (*spacepointListHandle)[is].ErrXYZ()[0];
4149  fData->SpacePointErrY[is] = (*spacepointListHandle)[is].ErrXYZ()[1];
4150  fData->SpacePointErrZ[is] = (*spacepointListHandle)[is].ErrXYZ()[2];
4151 
4152  fData->SpacePointID[is] = (*spacepointListHandle)[is].ID();
4153 
4154  fData->SpacePointID[is] = (*spacepointListHandle)[is].Chisq();
4155  }//end loop over spacepoints
4156  }//end fSpacePointSolverInfo
4157 
4158  if (fSaveFlashInfo){
4159  fData->no_flashes = (int) NFlashes;
4160  if (NFlashes > kMaxFlashes) {
4161  // got this error? consider increasing kMaxHits
4162  // (or ask for a redesign using vectors)
4163  mf::LogError("AnalysisTree:limits") << "event has " << NFlashes
4164  << " flashes, only kMaxFlashes=" << kMaxFlashes << " stored in tree";
4165  }
4166 
4167  std::sort(flashlist.begin(), flashlist.end(), recob::OpFlashPtrSortByPE);
4168 
4169  for (size_t i = 0; i < NFlashes && i < kMaxFlashes ; ++i){//loop over hits
4170  fData->flash_time[i] = flashlist[i]->Time();
4171  fData->flash_pe[i] = flashlist[i]->TotalPE();
4172  fData->flash_ycenter[i] = flashlist[i]->YCenter();
4173  fData->flash_zcenter[i] = flashlist[i]->ZCenter();
4174  fData->flash_ywidth[i] = flashlist[i]->YWidth();
4175  fData->flash_zwidth[i] = flashlist[i]->ZWidth();
4176  fData->flash_timewidth[i] = flashlist[i]->TimeWidth();
4177  }
4178  }
4179 
4181  fData->no_ExternCounts = (int) NExternCounts;
4182  if (NExternCounts > kMaxExternCounts) {
4183  // got this error? consider increasing kMaxHits
4184  // (or ask for a redesign using vectors)
4185  mf::LogError("AnalysisTree:limits") << "event has " << NExternCounts
4186  << " External Counters, only kMaxExternCounts=" << kMaxExternCounts << " stored in tree";
4187  }
4188  for (size_t i = 0; i < NExternCounts && i < kMaxExternCounts ; ++i){//loop over hits
4189  fData->externcounts_time[i] = countlist[i]->GetTrigTime();
4190  fData->externcounts_id[i] = countlist[i]->GetTrigID();
4191  }
4192  }
4193 
4194 
4195  // Declare object-ID-to-PFParticleID maps so we can assign hasPFParticle and PFParticleID to the tracks, showers, vertices.
4196  std::map<Short_t, Short_t> trackIDtoPFParticleIDMap, vertexIDtoPFParticleIDMap, showerIDtoPFParticleIDMap;
4197 
4198  //Save PFParticle information
4199  if (fSavePFParticleInfo){
4200  AnalysisTreeDataStruct::PFParticleDataStruct& PFParticleData = fData->GetPFParticleData();
4201  size_t NPFParticles = pfparticlelist.size();
4202 
4203  PFParticleData.SetMaxPFParticles(std::max(NPFParticles, (size_t) 1));
4204  PFParticleData.Clear(); // clear all the data
4205 
4206  PFParticleData.nPFParticles = (short) NPFParticles;
4207 
4208  // now set the tree addresses to the newly allocated memory;
4209  // this creates the tree branches in case they are not there yet
4211 
4212  if (NPFParticles > PFParticleData.GetMaxPFParticles()) {
4213  mf::LogError("AnalysisTree:limits") << "event has " << NPFParticles
4214  << " PFParticles, only "
4215  << PFParticleData.GetMaxPFParticles() << " stored in tree";
4216  }
4217 
4218  lar_pandora::PFParticleVector neutrinoPFParticles;
4219  lar_pandora::LArPandoraHelper::SelectNeutrinoPFParticles(pfparticlelist, neutrinoPFParticles);
4220  PFParticleData.pfp_numNeutrinos = neutrinoPFParticles.size();
4221 
4222  for (size_t i = 0; i < std::min(neutrinoPFParticles.size(), (size_t)kMaxNPFPNeutrinos); ++i) {
4223  PFParticleData.pfp_neutrinoIDs[i] = neutrinoPFParticles[i]->Self();
4224  }
4225 
4226  if (neutrinoPFParticles.size() > kMaxNPFPNeutrinos)
4227  std::cerr << "Warning: there were " << neutrinoPFParticles.size() << " reconstructed PFParticle neutrinos; only the first " << kMaxNPFPNeutrinos << " being stored in tree" << std::endl;
4228 
4229  // Get a PFParticle-to-vertex map.
4230  lar_pandora::VertexVector allPfParticleVertices;
4231  lar_pandora::PFParticlesToVertices pfParticleToVertexMap;
4232  lar_pandora::LArPandoraHelper::CollectVertices(evt, fPFParticleModuleLabel, allPfParticleVertices, pfParticleToVertexMap);
4233 
4234  // Get a PFParticle-to-track map.
4235  lar_pandora::TrackVector allPfParticleTracks;
4236  lar_pandora::PFParticlesToTracks pfParticleToTrackMap;
4237  lar_pandora::LArPandoraHelper::CollectTracks(evt, fPFParticleModuleLabel, allPfParticleTracks, pfParticleToTrackMap);
4238 
4239  // Get a PFParticle-to-shower map.
4240  lar_pandora::ShowerVector allPfParticleShowers;
4241  lar_pandora::PFParticlesToShowers pfParticleToShowerMap;
4242  lar_pandora::LArPandoraHelper::CollectShowers(evt, fPFParticleModuleLabel, allPfParticleShowers, pfParticleToShowerMap);
4243 
4244  for (size_t i = 0; i < NPFParticles && i < PFParticleData.GetMaxPFParticles() ; ++i){
4245  PFParticleData.pfp_selfID[i] = pfparticlelist[i]->Self();
4246  PFParticleData.pfp_isPrimary[i] = (Short_t)pfparticlelist[i]->IsPrimary();
4247  PFParticleData.pfp_numDaughters[i] = pfparticlelist[i]->NumDaughters();
4248  PFParticleData.pfp_parentID[i] = pfparticlelist[i]->Parent();
4249  PFParticleData.pfp_pdgCode[i] = pfparticlelist[i]->PdgCode();
4250  PFParticleData.pfp_isNeutrino[i] = lar_pandora::LArPandoraHelper::IsNeutrino(pfparticlelist[i]);
4251 
4252  // Set the daughter IDs.
4253  std::vector<size_t> daughterIDs = pfparticlelist[i]->Daughters();
4254 
4255  for (size_t j = 0; j < daughterIDs.size(); ++j)
4256  PFParticleData.pfp_daughterIDs[i][j] = daughterIDs[j];
4257 
4258  // Set the vertex ID.
4259  auto vertexMapIter = pfParticleToVertexMap.find(pfparticlelist[i]);
4260  if (vertexMapIter != pfParticleToVertexMap.end()) {
4261  lar_pandora::VertexVector pfParticleVertices = vertexMapIter->second;
4262 
4263  if (pfParticleVertices.size() > 1)
4264  std::cerr << "Warning: there was more than one vertex found for PFParticle with ID " << pfparticlelist[i]->Self() << ", storing only one" << std::endl;
4265 
4266  if (pfParticleVertices.size() > 0) {
4267  PFParticleData.pfp_vertexID[i] = pfParticleVertices.at(0)->ID();
4268  vertexIDtoPFParticleIDMap.insert(std::make_pair(pfParticleVertices.at(0)->ID(), pfparticlelist[i]->Self()));
4269  }
4270  }
4271  else
4272  std::cerr << "Warning: there was no vertex found for PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4273 
4274  if (lar_pandora::LArPandoraHelper::IsTrack(pfparticlelist[i])){
4275  PFParticleData.pfp_isTrack[i] = 1;
4276 
4277  // Set the track ID.
4278  auto trackMapIter = pfParticleToTrackMap.find(pfparticlelist[i]);
4279  if (trackMapIter != pfParticleToTrackMap.end()) {
4280  lar_pandora::TrackVector pfParticleTracks = trackMapIter->second;
4281 
4282  if (pfParticleTracks.size() > 1)
4283  std::cerr << "Warning: there was more than one track found for PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4284 
4285  if (pfParticleTracks.size() > 0) {
4286  PFParticleData.pfp_trackID[i] = pfParticleTracks.at(0)->ID();
4287  trackIDtoPFParticleIDMap.insert(std::make_pair(pfParticleTracks.at(0)->ID(), pfparticlelist[i]->Self()));
4288  }
4289  }
4290  else
4291  std::cerr << "Warning: there was no track found for track-like PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4292  }
4293  else
4294  PFParticleData.pfp_isTrack[i] = 0;
4295 
4296  if (lar_pandora::LArPandoraHelper::IsShower(pfparticlelist[i])) {
4297  PFParticleData.pfp_isShower[i] = 1;
4298  // Set the shower ID.
4299  auto showerMapIter = pfParticleToShowerMap.find(pfparticlelist[i]);
4300  if (showerMapIter != pfParticleToShowerMap.end()) {
4301  lar_pandora::ShowerVector pfParticleShowers = showerMapIter->second;
4302 
4303  if (pfParticleShowers.size() > 1)
4304  std::cerr << "Warning: there was more than one shower found for PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4305 
4306  if (pfParticleShowers.size() > 0) {
4307  PFParticleData.pfp_showerID[i] = pfParticleShowers.at(0)->ID();
4308  showerIDtoPFParticleIDMap.insert(std::make_pair(pfParticleShowers.at(0)->ID(), pfparticlelist[i]->Self()));
4309  }
4310  }
4311  else
4312  std::cerr << "Warning: there was no shower found for shower-like PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4313  }
4314  else
4315  PFParticleData.pfp_isShower[i] = 0;
4316 
4317  // Set the cluster IDs.
4318  auto clusterMapIter = pfParticleToClusterMap.find(pfparticlelist[i]);
4319  if (clusterMapIter != pfParticleToClusterMap.end()) {
4320  lar_pandora::ClusterVector pfParticleClusters = clusterMapIter->second;
4321  PFParticleData.pfp_numClusters[i] = pfParticleClusters.size();
4322 
4323  for (size_t j = 0; j < pfParticleClusters.size(); ++j)
4324  PFParticleData.pfp_clusterIDs[i][j] = pfParticleClusters[j]->ID();
4325  }
4326  //else
4327  // std::cerr << "Warning: there were no clusters found for PFParticle with ID " << pfparticlelist[i]->Self() << std::endl;
4328  }
4329  } // if fSavePFParticleInfo
4330 
4331  if (fSaveShowerInfo){
4332 
4333  // fill data from all the shower algorithms
4334  for (size_t iShowerAlgo = 0; iShowerAlgo < NShowerAlgos; ++iShowerAlgo) {
4336  = fData->GetShowerData(iShowerAlgo);
4337  std::vector<recob::Shower> const* pShowers = showerList[iShowerAlgo];
4338  art::Handle< std::vector<recob::Shower> > showerHandle = showerListHandle[iShowerAlgo];
4339 
4340  if (pShowers){
4341  FillShowers(ShowerData, *pShowers, fSavePFParticleInfo, showerIDtoPFParticleIDMap);
4342 
4343  if(fMVAPIDShowerModuleLabel[iShowerAlgo].size()){
4344  art::FindOneP<anab::MVAPIDResult> fmvapid(showerHandle, evt, fMVAPIDShowerModuleLabel[iShowerAlgo]);
4345  if(fmvapid.isValid()){
4346  for(unsigned int iShower=0;iShower<showerHandle->size();++iShower){
4347  const art::Ptr<anab::MVAPIDResult> pid = fmvapid.at(iShower);
4348  ShowerData.shwr_pidmvamu[iShower] = pid->mvaOutput.at("muon");
4349  ShowerData.shwr_pidmvae[iShower] = pid->mvaOutput.at("electron");
4350  ShowerData.shwr_pidmvapich[iShower] = pid->mvaOutput.at("pich");
4351  ShowerData.shwr_pidmvaphoton[iShower] = pid->mvaOutput.at("photon");
4352  ShowerData.shwr_pidmvapr[iShower] = pid->mvaOutput.at("proton");
4353  }
4354  } // fmvapid.isValid()
4355  }
4356  }
4357  else ShowerData.MarkMissing(fTree); // tree should reflect lack of data
4358  } // for iShowerAlgo
4359 
4360  } // if fSaveShowerInfo
4361 
4362  //track information for multiple trackers
4363  if (fSaveTrackInfo) {
4364  for (unsigned int iTracker=0; iTracker < NTrackers; ++iTracker){
4365  AnalysisTreeDataStruct::TrackDataStruct& TrackerData = fData->GetTrackerData(iTracker);
4366 
4367  size_t NTracks = tracklist[iTracker].size();
4368  // allocate enough space for this number of tracks (but at least for one of them!)
4369  TrackerData.SetMaxTracks(std::max(NTracks, (size_t) 1));
4370  TrackerData.Clear(); // clear all the data
4371 
4372  TrackerData.ntracks = (int) NTracks;
4373 
4374  // now set the tree addresses to the newly allocated memory;
4375  // this creates the tree branches in case they are not there yet
4376  SetTrackerAddresses(iTracker);
4377  if (NTracks > TrackerData.GetMaxTracks()) {
4378  // got this error? it might be a bug,
4379  // since we are supposed to have allocated enough space to fit all tracks
4380  mf::LogError("AnalysisTree:limits") << "event has " << NTracks
4381  << " " << fTrackModuleLabel[iTracker] << " tracks, only "
4382  << TrackerData.GetMaxTracks() << " stored in tree";
4383  }
4384 
4385  //call the track momentum algorithm that gives you momentum based on track range
4386  // - Should the minimal track length be 50 cm? The default of 100 has been used.
4387  trkf::TrackMomentumCalculator trkm{/*100.*/};
4388 
4389  for(size_t iTrk=0; iTrk < NTracks; ++iTrk){//loop over tracks
4390 
4391  //save t0 from reconstructed flash track matching for every track
4392  art::FindManyP<anab::T0> fmt0(trackListHandle[iTracker],evt,fFlashT0FinderLabel[iTracker]);
4393  if (fmt0.isValid()){
4394  if(fmt0.at(iTrk).size()>0){
4395  if(fmt0.at(iTrk).size()>1)
4396  std::cerr << "\n Warning : more than one cosmic tag per track in module! assigning the first tag to the track" << fFlashT0FinderLabel[iTracker];
4397  TrackerData.trkflashT0[iTrk] = fmt0.at(iTrk).at(0)->Time();
4398  }
4399  }
4400 
4401  //save t0 from reconstructed flash track matching for every track
4402  art::FindManyP<anab::T0> fmmct0(trackListHandle[iTracker],evt,fMCT0FinderLabel[iTracker]);
4403  if (fmmct0.isValid()){
4404  if(fmmct0.at(iTrk).size()>0){
4405  if(fmmct0.at(iTrk).size()>1)
4406  std::cerr << "\n Warning : more than one cosmic tag per track in module! assigning the first tag to the cluster" << fMCT0FinderLabel[iTracker];
4407  TrackerData.trktrueT0[iTrk] = fmmct0.at(iTrk).at(0)->Time();
4408  }
4409  }
4410 
4411  //Cosmic Tagger information
4412  art::FindManyP<anab::CosmicTag> fmct(trackListHandle[iTracker],evt,fCosmicTaggerAssocLabel[iTracker]);
4413  if (fmct.isValid()){
4414  TrackerData.trkncosmictags_tagger[iTrk] = fmct.at(iTrk).size();
4415  if (fmct.at(iTrk).size()>0){
4416  if(fmct.at(iTrk).size()>1)
4417  std::cerr << "\n Warning : more than one cosmic tag per track in module! assigning the first tag to the track" << fCosmicTaggerAssocLabel[iTracker];
4418  TrackerData.trkcosmicscore_tagger[iTrk] = fmct.at(iTrk).at(0)->CosmicScore();
4419  TrackerData.trkcosmictype_tagger[iTrk] = fmct.at(iTrk).at(0)->CosmicType();
4420  }
4421  }
4422 
4423  //Containment Tagger information
4424  art::FindManyP<anab::CosmicTag> fmcnt(trackListHandle[iTracker],evt,fContainmentTaggerAssocLabel[iTracker]);
4425  if (fmcnt.isValid()){
4426  TrackerData.trkncosmictags_containmenttagger[iTrk] = fmcnt.at(iTrk).size();
4427  if (fmcnt.at(iTrk).size()>0){
4428  if(fmcnt.at(iTrk).size()>1)
4429  std::cerr << "\n Warning : more than one containment tag per track in module! assigning the first tag to the track" << fContainmentTaggerAssocLabel[iTracker];
4430  TrackerData.trkcosmicscore_containmenttagger[iTrk] = fmcnt.at(iTrk).at(0)->CosmicScore();
4431  TrackerData.trkcosmictype_containmenttagger[iTrk] = fmcnt.at(iTrk).at(0)->CosmicType();
4432  }
4433  }
4434 
4435  //Flash match compatibility information
4436  //Unlike CosmicTagger, Flash match doesn't assign a cosmic tag for every track. For those tracks, AnalysisTree initializes them with -9999 or -99999
4437  art::FindManyP<anab::CosmicTag> fmbfm(trackListHandle[iTracker],evt,fFlashMatchAssocLabel[iTracker]);
4438  if (fmbfm.isValid()){
4439  TrackerData.trkncosmictags_flashmatch[iTrk] = fmbfm.at(iTrk).size();
4440  if (fmbfm.at(iTrk).size()>0){
4441  if(fmbfm.at(iTrk).size()>1)
4442  std::cerr << "\n Warning : more than one cosmic tag per track in module! assigning the first tag to the track" << fFlashMatchAssocLabel[iTracker];
4443  TrackerData.trkcosmicscore_flashmatch[iTrk] = fmbfm.at(iTrk).at(0)->CosmicScore();
4444  TrackerData.trkcosmictype_flashmatch[iTrk] = fmbfm.at(iTrk).at(0)->CosmicType();
4445  //std::cout<<"\n"<<evt.event()<<"\t"<<iTrk<<"\t"<<fmbfm.at(iTrk).at(0)->CosmicScore()<<"\t"<<fmbfm.at(iTrk).at(0)->CosmicType();
4446  }
4447  }
4448 
4449  art::Ptr<recob::Track> ptrack(trackListHandle[iTracker], iTrk);
4450  const recob::Track& track = *ptrack;
4451 
4452  TVector3 pos, dir_start, dir_end, end;
4453 
4454  double tlen = 0., mom = 0.;
4455  int TrackID = -1;
4456 
4457  int ntraj = track.NumberTrajectoryPoints();
4458  if (ntraj > 0) {
4459  pos = track.Vertex<TVector3>();
4460  dir_start = track.VertexDirection<TVector3>();
4461  dir_end = track.EndDirection<TVector3>();
4462  end = track.End<TVector3>();
4463 
4464  tlen = track.Length();
4465  if(track.NumberTrajectoryPoints() > 0)
4466  mom = track.VertexMomentum();
4467  // fill non-bezier-track reco branches
4468  TrackID = track.ID();
4469 
4470  double theta_xz = std::atan2(dir_start.X(), dir_start.Z());
4471  double theta_yz = std::atan2(dir_start.Y(), dir_start.Z());
4472  double dpos = bdist(pos); // FIXME - Passing an uncorrected position....
4473  double dend = bdist(end); // FIXME - Passing an uncorrected position....
4474 
4475  TrackerData.trkId[iTrk] = TrackID;
4476  TrackerData.trkstartx[iTrk] = pos.X();
4477  TrackerData.trkstarty[iTrk] = pos.Y();
4478  TrackerData.trkstartz[iTrk] = pos.Z();
4479  TrackerData.trkstartd[iTrk] = dpos;
4480  TrackerData.trkendx[iTrk] = end.X();
4481  TrackerData.trkendy[iTrk] = end.Y();
4482  TrackerData.trkendz[iTrk] = end.Z();
4483  TrackerData.trkendd[iTrk] = dend;
4484  TrackerData.trktheta[iTrk] = dir_start.Theta();
4485  TrackerData.trkphi[iTrk] = dir_start.Phi();
4486  TrackerData.trkstartdcosx[iTrk] = dir_start.X();
4487  TrackerData.trkstartdcosy[iTrk] = dir_start.Y();
4488  TrackerData.trkstartdcosz[iTrk] = dir_start.Z();
4489  TrackerData.trkenddcosx[iTrk] = dir_end.X();
4490  TrackerData.trkenddcosy[iTrk] = dir_end.Y();
4491  TrackerData.trkenddcosz[iTrk] = dir_end.Z();
4492  TrackerData.trkthetaxz[iTrk] = theta_xz;
4493  TrackerData.trkthetayz[iTrk] = theta_yz;
4494  TrackerData.trkmom[iTrk] = mom;
4495  TrackerData.trklen[iTrk] = tlen;
4496  TrackerData.trkmomrange[iTrk] = trkm.GetTrackMomentum(tlen,13);
4497  //TrackerData.trkmommschi2[iTrk] = trkm.GetMomentumMultiScatterChi2(ptrack);
4498  //TrackerData.trkmommsllhd[iTrk] = trkm.GetMomentumMultiScatterLLHD(ptrack);
4499 
4500  if (fSavePFParticleInfo) {
4501  auto mapIter = trackIDtoPFParticleIDMap.find(TrackID);
4502  if (mapIter != trackIDtoPFParticleIDMap.end()) {
4503  // This track has a corresponding PFParticle.
4504  TrackerData.trkhasPFParticle[iTrk] = 1;
4505  TrackerData.trkPFParticleID[iTrk] = mapIter->second;
4506  }
4507  else
4508  TrackerData.trkhasPFParticle[iTrk] = 0;
4509  }
4510 
4511  } // if we have trajectory
4512 
4513  // find vertices associated with this track
4514  /*
4515  art::FindMany<recob::Vertex> fmvtx(trackListHandle[iTracker], evt, fVertexModuleLabel[iTracker]);
4516  if(fmvtx.isValid()) {
4517  std::vector<const recob::Vertex*> verts = fmvtx.at(iTrk);
4518  // should have two at most
4519  for(size_t ivx = 0; ivx < verts.size(); ++ivx) {
4520  verts[ivx]->XYZ(xyz);
4521  // find the vertex in TrackerData to get the index
4522  short theVtx = -1;
4523  for(short jvx = 0; jvx < TrackerData.nvtx; ++jvx) {
4524  if(TrackerData.vtx[jvx][2] == xyz[2]) {
4525  theVtx = jvx;
4526  break;
4527  }
4528  } // jvx
4529  // decide if it should be assigned to the track Start or End.
4530  // A simple dz test should suffice
4531  if(fabs(xyz[2] - TrackerData.trkstartz[iTrk]) <
4532  fabs(xyz[2] - TrackerData.trkendz[iTrk])) {
4533  TrackerData.trksvtxid[iTrk] = theVtx;
4534  } else {
4535  TrackerData.trkevtxid[iTrk] = theVtx;
4536  }
4537  } // vertices
4538  } // fmvtx.isValid()
4539  */
4540 
4541 
4542  /* //commented out because now have several Vertices
4543  Float_t minsdist = 10000;
4544  Float_t minedist = 10000;
4545  for (int ivx = 0; ivx < NVertices && ivx < kMaxVertices; ++ivx){
4546  Float_t sdist = sqrt(pow(TrackerData.trkstartx[iTrk]-VertexData.vtxx[ivx],2)+
4547  pow(TrackerData.trkstarty[iTrk]-VertexData.vtxy[ivx],2)+
4548  pow(TrackerData.trkstartz[iTrk]-VertexData.vtxz[ivx],2));
4549  Float_t edist = sqrt(pow(TrackerData.trkendx[iTrk]-VertexData.vtxx[ivx],2)+
4550  pow(TrackerData.trkendy[iTrk]-VertexData.vtxy[ivx],2)+
4551  pow(TrackerData.trkendz[iTrk]-VertexData.vtxz[ivx],2));
4552  if (sdist<minsdist){
4553  minsdist = sdist;
4554  if (minsdist<10) TrackerData.trksvtxid[iTrk] = ivx;
4555  }
4556  if (edist<minedist){
4557  minedist = edist;
4558  if (minedist<10) TrackerData.trkevtxid[iTrk] = ivx;
4559  }
4560  }*/
4561 
4562  // find particle ID info
4563  /*
4564  // Note from Jake Calcutt: There has been a breaking change in the definition
4565  // of the anab::ParticleID class. If you are using this class and want this info
4566  // in this tree, these must be updated
4567  art::FindMany<anab::ParticleID> fmpid(trackListHandle[iTracker], evt, fParticleIDModuleLabel[iTracker]);
4568  if(fmpid.isValid()) {
4569  std::vector<const anab::ParticleID*> pids = fmpid.at(iTrk);
4570  //if(pids.size() > 1) {
4571  //mf::LogError("AnalysisTree:limits")
4572  //<< "the " << fTrackModuleLabel[iTracker] << " track #" << iTrk
4573  //<< " has " << pids.size()
4574  //<< " set of ParticleID variables. Only one stored in the tree";
4575  //}
4576  for (size_t ipid = 0; ipid < pids.size(); ++ipid){
4577  if (!pids[ipid]->PlaneID().isValid) continue;
4578  int planenum = pids[ipid]->PlaneID().Plane;
4579  if (planenum<0||planenum>2) continue;
4580  TrackerData.trkpidpdg[iTrk][planenum] = pids[ipid]->Pdg();
4581  TrackerData.trkpidchi[iTrk][planenum] = pids[ipid]->MinChi2();
4582  TrackerData.trkpidchipr[iTrk][planenum] = pids[ipid]->Chi2Proton();
4583  TrackerData.trkpidchika[iTrk][planenum] = pids[ipid]->Chi2Kaon();
4584  TrackerData.trkpidchipi[iTrk][planenum] = pids[ipid]->Chi2Pion();
4585  TrackerData.trkpidchimu[iTrk][planenum] = pids[ipid]->Chi2Muon();
4586  TrackerData.trkpidpida[iTrk][planenum] = pids[ipid]->PIDA();
4587  }
4588  } // fmpid.isValid()
4589  */
4590  if(fMVAPIDTrackModuleLabel[iTracker].size()){
4591  art::FindOneP<anab::MVAPIDResult> fmvapid(trackListHandle[iTracker], evt, fMVAPIDTrackModuleLabel[iTracker]);
4592  if(fmvapid.isValid()) {
4593  const art::Ptr<anab::MVAPIDResult> pid = fmvapid.at(iTrk);
4594  TrackerData.trkpidmvamu[iTrk] = pid->mvaOutput.at("muon");
4595  TrackerData.trkpidmvae[iTrk] = pid->mvaOutput.at("electron");
4596  TrackerData.trkpidmvapich[iTrk] = pid->mvaOutput.at("pich");
4597  TrackerData.trkpidmvaphoton[iTrk] = pid->mvaOutput.at("photon");
4598  TrackerData.trkpidmvapr[iTrk] = pid->mvaOutput.at("proton");
4599  } // fmvapid.isValid()
4600  }
4601  art::FindMany<anab::Calorimetry> fmcal(trackListHandle[iTracker], evt, fCalorimetryModuleLabel[iTracker]);
4602  if (fmcal.isValid()){
4603  std::vector<const anab::Calorimetry*> calos = fmcal.at(iTrk);
4604  if (calos.size() > TrackerData.GetMaxPlanesPerTrack(iTrk)) {
4605  // if you get this message, there is probably a bug somewhere since
4606  // the calorimetry planes should be 3.
4607  mf::LogError("AnalysisTree:limits")
4608  << "the " << fTrackModuleLabel[iTracker] << " track #" << iTrk
4609  << " has " << calos.size() << " planes for calorimetry , only "
4610  << TrackerData.GetMaxPlanesPerTrack(iTrk) << " stored in tree";
4611  }
4612  for (size_t ical = 0; ical<calos.size(); ++ical){
4613  if (!calos[ical]) continue;
4614  if (!calos[ical]->PlaneID().isValid) continue;
4615  int planenum = calos[ical]->PlaneID().Plane;
4616  if (planenum<0||planenum>2) continue;
4617  TrackerData.trkke[iTrk][planenum] = calos[ical]->KineticEnergy();
4618  TrackerData.trkrange[iTrk][planenum] = calos[ical]->Range();
4619  //For now make the second argument as 13 for muons.
4620  TrackerData.trkpitchc[iTrk][planenum]= calos[ical] -> TrkPitchC();
4621  const size_t NHits = calos[ical] -> dEdx().size();
4622  TrackerData.ntrkhits[iTrk][planenum] = (int) NHits;
4623  if (NHits > TrackerData.GetMaxHitsPerTrack(iTrk, planenum)) {
4624  // if you get this error, you'll have to increase kMaxTrackHits
4625  mf::LogError("AnalysisTree:limits")
4626  << "the " << fTrackModuleLabel[iTracker] << " track #" << iTrk
4627  << " has " << NHits << " hits on calorimetry plane #" << planenum
4628  <<", only "
4629  << TrackerData.GetMaxHitsPerTrack(iTrk, planenum) << " stored in tree";
4630  }
4631  if (!isCosmics){
4632  for(size_t iTrkHit = 0; iTrkHit < NHits && iTrkHit < TrackerData.GetMaxHitsPerTrack(iTrk, planenum); ++iTrkHit) {
4633  TrackerData.trkdedx[iTrk][planenum][iTrkHit] = (calos[ical] -> dEdx())[iTrkHit];
4634  TrackerData.trkdqdx[iTrk][planenum][iTrkHit] = (calos[ical] -> dQdx())[iTrkHit];
4635  TrackerData.trkresrg[iTrk][planenum][iTrkHit] = (calos[ical] -> ResidualRange())[iTrkHit];
4636  TrackerData.trktpc[iTrk][planenum][iTrkHit] = (calos[ical] -> PlaneID()).TPC;
4637  const auto& TrkPos = (calos[ical] -> XYZ())[iTrkHit];
4638  auto& TrkXYZ = TrackerData.trkxyz[iTrk][planenum][iTrkHit];
4639  TrkXYZ[0] = TrkPos.X();
4640  TrkXYZ[1] = TrkPos.Y();
4641  TrkXYZ[2] = TrkPos.Z();
4642  } // for track hits
4643  }
4644  } // for calorimetry info
4645  if(TrackerData.ntrkhits[iTrk][0] > TrackerData.ntrkhits[iTrk][1] && TrackerData.ntrkhits[iTrk][0] > TrackerData.ntrkhits[iTrk][2]) TrackerData.trkpidbestplane[iTrk] = 0;
4646  else if(TrackerData.ntrkhits[iTrk][1] > TrackerData.ntrkhits[iTrk][0] && TrackerData.ntrkhits[iTrk][1] > TrackerData.ntrkhits[iTrk][2]) TrackerData.trkpidbestplane[iTrk] = 1;
4647  else if(TrackerData.ntrkhits[iTrk][2] > TrackerData.ntrkhits[iTrk][0] && TrackerData.ntrkhits[iTrk][2] > TrackerData.ntrkhits[iTrk][1]) TrackerData.trkpidbestplane[iTrk] = 2;
4648  else if(TrackerData.ntrkhits[iTrk][2] == TrackerData.ntrkhits[iTrk][0] && TrackerData.ntrkhits[iTrk][2] > TrackerData.ntrkhits[iTrk][1]) TrackerData.trkpidbestplane[iTrk] = 2;
4649  else if(TrackerData.ntrkhits[iTrk][2] == TrackerData.ntrkhits[iTrk][1] && TrackerData.ntrkhits[iTrk][2] > TrackerData.ntrkhits[iTrk][0]) TrackerData.trkpidbestplane[iTrk] = 2;
4650  else if(TrackerData.ntrkhits[iTrk][1] == TrackerData.ntrkhits[iTrk][0] && TrackerData.ntrkhits[iTrk][1] > TrackerData.ntrkhits[iTrk][2]) TrackerData.trkpidbestplane[iTrk] = 0;
4651  else if(TrackerData.ntrkhits[iTrk][1] == TrackerData.ntrkhits[iTrk][0] && TrackerData.ntrkhits[iTrk][1] == TrackerData.ntrkhits[iTrk][2]) TrackerData.trkpidbestplane[iTrk] = 2;
4652 
4653  // FIXME - Do i want to add someway to work out the best TPC???....
4654  } // if has calorimetry info
4655 
4656  //track truth information
4657  if (isMC){
4658  //get the hits on each plane
4659  art::FindManyP<recob::Hit> fmht(trackListHandle[iTracker], evt, fTrackModuleLabel[iTracker]);
4660  std::vector< art::Ptr<recob::Hit> > allHits = fmht.at(iTrk);
4661  std::vector< art::Ptr<recob::Hit> > hits[kNplanes];
4662 
4663  for(size_t ah = 0; ah < allHits.size(); ++ah){
4664  if (/* allHits[ah]->WireID().Plane >= 0 && */ // always true
4665  allHits[ah]->WireID().Plane < 3){
4666  hits[allHits[ah]->WireID().Plane].push_back(allHits[ah]);
4667  }
4668  }
4669  for (size_t ipl = 0; ipl < 3; ++ipl){
4670  double maxe = 0;
4671  HitsPurity(clockData, hits[ipl],TrackerData.trkidtruth[iTrk][ipl],TrackerData.trkpurtruth[iTrk][ipl],maxe);
4672  //std::cout<<"\n"<<iTracker<<"\t"<<iTrk<<"\t"<<ipl<<"\t"<<trkidtruth[iTracker][iTrk][ipl]<<"\t"<<trkpurtruth[iTracker][iTrk][ipl]<<"\t"<<maxe;
4673  if (TrackerData.trkidtruth[iTrk][ipl]>0){
4674  const art::Ptr<simb::MCTruth> mc = pi_serv->TrackIdToMCTruth_P(TrackerData.trkidtruth[iTrk][ipl]);
4675  TrackerData.trkorigin[iTrk][ipl] = mc->Origin();
4676  const simb::MCParticle *particle = pi_serv->TrackIdToParticle_P(TrackerData.trkidtruth[iTrk][ipl]);
4677  double tote = 0;
4678  const std::vector<const sim::IDE*> vide=bt_serv->TrackIdToSimIDEs_Ps(TrackerData.trkidtruth[iTrk][ipl]);
4679  for (auto ide: vide) {
4680  tote += ide->energy;
4681  }
4682  TrackerData.trkpdgtruth[iTrk][ipl] = particle->PdgCode();
4683  TrackerData.trkefftruth[iTrk][ipl] = maxe/(tote/kNplanes); //tote include both induction and collection energies
4684  //std::cout<<"\n"<<trkpdgtruth[iTracker][iTrk][ipl]<<"\t"<<trkefftruth[iTracker][iTrk][ipl];
4685  }
4686  }
4687 
4688  double maxe = 0;
4689  HitsPurity(clockData, allHits,TrackerData.trkg4id[iTrk],TrackerData.trkpurity[iTrk],maxe);
4690  if (TrackerData.trkg4id[iTrk]>0){
4691  const art::Ptr<simb::MCTruth> mc = pi_serv->TrackIdToMCTruth_P(TrackerData.trkg4id[iTrk]);
4692  TrackerData.trkorig[iTrk] = mc->Origin();
4693  }
4694  if (allHits.size()){
4695  std::vector<art::Ptr<recob::Hit> > all_hits;
4697  float totenergy = 0;
4698  if (evt.get(allHits[0].id(), hithandle)){
4699  art::fill_ptr_vector(all_hits, hithandle);
4700  for(size_t h = 0; h < all_hits.size(); ++h){
4701 
4702  art::Ptr<recob::Hit> hit = all_hits[h];
4703  std::vector<sim::IDE*> ides;
4704  //bt_serv->HitToSimIDEs(hit,ides);
4705  std::vector<sim::TrackIDE> eveIDs = bt_serv->HitToEveTrackIDEs(clockData, hit);
4706 
4707  for(size_t e = 0; e < eveIDs.size(); ++e){
4708  //std::cout<<h<<" "<<e<<" "<<eveIDs[e].trackID<<" "<<eveIDs[e].energy<<" "<<eveIDs[e].energyFrac<<std::endl;
4709  if (eveIDs[e].trackID==TrackerData.trkg4id[iTrk]) totenergy += eveIDs[e].energy;
4710  }
4711  }
4712  }
4713  if (totenergy) TrackerData.trkcompleteness[iTrk] = maxe/totenergy;
4714  }
4715  }//end if (isMC)
4716  }//end loop over track
4717  }//end loop over track module labels
4718  }// end (fSaveTrackInfo)
4719 
4720  /*trkf::TrackMomentumCalculator trkm;
4721  std::cout<<"\t"<<trkm.GetTrackMomentum(200,2212)<<"\t"<<trkm.GetTrackMomentum(-10, 13)<<"\t"<<trkm.GetTrackMomentum(300,-19)<<"\n";
4722  */
4723 
4724  //Save Vertex information for multiple algorithms
4725  if (fSaveVertexInfo){
4726  for (unsigned int iVertexAlg=0; iVertexAlg < NVertexAlgos; ++iVertexAlg){
4727  AnalysisTreeDataStruct::VertexDataStruct& VertexData = fData->GetVertexData(iVertexAlg);
4728 
4729  size_t NVertices = vertexlist[iVertexAlg].size();
4730 
4731  VertexData.SetMaxVertices(std::max(NVertices, (size_t) 1));
4732  VertexData.Clear(); // clear all the data
4733 
4734  VertexData.nvtx = (short) NVertices;
4735 
4736  // now set the tree addresses to the newly allocated memory;
4737  // this creates the tree branches in case they are not there yet
4738  SetVertexAddresses(iVertexAlg);
4739  if (NVertices > VertexData.GetMaxVertices()) {
4740  // got this error? it might be a bug,
4741  // since we are supposed to have allocated enough space to fit all tracks
4742  mf::LogError("AnalysisTree:limits") << "event has " << NVertices
4743  << " " << fVertexModuleLabel[iVertexAlg] << " tracks, only "
4744  << VertexData.GetMaxVertices() << " stored in tree";
4745  }
4746 
4747  for (size_t i = 0; i < NVertices && i < kMaxVertices ; ++i){//loop over hits
4748  VertexData.vtxId[i] = vertexlist[iVertexAlg][i]->ID();
4749  Double_t xyz[3] = {};
4750  vertexlist[iVertexAlg][i] -> XYZ(xyz);
4751  VertexData.vtxx[i] = xyz[0];
4752  VertexData.vtxy[i] = xyz[1];
4753  VertexData.vtxz[i] = xyz[2];
4754 
4755  if (fSavePFParticleInfo) {
4756  auto mapIter = vertexIDtoPFParticleIDMap.find(vertexlist[iVertexAlg][i]->ID());
4757  if (mapIter != vertexIDtoPFParticleIDMap.end()) {
4758  // This vertex has a corresponding PFParticle.
4759  VertexData.vtxhasPFParticle[i] = 1;
4760  VertexData.vtxPFParticleID[i] = mapIter->second;
4761  }
4762  else
4763  VertexData.vtxhasPFParticle[i] = 0;
4764  }
4765 
4766  // find PFParticle ID info
4767  art::FindMany<recob::PFParticle> fmPFParticle(vertexListHandle[iVertexAlg], evt, fPFParticleModuleLabel);
4768  if(fmPFParticle.isValid()) {
4769  std::vector<const recob::PFParticle*> pfparticles = fmPFParticle.at(i);
4770  if(pfparticles.size() > 1)
4771  std::cerr << "Warning: more than one associated PFParticle found for a vertex. Only one stored in tree." << std::endl;
4772  if (pfparticles.size() == 0)
4773  VertexData.vtxhasPFParticle[i] = 0;
4774  else {
4775  VertexData.vtxhasPFParticle[i] = 1;
4776  VertexData.vtxPFParticleID[i] = pfparticles.at(0)->Self();
4777  }
4778  } // fmPFParticle.isValid()
4779  }
4780  }
4781  }
4782 
4783  //mc truth information
4784  if (isMC){
4785 
4786  // Find the simb::MCFlux objects corresponding to
4787  // each simb::MCTruth object made by the generator with
4788  // the label fGenieGenModuleLabel
4789  art::FindOne<simb::MCFlux> find_mcflux(mctruthListHandle,
4791 
4792  if (fSaveCryInfo){
4793  //store cry (cosmic generator information)
4794  fData->mcevts_truthcry = mclistcry.size();
4795  fData->cry_no_primaries = nCryPrimaries;
4796  //fData->cry_no_primaries;
4797  for(Int_t iPartc = 0; iPartc < mctruthcry->NParticles(); ++iPartc){
4798  const simb::MCParticle& partc(mctruthcry->GetParticle(iPartc));
4799  fData->cry_primaries_pdg[iPartc]=partc.PdgCode();
4800  fData->cry_Eng[iPartc]=partc.E();
4801  fData->cry_Px[iPartc]=partc.Px();
4802  fData->cry_Py[iPartc]=partc.Py();
4803  fData->cry_Pz[iPartc]=partc.Pz();
4804  fData->cry_P[iPartc]=partc.P();
4805  fData->cry_StartPointx[iPartc] = partc.Vx();
4806  fData->cry_StartPointy[iPartc] = partc.Vy();
4807  fData->cry_StartPointz[iPartc] = partc.Vz();
4808  fData->cry_StartPointt[iPartc] = partc.T();
4809  fData->cry_status_code[iPartc]=partc.StatusCode();
4810  fData->cry_mass[iPartc]=partc.Mass();
4811  fData->cry_trackID[iPartc]=partc.TrackId();
4812  fData->cry_ND[iPartc]=partc.NumberDaughters();
4813  fData->cry_mother[iPartc]=partc.Mother();
4814  } // for cry particles
4815  }// end fSaveCryInfo
4816 
4817  // Save the protoDUNE beam generator information
4818  if(fSaveProtoInfo){
4819  fData->proto_no_primaries = nProtoPrimaries;
4820  for(Int_t iPartp = 0; iPartp < nProtoPrimaries; ++iPartp){
4821  const simb::MCParticle& partp(mctruthproto->GetParticle(iPartp));
4822 
4823  fData->proto_isGoodParticle[iPartp] = (partp.Process() == "primary");
4824  fData->proto_vx[iPartp] = partp.Vx();
4825  fData->proto_vy[iPartp] = partp.Vy();
4826  fData->proto_vz[iPartp] = partp.Vz();
4827  fData->proto_t[iPartp] = partp.T();
4828  fData->proto_px[iPartp] = partp.Px();
4829  fData->proto_py[iPartp] = partp.Py();
4830  fData->proto_pz[iPartp] = partp.Pz();
4831  fData->proto_momentum[iPartp] = partp.P();
4832  fData->proto_energy[iPartp] = partp.E();
4833  fData->proto_pdg[iPartp] = partp.PdgCode();
4834  // We will deal with the matching to GEANT later
4835  }
4836  }
4837 
4838  //save neutrino interaction information
4839  fData->mcevts_truth = mclist.size();
4840  if (fData->mcevts_truth > 0){//at least one mc record
4841  if (fSaveGenieInfo){
4842  int neutrino_i = 0;
4843  for(unsigned int iList = 0; (iList < mclist.size()) && (neutrino_i < kMaxTruth) ; ++iList){
4844  if (mclist[iList]->NeutrinoSet()){
4845  fData->nuPDG_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().PdgCode();
4846  fData->ccnc_truth[neutrino_i] = mclist[iList]->GetNeutrino().CCNC();
4847  fData->mode_truth[neutrino_i] = mclist[iList]->GetNeutrino().Mode();
4848  fData->Q2_truth[neutrino_i] = mclist[iList]->GetNeutrino().QSqr();
4849  fData->W_truth[neutrino_i] = mclist[iList]->GetNeutrino().W();
4850  fData->X_truth[neutrino_i] = mclist[iList]->GetNeutrino().X();
4851  fData->Y_truth[neutrino_i] = mclist[iList]->GetNeutrino().Y();
4852  fData->hitnuc_truth[neutrino_i] = mclist[iList]->GetNeutrino().HitNuc();
4853  fData->enu_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().E();
4854  fData->nuvtxx_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Vx();
4855  fData->nuvtxy_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Vy();
4856  fData->nuvtxz_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Vz();
4857  if (mclist[iList]->GetNeutrino().Nu().P()){
4858  fData->nu_dcosx_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Px()/mclist[iList]->GetNeutrino().Nu().P();
4859  fData->nu_dcosy_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Py()/mclist[iList]->GetNeutrino().Nu().P();
4860  fData->nu_dcosz_truth[neutrino_i] = mclist[iList]->GetNeutrino().Nu().Pz()/mclist[iList]->GetNeutrino().Nu().P();
4861  }
4862  fData->lep_mom_truth[neutrino_i] = mclist[iList]->GetNeutrino().Lepton().P();
4863  if (mclist[iList]->GetNeutrino().Lepton().P()){
4864  fData->lep_dcosx_truth[neutrino_i] = mclist[iList]->GetNeutrino().Lepton().Px()/mclist[iList]->GetNeutrino().Lepton().P();
4865  fData->lep_dcosy_truth[neutrino_i] = mclist[iList]->GetNeutrino().Lepton().Py()/mclist[iList]->GetNeutrino().Lepton().P();
4866  fData->lep_dcosz_truth[neutrino_i] = mclist[iList]->GetNeutrino().Lepton().Pz()/mclist[iList]->GetNeutrino().Lepton().P();
4867  }
4868 
4869  //flux information
4870  //
4871  // Double-check that a simb::MCFlux object is associated with the
4872  // current simb::MCTruth object. For GENIE events, these should
4873  // always accompany each other. Other generators (e.g., MARLEY) may
4874  // create simb::MCTruth objects without corresponding simb::MCFlux
4875  // objects. -- S. Gardiner
4876  if (find_mcflux.isValid()) {
4877  auto flux_maybe_ref = find_mcflux.at(iList);
4878  if (flux_maybe_ref.isValid()) {
4879  auto flux_ref = flux_maybe_ref.ref();
4880  fData->vx_flux[neutrino_i] = flux_ref.fvx;
4881  fData->vy_flux[neutrino_i] = flux_ref.fvy;
4882  fData->vz_flux[neutrino_i] = flux_ref.fvz;
4883  fData->pdpx_flux[neutrino_i] = flux_ref.fpdpx;
4884  fData->pdpy_flux[neutrino_i] = flux_ref.fpdpy;
4885  fData->pdpz_flux[neutrino_i] = flux_ref.fpdpz;
4886  fData->ppdxdz_flux[neutrino_i] = flux_ref.fppdxdz;
4887  fData->ppdydz_flux[neutrino_i] = flux_ref.fppdydz;
4888  fData->pppz_flux[neutrino_i] = flux_ref.fpppz;
4889 
4890  fData->ptype_flux[neutrino_i] = flux_ref.fptype;
4891  fData->ppvx_flux[neutrino_i] = flux_ref.fppvx;
4892  fData->ppvy_flux[neutrino_i] = flux_ref.fppvy;
4893  fData->ppvz_flux[neutrino_i] = flux_ref.fppvz;
4894  fData->muparpx_flux[neutrino_i] = flux_ref.fmuparpx;
4895  fData->muparpy_flux[neutrino_i] = flux_ref.fmuparpy;
4896  fData->muparpz_flux[neutrino_i] = flux_ref.fmuparpz;
4897  fData->mupare_flux[neutrino_i] = flux_ref.fmupare;
4898 
4899  fData->tgen_flux[neutrino_i] = flux_ref.ftgen;
4900  fData->tgptype_flux[neutrino_i] = flux_ref.ftgptype;
4901  fData->tgppx_flux[neutrino_i] = flux_ref.ftgppx;
4902  fData->tgppy_flux[neutrino_i] = flux_ref.ftgppy;
4903  fData->tgppz_flux[neutrino_i] = flux_ref.ftgppz;
4904  fData->tprivx_flux[neutrino_i] = flux_ref.ftprivx;
4905  fData->tprivy_flux[neutrino_i] = flux_ref.ftprivy;
4906  fData->tprivz_flux[neutrino_i] = flux_ref.ftprivz;
4907 
4908  fData->dk2gen_flux[neutrino_i] = flux_ref.fdk2gen;
4909  fData->gen2vtx_flux[neutrino_i] = flux_ref.fgen2vtx;
4910 
4911  fData->tpx_flux[neutrino_i] = flux_ref.ftpx;
4912  fData->tpy_flux[neutrino_i] = flux_ref.ftpy;
4913  fData->tpz_flux[neutrino_i] = flux_ref.ftpz;
4914  fData->tptype_flux[neutrino_i] = flux_ref.ftptype;
4915  } // flux_maybe_ref.isValid()
4916  } // find_mcflux.isValid()
4917  neutrino_i++;
4918  }//mclist is NeutrinoSet()
4919  }//loop over mclist
4920 
4921  if (mctruth->NeutrinoSet()){
4922  //genie particles information
4923  fData->genie_no_primaries = mctruth->NParticles();
4924 
4925  size_t StoreParticles = std::min((size_t) fData->genie_no_primaries, fData->GetMaxGeniePrimaries());
4926  if (fData->genie_no_primaries > (int) StoreParticles) {
4927  // got this error? it might be a bug,
4928  // since the structure should have enough room for everything
4929  mf::LogError("AnalysisTree:limits") << "event has "
4930  << fData->genie_no_primaries << " MC particles, only "
4931  << StoreParticles << " stored in tree";
4932  }
4933  for(size_t iPart = 0; iPart < StoreParticles; ++iPart){
4934  const simb::MCParticle& part(mctruth->GetParticle(iPart));
4935  fData->genie_primaries_pdg[iPart]=part.PdgCode();
4936  fData->genie_Eng[iPart]=part.E();
4937  fData->genie_Px[iPart]=part.Px();
4938  fData->genie_Py[iPart]=part.Py();
4939  fData->genie_Pz[iPart]=part.Pz();
4940  fData->genie_P[iPart]=part.P();
4941  fData->genie_status_code[iPart]=part.StatusCode();
4942  fData->genie_mass[iPart]=part.Mass();
4943  fData->genie_trackID[iPart]=part.TrackId();
4944  fData->genie_ND[iPart]=part.NumberDaughters();
4945  fData->genie_mother[iPart]=part.Mother();
4946  } // for particle
4947  //const simb::MCNeutrino& nu(mctruth->GetNeutrino());
4948  } //if neutrino set
4949  }// end (fSaveGenieInfo)
4950 
4951  //Extract MC Shower information and fill the Shower branches
4952  if (fSaveMCShowerInfo){
4953  fData->no_mcshowers = nMCShowers;
4954  size_t shwr = 0;
4955  for(std::vector<sim::MCShower>::const_iterator imcshwr = mcshowerh->begin();
4956  imcshwr != mcshowerh->end(); ++imcshwr) {
4957  const sim::MCShower& mcshwr = *imcshwr;
4958  fData->mcshwr_origin[shwr] = mcshwr.Origin();
4959  fData->mcshwr_pdg[shwr] = mcshwr.PdgCode();
4960  fData->mcshwr_TrackId[shwr] = mcshwr.TrackID();
4961  fData->mcshwr_Process[shwr] = mcshwr.Process();
4962  fData->mcshwr_startX[shwr] = mcshwr.Start().X();
4963  fData->mcshwr_startY[shwr] = mcshwr.Start().Y();
4964  fData->mcshwr_startZ[shwr] = mcshwr.Start().Z();
4965  fData->mcshwr_endX[shwr] = mcshwr.End().X();
4966  fData->mcshwr_endY[shwr] = mcshwr.End().Y();
4967  fData->mcshwr_endZ[shwr] = mcshwr.End().Z();
4968  if (mcshwr.DetProfile().E()!= 0){
4969  fData->mcshwr_isEngDeposited[shwr] = 1;
4970  fData->mcshwr_CombEngX[shwr] = mcshwr.DetProfile().X();
4971  fData->mcshwr_CombEngY[shwr] = mcshwr.DetProfile().Y();
4972  fData->mcshwr_CombEngZ[shwr] = mcshwr.DetProfile().Z();
4973  fData->mcshwr_CombEngPx[shwr] = mcshwr.DetProfile().Px();
4974  fData->mcshwr_CombEngPy[shwr] = mcshwr.DetProfile().Py();
4975  fData->mcshwr_CombEngPz[shwr] = mcshwr.DetProfile().Pz();
4976  fData->mcshwr_CombEngE[shwr] = mcshwr.DetProfile().E();
4977  fData->mcshwr_dEdx[shwr] = mcshwr.dEdx();
4978  fData->mcshwr_StartDirX[shwr] = mcshwr.StartDir().X();
4979  fData->mcshwr_StartDirY[shwr] = mcshwr.StartDir().Y();
4980  fData->mcshwr_StartDirZ[shwr] = mcshwr.StartDir().Z();
4981  }
4982  else
4983  fData->mcshwr_isEngDeposited[shwr] = 0;
4984  fData->mcshwr_Motherpdg[shwr] = mcshwr.MotherPdgCode();
4985  fData->mcshwr_MotherTrkId[shwr] = mcshwr.MotherTrackID();
4986  fData->mcshwr_MotherProcess[shwr] = mcshwr.MotherProcess();
4987  fData->mcshwr_MotherstartX[shwr] = mcshwr.MotherStart().X();
4988  fData->mcshwr_MotherstartY[shwr] = mcshwr.MotherStart().Y();
4989  fData->mcshwr_MotherstartZ[shwr] = mcshwr.MotherStart().Z();
4990  fData->mcshwr_MotherendX[shwr] = mcshwr.MotherEnd().X();
4991  fData->mcshwr_MotherendY[shwr] = mcshwr.MotherEnd().Y();
4992  fData->mcshwr_MotherendZ[shwr] = mcshwr.MotherEnd().Z();
4993  fData->mcshwr_Ancestorpdg[shwr] = mcshwr.AncestorPdgCode();
4994  fData->mcshwr_AncestorTrkId[shwr] = mcshwr.AncestorTrackID();
4995  fData->mcshwr_AncestorProcess[shwr] = mcshwr.AncestorProcess();
4996  fData->mcshwr_AncestorstartX[shwr] = mcshwr.AncestorStart().X();
4997  fData->mcshwr_AncestorstartY[shwr] = mcshwr.AncestorStart().Y();
4998  fData->mcshwr_AncestorstartZ[shwr] = mcshwr.AncestorStart().Z();
4999  fData->mcshwr_AncestorendX[shwr] = mcshwr.AncestorEnd().X();
5000  fData->mcshwr_AncestorendY[shwr] = mcshwr.AncestorEnd().Y();
5001  fData->mcshwr_AncestorendZ[shwr] = mcshwr.AncestorEnd().Z();
5002  ++shwr;
5003  }
5004  fData->mcshwr_Process.resize(shwr);
5005  fData->mcshwr_MotherProcess.resize(shwr);
5006  fData->mcshwr_AncestorProcess.resize(shwr);
5007  }//End if (fSaveMCShowerInfo){
5008 
5009  //Extract MC Track information and fill the Shower branches
5010  if (fSaveMCTrackInfo){
5011  fData->no_mctracks = nMCTracks;
5012  size_t trk = 0;
5013  for(std::vector<sim::MCTrack>::const_iterator imctrk = mctrackh->begin();imctrk != mctrackh->end(); ++imctrk) {
5014  const sim::MCTrack& mctrk = *imctrk;
5015  TLorentzVector tpcstart, tpcend, tpcmom;
5016  double plen = driftedLength(detProp, mctrk, tpcstart, tpcend, tpcmom);
5017  fData->mctrk_origin[trk] = mctrk.Origin();
5018  fData->mctrk_pdg[trk] = mctrk.PdgCode();
5019  fData->mctrk_TrackId[trk] = mctrk.TrackID();
5020  fData->mctrk_Process[trk] = mctrk.Process();
5021  fData->mctrk_startX[trk] = mctrk.Start().X();
5022  fData->mctrk_startY[trk] = mctrk.Start().Y();
5023  fData->mctrk_startZ[trk] = mctrk.Start().Z();
5024  fData->mctrk_endX[trk] = mctrk.End().X();
5025  fData->mctrk_endY[trk] = mctrk.End().Y();
5026  fData->mctrk_endZ[trk] = mctrk.End().Z();
5027  fData->mctrk_Motherpdg[trk] = mctrk.MotherPdgCode();
5028  fData->mctrk_MotherTrkId[trk] = mctrk.MotherTrackID();
5029  fData->mctrk_MotherProcess[trk] = mctrk.MotherProcess();
5030  fData->mctrk_MotherstartX[trk] = mctrk.MotherStart().X();
5031  fData->mctrk_MotherstartY[trk] = mctrk.MotherStart().Y();
5032  fData->mctrk_MotherstartZ[trk] = mctrk.MotherStart().Z();
5033  fData->mctrk_MotherendX[trk] = mctrk.MotherEnd().X();
5034  fData->mctrk_MotherendY[trk] = mctrk.MotherEnd().Y();
5035  fData->mctrk_MotherendZ[trk] = mctrk.MotherEnd().Z();
5036  fData->mctrk_Ancestorpdg[trk] = mctrk.AncestorPdgCode();
5037  fData->mctrk_AncestorTrkId[trk] = mctrk.AncestorTrackID();
5038  fData->mctrk_AncestorProcess[trk] = mctrk.AncestorProcess();
5039  fData->mctrk_AncestorstartX[trk] = mctrk.AncestorStart().X();
5040  fData->mctrk_AncestorstartY[trk] = mctrk.AncestorStart().Y();
5041  fData->mctrk_AncestorstartZ[trk] = mctrk.AncestorStart().Z();
5042  fData->mctrk_AncestorendX[trk] = mctrk.AncestorEnd().X();
5043  fData->mctrk_AncestorendY[trk] = mctrk.AncestorEnd().Y();
5044  fData->mctrk_AncestorendZ[trk] = mctrk.AncestorEnd().Z();
5045 
5046  fData->mctrk_len_drifted[trk] = plen;
5047 
5048  if (plen != 0){
5049  fData->mctrk_startX_drifted[trk] = tpcstart.X();
5050  fData->mctrk_startY_drifted[trk] = tpcstart.Y();
5051  fData->mctrk_startZ_drifted[trk] = tpcstart.Z();
5052  fData->mctrk_endX_drifted[trk] = tpcend.X();
5053  fData->mctrk_endY_drifted[trk] = tpcend.Y();
5054  fData->mctrk_endZ_drifted[trk] = tpcend.Z();
5055  fData->mctrk_p_drifted[trk] = tpcmom.Vect().Mag();
5056  fData->mctrk_px_drifted[trk] = tpcmom.X();
5057  fData->mctrk_py_drifted[trk] = tpcmom.Y();
5058  fData->mctrk_pz_drifted[trk] = tpcmom.Z();
5059  }
5060  ++trk;
5061  }
5062 
5063  fData->mctrk_Process.resize(trk);
5064  fData->mctrk_MotherProcess.resize(trk);
5065  fData->mctrk_AncestorProcess.resize(trk);
5066  }//End if (fSaveMCTrackInfo){
5067 
5068 
5069  //GEANT particles information
5070  if (fSaveGeantInfo){
5071 
5072  const sim::ParticleList& plist = pi_serv->ParticleList();
5073 
5074  std::string pri("primary");
5075  int primary=0;
5076  int active = 0;
5077  size_t geant_particle=0;
5078  sim::ParticleList::const_iterator itPart = plist.begin(),
5079  pend = plist.end(); // iterator to pairs (track id, particle)
5080 
5081  // helper map track ID => index
5082  std::map<int, size_t> TrackIDtoIndex;
5083  std::vector<int> gpdg;
5084  std::vector<int> gmother;
5085  for(size_t iPart = 0; (iPart < plist.size()) && (itPart != pend); ++iPart){
5086  const simb::MCParticle* pPart = (itPart++)->second;
5087  if (!pPart) {
5089  << "GEANT particle #" << iPart << " returned a null pointer";
5090  }
5091 
5092  //++geant_particle;
5093  bool isPrimary = pPart->Process() == pri;
5094  int TrackID = pPart->TrackId();
5095  TrackIDtoIndex.emplace(TrackID, iPart);
5096  gpdg.push_back(pPart->PdgCode());
5097  gmother.push_back(pPart->Mother());
5098  if (iPart < fData->GetMaxGEANTparticles()) {
5099  if (pPart->E()<fG4minE&&(!isPrimary)) continue;
5100  if (isPrimary) ++primary;
5101 
5102  TLorentzVector mcstart, mcend, mcstartdrifted, mcenddrifted;
5103  unsigned int pstarti, pendi, pstartdriftedi, penddriftedi; //mcparticle indices for starts and ends in tpc or drifted volumes
5104  double plen = length(*pPart, mcstart, mcend, pstarti, pendi);
5105  double plendrifted = driftedLength(detProp, *pPart, mcstartdrifted, mcenddrifted, pstartdriftedi, penddriftedi);
5106 
5107  bool isActive = plen != 0;
5108  bool isDrifted = plendrifted!= 0;
5109  if (plen) ++active;
5110 
5111  fData->process_primary[geant_particle] = int(isPrimary);
5112  fData->processname[geant_particle]= pPart->Process();
5113  fData->Mother[geant_particle]=pPart->Mother();
5114  fData->TrackId[geant_particle]=TrackID;
5115  fData->pdg[geant_particle]=pPart->PdgCode();
5116  fData->status[geant_particle] = pPart->StatusCode();
5117  fData->Eng[geant_particle]=pPart->E();
5118  fData->EndE[geant_particle]=pPart->EndE();
5119  fData->Mass[geant_particle]=pPart->Mass();
5120  fData->Px[geant_particle]=pPart->Px();
5121  fData->Py[geant_particle]=pPart->Py();
5122  fData->Pz[geant_particle]=pPart->Pz();
5123  fData->P[geant_particle]=pPart->Momentum().Vect().Mag();
5124  fData->StartPointx[geant_particle]=pPart->Vx();
5125  fData->StartPointy[geant_particle]=pPart->Vy();
5126  fData->StartPointz[geant_particle]=pPart->Vz();
5127  fData->StartT[geant_particle] = pPart->T();
5128  fData->EndPointx[geant_particle]=pPart->EndPosition()[0];
5129  fData->EndPointy[geant_particle]=pPart->EndPosition()[1];
5130  fData->EndPointz[geant_particle]=pPart->EndPosition()[2];
5131  fData->EndT[geant_particle] = pPart->EndT();
5132  fData->theta[geant_particle] = pPart->Momentum().Theta();
5133  fData->phi[geant_particle] = pPart->Momentum().Phi();
5134  fData->theta_xz[geant_particle] = std::atan2(pPart->Px(), pPart->Pz());
5135  fData->theta_yz[geant_particle] = std::atan2(pPart->Py(), pPart->Pz());
5136  fData->pathlen[geant_particle] = plen;
5137  fData->pathlen_drifted[geant_particle] = plendrifted;
5138  fData->NumberDaughters[geant_particle]=pPart->NumberDaughters();
5139  fData->inTPCActive[geant_particle] = int(isActive);
5140  fData->inTPCDrifted[geant_particle] = int(isDrifted);
5141  art::Ptr<simb::MCTruth> const& mc_truth = pi_serv->ParticleToMCTruth_P(pPart);
5142  if (mc_truth){
5143  fData->origin[geant_particle] = mc_truth->Origin();
5144  fData->MCTruthIndex[geant_particle] = mc_truth.key();
5145  }
5146  if (isActive){
5147  fData->StartPointx_tpcAV[geant_particle] = mcstart.X();
5148  fData->StartPointy_tpcAV[geant_particle] = mcstart.Y();
5149  fData->StartPointz_tpcAV[geant_particle] = mcstart.Z();
5150  fData->StartT_tpcAV[geant_particle] = mcstart.T();
5151  fData->StartE_tpcAV[geant_particle] = pPart->E(pstarti);
5152  fData->StartP_tpcAV[geant_particle] = pPart->P(pstarti);
5153  fData->StartPx_tpcAV[geant_particle] = pPart->Px(pstarti);
5154  fData->StartPy_tpcAV[geant_particle] = pPart->Py(pstarti);
5155  fData->StartPz_tpcAV[geant_particle] = pPart->Pz(pstarti);
5156  fData->EndPointx_tpcAV[geant_particle] = mcend.X();
5157  fData->EndPointy_tpcAV[geant_particle] = mcend.Y();
5158  fData->EndPointz_tpcAV[geant_particle] = mcend.Z();
5159  fData->EndT_tpcAV[geant_particle] = mcend.T();
5160  fData->EndE_tpcAV[geant_particle] = pPart->E(pendi);
5161  fData->EndP_tpcAV[geant_particle] = pPart->P(pendi);
5162  fData->EndPx_tpcAV[geant_particle] = pPart->Px(pendi);
5163  fData->EndPy_tpcAV[geant_particle] = pPart->Py(pendi);
5164  fData->EndPz_tpcAV[geant_particle] = pPart->Pz(pendi);
5165  }
5166  if (isDrifted){
5167  fData->StartPointx_drifted[geant_particle] = mcstartdrifted.X();
5168  fData->StartPointy_drifted[geant_particle] = mcstartdrifted.Y();
5169  fData->StartPointz_drifted[geant_particle] = mcstartdrifted.Z();
5170  fData->StartT_drifted[geant_particle] = mcstartdrifted.T();
5171  fData->StartE_drifted[geant_particle] = pPart->E(pstartdriftedi);
5172  fData->StartP_drifted[geant_particle] = pPart->P(pstartdriftedi);
5173  fData->StartPx_drifted[geant_particle] = pPart->Px(pstartdriftedi);
5174  fData->StartPy_drifted[geant_particle] = pPart->Py(pstartdriftedi);
5175  fData->StartPz_drifted[geant_particle] = pPart->Pz(pstartdriftedi);
5176  fData->EndPointx_drifted[geant_particle] = mcenddrifted.X();
5177  fData->EndPointy_drifted[geant_particle] = mcenddrifted.Y();
5178  fData->EndPointz_drifted[geant_particle] = mcenddrifted.Z();
5179  fData->EndT_drifted[geant_particle] = mcenddrifted.T();
5180  fData->EndE_drifted[geant_particle] = pPart->E(penddriftedi);
5181  fData->EndP_drifted[geant_particle] = pPart->P(penddriftedi);
5182  fData->EndPx_drifted[geant_particle] = pPart->Px(penddriftedi);
5183  fData->EndPy_drifted[geant_particle] = pPart->Py(penddriftedi);
5184  fData->EndPz_drifted[geant_particle] = pPart->Pz(penddriftedi);
5185  }
5186 
5187  //access auxiliary detector parameters
5188  if (fSaveAuxDetInfo) {
5189  unsigned short nAD = 0; // number of cells that particle hit
5190 
5191  // find deposit of this particle in each of the detector cells
5192  for (const sim::AuxDetSimChannel* c: fAuxDetSimChannels) {
5193 
5194  // find if this cell has a contribution (IDE) from this particle,
5195  // and which one
5196  const std::vector<sim::AuxDetIDE>& setOfIDEs = c->AuxDetIDEs();
5197  // using a C++ "lambda" function here; this one:
5198  // - sees only TrackID from the current scope
5199  // - takes one parameter: the AuxDetIDE to be tested
5200  // - returns if that IDE belongs to the track we are looking for
5202  = std::find_if(
5203  setOfIDEs.begin(), setOfIDEs.end(),
5204  [TrackID](const sim::AuxDetIDE& IDE){ return IDE.trackID == TrackID; }
5205  );
5206  if (iIDE == setOfIDEs.end()) continue;
5207 
5208  // now iIDE points to the energy released by the track #i (TrackID)
5209 
5210  // look for IDE with matching trackID
5211  // find trackIDs stored in setOfIDEs with the same trackID, but negative,
5212  // this is an untracked particle who's energy should be added as deposited by this original trackID
5213  float totalE = 0.; // total energy deposited around by the GEANT particle in this cell
5214  for(const auto& adtracks: setOfIDEs) {
5215  if( fabs(adtracks.trackID) == TrackID )
5216  totalE += adtracks.energyDeposited;
5217  } // for
5218 
5219  // fill the structure
5220  if (nAD < kMaxAuxDets) {
5221  fData->AuxDetID[geant_particle][nAD] = c->AuxDetID();
5222  fData->entryX[geant_particle][nAD] = iIDE->entryX;
5223  fData->entryY[geant_particle][nAD] = iIDE->entryY;
5224  fData->entryZ[geant_particle][nAD] = iIDE->entryZ;
5225  fData->entryT[geant_particle][nAD] = iIDE->entryT;
5226  fData->exitX[geant_particle][nAD] = iIDE->exitX;
5227  fData->exitY[geant_particle][nAD] = iIDE->exitY;
5228  fData->exitZ[geant_particle][nAD] = iIDE->exitZ;
5229  fData->exitT[geant_particle][nAD] = iIDE->exitT;
5230  fData->exitPx[geant_particle][nAD] = iIDE->exitMomentumX;
5231  fData->exitPy[geant_particle][nAD] = iIDE->exitMomentumY;
5232  fData->exitPz[geant_particle][nAD] = iIDE->exitMomentumZ;
5233  fData->CombinedEnergyDep[geant_particle][nAD] = totalE;
5234  }
5235  ++nAD;
5236  } // for aux det sim channels
5237  fData->NAuxDets[geant_particle] = nAD;
5238 
5239  if (nAD > kMaxAuxDets) {
5240  // got this error? consider increasing kMaxAuxDets
5241  mf::LogError("AnalysisTree:limits")
5242  << "particle #" << iPart
5243  << " touches " << nAD << " auxiliary detector cells, only "
5244  << kMaxAuxDets << " of them are saved in the tree";
5245  } // if too many detector cells
5246  } // if (fSaveAuxDetInfo)
5247 
5248  ++geant_particle;
5249  }
5250  else if (iPart == fData->GetMaxGEANTparticles()) {
5251  // got this error? it might be a bug,
5252  // since the structure should have enough room for everything
5253  mf::LogError("AnalysisTree:limits") << "event has "
5254  << plist.size() << " MC particles, only "
5255  << fData->GetMaxGEANTparticles() << " will be stored in tree";
5256  }
5257  } // for particles
5258 
5259  fData->geant_list_size_in_tpcAV = active;
5260  fData->no_primaries = primary;
5261  fData->geant_list_size = geant_particle;
5262  fData->processname.resize(geant_particle);
5263  MF_LOG_DEBUG("AnalysisTree")
5264  << "Counted "
5265  << fData->geant_list_size << " GEANT particles ("
5266  << fData->geant_list_size_in_tpcAV << " in AV), "
5267  << fData->no_primaries << " primaries, "
5268  << fData->genie_no_primaries << " GENIE particles";
5269 
5270  FillWith(fData->MergedId, 0);
5271 
5272  // for each particle, consider all the direct ancestors with the same
5273  // PDG ID, and mark them as belonging to the same "group"
5274  // (having the same MergedId)
5275  /* turn off for now
5276  int currentMergedId = 1;
5277  for(size_t iPart = 0; iPart < geant_particle; ++iPart){
5278  // if the particle already belongs to a group, don't bother
5279  if (fData->MergedId[iPart]) continue;
5280  // the particle starts its own group
5281  fData->MergedId[iPart] = currentMergedId;
5282  int currentMotherTrackId = fData->Mother[iPart];
5283  while (currentMotherTrackId > 0) {
5284  if (TrackIDtoIndex.find(currentMotherTrackId)==TrackIDtoIndex.end()) break;
5285  size_t gindex = TrackIDtoIndex[currentMotherTrackId];
5286  if (gindex<0||gindex>=plist.size()) break;
5287  // if the mother particle is of a different type,
5288  // don't bother with iPart ancestry any further
5289  if (gpdg[gindex]!=fData->pdg[iPart]) break;
5290  if (TrackIDtoIndex.find(currentMotherTrackId)!=TrackIDtoIndex.end()){
5291  size_t igeantMother = TrackIDtoIndex[currentMotherTrackId];
5292  if (igeantMother>=0&&igeantMother<geant_particle){
5293  fData->MergedId[igeantMother] = currentMergedId;
5294  }
5295  }
5296  currentMotherTrackId = gmother[gindex];
5297  }
5298  ++currentMergedId;
5299  }// for merging check
5300  */
5301  } // if (fSaveGeantInfo)
5302 
5303  // Now we have the GEANT info, see if we can match the protoDUNE generator particles
5304  if(fSaveProtoInfo){
5305  for(Int_t prt = 0; prt < nProtoPrimaries; ++prt){
5306  for(Int_t gnt = 0; gnt < fData->geant_list_size; ++gnt){
5307 // if(fData->proto_pdg[prt] == fData->pdg[gnt] && fData->proto_px[prt] == fData->Px[gnt]){
5308  if(fData->proto_pdg[prt] == fData->pdg[gnt] && std::fabs(fData->proto_px[prt] - fData->Px[gnt]) < 0.0001){
5309  fData->proto_geantTrackID[prt] = fData->TrackId[gnt];
5310  fData->proto_geantIndex[prt] = gnt;
5311  break;
5312  }
5313  } // End GEANT loop
5314  } // End protoDUNE generator loop
5315  } // End ProtoDUNE generator if statement
5316 
5317  }//if (mcevts_truth)
5318  }//if (isMC){
5319  fData->taulife = detProp.ElectronLifetime();
5320  fTree->Fill();
5321 
5322  if (mf::isDebugEnabled()) {
5323  // use mf::LogDebug instead of MF_LOG_DEBUG because we reuse it in many lines;
5324  // thus, we protect this part of the code with the line above
5325  mf::LogDebug logStream("AnalysisTreeStructure");
5326  logStream
5327  << "Tree data structure contains:"
5328  << "\n - " << fData->no_hits << " hits (" << fData->GetMaxHits() << ")"
5329  << "\n - " << fData->genie_no_primaries << " genie primaries (" << fData->GetMaxGeniePrimaries() << ")"
5330  << "\n - " << fData->geant_list_size << " GEANT particles (" << fData->GetMaxGEANTparticles() << "), "
5331  << fData->no_primaries << " primaries"
5332  << "\n - " << fData->geant_list_size_in_tpcAV << " GEANT particles in AV "
5333  << "\n - " << ((int) fData->kNTracker) << " trackers:"
5334  ;
5335 
5336  size_t iTracker = 0;
5337  for (auto tracker = fData->TrackData.cbegin();
5338  tracker != fData->TrackData.cend(); ++tracker, ++iTracker
5339  ) {
5340  logStream
5341  << "\n -> " << tracker->ntracks << " " << fTrackModuleLabel[iTracker]
5342  << " tracks (" << tracker->GetMaxTracks() << ")"
5343  ;
5344  for (int iTrk = 0; iTrk < tracker->ntracks; ++iTrk) {
5345  logStream << "\n [" << iTrk << "] "<< tracker->ntrkhits[iTrk][0];
5346  for (size_t ipl = 1; ipl < tracker->GetMaxPlanesPerTrack(iTrk); ++ipl)
5347  logStream << " + " << tracker->ntrkhits[iTrk][ipl];
5348  logStream << " hits (" << tracker->GetMaxHitsPerTrack(iTrk, 0);
5349  for (size_t ipl = 1; ipl < tracker->GetMaxPlanesPerTrack(iTrk); ++ipl)
5350  logStream << " + " << tracker->GetMaxHitsPerTrack(iTrk, ipl);
5351  logStream << ")";
5352  } // for tracks
5353  } // for trackers
5354  } // if logging enabled
5355 
5356 
5357  // if we don't use a permanent buffer (which can be huge),
5358  // delete the current buffer, and we'll create a new one on the next event
5359  if (!fUseBuffer) {
5360  MF_LOG_DEBUG("AnalysisTreeStructure") << "Freeing the tree data structure";
5361  DestroyData();
5362  }
5363 } // dune::AnalysisTree::analyze()
5364 
5365 
5367  recob::Shower const& shower, const bool fSavePFParticleInfo,
5368  const std::map<Short_t, Short_t> &showerIDtoPFParticleIDMap
5369  ) const {
5370 
5371  showerData.showerID[iShower] = shower.ID();
5372  showerData.shwr_bestplane[iShower] = shower.best_plane();
5373  showerData.shwr_length[iShower] = shower.Length();
5374 
5375  TVector3 const& dir_start = shower.Direction();
5376  showerData.shwr_startdcosx[iShower] = dir_start.X();
5377  showerData.shwr_startdcosy[iShower] = dir_start.Y();
5378  showerData.shwr_startdcosz[iShower] = dir_start.Z();
5379 
5380  TVector3 const& pos_start = shower.ShowerStart();
5381  showerData.shwr_startx[iShower] = pos_start.X();
5382  showerData.shwr_starty[iShower] = pos_start.Y();
5383  showerData.shwr_startz[iShower] = pos_start.Z();
5384 
5385  if (fSavePFParticleInfo) {
5386  auto mapIter = showerIDtoPFParticleIDMap.find(shower.ID());
5387  if (mapIter != showerIDtoPFParticleIDMap.end()) {
5388  // This vertex has a corresponding PFParticle.
5389  showerData.shwr_hasPFParticle[iShower] = 1;
5390  showerData.shwr_PFParticleID[iShower] = mapIter->second;
5391  }
5392  else
5393  showerData.shwr_hasPFParticle[iShower] = 0;
5394  }
5395 
5396  if (shower.Energy().size() == kNplanes)
5397  std::copy_n
5398  (shower.Energy().begin(), kNplanes, &showerData.shwr_totEng[iShower][0]);
5399  if (shower.dEdx().size() == kNplanes)
5400  std::copy_n
5401  (shower.dEdx().begin(), kNplanes, &showerData.shwr_dedx[iShower][0]);
5402  if (shower.MIPEnergy().size() == kNplanes)
5403  std::copy_n
5404  (shower.MIPEnergy().begin(), kNplanes, &showerData.shwr_mipEng[iShower][0]);
5405 
5406 } // dune::AnalysisTree::FillShower()
5407 
5408 
5410  std::vector<recob::Shower> const& showers, const bool fSavePFParticleInfo,
5411  const std::map<Short_t, Short_t> &showerIDtoPFParticleIDMap
5412  ) const {
5413 
5414  const size_t NShowers = showers.size();
5415 
5416  //
5417  // prepare the data structures, the tree and the connection between them
5418  //
5419 
5420  // allocate enough space for this number of showers
5421  // (but at least for one of them!)
5422  showerData.SetMaxShowers(std::max(NShowers, (size_t) 1));
5423  showerData.Clear(); // clear all the data
5424 
5425  // now set the tree addresses to the newly allocated memory;
5426  // this creates the tree branches in case they are not there yet
5427  showerData.SetAddresses(fTree);
5428  if (NShowers > showerData.GetMaxShowers()) {
5429  // got this error? it might be a bug,
5430  // since we are supposed to have allocated enough space to fit all showers
5431  mf::LogError("AnalysisTree:limits") << "event has " << NShowers
5432  << " " << showerData.Name() << " showers, only "
5433  << showerData.GetMaxShowers() << " stored in tree";
5434  }
5435 
5436  //
5437  // now set the data
5438  //
5439  // set the record of the number of showers
5440  // (data structures are already properly resized)
5441  showerData.nshowers = (Short_t) NShowers;
5442 
5443  // set all the showers one by one
5444  for (size_t i = 0; i < NShowers; ++i) FillShower(showerData, i, showers[i], fSavePFParticleInfo, showerIDtoPFParticleIDMap);
5445 
5446 } // dune::AnalysisTree::FillShowers()
5447 
5448 
5449 
5451  std::vector< art::Ptr<recob::Hit> > const& hits, Int_t& trackid, Float_t& purity, double& maxe){
5452 
5453  trackid = -1;
5454  purity = -1;
5455 
5457 
5458  std::map<int,double> trkide;
5459 
5460  for(size_t h = 0; h < hits.size(); ++h){
5461 
5462  art::Ptr<recob::Hit> hit = hits[h];
5463  std::vector<sim::IDE> ides;
5464  //bt_serv->HitToSimIDEs(hit,ides);
5465  std::vector<sim::TrackIDE> eveIDs = bt_serv->HitToEveTrackIDEs(clockData, hit);
5466 
5467  for(size_t e = 0; e < eveIDs.size(); ++e){
5468  //std::cout<<h<<" "<<e<<" "<<eveIDs[e].trackID<<" "<<eveIDs[e].energy<<" "<<eveIDs[e].energyFrac<<std::endl;
5469  trkide[eveIDs[e].trackID] += eveIDs[e].energy;
5470  }
5471  }
5472 
5473  maxe = -1;
5474  double tote = 0;
5475  for (std::map<int,double>::iterator ii = trkide.begin(); ii!=trkide.end(); ++ii){
5476  tote += ii->second;
5477  if ((ii->second)>maxe){
5478  maxe = ii->second;
5479  trackid = ii->first;
5480  }
5481  }
5482 
5483  //std::cout << "the total energy of this reco track is: " << tote << std::endl;
5484 
5485  if (tote>0){
5486  purity = maxe/tote;
5487  }
5488 }
5489 
5490 // Calculate distance to boundary.
5491 double dune::AnalysisTree::bdist(const TVector3& pos)
5492 {
5493  double d1 = -ActiveBounds[0] + pos.X();
5494  double d2 = ActiveBounds[1] - pos.X();
5495  double d3 = -ActiveBounds[2] + pos.Y();
5496  double d4 = ActiveBounds[3] - pos.Y();
5497  double d5 = -ActiveBounds[4] + pos.Z();
5498  double d6 = ActiveBounds[5] - pos.Z();
5499 
5500  double Xmin = std::min(d1, d2);
5501  double result = 0;
5502  if (Xmin<0) result = std::min(std::min(std::min( d3, d4), d5), d6); // - FIXME Passing uncorrected hits means X positions are very wrong ( outside of ActiveVolume )
5503  else result = std::min(std::min(std::min(std::min(Xmin, d3), d4), d5), d6);
5504  if (result<-1) result = -1;
5505  /*
5506  std::cout << "\n" << std::endl;
5507  std::cout << "-"<<ActiveBounds[0]<<" + "<<pos.X()<< " = " << d1 << "\n"
5508  << ActiveBounds[1]<<" - "<<pos.X()<< " = " << d2 << "\n"
5509  << "-"<<ActiveBounds[2]<<" + "<<pos.Y()<< " = " << d3 << "\n"
5510  << ActiveBounds[3]<<" - "<<pos.Y()<< " = " << d4 << "\n"
5511  << "-"<<ActiveBounds[4]<<" + "<<pos.Z()<< " = " << d5 << "\n"
5512  << ActiveBounds[5]<<" - "<<pos.Z()<< " = " << d6 << "\n"
5513  << "And the Minimum is " << result << std::endl;
5514  */
5515  return result;
5516 }
5517 
5518 // Length of reconstructed track, trajectory by trajectory.
5520 {
5521  return track.Length();
5522 }
5523 
5524 
5526  const sim::MCTrack& mctrack, TLorentzVector& tpcstart, TLorentzVector& tpcend, TLorentzVector& tpcmom){
5527  auto const* geom = lar::providerFrom<geo::Geometry>();
5528 
5529  //compute the drift x range
5530  double vDrift = detProp.DriftVelocity()*1e-3; //cm/ns
5531  double xrange[2] = {DBL_MAX, -DBL_MAX };
5532  for (unsigned int c=0; c<geom->Ncryostats(); ++c) {
5533  for (unsigned int t=0; t<geom->NTPC(c); ++t) {
5534  double Xat0 = detProp.ConvertTicksToX(0,0,t,c);
5535  double XatT = detProp.ConvertTicksToX(detProp.NumberTimeSamples(),0,t,c);
5536  xrange[0] = std::min(std::min(Xat0, XatT), xrange[0]);
5537  xrange[1] = std::max(std::max(Xat0, XatT), xrange[1]);
5538  }
5539  }
5540 
5541  double result = 0.;
5542  TVector3 disp;
5543  bool first = true;
5544 
5545  for(auto step: mctrack) {
5546  // check if the particle is inside a TPC
5547  if (step.X() >= ActiveBounds[0] && step.X() <= ActiveBounds[1] &&
5548  step.Y() >= ActiveBounds[2] && step.Y() <= ActiveBounds[3] &&
5549  step.Z() >= ActiveBounds[4] && step.Z() <= ActiveBounds[5] ){
5550  // Doing some manual shifting to account for
5551  // an interaction not occuring with the beam dump
5552  // we will reconstruct an x distance different from
5553  // where the particle actually passed to to the time
5554  // being different from in-spill interactions
5555  double newX = step.X()+(step.T()*vDrift);
5556  if (newX < xrange[0] || newX > xrange[1]) continue;
5557 
5558  TLorentzVector pos(newX,step.Y(),step.Z(),step.T());
5559  if(first){
5560  tpcstart = pos;
5561  tpcmom = step.Momentum();
5562  first = false;
5563  }
5564  else {
5565  disp -= pos.Vect();
5566  result += disp.Mag();
5567  }
5568  disp = pos.Vect();
5569  tpcend = pos;
5570  }
5571  }
5572  return result;
5573 }
5574 
5575 // Length of MC particle, trajectory by trajectory (with the manual shifting for x correction)
5577  const simb::MCParticle& p, TLorentzVector& start, TLorentzVector& end, unsigned int &starti, unsigned int &endi)
5578 {
5579  auto const* geom = lar::providerFrom<geo::Geometry>();
5580 
5581  //compute the drift x range
5582  double vDrift = detProp.DriftVelocity()*1e-3; //cm/ns
5583  double xrange[2] = {DBL_MAX, -DBL_MAX };
5584  for (unsigned int c=0; c<geom->Ncryostats(); ++c) {
5585  for (unsigned int t=0; t<geom->NTPC(c); ++t) {
5586  double Xat0 = detProp.ConvertTicksToX(0,0,t,c);
5587  double XatT = detProp.ConvertTicksToX(detProp.NumberTimeSamples(),0,t,c);
5588  xrange[0] = std::min(std::min(Xat0, XatT), xrange[0]);
5589  xrange[1] = std::max(std::max(Xat0, XatT), xrange[1]);
5590  }
5591  }
5592 
5593  double result = 0.;
5594  TVector3 disp;
5595  bool first = true;
5596 
5597  for(unsigned int i = 0; i < p.NumberTrajectoryPoints(); ++i) {
5598  // check if the particle is inside a TPC
5599  if (p.Vx(i) >= ActiveBounds[0] && p.Vx(i) <= ActiveBounds[1] &&
5600  p.Vy(i) >= ActiveBounds[2] && p.Vy(i) <= ActiveBounds[3] &&
5601  p.Vz(i) >= ActiveBounds[4] && p.Vz(i) <= ActiveBounds[5]){
5602  // Doing some manual shifting to account for
5603  // an interaction not occuring with the beam dump
5604  // we will reconstruct an x distance different from
5605  // where the particle actually passed to to the time
5606  // being different from in-spill interactions
5607  double newX = p.Vx(i)+(p.T(i)*vDrift);
5608  if (newX < xrange[0] || newX > xrange[1]) continue;
5609  TLorentzVector pos(newX,p.Vy(i),p.Vz(i),p.T());
5610  if(first){
5611  start = pos;
5612  starti=i;
5613  first = false;
5614  }
5615  else {
5616  disp -= pos.Vect();
5617  result += disp.Mag();
5618  }
5619  disp = pos.Vect();
5620  end = pos;
5621  endi = i;
5622  }
5623  }
5624  return result;
5625 }
5626 
5627 // Length of MC particle, trajectory by trajectory (with out the manual shifting for x correction)
5628 double dune::AnalysisTree::length(const simb::MCParticle& p, TLorentzVector& start, TLorentzVector& end, unsigned int &starti, unsigned int &endi)
5629 {
5630  double result = 0.;
5631  TVector3 disp;
5632  bool first = true;
5633 
5634  for(unsigned int i = 0; i < p.NumberTrajectoryPoints(); ++i) {
5635  // check if the particle is inside a TPC
5636  if (p.Vx(i) >= ActiveBounds[0] && p.Vx(i) <= ActiveBounds[1] && p.Vy(i) >= ActiveBounds[2] && p.Vy(i) <= ActiveBounds[3] && p.Vz(i) >= ActiveBounds[4] && p.Vz(i) <= ActiveBounds[5]){
5637  if(first){
5638  start = p.Position(i);
5639  first = false;
5640  starti = i;
5641  }else{
5642  disp -= p.Position(i).Vect();
5643  result += disp.Mag();
5644  }
5645  disp = p.Position(i).Vect();
5646  end = p.Position(i);
5647  endi = i;
5648  }
5649  }
5650  return result;
5651 }
5652 
5653 
5654 
5655 namespace dune{
5656 
5658 
5659 }
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
static QCString name
Definition: declinfo.cpp:673
double E(const int i=0) const
Definition: MCParticle.h:233
std::vector< Float_t > mctrk_p_drifted
int best_plane() const
Definition: Shower.h:200
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::vector< Int_t > mcshwr_AncestorTrkId
code to link reconstructed objects back to the MC truth information
void DestroyData()
Destroy the local buffers (existing branches will point to invalid address!)
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:36
intermediate_table::iterator iterator
std::vector< Float_t > mctrk_endZ_drifted
void endSubRun(const art::SubRun &sr)
std::vector< Float_t > cry_mass
std::vector< Int_t > mctrk_AncestorTrkId
bool fSaveRawDigitInfo
whether to extract and save Hit information
std::vector< Float_t > EndE_drifted
std::vector< Float_t > mcshwr_endX
bool hasPandoraNuVertexInfo() const
Returns whether we have Pandora Nu Vertex data.
std::vector< Float_t > StartPointy_tpcAV
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:218
void CreateTree(bool bClearData=false)
Create the output tree and the data structures, if needed.
constexpr int kMaxNDaughtersPerPFP
bool hasSpacePointSolverInfo() const
Returns whether we have SpacePointSolver data.
const VertexDataStruct & GetVertexData(size_t iVertex) const
const TVector3 & ShowerStart() const
Definition: Shower.h:192
size_t GetMaxGeniePrimaries() const
Returns the number of GENIE primaries for which memory is allocated.
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
Short_t pfp_numNeutrinos
the number of reconstructed neutrinos
std::vector< Float_t > SpacePointChisq
simb::Origin_t Origin() const
Definition: MCTrack.h:40
int PdgCode() const
Definition: MCParticle.h:212
std::vector< Float_t > mcshwr_MotherendY
constexpr std::uint32_t timeLow() const
Definition: Timestamp.h:29
std::vector< Float_t > mctrk_endY
std::vector< Float_t > mctrk_MotherstartX
PFParticleDataStruct(size_t maxPFParticles=0)
Creates a PFParticle data structure allowing up to maxPFParticles PFParticles.
double VertexMomentum() const
Definition: Track.h:142
double driftedLength(detinfo::DetectorPropertiesData const &detProp, const simb::MCParticle &part, TLorentzVector &start, TLorentzVector &end, unsigned int &starti, unsigned int &endi)
const MCStep & End() const
Definition: MCShower.h:56
ShowerData_t< Float_t > shwr_startx
startx of shower
double Py(const int i=0) const
Definition: MCParticle.h:231
float SummedADCaverage() const
Returns the average signal ADC counts of the cluster hits.
Definition: Cluster.h:656
int ntracks
Definition: tracks.py:246
float IntegralAverage() const
Returns the average charge of the cluster hits.
Definition: Cluster.h:622
std::vector< Float_t > EndPointy_drifted
bool fSavePFParticleInfo
whether to extract and save Shower information
std::vector< Float_t > genie_mass
std::vector< Float_t > SpacePointY
std::vector< Float_t > EndT_tpcAV
bool hasCnnInfo() const
Returns whether we have CNN data.
std::vector< Float_t > SpacePointQ
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:140
constexpr int kMaxTrackHits
double EndE() const
Definition: MCParticle.h:244
static QCString result
constexpr int kMaxNPFPNeutrinos
const TLorentzVector & EndPosition() const
Definition: MCParticle.h:225
std::vector< Float_t > EndPointx_drifted
std::vector< Float_t > mcshwr_startY
void SetAddresses(TTree *pTree, std::string tracker, bool isCosmics)
PFParticleDataStruct & GetPFParticleData()
std::vector< std::string > fCosmicTaggerAssocLabel
whether to extract and save CNN information
size_t MaxPFParticles
maximum number of storable PFParticles
AuxDetMCData_t< Float_t > entryX
Entry X position of particle into AuxDet.
std::vector< Float_t > EndPx_tpcAV
size_t GetNShowerAlgos() const
Returns the number of trackers for which data structures are allocated.
std::vector< Float_t > mctrk_AncestorendX
ShowerData_t< Float_t > shwr_startz
startz of shower
static constexpr size_t size()
begin/end interface
std::map< art::Ptr< recob::PFParticle >, ClusterVector > PFParticlesToClusters
double Length() const
Definition: Shower.h:201
PlaneData_t< Float_t > shwr_dedx
dE/dx of the shower per plane
ClusterData_t< Short_t > pfp_clusterIDs
the IDs of any associated clusters
A wrapper to a C array (needed to embed an array into a vector)
constexpr unsigned short kMaxAuxDets
max number of auxiliary detector cells per MC particle
unsigned int TrackID() const
Definition: MCShower.h:53
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
bool hasShowerInfo() const
Returns whether we have Shower data.
bool fSaveAuxDetInfo
whether to extract and save auxiliary detector data
std::vector< Float_t > EndPz_drifted
std::vector< Float_t > EndPy_tpcAV
bool hasProtoInfo() const
Returns whether we have protoDUNE beam primaries.
std::vector< Float_t > mctrk_endY_drifted
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
std::vector< Int_t > cry_status_code
unsigned int ID
void SetVertexAddresses(size_t iVertexAlg)
Creates a simple ROOT tree with tracking and calorimetry information.
void SetShowerAlgos(std::vector< std::string > const &ShowerAlgos)
Allocates data structures for the given number of trackers (no Clear())
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< Float_t > SpacePointErrY
const simb::MCParticle * TrackIdToParticle_P(int id) const
const std::string & AncestorProcess() const
Definition: MCTrack.h:57
PFParticleData_t< Short_t > pfp_showerID
the ID of the shower object corresponding to this PFParticle, if isShower
int Mother() const
Definition: MCParticle.h:213
std::vector< Float_t > mctrk_AncestorendZ
void SetShowerAddresses(size_t iShower)
AuxDetMCData_t< Float_t > exitX
Exit X position of particle out of AuxDet.
std::vector< Int_t > genie_trackID
constexpr std::uint32_t timeHigh() const
Definition: Timestamp.h:34
simb::Origin_t Origin() const
Definition: MCTruth.h:74
double Mass() const
Definition: MCParticle.h:239
TrackDataStruct()
Creates an empty tracker data structure.
void SetBits(unsigned int setbits, bool unset=false)
Sets the specified bits.
std::vector< Float_t > mctrk_pz_drifted
Geometry information for a single TPC.
Definition: TPCGeo.h:38
std::vector< Float_t > proto_energy
const std::vector< double > & Energy() const
Definition: Shower.h:195
unsigned int bits
complementary information
TrackDataStruct & GetTrackerData(size_t iTracker)
double Px(const int i=0) const
Definition: MCParticle.h:230
std::vector< Float_t > mcshwr_CombEngPx
std::vector< Float_t > StartT_drifted
std::vector< std::string > mctrk_Process
bool hasMCTrackInfo() const
Returns whether we have MCTrack data.
std::vector< Float_t > mctrk_AncestorstartZ
struct vector vector
AuxDetMCData_t< Short_t > AuxDetID
Which AuxDet this particle went through.
bool fSaveCaloCosmics
save calorimetry information for cosmics
std::vector< Float_t > StartPx_tpcAV
ChannelGroupService::Name Name
const MCStep & MotherEnd() const
Definition: MCTrack.h:53
unsigned int AncestorTrackID() const
Definition: MCTrack.h:56
std::vector< BoxedArray< T[kNplanes][kMaxTrackHits][3]>> HitCoordData_t
std::vector< Float_t > mctrk_AncestorstartX
bool hasMCShowerInfo() const
Returns whether we have MCShower data.
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:102
std::vector< Float_t > EndE_tpcAV
std::vector< std::string > mctrk_AncestorProcess
float StartWire() const
Returns the wire coordinate of the start of the cluster.
Definition: Cluster.h:286
std::string fSpacePointSolverModuleLabel
int PdgCode() const
Definition: MCShower.h:52
Vector_t VertexDirection() const
Definition: Track.h:132
std::vector< std::string > mcshwr_AncestorProcess
static bool IsShower(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as shower-like.
std::vector< Int_t > mcshwr_Ancestorpdg
VertexDataStruct & GetVertexData(size_t iVertex)
bool hasPFParticleInfo() const
Returns whether we have PFParticle data.
std::vector< Float_t > proto_vx
std::vector< std::string > fMVAPIDShowerModuleLabel
bool get(SelectorBase const &, Handle< PROD > &result) const
Definition: DataViewImpl.h:606
AuxDetMCData_t< Float_t > exitPz
Exit z momentum of particle out of AuxDet.
std::vector< const sim::IDE * > TrackIdToSimIDEs_Ps(int const &id) const
std::vector< Float_t > mcshwr_MotherstartX
std::vector< Float_t > proto_vy
double Mass(Resonance_t res)
resonance mass (GeV)
void SetTrackers(size_t nTrackers)
Allocates data structures for the given number of trackers (no Clear())
STL namespace.
int StatusCode() const
Definition: MCParticle.h:211
std::pair< float, std::string > P
Information about charge reconstructed in the active volume.
int PdgCode() const
Return the type of particle as a PDG ID.
Definition: PFParticle.h:83
TrackDataStruct(size_t maxTracks)
Creates a tracker data structure allowing up to maxTracks tracks.
std::vector< Float_t > cry_StartPointy
Set of hits with a 2D structure.
Definition: Cluster.h:71
std::vector< art::Ptr< recob::Shower > > ShowerVector
intermediate_table::const_iterator const_iterator
void ResizeGenie(int nPrimaries)
Resize the data strutcure for Genie primaries.
float EndTick() const
Returns the tick coordinate of the end of the cluster.
Definition: Cluster.h:342
std::vector< Float_t > mctrk_px_drifted
std::vector< Float_t > SpacePointX
bool hasVertexInfo() const
Returns whether we have Vertex data.
int NParticles() const
Definition: MCTruth.h:75
std::vector< Float_t > EndPointy_tpcAV
float MultipleHitDensity() const
Density of wires in the cluster with more than one hit.
Definition: Cluster.h:723
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Cluster finding and building.
ShowerData_t< Float_t > shwr_startdcosy
Y directional cosine at start of shower.
std::string Process() const
Definition: MCParticle.h:215
std::vector< Float_t > mcshwr_endY
std::vector< std::string > fContainmentTaggerAssocLabel
int AncestorPdgCode() const
Definition: MCTrack.h:55
ShowerData_t< Float_t > shwr_length
Shower length.
std::vector< std::string > mcshwr_MotherProcess
std::vector< Int_t > mctrk_Ancestorpdg
bool hasFlashInfo() const
Returns whether we have Flash data.
constexpr int kMaxExternCounts
bool isValid() const
Returns if the cluster is valid (that is, if its ID is not invalid)
Definition: Cluster.h:753
const MCStep & End() const
Definition: MCTrack.h:45
float StartAngle() const
Returns the starting angle of the cluster.
Definition: Cluster.h:475
ShowerData_t< Float_t > shwr_starty
starty of shower
std::vector< std::string > fMCT0FinderLabel
std::vector< Float_t > StartPointx_tpcAV
std::map< art::Ptr< recob::PFParticle >, TrackVector > PFParticlesToTracks
size_t GetMaxHits() const
Returns the number of hits for which memory is allocated.
std::vector< std::string > fVertexModuleLabel
int NumberDaughters() const
Definition: MCParticle.h:217
Class def header for mcstep data container.
std::vector< Float_t > mctrk_MotherendX
unsigned int MotherTrackID() const
Definition: MCTrack.h:50
std::vector< Float_t > StartPointz
void ResizeCry(int nPrimaries)
Resize the data strutcure for Cry primaries.
bool hasAuxDetector() const
Returns whether we have auxiliary detector data.
object containing MC flux information
art framework interface to geometry description
std::vector< Float_t > mctrk_AncestorstartY
AnalysisTreeDataStruct(size_t nTrackers=0, size_t nVertexAlgos=0, std::vector< std::string > const &ShowerAlgos={})
Constructor; clears all fields.
std::map< art::Ptr< recob::PFParticle >, VertexVector > PFParticlesToVertices
std::vector< Float_t > StartPz_drifted
int TrackId() const
Definition: MCParticle.h:210
std::vector< BoxedArray< T[kMaxNClustersPerPFP]>> ClusterData_t
total_extent<T>::value has the total number of elements of an array
std::vector< Int_t > proto_geantTrackID
std::vector< Float_t > mcshwr_startZ
std::vector< Float_t > mcshwr_AncestorstartX
std::vector< Float_t > mctrk_endX_drifted
std::vector< BoxedArray< T[kNplanes][kMaxShowerHits]>> HitData_t
void ClearLocalData()
Clear all fields if this object (not the tracker algorithm data)
ShowerDataStruct & GetShowerData(size_t iShower)
bool hasGenieInfo() const
Returns whether we have Genie data.
std::vector< Float_t > mcshwr_startX
void SetAddresses(TTree *pTree, std::string tracker, bool isCosmics)
void ResizeGEANT(int nParticles)
Resize the data strutcure for GEANT particles.
std::vector< Float_t > cry_Eng
constexpr int kMaxTrackers
QuadExpr operator-(double v, const QuadExpr &e)
Definition: QuadExpr.h:38
static constexpr value_type value
std::vector< Float_t > EndP_drifted
bool isValid() const noexcept
Definition: Handle.h:191
constexpr int kMaxVertexAlgos
bool hasCryInfo() const
Returns whether we have Cry data.
std::vector< std::string > fParticleIDModuleLabel
PlaneData_t< Float_t > shwr_mipEng
Total MIP energy of the shower per plane.
std::vector< Int_t > mcshwr_TrackId
std::vector< Int_t > mcshwr_isEngDeposited
std::vector< UShort_t > NAuxDets
Number of AuxDets crossed by this particle.
std::vector< std::string > fFlashT0FinderLabel
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
AuxDetMCData_t< Float_t > exitPx
Exit x momentum of particle out of AuxDet.
std::vector< Float_t > theta_xz
const TVector3 & StartDir() const
Definition: MCShower.h:82
PFParticleData_t< Short_t > pfp_selfID
the PFParticles&#39; own IDs
Collection of particles crossing one auxiliary detector cell.
std::vector< Float_t > mcshwr_MotherstartZ
std::vector< Float_t > StartPointz_tpcAV
void CheckData(std::string caller) const
Helper function: throws if no data structure is available.
DaughterData_t< Short_t > pfp_daughterIDs
the IDs of the daughter PFParticles
bool isRealData() const
size_t GetNTrackers() const
Returns the number of trackers for which data structures are allocated.
bool fSaveExternCounterInfo
whether to extract and save Flash information
AuxDetMCData_t< Float_t > CombinedEnergyDep
Sum energy of all particles with this trackID (+ID or -ID) in AuxDet.
std::vector< Float_t > SpacePointErrZ
float EndCharge() const
Returns the charge on the last wire of the cluster.
Definition: Cluster.h:498
std::vector< Float_t > StartPointy
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
PFParticleData_t< Short_t > pfp_isShower
whether this PFParticle corresponds to a shower
float SummedADC() const
Returns the total charge of the cluster from signal ADC counts.
Definition: Cluster.h:634
double bdist(const TVector3 &pos)
std::string fCosmicClusterTaggerAssocLabel
size_t GetMaxVertexAlgos() const
Returns the number of trackers for which memory is allocated.
simb::Origin_t Origin() const
Definition: MCShower.h:50
std::vector< Float_t > mcshwr_endZ
const double e
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:167
void ResizeSpacePointSolver(int nSpacePoints)
Resize the data structure for SpacePointSolver.
std::vector< Float_t > mcshwr_dEdx
std::map< art::Ptr< recob::PFParticle >, ShowerVector > PFParticlesToShowers
std::vector< std::string > fMVAPIDTrackModuleLabel
double Px() const
Definition: MCStep.h:46
std::vector< Float_t > mctrk_MotherendZ
PFParticleData_t< Short_t > pfp_numDaughters
the number of daughters belonging to this PFParticle
bool hasHitInfo() const
Returns whether we have Hit data.
std::remove_all_extents< Array_t >::type Data_t
Timestamp time() const
const std::vector< double > & dEdx() const
Definition: Shower.h:203
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
AnalysisTreeDataStruct::SubRunData_t SubRunData
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::vector< Float_t > EndPointx_tpcAV
const std::vector< double > & MIPEnergy() const
Definition: Shower.h:198
int MotherPdgCode() const
Definition: MCShower.h:58
void SetAddresses()
Sets the addresses of all the tree branches, creating the missing ones.
std::vector< Float_t > proto_vz
const std::string & AncestorProcess() const
Definition: MCShower.h:66
std::vector< Float_t > genie_Eng
std::vector< Int_t > proto_geantIndex
std::vector< Float_t > mcshwr_MotherstartY
std::vector< Float_t > mctrk_MotherendY
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
size_t GetMaxShowers() const
Returns the number of trackers for which memory is allocated.
std::vector< Float_t > StartPy_tpcAV
bool fSaveVertexInfo
whether to extract and save Track information
void Clear()
Clear all fields.
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
std::void_t< T > n
static void CollectShowers(const art::Event &evt, const std::string &label, ShowerVector &showerVector, PFParticlesToShowers &particlesToShowers)
Collect the reconstructed PFParticles and associated Showers from the ART event record.
std::vector< BoxedArray< T[kMaxNDaughtersPerPFP]>> DaughterData_t
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
std::vector< Float_t > StartP_tpcAV
double P(const int i=0) const
Definition: MCParticle.h:234
key_type key() const noexcept
Definition: Ptr.h:216
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::vector< Float_t > mcshwr_CombEngE
float Width() const
A measure of the cluster width, in homogenized units.
Definition: Cluster.h:727
size_t GetNShowerAlgos() const
Returns the number of shower algorithms configured.
void MarkMissing(TTree *pTree)
Applies a special prescription to mark shower information as missing.
Point_t const & Vertex() const
Definition: Track.h:124
static void CollectVertices(const art::Event &evt, const std::string &label, VertexVector &vertexVector, PFParticlesToVertices &particlesToVertices)
Collect the reconstructed PFParticles and associated Vertices from the ART event record.
std::string fPandoraNuVertexModuleLabel
std::vector< Float_t > mcshwr_AncestorendY
double T(const int i=0) const
Definition: MCParticle.h:224
void ResizeProto(int nPrimaries)
Resize the data structure for ProtoDUNE primaries.
double Z() const
Definition: MCStep.h:44
Little helper functor class to create or reset branches in a tree.
size_t MaxShowers
maximum number of storable showers
std::vector< Int_t > mcshwr_origin
std::vector< std::string > fCalorimetryModuleLabel
std::vector< Float_t > EndPointz
std::vector< Int_t > mcshwr_MotherTrkId
p
Definition: test.py:223
constexpr int kMaxClusters
struct recob::OpFlashPtrSortByPE_t OpFlashPtrSortByPE
bool fUseBuffer
whether to use a permanent buffer (faster, huge memory)
ShowerData_t< Short_t > shwr_bestplane
Shower best plane.
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
std::vector< Float_t > StartPointx
std::vector< std::string > mcshwr_Process
bool IsPrimary() const
Returns whether the particle is the root of the flow.
Definition: PFParticle.h:86
std::vector< BoxedArray< T[kNplanes][kMaxTrackHits]>> HitData_t
std::vector< Float_t > mcshwr_CombEngPz
bool isDebugEnabled()
bool hasTrackInfo() const
Returns whether we have Track data.
const TVector3 & Direction() const
Definition: Shower.h:189
CodeOutputInterface * code
double Py() const
Definition: MCStep.h:47
std::vector< Float_t > genie_Py
std::vector< Float_t > mctrk_len_drifted
double Y() const
Definition: MCStep.h:43
size_t GetMaxTrackers() const
Returns the number of trackers for which memory is allocated.
std::vector< Float_t > SpacePointZ
std::vector< art::Ptr< recob::Track > > TrackVector
std::vector< Float_t > StartE_tpcAV
const MCStep & AncestorStart() const
Definition: MCShower.h:67
RunNumber_t run() const
Definition: DataViewImpl.cc:71
static int max(int a, int b)
std::vector< Float_t > mctrk_startY_drifted
double EndT() const
Definition: MCParticle.h:229
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
size_t GetNVertexAlgos() const
std::vector< BoxedArray< T[kNplanes]>> PlaneData_t
ShowerData_t< Short_t > showerID
Shower ID.
constexpr int kNplanes
AuxDetMCData_t< Float_t > exitZ
Exit Z position of particle out of AuxDet.
std::string fPFParticleModuleLabel
Class def header for mctrack data container.
std::vector< Float_t > proto_t
const MCStep & AncestorStart() const
Definition: MCTrack.h:58
static void CollectTracks(const art::Event &evt, const std::string &label, TrackVector &trackVector, PFParticlesToTracks &particlesToTracks)
Collect the reconstructed PFParticles and associated Tracks from the ART event record.
bool fSaveProtoInfo
whether to extract and save Genie information
AuxDetMCData_t< Float_t > entryT
Entry T position of particle into AuxDet.
const std::string & MotherProcess() const
Definition: MCShower.h:60
PFParticleDataStruct PFParticleData
Definition of data types for geometry description.
std::vector< Float_t > StartPy_drifted
std::vector< Float_t > mcshwr_CombEngX
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
double dEdx() const
Definition: MCShower.h:81
bool fSaveTrackInfo
whether to extract and save Raw Digit information
size_t GetMaxGEANTparticles() const
Returns the number of GEANT particles for which memory is allocated.
bool fSaveClusterInfo
whether to extract and save Vertex information
unsigned int AncestorTrackID() const
Definition: MCShower.h:65
bool hasClusterInfo() const
Returns whether we have Cluster data.
std::vector< Float_t > StartPx_drifted
const MCStep & AncestorEnd() const
Definition: MCShower.h:68
int PdgCode() const
Definition: MCTrack.h:41
const MCStep & DetProfile() const
Definition: MCShower.h:70
Detector simulation of raw signals on wires.
std::vector< Int_t > mctrk_MotherTrkId
std::vector< Float_t > EndPointy
std::vector< Float_t > StartT_tpcAV
const sim::ParticleList & ParticleList() const
bool isCosmics
if it contains cosmics
double ConvertTicksToX(double ticks, int p, int t, int c) const
std::vector< Float_t > pathlen_drifted
std::vector< Float_t > mcshwr_AncestorendZ
void SetAddresses(TTree *pTree, std::vector< std::string > const &trackers, std::vector< std::string > const &vertexalgos, std::vector< std::string > const &showeralgos, bool isCosmics)
Connect this object with a tree.
static void SelectNeutrinoPFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select reconstructed neutrino particles from a list of all reconstructed particles.
Short_t nPFParticles
the total number of PFParticles
std::vector< std::string > fTrackModuleLabel
std::vector< Float_t > proto_pz
void SetVertexAlgos(size_t nVertexAlgos)
Allocates data structures for the given number of vertex algos (no Clear())
std::vector< Float_t > mcshwr_CombEngZ
bool fSavePandoraNuVertexInfo
whether to extract and save Cluster information
const MCStep & Start() const
Definition: MCShower.h:55
std::vector< Float_t > cry_StartPointz
std::vector< Float_t > mctrk_startZ
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::vector< Float_t > mcshwr_CombEngY
PFParticleData_t< Short_t > pfp_trackID
the ID of the track object corresponding to this PFParticle, if !isShower
std::string name
name of the shower algorithm (for branch names)
std::vector< Int_t > mcshwr_Motherpdg
constexpr int kMaxVertices
AuxDetMCData_t< Float_t > entryY
Entry Y position of particle into AuxDet.
double Vx(const int i=0) const
Definition: MCParticle.h:221
Class whose "type" contains the base data type of the container.
std::vector< Float_t > mcshwr_AncestorendX
int ID() const
Definition: Track.h:198
constexpr int kMaxHits
geo::View_t View() const
Returns the view for this cluster.
Definition: Cluster.h:741
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
Declaration of signal hit object.
const MCStep & MotherStart() const
Definition: MCTrack.h:52
ShowerData_t< Float_t > shwr_startdcosx
X directional cosine at start of shower.
void FillShower(AnalysisTreeDataStruct::ShowerDataStruct &showerData, size_t iShower, recob::Shower const &showers, const bool fSavePFParticleInfo, const std::map< Short_t, Short_t > &showerIDtoPFParticleIDMap) const
Stores the information of shower in slot iShower of showerData.
bool fSaveFlashInfo
whether to extract and save nu vertex information from Pandora
constexpr int kMaxNClustersPerPFP
std::vector< Float_t > EndPx_drifted
std::vector< Int_t > NumberDaughters
std::vector< Float_t > theta_yz
void ResizeMCTrack(int nMCTracks)
Resize the data strutcure for MC Tracks.
constexpr int kMaxFlashes
std::vector< Float_t > mctrk_endZ
PFParticleData_t< Int_t > pfp_pdgCode
the preliminary estimate of the PFParticle type using the PDG code
std::vector< Float_t > EndPointz_drifted
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
DoubleProduct operator+(DoubleProduct const &left, DoubleProduct const right)
Definition: ToyProducts.h:97
int MotherPdgCode() const
Definition: MCTrack.h:49
std::vector< Float_t > EndT_drifted
const MCStep & MotherEnd() const
Definition: MCShower.h:62
def fill(s)
Definition: translator.py:93
std::string fExternalCounterModuleLabel
std::vector< Float_t > mcshwr_MotherendX
Contains all timing reference information for the detector.
float StartCharge() const
Returns the charge on the first wire of the cluster.
Definition: Cluster.h:454
std::vector< Float_t > SpacePointEmScore
std::vector< BoxedArray< T[kNplanes]>> PlaneData_t
bool fSaveMCShowerInfo
whether to extract and save Geant information
bool fSaveMCTrackInfo
whether to extract and save MC Shower information
ID_t ID() const
Identifier of this cluster.
Definition: Cluster.h:738
std::vector< Float_t > StartPointx_drifted
AnalysisTree(fhicl::ParameterSet const &pset)
void analyze(const art::Event &evt)
read access to event
AuxDetMCData_t< Float_t > exitY
Exit Y position of particle out of AuxDet.
bool hasRawDigitInfo() const
Returns whether we have Hit data.
Vector_t EndDirection() const
Definition: Track.h:133
std::vector< Float_t > mcshwr_CombEngPy
std::vector< Int_t > proto_isGoodParticle
AuxDetMCData_t< Float_t > exitT
Exit T position of particle out of AuxDet.
size_t MaxTracks
maximum number of storable tracks
MC truth information to make RawDigits and do back tracking.
std::vector< Int_t > genie_status_code
SubRunData_t SubRunData
subrun data collected at begin of subrun
std::vector< sim::TrackIDE > HitToEveTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
std::vector< Float_t > EndPy_drifted
size_t GetNVertexAlgos() const
Returns the number of Vertex algos for which data structures are allocated.
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:220
const std::string & Process() const
Definition: MCTrack.h:43
def center(depos, point)
Definition: depos.py:117
const std::string & MotherProcess() const
Definition: MCTrack.h:51
std::vector< Float_t > EndPointz_tpcAV
static QCString type
Definition: declinfo.cpp:672
bool fSaveGeantInfo
whether to extract and save ProtDUNE beam simulation information
#define MF_LOG_DEBUG(id)
static bool IsTrack(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as track-like.
double Pz(const int i=0) const
Definition: MCParticle.h:232
std::vector< Float_t > mcshwr_StartDirZ
float fG4minE
Energy threshold to save g4 particle info.
Provides recob::Track data product.
void ResizeMCShower(int nMCShowers)
Resize the data strutcure for MC Showers.
size_t GetNTrackers() const
Returns the number of trackers configured.
void SetTrackerAddresses(size_t iTracker)
PFParticleData_t< Short_t > pfp_isNeutrino
whether this PFParticle is a neutrino
double E() const
Definition: MCStep.h:49
std::vector< Float_t > StartP_drifted
Class def header for MCShower data container.
PFParticleData_t< Short_t > pfp_vertexID
the ID of the vertex belonging to this PFParticle
unsigned int MotherTrackID() const
Definition: MCShower.h:59
double Vz(const int i=0) const
Definition: MCParticle.h:223
std::vector< double > SimIDEsToXYZ(std::vector< sim::IDE > const &ides) const
const std::string & Process() const
Definition: MCShower.h:54
ShowerDataStruct(std::string new_name="", size_t maxShowers=0)
Creates a shower data structure allowing up to maxShowers showers.
double Pz() const
Definition: MCStep.h:48
std::vector< art::Ptr< recob::Vertex > > VertexVector
std::vector< Int_t > process_primary
std::unique_ptr< AnalysisTreeDataStruct > fData
std::vector< Float_t > proto_px
AuxDetMCData_t< Float_t > exitPy
Exit y momentum of particle out of AuxDet.
bool bIgnoreMissingShowers
whether to ignore missing shower information
EventNumber_t event() const
Definition: EventID.h:116
Point_t const & End() const
Definition: Track.h:125
const MCStep & MotherStart() const
Definition: MCShower.h:61
Access the description of detector geometry.
std::vector< Float_t > StartPointy_drifted
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
bool fSaveCnnInfo
whether to extract and save SpacePointSolver information
const MCStep & Start() const
Definition: MCTrack.h:44
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:328
std::vector< std::string > processname
std::vector< Int_t > mctrk_Motherpdg
std::vector< Float_t > StartPz_tpcAV
std::vector< std::string > GetShowerAlgos() const
Returns the name of configured shower algorithms (converted to string)
std::vector< Int_t > cry_primaries_pdg
std::vector< Float_t > cry_StartPointt
bool hasGeantInfo() const
Returns whether we have Geant data.
std::vector< Int_t > genie_primaries_pdg
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
double X() const
Definition: MCStep.h:42
std::vector< Float_t > mctrk_MotherstartY
std::vector< const sim::IDE * > HitToSimIDEs_Ps(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
Definition: DataViewImpl.h:500
const TrackDataStruct & GetTrackerData(size_t iTracker) const
std::vector< Float_t > genie_Px
size_t MaxVertices
maximum number of storable vertices
constexpr int kMaxShowerHits
std::vector< Float_t > mctrk_endX
PFParticleData_t< Short_t > pfp_numClusters
the number of associated clusters
std::vector< Float_t > StartPointz_drifted
std::vector< art::Ptr< recob::Cluster > > ClusterVector
unsigned int NHits() const
Number of hits in the cluster.
Definition: Cluster.h:275
unsigned int TrackID() const
Definition: MCTrack.h:42
bool NeutrinoSet() const
Definition: MCTruth.h:78
void CheckTree(std::string caller) const
Helper function: throws if no tree is available.
std::vector< std::string > mctrk_MotherProcess
TCEvent evt
Definition: DataStructs.cxx:7
int AncestorPdgCode() const
Definition: MCShower.h:64
Contains ROOTTreeCode<>::code, ROOT tree character for branch of type T.
std::vector< Float_t > proto_momentum
std::vector< ShowerDataStruct > ShowerData
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
const PFParticleDataStruct & GetPFParticleData() const
std::vector< Float_t > StartE_drifted
std::map< std::string, double > mvaOutput
Definition: MVAPIDResult.h:27
ShowerData_t< Float_t > shwr_startdcosz
Z directional cosine at start of shower.
void CreateData(bool bClearData=false)
Creates the structure for the tree data; optionally initializes it.
float EndAngle() const
Returns the ending angle of the cluster.
Definition: Cluster.h:519
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:776
AuxDetMCData_t< Float_t > entryZ
Entry Z position of particle into AuxDet.
std::vector< Float_t > mcshwr_AncestorstartY
std::vector< Float_t > mcshwr_MotherendZ
double length(const recob::Track &track)
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
std::vector< Float_t > mctrk_startX_drifted
std::vector< Float_t > pathlen
std::vector< Float_t > mcshwr_AncestorstartZ
recob::tracking::Plane Plane
Definition: TrackState.h:17
static constexpr double sr
Definition: Units.h:166
std::vector< Float_t > cry_StartPointx
std::vector< std::string > fFlashMatchAssocLabel
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
bool hasExternCountInfo() const
Returns whether we have External Counter data.
helper function for LArPandoraInterface producer module
Int_t no_primaries
! how many particles there is currently room for
float StartTick() const
Returns the tick coordinate of the start of the cluster.
Definition: Cluster.h:297
std::vector< Float_t > mcshwr_StartDirX
void HitsPurity(detinfo::DetectorClocksData const &clockData, std::vector< art::Ptr< recob::Hit > > const &hits, Int_t &trackid, Float_t &purity, double &maxe)
constexpr int kMaxTruth
int bool
Definition: qglobal.h:345
std::vector< Float_t > SpacePointErrX
std::vector< std::string > fShowerModuleLabel
std::vector< VertexDataStruct > VertexData
std::vector< Float_t > EndP_tpcAV
std::vector< Float_t > mctrk_startY
PFParticleData_t< Short_t > pfp_isPrimary
whether the PFParticle is a primary particle
int ID() const
Definition: Shower.h:187
void FillShowers(AnalysisTreeDataStruct::ShowerDataStruct &showerData, std::vector< recob::Shower > const &showers, const bool fSavePFParticleInfo, const std::map< Short_t, Short_t > &showerIDtoPFParticleIDMap) const
Stores the information of all showers into showerData.
PFParticleData_t< Short_t > pfp_parentID
the ID of this PFParticle&#39;s immediate parent
std::vector< Float_t > mctrk_MotherstartZ
ShowerDataStruct const & GetShowerData(size_t iShower) const
std::vector< Float_t > mctrk_startX
std::vector< BoxedArray< T[kNplanes][kMaxShowerHits][3]>> HitCoordData_t
bool fSaveHitInfo
whether to extract and save MC Track information
std::vector< Float_t > mctrk_startZ_drifted
std::vector< Float_t > genie_P
static std::unique_ptr< MVAReader > create(const art::Event &evt, const art::InputTag &tag)
Definition: MVAReader.h:110
EventID id() const
Definition: Event.cc:34
double Vy(const int i=0) const
Definition: MCParticle.h:222
const MCStep & AncestorEnd() const
Definition: MCTrack.h:59
PlaneData_t< Float_t > shwr_totEng
Total energy of the shower per plane.
static QCString str
bool fSaveGenieInfo
whether to extract and save CRY particle data
PFParticleData_t< Short_t > pfp_isTrack
whether this PFParticle corresponds to a track
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
std::vector< TrackDataStruct > TrackData
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
std::vector< BoxedArray< T[kMaxAuxDets]>> AuxDetMCData_t
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Cosmic rays.
Definition: MCTruth.h:24
QTextStream & endl(QTextStream &s)
std::vector< Float_t > EndPz_tpcAV
std::vector< Float_t > mcshwr_StartDirY
Event finding and building.
std::vector< Float_t > genie_Pz
bool fSaveSpacePointSolverInfo
whether to extract and save PFParticle information
std::vector< Float_t > EndPointx
std::vector< Float_t > mctrk_AncestorendY
std::vector< Int_t > mctrk_TrackId
std::vector< Float_t > proto_py
std::vector< Float_t > mctrk_py_drifted
void beginSubRun(const art::SubRun &sr)
float Integral() const
Returns the total charge of the cluster from hit shape.
Definition: Cluster.h:600
float EndWire() const
Returns the wire coordinate of the end of the cluster.
Definition: Cluster.h:329
vertex reconstruction
bool fSaveShowerInfo
whether to extract and save External Counter information