OpFlashFinderDualPhase_module.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 2; -*-
2 //
3 // This module groups OpHits into OpFlashes,
4 // based in the time and space distribution
5 // of the OpHits.
6 // by José Soto, CIEMAT (2019)
7 //
8 
9 
10 #ifndef OpFlashFinderDualPhase_H
11 #define OpFlashFinderDualPhase_H 1
12 
13 // LArSoft includes
19 
20 // Framework includes
24 #include "fhiclcpp/ParameterSet.h"
29 
30 // ROOT includes
31 
32 // C++ Includes
33 #include <vector>
34 #include <string>
35 #include <memory>
36 
37 namespace opdet {
38 
40  public:
41 
42  // Standard constructor and destructor for an ART module.
44  virtual ~OpFlashFinderDualPhase();
45 
46  void beginJob();
47  void endJob();
48  void reconfigure(fhicl::ParameterSet const& pset);
49 
50  // The producer routine, called once per event.
51  void produce(art::Event&);
52 
53 
54  void RunFlashFinder(std::vector< recob::OpHit > const& HitVector,
55  std::vector< recob::OpFlash >& FlashVector,
56  std::vector< std::vector< int > >& AssocList,
57  geo::GeometryCore const& geom,
59  float const& TrigCoinc);
60  void AddHitContribution(recob::OpHit const& currentHit,
61  double& MaxTime,
62  double& MinTime,
63  double& AveTime,
64  double& FastToTotal,
65  double& AveAbsTime,
66  double& TotalPE,
67  std::vector< double >& PEs);
68  void GetHitGeometryInfo(recob::OpHit const& currentHit,
69  geo::GeometryCore const& geom,
70  std::vector< double >& sumw,
71  std::vector< double >& sumw2,
72  double& sumy,
73  double& sumy2,
74  double& sumz,
75  double& sumz2);
76  double CalculateWidth(double const& sum,
77  double const& sum_squared,
78  double const& weights_sum);
79  std::vector<int> getNeighbors( std::vector< recob::OpHit > const& HitVector,
80  int hitnumber,
81  std::vector<bool> &processed, float initimecluster, std::vector<int> &sorted,geo::GeometryCore const& geom);
82  void AssignHitsToFlash( std::vector< recob::OpHit > const& HitVector,
83  std::vector< std::vector< int > >& HitsPerFlash,geo::GeometryCore const& geom);
84  void ConstructFlash(std::vector< int > const& HitsPerFlashVec,
85  std::vector< recob::OpHit > const& HitVector,
86  std::vector< recob::OpFlash >& FlashVector,
87  geo::GeometryCore const& geom,
89  float const& TrigCoinc);
90  private:
91 
92  // The parameters we'll read from the .fcl file.
93  std::string fInputModule; // Input tag for OpHit collection
94 
95 
96  Double_t fMaximumDistance;
99  Double_t fTrigCoinc;
100 
101  };
102 
103 }
104 
105 namespace opdet {
107 }
108 
109 #endif
110 
111 namespace opdet {
112 
113  //----------------------------------------------------------------------------
114  // Constructor
116  : EDProducer{pset}
117  {
118 
119  reconfigure(pset);
120 
121  produces< std::vector< recob::OpFlash > >();
122  produces< art::Assns< recob::OpFlash, recob::OpHit > >();
123 
124  }
125 
126  //----------------------------------------------------------------------------
128  {
129 
130  // Indicate that the Input Module comes from .fcl
131  fInputModule = pset.get< std::string >("InputModule");
132 
133  fTrigCoinc = pset.get< double >("TrigCoinc");
134  fMaximumDistance = pset.get< double >("MaximumDistance");
135  fMaximumTimeDistance = pset.get< double >("MaximumTimeDistance");
136  fMaximumTimeWindow = pset.get< double >("MaximumTimeWindow");
137 
138  }
139 
140  //----------------------------------------------------------------------------
141  // Destructor
143  {
144  }
145 
146  //----------------------------------------------------------------------------
148  {
149  }
150 
151  //----------------------------------------------------------------------------
153  {
154  }
155 
156  //----------------------------------------------------------------------------
158  {
159 
160  // These are the storage pointers we will put in the event
161  std::unique_ptr< std::vector< recob::OpFlash > >
162  flashPtr(new std::vector< recob::OpFlash >);
163  std::unique_ptr< art::Assns< recob::OpFlash, recob::OpHit > >
165 
166  // This will keep track of what flashes will assoc to what ophits
167  // at the end of processing
168  std::vector< std::vector< int > > assocList;
169 
170  auto const& geometry(*lar::providerFrom< geo::Geometry >());
171 
172  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
173 
174  // Get OpHits from the event
175  auto opHitHandle = evt.getHandle< std::vector< recob::OpHit > >(fInputModule);
176 
177  RunFlashFinder(*opHitHandle,
178  *flashPtr,
179  assocList,
180  geometry,
181  clockData,
182  fTrigCoinc);
183 
184 
185 
186 
187  // Make the associations which we noted we need
188  for (size_t i = 0; i != assocList.size(); ++i)
189  {
190  art::PtrVector< recob::OpHit > opHitPtrVector;
191  for (int const& hitIndex : assocList.at(i))
192  {
193  art::Ptr< recob::OpHit > opHitPtr(opHitHandle, hitIndex);
194  opHitPtrVector.push_back(opHitPtr);
195  }
196 
197  util::CreateAssn(*this, evt, *flashPtr, opHitPtrVector,
198  *(assnPtr.get()), i);
199  }
200 
201  // Store results into the event
202  evt.put(std::move(flashPtr));
203  evt.put(std::move(assnPtr));
204 
205  }
206 
207  void OpFlashFinderDualPhase::RunFlashFinder(std::vector< recob::OpHit > const& HitVector,
208  std::vector< recob::OpFlash >& FlashVector,
209  std::vector< std::vector< int > >& AssocList,
210  geo::GeometryCore const& geom,
211  detinfo::DetectorClocksData const& ts,
212  float const& TrigCoinc) {
213 
214  // Now start to create flashes.
215  // First, need vector to keep track of which hits belong to which flashes
216  std::vector< std::vector< int > > HitsPerFlash;
217 
218  AssignHitsToFlash(HitVector,
219  HitsPerFlash,
220  geom);
221 
222  // Now we have all our hits assigned to a flash.
223  // Make the recob::OpFlash objects
224  for (auto const& HitsPerFlashVec : HitsPerFlash)
225  ConstructFlash(HitsPerFlashVec,
226  HitVector,
227  FlashVector,
228  geom,
229  ts,
230  TrigCoinc);
231 
232  // Finally, write the association list.
233  // back_inserter tacks the result onto the end of AssocList
234  for (auto& HitIndicesThisFlash : HitsPerFlash)
235  AssocList.push_back(HitIndicesThisFlash);
236 
237  } // End RunFlashFinder
238 
239  //----------------------------------------------------------------------------
240  void OpFlashFinderDualPhase::ConstructFlash(std::vector< int > const& HitsPerFlashVec,
241  std::vector< recob::OpHit > const& HitVector,
242  std::vector< recob::OpFlash >& FlashVector,
243  geo::GeometryCore const& geom,
244  detinfo::DetectorClocksData const& ts,
245  float const& TrigCoinc) {
246 
247  double MaxTime = -1e9;
248  double MinTime = 1e9;
249 
250  std::vector< double > PEs(geom.MaxOpChannel() + 1, 0.0);
251  unsigned int Nplanes = geom.Nplanes();
252  std::vector< double > sumw (Nplanes, 0.0);
253  std::vector< double > sumw2(Nplanes, 0.0);
254 
255  double TotalPE = 0;
256  double AveTime = 0;
257  double AveAbsTime = 0;
258  double FastToTotal = 0;
259  double sumy = 0;
260  double sumz = 0;
261  double sumy2 = 0;
262  double sumz2 = 0;
263 
264  for (auto const& HitID : HitsPerFlashVec) {
265  AddHitContribution(HitVector.at(HitID),
266  MaxTime,
267  MinTime,
268  AveTime,
269  FastToTotal,
270  AveAbsTime,
271  TotalPE,
272  PEs);
273  GetHitGeometryInfo(HitVector.at(HitID),
274  geom,
275  sumw,
276  sumw2,
277  sumy,
278  sumy2,
279  sumz,
280  sumz2);
281  }
282 
283  AveTime /= TotalPE;
284  AveAbsTime /= TotalPE;
285  FastToTotal /= TotalPE;
286 
287  double meany = sumy/TotalPE;
288  double meanz = sumz/TotalPE;
289 
290  double widthy = CalculateWidth(sumy, sumy2, TotalPE);
291  double widthz = CalculateWidth(sumz, sumz2, TotalPE);
292 
293  std::vector< double > WireCenters(Nplanes, 0.0);
294  std::vector< double > WireWidths(Nplanes, 0.0);
295 
296  for (size_t p = 0; p != Nplanes; ++p) {
297  WireCenters.at(p) = sumw.at(p)/TotalPE;
298  WireWidths.at(p) = CalculateWidth(sumw.at(p), sumw2.at(p), TotalPE);
299  }
300 
301  // Emprical corrections to get the Frame right.
302  // Eventual solution - remove frames
303  int Frame = ts.OpticalClock().Frame(AveAbsTime - 18.1);
304  if (Frame == 0) Frame = 1;
305 
306  int BeamFrame = ts.OpticalClock().Frame(ts.TriggerTime());
307  bool InBeamFrame = false;
308  if (!(ts.TriggerTime() < 0)) InBeamFrame = (Frame == BeamFrame);
309 
310  double TimeWidth = (MaxTime - MinTime)/2.0;
311 
312  int OnBeamTime = 0;
313  if (InBeamFrame && (std::abs(AveTime) < TrigCoinc)) OnBeamTime = 1;
314 
315  FlashVector.emplace_back(AveTime,
316  TimeWidth,
317  AveAbsTime,
318  Frame,
319  PEs,
320  InBeamFrame,
321  OnBeamTime,
322  FastToTotal,
323  meany,
324  widthy,
325  meanz,
326  widthz,
327  WireCenters,
328  WireWidths);
329 
330  }
332  double& MaxTime,
333  double& MinTime,
334  double& AveTime,
335  double& FastToTotal,
336  double& AveAbsTime,
337  double& TotalPE,
338  std::vector< double >& PEs) {
339 
340  double PEThisHit = currentHit.PE();
341  double TimeThisHit = currentHit.PeakTime();
342  if (TimeThisHit > MaxTime) MaxTime = TimeThisHit;
343  if (TimeThisHit < MinTime) MinTime = TimeThisHit;
344 
345  // These quantities for the flash are defined
346  // as the weighted averages over the hits
347  AveTime += PEThisHit*TimeThisHit;
348  FastToTotal += PEThisHit*currentHit.FastToTotal();
349  AveAbsTime += PEThisHit*currentHit.PeakTimeAbs();
350 
351  // These are totals
352  TotalPE += PEThisHit;
353  PEs.at(static_cast< unsigned int >(currentHit.OpChannel())) += PEThisHit;
354 
355  }
356 
357  //----------------------------------------------------------------------------
359  geo::GeometryCore const& geom,
360  std::vector< double >& sumw,
361  std::vector< double >& sumw2,
362  double& sumy,
363  double& sumy2,
364  double& sumz,
365  double& sumz2) {
366 
367  double xyz[3];
368  geom.OpDetGeoFromOpChannel(currentHit.OpChannel()).GetCenter(xyz);
369  double PEThisHit = currentHit.PE();
370 
371  geo::TPCID tpc = geom.FindTPCAtPosition(xyz);
372  // if the point does not fall into any TPC,
373  // it does not contribute to the average wire position
374  if (tpc.isValid) {
375  for (size_t p = 0; p != geom.Nplanes(); ++p) {
376  geo::PlaneID const planeID(tpc, p);
377  unsigned int w = geom.NearestWire(xyz, planeID);
378  sumw.at(p) += PEThisHit*w;
379  sumw2.at(p) += PEThisHit*w*w;
380  }
381  } // if we found the TPC
382  sumy += PEThisHit*xyz[1];
383  sumy2 += PEThisHit*xyz[1]*xyz[1];
384  sumz += PEThisHit*xyz[2];
385  sumz2 += PEThisHit*xyz[2]*xyz[2];
386 
387  }
388 
389  //----------------------------------------------------------------------------
390  double OpFlashFinderDualPhase::CalculateWidth(double const& sum,
391  double const& sum_squared,
392  double const& weights_sum) {
393 
394  if (sum_squared*weights_sum - sum*sum < 0) return 0;
395  else return std::sqrt(sum_squared*weights_sum - sum*sum)/weights_sum;
396 
397  }
398 
399 
400  std::vector<int> OpFlashFinderDualPhase::getNeighbors( std::vector< recob::OpHit > const& HitVector,int hitnumber, std::vector<bool> &processed, float initimecluster, std::vector<int> &sorted,geo::GeometryCore const& geom)
401  {
402 
403  int itTmin=0;
404  int itTmax=HitVector.size();
405  for (int h=hitnumber;h>0;h--) if(HitVector[sorted[h]].PeakTime() < HitVector[sorted[hitnumber]].PeakTime()-fMaximumTimeDistance)
406  {
407  itTmin=h; break;
408  }
409  for (unsigned int h=hitnumber;h<HitVector.size();h++) if(HitVector[sorted[h]].PeakTime() > HitVector[sorted[hitnumber]].PeakTime()+fMaximumTimeDistance)
410  {
411  itTmax=h; break;
412  }
413 
414  std::vector<int> neighbors;
415  float dx, dy, dz, dt, dtmax;
416  double xyz_hitnumber[3];
417  geom.OpDetGeoFromOpChannel(HitVector[sorted[hitnumber]].OpChannel()).GetCenter(xyz_hitnumber);
418 
419  for (int h=itTmin;h<itTmax;h++)
420  {
421  if(!processed[h])
422  {
423  double xyz_h[3];
424  geom.OpDetGeoFromOpChannel(HitVector[sorted[h]].OpChannel()).GetCenter(xyz_h);
425  dx = xyz_h[0] - xyz_hitnumber[0];
426  dy = xyz_h[1] - xyz_hitnumber[1];
427  dz = xyz_h[2] - xyz_hitnumber[2];
428  dt = TMath::Abs( HitVector[sorted[hitnumber]].PeakTime() - HitVector[sorted[h]].PeakTime() );
429  dtmax = TMath::Abs(initimecluster - HitVector[sorted[h]].PeakTime() );
430  float distance = dx*dx + dy*dy + dz*dz;
431 // std::cout << distance << " " << dt << " " << dtmax << std::endl; lets_pause();
432  if(distance<fMaximumDistance*fMaximumDistance && dt<fMaximumTimeDistance && dtmax<fMaximumTimeWindow){ neighbors.push_back(h);processed[h]=true;}
433  }
434  }
435  return neighbors;
436  }
437 // AssignHitsToFlash(HitVector, HitsPerFlash, MaximumDistance, MaximumTimeDistance, MaximumTimeWindow);
438  void OpFlashFinderDualPhase::AssignHitsToFlash( std::vector< recob::OpHit > const& HitVector,
439  std::vector< std::vector< int > >& HitsPerFlash,
440  geo::GeometryCore const& geom)
441  {
442 
443  int ntothits=HitVector.size();
444  std::size_t n(0);
445  std::vector<int> sorted;
446  sorted.resize(ntothits);
447  std::generate(std::begin(sorted), std::end(sorted), [&]{ return n++; });
448  std::sort( std::begin(sorted), std::end(sorted), [&](int i1, int i2) { return HitVector[i1].PeakTime() < HitVector[i2].PeakTime(); });
449 
450  HitsPerFlash.clear();
451 
452  std::vector<bool> processed;
453  processed.resize(HitVector.size(),false);
454 
455  for (unsigned int h=0;h<HitVector.size();h++)
456  {
457  if(!processed[h])
458  {
459  processed[h]=true;
460  std::vector<int> N; N.clear();
461  std::vector<int> nb =getNeighbors(HitVector,h, processed, HitVector[sorted[h]].PeakTime(),sorted,geom);
462  N.insert( N.end(), nb.begin(), nb.end() );
463 
464  for (unsigned int i=0;i<N.size();i++)
465  {
466  std::vector<int> nb2 =getNeighbors(HitVector,N[i], processed, HitVector[sorted[h]].PeakTime(),sorted,geom);
467  N.insert( N.end(), nb2.begin(), nb2.end() );
468  }
469  N.push_back(sorted[h]);
470  HitsPerFlash.push_back(N);
471  }
472  }
473 
474  } // End AssignHitsToFlash
475 
476  //----------------------------------------------------------------------------
477 
478 } // namespace opdet
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
double FastToTotal() const
Definition: OpHit.h:70
Index OpChannel(Index detNum, Index channel)
static constexpr double nb
Definition: Units.h:81
void GetHitGeometryInfo(recob::OpHit const &currentHit, geo::GeometryCore const &geom, std::vector< double > &sumw, std::vector< double > &sumw2, double &sumy, double &sumy2, double &sumz, double &sumz2)
double CalculateWidth(double const &sum, double const &sum_squared, double const &weights_sum)
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
OpFlashFinderDualPhase(const fhicl::ParameterSet &)
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
struct vector vector
double PeakTime() const
Definition: OpHit.h:64
void GetCenter(double *xyz, double localz=0.0) const
Definition: OpDetGeo.cxx:40
constexpr int Frame() const noexcept
Returns the number of the frame containing the clock current time.
Definition: ElecClock.h:304
std::vector< int > getNeighbors(std::vector< recob::OpHit > const &HitVector, int hitnumber, std::vector< bool > &processed, float initimecluster, std::vector< int > &sorted, geo::GeometryCore const &geom)
art framework interface to geometry description
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
T abs(T value)
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
void RunFlashFinder(std::vector< recob::OpHit > const &HitVector, std::vector< recob::OpFlash > &FlashVector, std::vector< std::vector< int > > &AssocList, geo::GeometryCore const &geom, detinfo::DetectorClocksData const &ts, float const &TrigCoinc)
std::void_t< T > n
def move(depos, offset)
Definition: depos.py:107
T get(std::string const &key) const
Definition: ParameterSet.h:271
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
p
Definition: test.py:223
ElecClock const & OpticalClock() const noexcept
Borrow a const Optical clock with time set to Trigger time [us].
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
unsigned int MaxOpChannel() const
Largest optical channel number.
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Description of geometry of one entire detector.
double TriggerTime() const
Trigger electronics clock time in [us].
double PE() const
Definition: OpHit.h:69
std::vector< reco::ClusterHit2D * > HitVector
What follows are several highly useful typedefs which we want to expose to the outside world...
void AssignHitsToFlash(std::vector< recob::OpHit > const &HitVector, std::vector< std::vector< int > > &HitsPerFlash, geo::GeometryCore const &geom)
Contains all timing reference information for the detector.
void reconfigure(fhicl::ParameterSet const &pset)
double PeakTimeAbs() const
Definition: OpHit.h:65
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
TCEvent evt
Definition: DataStructs.cxx:7
void AddHitContribution(recob::OpHit const &currentHit, double &MaxTime, double &MinTime, double &AveTime, double &FastToTotal, double &AveAbsTime, double &TotalPE, std::vector< double > &PEs)
OpDetGeo const & OpDetGeoFromOpChannel(unsigned int OpChannel) const
Returns the geo::OpDetGeo object for the given channel number.
int OpChannel() const
Definition: OpHit.h:62
void ConstructFlash(std::vector< int > const &HitsPerFlashVec, std::vector< recob::OpHit > const &HitVector, std::vector< recob::OpFlash > &FlashVector, geo::GeometryCore const &geom, detinfo::DetectorClocksData const &ts, float const &TrigCoinc)