BackTrackerAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: BackTrackerAna
3 // Plugin Type: analyzer (art v3_06_03)
4 // File: BackTrackerAna_module.cc
5 //
6 // Generated at Tue Jul 20 09:48:51 2021 by Christopher Hilgenberg using cetskelgen
7 // from cetlib version v3_11_01.
8 ////////////////////////////////////////////////////////////////////////
9 
10 // framework includes
18 #include "fhiclcpp/ParameterSet.h"
20 #include "art_root_io/TFileService.h"
23 
24 // simb includes
28 
29 // garsoft includes
42 #include "CoreUtils/ServiceUtil.h"
43 #include "MCCheater/BackTracker.h"
44 #include "Geometry/GeometryGAr.h"
45 
46 // root includes
47 #include <TTree.h>
48 #include <TH1F.h>
49 #include <TH2F.h>
50 #include <TDatabasePDG.h>
51 #include <TParticlePDG.h>
52 
53 // c++ includes
54 #include <vector>
55 #include <string>
56 #include <map>
57 #include <iostream>
58 
59 using namespace gar;
60 using namespace std;
61 
62 class BackTrackerAna;
63 
64 
66 public:
67  explicit BackTrackerAna(fhicl::ParameterSet const& p);
68  // The compiler-generated destructor is fine for non-base
69  // classes without bare pointers or other resource use.
70 
71  // Plugins should not be copied or assigned.
72  BackTrackerAna(BackTrackerAna const&) = delete;
73  BackTrackerAna(BackTrackerAna&&) = delete;
74  BackTrackerAna& operator=(BackTrackerAna const&) = delete;
75  BackTrackerAna& operator=(BackTrackerAna&&) = delete;
76 
77  virtual void beginJob() override;
78 
79  // Required functions.
80  void analyze(art::Event const& e) override;
81 
82 private:
83 
84  // input product labels
85  string fGeantLabel; ///< module label for geant4 simulated hits
86  string fGeantInstanceCalo; ///< Instance name ECAL for sdp::CaloDeposit
87  string fHitLabel; ///< module label for reco TPC hits rec::Hit
88  string fTPCClusterLabel; ///< module label for TPC Clusters rec::TPCCluster
89  string fTrackLabel; ///< module label for TPC Tracks rec:Track
90  string fVertexLabel; ///< module label for vertexes rec:Vertex
91  string fVeeLabel; ///< module label for conversion/decay vertexes rec:Vee
92  string fClusterLabel; ///< module label for calo clusters rec::Cluster
93  string fCaloHitLabel; ///< module label for reco calo hits rec::CaloHit
94  string fCaloHitInstanceCalo; ///< Instance name ECAL for rec::CaloHit
95 
96  // ana objects
97  //TTree *fTree;
98  TH1F *fHistGenDiff;
99  TH1F *fHistG4Diff;
100  TH1F *fHistHitCompleteE; ///< MCParticle total energy remaining after all hits accounted for
101  TH1F *fHistHitCompleteKE; ///< MCParticle kinetic energy remaining after all hits accounted for
102  TH1F *fHistHitEnergy; ///< total energy contributed from each MCParticle to hits
109  TH1F *fHistEdeps; ///< total energy deposited by MCParticle via sdp::EnergyDeposit
110 
112 
113  // Geometry
114  const geo::GeometryCore* fGeo; ///< pointer to the geometry service
115 
116  // backtracker for determining inter product associations
117  cheat::BackTrackerCore* fBt;
118 
119 }; // class header
120 
121 
123  : EDAnalyzer{p} // ,
124  // More initializers here.
125 {
126  fGeantLabel = p.get<string>("GEANTLabel","geant");
127  fGeantInstanceCalo = p.get<string>("GEANTInstanceCalo","ECAL");
128  fHitLabel = p.get<string>("HitLabel","hit");
129  fTPCClusterLabel = p.get<string>("TPCClusterLabel","tpccluster");
130  fTrackLabel = p.get<string>("TrackLabel","track");
131  fVertexLabel = p.get<string>("VertexLabel","vertex");
132  fVeeLabel = p.get<string>("VeeLabel","veefinder1");
133  fCaloHitLabel = p.get<string>("CaloHitLabel","sipmhit");
134  fCaloHitInstanceCalo = p.get<string>("CaloHitInstanceCalo","ECAL");
135  fClusterLabel = p.get<string>("ClusterLabel","calocluster");
136 
137  // gen
138  consumesMany<vector<simb::MCTruth> >();
139  consumesMany<vector<simb::GTruth> >();
140 
141  // g4
142  consumes<art::Assns<simb::MCTruth, simb::MCParticle, void> >(fGeantLabel);
143  consumes<vector<simb::MCParticle> >(fGeantLabel);
144  consumes<vector<sdp::EnergyDeposit> >(fGeantLabel);
145  art::InputTag ecalgeanttag(fGeantLabel, fGeantInstanceCalo);
146  consumes<vector<sdp::CaloDeposit> >(ecalgeanttag);
147 
148  // reco
149  consumes<vector<rec::TPCCluster> >(fTPCClusterLabel);
150  consumes<art::Assns<rec::Track, rec::TPCCluster, void> >(fTPCClusterLabel);
151  consumes<vector<rec::Hit> >(fHitLabel);
152  consumes<vector<rec::Track> >(fTrackLabel);
153  consumes<vector<rec::Vertex> >(fVertexLabel);
154  consumes<art::Assns<rec::Track, rec::Vertex, void> >(fVertexLabel);
155  consumes<vector<rec::Vee> >(fVeeLabel);
156  consumes<art::Assns<rec::Track, rec::Vee, void> >(fVeeLabel);
157  consumes<vector<rec::TrackIoniz>>(fTrackLabel);
158  consumes<art::Assns<rec::TrackIoniz, rec::Track, void>>(fTrackLabel);
159  consumes<vector<rec::Cluster> >(fClusterLabel);
160  //consumes<Assns<rec::Cluster, rec::Track>>(fECALAssnLabel);
161 
162  fGeo = providerFrom<geo::GeometryGAr>();
163 
164 }// end constructor()
165 
167 
169  //fTree = tfs->make<TTree>("backtrackTree", "analyze garsoft::BackTracker performance");
170  fHistGenDiff = tfs->make<TH1F>("hGenDiff","gen stage;E_{final} - E_{initial} [MeV]",101,-500,500); //genie conserves energy?
171  fHistG4Diff = tfs->make<TH1F>("hG4Diff","G4 stage;E_{final} - E_{initial} [GeV]",301,-1000,2000);//geant conserves energy?
172  fHistEdeps = tfs->make<TH1F>("hEdeps","G4 stage - sdp::EnergyDeposit; remaining MCParticle KE [GeV]",200,-10,10);
173  fHistHitCompleteE = tfs->make<TH1F>("hHitCompleteE","reco stage: TPC hit;remaining MCParticle energy [GeV]",200,-10,10);
174  fHistHitCompleteKE = tfs->make<TH1F>("hHitCompleteKE","reco stage: TPC hit;remaining MCParticle energy [GeV]",200,-10,10);
175  fHistHitEnergy = tfs->make<TH1F>("hHitEnergy", "TPC Hit -> deposited energy; energy per hit [MeV]",1000,0,10);
176  fHistTrackHitDiff = tfs->make<TH1F>("hTrackHitDiff","reco stage: TPC track vs. hit;track - sum hit energy [GeV]",51,-2,2);
177  //fHistTrackTotHitSum = tfs->make<TH1F>("hTrackTotHitSum","reco stage: TPC track vs hit;
178  fHistTrackHitMult = tfs->make<TH1F>("hTrackHitMult","reco stage: TPC Track #rightarrow hit;hit duplication",30,-0.5,29.5);
179  fHistClustHitMult = tfs->make<TH1F>("hClustHitMult","reco stage: TPC cluster #rightarrow hit;hit duplication",30,-0.5,29.5);
180  fHistClustMult = tfs->make<TH1F>("hClustMult","reco stage: TPC track #rightarrow cluster;cluster duplication",30,-0.5,29.5);
181  fHistNHitAssocTrackNHitTotDiff = tfs->make<TH1F>("hNHitAssocTrackNHitTotDiff","TPC Track #rightarrow hit;total N^{0} hits - total N^{0} hits assoc'd to tracks",11001,-1000,10000);
182 
183  fHistEdepRelKE = tfs->make<TH1F>("hEdepRelKE","Track -> MCParticles;E_{dep}/KE_{initial}",29,0,29.001);//want 1 in the first bin
184  fHistG4Diff2d = tfs->make<TH2F>("hG4Diff2d","G4 stage;E_{initial} [GeV]; E_{final} [GeV]",100,0,1000,100,0,1000);
185 
186 }// end beginJob()
187 
189 {
190  cheat::BackTrackerCore const* const_bt = providerFrom<cheat::BackTracker>();
191  fBt = const_cast<cheat::BackTrackerCore*>(const_bt);
192 
193  // compare neutrino energy to FS particles (not expected to be conserved due to nuclear effects)
194 
195  bool warnClusterHitNotFound = true, warnTrackHitNotFound = true;
196 
197  //vector< art::Handle< vector<simb::MCTruth> > > mcthandlelist;
198  //vector< art::Handle< vector<simb::GTruth> > > gthandlelist;
199  //e.getManyByType(mcthandlelist);
200  auto gthandlelist = e.getMany< vector<simb::GTruth> >(); // update for art 3.0.9
201 
202  //const TDatabasePDG* databasePDG = TDatabasePDG::Instance();
203  //vector<double> e0, ef;
204 
205  //for(auto const& mcth : mcthandlelist) {
206  for(auto const& gth : gthandlelist) {
207 
208  // loop over single neutrino interactions
209  for(auto const& gt : *gth) {
210  /*for(auto const& mct : *mcth) {
211  const simb::MCNeutrino& mcnu = mct.GetNeutrino();
212  const simb::MCParticle& nu = mcnu.Nu();
213  double efinal = 0.;
214 
215  // loop over final state particles
216  for(int ifsp=0; ifsp < mct.NParticles(); ifsp++) {
217  const simb::MCParticle& mcp = mct.GetParticle(ifsp);
218  cout << "PDG code: " << mcp.PdgCode() << " w/total E = " << mcp.E() << endl;
219  if(mcp.PdgCode()!=2212 && mcp.PdgCode()!=2112 && mcp.PdgCode() < 3000) {
220  efinal += mcp.E();
221  }
222  else if(mcp.PdgCode()==2212 || mcp.PdgCode()==2112){
223  const TParticlePDG* definition = databasePDG->GetParticle( mcp.PdgCode() );
224  efinal += mcp.E() - definition->Mass();
225  }
226  else if(mcp.PdgCode()>1000000000) {
227  efinal +=
228  }
229  }*/
230  fHistGenDiff->Fill((gt.fFShadSystP4.E()+gt.fFSleptonP4.E()-gt.fProbeP4.E()-gt.fTgtP4.E()));
231  //fHistGenDiff->Fill(1000*(efinal - nu.E()));
232  }
233  }
234 
235 
236  // compare FS particle energies from gen stage to initial primary energies in g4 stage
237 
238  art::InputTag mcptag(fGeantLabel);
239  auto MCPHandle = e.getValidHandle<vector<simb::MCParticle>>(mcptag);
240  auto MCDepHandle = e.getValidHandle<vector<sdp::EnergyDeposit>>(mcptag);
241  double eprim = 0., efinal = 0.;
242 
243  map<int,double> mcpIdToKE, trkIdToERemain, trkIdToKERemain, trkIdToEdep; //maps for bookkeeping MCParticle energy
244 
245  //loop over energy deposits
246  for(sdp::EnergyDeposit const& ed : *MCDepHandle){
247  trkIdToEdep[ed.TrackID()] += ed.Energy();
248  }
249 
250  //loop over MCParticles
251  for ( auto mcp : *MCPHandle ) {
252 
253  mcpIdToKE[mcp.TrackId()] = mcp.E()-mcp.Momentum().M(); //initial KE
254 
255  if(mcp.PdgCode()>1e9) continue; //ignore nuclei
256 
257  // is it primary?
258  if(mcp.Process()=="primary"){
259  eprim += mcp.E();
260  }
261 
262  if(fGeo->PointInGArTPC(mcp.Position().Vect())) {
263  trkIdToKERemain[mcp.TrackId()] = mcp.E()-mcp.Momentum().M(); // fill with MCParticles initial KE
264  trkIdToERemain[mcp.TrackId()] = mcp.E(); // fill with MCParticles initial E
265  }
266 
267  efinal += mcp.EndE();
268 
269  if(mcp.E() < mcp.EndE())
270  std::cout << "MCParticle with final energy > intial energy ??? Ef-Ei = " << mcp.EndE()-mcp.E() << std::endl;
271 
272  double deltaEDep = mcp.E()-mcp.Momentum().M()-trkIdToEdep[mcp.TrackId()];
273  if(deltaEDep <0 && deltaEDep>1e-11)
274  deltaEDep=0.;
275  fHistEdeps->Fill(deltaEDep);
276  if(deltaEDep<-1e-11)
277  cout << "negative remaining energy from EnergyDeposit subtraction"
278  << "\n\ttrackID = " << mcp.TrackId()
279  << "\n\tPDG = " << mcp.PdgCode()
280  << "\n\tinitial KE = " << mcp.E()-mcp.Momentum().M()
281  << "\n\tMCP remaining energy = " << mcp.E()-mcp.Momentum().M()-trkIdToEdep[mcp.TrackId()]
282  << endl;
283 
284  }// for MCParticles
285 
286  fHistG4Diff->Fill(efinal-eprim);
287  fHistG4Diff2d->Fill(eprim,efinal);
288 
289  //------------------- reco -------------------------------------------------------------------
290  // loop over ALL hits, fill map to count instances in associations to TPCClusters and Tracks
291  art::InputTag tpchittag(fHitLabel);
292  auto TPCHitHandle = e.getValidHandle< vector<rec::Hit> >(tpchittag);
293  size_t nhit = TPCHitHandle->size(); //total number of hits
294  map<rec::Hit,int> track_hitcounts, cluster_hitcounts; //count instances of hits found from track/cluster associations
295  //int nprint = 0;
296  for ( rec::Hit const hit : *TPCHitHandle ) {
297 
298  /*if(nprint<5&&e.id().event()<10) {
299  cout << hit << endl;
300  nprint++;
301  }*/
302 
303  for(cheat::HitIDE const& ide : fBt->HitToHitIDEs(hit)) {
304  trkIdToERemain[ide.trackID] -= ide.energyTot; //subtract energy from MCParticle's total energy
305  trkIdToKERemain[ide.trackID] -= ide.energyTot; //subtract energy from MCParticle's available (kinetic) energy
306  fHistHitEnergy->Fill(ide.energyTot*1000.); //energy in hit converted to MeV
307  }
308 
309  if(track_hitcounts.find(hit)!=track_hitcounts.end()){
310  cout << "duplicate hits found in hit list" << endl;
311  }
312 
313  track_hitcounts[hit] = 0;
314  cluster_hitcounts[hit] = 0;
315 
316  }//for all hits
317 
318 
319  for(auto const& pair : trkIdToERemain) {
320  fHistHitCompleteE->Fill(pair.second);
321  }
322  for(auto const& pair : trkIdToKERemain) {
323  fHistHitCompleteKE->Fill(pair.second);
324  }
325 
326  //-------------------TPCCluster -> hits ----------------------------------------
327  art::InputTag tpcclustag(fTPCClusterLabel);
328  auto TPCClusterHandle = e.getValidHandle< vector<rec::TPCCluster> >(tpcclustag);
329  map<const rec::IDNumber,int> tpcclustcounts; //map of all TPCClusters to num instances in associations
330  int nclusterhit =0, nclusterhit_notfound = 0;
331  for(auto clust : *TPCClusterHandle) {
332 
333  if(tpcclustcounts.find(clust.getIDNumber())!=tpcclustcounts.end())
334  cout << "duplicate TPCClusters found!" << endl;
335  tpcclustcounts[clust.getIDNumber()] = 0;
336 
337  // for hits associated to this cluster
338  for(art::Ptr<rec::Hit> const& hit : fBt->TPCClusterToHits(&clust)) {
339  nclusterhit++;
340  if(cluster_hitcounts.find(*hit)==cluster_hitcounts.end()) {
341  nclusterhit_notfound++;
342  if(warnClusterHitNotFound) {
343  cout << "TPC hit associated to TPC cluster not found in hit list" << endl; //*********
344  warnClusterHitNotFound = false;
345  }
346  continue;
347  }
348  cluster_hitcounts[*hit] += 1;
349  }// for matched hits
350  }// for all TPCClusters
351 
352  //----------- TPC track->hits --------------------------------------
353  art::InputTag tracktag(fTrackLabel);
354  auto TrackHandle = e.getValidHandle< vector<rec::Track> >(tracktag);
355  size_t ntrackhit = 0;
356  for(auto track : *TrackHandle ) {
357 
358  // ------- TPC track -> clusters -------------------------
359  for(auto const& clust : fBt->TrackToClusters(&track) ) {
360  if(tpcclustcounts.find(clust->getIDNumber())==tpcclustcounts.end()) {
361  //if(warnTrackHitNotFound){
362  cout << "TPCCluster associated to track not found in cluster list" << endl;
363  //warnTrackHitNotFound = false;
364  //}
365  continue;
366  }
367  tpcclustcounts[clust->getIDNumber()] += 1;
368  }
369 
370  std::vector<std::pair<simb::MCParticle*,float>> trkmcps = fBt->TrackToMCParticles(&track);
371  double etot = fBt->TrackToTotalEnergy(&track);
372  double ehits = 0.;
373  vector<art::Ptr<rec::Hit>> const hits = fBt->TrackToHits(&track);
374  ntrackhit += hits.size();
375 
376  for(std::pair<simb::MCParticle*,float> const& mcp : trkmcps) {
377  if(mcpIdToKE.find(mcp.first->TrackId())==mcpIdToKE.end()){
378  std::cout << "MCParticle matched to track not found in MCParticle list" << std::endl;
379  continue;
380  }
381  double eratio = mcp.second*etot/mcpIdToKE[mcp.first->TrackId()];
382  fHistEdepRelKE->Fill(eratio);
383  if(eratio>1)
384  cout << "bad true contributed energy to track:MCParticle initial KE ratio!"
385  << "\n\ttrackID = " << mcp.first->TrackId()
386  << "\n\tPDG = " << mcp.first->PdgCode()
387  << "\n\tTotal energy = " << mcp.first->E() << " GeV"
388  << "\n\tKE0 = " << mcpIdToKE[mcp.first->TrackId()] << " GeV"
389  << "\n\tTotal track length = " << mcp.first->Trajectory().TotalLength() << " cm"
390  << "\n\tAvg. dE/dx = " << (mcp.first->E()-mcp.first->EndE())*1e3/mcp.first->Trajectory().TotalLength()<< " MeV/cm"
391  << "\n\ttotal true track energy = " << etot << " GeV"
392  << "\n\ttrue energy contributed = " << mcp.second*etot << " GeV"
393  << "\n\tFraction of total true track energy contributed = " << mcp.second
394  << "\n\tratio = " << eratio
395  << endl;
396  }
397 
398  for(auto const& hit : hits) {
399 
400  if(track_hitcounts.find(*hit)==track_hitcounts.end()) {
401  if(warnTrackHitNotFound){
402  cout << "TPC hit associated to track not found in hit list" << endl;//*********
403  //std::cout << *hit << std::endl;
404  warnTrackHitNotFound = false;
405  }
406  continue;
407  }
408  //track_hitcounts[hit.getIDNumber()] += 1;
409  track_hitcounts[*hit] += 1;
410 
411  for(auto const& ide : fBt->HitToHitIDEs(hit)) {
412  ehits += ide.energyTot;
413  }
414  }
415  fHistTrackHitDiff->Fill(etot-ehits);
416  }
417 
418  for(auto const& cts : track_hitcounts) {
419  fHistTrackHitMult->Fill(cts.second);
420  }
421 
422  for(auto const& cts : cluster_hitcounts) {
423  fHistClustHitMult->Fill(cts.second);
424  }
425  for(auto const& cts : tpcclustcounts) {
426  fHistClustMult->Fill(cts.second);
427  }
428  fHistNHitAssocTrackNHitTotDiff->Fill((int)nhit - (int)ntrackhit);
429  //cout << "total # hits - # hits associated with tracks = " << (int)nhit - (int)ntrackhit << endl;
430 }// end analyze()
431 
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
const geo::GeometryCore * fGeo
pointer to the geometry service
TH1F * fHistHitCompleteE
MCParticle total energy remaining after all hits accounted for.
string fTrackLabel
module label for TPC Tracks rec:Track
string fVeeLabel
module label for conversion/decay vertexes rec:Vee
TH1F * fHistHitCompleteKE
MCParticle kinetic energy remaining after all hits accounted for.
string fGeantInstanceCalo
Instance name ECAL for sdp::CaloDeposit.
string fVertexLabel
module label for vertexes rec:Vertex
virtual void beginJob() override
string fHitLabel
module label for reco TPC hits rec::Hit
STL namespace.
TH1F * fHistEdeps
total energy deposited by MCParticle via sdp::EnergyDeposit
cheat::BackTrackerCore * fBt
Particle class.
string fCaloHitLabel
module label for reco calo hits rec::CaloHit
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
uint8_t nhit
Definition: CRTFragment.hh:201
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
BackTrackerAna(fhicl::ParameterSet const &p)
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
Description of geometry of one entire detector.
TH1F * fHistHitEnergy
total energy contributed from each MCParticle to hits
Detector simulation of raw signals on wires.
string fGeantLabel
module label for geant4 simulated hits
void analyze(art::Event const &e) override
General GArSoft Utilities.
string fTPCClusterLabel
module label for TPC Clusters rec::TPCCluster
string fCaloHitInstanceCalo
Instance name ECAL for rec::CaloHit.
string fClusterLabel
module label for calo clusters rec::Cluster
art framework interface to geometry description
QTextStream & endl(QTextStream &s)