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