All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRTHitRecoAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CRTHitRecoAna
3 // Module Type: analyzer
4 // File: CRTHitRecoAna_module.cc
5 //
6 // Analysis module for evaluating CRT hit reconstruction on through going
7 // muons.
8 //
9 // Tom Brooks (tbrooks@fnal.gov)
10 ////////////////////////////////////////////////////////////////////////
11 
12 // sbndcode includes
18 
19 // LArSoft includes
22 #include "nusimdata/SimulationBase/MCParticle.h"
23 
24 // Framework includes
25 #include "art/Framework/Core/EDAnalyzer.h"
26 #include "art/Framework/Principal/Event.h"
27 #include "art/Framework/Principal/Handle.h"
28 #include "art/Framework/Services/Registry/ServiceHandle.h"
29 #include "art_root_io/TFileService.h"
30 #include "art/Framework/Core/ModuleMacros.h"
31 #include "canvas/Persistency/Common/FindManyP.h"
32 #include "canvas/Utilities/Exception.h"
34 
35 
36 // Utility libraries
37 #include "messagefacility/MessageLogger/MessageLogger.h"
38 #include "fhiclcpp/ParameterSet.h"
39 #include "fhiclcpp/types/Table.h"
40 #include "fhiclcpp/types/Atom.h"
41 
42 // ROOT includes. Note: To look up the properties of the ROOT classes,
43 // use the ROOT web site; e.g.,
44 // <https://root.cern.ch/doc/master/annotated.html>
45 #include "TH1.h"
46 #include "TH2.h"
47 #include "TGraphAsymmErrors.h"
48 #include "TVector3.h"
49 
50 // C++ includes
51 #include <map>
52 #include <vector>
53 #include <string>
54 
55 namespace {
56  // Local namespace for local functions
57  // Declare here, define later
58 
59 }
60 
61 namespace sbnd {
62 
63  class CRTHitRecoAna : public art::EDAnalyzer {
64  public:
65 
66  // Describes configuration parameters of the module
67  struct Config {
68  using Name = fhicl::Name;
69  using Comment = fhicl::Comment;
70 
71  // One Atom for each parameter
72  fhicl::Atom<art::InputTag> SimModuleLabel {
73  Name("SimModuleLabel"),
74  Comment("tag of detector simulation data product")
75  };
76 
77  fhicl::Atom<art::InputTag> CRTHitLabel {
78  Name("CRTHitLabel"),
79  Comment("tag of CRT hit product")
80  };
81 
82  fhicl::Atom<bool> Verbose {
83  Name("Verbose"),
84  Comment("Print information about what's going on")
85  };
86 
87  fhicl::Atom<bool> VeryVerbose {
88  Name("VeryVerbose"),
89  Comment("Print detailed information about every track")
90  };
91 
92  fhicl::Atom<bool> Plot {
93  Name("Plot"),
94  Comment("Plot tracks")
95  };
96 
97  fhicl::Atom<int> PlotTrackID {
98  Name("PlotTrackID"),
99  Comment("ID of track to plot")
100  };
101 
102  fhicl::Atom<double> MinAngleNpePlot {
103  Name("MinAngleNpePlot"),
104  Comment("Minimum angle for plotting Npe per hit")
105  };
106 
107  fhicl::Table<CRTEventDisplay::Config> Evd {
108  Name("Evd"),
109  };
110 
111  fhicl::Table<CRTBackTracker::Config> CrtBackTrack {
112  Name("CrtBackTrack"),
113  };
114 
115  }; // Config
116 
117  using Parameters = art::EDAnalyzer::Table<Config>;
118 
119  // Constructor: configures module
120  explicit CRTHitRecoAna(Parameters const& config);
121 
122  // Called once, at start of the job
123  virtual void beginJob() override;
124 
125  // Called once per event
126  virtual void analyze(const art::Event& event) override;
127 
128  // Called once, at end of the job
129  virtual void endJob() override;
130 
131  private:
132 
133  // fcl file parameters
134  art::InputTag fSimModuleLabel; ///< name of detsim producer
135  art::InputTag fCRTHitLabel; ///< name of CRT hit producer
136  bool fVerbose; ///< print information about what's going on
137  bool fVeryVerbose; ///< print more information about what's going on
138  bool fPlot; ///< plot tracks
139  int fPlotTrackID; ///< id of track to plot
140  double fMinAngleNpePlot; ///< Maximum angle for plotting Npe per hit
141 
142  // histograms
144 
145  std::map<std::string, TH1D*> hHitTime;
146  std::map<std::string, TH1D*> hNpe;
147  std::map<std::string, TH1D*> hAngle;
148  std::map<std::string, TH1D*> hRecoSipmDist;
149  std::map<std::string, TH1D*> hTrueSipmDist;
150 
151  std::map<std::string, TH1D*> hEffWidthTotal;
152  std::map<std::string, TH1D*> hEffWidthReco;
153  std::map<std::string, TH1D*> hEffLengthTotal;
154  std::map<std::string, TH1D*> hEffLengthReco;
155 
156  std::map<std::string,TH2D*> hTrueRecoSipmDist;
157  std::map<std::string,TH2D*> hNpeAngle;
158  std::map<std::string,TH2D*> hNpeSipmDist;
159  std::map<std::string,TH2D*> hNpeStripDist;
160 
161  // CRT helpers
165 
166  }; // class CRTHitRecoAna
167 
168  // Constructor
170  : EDAnalyzer(config)
171  , fSimModuleLabel (config().SimModuleLabel())
172  , fCRTHitLabel (config().CRTHitLabel())
173  , fVerbose (config().Verbose())
174  , fVeryVerbose (config().VeryVerbose())
175  , fPlot (config().Plot())
176  , fPlotTrackID (config().PlotTrackID())
177  , fMinAngleNpePlot (config().MinAngleNpePlot())
178  , evd (config().Evd())
179  , fCrtBackTrack (config().CrtBackTrack())
180  {
181 
182  }
183 
185  {
186  // Access tfileservice to handle creating and writing histograms
187  art::ServiceHandle<art::TFileService> tfs;
188  // Define histograms
189  hNpeAngleCut = tfs->make<TH1D>("NpeAngleCut", "", 60, 0, 600);
190  for(size_t i = 0; i < fCrtGeo.NumTaggers(); i++){
191  std::string tagger = fCrtGeo.GetTagger(i).name;
192  hRecoSipmDist[tagger] = tfs->make<TH1D>(Form("RecoSipmDist_%s", tagger.c_str()), "", 40, -2, 13);
193  hTrueSipmDist[tagger] = tfs->make<TH1D>(Form("TrueSipmDist_%s", tagger.c_str()), "", 40, -2, 13);
194  hHitTime[tagger] = tfs->make<TH1D>(Form("HitTime_%s", tagger.c_str()), "", 40, -2000, 3000);
195  hNpe[tagger] = tfs->make<TH1D>(Form("Npe_%s", tagger.c_str()), "", 60, 0, 600);
196  hAngle[tagger] = tfs->make<TH1D>(Form("Angle_%s", tagger.c_str()), "", 40, 0, 1.6);
197 
198  hEffWidthTotal[tagger] = tfs->make<TH1D>(Form("EffWidthTotal_%s", tagger.c_str()), "", 20, 0, 11.2);
199  hEffWidthReco[tagger] = tfs->make<TH1D>(Form("EffWidthReco_%s", tagger.c_str()), "", 20, 0, 11.2);
200  hEffLengthTotal[tagger] = tfs->make<TH1D>(Form("EffLengthTotal_%s", tagger.c_str()), "", 20, 0, 450);
201  hEffLengthReco[tagger] = tfs->make<TH1D>(Form("EffLengthReco_%s", tagger.c_str()), "", 20, 0, 450);
202 
203  hTrueRecoSipmDist[tagger] = tfs->make<TH2D>(Form("TrueRecoSipmDist_%s", tagger.c_str()), "", 30, -2, 13, 30, -2, 13);
204  hNpeAngle[tagger] = tfs->make<TH2D>(Form("NpeAngle_%s", tagger.c_str()), "", 30, 0, 1.6, 30, 0, 600);
205  hNpeSipmDist[tagger] = tfs->make<TH2D>(Form("NpeSipmDist_%s", tagger.c_str()), "", 30, 0, 11.2, 30, 0, 600);
206  hNpeStripDist[tagger] = tfs->make<TH2D>(Form("NpeStripDist_%s", tagger.c_str()), "", 30, 0, 450, 30, 0, 600);
207  }
208 
209  // Initial output
210  std::cout<<"----------------- CRT Hit Reco Ana Module -------------------"<<std::endl;
211 
212  }// CRTHitRecoAna::beginJob()
213 
214  void CRTHitRecoAna::analyze(const art::Event& event)
215  {
216 
217  // Fetch basic event info
218  if(fVerbose){
219  std::cout<<"============================================"<<std::endl
220  <<"Run = "<<event.run()<<", SubRun = "<<event.subRun()<<", Event = "<<event.id().event()<<std::endl
221  <<"============================================"<<std::endl;
222  }
223 
224  //----------------------------------------------------------------------------------------------------------
225  // GETTING PRODUCTS
226  //----------------------------------------------------------------------------------------------------------
227  // Retrieve all the truth info in the events
228  auto particleHandle = event.getValidHandle<std::vector<simb::MCParticle>>(fSimModuleLabel);
229 
230  // Get all the CRT hits
231  auto crtHitHandle = event.getValidHandle<std::vector<sbn::crt::CRTHit>>(fCRTHitLabel);
232 
233  // Get hit to data associations
234  art::FindManyP<sbnd::crt::CRTData> findManyData(crtHitHandle, event, fCRTHitLabel);
235 
236  fCrtBackTrack.Initialize(event);
237 
238  //----------------------------------------------------------------------------------------------------------
239  // TRUTH MATCHING
240  //----------------------------------------------------------------------------------------------------------
241  std::map<int, std::vector<sbn::crt::CRTHit>> crtHits;
242  double minHitTime = 99999;
243  double maxHitTime = -99999;
244  int ht_i = 0;
245  for(auto const& hit : (*crtHitHandle)){
246  int trueId = fCrtBackTrack.TrueIdFromHitId(event, ht_i);
247  ht_i++;
248  if(trueId == -99999) continue;
249  crtHits[trueId].push_back(hit);
250  double hitTime = (double)(int)hit.ts1_ns * 1e-3;
251  if(hitTime < minHitTime) minHitTime = hitTime;
252  if(hitTime > maxHitTime) maxHitTime = hitTime;
253  }
254 
255  //----------------------------------------------------------------------------------------------------------
256  // EFFICIENCIES
257  //----------------------------------------------------------------------------------------------------------
258  // Fill a map of true particles
259  std::map<int, simb::MCParticle> particles;
260  for (auto const& particle: (*particleHandle)){
261  int partId = particle.TrackId();
262  particles[partId] = particle;
263 
264  // Only consider particles within the time limit of the generated CRT hits
265  double time = particle.T() * 1e-3;
266  if(time < minHitTime || time > maxHitTime) continue;
267 
268  if(!(std::abs(particle.PdgCode()) == 13 && particle.Mother()==0)) continue;
269 
270  std::vector<std::string> stripNames = fCrtGeo.CrossesStrips(particle);
271 
272  for(auto const& stripName : stripNames){
273  std::string tagger = fCrtGeo.GetTaggerName(stripName);
274  if(!fCrtGeo.ValidCrossingPoint(tagger, particle)) continue;
275  geo::Point_t cross = fCrtGeo.StripCrossingPoint(stripName, particle);
276  double sipmDist = fCrtGeo.DistanceBetweenSipms(cross, stripName);
277  double stripDist = fCrtGeo.DistanceDownStrip(cross, stripName);
278  hEffWidthTotal[tagger]->Fill(sipmDist);
279  hEffLengthTotal[tagger]->Fill(stripDist);
280 
281  //Loop over crt hits
282  if(crtHits.find(partId) == crtHits.end()) continue;
283  bool match = false;
284  for(size_t i = 0; i < crtHits[partId].size(); i++){
285  //If you find a hit on the same tagger then fill
286  if(crtHits[partId][i].tagger == tagger) match = true;
287  }
288 
289  if(!match) continue;
290  hEffWidthReco[tagger]->Fill(sipmDist);
291  hEffLengthReco[tagger]->Fill(stripDist);
292  }
293  }
294 
295  //----------------------------------------------------------------------------------------------------------
296  // CRT HIT ANALYSIS
297  //----------------------------------------------------------------------------------------------------------
298  int hit_i = 0;
299  for(auto const& hit : (*crtHitHandle)){
300  std::string tagger = hit.tagger;
301 
302  // Calculate the time of the CRT hit in us
303  double time = (double)(int)hit.ts1_ns * 1e-3;
304  hHitTime[tagger]->Fill(time);
305 
306  geo::Point_t hitPos {hit.x_pos, hit.y_pos, hit.z_pos};
307 
308  // Get the data associated with the hit
309  std::vector<art::Ptr<sbnd::crt::CRTData>> data = findManyData.at(hit_i);
310 
311  // Get all the strips from the crt hit
312  std::vector<std::string> stripNames;
313  for(auto const& dat : data){
314  std::string name = fCrtGeo.ChannelToStripName(dat->Channel());
315  if(std::find(stripNames.begin(), stripNames.end(), name) == stripNames.end())
316  stripNames.push_back(name);
317  }
318 
319  // Match hit to true track
320  int trueId = fCrtBackTrack.TrueIdFromHitId(event, hit_i);
321  hit_i++;
322  if(particles.find(trueId) == particles.end()) continue;
323  if(!(std::abs(particles[trueId].PdgCode()) == 13 && particles[trueId].Mother()==0)) continue;
324 
325  // Calculate the angle to the tagger
326  double angle = TMath::Pi()/2. - fCrtGeo.AngleToTagger(tagger, particles[trueId]);
327  if(angle > fMinAngleNpePlot && tagger != "volTaggerBot_0") hNpeAngleCut->Fill(hit.peshit);
328  hNpe[tagger]->Fill(hit.peshit);
329  hAngle[tagger]->Fill(angle);
330  hNpeAngle[tagger]->Fill(angle, hit.peshit);
331 
332  // Calculate the true distance from the channel
333  for(auto const& stripName : stripNames){
334  // Calculate the reconstructed position between sipms
335  double hitDist = fCrtGeo.DistanceBetweenSipms(hitPos, stripName);
336  hRecoSipmDist[tagger]->Fill(hitDist);
337 
338  // Calculate the true position between the sipms
339  geo::Point_t truePos = fCrtGeo.StripCrossingPoint(stripName, particles[trueId]);
340  double trueDist = fCrtGeo.DistanceBetweenSipms(truePos, stripName);
341  hTrueSipmDist[tagger]->Fill(trueDist);
342  hTrueRecoSipmDist[tagger]->Fill(trueDist, hitDist);
343 
344  // Fill the number of pe as a function of distances
345  hNpeSipmDist[tagger]->Fill(trueDist, hit.peshit);
346  double stripDist = fCrtGeo.DistanceDownStrip(truePos, stripName);
347  hNpeStripDist[tagger]->Fill(stripDist, hit.peshit);
348  }
349 
350  }
351 
352  if(fPlot){
353  evd.SetDrawCrtData(true);
354  evd.SetDrawCrtHits(true);
355  evd.SetDrawCrtTracks(true);
356  if(fVeryVerbose) evd.SetPrint(true);
357  if(fPlotTrackID != -99999) evd.SetTrueId(fPlotTrackID);
358  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
359  evd.Draw(clockData, event);
360  }
361 
362  } // CRTHitRecoAna::analyze()
363 
365 
366  } // CRTHitRecoAna::endJob()
367 
368  DEFINE_ART_MODULE(CRTHitRecoAna)
369 } // namespace sbnd
370 
371 // Back to local namespace.
372 namespace {
373 
374 } // local namespace
std::map< std::string, TH2D * > hNpeAngle
BEGIN_PROLOG Verbose
void Draw(detinfo::DetectorClocksData const &clockData, const art::Event &event)
virtual void analyze(const art::Event &event) override
bool fVerbose
print information about what&#39;s going on
std::map< std::string, TH1D * > hEffLengthReco
virtual void beginJob() override
CRTTaggerGeo GetTagger(std::string taggerName) const
art::EDAnalyzer::Table< Config > Parameters
fhicl::Table< CRTEventDisplay::Config > Evd
geo::Point_t StripCrossingPoint(std::string stripName, const simb::MCParticle &particle)
std::map< std::string, TH2D * > hTrueRecoSipmDist
process_name hit
Definition: cheaterreco.fcl:51
int fPlotTrackID
id of track to plot
std::map< std::string, TH1D * > hRecoSipmDist
bool fVeryVerbose
print more information about what&#39;s going on
double fMinAngleNpePlot
Maximum angle for plotting Npe per hit.
int TrueIdFromHitId(const art::Event &event, int hit_i)
fhicl::Atom< art::InputTag > CRTHitLabel
std::map< std::string, TH1D * > hHitTime
T abs(T value)
std::map< std::string, TH1D * > hNpe
std::map< std::string, TH1D * > hAngle
art::InputTag fCRTHitLabel
name of CRT hit producer
fhicl::Table< CRTBackTracker::Config > CrtBackTrack
std::map< std::string, TH1D * > hEffWidthTotal
CRTHitRecoAna(Parameters const &config)
std::string ChannelToStripName(size_t channel) const
double DistanceDownStrip(geo::Point_t position, std::string stripName) const
BEGIN_PROLOG vertical distance to the surface Name
Definition of data types for geometry description.
std::string GetTaggerName(std::string name) const
std::vector< std::string > CrossesStrips(const simb::MCParticle &particle)
fhicl::Atom< double > MinAngleNpePlot
double AngleToTagger(std::string taggerName, const simb::MCParticle &particle)
std::map< std::string, TH1D * > hTrueSipmDist
void SetDrawCrtTracks(bool tf)
std::map< std::string, TH1D * > hEffLengthTotal
std::map< std::string, TH2D * > hNpeStripDist
std::map< std::string, TH2D * > hNpeSipmDist
do i e
stream1 can override from command line with o or output services user sbnd
then echo fcl name
finds tracks best matching by angle
virtual void endJob() override
art::ServiceHandle< art::TFileService > tfs
std::map< std::string, TH1D * > hEffWidthReco
void SetDrawCrtHits(bool tf)
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
bool ValidCrossingPoint(std::string taggerName, const simb::MCParticle &particle)
void SetDrawCrtData(bool tf)
BEGIN_PROLOG could also be cout
art::InputTag fSimModuleLabel
name of detsim producer
fhicl::Atom< art::InputTag > SimModuleLabel
double DistanceBetweenSipms(geo::Point_t position, size_t channel) const