All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CosmicsGen_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file CosmicsGen_module.cc
3 /// \brief Generator for cosmic-rays
4 ///
5 /// Module to produce cosmic ray MC using CRY
6 ///
7 /// \author brebel@fnal.gov
8 ////////////////////////////////////////////////////////////////////////
9 
10 // ROOT includes
11 #include "TH1.h"
12 #include "TH2.h"
13 
14 // Framework includes
15 #include "art/Framework/Core/EDProducer.h"
16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Principal/Event.h"
18 #include "art/Framework/Principal/Run.h"
19 #include "fhiclcpp/ParameterSet.h"
20 #include "art/Framework/Services/Registry/ServiceHandle.h"
21 #include "art_root_io/TFileService.h"
22 
23 // art extensions
24 #include "nurandom/RandomUtils/NuRandomService.h"
25 
26 // larsoft includes
27 #include "nusimdata/SimulationBase/MCTruth.h"
28 #include "nusimdata/SimulationBase/MCParticle.h"
29 #include "nugen/EventGeneratorBase/evgenbase.h"
30 #include "nutools/EventGeneratorBase/CRY/CRYHelper.h"
33 
34 namespace evgen {
35 
36  /// A module to check the results from the Monte Carlo generator
37  class CosmicsGen : public art::EDProducer {
38  public:
39  explicit CosmicsGen(fhicl::ParameterSet const& pset);
40 
41  private:
42 
43  void produce(art::Event& evt) override;
44  void beginJob() override;
45  void beginRun(art::Run& run) override;
46 
47  std::vector<double> fbuffbox;
48 
49  TH2F* fPhotonAngles; ///< Photon rate vs angle
50  TH2F* fPhotonAnglesLo; ///< Photon rate vs angle, low momenta
51  TH2F* fPhotonAnglesMi; ///< Photon rate vs angle, middle momenta
52  TH2F* fPhotonAnglesHi; ///< Photon rate vs angle, high momenta
53  TH1F* fPhotonCosQ; ///< Photon rate vs cos(Q)
54  TH1F* fPhotonEnergy; ///< Photon energy (GeV)
55  TH1F* fPhotonsPerSample; ///< number of photons in the sampled time window
56  TH1F* fPhotonsInCStat; ///< number of photons in the cryostat during
57  ///< the sampled time window
58  TH1F* fPhotonsInTPC; ///< number of photons in the tpc during
59  ///< the sampled time window
60 
61  TH2F* fElectronAngles; ///< Electron rate vs angle
62  TH2F* fElectronAnglesLo; ///< Electron rate vs angle, low momenta
63  TH2F* fElectronAnglesMi; ///< Electron rate vs angle, middle momenta
64  TH2F* fElectronAnglesHi; ///< Electron rate vs angle, high momenta
65  TH1F* fElectronCosQ; ///< Electron rate vs cos(Q)
66  TH1F* fElectronEnergy; ///< Electron energy (GeV)
67  TH1F* fElectronsPerSample; ///< number of electrons in the sampled time window
68  TH1F* fElectronsInCStat; ///< number of electrons in the cryostat during
69  ///< the sampled time window
70  TH1F* fElectronsInTPC; ///< number of electrons in the tpc during
71  ///< the sampled time window
72 
73  TH2F* fMuonAngles; ///< Muon rate vs angle
74  TH2F* fMuonAnglesLo; ///< Muon rate vs angle, low momenta
75  TH2F* fMuonAnglesMi; ///< Muon rate vs angle, middle momenta
76  TH2F* fMuonAnglesHi; ///< Muon rate vs angle, high momenta
77  TH1F* fMuonCosQ; ///< Muon rate vs cos(Q)
78  TH1F* fMuonEnergy; ///< Muon energy (GeV)
79  TH1F* fMuonsPerSample; ///< number of muons in the sampled time window
80  TH1F* fMuonsInCStat; ///< number of muons in the cryostat during
81  ///< the sampled time window
82  TH1F* fMuonsInTPC; ///< number of muons in the tpc during
83  ///< the sampled time window
84  CLHEP::HepRandomEngine& fEngine; ///< art-managed random-number engine
85  evgb::CRYHelper fCRYHelp; ///< CRY generator object
86  };
87 }
88 
89 namespace evgen{
90 
91  //____________________________________________________________________________
92  CosmicsGen::CosmicsGen(fhicl::ParameterSet const& pset)
93  : art::EDProducer{pset}
94  , fbuffbox{pset.get<std::vector<double>>("BufferBox",{0.0, 0.0, 0.0, 0.0, 0.0, 0.0})}
95  // create a default random engine; obtain the random seed from NuRandomService,
96  // unless overridden in configuration with key "Seed"
97  , fEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, pset, "Seed"))
98  , fCRYHelp{pset,
99  fEngine,
100  art::ServiceHandle<geo::Geometry const>{}->GetWorldVolumeName()}
101  {
102  produces< std::vector<simb::MCTruth> >();
104  }
105 
106  //____________________________________________________________________________
107  void CosmicsGen::beginJob()
108  {
109  art::ServiceHandle<art::TFileService const> tfs;
110 
111  fPhotonAngles = tfs->make<TH2F>("fPhotonAngles", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
112  fPhotonAnglesLo = tfs->make<TH2F>("fPhotonAnglesLo", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
113  fPhotonAnglesMi = tfs->make<TH2F>("fPhotonAnglesMi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
114  fPhotonAnglesHi = tfs->make<TH2F>("fPhotonAnglesHi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
115  fPhotonCosQ = tfs->make<TH1F>("fPhotonCosQ", ";cos#theta;tracks", 50,-1.0,1.0);
116  fPhotonEnergy = tfs->make<TH1F>("fPhotonEnergy", ";E (GeV)", 5000,0.0,1000.0);
117  fPhotonsPerSample = tfs->make<TH1F>("fPhotonsPerSample", ";Number Photons;Samples", 100, 0, 1000);
118  fPhotonsInCStat = tfs->make<TH1F>("fPhotonsInCryostat", ";Number Photons;Samples", 100, 0, 1000);
119  fPhotonsInTPC = tfs->make<TH1F>("fPhotonsInTPC", ";Number Photons;Samples", 100, 0, 1000);
120 
121  fElectronAngles = tfs->make<TH2F>("fElectronAngles", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
122  fElectronAnglesLo = tfs->make<TH2F>("fElectronAnglesLo", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
123  fElectronAnglesMi = tfs->make<TH2F>("fElectronAnglesMi", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
124  fElectronAnglesHi = tfs->make<TH2F>("fElectronAnglesHi", ";#phi;cos#theta",36,-180.0,180.0,50,-1.0,1.0);
125  fElectronCosQ = tfs->make<TH1F>("fElectronCosQ", ";cos#theta;tracks",50,-1.0,1.0);
126  fElectronEnergy = tfs->make<TH1F>("fElectronEnergy", ";E (GeV)", 5000,0.0,1000.0);
127  fElectronsPerSample = tfs->make<TH1F>("fElectronsPerSample", ";Number Electrons;Samples", 100, 0, 1000);
128  fElectronsInCStat = tfs->make<TH1F>("fElectronsInCryotat", ";Number Electrons;Samples", 100, 0, 1000);
129  fElectronsInTPC = tfs->make<TH1F>("fElectronsInTPC", ";Number Electrons;Samples", 100, 0, 1000);
130 
131  fMuonAngles = tfs->make<TH2F>("fMuonAngles", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
132  fMuonAnglesLo = tfs->make<TH2F>("fMuonAnglesLo", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
133  fMuonAnglesMi = tfs->make<TH2F>("fMuonAnglesMi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
134  fMuonAnglesHi = tfs->make<TH2F>("fMuonAnglesHi", ";#phi;cos#theta", 36,-180.0,180.0,50,-1.0,1.0);
135  fMuonCosQ = tfs->make<TH1F>("fMuonCosQ", ";cos#theta;tracks",50,-1.0,1.0);
136  fMuonEnergy = tfs->make<TH1F>("fMuonEnergy", ";E (GeV)", 5000,0.0,1000.0);
137  fMuonsPerSample = tfs->make<TH1F>("fMuonsPerSample", ";Number Muons;Samples", 100, 0, 1000);
138  fMuonsInCStat = tfs->make<TH1F>("fMuonsInCryostat", ";Number Muons;Samples", 100, 0, 1000);
139  fMuonsInTPC = tfs->make<TH1F>("fMuonsInTPC", ";Number Muons;Samples", 100, 0, 1000);
140  }
141 
142  //____________________________________________________________________________
143  void CosmicsGen::beginRun(art::Run& run)
144  {
145  art::ServiceHandle<geo::Geometry const> geo;
146  run.put(std::make_unique<sumdata::RunData>(geo->DetectorName()));
147  }
148 
149  //____________________________________________________________________________
150  void CosmicsGen::produce(art::Event& evt)
151  {
152  std::unique_ptr< std::vector<simb::MCTruth> > truthcol(new std::vector<simb::MCTruth>);
153 
154  // fill some histograms about this event
155  art::ServiceHandle<geo::Geometry const> geom;
156 
157  int nCrossCryostat = 0;
158 
159  simb::MCTruth truth;
160 
161  while(nCrossCryostat < 1){
162 
163  simb::MCTruth pretruth;
164  truth.SetOrigin(simb::kCosmicRay);
165  fCRYHelp.Sample(pretruth,
166  geom->SurfaceY(),
167  geom->DetLength(),
168  0);
169 
170  int numPhotons = 0;
171  int numElectrons = 0;
172  int numMuons = 0;
173  int allPhotons = 0;
174  int allElectrons = 0;
175  int allMuons = 0;
176 
177  // loop over particles in the truth object
178  for(int i = 0; i < pretruth.NParticles(); ++i){
179  simb::MCParticle particle = pretruth.GetParticle(i);
180  const TLorentzVector& v4 = particle.Position();
181  const TLorentzVector& p4 = particle.Momentum();
182  double x0[3] = {v4.X(), v4.Y(), v4.Z() };
183  double dx[3] = {p4.Px(), p4.Py(), p4.Pz()};
184 
185  if (std::abs(particle.PdgCode())==13) ++allMuons;
186  else if (std::abs(particle.PdgCode())==22) ++allPhotons;
187  else if (std::abs(particle.PdgCode())==11) ++allElectrons;
188 
189  TH1F* hCosQ = 0;
190  TH2F* hAngles = 0;
191  TH2F* hAnglesLo = 0;
192  TH2F* hAnglesMi = 0;
193  TH2F* hAnglesHi = 0;
194  TH1F* hEnergy = 0;
195  if (std::abs(particle.PdgCode())==13) {
196  hCosQ = fMuonCosQ;
197  hAngles = fMuonAngles;
198  hAnglesLo = fMuonAnglesLo;
199  hAnglesMi = fMuonAnglesMi;
200  hAnglesHi = fMuonAnglesHi;
201  hEnergy = fMuonEnergy;
202  }
203  else if (std::abs(particle.PdgCode())==22) {
204  hCosQ = fPhotonCosQ;
205  hAngles = fPhotonAngles;
206  hAnglesLo = fPhotonAnglesLo;
207  hAnglesMi = fPhotonAnglesMi;
208  hAnglesHi = fPhotonAnglesHi;
209  hEnergy = fPhotonEnergy;
210  }
211  else if (std::abs(particle.PdgCode())==11) {
212  hCosQ = fElectronCosQ;
213  hAngles = fElectronAngles;
214  hAnglesLo = fElectronAnglesLo;
215  hAnglesMi = fElectronAnglesMi;
216  hAnglesHi = fElectronAnglesHi;
217  hEnergy = fElectronEnergy;
218  }
219 
220  // now check if the particle goes through any cryostat in the detector
221  // if so, add it to the truth object.
222  for(unsigned int c = 0; c < geom->Ncryostats(); ++c){
223 
224  double bounds[6] = {0.};
225  geom->CryostatBoundaries(bounds, c);
226 
227  //add a buffer box around the cryostat bounds to increase the acceptance
228  //(geometrically) at the CRY level to make up for particles we will loose
229  //due to multiple scattering effects that pitch in during GEANT4 tracking
230  //By default, the buffer box has zero size
231  for (unsigned int cb=0; cb<6; cb++)
232  bounds[cb] = bounds[cb]+fbuffbox[cb];
233 
234  //calculate the intersection point with each cryostat surface
235  bool intersects_cryo = false;
236  for (int bnd=0; bnd!=6; ++bnd) {
237  if (bnd<2) {
238  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])};
239  if ( p2[1] >= bounds[2] && p2[1] <= bounds[3] &&
240  p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
241  intersects_cryo = true;
242  break;
243  }
244  }
245  else if (bnd>=2 && bnd<4) {
246  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])};
247  if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
248  p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
249  intersects_cryo = true;
250  break;
251  }
252  }
253  else if (bnd>=4) {
254  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]};
255  if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
256  p2[1] >= bounds[2] && p2[1] <= bounds[3] ) {
257  intersects_cryo = true;
258  break;
259  }
260  }
261  }
262 
263 
264  if (intersects_cryo) {
265  truth.Add(particle);
266 
267  if (std::abs(particle.PdgCode())==13) ++numMuons;
268  else if (std::abs(particle.PdgCode())==22) ++numPhotons;
269  else if (std::abs(particle.PdgCode())==11) ++numElectrons;
270 
271  //The following code no longer works now that we require intersection with the cryostat boundary
272  //For example, the particle could intersect this cryostat but miss its TPC, but intersect a TPC
273  //in another cryostat
274  /*try{
275  unsigned int tpc = 0;
276  unsigned int cstat = 0;
277  geom->PositionToTPC(x2, tpc, cstat);
278  if (std::abs(particle.PdgCode())==13) ++tpcMuons;
279  else if (std::abs(particle.PdgCode())==22) ++tpcPhotons;
280  else if (std::abs(particle.PdgCode())==11) ++tpcElectrons;
281  }
282  catch(cet::exception &e){
283  MF_LOG_DEBUG("CosmicsGen") << "current particle does not go through any tpc";
284  }*///
285 
286  if (hCosQ!=0) {
287  double cosq = -p4.Py()/p4.P();
288  double phi = std::atan2(p4.Pz(),p4.Px());
289  phi *= 180/M_PI;
290  hCosQ->Fill(cosq);
291  hAngles->Fill(phi,cosq);
292  if (p4.E()<1.0) hAnglesLo->Fill(phi,cosq);
293  else if (p4.E()<10.0) hAnglesMi->Fill(phi,cosq);
294  else hAnglesHi->Fill(phi,cosq);
295  hEnergy->Fill(p4.E());
296  }//end if there is a cos(theta) histogram
297  break; //leave loop over cryostats to avoid adding particle multiple times
298  }// end if particle goes into a cryostat
299  }// end loop over cryostats in the detector
300 
301  }// loop on particles
302 
303  nCrossCryostat = truth.NParticles();
304 
305  fPhotonsPerSample ->Fill(allPhotons);
306  fElectronsPerSample->Fill(allElectrons);
307  fMuonsPerSample ->Fill(allMuons);
308 
309  fPhotonsInCStat ->Fill(numPhotons);
310  fElectronsInCStat->Fill(numElectrons);
311  fMuonsInCStat ->Fill(numMuons);
312 
313  /*fPhotonsInTPC ->Fill(tpcPhotons);
314  fElectronsInTPC->Fill(tpcElectrons);
315  fMuonsInTPC ->Fill(tpcMuons);*/
316  }
317 
318  truthcol->push_back(truth);
319  evt.put(std::move(truthcol));
320  }// end produce
321 
322 }// end namespace
323 
324 
325 namespace evgen{
326 
327  DEFINE_ART_MODULE(CosmicsGen)
328 
329 }
TH2F * fElectronAnglesHi
Electron rate vs angle, high momenta.
void beginJob() override
TH2F * fPhotonAngles
Photon rate vs angle.
TH2F * fMuonAnglesHi
Muon rate vs angle, high momenta.
TH1F * fElectronEnergy
Electron energy (GeV)
TH2F * fElectronAnglesLo
Electron rate vs angle, low momenta.
TH2F * fElectronAngles
Electron rate vs angle.
TH1F * fElectronCosQ
Electron rate vs cos(Q)
TH2F * fMuonAngles
Muon rate vs angle.
TH2F * fMuonAnglesLo
Muon rate vs angle, low momenta.
TH1F * fPhotonEnergy
Photon energy (GeV)
produces< sumdata::RunData, art::InRun >()
TH2F * fElectronAnglesMi
Electron rate vs angle, middle momenta.
void produce(art::Event &evt) override
TH1F * fMuonCosQ
Muon rate vs cos(Q)
TH1F * fElectronsPerSample
number of electrons in the sampled time window
CosmicsGen(fhicl::ParameterSet const &pset)
TH1F * fPhotonsPerSample
number of photons in the sampled time window
T abs(T value)
fEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this, pset,"Seed"))
TH1F * fPhotonCosQ
Photon rate vs cos(Q)
CLHEP::HepRandomEngine & fEngine
art-managed random-number engine
const Cut kCosmicRay
void beginRun(art::Run &run) override
evgb::CRYHelper fCRYHelp
CRY generator object.
TH2F * fMuonAnglesMi
Muon rate vs angle, middle momenta.
std::vector< double > fbuffbox
TH2F * fPhotonAnglesMi
Photon rate vs angle, middle momenta.
TH2F * fPhotonAnglesLo
Photon rate vs angle, low momenta.
TH2F * fPhotonAnglesHi
Photon rate vs angle, high momenta.
A module to check the results from the Monte Carlo generator.
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8
TH1F * fMuonsPerSample
number of muons in the sampled time window
TH1F * fMuonEnergy
Muon energy (GeV)
art framework interface to geometry description