All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRTDetSimAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CRTDetSimAna
3 // Module Type: analyzer
4 // File: CRTDetSimAna_module.cc
5 //
6 // Analysis module for evaluating CRT reconstruction on through going
7 // muons.
8 //
9 // Tom Brooks (tbrooks@fnal.gov)
10 ////////////////////////////////////////////////////////////////////////
11 
12 // sbndcode includes
17 
18 // LArSoft includes
21 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
26 #include "nusimdata/SimulationBase/MCParticle.h"
27 #include "nusimdata/SimulationBase/MCTruth.h"
28 
29 // Framework includes
30 #include "art/Framework/Core/EDAnalyzer.h"
31 #include "art/Framework/Principal/Event.h"
32 #include "art/Framework/Principal/Handle.h"
33 #include "art/Framework/Services/Registry/ServiceHandle.h"
34 #include "art_root_io/TFileService.h"
35 #include "art/Framework/Core/ModuleMacros.h"
36 #include "canvas/Persistency/Common/FindManyP.h"
37 #include "canvas/Utilities/Exception.h"
40 
41 // Utility libraries
42 #include "messagefacility/MessageLogger/MessageLogger.h"
43 #include "fhiclcpp/ParameterSet.h"
44 #include "fhiclcpp/types/Table.h"
45 #include "fhiclcpp/types/Atom.h"
46 #include "cetlib/pow.h" // cet::sum_of_squares()
47 
48 // ROOT includes. Note: To look up the properties of the ROOT classes,
49 // use the ROOT web site; e.g.,
50 // <https://root.cern.ch/doc/master/annotated.html>
51 #include "TH1.h"
52 #include "TH2.h"
53 #include "TVector3.h"
54 #include "TString.h"
55 
56 // C++ includes
57 #include <map>
58 #include <vector>
59 #include <string>
60 
61 namespace sbnd {
62 
63  class CRTDetSimAna : 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 particle simulation data product")
75  };
76 
77  fhicl::Atom<art::InputTag> SimChannelModuleLabel {
78  Name("SimChannelModuleLabel"),
79  Comment("tag of channel simulation data product")
80  };
81 
82  fhicl::Atom<art::InputTag> CRTSimLabel {
83  Name("CRTSimLabel"),
84  Comment("tag of CRT simulation data product")
85  };
86 
87  fhicl::Atom<bool> Verbose {
88  Name("Verbose"),
89  Comment("Print information about what's going on")
90  };
91 
92  fhicl::Atom<double> QPed {
93  Name("QPed"),
94  };
95 
96  fhicl::Atom<double> QSlope {
97  Name("QSlope"),
98  };
99 
100  fhicl::Atom<double> ClockSpeedCRT {
101  Name("ClockSpeedCRT"),
102  Comment("Clock speed of the CRT system [MHz]")
103  };
104 
105  fhicl::Table<CRTBackTracker::Config> CrtBackTrack {
106  Name("CrtBackTrack"),
107  };
108 
109  }; // Config
110 
111  using Parameters = art::EDAnalyzer::Table<Config>;
112 
113  // Constructor: configures module
114  explicit CRTDetSimAna(Parameters const& config);
115 
116  // Called once, at start of the job
117  virtual void beginJob() override;
118 
119  // Called once per event
120  virtual void analyze(const art::Event& event) override;
121 
122  // Called once, at end of the job
123  virtual void endJob() override;
124 
125  private:
126 
127  // fcl file parameters
128  art::InputTag fSimModuleLabel; ///< name of MCParticle producer in g4
129  art::InputTag fSimChannelModuleLabel; ///< name of SimChannel producer in g4
130  art::InputTag fCRTSimLabel; ///< name of CRT producer
131  bool fVerbose; ///< print information about what's going on
132  double fQPed;
133  double fQSlope;
135 
136  // Histograms
137  // ADCs of crt data
138  std::map<std::string, TH1D*> hADC;
139  std::map<std::string, TH1D*> hNpe;
140  std::map<std::string, TH1D*> hNpeRatio;
141  // Time of CRT data
142  std::map<std::string, TH1D*> hTime;
143  std::map<std::string, TH1D*> hStripDist;
144  std::map<std::string, TH1D*> hSipmDist;
145 
146  // Efficiency plots
147  std::map<std::string, TH1D*> hEffSipmDistTotal;
148  std::map<std::string, TH1D*> hEffSipmDistReco;
149  std::map<std::string, TH1D*> hEffStripDistTotal;
150  std::map<std::string, TH1D*> hEffStripDistReco;
151  std::map<std::string, TH1D*> hEffEDepTotal;
152  std::map<std::string, TH1D*> hEffEDepReco;
153  std::map<std::string, TH1D*> hEffLengthTotal;
154  std::map<std::string, TH1D*> hEffLengthReco;
155 
156  // ADC as a function of distance from distance along width
157  std::map<std::string, TH2D*> hStripDistADC;
158  std::map<std::string, TH2D*> hSipmDistADC;
159  std::map<std::string, TH2D*> hStripDistNpe;
160  std::map<std::string, TH2D*> hSipmDistNpe;
161  std::map<std::string, TH2D*> hSipmDistNpeRatio;
162 
163  // Other variables shared between different methods.
168 
169  }; // class CRTDetSimAna
170 
171  // Constructor
173  : EDAnalyzer(config)
174  , fSimModuleLabel (config().SimModuleLabel())
175  , fSimChannelModuleLabel(config().SimChannelModuleLabel())
176  , fCRTSimLabel (config().CRTSimLabel())
177  , fVerbose (config().Verbose())
178  , fQPed (config().QPed())
179  , fQSlope (config().QSlope())
180  , fClockSpeedCRT (config().ClockSpeedCRT())
181  , fCrtBackTrack (config().CrtBackTrack())
182  {
183  // Get a pointer to the fGeometryServiceetry service provider
184  fGeometryService = lar::providerFrom<geo::Geometry>();
185  }
186 
188  {
189  // Access tfileservice to handle creating and writing histograms
190  art::ServiceHandle<art::TFileService> tfs;
191  for(size_t i = 0; i < fCrtGeo.NumTaggers(); i++){
192  std::string tagger = fCrtGeo.GetTagger(i).name;
193  hADC[tagger] = tfs->make<TH1D>(Form("ADC_%s", tagger.c_str()), "", 40, 0, 10000);
194  hNpe[tagger] = tfs->make<TH1D>(Form("Npe_%s", tagger.c_str()), "", 40, 0, 300);
195  hNpeRatio[tagger] = tfs->make<TH1D>(Form("NpeRatio_%s", tagger.c_str()), "", 40, 0, 10);
196  hTime[tagger] = tfs->make<TH1D>(Form("Time_%s", tagger.c_str()), "", 40, -5000, 5000);
197  hStripDist[tagger] = tfs->make<TH1D>(Form("StripDist_%s", tagger.c_str()), "", 40, 0, 450);
198  hSipmDist[tagger] = tfs->make<TH1D>(Form("SipmDist_%s", tagger.c_str()), "", 40, 0, 11.2);
199 
200  hEffSipmDistTotal[tagger] = tfs->make<TH1D>(Form("EffSipmDistTotal_%s", tagger.c_str()), "", 20, 0, 11.2);
201  hEffSipmDistReco[tagger] = tfs->make<TH1D>(Form("EffSipmDistReco_%s", tagger.c_str()), "", 20, 0, 11.2);
202  hEffStripDistTotal[tagger] = tfs->make<TH1D>(Form("EffStripDistTotal_%s", tagger.c_str()), "", 20, 0, 450);
203  hEffStripDistReco[tagger] = tfs->make<TH1D>(Form("EffStripDistReco_%s", tagger.c_str()), "", 20, 0, 450);
204  hEffEDepTotal[tagger] = tfs->make<TH1D>(Form("EffEdepTotal_%s", tagger.c_str()), "", 20, 0, 0.01);
205  hEffEDepReco[tagger] = tfs->make<TH1D>(Form("EffEdepReco_%s", tagger.c_str()), "", 20, 0, 0.01);
206  hEffLengthTotal[tagger] = tfs->make<TH1D>(Form("EffLengthTotal_%s", tagger.c_str()), "", 20, 0, 10);
207  hEffLengthReco[tagger] = tfs->make<TH1D>(Form("EffLengthReco_%s", tagger.c_str()), "", 20, 0, 10);
208 
209  hStripDistADC[tagger] = tfs->make<TH2D>(Form("StripDistADC_%s", tagger.c_str()), "", 20, 0, 450, 20, 0, 10000);
210  hSipmDistADC[tagger] = tfs->make<TH2D>(Form("SipmDistADC_%s", tagger.c_str()), "", 20, 0, 11.2, 20, 0, 10000);
211  hStripDistNpe[tagger] = tfs->make<TH2D>(Form("StripDistNpe_%s", tagger.c_str()), "", 20, 0, 450, 20, 0, 300);
212  hSipmDistNpe[tagger] = tfs->make<TH2D>(Form("SipmDistNpe_%s", tagger.c_str()), "", 20, 0, 11.2, 20, 0, 300);
213  hSipmDistNpeRatio[tagger] = tfs->make<TH2D>(Form("SipmDistNpeRatio_%s", tagger.c_str()), "", 20, 0, 11.2, 20, 0, 10);
214  }
215 
216 
217  // Initial output
218  std::cout<<"----------------- Full CRT Detector Simulation Analysis Module -------------------"<<std::endl;
219 
220  }// CRTDetSimAna::beginJob()
221 
222  void CRTDetSimAna::analyze(const art::Event& event)
223  {
224 
225  // Fetch basic event info
226  if(fVerbose){
227  std::cout<<"============================================"<<std::endl
228  <<"Run = "<<event.run()<<", SubRun = "<<event.subRun()<<", Event = "<<event.id().event()<<std::endl
229  <<"============================================"<<std::endl;
230  }
231 
232 
233  //----------------------------------------------------------------------------------------------------------
234  // GETTING PRODUCTS
235  //----------------------------------------------------------------------------------------------------------
236 
237  // Get g4 particles
238  art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
239  auto particleHandle = event.getValidHandle<std::vector<simb::MCParticle>>(fSimModuleLabel);
240 
241  // Get CRT data from the event
242  art::Handle< std::vector<sbnd::crt::CRTData>> crtDataHandle;
243  std::vector<art::Ptr<sbnd::crt::CRTData> > crtDataList;
244  if (event.getByLabel(fCRTSimLabel, crtDataHandle))
245  art::fill_ptr_vector(crtDataList, crtDataHandle);
246 
247  art::FindManyP<sim::AuxDetIDE> findManyIdes(crtDataHandle, event, fCRTSimLabel);
248 
249  // Get all the auxdet IDEs from the event
250  art::Handle<std::vector<sim::AuxDetSimChannel> > channels;
251  event.getByLabel(fSimChannelModuleLabel, channels);
252 
253  //----------------------------------------------------------------------------------------------------------
254  // TRUTH MATCHING
255  //----------------------------------------------------------------------------------------------------------
256 
257  std::map<int, simb::MCParticle> particles;
258  // Loop over the true particles
259  for (auto const& particle: (*particleHandle)){
260 
261  // Make map with ID
262  int partID = particle.TrackId();
263  particles[partID] = particle;
264 
265  }
266 
267  //----------------------------------------------------------------------------------------------------------
268  // CRT DATA ANALYSIS
269  //----------------------------------------------------------------------------------------------------------
270 
271  std::map<int, std::vector<sbnd::crt::CRTData>> crtData;
272  for(size_t i = 0; i < crtDataList.size(); i++){
273 
274  // Truth matching
275  std::vector<int> trueIDs = fCrtBackTrack.AllTrueIds(event, *crtDataList[i]);
276  for(auto const& id : trueIDs){
277  crtData[id].push_back(*crtDataList[i]);
278  }
279 
280  int trueID = fCrtBackTrack.TrueIdFromTotalEnergy(event, *crtDataList[i]);
281  // Only consider primary muons
282  if(particles.find(trueID) == particles.end()) continue;
283  if(!(std::abs(particles[trueID].PdgCode()) == 13 && particles[trueID].Mother() == 0)) continue;
284 
285  // Get the IDEs associated with the crtData
286  std::vector<art::Ptr<sim::AuxDetIDE>> ides = findManyIdes.at(i);
287  // Calculate the average position
288  double x = 0, y = 0, z = 0;
289  for(auto const& ide : ides){
290  x += (ide->entryX + ide->exitX)/2.;
291  y += (ide->entryY + ide->exitY)/2.;
292  z += (ide->entryZ + ide->exitZ)/2.;
293  }
294  x = x/ides.size();
295  y = y/ides.size();
296  z = z/ides.size();
297  geo::Point_t cross {x, y, z};
298 
299  int channel = crtDataList[i]->Channel();
300  std::string stripName = fCrtGeo.ChannelToStripName(channel);
301  std::string tagger = fCrtGeo.GetTaggerName(stripName);
302 
303  double npe = ((double)crtDataList[i]->ADC() - fQPed)/fQSlope;
304 
305  // Calculate distance to the sipm
306  double sipmDist = fCrtGeo.DistanceBetweenSipms(cross, channel);
307  hSipmDist[tagger]->Fill(sipmDist);
308  hSipmDistADC[tagger]->Fill(sipmDist, crtDataList[i]->ADC());
309  hSipmDistNpe[tagger]->Fill(sipmDist, npe);
310 
311  if(channel % 2 == 0){
312  double npe1 = ((double)crtDataList[i+1]->ADC() - fQPed)/fQSlope;
313  hNpeRatio[tagger]->Fill(npe/npe1);
314  hSipmDistNpeRatio[tagger]->Fill(sipmDist, npe/npe1);
315  }
316 
317  // Calculate the distance to the end
318  double stripDist = std::abs(fCrtGeo.DistanceDownStrip(cross, stripName));
319  hStripDist[tagger]->Fill(stripDist);
320  hStripDistADC[tagger]->Fill(stripDist, crtDataList[i]->ADC());
321  hStripDistNpe[tagger]->Fill(stripDist, npe);
322 
323  hADC[tagger]->Fill(crtDataList[i]->ADC());
324  hNpe[tagger]->Fill(npe);
325 
326  //fTrigClock.SetTime(crtDataList[i]->T0());
327  //double time = fTrigClock.Time(); // [us]
328  double time = (double)(int)crtDataList[i]->T0()/fClockSpeedCRT; // [tick -> us]
329  hTime[tagger]->Fill(time);
330  }
331 
332  //----------------------------------------------------------------------------------------------------------
333  // EFFICIENCIES
334  //----------------------------------------------------------------------------------------------------------
335 
336  for (auto& adsc : *channels) {
337  // Get the IDEs from the Aux Det channels
338  if(adsc.AuxDetSensitiveID() == UINT_MAX) {
339  mf::LogWarning("CRTDetSimAna") << "AuxDetSimChannel with ID: UINT_MAX\n"
340  << "skipping channel...";
341  continue;
342  }
343 
344  std::string stripName = fCrtGeo.GetStrip(adsc.AuxDetSensitiveID()).name;
345  std::string tagger = fCrtGeo.GetTaggerName(stripName);
346  std::vector<sim::AuxDetIDE> ides = adsc.AuxDetIDEs();
347 
348  for(auto const& ide : ides){
349  geo::Point_t pos {(ide.entryX + ide.exitX)/2,
350  (ide.entryY + ide.exitY)/2,
351  (ide.entryZ + ide.exitZ)/2};
352  int trueID = ide.trackID;
353  // Calculate length in strip
354  double length = std::sqrt(std::pow(ide.entryX - ide.exitX, 2)
355  + std::pow(ide.entryY - ide.exitY, 2)
356  + std::pow(ide.entryZ - ide.exitZ, 2));
357  // Calculate distances of average point to sipms
358  double sipmDistIde = fCrtGeo.DistanceBetweenSipms(pos, stripName);
359  double stripDistIde = fCrtGeo.DistanceDownStrip(pos, stripName);
360 
361  // Only consider primary muons for efficiency
362  if(particles.find(trueID) == particles.end()) continue;
363  if(!(std::abs(particles[trueID].PdgCode()) == 13 && particles[trueID].Mother() == 0)) continue;
364 
365  // Fill total histograms
366  hEffSipmDistTotal[tagger]->Fill(sipmDistIde);
367  hEffStripDistTotal[tagger]->Fill(stripDistIde);
368  hEffEDepTotal[tagger]->Fill(ide.energyDeposited);
369  hEffLengthTotal[tagger]->Fill(length);
370 
371  // Get all the CRT data matched to the same true ID
372  if(crtData.find(trueID) == crtData.end()) continue;
373  bool match = false;
374  // If there is CRT data produced on the same channel then it is matched
375  for(auto const& data : crtData[trueID]){
376  std::string stripNameData = fCrtGeo.ChannelToStripName(data.Channel());
377  if(stripName == stripNameData) match = true;
378  }
379  if(!match) continue;
380 
381  // Fill reconstructed histograms
382  hEffSipmDistReco[tagger]->Fill(sipmDistIde);
383  hEffStripDistReco[tagger]->Fill(stripDistIde);
384  hEffEDepReco[tagger]->Fill(ide.energyDeposited);
385  hEffLengthReco[tagger]->Fill(length);
386 
387  }
388  }
389 
390 
391  } // CRTDetSimAna::analyze()
392 
394 
395  } // CRTDetSimAna::endJob()
396 
397 
398  DEFINE_ART_MODULE(CRTDetSimAna)
399 } // namespace sbnd
BEGIN_PROLOG Verbose
art::EDAnalyzer::Table< Config > Parameters
process_name opflash particleana ie ie ie z
fhicl::Atom< double > QSlope
std::vector< int > AllTrueIds(const art::Event &event, const sbnd::crt::CRTData &data)
Utilities related to art service access.
process_name opflash particleana ie x
std::map< std::string, TH1D * > hEffStripDistReco
std::map< std::string, TH1D * > hSipmDist
CRTTaggerGeo GetTagger(std::string taggerName) const
CRTBackTracker fCrtBackTrack
std::map< std::string, TH1D * > hEffStripDistTotal
fhicl::Atom< art::InputTag > SimModuleLabel
fhicl::Atom< double > QPed
std::map< std::string, TH1D * > hEffLengthTotal
art::InputTag fCRTSimLabel
name of CRT producer
bool fVerbose
print information about what&#39;s going on
fhicl::Atom< art::InputTag > CRTSimLabel
std::map< std::string, TH1D * > hNpe
int TrueIdFromTotalEnergy(const art::Event &event, const sbnd::crt::CRTData &data)
art::InputTag fSimModuleLabel
name of MCParticle producer in g4
fhicl::Table< CRTBackTracker::Config > CrtBackTrack
CRTDetSimAna(Parameters const &config)
virtual void beginJob() override
Access the description of detector geometry.
T abs(T value)
object containing MC truth information necessary for making RawDigits and doing back tracking ...
process_name opflash particleana ie ie y
virtual void analyze(const art::Event &event) override
std::string ChannelToStripName(size_t channel) const
art framework interface to geometry description for auxiliary detectors
double DistanceDownStrip(geo::Point_t position, std::string stripName) const
BEGIN_PROLOG vertical distance to the surface Name
CRTStripGeo GetStrip(std::string stripName) const
std::map< std::string, TH2D * > hSipmDistNpeRatio
fhicl::Atom< double > ClockSpeedCRT
Description of geometry of one entire detector.
Definition of data types for geometry description.
std::string GetTaggerName(std::string name) const
std::map< std::string, TH1D * > hNpeRatio
fhicl::Atom< art::InputTag > SimChannelModuleLabel
std::map< std::string, TH2D * > hSipmDistNpe
std::map< std::string, TH1D * > hADC
std::map< std::string, TH1D * > hEffSipmDistReco
virtual void endJob() override
std::map< std::string, TH1D * > hEffEDepTotal
std::map< std::string, TH2D * > hSipmDistADC
stream1 can override from command line with o or output services user sbnd
then echo fcl name
std::map< std::string, TH1D * > hEffEDepReco
art::ServiceHandle< art::TFileService > tfs
std::map< std::string, TH2D * > hStripDistADC
std::map< std::string, TH1D * > hStripDist
art::InputTag fSimChannelModuleLabel
name of SimChannel producer in g4
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
std::map< std::string, TH1D * > hTime
std::map< std::string, TH1D * > hEffLengthReco
std::map< std::string, TH1D * > hEffSipmDistTotal
std::map< std::string, TH2D * > hStripDistNpe
art framework interface to geometry description
BEGIN_PROLOG could also be cout
geo::GeometryCore const * fGeometryService
double DistanceBetweenSipms(geo::Point_t position, size_t channel) const