ParamSim_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 // Class: ParamSim
3 // Plugin Type: analyzer
4 // File: ParamSim_module.cc
5 ////////////////////////////////////////////////////////////////////////////////
6 
13 #include "art_root_io/TFileService.h"
15 #include "fhiclcpp/ParameterSet.h"
18 #include "canvas/Persistency/Common/FindOne.h"
19 #include "canvas/Persistency/Common/FindOneP.h"
20 #include "canvas/Persistency/Common/FindMany.h"
21 #include "canvas/Persistency/Common/FindManyP.h"
22 
23 // nutools extensions
24 #include "nurandom/RandomUtils/NuRandomService.h"
25 
29 #include "CoreUtils/ServiceUtil.h"
30 #include "Geometry/GeometryGAr.h"
31 
32 #include "CLHEP/Random/RandGauss.h"
33 #include "CLHEP/Random/RandFlat.h"
34 
35 #include "TFile.h"
36 #include "TTree.h"
37 #include "TDatabasePDG.h"
38 #include "TParticlePDG.h"
39 #include "TVector3.h"
40 #include "TF1.h"
41 #include "TH1.h"
42 #include "TH2.h"
43 
44 #include <string>
45 #include <vector>
46 #include <unordered_map>
47 
48 namespace gar {
49 
50  //Helper Class
51  class CAFHelper
52  {
53  public:
54  /* C'tor */
55  CAFHelper(const geo::GeometryCore *fGeo, CLHEP::HepRandomEngine& engine);
56 
57  /* D'tor */
58  ~CAFHelper();
59 
60  /* Check if MCP point is in fiducial */
61  bool PointInFiducial(const TVector3& point);
62 
63  /* Check if MCP point is in TPC Volume (can be outside Fid) */
64  bool PointInTPC(const TVector3& point);
65 
66  /* Check if MCP point is in the ECAL */
67  bool PointInCalo(const TVector3& point);
68 
69  /* Check if MCP point is in between the TPC and the ECAL */
70  bool PointStopBetween(const TVector3& point);
71 
72  /* Check if MCP point is not in the fiducial and not in the ECAL */
73  bool isThroughCalo(const TVector3& point);
74 
75  /* Check if MCP decayed in calo */
76  bool hasDecayedInCalo(const TVector3& point);
77 
78  /* Check if MCP is in the Barrel region */
79  bool isBarrel(const TVector3& point);
80 
81  /* Check if MCP is in the Endcap region */
82  bool isEndcap(const TVector3& point);
83 
84  float GetRamdomNumber();
85 
86  float GaussianSmearing(const float mean, const float sigma);
87 
88  private:
89  void PrintParameters();
90 
91  CLHEP::HepRandomEngine& fEngine;
92 
93  //For the fiducial volume
94  const double fTPCFidRadius = 222.5;
95  const double fTPCFidLength = 215.;
96 
97  double fTPCRadius;
98  double fTPCLength;
103  double fECALStartX;
104  double fECALEndX;
105  };
106 
107  //==============================================================================
108  inline float CAFHelper::GetRamdomNumber() {
109  CLHEP::RandFlat FlatRand(fEngine);
110  return FlatRand.fire();;
111  }
112 
113  //==============================================================================
114  inline float CAFHelper::GaussianSmearing(const float mean, const float sigma) {
115  CLHEP::RandGauss GausRand(fEngine);
116  return GausRand.fire(mean, sigma);;
117  }
118 
119  //==============================================================================
120  CAFHelper::CAFHelper(const geo::GeometryCore *fGeo, CLHEP::HepRandomEngine& engine)
121  : fEngine(engine)
122  {
123  fTPCRadius = fGeo->TPCRadius();
124  fTPCLength = fGeo->TPCLength()/2.;
130  fECALEndX = fGeo->GetECALEndcapOuterX();
131 
132  PrintParameters();
133  }
134 
135  //==============================================================================
137  {
138 
139  }
140 
141  //==============================================================================
143  {
144  std::cout << " ==== CAFHelper Parameters ==== " << std::endl;
145  std::cout << "TPC Radius " << fTPCRadius << " cm" << std::endl;
146  std::cout << "TPC Length " << fTPCLength << " cm" << std::endl;
147  std::cout << "ECAL Barrel Inner Radius " << fECALBarrelInnerRadius << " cm" << std::endl;
148  std::cout << "ECAL Barrel Outer Radius " << fECALBarrelOuterRadius << " cm" << std::endl;
149  std::cout << "ECAL Endcap Inner Radius " << fECALEndcapInnerRadius << " cm" << std::endl;
150  std::cout << "ECAL Endcap Outer Radius " << fECALEndcapOuterRadius << " cm" << std::endl;
151  std::cout << "ECAL Endcap Start X " << fECALStartX << " cm" << std::endl;
152  std::cout << "ECAL Endcap End X " << fECALEndX << " cm" << std::endl;
153  std::cout << " ==== CAFHelper Parameters ==== " << std::endl;
154  }
155 
156  //==============================================================================
157  inline bool CAFHelper::PointInFiducial(const TVector3& point)
158  {
159  //TPC Fiducial volume defined as
160  //R < 260 cm
161  //|X| < 250 cm
162  bool isInFiducial = true;
163 
164  float r_point = std::sqrt( point.Y()*point.Y() + point.Z()*point.Z() );
165  if( r_point > fTPCFidRadius ) isInFiducial = false;
166  if( r_point < fTPCFidRadius && std::abs(point.X()) > fTPCFidLength ) isInFiducial = false;
167 
168  return isInFiducial;
169  }
170 
171  //==============================================================================
172  inline bool CAFHelper::PointInTPC(const TVector3& point)
173  {
174  //TPC volume defined as
175  //R < 260 cm
176  //|X| < 250 cm
177  if(PointInFiducial(point)) return true;
178  bool isInTPC = true;
179 
180  float r_point = std::sqrt( point.Y()*point.Y() + point.Z()*point.Z() );
181  if( r_point > fTPCRadius ) isInTPC = false;
182  if( r_point < fTPCRadius && std::abs(point.X()) > fTPCLength ) isInTPC = false;
183 
184  return isInTPC;
185  }
186 
187  //==============================================================================
188  inline bool CAFHelper::PointInCalo(const TVector3& point)
189  {
190  //Barrel Radius 278 cm
191  //Endcap starts at 364 cm
192  bool isInCalo = false;
193  float r_point = std::sqrt( point.Y()*point.Y() + point.Z()*point.Z() );
194  //in the Barrel
195  if( r_point > fECALBarrelInnerRadius && r_point < fECALBarrelOuterRadius && std::abs(point.X()) < fECALStartX ) isInCalo = true;
196  //in the Endcap
197  if( r_point < fECALEndcapOuterRadius && std::abs(point.X()) > fECALStartX && std::abs(point.X()) < fECALEndX ) isInCalo = true;
198 
199  return isInCalo;
200  }
201 
202  //==============================================================================
203  inline bool CAFHelper::PointStopBetween(const TVector3& point)
204  {
205  //Barrel Radius 278 cm
206  //Endcap starts at 364 cm
207  bool isStopBetween = false;
208  float r_point = std::sqrt( point.Y()*point.Y() + point.Z()*point.Z() );
209  //in the Barrel
210  if( r_point < fECALBarrelInnerRadius && r_point > fTPCRadius && std::abs(point.X()) < fTPCLength ) isStopBetween = true;
211  //in the Endcap
212  if( r_point < fECALEndcapOuterRadius && std::abs(point.X()) > fTPCLength && std::abs(point.X()) < fECALStartX ) isStopBetween = true;
213 
214  return isStopBetween;
215  }
216 
217  //==============================================================================
218  inline bool CAFHelper::isThroughCalo(const TVector3& point)
219  {
220  return !PointInTPC(point) && !PointStopBetween(point) && !PointInCalo(point);
221  }
222 
223  //==============================================================================
224  inline bool CAFHelper::hasDecayedInCalo(const TVector3& point)
225  {
226  return PointInCalo(point);
227  }
228 
229  //==============================================================================
230  inline bool CAFHelper::isBarrel(const TVector3& point)
231  {
232  bool isBarrel = false;
233  float theta = std::atan(fECALBarrelInnerRadius / std::abs(fECALStartX) ); //angle for barrel/endcap transition
234  float r_point = std::sqrt( point.Y()*point.Y() + point.Z()*point.Z() );
235  float theta_point = std::atan(r_point / std::abs(point.X()) ); //angle for barrel/endcap transition for the point
236 
237  if( theta_point > theta ) isBarrel = true;
238  return isBarrel;
239  }
240 
241  //==============================================================================
242  inline bool CAFHelper::isEndcap(const TVector3& point)
243  {
244  bool isEndcap = false;
245  if( !isBarrel(point) ) isEndcap = true;
246  return isEndcap;
247  }
248 
249  //==============================================================================
250  class ParamSim : public art::EDAnalyzer {
251  public:
252  explicit ParamSim(fhicl::ParameterSet const & p);
253  // The compiler-generated destructor is fine for non-base
254  // classes without bare pointers or other resource use.
255 
256  // Plugins should not be copied or assigned.
257  ParamSim(ParamSim const &) = delete;
258  ParamSim(ParamSim &&) = delete;
259  ParamSim & operator = (ParamSim const &) = delete;
260  ParamSim & operator = (ParamSim &&) = delete;
261 
262  virtual void beginJob() override;
263 
264  // Required functions.
265  void analyze(art::Event const & e) override;
266 
267  private:
268  void ClearVectors();
269  void SaveGtruthMCtruth(art::Event const & e);
270  void TreatMCParticles(art::Event const & e);
271  void TreatTPCVisible(const float ecaltime);
272  void TreatTPCNotVisible(const float ecaltime);
273 
274  //Helpers
275  void FillCommonVariables(const int pdg, const TLorentzVector& momentum, const TLorentzVector& position, const TLorentzVector& positionEnd, const int mctrackid, const int mothertrackid, const int motherpdg, const float ptrue, const float angle, const std::string mcp_process, const std::string mcp_endprocess, const float time);
276  void ComputeTrkLength(const simb::MCParticle &mcp);
277  void DoRangeCalculation(float &preco, float &angle_reco);
278  void DoGluckSternCalculation(float &preco, float &angle_reco);
279  void TPCParticleIdentification();
280  void TreatNeutrons(const float ecaltime);
281  void TreatPhotons(const float ecaltime);
282  void TreatOthers(const float ecaltime);
283  bool CheckVectorSize();
284 
285  //TTree
286  TTree *fTree;
287  std::unordered_map<int, TH2F*> m_pidinterp;
288 
289  //Geometry
290  const geo::GeometryCore* fGeo; ///< pointer to the geometry
292  CLHEP::HepRandomEngine &fEngine; ///< random engine
293 
294  //fcl parameters
296  std::string fGeantLabel; ///< module label for geant4 simulated hits
298 
299  //Fixed parameters
300  float fOrigin[3];
301  const std::vector<int> neutrinos = {12, 14, 16};
302  //gamma, neutron, pi0, k0L, k0S, k0, delta0
303  const std::vector<int> pdg_neutral = {22, 2112, 111, 130, 310, 311, 2114};
304  //pion, muon, proton, kaon, deuteron, electron
305  const std::vector<int> pdg_charged = {211, 13, 2212, 321, 1000010020, 11};
306  const float gastpc_len = 2.; // new track length cut in cm based on Thomas' study of low energy protons
307  const float gastpc_B = 0.5; // B field strength in Tesla
308  const float gastpc_padPitch = 0.1; // 1 mm. Actual pad pitch varies, which is going to be impossible to implement
309  const float gastpc_X0 = 1300.; // cm = 13m radiation length
310  //Resolution for short tracks //TODO check this numbers!
311  const float sigmaP_short = 0.1; //in GeV
312  // point resolution
313  const float sigma_x = 0.1;
314  //as function of KE
315  //0 -> 50 MeV ~ 20%
316  //> 50 MeV ~ 40%
317  const float NeutronECAL_detEff[2] = {0.2, 0.4};
318  const float sigmaNeutronECAL_first = 0.11;
319  //TODO fraction of rescatters
320  // float sigmaNeutronECAL_rescatter = 0.26;
321  //ECAL energy resolution sigmaE/E
322  const float ECAL_stock = 0.06; //in %
323  const float ECAL_const = 0.02;
324  TF1 *fRes;
325  //ECAL sampling fraction
326  // double sampling_frac = 4.32;
327  //ECAL nlayers
328  const int nLayers = 60;
329  //ECAL MIP resolution (based on AHCAL numbers)
330  const double ECAL_MIP_Res = 0.23;
331  //MIP2GeV conversion factor
332  const double MIP2GeV_factor = 0.814 / 1000;
333  //float ECAL_pi0_resolution = 0.13; //sigmaE/E in between at rest (17%) and high energy (~few %)
334  const float fECALTimeResolution = 1.; // 1 ns time resolution
335  TParticlePDG *neutron = TDatabasePDG::Instance()->GetParticle(2112);
336  const float neutron_mass = neutron->Mass(); //in GeV
337 
338  //CAF variables
339  //Event-wise values
340  unsigned int fRun, fEvent, fSubRun;
341  //Generator values
342  std::vector<int> mode, ccnc, ntype, gint, weight, tgtpdg, gt_t, intert, detected;
343  std::vector<double> q2, w, y, x, theta, t, mctime, mcnupx, mcnupy, mcnupz, vertx, verty, vertz;
344  //MC Particle Values, with motherid added
345  unsigned int _nFSP;
346  std::vector<int> mctrkid, motherid, pdgmother, truepdg, _MCPStartX, _MCPStartY, _MCPStartZ, _MCPEndX, _MCPEndY, _MCPEndZ;
347  std::vector<std::string> _MCProc, _MCEndProc;
348  std::vector<double> trkLen, trkLenPerp, truep, truepx, truepy, truepz, _angle;
349  //Reco values
350  std::vector<int> recopid, recopidecal;
351  std::vector<double> prob_arr, anglereco, _preco, erecon, etime;
352  //Geometry
353  std::vector<unsigned int> isFidStart, isTPCStart, isCaloStart, isInBetweenStart, isThroughCaloStart;
354  std::vector<unsigned int> isFidEnd, isTPCEnd, isCaloEnd, isInBetweenEnd, isThroughCaloEnd;
355  std::vector<unsigned int> isBarrelStart, isEndcapStart, isBarrelEnd, isEndcapEnd;
356  };
357 
358  //==============================================================================
360  : EDAnalyzer(p),
361  fEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, p, "Seed"))
362  {
363  fGeo = gar::providerFrom<geo::GeometryGAr>();
364 
365  fGeneratorLabel = p.get<std::string>("GeneratorLabel","genie");
366  fGeantLabel = p.get<std::string>("GEANTLabel","geant");
367  fCorrect4origin = p.get<bool>("Correct4Origin", false);
368 
369  consumes<std::vector<simb::MCTruth> >(fGeneratorLabel);
370  consumes<std::vector<simb::GTruth> >(fGeneratorLabel);
371  consumes<std::vector<simb::MCParticle> >(fGeantLabel);
372  }
373 
374  //==============================================================================
376  {
377  fOrigin[0] = fGeo->GetOriginX();
378  fOrigin[1] = fGeo->GetOriginY();
379  fOrigin[2] = fGeo->GetOriginZ();
380 
381  fRes = new TF1("fRes", "TMath::Sqrt ( [0]*[0]/x + [1]*[1] )", 3);
382  fRes->FixParameter(0, ECAL_stock);
383  fRes->FixParameter(1, ECAL_const);
384  fHelper = new CAFHelper(fGeo, fEngine);
385 
386  // read the PID parametrization ntuple from T. Junk
387  TString filename = "${DUNE_PARDATA_DIR}/MPD/dedxPID/dedxpidmatrices8kevcm.root";
388  TFile pidfile(filename, "READ");
389 
390  m_pidinterp.clear();
391  char str[11];
392  for (int q = 0; q < 501; ++q)
393  {
394  sprintf(str, "%d", q);
395  std::string s = "pidmatrix";
396  s.append(str);
397  // read the 500 histograms one by one; each histogram is a
398  // 6 by 6 matrix of probabilities for a given momentum value
399  m_pidinterp.insert( std::make_pair(q, (TH2F*) pidfile.Get(s.c_str())->Clone("pidinterp")) );
400  }
401 
402  // pidfile.Close();
403 
405  fTree = tfs->make<TTree>("caf","caf tree");
406 
407  //Event number, //Run number, //Sub Run number
408  fTree->Branch("Event", &fEvent);
409  fTree->Branch("Run", &fRun);
410  fTree->Branch("SubRun", &fSubRun);
411 
412  //MC Truth info (Generator)
413  fTree->Branch("mode", &mode);
414  fTree->Branch("q2", &q2);
415  fTree->Branch("w", &w);
416  fTree->Branch("y", &y);
417  fTree->Branch("x", &x);
418  fTree->Branch("theta", &theta);
419  fTree->Branch("t", &t);
420  fTree->Branch("ntype", &ntype);
421  fTree->Branch("ccnc", &ccnc);
422  fTree->Branch("gint", &gint);
423  fTree->Branch("tgtpdg", &tgtpdg);
424  fTree->Branch("weight", &weight);
425  fTree->Branch("gt_t", &gt_t);
426  fTree->Branch("intert", &intert);
427  fTree->Branch("mcnupx", &mcnupx);
428  fTree->Branch("mcnupy", &mcnupy);
429  fTree->Branch("mcnupz", &mcnupz);
430  fTree->Branch("vertx", &vertx);
431  fTree->Branch("verty", &verty);
432  fTree->Branch("vertz", &vertz);
433 
434  //Number of final state particle (primaries)
435  fTree->Branch("nFSP", &_nFSP);
436  //MC Particle info
437  fTree->Branch("detected", &detected);
438  fTree->Branch("pdgmother", &pdgmother);
439  fTree->Branch("MCPTime", &mctime);
440  fTree->Branch("MCPStartX", &_MCPStartX);
441  fTree->Branch("MCPStartY", &_MCPStartY);
442  fTree->Branch("MCPStartZ", &_MCPStartZ);
443  fTree->Branch("motherid", &motherid);
444  fTree->Branch("mctrkid", &mctrkid);
445  fTree->Branch("truepx", &truepx);
446  fTree->Branch("truepy", &truepy);
447  fTree->Branch("truepz", &truepz);
448  fTree->Branch("MCPEndX", &_MCPEndX);
449  fTree->Branch("MCPEndY", &_MCPEndY);
450  fTree->Branch("MCPEndZ", &_MCPEndZ);
451  fTree->Branch("MCProc", &_MCProc);
452  fTree->Branch("MCEndProc", &_MCEndProc);
453  fTree->Branch("angle", &_angle);
454  fTree->Branch("truep", &truep);
455  fTree->Branch("truepdg", &truepdg);
456  //Reco info
457  fTree->Branch("recopid", &recopid);
458  fTree->Branch("recopidecal", &recopidecal);
459  fTree->Branch("trkLen", &trkLen);
460  fTree->Branch("trkLenPerp", &trkLenPerp);
461  fTree->Branch("preco", &_preco);
462  fTree->Branch("anglereco", &anglereco);
463  fTree->Branch("erecon", &erecon);
464  fTree->Branch("etime", &etime);
465  fTree->Branch("prob_arr", &prob_arr);
466  //Geometry
467  fTree->Branch("isFidStart", &isFidStart);
468  fTree->Branch("isTPCStart", &isTPCStart);
469  fTree->Branch("isCaloStart", &isCaloStart);
470  fTree->Branch("isInBetweenStart", &isInBetweenStart);
471  fTree->Branch("isThroughCaloStart", &isThroughCaloStart);
472  fTree->Branch("isBarrelStart", &isBarrelStart);
473  fTree->Branch("isEndcapStart", &isEndcapStart);
474 
475  fTree->Branch("isFidEnd", &isFidEnd);
476  fTree->Branch("isTPCEnd", &isTPCEnd);
477  fTree->Branch("isCaloEnd", &isCaloEnd);
478  fTree->Branch("isThroughCaloEnd", &isThroughCaloEnd);
479  fTree->Branch("isInBetweenEnd", &isInBetweenEnd);
480  fTree->Branch("isBarrelEnd", &isBarrelEnd);
481  fTree->Branch("isEndcapEnd", &isEndcapEnd);
482  }
483 
484  //==============================================================================
486  {
487  ClearVectors();
488  fRun = e.run();
489  fSubRun = e.subRun();
490  fEvent = e.id().event();
491 
493  TreatMCParticles(e);
494 
495  //Checks
496  if(CheckVectorSize()) {
497  fTree->Fill();
498  } else {
499  std::cerr << "Event " << fEvent << std::endl;
500  std::cerr << "Number of FSP " << _nFSP << std::endl;
501 
502  std::cerr << "Size of pdgmother " << pdgmother.size() << std::endl;
503  std::cerr << "Size of truepdg " << truepdg.size() << std::endl;
504  std::cerr << "Size of mctime " << mctime.size() << std::endl;
505  std::cerr << "Size of mctrkid " << mctrkid.size() << std::endl;
506  std::cerr << "Size of motherid " << motherid.size() << std::endl;
507  std::cerr << "Size of _MCPStartX " << _MCPStartX.size() << std::endl;
508  std::cerr << "Size of _MCPStartY " << _MCPStartY.size() << std::endl;
509  std::cerr << "Size of _MCPStartZ " << _MCPStartZ.size() << std::endl;
510  std::cerr << "Size of _MCPEndX " << _MCPEndX.size() << std::endl;
511  std::cerr << "Size of _MCPEndY " << _MCPEndY.size() << std::endl;
512  std::cerr << "Size of _MCPEndZ " << _MCPEndZ.size() << std::endl;
513  std::cerr << "Size of _MCProc " << _MCProc.size() << std::endl;
514  std::cerr << "Size of _MCEndProc " << _MCEndProc.size() << std::endl;
515  std::cerr << "Size of trkLen " << trkLen.size() << std::endl;
516  std::cerr << "Size of trkLenPerp " << trkLenPerp.size() << std::endl;
517  std::cerr << "Size of truep " << truep.size() << std::endl;
518  std::cerr << "Size of truepx " << truepx.size() << std::endl;
519  std::cerr << "Size of truepy " << truepy.size() << std::endl;
520  std::cerr << "Size of truepz " << truepz.size() << std::endl;
521  std::cerr << "Size of _angle " << _angle.size() << std::endl;
522 
523  //Reco values
524  std::cerr << "Size of detected " << detected.size() << std::endl;
525  std::cerr << "Size of recopid " << recopid.size() << std::endl;
526  std::cerr << "Size of recopidecal " << recopidecal.size() << std::endl;
527  // std::cerr << "Size of prob_arr " << prob_arr.size() << std::endl;
528  std::cerr << "Size of anglereco " << anglereco.size() << std::endl;
529  std::cerr << "Size of _preco " << _preco.size() << std::endl;
530  std::cerr << "Size of erecon " << erecon.size() << std::endl;
531  std::cerr << "Size of etime " << etime.size() << std::endl;
532 
533  //Geometry
534  std::cerr << "Size of isFidStart " << isFidStart.size() << std::endl;
535  std::cerr << "Size of isTPCStart " << isTPCStart.size() << std::endl;
536  std::cerr << "Size of isCaloStart " << isCaloStart.size() << std::endl;
537  std::cerr << "Size of isThroughCaloStart " << isThroughCaloStart.size() << std::endl;
538  std::cerr << "Size of isInBetweenStart " << isInBetweenStart.size() << std::endl;
539  std::cerr << "Size of isBarrelStart " << isBarrelStart.size() << std::endl;
540  std::cerr << "Size of isEndcapStart " << isEndcapStart.size() << std::endl;
541 
542  std::cerr << "Size of isFidEnd " << isFidEnd.size() << std::endl;
543  std::cerr << "Size of isTPCEnd " << isTPCEnd.size() << std::endl;
544  std::cerr << "Size of isCaloEnd " << isCaloEnd.size() << std::endl;
545  std::cerr << "Size of isThroughCaloEnd " << isThroughCaloEnd.size() << std::endl;
546  std::cerr << "Size of isInBetweenEnd " << isInBetweenEnd.size() << std::endl;
547  std::cerr << "Size of isBarrelEnd " << isBarrelEnd.size() << std::endl;
548  std::cerr << "Size of isEndcapEnd " << isEndcapEnd.size() << std::endl;
549 
550  std::cerr << "Event with wrong vector sizes... skipped" << std::endl;
551  }
552 
553  }
554 
555  //==============================================================================
557  {
558  auto MCTHandle = e.getHandle< std::vector<simb::MCTruth> >(fGeneratorLabel);
559  if (!MCTHandle) {
560  throw cet::exception("ParamSim") << " No simb::MCTruth branch."
561  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
562  }
563 
564  auto GTHandle = e.getHandle< std::vector<simb::GTruth> >(fGeneratorLabel);
565  if (!GTHandle) {
566  throw cet::exception("ParamSim") << " No simb::GTruth branch."
567  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
568  }
569 
570  // save MCTruth info
571  for ( auto const& mct : (*MCTHandle) ) {
572  if (mct.NeutrinoSet()) {
573  simb::MCNeutrino nuw = mct.GetNeutrino();
574  ccnc.push_back(nuw.CCNC());
575  ntype.push_back(nuw.Nu().PdgCode());
576  q2.push_back(nuw.QSqr());
577  w.push_back(nuw.W());
578  y.push_back(nuw.Y());
579  x.push_back(nuw.X());
580  theta.push_back(nuw.Theta());
581  mode.push_back(nuw.Mode());
582  intert.push_back(nuw.InteractionType());
583  if(fCorrect4origin){
584  vertx.push_back(nuw.Nu().EndX() - fOrigin[0]);
585  verty.push_back(nuw.Nu().EndY() - fOrigin[1]);
586  vertz.push_back(nuw.Nu().EndZ() - fOrigin[2]);
587  } else {
588  vertx.push_back(nuw.Nu().EndX());
589  verty.push_back(nuw.Nu().EndY());
590  vertz.push_back(nuw.Nu().EndZ());
591  }
592  mcnupx.push_back(nuw.Nu().Px());
593  mcnupy.push_back(nuw.Nu().Py());
594  mcnupz.push_back(nuw.Nu().Pz());
595  } // end MC info from MCTruth
596  }
597 
598  // save GTruth info
599  for ( auto const& gt : (*GTHandle) ) {
600  gint.push_back(gt.fGint);
601  tgtpdg.push_back(gt.ftgtPDG);
602  weight.push_back(gt.fweight);
603  gt_t.push_back(gt.fgT);
604  }
605  }
606 
607  //==============================================================================
609  {
610  auto MCPHandle = e.getHandle< std::vector<simb::MCParticle> >(fGeantLabel);
611  if (!MCPHandle) {
612  throw cet::exception("anatree") << " No simb::MCParticle branch."
613  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
614  }
615 
616  std::unordered_map<int, int> TrackIdToIndex;
617  int index = 0;
618  for ( auto const& mcp : (*MCPHandle) ) {
619  int TrackId = mcp.TrackId();
620  TrackIdToIndex[TrackId] = index++;
621  }
622 
623  //Loop over the mcp
624  for ( auto const& mcp : (*MCPHandle) ) {
625 
626  const TDatabasePDG* databasePDG = TDatabasePDG::Instance();
627  const TParticlePDG* definition = databasePDG->GetParticle( mcp.PdgCode() );
628  if (definition == nullptr) continue;
629 
630  const std::string mcp_process = mcp.Process();
631  const std::string mcp_endprocess = mcp.EndProcess();
632  const int mctrackid = mcp.TrackId();
633  const int mothertrackid = mcp.Mother();
634  const int pdg = mcp.PdgCode();
635  const TLorentzVector& position = mcp.Position(0);
636  const TVector3 spoint(position.X() - fOrigin[0], position.Y() - fOrigin[1], position.Z() - fOrigin[2]);
637  const TLorentzVector& positionEnd = mcp.EndPosition();
638  const TVector3 epoint(positionEnd.X() - fOrigin[0], positionEnd.Y() - fOrigin[1], positionEnd.Z() - fOrigin[2]);
639  const TLorentzVector& momentum = mcp.Momentum(0);
640  const TVector3 mom(momentum.X(), momentum.Y(), momentum.Z());
641  const float ptrue = mom.Mag();
642  const float angle = atan(mom.X() / mom.Z());
643  const float time = mcp.T();
644  int motherpdg = 0;
645 
646  //Find out mother pdg
647  if(TrackIdToIndex.find(mothertrackid) != TrackIdToIndex.end()) {
648  motherpdg = (*MCPHandle).at(TrackIdToIndex[mothertrackid]).PdgCode();
649  }
650 
651  //need to ignore neutrals for this - put the value to 0
652  auto result = std::find(pdg_neutral.begin(), pdg_neutral.end(), abs(pdg));
653  bool isNeutral = (result != pdg_neutral.end()) ? true : false;
654 
655  if( isNeutral )
656  {
657  trkLen.push_back(-1);
658  trkLenPerp.push_back(-1);
659  }
660  else {
661  ComputeTrkLength(mcp);
662  }
663 
664  float ecaltime = fHelper->GaussianSmearing(time, fECALTimeResolution);
665 
666  //Store common mcp properties
667  FillCommonVariables(pdg, momentum, position, positionEnd, mctrackid, mothertrackid, motherpdg, ptrue, angle, mcp_process, mcp_endprocess, time);
668 
669  //Treat visible particles in the TPC
670  if( trkLen.at(_nFSP) > gastpc_len ) {
671  TreatTPCVisible(ecaltime);
672  }
673  else
674  {
675  TreatTPCNotVisible(ecaltime);
676  }// end trkLen.at(_nFSP) < gastpc_len
677 
678  _nFSP++;
679  }//end loop mcp
680  }
681 
682  //==============================================================================
683  void ParamSim::FillCommonVariables(const int pdg, const TLorentzVector& momentum, const TLorentzVector& position, const TLorentzVector& positionEnd, const int mctrackid, const int mothertrackid, const int motherpdg, const float ptrue, const float angle, const std::string mcp_process, const std::string mcp_endprocess, const float time)
684  {
685  const TVector3 spoint(position.X() - fOrigin[0], position.Y() - fOrigin[1], position.Z() - fOrigin[2]);
686  const TVector3 epoint(positionEnd.X() - fOrigin[0], positionEnd.Y() - fOrigin[1], positionEnd.Z() - fOrigin[2]);
687 
688  truepdg.push_back(pdg);
689  truepx.push_back(momentum.X());
690  truepy.push_back(momentum.Y());
691  truepz.push_back(momentum.Z());
692 
693  if(fCorrect4origin){
694  _MCPStartX.push_back(position.X() - fOrigin[0]);
695  _MCPStartY.push_back(position.Y() - fOrigin[1]);
696  _MCPStartZ.push_back(position.Z() - fOrigin[2]);
697  _MCPEndX.push_back(positionEnd.X() - fOrigin[0]);
698  _MCPEndY.push_back(positionEnd.Y() - fOrigin[1]);
699  _MCPEndZ.push_back(positionEnd.Z() - fOrigin[2]);
700  } else {
701  _MCPStartX.push_back(position.X());
702  _MCPStartY.push_back(position.Y());
703  _MCPStartZ.push_back(position.Z());
704  _MCPEndX.push_back(positionEnd.X());
705  _MCPEndY.push_back(positionEnd.Y());
706  _MCPEndZ.push_back(positionEnd.Z());
707  }
708 
709  // save the true momentum
710  truep.push_back(ptrue);
711  // save the true angle
712  _angle.push_back(angle);
713  //Save MC process
714  _MCProc.push_back(mcp_process);
715  _MCEndProc.push_back(mcp_endprocess);
716  mctime.push_back(time);
717  mctrkid.push_back(mctrackid);
718  motherid.push_back(mothertrackid);
719  pdgmother.push_back(motherpdg);
720 
721  isFidStart.push_back(fHelper->PointInFiducial(spoint));
722  isTPCStart.push_back(fHelper->PointInTPC(spoint));
723  isCaloStart.push_back(fHelper->PointInCalo(spoint));
724  isThroughCaloStart.push_back(fHelper->isThroughCalo(spoint));
725  isInBetweenStart.push_back(fHelper->PointStopBetween(spoint));
726  isBarrelStart.push_back(fHelper->isBarrel(spoint));
727  isEndcapStart.push_back(fHelper->isEndcap(spoint));
728  //Check where endpoint of mcp is
729  isFidEnd.push_back(fHelper->PointInFiducial(epoint));
730  isTPCEnd.push_back(fHelper->PointInTPC(epoint));
731  isCaloEnd.push_back(fHelper->PointInCalo(epoint));
732  isThroughCaloEnd.push_back(fHelper->isThroughCalo(epoint));
733  isInBetweenEnd.push_back(fHelper->PointStopBetween(epoint));
734  isBarrelEnd.push_back(fHelper->isBarrel(epoint));
735  isEndcapEnd.push_back(fHelper->isEndcap(epoint));
736  }
737 
738  //==============================================================================
740  {
741  //start track length
742  //***************************************************************************************************************/
743 
744  // calculate the total and the transverse track lengths and restrict the
745  // tracklength to be above the gas TPC track length threshold
746  double tracklen = 0.;
747  double tracklen_perp = 0.;
748 
749  //CAREFUL No offset for the trajectory points (origin for them is the TPC?)??????
750  //TODO check if the mcp point is within the TPC volume! Skip for mcp in the ECAL (showers)
751  //TODO Link showers to original mcp?
752  for(size_t itraj = 1; itraj < mcp.Trajectory().size(); itraj++)
753  {
754  float xTraj = mcp.Trajectory().X(itraj);
755  float yTraj = mcp.Trajectory().Y(itraj);
756  float zTraj = mcp.Trajectory().Z(itraj);
757 
758  //Traj point+1
759  TVector3 point(xTraj - fOrigin[0], yTraj - fOrigin[1], zTraj - fOrigin[2]);
760 
761  //point is not in the TPC anymore - stop traj loop
762  if(not fHelper->PointInTPC(point))
763  continue;
764 
765  // find the length of the track by getting the distance between each hit
766  TVector3 diff(xTraj - mcp.Trajectory().X(itraj - 1), yTraj - mcp.Trajectory().Y(itraj - 1), zTraj - mcp.Trajectory().Z(itraj - 1));
767  // perp length
768  TVector2 tracklen_perp_vec(zTraj - mcp.Trajectory().Z(itraj - 1), yTraj - mcp.Trajectory().Y(itraj - 1));
769  // Summing up
770  tracklen += diff.Mag();
771  tracklen_perp += tracklen_perp_vec.Mod();
772  }
773 
774  trkLen.push_back(tracklen);
775  trkLenPerp.push_back(tracklen_perp);
776  }
777 
778  //==============================================================================
779  void ParamSim::DoRangeCalculation(float &preco, float &angle_reco)
780  {
781  // calculate number of trackpoints
782  float nHits = round (trkLen.at(_nFSP) / gastpc_padPitch);
783  // angular resolution first term
784  float sigma_angle_1 = ((sigma_x * sigma_x * 0.0001) / trkLen.at(_nFSP)*trkLen.at(_nFSP)*0.0001) * (12*(nHits-1))/(nHits*(nHits+1));
785  // scattering term in Gluckstern formula
786  float sigma_angle_2 = (0.015*0.015 / (3. * truep.at(_nFSP) * truep.at(_nFSP))) * (trkLen.at(_nFSP)/gastpc_X0);
787  // angular resolution from the two terms above
788  float sigma_angle_short = sqrt(sigma_angle_1 + sigma_angle_2);
789 
790  //reconstructed angle
791  angle_reco = fHelper->GaussianSmearing(_angle.at(_nFSP), sigma_angle_short);
792  //reconstructed momentum
793  preco = fHelper->GaussianSmearing( truep.at(_nFSP), sigmaP_short );
794  }
795 
796  //==============================================================================
797  void ParamSim::DoGluckSternCalculation(float &preco, float &angle_reco)
798  {
799  //Case where the endpoint is not in the TPC, should be able to use the Gluckstern formula
800  // calculate number of trackpoints
801  float nHits = round (trkLen.at(_nFSP) / gastpc_padPitch);
802  // measurement term in Gluckstern formula
803  float fracSig_meas = sqrt(720./(nHits+4)) * ((0.01*gastpc_padPitch*truep.at(_nFSP)) / (0.3 * gastpc_B * 0.0001 *trkLenPerp.at(_nFSP)*trkLenPerp.at(_nFSP)));
804  // multiple Coulomb scattering term in Gluckstern formula
805  float fracSig_MCS = (0.052*sqrt(1.43)) / (gastpc_B * sqrt(gastpc_X0*trkLenPerp.at(_nFSP)*0.0001));
806  // momentum resoltion from the two terms above
807  float sigmaP = truep.at(_nFSP) * sqrt( fracSig_meas*fracSig_meas + fracSig_MCS*fracSig_MCS );
808  // now Gaussian smear the true momentum using the momentum resolution
809  preco = fHelper->GaussianSmearing( truep.at(_nFSP), sigmaP );
810 
811  // measurement term in the Gluckstern formula for calculating the
812  // angular resolution
813  float sigma_angle_1 = ((sigma_x * sigma_x * 0.0001) / trkLen.at(_nFSP)*trkLen.at(_nFSP)*0.0001) * (12*(nHits-1))/(nHits*(nHits+1));
814  // scattering term in Gluckstern formula
815  float sigma_angle_2 = (0.015*0.015 / (3. * truep.at(_nFSP) * truep.at(_nFSP))) * (trkLen.at(_nFSP)/gastpc_X0);
816  // angular resolution from the two terms above
817  float sigma_angle = sqrt(sigma_angle_1 + sigma_angle_2);
818  // now Gaussian smear the true angle using the angular resolution
819  angle_reco = fHelper->GaussianSmearing(_angle.at(_nFSP), sigma_angle);
820  }
821 
822  //==============================================================================
823  void ParamSim::TreatTPCVisible(const float ecaltime)
824  {
825  //start tpc
826  //***************************************************************************************************************/
827  int pdg = truepdg.at(_nFSP);
828 
829  if ( std::find(pdg_charged.begin(), pdg_charged.end(), std::abs(pdg)) != pdg_charged.end() )
830  {
831  TVector3 epoint(_MCPEndX.at(_nFSP), _MCPEndY.at(_nFSP), _MCPEndZ.at(_nFSP));
832  float ptrue = truep.at(_nFSP);
833 
834  //Use range instead of Gluckstern for stopping tracks
835  //TODO is that correct? What if it is a scatter in the TPC? Need to check if daughter is same particle
836  float preco = 0.;
837  float angle_reco = 0.;
838 
839  //Case for range, the end point of the mcp is in the TPC, does not reach the ecal
840  if( fHelper->PointInTPC(epoint) )
841  {
842  DoRangeCalculation(preco, angle_reco);
843 
844  if(preco > 0)
845  _preco.push_back(preco);
846  else
847  _preco.push_back(-1);
848  anglereco.push_back(angle_reco);
849  erecon.push_back(-1);
850  recopidecal.push_back(-1);
851  etime.push_back(-1);
852  detected.push_back(-1);
853  }
854  else
855  {
856  DoGluckSternCalculation(preco, angle_reco);
857 
858  // save reconstructed momentum and angle to cafanatree
859  if(preco > 0)
860  _preco.push_back(preco);
861  else
862  _preco.push_back(-1);
863  anglereco.push_back(angle_reco);
864 
865  //Reaches the ECAL and stops there
866  if( fHelper->PointInCalo(epoint) )
867  {
868  //Need energy measurement in ecal
869  TParticlePDG *part = TDatabasePDG::Instance()->GetParticle(abs(pdg));
870  if(nullptr == part)
871  {
872  //deuteron
873  if( pdg == 1000010020 )
874  {
875  float mass = 1.8756;//in GeV mass deuteron
876  float etrue = std::sqrt(ptrue*ptrue + mass*mass) - mass;
877  float ECAL_resolution = fRes->Eval(etrue)*etrue;
878  float ereco = fHelper->GaussianSmearing(etrue, ECAL_resolution);
879  erecon.push_back((ereco > 0) ? ereco : 0.);
880  recopidecal.push_back(-1);
881  detected.push_back(1);
882  etime.push_back(ecaltime);
883  }
884  else
885  {
886  erecon.push_back(-1);
887  recopidecal.push_back(-1);
888  detected.push_back(0);
889  etime.push_back(-1);
890  }
891  }
892  else
893  {
894  //by default should be tagged as an electron as it has a track,
895  //otherwise tag as gamma if not track -> need mis association rate, and use dE/dX in Scintillator?
896  //separation between e and mu/pi should be around 100%
897  //separation mu/pi -> based on Chris study with only the ECAL (no Muon ID detector)
898  //separation with p and mu/pi/e ?? high energy -> confusion with mu/pi, low energy confusion with e
899  //using E/p to ID?
900  float mass = part->Mass();//in GeV
901  float etrue = std::sqrt(ptrue*ptrue + mass*mass) - mass;
902  float ECAL_resolution = fRes->Eval(etrue)*etrue;
903  float ereco = fHelper->GaussianSmearing(etrue, ECAL_resolution);
904  erecon.push_back((ereco > 0) ? ereco : 0.);
905  detected.push_back(1);
906  etime.push_back(ecaltime);
907 
908  //Electron
909  if( abs(pdg) == 11 ){
910  recopidecal.push_back(11);
911  }
912  else if( abs(pdg) == 13 || abs(pdg) == 211 )
913  {
914  //Muons and Pions
915  //ptrue < 480 MeV/c 100% separation
916  //80% from 480 to 750
917  //90% up to 750 to 900
918  //95% over 900
919  float random_number = fHelper->GetRamdomNumber();
920 
921  if(ptrue < 0.48) {
922  recopidecal.push_back(abs(pdg));//100% efficiency by range
923  }
924  else if(ptrue >= 0.48 && ptrue < 0.75)
925  {
926  //case muon
927  if(abs(pdg) == 13)
928  {
929  if(random_number > (1 - 0.8)) {
930  recopidecal.push_back(13);
931  }
932  else{
933  recopidecal.push_back(211);
934  }
935  }
936  //case pion
937  if(abs(pdg) == 211)
938  {
939  if(random_number > (1 - 0.8)) {
940  recopidecal.push_back(211);
941  }
942  else{
943  recopidecal.push_back(13);
944  }
945  }
946  }
947  else if(ptrue >= 0.75 && ptrue < 0.9)
948  {
949  //case muon
950  if(abs(pdg) == 13){
951  if(random_number > (1 - 0.9)) {
952  recopidecal.push_back(13);
953  }
954  else{
955  recopidecal.push_back(211);
956  }
957  }
958  //case pion
959  if(abs(pdg) == 211) {
960  if(random_number > (1 - 0.9)) {
961  recopidecal.push_back(211);
962  }
963  else{
964  recopidecal.push_back(13);
965  }
966  }
967  }
968  else
969  {
970  //case muon
971  if(abs(pdg) == 13){
972  if(random_number > (1 - 0.95)) {
973  recopidecal.push_back(13);
974  }
975  else{
976  recopidecal.push_back(211);
977  }
978  }
979  //case pion
980  if(abs(pdg) == 211){
981  if(random_number > (1 - 0.95)) {
982  recopidecal.push_back(211);
983  }
984  else{
985  recopidecal.push_back(13);
986  }
987  }
988  }
989  }
990  else if( abs(pdg) == 2212 )
991  {
992  recopidecal.push_back(2212);//TODO for p/pi separation
993  }
994  else {
995  recopidecal.push_back(-1);
996  }
997  }
998  }
999  else if( fHelper->isThroughCalo(epoint) )
1000  {
1001  //Case the endpoint is outside the CALO -> it went through the ECAL (mu/pi/p possible)
1002  //the ECAL will see 60 MIPs on average
1003  double Evis = (double)nLayers; //in MIP
1004  //Smearing to account for Gaussian detector noise (Landau negligible)
1005  Evis = fHelper->GaussianSmearing(Evis, ECAL_MIP_Res);
1006  //1 MIP = 0.814 MeV
1007  double Erec = Evis * MIP2GeV_factor;
1008  erecon.push_back((Erec > 0) ? Erec : 0.);
1009  etime.push_back(ecaltime);
1010  detected.push_back(1);
1011 
1012  //Muon/Pions/Protons are reco as Muons (without MuID detector)
1013  if( abs(pdg) == 13 || abs(pdg) == 211 || abs(pdg) == 2212 ) {
1014  recopidecal.push_back(13);
1015  }
1016  else{
1017  recopidecal.push_back(-1);
1018  }
1019  }
1020  else
1021  {
1022  //Does not reach the ECAL???
1023  erecon.push_back(-1);
1024  recopidecal.push_back(-1);
1025  etime.push_back(-1);
1026  detected.push_back(0);
1027  }
1028  } //end endpoint is not in TPC
1029 
1031 
1032  } // end is charged mcp
1033  else
1034  {
1035  //not in the pdglist of particles but visible in TPC?
1036  auto found = std::find(pdg_charged.begin(), pdg_charged.end(), abs(pdg));
1037  if(found == pdg_charged.end())
1038  {
1039  detected.push_back(0);
1040  etime.push_back(-1);
1041  erecon.push_back(-1);
1042  _preco.push_back(-1);
1043  anglereco.push_back(-1);
1044  recopid.push_back(-1);
1045  recopidecal.push_back(-1);
1046  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1047  }
1048  }
1049 
1050  //end tpc
1051  //***************************************************************************************************************/
1052  }
1053 
1055  {
1056  //start pid
1057  //***************************************************************************************************************/
1058 
1059  int pdg = truepdg.at(_nFSP);
1060 
1061  for (int pidm = 0; pidm < 6; ++pidm)
1062  {
1063  if ( abs(pdg) == pdg_charged.at(pidm) )
1064  {
1065  float p = _preco.at(_nFSP);
1066  std::vector<double> vec;
1067  std::vector<std::string> pnamelist = {"#pi", "#mu", "p", "K", "d", "e"};
1068  std::vector<std::string> recopnamelist = {"#pi", "#mu", "p", "K", "d", "e"};
1069 
1070  int qclosest = 0;
1071  float dist = 100000000.;
1072 
1073  for (int q = 0; q < 501; ++q)
1074  {
1075  //Check the title and the reco momentum take only the one that fits
1076  std::string fulltitle = m_pidinterp[q]->GetTitle();
1077  unsigned first = fulltitle.find("=");
1078  unsigned last = fulltitle.find("GeV");
1079  std::string substr = fulltitle.substr(first+1, last - first-1);
1080  float pidinterp_mom = std::atof(substr.c_str());
1081  //calculate the distance between the bin and mom, store the q the closest
1082  float disttemp = std::abs(pidinterp_mom - p);
1083 
1084  if( disttemp < dist ) {
1085  dist = disttemp;
1086  qclosest = q;
1087  }
1088  } // closes the "pidmatrix" loop
1089 
1090  //loop over the columns (true pid)
1091  std::vector< std::pair<float, std::string> > v_prob;
1092  //get true particle name
1093  std::string trueparticlename = m_pidinterp[qclosest]->GetXaxis()->GetBinLabel(pidm+1);
1094  // std::cout << trueparticlename << std::endl;
1095  if ( trueparticlename == pnamelist[pidm] )
1096  {
1097  //loop over the rows (reco pid)
1098  for (int pidr = 0; pidr < 6; ++pidr)
1099  {
1100  std::string recoparticlename = m_pidinterp[qclosest]->GetYaxis()->GetBinLabel(pidr+1);
1101  // std::cout << recoparticlename << std::endl;
1102  if (recoparticlename == recopnamelist[pidr])
1103  {
1104  float prob = m_pidinterp[qclosest]->GetBinContent(pidm+1,pidr+1);
1105  prob_arr.push_back(prob);
1106  //Need to check random number value and prob value then associate the recopdg to the reco prob
1107  v_prob.push_back( std::make_pair(prob, recoparticlename) );
1108  }
1109  }
1110 
1111  int pid = -1;
1112  if(v_prob.size() > 1)
1113  {
1114  //Order the vector of prob
1115  std::sort(v_prob.begin(), v_prob.end());
1116  //Throw a random number between 0 and 1
1117  float random_number = fHelper->GetRamdomNumber();
1118  //Make cumulative sum to get the range
1119  std::partial_sum(v_prob.begin(), v_prob.end(), v_prob.begin(), [](const std::pair<float, std::string>& _x, const std::pair<float, std::string>& _y){return std::pair<float, std::string>(_x.first + _y.first, _y.second);});
1120  for(size_t ivec = 0; ivec < v_prob.size()-1; ivec++)
1121  {
1122  if( random_number < v_prob.at(ivec+1).first && random_number >= v_prob.at(ivec).first )
1123  {
1124  pid = pdg_charged.at( std::distance( recopnamelist.begin(), std::find(recopnamelist.begin(), recopnamelist.end(), v_prob.at(ivec+1).second) ) );
1125  }
1126  }
1127  }
1128  else
1129  {
1130  pid = pdg_charged.at( std::distance( recopnamelist.begin(), std::find(recopnamelist.begin(), recopnamelist.end(), v_prob.at(0).second) ) );
1131  }
1132 
1133  recopid.push_back( pid );
1134  } // closes the if statement
1135  } // end if charged in pdg list
1136  } // end loop pidm
1137 
1138  //end pid
1139  //***************************************************************************************************************/
1140  }
1141 
1142  //==============================================================================
1143  void ParamSim::TreatTPCNotVisible(const float ecaltime)
1144  {
1145  int pdg = truepdg.at(_nFSP);
1146 
1147  //Case neutrinos
1148  if(std::find(neutrinos.begin(), neutrinos.end(), std::abs(pdg)) != neutrinos.end())
1149  {
1150  detected.push_back(0);
1151  etime.push_back(0.);
1152  erecon.push_back(0.);
1153  recopidecal.push_back(-1);
1154  _preco.push_back(-1);
1155  anglereco.push_back(-1);
1156  recopid.push_back(-1);
1157  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1158  }
1159  else if( std::abs(pdg) == 2112 )
1160  {
1161  TreatNeutrons(ecaltime);
1162  }
1163  else if(std::abs(pdg) == 111)
1164  {
1165  //Pi0 case
1166  erecon.push_back(-1);
1167  recopid.push_back(-1);
1168  detected.push_back(0);
1169  recopidecal.push_back(-1);
1170  etime.push_back(-1);
1171  _preco.push_back(-1);
1172  anglereco.push_back(-1);
1173 
1174  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1175  }
1176  else if(std::abs(pdg) == 22)
1177  {
1178  TreatPhotons(ecaltime);
1179  }
1180  else
1181  {
1182  TreatOthers(ecaltime);
1183  }//end case charged but not visible in TPC
1184  }
1185 
1186  //==============================================================================
1187  void ParamSim::TreatNeutrons(const float ecaltime)
1188  {
1189  TVector3 epoint(_MCPEndX.at(_nFSP), _MCPEndY.at(_nFSP), _MCPEndZ.at(_nFSP));
1190  //start neutrons
1191  //***************************************************************************************************************/
1192 
1193  if(fHelper->PointInCalo(epoint)) //needs to stop in the ECAL
1194  {
1195  //check if it can be detected by the ECAL
1196  //Assumes 40% efficiency to detect
1197  float random_number = fHelper->GetRamdomNumber();
1198  float true_KE = std::sqrt(truep.at(_nFSP)*truep.at(_nFSP) + neutron_mass*neutron_mass) - neutron_mass;
1199  // float true_KE = ptrue*ptrue / (2*neutron_mass); // in GeV
1200  int index = (true_KE >= 0.05) ? 1 : 0;
1201 
1202  if(random_number > (1 - NeutronECAL_detEff[index]) && true_KE > 0.003)//Threshold of 3 MeV
1203  {
1204  //TODO random is first interaction or rescatter and smear accordingly to Chris's study
1205  //Detected in the ECAL
1206  recopid.push_back(-1); //reco pid set to 0?
1207  detected.push_back(1);
1208  float eres = sigmaNeutronECAL_first * true_KE;
1209  float ereco = fHelper->GaussianSmearing( true_KE, eres );
1210  erecon.push_back(ereco > 0 ? ereco : 0.);
1211  etime.push_back(ecaltime);
1212  _preco.push_back(-1);
1213  anglereco.push_back(-1);
1214  recopidecal.push_back(2112);
1215  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1216  }
1217  else
1218  {
1219  //neutron not detected
1220  detected.push_back(0);
1221  recopid.push_back(-1);
1222  erecon.push_back(-1);
1223  etime.push_back(-1);
1224  _preco.push_back(-1);
1225  anglereco.push_back(-1);
1226  recopidecal.push_back(-1);
1227  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1228  }
1229  } //endpoint is in ECAL
1230  else
1231  {
1232  //Endpoint is not in calo (TPC/isInBetween or outside Calo)
1233  detected.push_back(0);
1234  recopid.push_back(-1);
1235  erecon.push_back(-1);
1236  etime.push_back(-1);
1237  _preco.push_back(-1);
1238  anglereco.push_back(-1);
1239  recopidecal.push_back(-1);
1240  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1241  }
1242 
1243  //End neutrons
1244  //***************************************************************************************************************/
1245  }
1246 
1247  //==============================================================================
1248  void ParamSim::TreatPhotons(const float ecaltime)
1249  {
1250  TVector3 epoint(_MCPEndX.at(_nFSP), _MCPEndY.at(_nFSP), _MCPEndZ.at(_nFSP));
1251  //start gammas
1252  //***************************************************************************************************************/
1253 
1254  if( pdgmother.at(_nFSP) != 111 )
1255  {
1256  //Endpoint is in the ECAL
1257  if(fHelper->PointInCalo(epoint))
1258  {
1259  //if they hit the ECAL and smear their energy
1260  float ECAL_resolution = fRes->Eval(truep.at(_nFSP))*truep.at(_nFSP);
1261  float ereco = fHelper->GaussianSmearing(truep.at(_nFSP), ECAL_resolution);
1262  erecon.push_back( (ereco > 0) ? ereco : 0. );
1263  recopid.push_back(-1);
1264  detected.push_back(1);
1265  etime.push_back(ecaltime);
1266  _preco.push_back(-1);
1267  anglereco.push_back(-1);
1268  //reach the ECAL, should be tagged as gamma
1269  recopidecal.push_back(22);
1270  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1271  }
1272  else if(fHelper->PointInTPC(epoint) || fHelper->PointStopBetween(epoint) || fHelper->isThroughCalo(epoint))
1273  {
1274  erecon.push_back(-1);
1275  recopid.push_back(-1);
1276  detected.push_back(0);
1277  etime.push_back(-1);
1278  _preco.push_back(-1);
1279  anglereco.push_back(-1);
1280  //converted so not seen in ECAL
1281  recopidecal.push_back(-1);
1282  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1283  }
1284  }
1285  else
1286  {
1287  //From a pi0
1288  if(fHelper->PointInCalo(epoint))
1289  {
1290  //if they hit the ECAL and smear their energy
1291  float ECAL_resolution = fRes->Eval(truep.at(_nFSP))*truep.at(_nFSP);
1292  float ereco = fHelper->GaussianSmearing(truep.at(_nFSP), ECAL_resolution);
1293  erecon.push_back((ereco > 0) ? ereco : 0.);
1294  recopid.push_back(-1);
1295  detected.push_back(1);
1296  etime.push_back(ecaltime);
1297  _preco.push_back(-1);
1298  anglereco.push_back(-1);
1299  //reaches the ecal
1300  recopidecal.push_back(22);
1301  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1302  }
1303  else if(fHelper->PointInTPC(epoint) || fHelper->PointStopBetween(epoint) || fHelper->isThroughCalo(epoint))
1304  {
1305  //from pi0 and converted in TPC or stopped between TPC/ECAL
1306  erecon.push_back(-1);
1307  recopid.push_back(-1);
1308  detected.push_back(0);
1309  etime.push_back(-1);
1310  _preco.push_back(-1);
1311  anglereco.push_back(-1);
1312  //converted not seen by ecal
1313  recopidecal.push_back(-1);
1314  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1315  }
1316  }
1317 
1318  //end gammas
1319  //***************************************************************************************************************/
1320  }
1321 
1322  //==============================================================================
1323  void ParamSim::TreatOthers(const float ecaltime)
1324  {
1325  int pdg = truepdg.at(_nFSP);
1326  TVector3 epoint(_MCPEndX.at(_nFSP), _MCPEndY.at(_nFSP), _MCPEndZ.at(_nFSP));
1327  //Case for particles that stop or go through ECAL (problematic particles with no track length????)
1328  //Not visible in the TPC and not neutron or gamma or pi0 (otherwise it has been already done above)
1329  if(fHelper->PointInCalo(epoint))
1330  {
1331  detected.push_back(1);
1332  etime.push_back(ecaltime);
1333 
1334  TParticlePDG *part = TDatabasePDG::Instance()->GetParticle(abs(pdg));
1335  float mass = 0.;
1336  if(nullptr != part)
1337  mass = part->Mass();//in GeV
1338 
1339  float etrue = std::sqrt(truep.at(_nFSP)*truep.at(_nFSP) + mass*mass) - mass;
1340  float ECAL_resolution = fRes->Eval(etrue)*etrue;
1341  float ereco = fHelper->GaussianSmearing(etrue, ECAL_resolution);
1342  erecon.push_back((ereco > 0) ? ereco : 0.);
1343 
1344  //Electron
1345  if( abs(pdg) == 11 ){
1346  recopidecal.push_back(11);
1347  }
1348  else if( abs(pdg) == 13 || abs(pdg) == 211 )
1349  {
1350  //Muons and Pions
1351  //ptrue < 480 MeV/c 100% separation
1352  //80% from 480 to 750
1353  //90% up to 750 to 900
1354  //95% over 900
1355  float random_number = fHelper->GetRamdomNumber();
1356 
1357  if(truep.at(_nFSP) < 0.48) {
1358  recopidecal.push_back(abs(pdg));//100% efficiency by range
1359  }
1360  else if(truep.at(_nFSP) >= 0.48 && truep.at(_nFSP) < 0.75)
1361  {
1362  //case muon
1363  if(abs(pdg) == 13)
1364  {
1365  if(random_number > (1 - 0.8)) {
1366  recopidecal.push_back(13);
1367  }
1368  else{
1369  recopidecal.push_back(211);
1370  }
1371  }
1372 
1373  //case pion
1374  if(abs(pdg) == 211)
1375  {
1376  if(random_number > (1 - 0.8)) {
1377  recopidecal.push_back(211);
1378  }
1379  else{
1380  recopidecal.push_back(13);
1381  }
1382  }
1383  }
1384  else if(truep.at(_nFSP) >= 0.75 && truep.at(_nFSP) < 0.9)
1385  {
1386  //case muon
1387  if(abs(pdg) == 13){
1388  if(random_number > (1 - 0.9)) {
1389  recopidecal.push_back(13);
1390  }
1391  else{
1392  recopidecal.push_back(211);
1393  }
1394  }
1395  //case pion
1396  if(abs(pdg) == 211) {
1397  if(random_number > (1 - 0.9)) {
1398  recopidecal.push_back(211);
1399  }
1400  else{
1401  recopidecal.push_back(13);
1402  }
1403  }
1404  }
1405  else
1406  {
1407  //case muon
1408  if(abs(pdg) == 13){
1409  if(random_number > (1 - 0.95)) {
1410  recopidecal.push_back(13);
1411  }
1412  else{
1413  recopidecal.push_back(211);
1414  }
1415  }
1416  //case pion
1417  if(abs(pdg) == 211){
1418  if(random_number > (1 - 0.95)) {
1419  recopidecal.push_back(211);
1420  }
1421  else{
1422  recopidecal.push_back(13);
1423  }
1424  }
1425  }
1426  }
1427  else if( abs(pdg) == 2212 )
1428  {
1429  recopidecal.push_back(2212);//TODO for p/pi separation
1430  }
1431  else {
1432  recopidecal.push_back(-1);
1433  }
1434 
1435  _preco.push_back(-1);
1436  anglereco.push_back(-1);
1437  recopid.push_back(-1);
1438  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1439  }
1440  else if (fHelper->isThroughCalo(epoint))
1441  {
1442  //Case the endpoint is outside the CALO -> it went through the ECAL (mu/pi/p possible)
1443  //the ECAL will see 60 MIPs on average
1444  double Evis = (double)nLayers; //in MIP
1445  //Smearing to account for Gaussian detector noise (Landau negligible)
1446  Evis = fHelper->GaussianSmearing(Evis, ECAL_MIP_Res);
1447  //1 MIP = 0.814 MeV
1448  double Erec = Evis * MIP2GeV_factor;
1449  erecon.push_back((Erec > 0) ? Erec : 0.);
1450  etime.push_back(ecaltime);
1451  detected.push_back(1);
1452 
1453  //Muon/Pions/Protons are reco as Muons (without MuID detector)
1454  if( abs(pdg) == 13 || abs(pdg) == 211 || abs(pdg) == 2212 ) {
1455  recopidecal.push_back(13);
1456  }
1457  else {
1458  recopidecal.push_back(-1);
1459  }
1460 
1461  _preco.push_back(-1);
1462  anglereco.push_back(-1);
1463  recopid.push_back(-1);
1464  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1465  }
1466  else if(fHelper->PointInTPC(epoint) || fHelper->PointStopBetween(epoint))
1467  {
1468  detected.push_back(0);
1469  etime.push_back(-1);
1470  erecon.push_back(-1);
1471  _preco.push_back(-1);
1472  anglereco.push_back(-1);
1473  recopid.push_back(-1);
1474  recopidecal.push_back(-1);
1475  for (int pidr = 0; pidr < 6; ++pidr) prob_arr.push_back(-1);
1476  }
1477  }
1478 
1479  //==============================================================================
1481  {
1482  //Generator values
1483  mode.clear();
1484  ccnc.clear();
1485  ntype.clear();
1486  gint.clear();
1487  weight.clear();
1488  tgtpdg.clear();
1489  gt_t.clear();
1490  intert.clear();
1491  q2.clear();
1492  w.clear();
1493  y.clear();
1494  x.clear();
1495  theta.clear();
1496  t.clear();
1497  mcnupx.clear();
1498  mcnupy.clear();
1499  mcnupz.clear();
1500  vertx.clear();
1501  verty.clear();
1502  vertz.clear();
1503 
1504  //MC Particle values
1505  _nFSP = 0;
1506  detected.clear();
1507  pdgmother.clear();
1508  truepdg.clear();
1509  mctime.clear();
1510  mctrkid.clear();
1511  motherid.clear();
1512  _MCPStartX.clear();
1513  _MCPStartY.clear();
1514  _MCPStartZ.clear();
1515  _MCPEndX.clear();
1516  _MCPEndY.clear();
1517  _MCPEndZ.clear();
1518  _MCProc.clear();
1519  _MCEndProc.clear();
1520  trkLen.clear();
1521  trkLenPerp.clear();
1522  truep.clear();
1523  truepx.clear();
1524  truepy.clear();
1525  truepz.clear();
1526  _angle.clear();
1527 
1528  //Reco values
1529  recopid.clear();
1530  recopidecal.clear();
1531  prob_arr.clear();
1532  anglereco.clear();
1533  _preco.clear();
1534  erecon.clear();
1535  etime.clear();
1536 
1537  //Geometry
1538  isFidStart.clear();
1539  isTPCStart.clear();
1540  isCaloStart.clear();
1541  isThroughCaloStart.clear();
1542  isInBetweenStart.clear();
1543  isBarrelStart.clear();
1544  isEndcapStart.clear();
1545 
1546  isFidEnd.clear();
1547  isTPCEnd.clear();
1548  isCaloEnd.clear();
1549  isThroughCaloEnd.clear();
1550  isInBetweenEnd.clear();
1551  isBarrelEnd.clear();
1552  isEndcapEnd.clear();
1553  }
1554 
1555  //==============================================================================
1557  {
1558  bool isOK = true;
1559 
1560  if(_nFSP != pdgmother.size()) isOK = false;
1561  if(_nFSP != truepdg.size()) isOK = false;
1562  if(_nFSP != mctime.size()) isOK = false;
1563  if(_nFSP != mctrkid.size()) isOK = false;
1564  if(_nFSP != motherid.size()) isOK = false;
1565  if(_nFSP != _MCPStartX.size()) isOK = false;
1566  if(_nFSP != _MCPStartY.size()) isOK = false;
1567  if(_nFSP != _MCPStartZ.size()) isOK = false;
1568  if(_nFSP != _MCPEndX.size()) isOK = false;
1569  if(_nFSP != _MCPEndY.size()) isOK = false;
1570  if(_nFSP != _MCPEndZ.size()) isOK = false;
1571  if(_nFSP != _MCProc.size()) isOK = false;
1572  if(_nFSP != _MCEndProc.size()) isOK = false;
1573  if(_nFSP != trkLen.size()) isOK = false;
1574  if(_nFSP != trkLenPerp.size()) isOK = false;
1575  if(_nFSP != truep.size()) isOK = false;
1576  if(_nFSP != truepx.size()) isOK = false;
1577  if(_nFSP != truepy.size()) isOK = false;
1578  if(_nFSP != truepz.size()) isOK = false;
1579  if(_nFSP != _angle.size()) isOK = false;
1580 
1581  //Reco values
1582  if(_nFSP != recopid.size()) isOK = false;
1583  if(_nFSP != detected.size()) isOK = false;
1584  if(_nFSP != recopidecal.size()) isOK = false;
1585  // if(_nFSP != prob_arr.size()) isOK = false;
1586  if(_nFSP != anglereco.size()) isOK = false;
1587  if(_nFSP != _preco.size()) isOK = false;
1588  if(_nFSP != erecon.size()) isOK = false;
1589  if(_nFSP != etime.size()) isOK = false;
1590 
1591  //Geometry
1592  if(_nFSP != isFidStart.size()) isOK = false;
1593  if(_nFSP != isTPCStart.size()) isOK = false;
1594  if(_nFSP != isCaloStart.size()) isOK = false;
1595  if(_nFSP != isThroughCaloStart.size()) isOK = false;
1596  if(_nFSP != isInBetweenStart.size()) isOK = false;
1597  if(_nFSP != isBarrelStart.size()) isOK = false;
1598  if(_nFSP != isEndcapStart.size()) isOK = false;
1599 
1600  if(_nFSP != isFidEnd.size()) isOK = false;
1601  if(_nFSP != isTPCEnd.size()) isOK = false;
1602  if(_nFSP != isCaloEnd.size()) isOK = false;
1603  if(_nFSP != isThroughCaloEnd.size()) isOK = false;
1604  if(_nFSP != isInBetweenEnd.size()) isOK = false;
1605  if(_nFSP != isBarrelEnd.size()) isOK = false;
1606  if(_nFSP != isEndcapEnd.size()) isOK = false;
1607 
1608  return isOK;
1609  }
1610 
1611 } //end namespace gar
1612 
1613 namespace gar {
1615 }
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
std::vector< double > _preco
bool PointInFiducial(const TVector3 &point)
void DoGluckSternCalculation(float &preco, float &angle_reco)
void TreatTPCVisible(const float ecaltime)
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
double Z(const size_type i) const
Definition: MCTrajectory.h:151
double X(const size_type i) const
Definition: MCTrajectory.h:149
int PdgCode() const
Definition: MCParticle.h:212
int CCNC() const
Definition: MCNeutrino.h:148
CAFHelper(const geo::GeometryCore *fGeo, CLHEP::HepRandomEngine &engine)
std::vector< int > weight
std::vector< double > truepz
double QSqr() const
Definition: MCNeutrino.h:157
std::vector< int > ccnc
unsigned int fRun
double Theta() const
angle between incoming and outgoing leptons, in radians
Definition: MCNeutrino.cxx:63
CLHEP::HepRandomEngine & fEngine
random engine
double Py(const int i=0) const
Definition: MCParticle.h:231
std::vector< unsigned int > isFidEnd
void TreatPhotons(const float ecaltime)
static QCString result
const TLorentzVector & EndPosition() const
Definition: MCParticle.h:225
double EndZ() const
Definition: MCParticle.h:228
std::vector< double > y
std::vector< double > mcnupy
std::vector< std::string > _MCEndProc
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
const simb::MCTrajectory & Trajectory() const
Definition: MCParticle.h:253
const float sigmaP_short
int Mother() const
Definition: MCParticle.h:213
std::vector< unsigned int > isBarrelStart
std::vector< int > detected
const simb::MCParticle & Nu() const
Definition: MCNeutrino.h:146
float GetOriginX() const
Definition: GeometryCore.h:548
std::vector< int > ntype
double Px(const int i=0) const
Definition: MCParticle.h:230
unsigned int fEvent
std::vector< std::string > _MCProc
std::string fGeneratorLabel
const double fTPCFidRadius
const double MIP2GeV_factor
std::unordered_map< int, TH2F * > m_pidinterp
CLHEP::HepRandomEngine & fEngine
float GaussianSmearing(const float mean, const float sigma)
void ComputeTrkLength(const simb::MCParticle &mcp)
Description of geometry of one entire detector.
Definition: GeometryCore.h:436
bool PointInTPC(const TVector3 &point)
float GetECALOuterEndcapRadius() const
Definition: GeometryCore.h:951
std::vector< int > recopidecal
std::string Process() const
Definition: MCParticle.h:215
Particle class.
double EndY() const
Definition: MCParticle.h:227
string filename
Definition: train.py:213
std::vector< double > _angle
std::vector< double > truepx
std::vector< int > gint
void DoRangeCalculation(float &preco, float &angle_reco)
ParamSim(fhicl::ParameterSet const &p)
void TreatNeutrons(const float ecaltime)
std::vector< unsigned int > isTPCStart
int TrackId() const
Definition: MCParticle.h:210
bool isBarrel(const TVector3 &point)
std::vector< double > vertx
std::string fGeantLabel
module label for geant4 simulated hits
float GetOriginZ() const
Definition: GeometryCore.h:552
std::vector< int > motherid
std::vector< double > mcnupx
std::vector< double > vertz
std::vector< int > _MCPEndY
void TreatOthers(const float ecaltime)
int InteractionType() const
Definition: MCNeutrino.h:150
T abs(T value)
std::vector< unsigned int > isEndcapEnd
std::vector< int > truepdg
const double e
std::vector< double > verty
std::vector< unsigned int > isTPCEnd
double Y(const size_type i) const
Definition: MCTrajectory.h:150
double W() const
Definition: MCNeutrino.h:154
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::string EndProcess() const
Definition: MCParticle.h:216
void beginJob()
Definition: Breakpoints.cc:14
float TPCRadius() const
Returns the radius of the TPC (y or z direction)
Definition: GeometryCore.h:755
std::vector< int > mctrkid
double Y() const
Definition: MCNeutrino.h:156
float GetECALInnerEndcapRadius() const
Definition: GeometryCore.h:948
std::vector< unsigned int > isFidStart
std::vector< int > gt_t
T get(std::string const &key) const
Definition: ParameterSet.h:271
bool PointStopBetween(const TVector3 &point)
double T(const int i=0) const
Definition: MCParticle.h:224
std::vector< int > _MCPEndZ
std::vector< double > w
double fECALEndcapOuterRadius
p
Definition: test.py:223
std::vector< unsigned int > isThroughCaloEnd
const float gastpc_padPitch
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
const float neutron_mass
double X() const
Definition: MCNeutrino.h:155
float GetOriginY() const
Definition: GeometryCore.h:550
std::vector< int > mode
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
std::vector< double > q2
std::vector< double > truepy
RunNumber_t run() const
Definition: DataViewImpl.cc:71
double fECALEndcapInnerRadius
bool isThroughCalo(const TVector3 &point)
std::vector< double > trkLen
float GetECALEndcapStartX() const
Definition: GeometryCore.h:975
void FillCommonVariables(const int pdg, const TLorentzVector &momentum, const TLorentzVector &position, const TLorentzVector &positionEnd, const int mctrackid, const int mothertrackid, const int motherpdg, const float ptrue, const float angle, const std::string mcp_process, const std::string mcp_endprocess, const float time)
float GetECALOuterBarrelRadius() const
Definition: GeometryCore.h:945
bool isEndcap(const TVector3 &point)
std::vector< unsigned int > isEndcapStart
std::vector< double > prob_arr
void TreatMCParticles(art::Event const &e)
std::vector< int > recopid
void SaveGtruthMCtruth(art::Event const &e)
std::vector< unsigned int > isCaloStart
General GArSoft Utilities.
std::vector< double > x
std::vector< unsigned int > isThroughCaloStart
std::vector< unsigned int > isCaloEnd
size_type size() const
Definition: MCTrajectory.h:166
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
unsigned int fSubRun
std::vector< int > _MCPStartZ
std::vector< double > truep
std::vector< unsigned int > isBarrelEnd
std::vector< int > _MCPStartY
unsigned int _nFSP
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:220
std::vector< double > mcnupz
const float gastpc_X0
double Pz(const int i=0) const
Definition: MCParticle.h:232
CAFHelper * fHelper
void TPCParticleIdentification()
std::vector< double > theta
std::vector< double > t
float GetECALInnerBarrelRadius() const
Definition: GeometryCore.h:942
virtual void beginJob() override
EventNumber_t event() const
Definition: EventID.h:116
std::vector< double > mctime
list x
Definition: train.py:276
float TPCLength() const
Returns the length of the TPC (x direction)
Definition: GeometryCore.h:763
void analyze(art::Event const &e) override
const geo::GeometryCore * fGeo
pointer to the geometry
std::vector< int > intert
const float gastpc_len
def momentum(x1, x2, x3, scale=1.)
double EndX() const
Definition: MCParticle.h:226
Event generator information.
Definition: MCNeutrino.h:18
art framework interface to geometry description
bool PointInCalo(const TVector3 &point)
int Mode() const
Definition: MCNeutrino.h:149
const double fTPCFidLength
std::vector< double > anglereco
std::vector< int > _MCPEndX
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:16
std::vector< double > erecon
std::vector< unsigned int > isInBetweenEnd
std::vector< int > tgtpdg
static QCString * s
Definition: config.cpp:1042
std::vector< unsigned int > isInBetweenStart
EventID id() const
Definition: Event.cc:34
void TreatTPCNotVisible(const float ecaltime)
std::vector< int > _MCPStartX
static QCString str
std::vector< int > pdgmother
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool hasDecayedInCalo(const TVector3 &point)
QTextStream & endl(QTextStream &s)
double fECALBarrelOuterRadius
QCString & append(const char *s)
Definition: qcstring.cpp:383
float GetECALEndcapOuterX() const
Definition: GeometryCore.h:978
std::vector< double > trkLenPerp
double fECALBarrelInnerRadius
std::vector< double > etime