All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
icaruscode/icaruscode/PMT/OpReco/FlashFinder/SimpleFlashAlgo.cxx
Go to the documentation of this file.
1 #ifndef SIMPLEFLASHALGO_CXX
2 #define SIMPLEFLASHALGO_CXX
3 
4 #include "SimpleFlashAlgo.h"
5 #include <set>
6 namespace pmtana{
7 
9 
11  : FlashAlgoBase(name)
12  {}
13 
15  {
16  Reset();
17  _debug = p.get<bool>("DebugMode",false);
18  _min_pe_hit = p.get<double>("PEThresholdHit",0.5);
19  _min_pe_flash = p.get<double>("PEThreshold",10);
20  _min_pe_coinc = p.get<double>("MinPECoinc", 5);
21  _min_mult_coinc = p.get<double>("MinMultCoinc", 2);
22  _integral_time = p.get<double>("IntegralTime",8);
23  _pre_sample = p.get<double>("PreSample",0.1);
24  _veto_time = p.get<double>("VetoSize",8.);
25  _time_res = p.get<double>("TimeResolution",0.03);
26  //_pe_baseline_v.clear();
27  //_pe_baseline_v = p.get<std::vector<double> >("PEBaseline",_pe_baseline_v);
28  if(_integral_time > _veto_time) {
29  std::cerr << "Integral time cannot exceed veto time!" << std::endl;
30  throw std::exception();
31  }
32  auto const range_start_v = p.get<std::vector<double> >("HitVetoRangeStart");
33  auto const range_end_v = p.get<std::vector<double> >("HitVetoRangeEnd");
34  if(range_start_v.size() != range_end_v.size()) {
35  std::cerr << "OpHit veto range start and end config value array have different length!" << std::endl;
36  throw std::exception();
37  }
38  for(size_t i=0; i<range_start_v.size(); ++i) {
39  if(range_start_v[i] >= range_end_v[i]) {
40  std::cerr << "OpHit veto range element " << i
41  << " have start time @ " << range_start_v[i]
42  << " being later than end time @ " << range_end_v[i]
43  << std::endl;
44  throw std::exception();
45  }
46  _flash_veto_range_m.emplace(range_end_v[i],range_start_v[i]);
47  }
48 
49  _index_to_opch_v.clear();
50  _index_to_opch_v = p.get<std::vector<int> >("OpChannel",_index_to_opch_v);
51  if(_index_to_opch_v.empty()) {
52  int cryostat = p.get<int>("Cryostat",-1);
53  if(cryostat>=0) {
54  auto const opch_v = ListOpChannels(cryostat);
55  _index_to_opch_v.reserve(opch_v.size());
56  for(auto const& v : opch_v) _index_to_opch_v.push_back(v);
57  }else{
58  auto opch_range = p.get<std::vector<int> >("OpChannelRange");
59  if(opch_range.size()!=2) {
60  std::cerr << "OpChannelRange must be a vector of length two!" << std::endl;
61  throw std::exception();
62  }else if(opch_range[0] > opch_range[1]) {
63  std::cerr << "OpChannelRange 0th element (" << opch_range[0]
64  << ") must be larger than the 1st element (" << opch_range[1]
65  << ")" << std::endl;
66  throw std::exception();
67  }
68  _index_to_opch_v.reserve(opch_range[1]-opch_range[0]+1);
69  for(int i=opch_range[0]; i<=opch_range[1]; ++i)
70  _index_to_opch_v.push_back(i);
71  }
72  }
73  size_t valid_id=0;
74  std::set<size_t> duplicate;
75  for(auto const& ch : _index_to_opch_v) {
76  if(ch >= (int)(_opch_to_index_v.size())) _opch_to_index_v.resize(ch+1,-1);
77  if(duplicate.find(ch) != duplicate.end()) {
78  std::cerr << "Channel number " << ch << " is duplicated!" << std::endl;
79  throw std::exception();
80  }
81  _opch_to_index_v[ch] = valid_id;
82  valid_id += 1;
83  duplicate.insert(ch);
84  }
85 
86  if(_opch_to_index_v.empty()) {
87  std::cerr << "Length of OpChannel array parameter is 0..." << std::endl;
88  throw std::exception();
89  }
90  /*
91  if(_pe_baseline_v.size() != duplicate.size()) {
92  std::cout << "PEBaseline array length (" << _pe_baseline_v.size()
93  << ") is not same as OpDet ID count (" << duplicate.size() << ")!" << std::endl;
94  throw std::exception();
95  }
96  */
97  }
98 
99  bool SimpleFlashAlgo::Veto(double t) const
100  {
101  auto iter = _flash_veto_range_m.lower_bound(t);
102  if(iter == _flash_veto_range_m.end()) return false;
103  return (t >= (*iter).second);
104  }
105 
107  {}
108 
110 
111  Reset();
112  size_t max_ch = _opch_to_index_v.size() - 1;
113  size_t NOpDet = _index_to_opch_v.size();
114 
115  //static std::vector<double> pesum_v;
116  static std::vector<double> mult_v; //< this is not strictly a multiplicity of PMTs, but multiplicity of hits
117  static std::vector<std::vector<double> > pespec_v;
118  static std::vector<std::vector<unsigned int> > hitidx_v;
119  double min_time=1.1e20;
120  double max_time=1.1e20;
121  for(auto const& oph : ophits) {
122  if(max_time > 1.e20 || oph.peak_time > max_time) max_time = oph.peak_time;
123  if(min_time > 1.e20 || oph.peak_time < min_time) min_time = oph.peak_time;
124  }
125  min_time -= 10* _time_res;
126  max_time += 10* _time_res;
127  if(_debug)
128  std::cout << "T span: " << min_time << " => " << max_time << " ... " << (size_t)((max_time - min_time) / _time_res) << std::endl;
129 
130  size_t nbins_pesum_v = (size_t)((max_time - min_time) / _time_res) + 1;
131  if(_pesum_v.size() < nbins_pesum_v) _pesum_v.resize(nbins_pesum_v,0);
132  if(mult_v.size() < nbins_pesum_v) mult_v.resize(nbins_pesum_v,0);
133  if(pespec_v.size() < nbins_pesum_v) pespec_v.resize(nbins_pesum_v,std::vector<double>(NOpDet));
134  if(hitidx_v.size() < nbins_pesum_v) hitidx_v.resize(nbins_pesum_v,std::vector<unsigned int>());
135  for(size_t i=0; i<_pesum_v.size(); ++i) {
136  _pesum_v[i] = 0;
137  mult_v[i] = 0;
138  hitidx_v[i].clear();
139  for(auto& v : pespec_v[i]) v=0;
140  }
141 
142  // Fill _pesum_v
143  for(size_t hitidx = 0; hitidx < ophits.size(); ++hitidx) {
144  auto const& oph = ophits[hitidx];
145  if(oph.channel > max_ch || _opch_to_index_v[oph.channel] < 0) {
146  if(_debug) std::cout << "Ignoring OpChannel " << oph.channel << std::endl;
147  continue;
148  }
149  if(Veto(oph.peak_time)) {
150  if(_debug) std::cout << "Ignoring hit @ time " << oph.peak_time << std::endl;
151  continue;
152  }
153  if(oph.pe <= 0.) continue;
154  if(_min_pe_hit > 0. && oph.pe < _min_pe_hit) continue;
155  size_t index = (size_t)((oph.peak_time - min_time) / _time_res);
156  _pesum_v[index] += oph.pe;
157  mult_v[index] += 1;
158  pespec_v[index][_opch_to_index_v[oph.channel]] += oph.pe;
159  hitidx_v[index].push_back(hitidx);
160  }
161 
162  // Order by pe (above threshold)
163  std::map<double,size_t> pesum_idx_map;
164  for(size_t idx=0; idx<nbins_pesum_v; ++idx) {
165  if(_pesum_v[idx] < _min_pe_coinc ) continue;
166  if(mult_v[idx] < _min_mult_coinc ) continue;
167  pesum_idx_map[1./(_pesum_v[idx])] = idx;
168  }
169 
170  // Get candidate flash times
171  std::vector<std::pair<size_t,size_t> > flash_period_v;
172  std::vector<size_t> flash_time_v;
173  size_t veto_ctr = (size_t)(_veto_time / _time_res);
174  size_t default_integral_ctr = (size_t)(_integral_time / _time_res);
175  size_t precount = (size_t)(_pre_sample / _time_res);
176  flash_period_v.reserve(pesum_idx_map.size());
177  flash_time_v.reserve(pesum_idx_map.size());
178 
179  double sum_baseline = 0;
180  //for(auto const& v : _pe_baseline_v) sum_baseline += v;
181 
182  for(auto const& pe_idx : pesum_idx_map) {
183 
184  //auto const& pe = 1./(pe_idx.first);
185  auto const& idx = pe_idx.second;
186 
187  size_t start_time = idx;
188  if(start_time < precount) start_time = 0;
189  else start_time = idx - precount;
190 
191  // see if this idx can be used
192  bool skip=false;
193  size_t integral_ctr = default_integral_ctr;
194  for(auto const& used_period : flash_period_v) {
195  if( start_time <= used_period.first && (start_time + veto_ctr) > used_period.first ) {
196  skip=true;
197  break;
198  }
199  if( used_period.first <= start_time && start_time < (used_period.first + veto_ctr) ) {
200  skip=true;
201  break;
202  }
203  if( used_period.first >= start_time && used_period.first < (start_time + integral_ctr) ) {
204  if(_debug) std::cout << "Truncating flash @ " << start_time
205  << " (previous flash @ " << used_period.first
206  << ") ... integral ctr change: " << integral_ctr
207  << " => " << used_period.first - start_time << std::endl;
208 
209  integral_ctr = used_period.first - start_time;
210  }
211  if(_debug) {
212  std::cout << "Flash @ " << min_time + used_period.first * _time_res
213  << " => " << min_time + (used_period.first + used_period.second) * _time_res
214  << " does not interfare with THIS flash @ " << min_time + start_time * _time_res
215  << " => " << min_time + (start_time + integral_ctr) * _time_res << std::endl;
216  }
217  }
218  if(skip) {
219  if(_debug) std::cout << "Skipping a candidate @ " << min_time + start_time * _time_res << " as it is in a veto window!" <<std::endl;
220  continue;
221  }
222 
223  // See if this flash is declarable
224  double pesum = 0;
225  for(size_t i=start_time; i<std::min(nbins_pesum_v,(start_time+integral_ctr)); ++i)
226 
227  pesum += _pesum_v[i];
228 
229  if(pesum < (_min_pe_flash + sum_baseline)) {
230  if(_debug) std::cout << "Skipping a candidate @ " << start_time << " => " << start_time + integral_ctr
231  << " as it got " << pesum
232  << " PE which is lower than threshold " << (_min_pe_flash + sum_baseline) << std::endl;
233  continue;
234  }
235 
236  flash_period_v.push_back(std::pair<size_t,size_t>(start_time,integral_ctr));
237  flash_time_v.push_back(idx);
238  }
239 
240  // Construct flash
241  LiteOpFlashArray_t res;
242  for(size_t flash_idx=0; flash_idx<flash_period_v.size(); ++flash_idx) {
243 
244  auto const& start = flash_period_v[flash_idx].first;
245  auto const& period = flash_period_v[flash_idx].second;
246  auto const& time = flash_time_v[flash_idx];
247 
248  std::vector<double> pe_v(max_ch+1,0);
249  for(size_t index=start; index<(start+period) && index<pespec_v.size(); ++index) {
250 
251  for(size_t pmt_index=0; pmt_index<NOpDet; ++pmt_index)
252 
253  pe_v[_index_to_opch_v[pmt_index]] += pespec_v[index][pmt_index];
254 
255  }
256 
257  for(size_t opch=0; opch<max_ch; ++opch) {
258 
259  if(_opch_to_index_v[opch]<0) continue;
260 
261  //pe_v[opch] -= _pe_baseline_v[_opch_to_index_v[opch]];
262 
263  if(pe_v[opch]<0) pe_v[opch]=0;
264 
265  }
266 
267  std::vector<unsigned int> asshit_v;
268  for(size_t index=start; index<(start+period) && index<pespec_v.size(); ++index) {
269  for(auto const& idx : hitidx_v[index])
270  asshit_v.push_back(idx);
271  }
272 
273  if(_debug) {
274  std::cout << "Claiming a flash @ " << min_time + time * _time_res
275  << " : " << std::flush;
276  double tmpsum=0;
277  for(auto const& v : pe_v) { std::cout << v << " "; tmpsum +=v; }
278  std::cout << " ... sum = " << tmpsum << std::endl;
279  }
280 
281  LiteOpFlash_t flash( min_time + time * _time_res,
282  period * _time_res / 2.,
283  std::move(pe_v),
284  std::move(asshit_v));
285  res.emplace_back( std::move(flash) );
286 
287  }
288  if(_debug) std::cout << std::endl;
289  return res;
290  }
291 
292 }
293 #endif
294 
std::vector< pmtana::LiteOpHit_t > LiteOpHitArray_t
A concrete factory class for pmtana::SimpleFlashAlgo.
BEGIN_PROLOG could also be cerr
pdgs p
Definition: selectors.fcl:22
LiteOpFlashArray_t RecoFlash(const LiteOpHitArray_t ophits)
static SimpleFlashAlgoFactory __SimpleFlashAlgoFactoryStaticObject__
std::vector< pmtana::LiteOpFlash_t > LiteOpFlashArray_t
then echo fcl sbnd_project sbnd_project sbnd_project sbnd_project production production start_time
then echo fcl name
BEGIN_PROLOG could also be cout