LArG4Ana_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file LArG4Ana_module.cc
3 /// \brief Use Geant4 to run the LArSoft detector simulation
4 ///
5 /// \author seligman@nevis.columbia.edu
6 ////////////////////////////////////////////////////////////////////////
7 
8 /// Framework includes
11 
12 // Framework includes
14 #include "fhiclcpp/ParameterSet.h"
16 #include "art_root_io/TFileService.h"
18 
19 // LArSoft Includes
21 #include "nug4/ParticleNavigation/ParticleList.h"
25 
26 // ROOT includes
27 #include "TH1.h"
28 #include "TProfile.h"
29 #include "TLorentzVector.h"
30 #include <TTree.h>
31 
32 // C++ Includes
33 #include <cstring>
34 
35 ///Geant4 interface
36 namespace larg4 {
37 
38  class LArG4Ana : public art::EDAnalyzer{
39  public:
40 
41  /// Standard constructor and destructor for an FMWK module.
42  explicit LArG4Ana(fhicl::ParameterSet const& pset);
43 
44  void analyze (const art::Event& evt);
45  void beginJob();
46 
47  private:
48 
49  std::string fG4ModuleLabel; ///< module label for the Geant
50  std::string fTruthModuleLabel; ///< module label for the Geant
51 
52 
53  TH1D *fPDGCodes;
54  TH1D *fPi0Momentum;
55  TH1D *fnEnergy;
56  TH1D *fnDist;
57  TH1D *fnumChannels; ///< The number of channels recieving charge per event
58  TProfile *fnumIDEs; ///< Number of drift electrons per channel.
59  TH1D *fEventCharge; ///< Charge collected per event
60  TH1D *fEventEnergy; ///< Energy collected per event
61  TProfile *fChannelCharge; ///< Charge per channel.
62  TProfile *fChannelEnergy; ///< Energy per channel.
63 
64  // Int_t stringDim = 35;
65 
66  TTree *fTree;
67  Int_t fTEvt;
68  Int_t fTSub;
69  Int_t fTRun;
70  Int_t fTPdg;
71  Int_t fTID;
73  Int_t fTNds;
74  Int_t fTNds4;
75  Int_t *fTDID;
76  Int_t *fTDPdg;
77  Float_t *fTDWt;
78  Char_t fTProcess[35];
79  Char_t fTVolume[35];
80  Char_t fTTVolume[35]; // Termination Volume
81  Char_t fTMaterial[35];
82  Char_t fTDProcess[200][35];
83  Int_t fTParentID;
84  Int_t fTStatus;
85  Float_t fTWeight;
86  Float_t* fT4Origin;
87  Float_t* fT4DOrigin;
88  Float_t* fT4Termination; // Termination Coordinates
89  Float_t* fT4Momentum;
90  Float_t* fT4DMomentum;
91  };
92 
93 } // namespace larg4
94 
95 namespace larg4 {
96 
97  //-----------------------------------------------------------------------
98  // Constructor
100  : EDAnalyzer(pset)
101  , fG4ModuleLabel{pset.get< std::string >("GeantModuleLabel")}
102  , fTruthModuleLabel{pset.get< std::string >("TruthModuleLabel")}
103  , fTNdsOriginal{pset.get< int >("Ndaughters" )}
105  {}
106 
107  //-----------------------------------------------------------------------
109  {
112 
113  fPDGCodes = tfs->make<TH1D>("pdgcodes", ";PDG Code;", 5000, -2500, 2500);
114  fPi0Momentum = tfs->make<TH1D>("pi0mom", ";#pi^{0} Momentum (GeV);", 1000, 0., 1000.);
115 
116  fTree = tfs->make<TTree>("MCTTree","MCTTree");
117  fnEnergy = tfs->make<TH1D>("nEnergy", ";n,#Lambda^{0},K^{0} Momentum (GeV);", 100, 0., 10.);
118  fnDist = tfs->make<TH1D>("nDistance", ";n,#Lambda^{0},K^{0} Distance (m);", 200, -30000.0, +30000.);
119 
120 
121  // Some histograms relating to drift electrons, active detector
122  // channels and charge/energy on channels
123  fnumChannels = tfs->make<TH1D>("fnumChannels",
124  "Active channels;Active channels;# events",
125  256, 0, geo->Nchannels());
126  fnumIDEs = tfs->make<TProfile>("fnumIDEs",
127  "Drift Electrons per channel;Channel;Drift electrons",
128  geo->Nchannels()+1, 0, geo->Nchannels(),
129  0, 1e4);
130  fEventCharge = tfs->make<TH1D>("fEventCharge",
131  "Charge in event;Total charge per event;# events",
132  100, 0, 2.5e8);
133  fEventEnergy = tfs->make<TH1D>("fEventEnergy",
134  "Energy in event;Total energy per event;# events",
135  100, 0, 1e4);
136  fChannelCharge = tfs->make<TProfile>("fChannelCharge",
137  "Charge on channel;Channel;Total charge per channel",
138  geo->Nchannels()+1,0,geo->Nchannels(),
139  0,1e5);
140  fChannelEnergy = tfs->make<TProfile>("fChannelEnergy",
141  "Energy on channel;Channel;Total energy per channel",
142  geo->Nchannels()+1,0,geo->Nchannels(),
143  0, 1e3);
144 
145 
146  fT4Origin = new Float_t[4];
147  fT4DOrigin = new Float_t[fTNds*4];
148  fT4Termination = new Float_t[4];
149  fT4Momentum = new Float_t[4];
150  fT4DMomentum = new Float_t[fTNds*4];
151  fTDID = new Int_t[fTNds];
152  fTDPdg = new Int_t[fTNds];
153  fTDWt = new Float_t[fTNds];
154  fTNds4 = fTNds*4; // TTree/Branch requirement to store this.
155 
156  fTree->Branch("MCEvt", &fTEvt, "MCEvt/I");
157  fTree->Branch("MCSub", &fTSub, "MCSub/I");
158  fTree->Branch("MCRun", &fTRun, "MCRun/I");
159  fTree->Branch("MCWt", &fTWeight, "MCWt/F");
160  fTree->Branch("MCPdg", &fTPdg, "MCPdg/I");
161  fTree->Branch("MCID", &fTID, "MCID/I");
162  fTree->Branch("MCParentID", &fTParentID, "MCParentID/I");
163  fTree->Branch("MCNumDs", &fTNds, "MCNumDs/I");
164  fTree->Branch("MCNumDs4", &fTNds4, "MCNumDs4/I");
165  fTree->Branch("MCDID", fTDID, "MCDID[MCNumDs]/I");
166  fTree->Branch("MCDPdg", fTDPdg, "MCDPdg[MCNumDs]/I");
167  fTree->Branch("MCDWt", fTDWt, "MCDWt[MCNumDs]/I");
168  fTree->Branch("MCProcess", fTProcess, "MCProcess/C");
169  fTree->Branch("MCVolume", fTVolume, "MCVolume/C");
170  fTree->Branch("MCTVolume", fTTVolume, "MCTVolume/C");
171  fTree->Branch("MCMaterial", fTMaterial, "MCMaterial/C");
172  fTree->Branch("MCDProcess", fTDProcess, "MCDProcess[MCNumDs]/C");
173  fTree->Branch("MCStatus", &fTStatus, "MCStatus/I");
174  fTree->Branch("MCOrigin", fT4Origin, "MCOrigin[4]/F");
175  fTree->Branch("MCDOrigin", fT4DOrigin, "MCDOrigin[MCNumDs4]/F");
176  fTree->Branch("MCTermination", fT4Termination, "MCTermination[4]/F");
177  fTree->Branch("MCMomentum", fT4Momentum, "MCMomentum[4]/F");
178  fTree->Branch("MCDMomentum", fT4DMomentum, "MCDMomentum[MCNumDs4]/F");
179 
180  }
181 
182  //-----------------------------------------------------------------------
184  {
185 
186  //get the list of particles from this event
188  const sim::ParticleList& plist = pi_serv->ParticleList();
190 
191  // loop over all sim::SimChannels in the event and make sure there are no
192  // sim::IDEs with trackID values that are not in the sim::ParticleList
193  std::vector<const sim::SimChannel*> sccol;
194  evt.getView(fG4ModuleLabel, sccol);
195 
196  double totalCharge=0.0;
197  double totalEnergy=0.0;
198  fnumChannels->Fill(sccol.size());
199  for(size_t sc = 0; sc < sccol.size(); ++sc){
200  double numIDEs=0.0;
201  double scCharge=0.0;
202  double scEnergy=0.0;
203  const auto & tdcidemap = sccol[sc]->TDCIDEMap();
204  for(auto mapitr = tdcidemap.begin(); mapitr != tdcidemap.end(); mapitr++){
205  const std::vector<sim::IDE> idevec = (*mapitr).second;
206  numIDEs += idevec.size();
207  for(size_t iv = 0; iv < idevec.size(); ++iv){
208  if(plist.find( idevec[iv].trackID ) == plist.end()
209  && idevec[iv].trackID != sim::NoParticleId)
210  mf::LogWarning("LArG4Ana") << idevec[iv].trackID << " is not in particle list";
211  totalCharge +=idevec[iv].numElectrons;
212  scCharge += idevec[iv].numElectrons;
213  totalEnergy +=idevec[iv].energy;
214  scEnergy += idevec[iv].energy;
215  }
216  }
217  fnumIDEs->Fill(sc,numIDEs);
218  fChannelCharge->Fill(sc,scCharge);
219  fChannelEnergy->Fill(sc,scEnergy);
220  }
221  fEventCharge->Fill(totalCharge);
222  fEventEnergy->Fill(totalEnergy);
223 
224  // get the particles from the back tracker
225  const sim::ParticleList& Particles = pi_serv->ParticleList();
226  std::vector<const simb::MCParticle*> pvec;
227  pvec.reserve(Particles.size());
228  for (const auto& PartPair: Particles) {
229  pvec.push_back(PartPair.second);
230  fPDGCodes->Fill(PartPair.second->PdgCode());
231  }
232 
233  // now look for pi0's that decay to 2 gammas
234  int pi0loc = -1;
235  int numpi0gamma = 0;
236  for(unsigned int i = 0; i < pvec.size(); ++i){
237  if(pvec[i]->PdgCode() == 111) pi0loc = i;
238  if(pvec[i]->Mother() == pi0loc+1 &&
239  pi0loc > 0 &&
240  pvec[i]->PdgCode() == 22){
241  mf::LogInfo("LArG4Ana") << pvec[i]->E() << " gamma energy ";
242  ++numpi0gamma;
243  }
244 
245  // n,Lambda,K0s,K0L,K0
246  if (pvec[i]->PdgCode() == 2112 ||
247  pvec[i]->PdgCode() == 3122 ||
248  pvec[i]->PdgCode() == 130 ||
249  pvec[i]->PdgCode() == 310 ||
250  pvec[i]->PdgCode() == 311 ) {
251  fnEnergy->Fill(pvec[i]->E(),pvec[i]->Weight());
252  fnDist->Fill(pvec[i]->Vx(),pvec[i]->Weight());
253  }
254 
255  fTPdg = pvec[i]->PdgCode();
256  fTID = pvec[i]->TrackId();
257  // 0 out strings, else there may be cruft in here from prev evt.
258  for (unsigned int s = 0; s < 35; ++s){
259  *(fTProcess+s) = 0;
260  *(fTProcess+s) = 0;
261  *(fTMaterial+s) = 0;
262  *(fTMaterial+s) = 0;
263  *(fTVolume+s) = 0;
264  *(fTVolume+s) = 0;
265  *(fTTVolume+s) = 0;
266  *(fTTVolume+s) = 0;
267  }
268 
269  for(unsigned int s = 0; s < pvec[i]->Process().length(); ++s) *(fTProcess+s) = pvec[i]->Process()[s];
270 
271  TVector3 dum = pvec[i]->Position().Vect();
272 
273  for (unsigned int s = 0; s < geom->MaterialName(pvec[i]->Position().Vect()).length(); ++s)
274  *(fTMaterial+s) = geom->MaterialName(pvec[i]->Position().Vect())[s];
275 
276  for (unsigned int s = 0; s < geom->VolumeName(pvec[i]->Position().Vect()).length(); ++s)
277  *(fTVolume+s) = geom->VolumeName(pvec[i]->Position().Vect())[s];
278 
279  for (unsigned int s = 0; s < geom->VolumeName(pvec[i]->EndPosition().Vect()).length(); ++s)
280  *(fTTVolume+s) = geom->VolumeName(pvec[i]->EndPosition().Vect())[s];
281 
282  fTEvt = evt.id().event();
283  fTSub = evt.subRun();
284  fTRun = evt.run();
285  fTParentID = pvec[i]->Mother();
286  fTStatus = pvec[i]->StatusCode();
287  int daughter = 9999;
288  fTNds = TMath::Min(pvec[i]->NumberDaughters(),fTNdsOriginal);
289  for( int d = 0; d < fTNds; d++ ){
290  daughter = pvec[i]->Daughter(d);
291  fTDID[d] = daughter;
292  // zero it out.
293  for (unsigned int s = 0; s < 35; ++s) *(fTDProcess[d]+s) = 0;
294 
295  for(unsigned int jj = i; jj < pvec.size(); ++jj){ // Don't look below i.
296 
297  if (fTDID[d] == pvec[jj]->TrackId()){
298  fTDPdg[d] = pvec[jj]->PdgCode(); // get the pointer,
299  fTDWt[d] = pvec[jj]->Weight();
300 
301  for (unsigned int s = 0; s < pvec[jj]->Process().length(); ++s)
302  *(fTDProcess[d]+s) = pvec[jj]->Process()[s];
303 
304  for (unsigned int kk = 0; kk < 4; ++kk){
305  fT4DOrigin[d*4+kk] = pvec[jj]->Position()[kk];
306  fT4DMomentum[d*4+kk] = pvec[jj]->Momentum()[kk];
307  }
308  break;
309  }
310  }
311  }//end loop over d
312 
313  for (unsigned int ii = 0; ii < 4; ++ii){
314  fT4Termination[ii] = 1e9;
315  fT4Origin[ii] = pvec[i]->Position()[ii];
316  if (ii!=3) fT4Termination[ii] = pvec[i]->EndPosition()[ii];
317  if (ii==4) fT4Termination[ii] = pvec[i]->Momentum()[ii]; // yes, odd
318  fT4Momentum[ii] = pvec[i]->Momentum()[ii];
319  }
320 
321  fTWeight = pvec[i]->Weight();
322  fTree->Fill();
323 
324  } // end loop on particles in list
325  if(numpi0gamma == 2 && pi0loc > 0){
326  mf::LogInfo("LArG4Ana") << pvec[pi0loc]->E();
327  fPi0Momentum->Fill(pvec[pi0loc]->E());
328  }
329 
330  return;
331  }
332 
333 
334 
335 } // namespace larg4
336 
337 namespace larg4 {
338 
340 
341 } // namespace LArG4
TProfile * fChannelCharge
Charge per channel.
void analyze(const art::Event &evt)
std::string fG4ModuleLabel
module label for the Geant
TH1D * fnumChannels
The number of channels recieving charge per event.
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
Float_t * fT4Termination
Char_t fTTVolume[35]
Geant4 interface.
Char_t fTMaterial[35]
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
TH1D * fEventEnergy
Energy collected per event.
Char_t fTVolume[35]
art framework interface to geometry description
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
TProfile * fChannelEnergy
Energy per channel.
Char_t fTDProcess[200][35]
Float_t * fT4DMomentum
int PdgCode(Resonance_t res, int Q)
(resonance id, charge) -> PDG code
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
static const int NoParticleId
Definition: sim.h:28
T get(std::string const &key) const
Definition: ParameterSet.h:271
Char_t fTProcess[35]
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
RunNumber_t run() const
Definition: DataViewImpl.cc:71
TH1D * fEventCharge
Charge collected per event.
LArG4Ana(fhicl::ParameterSet const &pset)
Standard constructor and destructor for an FMWK module.
const sim::ParticleList & ParticleList() const
std::string fTruthModuleLabel
module label for the Geant
E
Definition: 018_def.c:13
EventNumber_t event() const
Definition: EventID.h:116
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
Definition: DataViewImpl.h:500
std::string MaterialName(TVector3 const &point) const
Name of the deepest material containing the point xyz.
Tools and modules for checking out the basics of the Monte Carlo.
TCEvent evt
Definition: DataStructs.cxx:7
LArSoft geometry interface.
Definition: ChannelGeo.h:16
std::string VolumeName(geo::Point_t const &point) const
Returns the name of the deepest volume containing specified point.
Float_t * fT4DOrigin
static QCString * s
Definition: config.cpp:1042
EventID id() const
Definition: Event.cc:34
TProfile * fnumIDEs
Number of drift electrons per channel.
Float_t * fT4Momentum