DisambigAlg.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // DisambigAlg.cxx
4 //
5 // tylerdalion@gmail.com
6 //
7 // description
8 //
9 //
10 // Since we are letting the module make the final column of hits, a disambiguated
11 // hit in this algorithm is a pair< art::Ptr<recob::Hit>, geo::WireID >
12 //
13 //
14 ////////////////////////////////////////////////////////////////////////
15 
16 //Framework includes:
18 #include "fhiclcpp/ParameterSet.h"
20 
27 
28 #include <cmath>
29 #include <cstdlib>
30 #include <map>
31 
32 #include "range/v3/view.hpp"
33 
34 using lar::to_element;
36 using ranges::views::transform;
37 
38 namespace apa {
39 
41  : fAPAGeo(p.get<fhicl::ParameterSet>("APAGeometryAlg"))
42  {
43  fCrawl = p.get<bool>("Crawl");
44  fUseEndP = p.get<bool>("UseEndP");
45  fCompareViews = p.get<bool>("CompareViews");
46  fCloseHitsRadius = p.get<double>("CloseHitsRadius");
47  fMaxEndPDegRange = p.get<double>("MaxEndPDegRange");
48  fNChanJumps = p.get<unsigned int>("NChanJumps");
49  }
50 
51  //----------------------------------------------------------
52  //----------------------------------------------------------
53  void
55  detinfo::DetectorPropertiesData const& detProp,
56  art::Handle<std::vector<recob::Hit>> ChannelHits)
57  {
58  fUeffSoFar.clear();
59  fVeffSoFar.clear();
60  fnUSoFar.clear();
61  fnVSoFar.clear();
62  fnDUSoFar.clear();
63  fnDVSoFar.clear();
64  fChannelToHits.clear();
65  fAPAToUVHits.clear();
66  fAPAToZHits.clear();
67  fAPAToHits.clear();
68  fAPAToEndPHits.clear();
69  fAPAToDHits.clear();
70  fDisambigHits.clear();
71  fChanTimeToWid.clear();
72  fHasBeenDisambiged.clear();
73 
74  std::vector<art::Ptr<recob::Hit>> ChHits;
75  art::fill_ptr_vector(ChHits, ChannelHits);
76 
77  fHasBeenDisambiged.clear();
78  unsigned int skipNoise(0);
79  // Map hits by channel/APA, initialize the disambiguation status map
80  for (size_t h = 0; h < ChHits.size(); h++) {
81  art::Ptr<recob::Hit> const& hit = ChHits[h];
82 
83  // **temporary** option to skip noise hits
84  try {
85  bt_serv->HitToXYZ(clockData, hit);
86  }
87  catch (...) {
88  skipNoise++;
89  continue;
90  }
91 
92  geo::View_t view = hit->View();
93  unsigned int apa(0), cryo(0);
94  fAPAGeo.ChannelToAPA(hit->Channel(), apa, cryo);
95  fAPAToHits[apa].push_back(hit);
96  if (view == geo::kZ) {
97  fAPAToZHits[apa].push_back(hit);
98  continue;
99  }
100  else if (view == geo::kU || view == geo::kV) {
101  std::pair<double, double> ChanTime(hit->Channel() * 1., hit->PeakTime() * 1.);
102  this->fHasBeenDisambiged[apa][ChanTime] = false;
103  fChannelToHits[hit->Channel()].push_back(hit);
104  fAPAToUVHits[apa].push_back(hit);
105  }
106  }
107 
108  if (skipNoise > 0)
109  mf::LogWarning("DisambigAlg")
110  << "\nSkipped " << skipNoise << " induction noise hits using the BackTrackerService.\n"
111  << "This is only to temporarily deal with the excessive amount of noise due to the bad "
112  "deconvolution.\n";
113 
114  mf::LogVerbatim("RunDisambig") << "\n~~~~~~~~~~~ Running Disambiguation ~~~~~~~~~~~\n";
115 
116  std::map<unsigned int, std::vector<art::Ptr<recob::Hit>>>::iterator APA_it;
117  for (APA_it = fAPAToUVHits.begin(); APA_it != fAPAToUVHits.end(); APA_it++) {
118  unsigned int apa = APA_it->first;
119 
120  mf::LogVerbatim("RunDisambig") << "APA " << apa << ":";
121 
122  fUeffSoFar[apa] = 0.;
123  fVeffSoFar[apa] = 0.;
124  fnUSoFar[apa] = 0;
125  fnVSoFar[apa] = 0;
126  fnDUSoFar[apa] = 0;
127  fnDVSoFar[apa] = 0;
128 
129  // Always run this...
130  this->TrivialDisambig(clockData, detProp, apa);
131  this->AssessDisambigSoFar(apa);
132  mf::LogVerbatim("RunDisambig")
133  << " Trivial Disambig --> " << fnDUSoFar[apa] << " / " << fnUSoFar[apa] << " U, "
134  << fnDVSoFar[apa] << " / " << fnVSoFar[apa] << " V";
135 
136  // ... and pick the rest with the configurations.
137  if (fCrawl) {
138  this->Crawl(apa);
139  this->AssessDisambigSoFar(apa);
140  mf::LogVerbatim("RunDisambig")
141  << " Crawl --> " << fnDUSoFar[apa] << " / " << fnUSoFar[apa] << " U, "
142  << fnDVSoFar[apa] << " / " << fnVSoFar[apa] << " V";
143  }
144 
145  if (fUseEndP) {
146  this->FindChanTimeEndPts(detProp, apa);
147  this->UseEndPts(detProp, apa); // does the crawl from inside
148  this->AssessDisambigSoFar(apa);
149  mf::LogVerbatim("RunDisambig")
150  << " Endpoint Crawl --> " << fnDUSoFar[apa] << " / " << fnUSoFar[apa] << " U, "
151  << fnDVSoFar[apa] << " / " << fnVSoFar[apa] << " V";
152  }
153 
154  if (fCompareViews) {
155  unsigned int nDisambig(1);
156  while (nDisambig > 0) {
157  nDisambig = this->CompareViews(detProp, apa);
158  this->Crawl(apa);
159  }
160  this->AssessDisambigSoFar(apa);
161  mf::LogVerbatim("RunDisambig")
162  << " Compare Views --> " << fnDUSoFar[apa] << " / " << fnUSoFar[apa] << " U, "
163  << fnDVSoFar[apa] << " / " << fnVSoFar[apa] << " V";
164  }
165 
166  // For now just buld a simple list to get from the module
167  for (size_t i = 0; i < fAPAToDHits[apa].size(); i++)
168  fDisambigHits.push_back(fAPAToDHits[apa][i]);
169 
170  } // end loop through APA
171  }
172 
173  //-------------------------------------------------
174  //-------------------------------------------------
175  void
177  {
178  std::pair<double, double> ChanTime(hit->Channel() * 1., hit->PeakTime() * 1.);
179  if (fHasBeenDisambiged[apa][ChanTime]) return;
180 
181  if (!wid.isValid) {
182  mf::LogWarning("InvalidWireID") << "wid is invalid, hit not being made\n";
183  return;
184  }
185 
186  fAPAToDHits[apa].emplace_back(hit, wid);
187  fHasBeenDisambiged[apa][ChanTime] = true;
188  fChanTimeToWid[ChanTime] = wid;
189  }
190 
191  //----------------------------------------------------------
192  //----------------------------------------------------------
193  bool
195  recob::Hit const& hitA,
196  recob::Hit const& hitB)
197  {
198  double AsT = hitA.PeakTimeMinusRMS();
199  double AeT = hitA.PeakTimePlusRMS();
200  double BsT = hitB.PeakTimeMinusRMS();
201  double BeT = hitB.PeakTimePlusRMS();
202 
203  if (hitA.View() == geo::kU) {
204  AsT -= detProp.TimeOffsetU();
205  AeT -= detProp.TimeOffsetU();
206  }
207  else if (hitA.View() == geo::kV) {
208  AsT -= detProp.TimeOffsetV();
209  AeT -= detProp.TimeOffsetV();
210  }
211  else if (hitA.View() == geo::kZ) {
212  AsT -= detProp.TimeOffsetZ();
213  AeT -= detProp.TimeOffsetZ();
214  }
215 
216  if (hitB.View() == geo::kU) {
217  BsT += detProp.TimeOffsetU();
218  BeT -= detProp.TimeOffsetU();
219  }
220  else if (hitB.View() == geo::kV) {
221  BsT -= detProp.TimeOffsetV();
222  BeT -= detProp.TimeOffsetV();
223  }
224  else if (hitA.View() == geo::kZ) { // FIXME: Shouldn't this be hitB, BsT, and BeT?
225  AsT -= detProp.TimeOffsetZ();
226  AeT -= detProp.TimeOffsetZ();
227  }
228 
229  return (AsT <= BsT && BsT <= AeT) || (AsT <= BeT && BeT <= AeT) || (BsT <= AsT && AsT <= BeT) ||
230  (BsT <= AeT && AeT <= BeT);
231  }
232 
233  //----------------------------------------------------------
234  //----------------------------------------------------------
235  void
237  detinfo::DetectorPropertiesData const& detProp,
238  unsigned int apa)
239  {
240  // Loop through ambiguous hits (U/V) in this APA
241  for (auto const& hitPtr : fAPAToUVHits[apa]) {
242  auto const& hit = *hitPtr;
243  raw::ChannelID_t chan = hit.Channel();
244  unsigned int peakT = hit.PeakTime();
245 
246  std::vector<geo::WireID> hitwids = geom->ChannelToWire(chan);
247  std::vector<bool> IsReasonableWid(hitwids.size(), false);
248  unsigned short nPossibleWids(0);
249  for (size_t w = 0; w < hitwids.size(); w++) {
250  geo::WireID wid = hitwids[w];
251 
252  double xyzStart[3] = {0.};
253  double xyzEnd[3] = {0.};
254  geom->WireEndPoints(wid.Cryostat, wid.TPC, wid.Plane, wid.Wire, xyzStart, xyzEnd);
255  unsigned int side(wid.TPC % 2), cryo(wid.Cryostat);
256  double zminPos(xyzStart[2]), zmaxPos(xyzEnd[2]);
257 
258  // get appropriate x and y with tpc center
259  TVector3 tpcCenter(0, 0, 0);
260  unsigned int tpc =
261  2 * apa + side - cryo * geom->NTPC(); // apa number does not reset per cryo
262  tpcCenter = geom->Cryostat(cryo).TPC(tpc).LocalToWorld(tpcCenter);
263 
264  // get channel range
265  TVector3 Min(tpcCenter);
266  Min[2] = zminPos;
267  TVector3 Max(tpcCenter);
268  Max[2] = zmaxPos;
269  raw::ChannelID_t ZminChan = geom->NearestChannel(Min, 2, tpc, cryo);
270  raw::ChannelID_t ZmaxChan = geom->NearestChannel(Max, 2, tpc, cryo);
271 
272  for (auto const& zhit : fAPAToZHits[apa] | transform(to_element)) {
273  raw::ChannelID_t chan = zhit.Channel();
274  if (chan <= ZminChan || ZmaxChan <= chan) continue;
275 
276  if (this->HitsOverlapInTime(detProp, hit, zhit)) {
277  IsReasonableWid[w] = true;
278  nPossibleWids++;
279  break;
280  }
281  }
282 
283  } // end hit chan-wid loop
284 
285  if (nPossibleWids == 0) {
286  std::vector<double> xyz;
287  try {
288  xyz = bt_serv->HitToXYZ(clockData, hit);
289  } // TEMPORARY
290  catch (...) {
291  continue;
292  }
293  ///\ todo: Figure out why sometimes non-noise hits dont match any Z hits at all.
294  mf::LogWarning("UniqueTimeSeg")
295  << "U/V hit inconsistent with Z info; peak time is " << peakT << " in APA " << apa
296  << " on channel " << hit.Channel();
297  }
298  else if (nPossibleWids == 1) {
299  for (size_t d = 0; d < hitwids.size(); d++)
300  if (IsReasonableWid[d]) this->MakeDisambigHit(hitPtr, hitwids[d], apa);
301  }
302  else if (nPossibleWids == 2) {
303  ///\ todo: Add mechanism to at least eliminate the wids that aren't even possible, for the benefit of future methods
304  }
305 
306  } // end ambig hits loop
307  }
308 
309  //----------------------------------------------------------
310  //----------------------------------------------------------
311  unsigned int
312  DisambigAlg::MakeCloseHits(int ext, geo::WireID Dwid, double Dmin, double Dmax)
313  {
314  // Function to look, on a channel *ext* channels away from a
315  // disambiguated hit channel, for hits with time windows touching
316  // range *Dmin to Dmax*. If found, make such a hit to have a
317  // wireID adjacent to supplied *wid*. Returns number of NEW hits
318  // made.
319 
320  raw::ChannelID_t Dchan =
321  geom->PlaneWireToChannel(Dwid.Plane, Dwid.Wire, Dwid.TPC, Dwid.Cryostat);
322  geo::View_t view = geom->View(Dchan);
323  if (view == geo::kZ)
324  throw cet::exception("MakeCloseHits") << "Function not meant for non-wrapped channels.\n";
325 
326  // Account for wrapping
327  raw::ChannelID_t firstChan = fAPAGeo.FirstChannelInView(view, Dchan);
328  unsigned int ChanPerView = fAPAGeo.ChannelsInView(view);
329  int tempchan = Dchan + ext; // need sign for the set of channels starting with channel 0
330  if (tempchan < (int)firstChan) tempchan += ChanPerView;
331  if (tempchan > (int)(firstChan + ChanPerView - 1)) tempchan -= ChanPerView;
332  raw::ChannelID_t chan = (raw::ChannelID_t)(tempchan);
333 
334  // There may just be no hits
335  if (fChannelToHits.count(chan) == 0) return 0;
336 
337  // There are close channel hits, so for each
338  unsigned int apa(0), cryo(0);
339  fAPAGeo.ChannelToAPA(chan, apa, cryo);
340  unsigned int MakeCount(0);
341  for (size_t i = 0; i < fChannelToHits[chan].size(); i++) {
342  art::Ptr<recob::Hit> closeHit = fChannelToHits[chan][i];
343  double st = closeHit->PeakTimeMinusRMS();
344  double et = closeHit->PeakTimePlusRMS();
345  std::vector<geo::WireID> wids = geom->ChannelToWire(chan);
346 
347  if (!(Dmin <= st && st <= Dmax) && !(Dmin <= et && et <= Dmax)) continue;
348 
349  // Found hit with window overlapping given range,
350  // now find the only reasonable wireID.
351  for (size_t w = 0; w < wids.size(); w++) {
352  if (wids[w].TPC != Dwid.TPC) continue;
353  if ((int)(wids[w].Wire) - (int)(Dwid.Wire) != ext) continue;
354 
355  // In this case, we have a unique wireID.
356  // Check to see if it has already been made - if so, do not incriment count
357  std::pair<double, double> ChanTime(closeHit->Channel() * 1., closeHit->PeakTime() * 1.);
358  if (!fHasBeenDisambiged[apa][ChanTime]) {
359  this->MakeDisambigHit(closeHit, wids[w], apa);
360  MakeCount++;
361  //std::cout << " Close hit found on channel " << chan << ", time " << st<<"-"<<et << "... \n";
362  //std::cout << " ... giving it wireID ("<< Dwid.Cryostat <<"," << Dwid.TPC
363  // << "," << Dwid.Plane << "," << Dwid.Wire << ")\n";
364  }
365  break;
366  } // end find right wireID
367 
368  } // end loop through all hits on chan
369 
370  return MakeCount;
371  }
372 
373  //----------------------------------------------------------
374  //----------------------------------------------------------
375  void
376  DisambigAlg::Crawl(unsigned int apa)
377  {
378 
379  std::vector<art::Ptr<recob::Hit>> hits = fAPAToUVHits[apa];
380 
381  // repeat this method until stable
382  unsigned int nExtended(1);
383  while (nExtended > 0) {
384  nExtended = 0;
385 
386  // Look for any disambiguated hit ...
387  for (size_t h = 0; h < hits.size(); h++) {
388  std::pair<double, double> ChanTime(hits[h]->Channel() * 1., hits[h]->PeakTime() * 1.);
389  if (!fHasBeenDisambiged[apa][ChanTime]) continue;
390  double stD = hits[h]->PeakTimePlusRMS(-1.);
391  double etD = hits[h]->PeakTimePlusRMS(+1.);
392  double hitWindow = etD - stD;
393  geo::WireID Dwid = fChanTimeToWid[ChanTime];
394 
395  // ... and if any neighboring-channel hits are close enough in time,
396  // extend the disambiguation to the neighboring wire.
397  unsigned int extensions = 0;
398  for (unsigned int ext = 1; ext < fNChanJumps + 1; ext++) {
399  ///\ todo: Evaluate how aggressive we can be here. How far should we jump? In what cases should we quit out?
400  unsigned int N(0);
401  double timeExt = hitWindow * ext;
402  N += this->MakeCloseHits((int)(-ext), Dwid, stD - 5 - timeExt, etD + 5 + timeExt);
403  N += this->MakeCloseHits((int)(ext), Dwid, stD - 5 - timeExt, etD + 5 + timeExt);
404  extensions += N;
405  }
406  nExtended += extensions;
407 
408  } // end UV hits loop
409 
410  } // end while still disambiguating***
411 
412  // *** nested while loops allow disambigauation to hop the channel-wrap-boundary
413  }
414 
415  //----------------------------------------------------------
416  //----------------------------------------------------------
417  unsigned int
419  {
420  ///\ todo: Clean up and break down into two functions.
421  ///\ todo: Make the conditions more robust to some spotty hits around a potential endpoint.
422 
423  double pi = 3.14159265;
424  double fMaxEndPRadRange = fMaxEndPDegRange / 180. * (2 * pi);
425 
426  for (size_t h = 0; h < fAPAToHits[apa].size(); h++) {
427  art::Ptr<recob::Hit> centhit = fAPAToHits[apa][h];
428  geo::View_t view = centhit->View();
429  unsigned int plane = 0;
430  if (view == geo::kV) { plane = 1; }
431  else if (view == geo::kZ)
432  plane = 2;
433  std::vector<double> ChanTimeCenter(2, 0.);
434  unsigned int relchan = centhit->Channel() - fAPAGeo.FirstChannelInView(centhit->Channel());
435  ChanTimeCenter[0] = relchan * geom->WirePitch(view);
436  ChanTimeCenter[1] = detProp.ConvertTicksToX(centhit->PeakTime(),
437  plane,
438  apa * 2, // tpc doesnt matter
439  centhit->WireID().Cryostat);
440  //std::vector< art::Ptr<recob::Hit> > CloseHits;
441  std::vector<std::vector<double>> CloseHitsChanTime;
442  std::vector<double> FurthestCloseChanTime(2, 0.); //double maxDist = 0.;
443  std::vector<double> ClosestChanTime(2, 0.);
444  double minDist = fCloseHitsRadius + 1.;
445  double ChanDistRange = fAPAGeo.ChannelsInView(view) * geom->WirePitch(view);
446 
447  for (size_t c = 0; c < fAPAToHits[apa].size(); c++) {
448  art::Ptr<recob::Hit> closehit = fAPAToHits[apa][c];
449  if (view != closehit->View()) continue;
450  if (view == geo::kZ && centhit->WireID().TPC != closehit->WireID().TPC) continue;
451  unsigned int plane = 0;
452  if (view == geo::kV) { plane = 1; }
453  else if (view == geo::kZ)
454  plane = 2;
455  std::vector<double> ChanTimeClose(2, 0.);
456  unsigned int relchanclose =
457  closehit->Channel() - fAPAGeo.FirstChannelInView(closehit->Channel());
458  ChanTimeClose[0] = relchanclose * geom->WirePitch(view);
459  ChanTimeClose[1] = detProp.ConvertTicksToX(closehit->PeakTime(),
460  plane,
461  apa * 2, // tpc doesnt matter
462  closehit->WireID().Cryostat);
463  if (ChanTimeClose == ChanTimeCenter) continue; // move on if the same one
464 
465  double ChanDist = ChanTimeClose[0] - ChanTimeCenter[0];
466  if (ChanDist > ChanDistRange / 2) ChanDist = ChanDistRange - ChanDist;
467 
468  double distance = std::hypot(ChanDist, ChanTimeClose[1] - ChanTimeCenter[1]);
469 
470  if (distance <= fCloseHitsRadius) CloseHitsChanTime.push_back(ChanTimeClose);
471 
472  if (distance < minDist) {
473  ClosestChanTime = ChanTimeClose;
474  minDist = distance;
475  }
476 
477  } // end close-by hit loop
478 
479  if (CloseHitsChanTime.size() < 5) continue; // quick fix, to-be improved
480 
481  double minRad(2 * pi + 1.), maxRad(0.);
482  bool CloseToNegPi(false), CloseToPosPi(false);
483  for (size_t i = 0; i < CloseHitsChanTime.size(); i++) {
484  std::vector<double> ThisChanTime(CloseHitsChanTime[i]);
485  //if(ThisChanTime==ClosestChanTime) continue;
486  double ChanDist = ThisChanTime[0] - ChanTimeCenter[0];
487  if (ChanDist > ChanDistRange / 2) ChanDist = ChanDistRange - ChanDist;
488  double hitrad = std::atan2(ThisChanTime[1] - ChanTimeCenter[1], ChanDist);
489  if (hitrad > maxRad) maxRad = hitrad;
490  if (hitrad < minRad) minRad = hitrad;
491  if (hitrad + fMaxEndPRadRange > pi)
492  CloseToPosPi = true;
493  else if (hitrad - fMaxEndPRadRange < -pi)
494  CloseToNegPi = true;
495  }
496 
497  // activity at this boundary automatically kills the test, move boundary and redo
498  if (CloseToPosPi && CloseToNegPi) {
499  for (size_t i = 0; i < CloseHitsChanTime.size(); i++) {
500  std::vector<double> ThisChanTime(CloseHitsChanTime[i]);
501  //if(ThisChanTime==ClosestChanTime) continue;
502  double ChanDist = ThisChanTime[0] - ChanTimeCenter[0];
503  if (ChanDist > ChanDistRange / 2) ChanDist = ChanDistRange - ChanDist;
504  double hitrad = std::atan2(ThisChanTime[1] - ChanTimeCenter[1], ChanDist);
505  if (hitrad > 0) hitrad = pi - hitrad; // reflec across pi/2 line
506  if (hitrad < 0) hitrad = -pi - hitrad;
507  if (hitrad > maxRad) maxRad = hitrad;
508  if (hitrad < minRad) minRad = hitrad;
509  }
510  }
511 
512  if (maxRad - minRad < fMaxEndPRadRange) fAPAToEndPHits[apa].push_back(centhit);
513 
514  } // end UV hit loop
515 
516  if (fAPAToEndPHits[apa].size() == 0) return 0;
517  mf::LogVerbatim("FindChanTimeEndPts") << " Found " << fAPAToEndPHits[apa].size()
518  << " endpoint hits in apa " << apa << std::endl;
519  for (size_t ep = 0; ep < fAPAToEndPHits[apa].size(); ep++) {
520  art::Ptr<recob::Hit> epHit = fAPAToEndPHits[apa][ep];
521  mf::LogVerbatim("FindChanTimeEndPts") << " endP on channel " << epHit->Channel()
522  << " at time " << epHit->PeakTime() << std::endl;
523  }
524 
525  return fAPAToEndPHits[apa].size();
526  }
527 
528  //----------------------------------------------------------
529  //----------------------------------------------------------
530  void
532  {
533 
534  ///\ todo: This function could be made much cleaner and more compact
535 
536  if (fAPAToEndPHits[apa].size() == 0) {
537  mf::LogVerbatim("UseEndPts") << " APA " << apa << " has no endpoints.";
538  return;
539  }
540  std::vector<art::Ptr<recob::Hit>> const& endPts = fAPAToEndPHits[apa];
541 
542  std::vector<std::vector<art::Ptr<recob::Hit>>> EndPMatch;
543  unsigned short nZendPts(0);
544 
545  auto on_z_plane = [](art::Ptr<recob::Hit> const& hit) { return hit->View() == geo::kZ; };
546  auto not_on_z_plane = [](art::Ptr<recob::Hit> const& hit) { return hit->View() != geo::kZ; };
547  for (auto const& ZHitPtr : endPts | filter(on_z_plane)) {
548  auto const& ZHit = *ZHitPtr;
549  art::Ptr<recob::Hit> Uhit = ZHitPtr;
550  art::Ptr<recob::Hit> Vhit = ZHitPtr;
551  unsigned short Umatch(0), Vmatch(0);
552  ++nZendPts;
553 
554  // look for U and V hits overlapping in time
555  for (auto const& hitPtr : endPts | filter(not_on_z_plane)) {
556  auto const& hit = *hitPtr;
557  if (not HitsOverlapInTime(detProp, ZHit, hit)) continue;
558 
559  if (hit.View() == geo::kU) {
560  Uhit = hitPtr;
561  Umatch++;
562  }
563  else if (hit.View() == geo::kV) {
564  Vhit = hitPtr;
565  Vmatch++;
566  }
567  }
568 
569  TVector3 tpcCenter(0, 0, 0);
570  unsigned int tpc(ZHit.WireID().TPC), cryo(ZHit.WireID().Cryostat);
571  tpcCenter = geom->Cryostat(cryo).TPC(tpc).LocalToWorld(tpcCenter);
572 
573  if (Umatch == 1 && Vmatch == 1) {
574 
575  std::vector<double> yzEndPt =
576  fAPAGeo.ThreeChanPos(Uhit->Channel(), Vhit->Channel(), ZHit.Channel());
577  double intersect[3] = {tpcCenter[0], yzEndPt[0], yzEndPt[1]};
578 
579  geo::WireID Uwid = fAPAGeo.NearestWireIDOnChan(intersect, Uhit->Channel(), 0, tpc, cryo);
580  geo::WireID Vwid = fAPAGeo.NearestWireIDOnChan(intersect, Vhit->Channel(), 1, tpc, cryo);
581  this->MakeDisambigHit(Uhit, Uwid, apa);
582  this->MakeDisambigHit(Vhit, Vwid, apa);
583  }
584  else if (Umatch == 1 && Vmatch != 1) {
585 
586  std::vector<geo::WireIDIntersection> widIntersects;
587  fAPAGeo.APAChannelsIntersect(Uhit->Channel(), ZHit.Channel(), widIntersects);
588  if (widIntersects.size() == 0)
589  continue;
590  else if (widIntersects.size() == 1) {
591  double intersect[3] = {tpcCenter[0], widIntersects[0].y, widIntersects[0].z};
592  geo::WireID Uwid = fAPAGeo.NearestWireIDOnChan(intersect, Uhit->Channel(), 0, tpc, cryo);
593  this->MakeDisambigHit(Uhit, Uwid, apa);
594  }
595  else {
596  for (size_t i = 0; i < widIntersects.size(); i++) {
597  // compare to V hit times, see if only one makes sense
598  }
599  }
600  }
601  else if (Umatch == 1 && Vmatch != 1) {
602 
603  std::vector<geo::WireIDIntersection> widIntersects;
604  fAPAGeo.APAChannelsIntersect(Vhit->Channel(), ZHit.Channel(), widIntersects);
605  if (widIntersects.size() == 0)
606  continue;
607  else if (widIntersects.size() == 1) {
608  double intersect[3] = {tpcCenter[0], widIntersects[0].y, widIntersects[0].z};
609  geo::WireID Vwid = fAPAGeo.NearestWireIDOnChan(intersect, Vhit->Channel(), 0, tpc, cryo);
610  this->MakeDisambigHit(Vhit, Vwid, apa);
611  }
612  }
613  }
614 
615  if (nZendPts == 0 && endPts.size() == 2 &&
616  this->HitsOverlapInTime(detProp, *endPts[0], *endPts[1])) {
617  std::vector<geo::WireIDIntersection> widIntersects;
618  fAPAGeo.APAChannelsIntersect(endPts[0]->Channel(), endPts[1]->Channel(), widIntersects);
619  if (widIntersects.size() == 1) {
620  TVector3 tpcCenter(0, 0, 0);
621  unsigned int cryo = endPts[0]->WireID().Cryostat;
622  unsigned int tpc = widIntersects[0].TPC;
623  tpcCenter = geom->Cryostat(cryo).TPC(tpc).LocalToWorld(tpcCenter);
624  double intersect[3] = {tpcCenter[0], widIntersects[0].y, widIntersects[0].z};
625  unsigned int plane0(0), plane1(0);
626  if (endPts[0]->View() == geo::kV) plane0 = 1;
627  if (endPts[1]->View() == geo::kV) plane1 = 1;
628  geo::WireID wid0 =
629  fAPAGeo.NearestWireIDOnChan(intersect, endPts[0]->Channel(), plane0, tpc, cryo);
630  this->MakeDisambigHit(endPts[0], wid0, apa);
631  geo::WireID wid1 =
632  fAPAGeo.NearestWireIDOnChan(intersect, endPts[1]->Channel(), plane1, tpc, cryo);
633  this->MakeDisambigHit(endPts[1], wid1, apa);
634  }
635  }
636 
637  this->Crawl(apa);
638  }
639 
640  //----------------------------------------------------------
641  //----------------------------------------------------------
642  void
644  {
645  unsigned int nU(0), nV(0);
646  for (size_t h = 0; h < fAPAToUVHits[apa].size(); h++) {
648  if (hit->View() == geo::kU)
649  nU++;
650  else if (hit->View() == geo::kV)
651  nV++;
652  }
653 
654  unsigned int nDU(0), nDV(0);
655  for (size_t h = 0; h < fAPAToDHits[apa].size(); h++) {
656  art::Ptr<recob::Hit> hit = fAPAToDHits[apa][h].first;
657  if (hit->View() == geo::kU)
658  nDU++;
659  else if (hit->View() == geo::kV)
660  nDV++;
661  }
662 
663  fUeffSoFar[apa] = (nDU * 1.) / (nU * 1.);
664  fVeffSoFar[apa] = (nDV * 1.) / (nV * 1.);
665  fnUSoFar[apa] = nU;
666  fnVSoFar[apa] = nV;
667  fnDUSoFar[apa] = nDU;
668  fnDVSoFar[apa] = nDV;
669  }
670 
671  //----------------------------------------------------------
672  //----------------------------------------------------------
673  unsigned int
675  {
676  unsigned int nDisambiguations(0);
677 
678  // loop through all hits that are still ambiguous
679  for (auto const& ambighitPtr : fAPAToUVHits[apa]) {
680  auto const& ambighit = *ambighitPtr;
681  raw::ChannelID_t ambigchan = ambighit.Channel();
682  std::pair<double, double> ambigChanTime(ambigchan * 1., ambighit.PeakTime());
683  if (fHasBeenDisambiged[apa][ambigChanTime]) continue;
684  geo::View_t view = ambighit.View();
685  std::vector<geo::WireID> ambigwids = geom->ChannelToWire(ambigchan);
686  std::vector<unsigned int> widDcounts(ambigwids.size(), 0);
687  std::vector<unsigned int> widAcounts(ambigwids.size(), 0);
688 
689  // loop through hits in the other view which are close in time
690  for (auto const& hit : fAPAToUVHits[apa] | transform(to_element)) {
691  if (hit.View() == view || !this->HitsOverlapInTime(detProp, ambighit, hit)) continue;
692 
693  // An other-view-hit overlaps in time, see what
694  // wids of the ambiguous hit's channels it overlaps
695  raw::ChannelID_t chan = hit.Channel();
696  std::vector<geo::WireID> wids = geom->ChannelToWire(chan);
697  std::pair<double, double> ChanTime(chan * 1., hit.PeakTime());
698  geo::WireIDIntersection widIntersect; // only so we can use the function
699  if (fHasBeenDisambiged[apa][ChanTime]) {
700  for (size_t a = 0; a < ambigwids.size(); a++)
701  if (ambigwids[a].TPC == fChanTimeToWid[ChanTime].TPC &&
702  geom->WireIDsIntersect(ambigwids[a], fChanTimeToWid[ChanTime], widIntersect))
703  widDcounts[a]++;
704  }
705  else {
706  // still might be able to glean disambiguation
707  // from the ambiguous hits at this time
708  for (size_t a = 0; a < ambigwids.size(); a++)
709  for (size_t w = 0; w < wids.size(); w++)
710  if (ambigwids[a].TPC == wids[w].TPC &&
711  geom->WireIDsIntersect(ambigwids[a], wids[w], widIntersect))
712  widAcounts[a]++;
713  }
714  } // end loop through close-time hits
715 
716  // For now, just make a hit if either ambig or disambig hits
717  // unanimously intersect a single wireID
718  unsigned int Dcount(0), Acount(0);
719  for (size_t d = 0; d < widDcounts.size(); d++)
720  Dcount += widDcounts[d];
721  for (size_t a = 0; a < widAcounts.size(); a++)
722  Acount += widAcounts[a];
723  for (size_t d = 0; d < widDcounts.size(); d++) {
724  if (Dcount == widDcounts[d] && Dcount > 0 && Acount == 0) {
725  this->MakeDisambigHit(ambighitPtr, ambigwids[d], apa);
726  nDisambiguations++;
727  }
728  }
729  } // end loop through still ambiguous hits
730 
731  return nDisambiguations;
732  }
733 
734 } //end namespace apa
std::map< unsigned int, std::map< std::pair< double, double >, bool > > fHasBeenDisambiged
Convenient way to keep track of disambiguation so far.
Definition: DisambigAlg.h:82
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::map< raw::ChannelID_t, std::vector< art::Ptr< recob::Hit > > > fChannelToHits
Definition: DisambigAlg.h:71
list extensions
Definition: conf.py:32
constexpr to_element_t to_element
Definition: ToElement.h:24
Encapsulate the construction of a single cyostat.
double fCloseHitsRadius
Definition: DisambigAlg.h:101
bool HitsOverlapInTime(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hitA, recob::Hit const &hitB)
AdcChannelData::View View
std::map< unsigned int, std::vector< art::Ptr< recob::Hit > > > fAPAToZHits
Definition: DisambigAlg.h:72
std::map< unsigned int, unsigned int > fnDVSoFar
Definition: DisambigAlg.h:58
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:130
geo::WireID WireID() const
Definition: Hit.h:233
apa::APAGeometryAlg fAPAGeo
Definition: DisambigAlg.h:65
std::map< unsigned int, unsigned int > fnVSoFar
Definition: DisambigAlg.h:56
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
uint32_t FirstChannelInView(geo::View_t geoview, unsigned int apa, unsigned int cryo) const
void Crawl(unsigned int apa)
Extend what we disambiguation we do have in apa.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
Planes which measure Z direction.
Definition: geo_types.h:132
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
void RunDisambig(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::Handle< std::vector< recob::Hit >> GausHits)
Definition: DisambigAlg.cxx:54
std::map< unsigned int, std::vector< art::Ptr< recob::Hit > > > fAPAToEndPHits
\ todo: Channel/APA to hits can be done in a unified way
Definition: DisambigAlg.h:75
std::vector< double > HitToXYZ(detinfo::DetectorClocksData const &clockData, const recob::Hit &hit) const
bool APAChannelsIntersect(uint32_t chan1, uint32_t chan2, std::vector< geo::WireIDIntersection > &IntersectVector) const
If the channels intersect, get all intersections.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
art::ServiceHandle< geo::Geometry const > geom
Definition: DisambigAlg.h:66
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
void TrivialDisambig(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, unsigned int apa)
Make the easiest and safest disambiguations in apa.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
Planes which measure U.
Definition: geo_types.h:129
unsigned int ChannelToAPA(uint32_t chan) const
Get number of the APA containing the given channel.
void AssessDisambigSoFar(unsigned int apa)
See how much disambiguation has been done in this apa so far.
std::map< unsigned int, std::vector< art::Ptr< recob::Hit > > > fAPAToUVHits
Definition: DisambigAlg.h:72
const double a
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::map< unsigned int, std::vector< art::Ptr< recob::Hit > > > fAPAToHits
Definition: DisambigAlg.h:73
DisambigAlg(fhicl::ParameterSet const &pset)
Definition: DisambigAlg.cxx:40
p
Definition: test.py:223
unsigned int ChannelsInView(geo::View_t geoview) const
std::map< unsigned int, double > fVeffSoFar
Definition: DisambigAlg.h:54
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
void MakeDisambigHit(art::Ptr< recob::Hit > const &hit, geo::WireID, unsigned int apa)
Makes a disambiguated hit while keeping track of what has already been disambiguated.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
unsigned int fNChanJumps
Number of channels the crawl can jump over.
Definition: DisambigAlg.h:100
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
void UseEndPts(detinfo::DetectorPropertiesData const &detProp, unsigned int apa)
float PeakTimeMinusRMS(float sigmas=+1.) const
Definition: Hit.h:239
Detector simulation of raw signals on wires.
double ConvertTicksToX(double ticks, int p, int t, int c) const
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
Declaration of signal hit object.
geo::WireID NearestWireIDOnChan(const double WorldLoc[3], uint32_t chan, unsigned int const plane, unsigned int const tpc=0, unsigned int const cstat=0) const
Contains all timing reference information for the detector.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
bool fCrawl
\ todo: Write function that compares hits more detailedly
Definition: DisambigAlg.h:97
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
art::ServiceHandle< cheat::BackTrackerService const > bt_serv
Definition: DisambigAlg.h:68
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
std::vector< std::pair< art::Ptr< recob::Hit >, geo::WireID > > fDisambigHits
The final list of hits to pass back to be made.
Definition: DisambigAlg.h:60
double fMaxEndPDegRange
Definition: DisambigAlg.h:103
unsigned int CompareViews(detinfo::DetectorPropertiesData const &detProp, unsigned int apa)
Compare U and V to see if one says something about the other.
std::map< unsigned int, double > fUeffSoFar
Definition: DisambigAlg.h:53
static unsigned filter(unsigned char *out, const unsigned char *in, unsigned w, unsigned h, const LodePNG_InfoColor *info)
Definition: lodepng.cpp:3576
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
float pi
Definition: units.py:11
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:236
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
std::vector< double > ThreeChanPos(uint32_t u, uint32_t v, uint32_t z) const
Find the center of the 3 intersections, choose best if multiple.
raw::ChannelID_t NearestChannel(geo::Point_t const &worldLoc, geo::PlaneID const &planeid) const
Returns the ID of the channel nearest to the specified position.
std::map< unsigned int, unsigned int > fnUSoFar
Definition: DisambigAlg.h:55
unsigned int FindChanTimeEndPts(detinfo::DetectorPropertiesData const &detProp, unsigned int apa)
Basic endpoint-hit finder per apa.
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:230
std::map< unsigned int, std::vector< std::pair< art::Ptr< recob::Hit >, geo::WireID > > > fAPAToDHits
Hold the disambiguations per APA.
Definition: DisambigAlg.h:76
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:563
unsigned int MakeCloseHits(int ext, geo::WireID wid, double Dmin, double Dmax)
Having disambiguated a time range on a wireID, extend to neighboring channels.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.
std::map< std::pair< double, double >, geo::WireID > fChanTimeToWid
If a hit is disambiguated, map its chan and peak time to the chosen wireID.
Definition: DisambigAlg.h:80
std::map< unsigned int, unsigned int > fnDUSoFar
Definition: DisambigAlg.h:57