LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
CosmicsGen_module.cc
Go to the documentation of this file.
1 #ifndef EVGEN_COSMICSGEN_H
10 #define EVGEN_COSMICSGEN_H
11 
12 // ROOT includes
13 #include "TRandom3.h"
14 #include "TH1.h"
15 #include "TH2.h"
16 
17 // Framework includes
21 #include "fhiclcpp/ParameterSet.h"
29 
30 // art extensions
32 
33 // larsoft includes
42 
43 namespace evgen {
44 
46  class CosmicsGen : public art::EDProducer {
47  public:
48  explicit CosmicsGen(fhicl::ParameterSet const& pset);
49  virtual ~CosmicsGen();
50 
51 
52  void produce(art::Event& evt);
53  void beginJob();
54  void beginRun(art::Run& run);
55  void reconfigure(fhicl::ParameterSet const& p);
56 
57  private:
58 
60 
61  std::vector<double> fbuffbox;
62 
63  TH2F* fPhotonAngles;
67  TH1F* fPhotonCosQ;
68  TH1F* fPhotonEnergy;
71  TH1F* fPhotonsInTPC;
73 
79  TH1F* fElectronCosQ;
83  TH1F* fElectronsInTPC;
85 
87  TH2F* fMuonAngles;
88  TH2F* fMuonAnglesLo;
89  TH2F* fMuonAnglesMi;
90  TH2F* fMuonAnglesHi;
91  TH1F* fMuonCosQ;
92  TH1F* fMuonEnergy;
94  TH1F* fMuonsInCStat;
95  TH1F* fMuonsInTPC;
97 
99  };
100 }
101 
102 namespace evgen{
103 
104  //____________________________________________________________________________
106  : fCRYHelp(0)
107  {
108  // create a default random engine; obtain the random seed from NuRandomService,
109  // unless overridden in configuration with key "Seed"
111  ->createEngine(*this, pset, "Seed");
112 
113  //the buffer box bounds specified here will extend on the cryostat boundaries
114  fbuffbox = pset.get< std::vector<double> >("BufferBox",{0.0, 0.0, 0.0, 0.0, 0.0, 0.0});
115 
116  this->reconfigure(pset);
117 
118  produces< std::vector<simb::MCTruth> >();
119  produces< sumdata::RunData, art::InRun >();
120  }
121 
122  //____________________________________________________________________________
124  {
125  if(fCRYHelp) delete fCRYHelp;
126  }
127 
128  //____________________________________________________________________________
130  {
131  if(fCRYHelp){
132  delete fCRYHelp;
133  fCRYHelp = 0;
134  }
135 
136  // get the random number generator service and make some CLHEP generators
138  CLHEP::HepRandomEngine& engine = rng->getEngine();
139 
141 
142  fCRYHelp = new evgb::CRYHelper(p, engine, geo->GetWorldVolumeName());
143 
144  return;
145  }
146 
147  //____________________________________________________________________________
149  {
151 
152  fPhotonAngles = tfs->make<TH2F>("fPhotonAngles", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
153  fPhotonAnglesLo = tfs->make<TH2F>("fPhotonAnglesLo", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
154  fPhotonAnglesMi = tfs->make<TH2F>("fPhotonAnglesMi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
155  fPhotonAnglesHi = tfs->make<TH2F>("fPhotonAnglesHi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
156  fPhotonCosQ = tfs->make<TH1F>("fPhotonCosQ", ";cos#theta;tracks", 50,-1.0,1.0);
157  fPhotonEnergy = tfs->make<TH1F>("fPhotonEnergy", ";E (GeV)", 5000,0.0,1000.0);
158  fPhotonsPerSample = tfs->make<TH1F>("fPhotonsPerSample", ";Number Photons;Samples", 100, 0, 1000);
159  fPhotonsInCStat = tfs->make<TH1F>("fPhotonsInCryostat", ";Number Photons;Samples", 100, 0, 1000);
160  fPhotonsInTPC = tfs->make<TH1F>("fPhotonsInTPC", ";Number Photons;Samples", 100, 0, 1000);
161 
162  fElectronAngles = tfs->make<TH2F>("fElectronAngles", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
163  fElectronAnglesLo = tfs->make<TH2F>("fElectronAnglesLo", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
164  fElectronAnglesMi = tfs->make<TH2F>("fElectronAnglesMi", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
165  fElectronAnglesHi = tfs->make<TH2F>("fElectronAnglesHi", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
166  fElectronCosQ = tfs->make<TH1F>("fElectronCosQ", ";cos#theta;tracks",50,-1.0,1.0);
167  fElectronEnergy = tfs->make<TH1F>("fElectronEnergy", ";E (GeV)", 5000,0.0,1000.0);
168  fElectronsPerSample = tfs->make<TH1F>("fElectronsPerSample", ";Number Electrons;Samples", 100, 0, 1000);
169  fElectronsInCStat = tfs->make<TH1F>("fElectronsInCryotat", ";Number Electrons;Samples", 100, 0, 1000);
170  fElectronsInTPC = tfs->make<TH1F>("fElectronsInTPC", ";Number Electrons;Samples", 100, 0, 1000);
171 
172  fMuonAngles = tfs->make<TH2F>("fMuonAngles", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
173  fMuonAnglesLo = tfs->make<TH2F>("fMuonAnglesLo", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
174  fMuonAnglesMi = tfs->make<TH2F>("fMuonAnglesMi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
175  fMuonAnglesHi = tfs->make<TH2F>("fMuonAnglesHi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
176  fMuonCosQ = tfs->make<TH1F>("fMuonCosQ", ";cos#theta;tracks",50,-1.0,1.0);
177  fMuonEnergy = tfs->make<TH1F>("fMuonEnergy", ";E (GeV)", 5000,0.0,1000.0);
178  fMuonsPerSample = tfs->make<TH1F>("fMuonsPerSample", ";Number Muons;Samples", 100, 0, 1000);
179  fMuonsInCStat = tfs->make<TH1F>("fMuonsInCryostat", ";Number Muons;Samples", 100, 0, 1000);
180  fMuonsInTPC = tfs->make<TH1F>("fMuonsInTPC", ";Number Muons;Samples", 100, 0, 1000);
181 
182  }
183 
184  //____________________________________________________________________________
186  {
187 
188  // grab the geometry object to see what geometry we are using
190 
191  std::unique_ptr<sumdata::RunData> runcol(new sumdata::RunData(geo->DetectorName()));
192 
193  run.put(std::move(runcol));
194 
195  return;
196  }
197 
198  //____________________________________________________________________________
200  {
201  std::unique_ptr< std::vector<simb::MCTruth> > truthcol(new std::vector<simb::MCTruth>);
202 
203  // fill some histograms about this event
205 
206  int nCrossCryostat = 0;
207 
208  simb::MCTruth truth;
209 
210  while(nCrossCryostat < 1){
211 
212  simb::MCTruth pretruth;
214  fCRYHelp->Sample(pretruth,
215  geom->SurfaceY(),
216  geom->DetLength(),
217  0);
218 
219  int numPhotons = 0;
220  int numElectrons = 0;
221  int numMuons = 0;
222  int allPhotons = 0;
223  int allElectrons = 0;
224  int allMuons = 0;
225  // for c2: remove unused variables
226  //int tpcPhotons = 0;
227  //int tpcElectrons = 0;
228  //int tpcMuons = 0;
229 
230  // loop over particles in the truth object
231  for(int i = 0; i < pretruth.NParticles(); ++i){
232  simb::MCParticle particle = pretruth.GetParticle(i);
233  const TLorentzVector& v4 = particle.Position();
234  const TLorentzVector& p4 = particle.Momentum();
235  double x0[3] = {v4.X(), v4.Y(), v4.Z() };
236  double dx[3] = {p4.Px(), p4.Py(), p4.Pz()};
237 
238  if (std::abs(particle.PdgCode())==13) ++allMuons;
239  else if (std::abs(particle.PdgCode())==22) ++allPhotons;
240  else if (std::abs(particle.PdgCode())==11) ++allElectrons;
241 
242  TH1F* hCosQ = 0;
243  TH2F* hAngles = 0;
244  TH2F* hAnglesLo = 0;
245  TH2F* hAnglesMi = 0;
246  TH2F* hAnglesHi = 0;
247  TH1F* hEnergy = 0;
248  if (std::abs(particle.PdgCode())==13) {
249  hCosQ = fMuonCosQ;
250  hAngles = fMuonAngles;
251  hAnglesLo = fMuonAnglesLo;
252  hAnglesMi = fMuonAnglesMi;
253  hAnglesHi = fMuonAnglesHi;
254  hEnergy = fMuonEnergy;
255  }
256  else if (std::abs(particle.PdgCode())==22) {
257  hCosQ = fPhotonCosQ;
258  hAngles = fPhotonAngles;
259  hAnglesLo = fPhotonAnglesLo;
260  hAnglesMi = fPhotonAnglesMi;
261  hAnglesHi = fPhotonAnglesHi;
262  hEnergy = fPhotonEnergy;
263  }
264  else if (std::abs(particle.PdgCode())==11) {
265  hCosQ = fElectronCosQ;
266  hAngles = fElectronAngles;
267  hAnglesLo = fElectronAnglesLo;
268  hAnglesMi = fElectronAnglesMi;
269  hAnglesHi = fElectronAnglesHi;
270  hEnergy = fElectronEnergy;
271  }
272 
273  // now check if the particle goes through any cryostat in the detector
274  // if so, add it to the truth object.
275  for(unsigned int c = 0; c < geom->Ncryostats(); ++c){
276 
277  double bounds[6] = {0.};
278  geom->CryostatBoundaries(bounds, c);
279 
280  //add a buffer box around the cryostat bounds to increase the acceptance
281  //(geometrically) at the CRY level to make up for particles we will loose
282  //due to multiple scattering effects that pitch in during GEANT4 tracking
283  //By default, the buffer box has zero size
284  for (unsigned int cb=0; cb<6; cb++)
285  bounds[cb] = bounds[cb]+fbuffbox[cb];
286 
287  //calculate the intersection point with each cryostat surface
288  bool intersects_cryo = false;
289  for (int bnd=0; bnd!=6; ++bnd) {
290  if (bnd<2) {
291  double p2[3] = {bounds[bnd], x0[1] + (dx[1]/dx[0])*(bounds[bnd] - x0[0]), x0[2] + (dx[2]/dx[0])*(bounds[bnd] - x0[0])};
292  if ( p2[1] >= bounds[2] && p2[1] <= bounds[3] &&
293  p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
294  intersects_cryo = true;
295  break;
296  }
297  }
298  else if (bnd>=2 && bnd<4) {
299  double p2[3] = {x0[0] + (dx[0]/dx[1])*(bounds[bnd] - x0[1]), bounds[bnd], x0[2] + (dx[2]/dx[1])*(bounds[bnd] - x0[1])};
300  if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
301  p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
302  intersects_cryo = true;
303  break;
304  }
305  }
306  else if (bnd>=4) {
307  double p2[3] = {x0[0] + (dx[0]/dx[2])*(bounds[bnd] - x0[2]), x0[1] + (dx[1]/dx[2])*(bounds[bnd] - x0[2]), bounds[bnd]};
308  if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
309  p2[1] >= bounds[2] && p2[1] <= bounds[3] ) {
310  intersects_cryo = true;
311  break;
312  }
313  }
314  }
315 
316 
317  if (intersects_cryo) {
318  truth.Add(particle);
319 
320  if (std::abs(particle.PdgCode())==13) ++numMuons;
321  else if (std::abs(particle.PdgCode())==22) ++numPhotons;
322  else if (std::abs(particle.PdgCode())==11) ++numElectrons;
323 
324  //The following code no longer works now that we require intersection with the cryostat boundary
325  //For example, the particle could intersect this cryostat but miss its TPC, but intersect a TPC
326  //in another cryostat
327  /*try{
328  unsigned int tpc = 0;
329  unsigned int cstat = 0;
330  geom->PositionToTPC(x2, tpc, cstat);
331  if (std::abs(particle.PdgCode())==13) ++tpcMuons;
332  else if (std::abs(particle.PdgCode())==22) ++tpcPhotons;
333  else if (std::abs(particle.PdgCode())==11) ++tpcElectrons;
334  }
335  catch(cet::exception &e){
336  LOG_DEBUG("CosmicsGen") << "current particle does not go through any tpc";
337  }*///
338 
339  if (hCosQ!=0) {
340  double cosq = -p4.Py()/p4.P();
341  double phi = std::atan2(p4.Pz(),p4.Px());
342  phi *= 180/M_PI;
343  hCosQ->Fill(cosq);
344  hAngles->Fill(phi,cosq);
345  if (p4.E()<1.0) hAnglesLo->Fill(phi,cosq);
346  else if (p4.E()<10.0) hAnglesMi->Fill(phi,cosq);
347  else hAnglesHi->Fill(phi,cosq);
348  hEnergy->Fill(p4.E());
349  }//end if there is a cos(theta) histogram
350  break; //leave loop over cryostats to avoid adding particle multiple times
351  }// end if particle goes into a cryostat
352  }// end loop over cryostats in the detector
353 
354  }// loop on particles
355 
356  nCrossCryostat = truth.NParticles();
357 
358  fPhotonsPerSample ->Fill(allPhotons);
359  fElectronsPerSample->Fill(allElectrons);
360  fMuonsPerSample ->Fill(allMuons);
361 
362  fPhotonsInCStat ->Fill(numPhotons);
363  fElectronsInCStat->Fill(numElectrons);
364  fMuonsInCStat ->Fill(numMuons);
365 
366  /*fPhotonsInTPC ->Fill(tpcPhotons);
367  fElectronsInTPC->Fill(tpcElectrons);
368  fMuonsInTPC ->Fill(tpcMuons);*/
369  }
370 
371  truthcol->push_back(truth);
372  evt.put(std::move(truthcol));
373 
374  return;
375  }// end produce
376 
377 }// end namespace
378 
379 
380 namespace evgen{
381 
383 
384 }
385 
386 #endif // EVGEN_COSMICSGEN_H
387 
TH2F * fElectronAnglesHi
Electron rate vs angle, high momenta.
Interface to the CRY cosmic-ray generator.
Definition: CRYHelper.h:26
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:223
TH2F * fPhotonAngles
Photon rate vs angle.
int PdgCode() const
Definition: MCParticle.h:216
TH2F * fMuonAnglesHi
Muon rate vs angle, high momenta.
TH1F * fElectronEnergy
Electron energy (GeV)
Encapsulate the construction of a single cyostat.
TH2F * fElectronAnglesLo
Electron rate vs angle, low momenta.
TH2F * fElectronAngles
Electron rate vs angle.
Collect all the geometry header files together.
TH1F * fElectronCosQ
Electron rate vs cos(Q)
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:78
TH2F * fMuonAngles
Muon rate vs angle.
void reconfigure(fhicl::ParameterSet const &p)
TH2F * fMuonAnglesLo
Muon rate vs angle, low momenta.
TH1F * fPhotonEnergy
Photon energy (GeV)
const std::string GetWorldVolumeName() const
Return the name of the world volume (needed by Geant4 simulation)
int NParticles() const
Definition: MCTruth.h:72
art::ProductID put(std::unique_ptr< PROD > &&)
Definition: Run.h:148
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
TH2F * fElectronAnglesMi
Electron rate vs angle, middle momenta.
Particle class.
void Add(simb::MCParticle &part)
Definition: MCTruth.h:77
TH1F * fMuonCosQ
Muon rate vs cos(Q)
TH1F * fElectronsPerSample
number of electrons in the sampled time window
void CryostatBoundaries(double *boundaries, geo::CryostatID const &cid) const
Returns the boundaries of the specified cryostat.
Definition: Run.h:30
CosmicsGen(fhicl::ParameterSet const &pset)
TH1F * fPhotonsPerSample
number of photons in the sampled time window
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
evgb::CRYHelper * fCRYHelp
CRY generator object.
base_engine_t & getEngine() const
double Sample(simb::MCTruth &mctruth, double const &surfaceY, double const &detectorLength, double *w, double rantime=0)
Definition: CRYHelper.cxx:97
base_engine_t & createEngine(seed_t seed)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
Interface to the CRY cosmic ray generator.
T get(std::string const &key) const
Definition: ParameterSet.h:231
TH1F * fPhotonCosQ
Photon rate vs cos(Q)
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
geo::Length_t SurfaceY() const
The position of the detector respect to earth surface.
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
TH2F * fMuonAnglesMi
Muon rate vs angle, middle momenta.
std::vector< double > fbuffbox
const simb::MCParticle & GetParticle(int i) const
Definition: MCTruth.h:73
TH2F * fPhotonAnglesMi
Photon rate vs angle, middle momenta.
TH2F * fPhotonAnglesLo
Photon rate vs angle, low momenta.
T * make(ARGS...args) const
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
void produce(art::Event &evt)
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:224
TH2F * fPhotonAnglesHi
Photon rate vs angle, high momenta.
A module to check the results from the Monte Carlo generator.
void beginRun(art::Run &run)
Event generator information.
Definition: MCTruth.h:30
TH1F * fMuonsPerSample
number of muons in the sampled time window
Namespace collecting geometry-related classes utilities.
TH1F * fMuonEnergy
Muon energy (GeV)
Event Generation using GENIE, cosmics or single particles.
BoundingBox bounds(int x, int y, int w, int h)
Definition: main.cpp:37
art framework interface to geometry description
Cosmic rays.
Definition: MCTruth.h:22