All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ICARUSOpHitAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ICARUSOpHitAna
3 // Plugin Type: analyzer (art v3_01_01)
4 // File: ICARUSOpHitAna_module.cc
5 //
6 // Generated at Tue Feb 12 06:49:35 2019 by Kazuhiro Terao using cetskelgen
7 // from cetlib version v3_05_01.
8 ////////////////////////////////////////////////////////////////////////
9 
10 #include "art/Framework/Core/EDAnalyzer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "canvas/Utilities/InputTag.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
19 
21 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
24 #include <TTree.h>
25 #include <TFile.h>
26 
27 class ICARUSOpHitAna;
28 
29 class ICARUSOpHitAna : public art::EDAnalyzer {
30 public:
31  explicit ICARUSOpHitAna(fhicl::ParameterSet const& p);
32  // The compiler-generated destructor is fine for non-base
33  // classes without bare pointers or other resource use.
34 
35  // Plugins should not be copied or assigned.
36  ICARUSOpHitAna(ICARUSOpHitAna const&) = delete;
37  ICARUSOpHitAna(ICARUSOpHitAna&&) = delete;
38  ICARUSOpHitAna& operator=(ICARUSOpHitAna const&) = delete;
40 
41  // Required functions.
42  void analyze(art::Event const& e) override;
43  void beginJob() override;
44  void endJob() override;
45 private:
46 
47  // Declare member data here.
48  TFile *_f;
49  std::string _output_fname;
50  // For data product labels
51  std::string _wf_label;
52  std::string _mchit_label;
53  std::vector<std::string> _hit_label_v;
54 
55  // For waveform tree
56  TTree* _wftree;
57  int _run, _event, _ch;
58  double _tstart;
59  std::vector<float> _wf;
60  std::vector<std::string> _wf_label_v;
61 
62  // For hit trees
63  TTree* _mchittree;
64  std::vector<TTree*> _hittree_v;
65  double _width;
66  double _time;
67  double _amp;
68  double _area;
69  double _pe;
70  double _time_true;
71  double _pe_true;
72  int _mc_idx;
73 
74  // Time period to match reco<=>MC (in micro-second)
77  double _match_dt;
78 
79  // For geometry info
80  TTree *_geotree;
81 
82 };
83 
84 
85 ICARUSOpHitAna::ICARUSOpHitAna(fhicl::ParameterSet const& p)
86  : EDAnalyzer{p}, _wftree(nullptr), _mchittree(nullptr), _geotree(nullptr)
87 {
88  _output_fname = p.get<std::string>("OutputFileName" );
89  _wf_label = p.get<std::string>("OpDetWaveformProducer" );
90  _mchit_label = p.get<std::string>("MCOpHitProducer" );
91  _hit_label_v = p.get<std::vector<std::string> >("OpHitProducerList");
92  _match_time_min = p.get<double>("MatchTimeStart",0.100); // in micro-seconds
93  _match_time_max = p.get<double>("MatchTimeEnd",0.120); // in micro-seconds
94  _match_dt = _match_time_max - _match_time_min;
95  assert(_match_dt>0);
96 }
97 
99 {
100  _f = TFile::Open(_output_fname.c_str(),"RECREATE");
101  _wftree = nullptr;
102  if(!_wf_label.empty()) {
103  std::string name = _wf_label + "_wftree";
104  _wftree = new TTree(name.c_str(),name.c_str());
105  _wftree->Branch("run",&_run,"run/I");
106  _wftree->Branch("event",&_event,"event/I");
107  _wftree->Branch("ch",&_ch,"ch/I");
108  _wftree->Branch("wf",&_wf);
109  _wftree->Branch("tstart",&_tstart,"tstart/D");
110  }
111 
112  _mchittree = new TTree("mchittree","mchittree");
113  _mchittree->Branch("run",&_run,"run/I");
114  _mchittree->Branch("event",&_event,"event/I");
115  _mchittree->Branch("ch",&_ch,"ch/I");
116  _mchittree->Branch("mc_idx",&_mc_idx,"mc_idx/I");
117  _mchittree->Branch("pe_true",&_pe_true,"pe_true/D");
118  _mchittree->Branch("time_true",&_time_true,"time_true/D");
119 
120  for(auto const& label : _hit_label_v) {
121  std::string name = label + "_hittree";
122  auto hittree = new TTree(name.c_str(),name.c_str());
123  hittree->Branch("run",&_run,"run/I");
124  hittree->Branch("event",&_event,"event/I");
125  hittree->Branch("ch",&_ch,"ch/I");
126  hittree->Branch("amp",&_amp,"amp/D");
127  hittree->Branch("area",&_area,"area/D");
128  hittree->Branch("width",&_width,"width/D");
129  hittree->Branch("time",&_time,"time/D");
130  hittree->Branch("pe",&_pe,"pe/D");
131  hittree->Branch("time_true",&_time_true,"time_true/D");
132  hittree->Branch("pe_true",&_pe_true,"pe_true/D");
133  hittree->Branch("mc_idx",&_mc_idx,"mc_idx/I");
134  _hittree_v.push_back(hittree);
135  }
136 
137  _geotree = new TTree("geotree","geotree");
138  std::vector<double> pmtX, pmtY, pmtZ;
139  std::vector<double> minX, minY, minZ;
140  std::vector<double> maxX, maxY, maxZ;
141  auto const geop = lar::providerFrom<geo::Geometry>();
142  double PMTxyz[3];
143  for(size_t opch=0; opch<geop->NOpChannels(); ++opch) {
144  geop->OpDetGeoFromOpChannel(opch).GetCenter(PMTxyz);
145  pmtX.push_back(PMTxyz[0]);
146  pmtY.push_back(PMTxyz[1]);
147  pmtZ.push_back(PMTxyz[2]);
148  }
149  for(auto iter=geop->begin_TPC(); iter!=geop->end_TPC(); ++iter) {
150  auto const& tpc = (*iter);
151  minX.push_back(tpc.BoundingBox().MinX());
152  minY.push_back(tpc.BoundingBox().MinY());
153  minZ.push_back(tpc.BoundingBox().MinZ());
154  maxX.push_back(tpc.BoundingBox().MaxX());
155  maxY.push_back(tpc.BoundingBox().MaxY());
156  maxZ.push_back(tpc.BoundingBox().MaxZ());
157  }
158  _geotree->Branch("pmtX",&pmtX);
159  _geotree->Branch("pmtY",&pmtY);
160  _geotree->Branch("pmtZ",&pmtZ);
161  _geotree->Branch("minX",&minX);
162  _geotree->Branch("minY",&minY);
163  _geotree->Branch("minZ",&minZ);
164  _geotree->Branch("maxX",&maxX);
165  _geotree->Branch("maxY",&maxY);
166  _geotree->Branch("maxZ",&maxZ);
167  _geotree->Fill();
168 }
169 
171 {
172  _f->cd();
173  _mchittree->Write();
174  if(_wftree) _wftree->Write();
175  for(auto& ptr : _hittree_v) { _f->cd(); ptr->Write(); }
176  _f->cd(); _geotree->Write();
177  if(_f) _f->Close();
178 }
179 
180 void ICARUSOpHitAna::analyze(art::Event const& e)
181 {
182 
183  _event = e.id().event();
184  _run = e.id().run();
185 
186  // Fill waveforms if requested
187  if(!_wf_label.empty()) {
188  art::Handle< std::vector< raw::OpDetWaveform > > wf_h;
189  e.getByLabel(_wf_label,wf_h);
190  if(!wf_h.isValid()){
191  std::cerr << "Invalid producer for raw::OpDetWaveform: " << _wf_label << std::endl;
192  throw std::exception();
193  }
194  for(auto const& wf : (*wf_h)) {
195  _wf.resize(wf.size());
196  for(size_t i=0; i<_wf.size(); ++i) { _wf.at(i) = wf.at(i); }
197  _ch=wf.ChannelNumber();
198  _tstart=wf.TimeStamp();
199  _wftree->Fill();
200  }
201  }
202 
203  // get MCOpHit
204  art::Handle< std::vector< recob::OpHit > > mchit_h;
205  e.getByLabel(_mchit_label, mchit_h);
206  if(!mchit_h.isValid()) {
207  std::cerr << "Invalid producer for truth recob::OpHit: " << _mchit_label << std::endl;
208  throw std::exception();
209  }
210  // Create a "time-map" of MCOpHit
211  // outer-array = op channel number
212  // inner map ... key = mchit timing
213  // value = mchit location (i.e. array index number)
214  std::vector<std::map<double,int> > mchit_db;
215  // fill the map
216  auto const geop = lar::providerFrom<geo::Geometry>();
217  mchit_db.resize(geop->NOpChannels());
218  for(size_t mchit_index=0; mchit_index < mchit_h->size(); ++mchit_index) {
219  auto const& mchit = (*mchit_h)[mchit_index];
220  _pe_true = mchit.PE();
221  _time_true = mchit.PeakTime();
222  _ch = mchit.OpChannel();
223  _mc_idx = mchit_index;
224  _mchittree->Fill();
225  auto& db = mchit_db.at(mchit.OpChannel());
226  db[mchit.PeakTime() + _match_time_min] = mchit_index;
227  }
228  // now fill ophit trees
229  for(size_t label_idx=0; label_idx<_hit_label_v.size(); ++label_idx) {
230  // Get data product handle
231  auto const& label = _hit_label_v[label_idx];
232  auto& hittree = _hittree_v[label_idx];
233  art::Handle< std::vector< recob::OpHit > > hit_h;
234  e.getByLabel(label,hit_h);
235  if(!hit_h.isValid()){
236  std::cerr << "Invalid producer for recob::OpHit: " << label << std::endl;
237  throw std::exception();
238  }
239 
240  // keep the record of which mchit was used (to store un-tagged mchit at the end)
241  std::vector<bool> mchit_used(mchit_h->size(),false);
242  // now loop over hit, identify mc hit, fill ttree
243  for(auto const& hit : (*hit_h)) {
244  // fill simple info
245  _ch=hit.OpChannel();
246  _time = hit.PeakTime();
247  _amp = hit.Amplitude();
248  _width = hit.Width();
249  _area = hit.Area();
250  _pe = hit.PE();
251  // search for corresponding mchit
252  auto const& db = mchit_db.at(_ch);
253  auto low = db.lower_bound(_time);
254  _pe_true = -1;
255  _time_true = std::numeric_limits<double>::max();
256  if(low != db.begin()) {
257  --low;
258  // get mc ophit
259  auto const& mchit = (*mchit_h).at((*low).second);
260  // Check if this is in the "match" range
261  if( (_time - (*low).first) < _match_dt ) {
262  _pe_true = mchit.PE();
263  _time_true = mchit.PeakTime();
264  _mc_idx = (*low).second;
265  mchit_used[(*low).second] = true;
266  }
267  }
268  hittree->Fill();
269  }
270  // now fill mchit info that was not tagged
271  for(size_t mchit_idx=0; mchit_idx < mchit_used.size(); ++mchit_idx) {
272  if(mchit_used[mchit_idx]) continue;
273  auto const& mchit = (*mchit_h)[mchit_idx];
274  _ch = mchit.OpChannel();
275  _pe_true = mchit.PE();
276  _time_true = mchit.PeakTime();
277  // fill the "reco hit" values with vogus values
278  _time = std::numeric_limits<double>::max();
279  _amp = std::numeric_limits<double>::max();
280  _area = std::numeric_limits<double>::max();
281  _pe = -1;
282  hittree->Fill();
283  }
284 
285  }
286 
287 }
288 
289 DEFINE_ART_MODULE(ICARUSOpHitAna)
ICARUSOpHitAna & operator=(ICARUSOpHitAna const &)=delete
Utilities related to art service access.
BEGIN_PROLOG could also be cerr
void analyze(art::Event const &e) override
pdgs p
Definition: selectors.fcl:22
std::vector< std::string > _hit_label_v
process_name hit
Definition: cheaterreco.fcl:51
standard_dbscan3dalg useful for diagnostics hits not in a line will not be clustered on on only for track like only for track like on on the smaller the less shower like tracks low
void endJob() override
void beginJob() override
std::vector< TTree * > _hittree_v
ICARUSOpHitAna(fhicl::ParameterSet const &p)
do i e
then echo fcl name
height to which particles are projected pnfs larsoft persistent physics cosmics Fermilab CORSIKA standard He_showers_ * db
std::vector< float > _wf
std::vector< std::string > _wf_label_v
art framework interface to geometry description