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