ECalibration_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ECalibration
3 // Module Type: analyzer
4 // File: ECalibration_module.cc
5 //
6 // Module does:
7 // - computes energy deposition in an event
8 // - selects interesting particle using MC truth
9 // - plots dE/dx vs range for particles which stop/decay according to the actual settings.
10 //
11 //
12 // it is possible to specify beam window coordinates in fcl file
13 // other parameters in fcl file:
14 // pdg of particle we want to analyze.
15 // we can choose decaying/stopping particles.
16 //
17 //If you have some questions you can write to dorota.stefan@cern.ch
18 //or robert.sulej@cern.ch
19 //
20 ////////////////////////////////////////////////////////////////////////
21 
40 
43 #include "canvas/Persistency/Common/FindManyP.h"
49 #include "art_root_io/TFileService.h"
51 #include "fhiclcpp/ParameterSet.h"
53 
54 #include "TH1.h"
55 #include "TTree.h"
56 #include "TLorentzVector.h"
57 #include "TVector3.h"
58 
59 #include <cmath>
60 
61 namespace proto
62 {
63  struct bHitInfo;
64  class ECalibration;
65 }
66 
68 {
69  bHitInfo(size_t i, double x, double e, int w) :
70  Index(i), dE(e), dx(x), wire(w)
71  { }
72  size_t Index;
73  double dE, dx;
74  int wire;
75 };
76 
78 public:
79  explicit ECalibration(fhicl::ParameterSet const & p);
80  // The destructor generated by the compiler is fine for classes
81  // without bare pointers or other resource use.
82 
83  // Plugins should not be copied or assigned.
84  ECalibration(ECalibration const &) = delete;
85  ECalibration(ECalibration &&) = delete;
86  ECalibration & operator = (ECalibration const &) = delete;
87  ECalibration & operator = (ECalibration &&) = delete;
88 
89  // Required functions.
90  void analyze(art::Event const & e) override;
91 
92  void beginJob() override;
93 
94  void beginRun(const art::Run& run) override;
95 
96  void reconfigure(fhicl::ParameterSet const& p) ;
97 private:
98 
99  // Declare member data here.
100  void ResetVars();
101 
104 
105  bool Has(std::vector<int> v, int i) const;
106 
107  double GetEdepMC(art::Event const & e) const;
108 
109  double GetEdepHits(detinfo::DetectorClocksData const& clockData,
110  detinfo::DetectorPropertiesData const& detProp) const;
111 
112  bool EvMCselect(art::Event const & e);
113 
114  void Make_dEdx( std::vector< double > & dEdx,
115  std::vector< double > & range,
116  const std::vector< proto::bHitInfo > & hits,
117  double rmax) const;
118 
119  int GetClosestBeamTrkId() const;
120  // beam related:
121  void SetBeamWindowEnd();
122  TVector3 fBeamPos;
123  double fX0; double fX1;
124  double fY0; double fY1;
125  double fZ0; double fZ1;
126  double fThXZ;
127  double fThYZ;
128  //
129 
130  std::vector<int> fPdg;
131  int fSimPdg;
132  //int fSimTrackID; // unused
133  int fFlip;
135 
136  bool fStopping;
137  bool fDecaying;
138 
139  double fMaxRange;
140  double fT0;
141 
142  //////
144 
145  TTree *fTree; TTree *fDataTree;
146  int fRun;
147  int fEvent;
148  double fEdep;
149  double fEdepMC;
150  double fEkin;
151  int fTrkIdx;
152  double fdEdx;
153  double fRange;
154  //////
155 
156  std::map< size_t, std::vector< proto::bHitInfo >[3] > fTrk2InfoMap; // hits info sorted by views
158 
159  std::vector< art::Ptr<simb::MCParticle> > fSimlist;
160  std::vector< art::Ptr<recob::Hit> > fHitlist;
161  std::vector< art::Ptr<recob::Track> > fTracklist;
162  std::vector< art::Ptr<recob::Vertex> > fVertexlist;
163  std::vector< art::Ptr<recob::Shower> > fShslist;
164 
165  // Module labels to get data products
173 
175 
176 };
177 
179  :
180  EDAnalyzer(p),
181  fCalorimetryAlg(p.get<fhicl::ParameterSet>("CalorimetryAlg"))
182  // More initializers here.
183 {
184  // get a pointer to the geometry service provider
186 
187  reconfigure(p);
188 }
189 
191 {
193  fElectronsToGeV = 1./larParameters->GeVToElectrons();
194 }
195 
197 {
198  // access art's TFileService, which will handle creating and writing hists
200 
201  fMomentumStartHist = tfs->make<TH1D>("mom",";particle Momentum (GeV);",100, 0., 0.);
202 
203  fTree = tfs->make<TTree>("calibration","calibration tree");
204  fTree->Branch("fRun", &fRun, "fRun/I");
205  fTree->Branch("fEvent", &fEvent, "fEvent/I");
206  fTree->Branch("fEdep", &fEdep, "fEdep/D");
207  fTree->Branch("fEdepMC", &fEdepMC, "fEdepMC/D");
208  fTree->Branch("fEkin", &fEkin, "fEkin/D");
209 
210  fDataTree = tfs->make<TTree>("Data", "dE/dx info");
211  fDataTree->Branch("fRun", &fRun, "fRun/I");
212  fDataTree->Branch("fEvent", &fEvent, "fEvent/I");
213  fDataTree->Branch("fTrkIdx", &fTrkIdx, "fTrkIdx/I");
214  fDataTree->Branch("fdEdx", &fdEdx, "fdEdx/D");
215  fDataTree->Branch("fRange", &fRange, "fRange/D");
216 }
217 
219 {
220  fSimulationLabel = p.get< std::string >("SimulationLabel");
221  fHitsModuleLabel = p.get< std::string >("HitsModuleLabel");
222  fTrackModuleLabel = p.get< std::string >("TrackModuleLabel");
223  fShowerModuleLabel = p.get< std::string >("ShowerModuleLabel");
224  fClusterModuleLabel = p.get< std::string >("ClusterModuleLabel");
225  fVertexModuleLabel = p.get< std::string >("VertexModuleLabel");
226  fCalorimetryModuleLabel = p.get< std::string >("CalorimetryModuleLabel");
227  fX0 = p.get<double>("BeamPosX");
228  fY0 = p.get<double>("BeamPosY");
229  fZ0 = p.get<double>("BeamPosZ");
230  fThXZ = p.get<double>("ThXZ");
231  fThYZ = p.get<double>("ThYZ");
232 
233  fStopping = p.get<bool>("Stopping");
234  fDecaying = p.get<bool>("Decaying");
235 
236  fMaxRange = p.get<double>("MaxRange");
237  fPdg = p.get< std::vector<int> >("Pdg");
238 
239  fBestview = p.get<int>("Bestview");
240 }
241 
242 // selecting particle using MC truth
243 // here we are interested in stopping/decaying particles
244 // pdg is specified in fcl file
245 // decaying/stopping are switch on/off according to needs in fcl file
247 {
248  std::vector< art::Ptr<simb::MCParticle> > simlist;
249 
250  auto mcparticleHandle = e.getHandle< std::vector<simb::MCParticle> >(fSimulationLabel);
251  if (mcparticleHandle)
252  art::fill_ptr_vector(simlist, mcparticleHandle);
253 
254  std::map< int, const simb::MCParticle* > particleMap;
255  for (auto const& particle : simlist)
256  {
257  particleMap[particle->TrackId()] = &*particle;
258  }
259 
260  fSimPdg = particleMap.begin()->second->PdgCode();
261  fT0 = particleMap.begin()->second->T();
262 
263  if (fStopping)
264  {
265  if ((fSimPdg == 2212)
266  && Has(fPdg, fSimPdg)
267  && (particleMap.size() == 1)
268  && (particleMap.begin()->second->EndProcess() != "ProtonInelastic"))
269  {
270  return true;
271  }
272  else if ((fSimPdg == 13)
273  && Has(fPdg, fSimPdg))
274  {
275  return true;
276  }
277  else if ((fSimPdg == 211)
278  && (Has(fPdg, fSimPdg)))
279  {
280  return true;
281  }
282  }
283 
284  if (fDecaying)
285  {
286  if ((fSimPdg == 321)
287  && Has(fPdg, fSimPdg)
288  && (particleMap.begin()->second->EndProcess() == "Decay")
289  && (particleMap.begin()->second->NumberDaughters() == 2)
290  && (particleMap.size() == 6))
291  {
292  bool kaonmodedcy = false;
293  size_t count = 0;
294  for (auto const & p : particleMap)
295  {
296  if ((p.second->PdgCode() == 321) ||
297  (p.second->PdgCode() == -13) ||
298  (p.second->PdgCode() == 14))
299  {
300  kaonmodedcy = true;
301  }
302 
303  count++;
304  if (count == 3) break;
305  }
306  return kaonmodedcy;
307  }
308  else if ((fSimPdg == 13)
309  && Has(fPdg, fSimPdg))
310  {
311  return true;
312  }
313  else if ((fSimPdg == 211)
314  && (Has(fPdg, fSimPdg))
315  && (particleMap.begin()->second->EndProcess() == "Decay"))
316  {
317  return true;
318  }
319  }
320 
321  if (!fDecaying
322  && !fStopping
323  && (fSimPdg == abs(11))
324  && Has(fPdg, fSimPdg))
325  {
326  return true;
327  }
328 
329  fMomentumStartHist->Fill(particleMap.begin()->second->Momentum(0).P());
330 
331  return false;
332 }
333 
334 
336 {
337 
338  // Implementation of required member function here.
339  ResetVars();
341 
342  fRun = e.run();
343  fEvent = e.id().event();
344 
345  if (!EvMCselect(e)) return;
346 
347  // reco
348  // hits
349  auto hitListHandle = e.getHandle< std::vector<recob::Hit> >(fHitsModuleLabel);
350  if (hitListHandle) art::fill_ptr_vector(fHitlist, hitListHandle);
351 
352  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(e);
353  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(e, clockData);
354 
355  if (fHitlist.size())
356  {
357  fEdep = GetEdepHits(clockData, detProp);
358  fEdepMC = GetEdepMC(e);
359  }
360 
361  // vertices
362  auto vtxListHandle = e.getHandle< std::vector<recob::Vertex> >(fVertexModuleLabel);
363  if (vtxListHandle) art::fill_ptr_vector(fVertexlist, vtxListHandle);
364 
365  // showers
366  auto shsListHandle = e.getHandle< std::vector<recob::Shower> >(fShowerModuleLabel);
367  if (shsListHandle) art::fill_ptr_vector(fShslist, shsListHandle);
368 
369  // tracks
370  fTrk2InfoMap.clear();
371  fTrkListHandle = e.getHandle< std::vector<recob::Track> >(fTrackModuleLabel);
372  if (fTrkListHandle)
373  {
374  art::FindManyP< recob::Hit, recob::TrackHitMeta > hitFromTrk(fTrkListHandle, e, fTrackModuleLabel);
375 
376  // choose the primary track using information about the beam window position
377  int idt = GetClosestBeamTrkId();
378  if (hitFromTrk.size() && (idt > -1))
379  {
380  fFlip = 0; // tag track if it is reconstructed in the opposite direction
381  if ((*fTrkListHandle)[idt].End().Z() < (*fTrkListHandle)[idt].Vertex().Z())
382  { fFlip = 1; }
383 
384  auto vhit = hitFromTrk.at(idt);
385  auto vmeta = hitFromTrk.data(idt);
386 
387  for (size_t h = 0; h < vhit.size(); ++h)
388  {
389  int view = vhit[h]->WireID().Plane;
390 
391  if (view != fBestview) continue;
392 
393  size_t idx = vmeta[h]->Index();
394  double tdrift = vhit[h]->PeakTime();
395  double dx = vmeta[h]->Dx();
396  double dqadc = vhit[h]->Integral();
397  int wire = vhit[h]->WireID().Wire;
398 
399  double dq = fCalorimetryAlg.dEdx_AREA(clockData, detProp, dqadc/dx, tdrift, view, fT0) * dx;
400  fEkin += dq;
401 
402  fTrk2InfoMap[idt][view].emplace_back(idx, dx, dq, wire);
403  }
404 
405  for (auto const & trkEntry : fTrk2InfoMap)
406  {
407  std::vector< double > dEdx, range;
408  auto const & info = trkEntry.second;
409  Make_dEdx(dEdx, range, info[fBestview], fMaxRange);
410 
411  for (size_t i = 0; i < dEdx.size(); ++i)
412  {
413  fTrkIdx = trkEntry.first;
414  fdEdx = dEdx[i];
415  fRange = range[i];
416 
417  fDataTree->Fill();
418  }
419  }
420  }
421  }
422  fTree->Fill();
423 }
424 
426 {
427  int idt = -1;
428  if (!fTrkListHandle->size()) {return idt;}
429 
430  auto const & trk0 = (*fTrkListHandle)[0];
431  float mindist2 = pma::Dist2(fBeamPos, trk0.Vertex());
432  if (trk0.End().Z() < trk0.Vertex().Z())
433  {
434  mindist2 = pma::Dist2(fBeamPos, trk0.End());
435  idt = 0;
436  }
437  else
438  {
439  mindist2 = pma::Dist2(fBeamPos, trk0.Vertex());
440  idt = 0;
441  }
442 
443  for (size_t t = 1; t < fTrkListHandle->size(); ++t)
444  {
445  auto const & trk = (*fTrkListHandle)[t];
446 
447  float dist2 = pma::Dist2(fBeamPos, trk.Vertex());
448  if (trk.End().Z() < trk.Vertex().Z())
449  {
450  dist2 = pma::Dist2(fBeamPos, trk.End());
451  }
452  else
453  {
454  dist2 = pma::Dist2(fBeamPos, trk.Vertex());
455  }
456 
457  //
458  // idt:
459  // we assumed that primary, incoming particle
460  // has an index of a track closest to the beam window
461  //
462  if (dist2 < mindist2) {mindist2 = dist2; idt = t;}
463  }
464 
465  return idt;
466 }
467 
468 void proto::ECalibration::Make_dEdx(std::vector< double > & dEdx, std::vector< double > & range, const std::vector< proto::bHitInfo > & hits, double rmax) const
469 {
470  if (!hits.size()) return;
471 
472  dEdx.clear(); range.clear();
473 
474  int i0 = hits.size() - 1; int i1 = -1; int di = -1;
475  if (Has(fPdg, abs(11)) || fFlip) {i0 = 0; i1 = hits.size(); di = 1;}
476 
477  double de = 0.0;
478  double dx = 0.0;
479  double r0 = 0.0; double r1 = 0.0; double r = 0.0;
480 
481  double minDx = 0.1; // can be a parameter
482 
483  while ((i0 != i1) && (r < rmax))
484  {
485  dx = 0.0; de = 0.0;
486  while ((i0 != i1) && (dx <= minDx))
487  {
488  de += hits[i0].dE;
489  dx += hits[i0].dx;
490  i0 += di;
491  }
492 
493  r0 = r1;
494  r1 += dx;
495  r = 0.5 * (r0 + r1);
496 
497  if ((de > 0.0) && (dx > 0.0) && (r < rmax))
498  {
499  dEdx.push_back(de/dx);
500  range.push_back(r);
501  }
502  }
503 }
504 
506 {
507  double energy = 0.0;
508 
509  auto simchannelHandle = e.getHandle< std::vector<sim::SimChannel> >(fSimulationLabel);
510  if (simchannelHandle)
511  {
512  for ( auto const& channel : (*simchannelHandle) )
513  {
514  // for every time slice in this channel:
515  auto const& timeSlices = channel.TDCIDEMap();
516  for ( auto const& timeSlice : timeSlices )
517  {
518  // loop over the energy deposits.
519  auto const& energyDeposits = timeSlice.second;
520 
521  for ( auto const& energyDeposit : energyDeposits )
522  {
523  energy += energyDeposit.numElectrons * fElectronsToGeV * 1000;
524  }
525  }
526  }
527  }
528 
529  return energy;
530 }
531 
532 // use best view defined in fcl
534  detinfo::DetectorPropertiesData const& detProp) const
535 {
536  if (!fHitlist.size()) return 0.0;
537 
538  double dqsum = 0.0;
539  for (size_t h = 0; h < fHitlist.size(); ++h)
540  {
541  unsigned short plane = fHitlist[h]->WireID().Plane;
542  if (plane != geo::kZ) continue;
543 
544  double dqadc = fHitlist[h]->Integral();
545  if (!std::isnormal(dqadc) || (dqadc < 0)) continue;
546 
547  double dqel = fCalorimetryAlg.ElectronsFromADCArea(dqadc, plane);
548 
549  double tdrift = fHitlist[h]->PeakTime();
550  double correllifetime = fCalorimetryAlg.LifetimeCorrection(clockData, detProp, tdrift, fT0);
551 
552  double dq = dqel * correllifetime * fElectronsToGeV * 1000;
553  if (!std::isnormal(dq) || (dq < 0)) continue;
554 
555  dqsum += dq;
556  }
557 
558  return dqsum;
559 }
560 
561 bool proto::ECalibration::Has(std::vector<int> v, int i) const
562 {
563  for (auto c : v) if (c == i) return true;
564  return false;
565 }
566 
567 // to compute momenta of particles without distortion due to beam window
569 {
570  fZ1 = 0.0;
571 
572  double dz = fZ1 - fZ0;
573  double dx = dz * tan(fThXZ * (TMath::Pi() / 180.0));
574  double dy = dz * tan(fThYZ * (TMath::Pi() / 180.0));
575 
576  fX1 = fX0 + dx;
577  fY1 = fY0 + dy;
578 
579  fBeamPos.SetXYZ(fX1, fY1, fZ1);
580 }
581 
583 {
584  fSimlist.clear();
585  fHitlist.clear();
586  fTracklist.clear();
587  fVertexlist.clear();
588  fShslist.clear();
589  fSimPdg = 0;
590  fEdep = 0.0;
591  fEdepMC = 0.0;
592  fEkin = 0;
593  fT0 = 0.0;
594  fTrkIdx = 0;
595  fRange = 0.0;
596  fdEdx = 0.0;
597  fFlip = 0;
598 }
599 
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
calo::CalorimetryAlg fCalorimetryAlg
Store parameters for running LArG4.
std::vector< art::Ptr< recob::Hit > > fHitlist
std::vector< art::Ptr< simb::MCParticle > > fSimlist
art::Handle< std::vector< recob::Track > > fTrkListHandle
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:37
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
Class to keep data related to recob::Hit associated with recob::Track.
Planes which measure Z direction.
Definition: geo_types.h:132
int GetClosestBeamTrkId() const
uint8_t channel
Definition: CRTFragment.hh:201
unsigned int Index
Particle class.
art framework interface to geometry description
Definition: Run.h:17
double ElectronsFromADCArea(double area, unsigned short plane) const
T abs(T value)
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
virtual void reconfigure(fhicl::ParameterSet const &pset)
double GetEdepHits(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp) const
std::vector< art::Ptr< recob::Vertex > > fVertexlist
T get(std::string const &key) const
Definition: ParameterSet.h:271
p
Definition: test.py:223
General LArSoft Utilities.
geo::GeometryCore const * fGeometry
RunNumber_t run() const
Definition: DataViewImpl.cc:71
ECalibration(fhicl::ParameterSet const &p)
Description of geometry of one entire detector.
bHitInfo(size_t i, double x, double e, int w)
void Make_dEdx(std::vector< double > &dEdx, std::vector< double > &range, const std::vector< proto::bHitInfo > &hits, double rmax) const
void analyze(art::Event const &e) override
void beginRun(const art::Run &run) override
Implementation of the Projection Matching Algorithm.
Declaration of signal hit object.
double GetEdepMC(art::Event const &e) const
Contains all timing reference information for the detector.
std::vector< int > fPdg
Provides recob::Track data product.
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
bool Has(std::vector< int > v, int i) const
EventNumber_t event() const
Definition: EventID.h:116
Access the description of detector geometry.
list x
Definition: train.py:276
bool EvMCselect(art::Event const &e)
std::vector< art::Ptr< recob::Track > > fTracklist
void reconfigure(fhicl::ParameterSet const &p)
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
double LifetimeCorrection(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, double time, double T0=0) const
Collection of Physical constants used in LArSoft.
std::vector< art::Ptr< recob::Shower > > fShslist
std::map< size_t, std::vector< proto::bHitInfo >[3] > fTrk2InfoMap
EventID id() const
Definition: Event.cc:34
double GeVToElectrons() const
std::string fCalorimetryModuleLabel