LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
EMShower3D_module.cc
Go to the documentation of this file.
1 // Class: EMShower3D
3 // Module Type: producer
4 // File: EMShower3D_module.cc
5 // Authors: dorota.stefan@cern.ch robert.sulej@cern.ch
7 
13 #include "fhiclcpp/ParameterSet.h"
14 
25 
29 
30 #include <memory>
31 
34 
35 namespace {
36  struct IniSeg {
37  size_t idcl1;
38  size_t idcl2;
39  size_t idcl3;
40  size_t view1;
41  size_t view2;
42  size_t view3;
44  std::vector<art::Ptr<recob::Hit>> hits1;
45  std::vector<art::Ptr<recob::Hit>> hits2;
46  std::vector<art::Ptr<recob::Hit>> hits3;
47  };
48 }
49 
50 namespace ems {
51  class EMShower3D;
52 }
53 
55 public:
56  explicit EMShower3D(fhicl::ParameterSet const& p);
57 
58  EMShower3D(EMShower3D const&) = delete;
59  EMShower3D(EMShower3D&&) = delete;
60  EMShower3D& operator=(EMShower3D const&) = delete;
61  EMShower3D& operator=(EMShower3D&&) = delete;
62 
63 private:
64  void produce(art::Event& e) override;
65 
66  recob::Track ConvertFrom(detinfo::DetectorClocksData const& clock_data,
67  detinfo::DetectorPropertiesData const& det_prop,
68  pma::Track3D& src);
69  recob::Track ConvertFrom2(detinfo::DetectorClocksData const& clock_data,
70  detinfo::DetectorPropertiesData const& det_prop,
71  pma::Track3D& src);
72  recob::Cluster ConvertFrom(const std::vector<art::Ptr<recob::Hit>>& src);
73 
74  std::vector<ems::DirOfGamma*> CollectShower2D(detinfo::DetectorPropertiesData const& detProp,
75  art::Event const& e);
76 
77  void Link(detinfo::DetectorPropertiesData const& detProp, std::vector<ems::DirOfGamma*> input);
78 
79  // Remove tracks which are too close to each other
80  void Reoptimize(detinfo::DetectorPropertiesData const& detProp);
81 
82  void Make3DSeg(detinfo::DetectorPropertiesData const& detProp,
83  std::vector<ems::DirOfGamma*> pair);
84 
85  bool Validate(detinfo::DetectorPropertiesData const& detProp,
86  std::vector<ems::DirOfGamma*> input,
87  size_t id1,
88  size_t id2,
89  size_t c1,
90  size_t c2,
91  size_t plane3);
92 
93  void FilterOutSmallParts(detinfo::DetectorPropertiesData const& detProp,
94  double r2d,
95  const std::vector<art::Ptr<recob::Hit>>& hits_in,
97 
98  bool GetCloseHits(detinfo::DetectorPropertiesData const& detProp,
99  double r2d,
100  const std::vector<art::Ptr<recob::Hit>>& hits_in,
101  std::vector<size_t>& used,
102  std::vector<art::Ptr<recob::Hit>>& hits_out);
103 
104  bool Has(const std::vector<size_t>& v, size_t idx);
105 
106  size_t LinkCandidates(detinfo::DetectorPropertiesData const& detProp,
107  std::vector<ems::DirOfGamma*> input,
108  size_t id);
109 
110  std::vector<IniSeg> fInisegs;
111  std::vector<IniSeg> fSeltracks;
112  std::vector<IniSeg> fPMA3D;
113 
114  std::vector<std::vector<art::Ptr<recob::Hit>>> fClusters;
115 
116  std::vector<size_t> fClustersNotUsed;
117  std::vector<size_t> fTracksNotUsed;
118 
119  unsigned int fTrkIndex;
120  unsigned int fClIndex;
121  unsigned int fIniIndex;
122 
123  std::string fCluModuleLabel;
124  std::string fTrk3DModuleLabel;
125 
128 
130 };
131 
133  : EDProducer{p}
134  , fProjectionMatchingAlg(p.get<fhicl::ParameterSet>("ProjectionMatchingAlg"))
135  , fCalorimetryAlg(p.get<fhicl::ParameterSet>("CalorimetryAlg"))
136 {
137  fCluModuleLabel = p.get<std::string>("ClustersModuleLabel");
138  fTrk3DModuleLabel = p.get<std::string>("Trk3DModuleLabel");
139 
140  produces<std::vector<recob::Track>>();
141  produces<std::vector<recob::Vertex>>();
142  produces<std::vector<recob::Cluster>>();
143  produces<std::vector<recob::SpacePoint>>();
144  produces<art::Assns<recob::Track, recob::Hit>>();
145  produces<art::Assns<recob::Track, recob::Vertex>>();
146  produces<art::Assns<recob::Cluster, recob::Hit>>();
147  produces<art::Assns<recob::Track, recob::SpacePoint>>();
148  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
149  produces<art::Assns<recob::Track, recob::Cluster>>();
150 }
151 
153 {
154  return recob::Cluster(0.0F,
155  0.0F,
156  0.0F,
157  0.0F,
158  0.0F,
159  0.0F,
160  0.0F,
161  0.0F,
162  0.0F,
163  0.0F,
164  0.0F,
165  0.0F,
166  0.0F,
167  0.0F,
168  0.0F,
169  0.0F,
170  0.0F,
171  0.0F,
172  src.size(),
173  0.0F,
174  0.0F,
175  fClIndex,
176  src[0]->View(),
177  src[0]->WireID().planeID());
178 }
179 
181  detinfo::DetectorPropertiesData const& detProp,
182  pma::Track3D& src)
183 {
184  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
185  double avdrift = (src.front()->Point3D().X() + src.back()->Point3D().X()) * 0.5;
186  unsigned int nplanes = wireReadoutGeom.Nplanes({src.front()->Cryo(), src.front()->TPC()});
187  size_t nusedhitsmax = 0;
188  int bestplane = -1;
189  for (unsigned int p = 0; p < nplanes; ++p) {
190  unsigned int nusedP = 0;
191  fProjectionMatchingAlg.selectInitialHits(src, p, &nusedP);
192 
193  if (nusedP > nusedhitsmax) {
194  nusedhitsmax = nusedP;
195  bestplane = int(p);
196  }
197  }
198 
199  std::vector<std::vector<double>> vdedx;
200  std::vector<double> dedx;
201 
202  for (unsigned int p = 0; p < nplanes; ++p) {
203  unsigned int nusedP = 0;
204  double dqdxplane = fProjectionMatchingAlg.selectInitialHits(src, p, &nusedP);
205  double timeP = detProp.ConvertXToTicks(avdrift, p, src.front()->TPC(), src.front()->Cryo());
206  double dEdxplane = fCalorimetryAlg.dEdx_AREA(clock_data, detProp, dqdxplane, timeP, p);
207  dedx.push_back(dEdxplane);
208  if (int(p) == bestplane)
209  dedx.push_back(1);
210  else
211  dedx.push_back(0);
212  vdedx.push_back(dedx);
213  }
214 
215  std::vector<TVector3> xyz, dircos;
216 
217  for (size_t i = 0; i < src.size(); i++) {
218  xyz.push_back(src[i]->Point3D());
219 
220  if (i < src.size() - 1) {
221  TVector3 dc(src[i + 1]->Point3D());
222  dc -= src[i]->Point3D();
223  dc *= 1.0 / dc.Mag();
224  dircos.push_back(dc);
225  }
226  else
227  dircos.push_back(dircos.back());
228  }
229 
232  recob::Track::Flags_t(xyz.size()),
233  false),
234  0,
235  -1.,
236  0,
239  fIniIndex);
240 }
241 
243  detinfo::DetectorPropertiesData const& detProp,
244  pma::Track3D& src)
245 {
246  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
247 
248  double avdrift = (src.front()->Point3D().X() + src.back()->Point3D().X()) * 0.5;
249  unsigned int nplanes = wireReadoutGeom.Nplanes({src.front()->Cryo(), src.front()->TPC()});
250  size_t nusedhitsmax = 0;
251  int bestplane = -1;
252  for (unsigned int p = 0; p < nplanes; ++p) {
253  unsigned int nusedP = 0;
254  fProjectionMatchingAlg.selectInitialHits(src, p, &nusedP);
255 
256  if (nusedP > nusedhitsmax) {
257  nusedhitsmax = nusedP;
258  bestplane = int(p);
259  }
260  }
261 
262  std::vector<std::vector<double>> vdedx;
263  std::vector<double> dedx;
264 
265  for (unsigned int p = 0; p < nplanes; ++p) {
266  unsigned int nusedP = 0;
267  double dqdxplane = fProjectionMatchingAlg.selectInitialHits(src, p, &nusedP);
268  double timeP = detProp.ConvertXToTicks(avdrift, p, src.front()->TPC(), src.front()->Cryo());
269  double dEdxplane = fCalorimetryAlg.dEdx_AREA(clockData, detProp, dqdxplane, timeP, p);
270  dedx.push_back(dEdxplane);
271  if (int(p) == bestplane)
272  dedx.push_back(1);
273  else
274  dedx.push_back(0);
275  vdedx.push_back(dedx);
276  }
277 
278  std::vector<TVector3> xyz, dircos;
279 
280  for (size_t i = 0; i < src.size(); i++) {
281  xyz.push_back(src[i]->Point3D());
282 
283  if (i < src.size() - 1) {
284  TVector3 dc(src[i + 1]->Point3D());
285  dc -= src[i]->Point3D();
286  dc *= 1.0 / dc.Mag();
287  dircos.push_back(dc);
288  }
289  else
290  dircos.push_back(dircos.back());
291  }
292 
295  recob::Track::Flags_t(xyz.size()),
296  false),
297  0,
298  -1.,
299  0,
302  fIniIndex);
303 }
304 
306 {
308  fSeltracks.clear();
309  fInisegs.clear();
310  fClusters.clear();
311  fPMA3D.clear();
312  fClustersNotUsed.clear();
313 
314  auto tracks = std::make_unique<std::vector<recob::Track>>();
315  auto vertices = std::make_unique<std::vector<recob::Vertex>>();
316  auto clusters = std::make_unique<std::vector<recob::Cluster>>();
317  auto allsp = std::make_unique<std::vector<recob::SpacePoint>>();
318 
319  auto trk2hit = std::make_unique<art::Assns<recob::Track, recob::Hit>>();
320  auto trk2vtx = std::make_unique<art::Assns<recob::Track, recob::Vertex>>();
321  auto cl2hit = std::make_unique<art::Assns<recob::Cluster, recob::Hit>>();
322  auto trk2cl = std::make_unique<art::Assns<recob::Track, recob::Cluster>>();
323  auto trk2sp = std::make_unique<art::Assns<recob::Track, recob::SpacePoint>>();
324  auto sp2hit = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
325 
326  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
327  auto const detProp =
329 
331  fClustersNotUsed.clear();
332  fInisegs.clear();
334 
335  for (size_t id = 0; id < fCluListHandle->size(); id++) {
336  std::vector<art::Ptr<recob::Hit>> hitlist;
337  hitlist = fb.at(id);
338 
339  if (hitlist.size() > 5) fClustersNotUsed.push_back(id);
340  }
341 
342  std::vector<ems::DirOfGamma*> showernviews = CollectShower2D(detProp, e);
343 
344  Link(detProp, showernviews);
345 
346  while (fInisegs.size()) {
347  fSeltracks.push_back(fInisegs[0]);
348  fInisegs.erase(fInisegs.begin() + 0);
349  }
350 
351  Reoptimize(detProp);
352 
353  // conversion from pma track to recob::track
354 
355  size_t spStart = 0, spEnd = 0;
356  double sp_pos[3], sp_err[6], vtx_pos[3];
357  for (size_t i = 0; i < 6; i++)
358  sp_err[i] = 1.0;
359 
360  fTrkIndex = 0;
361 
362  for (auto const& trk : fSeltracks) {
363  tracks->push_back(ConvertFrom(clockData, detProp, *(trk.track)));
364 
365  vtx_pos[0] = trk.track->front()->Point3D().X();
366  vtx_pos[1] = trk.track->front()->Point3D().Y();
367  vtx_pos[2] = trk.track->front()->Point3D().Z();
368  vertices->emplace_back(vtx_pos, fTrkIndex);
369 
370  ++fTrkIndex;
371 
372  std::vector<art::Ptr<recob::Cluster>> cl2d;
373  cl2d.emplace_back(fCluListHandle, trk.idcl1);
374  cl2d.emplace_back(fCluListHandle, trk.idcl2);
375 
376  std::vector<art::Ptr<recob::Hit>> hits2d;
378 
379  spStart = allsp->size();
380  for (int h = trk.track->size() - 1; h >= 0; h--) {
381  pma::Hit3D* h3d = (*trk.track)[h];
382  hits2d.push_back(h3d->Hit2DPtr());
383 
384  if ((h == 0) || (sp_pos[0] != h3d->Point3D().X()) || (sp_pos[1] != h3d->Point3D().Y()) ||
385  (sp_pos[2] != h3d->Point3D().Z())) {
386  if (sp_hits.size()) // hits assigned to the previous sp
387  {
388  util::CreateAssn(e, *allsp, sp_hits, *sp2hit);
389  sp_hits.clear();
390  }
391  sp_pos[0] = h3d->Point3D().X();
392  sp_pos[1] = h3d->Point3D().Y();
393  sp_pos[2] = h3d->Point3D().Z();
394  allsp->push_back(recob::SpacePoint(sp_pos, sp_err, 1.0));
395  }
396  sp_hits.push_back(h3d->Hit2DPtr());
397  }
398  if (sp_hits.size()) // hits assigned to the last sp
399  {
400  util::CreateAssn(e, *allsp, sp_hits, *sp2hit);
401  }
402  spEnd = allsp->size();
403 
404  if (vertices->size()) {
405  size_t vtx_idx = (size_t)(vertices->size() - 1);
406  util::CreateAssn(e, *tracks, *vertices, *trk2vtx, vtx_idx, vtx_idx + 1);
407  }
408 
409  if (cl2d.size()) { util::CreateAssn(e, *tracks, cl2d, *trk2cl); }
410 
411  if (hits2d.size()) {
412  util::CreateAssn(e, *tracks, *allsp, *trk2sp, spStart, spEnd);
413  util::CreateAssn(e, *tracks, hits2d, *trk2hit);
414  }
415  }
416 
417  fIniIndex = fTrkIndex + 1;
418  for (auto const& trk : fPMA3D) {
419  tracks->push_back(ConvertFrom2(clockData, detProp, *(trk.track)));
420 
421  fIniIndex++;
422 
423  std::vector<art::Ptr<recob::Cluster>> cl2d;
424  cl2d.push_back(art::Ptr<recob::Cluster>(fCluListHandle, trk.idcl1));
425  cl2d.push_back(art::Ptr<recob::Cluster>(fCluListHandle, trk.idcl2));
426 
427  std::vector<art::Ptr<recob::Hit>> hits2d;
429 
430  spStart = allsp->size();
431  for (int h = trk.track->size() - 1; h >= 0; h--) {
432  pma::Hit3D* h3d = (*trk.track)[h];
433  hits2d.push_back(h3d->Hit2DPtr());
434 
435  if ((h == 0) || (sp_pos[0] != h3d->Point3D().X()) || (sp_pos[1] != h3d->Point3D().Y()) ||
436  (sp_pos[2] != h3d->Point3D().Z())) {
437  if (sp_hits.size()) // hits assigned to the previous sp
438  {
439  util::CreateAssn(e, *allsp, sp_hits, *sp2hit);
440  sp_hits.clear();
441  }
442  sp_pos[0] = h3d->Point3D().X();
443  sp_pos[1] = h3d->Point3D().Y();
444  sp_pos[2] = h3d->Point3D().Z();
445  allsp->push_back(recob::SpacePoint(sp_pos, sp_err, 1.0));
446  }
447  sp_hits.push_back(h3d->Hit2DPtr());
448  }
449  if (sp_hits.size()) // hits assigned to the last sp
450  {
451  util::CreateAssn(e, *allsp, sp_hits, *sp2hit);
452  }
453  spEnd = allsp->size();
454 
455  if (cl2d.size()) { util::CreateAssn(e, *tracks, cl2d, *trk2cl); }
456 
457  if (hits2d.size()) {
458  util::CreateAssn(e, *tracks, *allsp, *trk2sp, spStart, spEnd);
459  util::CreateAssn(e, *tracks, hits2d, *trk2hit);
460  }
461  }
462 
463  // create cluster from hits, which were an input to find initial part of the cascade.
464  fClIndex = 0;
465  for (auto const& cl : fClusters)
466  if (cl.size()) {
467  clusters->push_back(ConvertFrom(cl));
468  fClIndex++;
469 
470  util::CreateAssn(e, *clusters, cl, *cl2hit);
471  }
472 
473  for (unsigned int i = 0; i < showernviews.size(); i++)
474  delete showernviews[i];
475 
476  for (unsigned int i = 0; i < fSeltracks.size(); i++)
477  delete fSeltracks[i].track;
478 
479  for (unsigned int i = 0; i < fInisegs.size(); i++)
480  delete fInisegs[i].track;
481 
482  for (unsigned int i = 0; i < fPMA3D.size(); i++)
483  delete fPMA3D[i].track;
484  }
485 
486  e.put(std::move(tracks));
487  e.put(std::move(vertices));
488  e.put(std::move(clusters));
489  e.put(std::move(allsp));
490 
491  e.put(std::move(trk2hit));
492  e.put(std::move(trk2vtx));
493  e.put(std::move(cl2hit));
494  e.put(std::move(trk2cl));
495  e.put(std::move(trk2sp));
496  e.put(std::move(sp2hit));
497 }
498 
500 {
501  if (empty(fSeltracks)) return;
502  const float min_dist = 3.0F;
503  size_t ta = 0;
504  while (ta < (fSeltracks.size() - 1)) {
505  size_t tb = ta + 1;
506  bool found = false;
507  while (tb < fSeltracks.size()) {
508  if (ta == tb) {
509  tb++;
510  continue;
511  }
512 
513  TVector3 p1 = fSeltracks[ta].track->front()->Point3D();
514  TVector3 p2 = fSeltracks[tb].track->front()->Point3D();
515  float dist = std::sqrt(pma::Dist2(p1, p2));
516 
517  if (dist < min_dist)
518  if ((fSeltracks[ta].idcl1 == fSeltracks[tb].idcl1) ||
519  (fSeltracks[ta].idcl1 == fSeltracks[tb].idcl2) ||
520  (fSeltracks[ta].idcl2 == fSeltracks[tb].idcl1) ||
521  (fSeltracks[ta].idcl2 == fSeltracks[tb].idcl2)) {
522  found = true;
523  size_t view3 = fSeltracks[ta].view1;
524  size_t idcl3 = fSeltracks[ta].idcl1;
525  std::vector<art::Ptr<recob::Hit>> hits3 = fSeltracks[ta].hits1;
526  std::vector<art::Ptr<recob::Hit>> hits = fSeltracks[ta].hits1;
527  for (size_t h = 0; h < fSeltracks[ta].hits2.size(); ++h)
528  hits.push_back(fSeltracks[ta].hits2[h]);
529 
530  if ((fSeltracks[tb].view1 != fSeltracks[ta].view1) &&
531  (fSeltracks[tb].view1 != fSeltracks[ta].view2)) {
532  view3 = fSeltracks[tb].view1;
533  for (size_t h = 0; h < fSeltracks[tb].hits1.size(); ++h)
534  hits.push_back(fSeltracks[tb].hits1[h]);
535  }
536  if ((fSeltracks[tb].view2 != fSeltracks[ta].view1) &&
537  (fSeltracks[tb].view2 != fSeltracks[ta].view2)) {
538  view3 = fSeltracks[tb].view2;
539  for (size_t h = 0; h < fSeltracks[tb].hits2.size(); ++h)
540  hits.push_back(fSeltracks[tb].hits2[h]);
541  }
542 
543  if ((view3 == fSeltracks[ta].view1) || (view3 == fSeltracks[ta].view2)) {
544  delete fSeltracks[ta].track;
545  fSeltracks.erase(fSeltracks.begin() + ta);
546  }
547  else {
549 
550  if (pma::Dist2(track->back()->Point3D(), fSeltracks[ta].track->front()->Point3D()) <
551  pma::Dist2(track->front()->Point3D(), fSeltracks[ta].track->front()->Point3D()))
552  track->Flip();
553 
554  IniSeg initrack;
555  initrack.idcl1 = fSeltracks[ta].idcl1;
556  initrack.idcl3 = idcl3;
557  initrack.view1 = fSeltracks[ta].view1;
558  initrack.view3 = view3;
559  initrack.hits1 = fSeltracks[ta].hits1;
560  initrack.hits3 = hits3;
561  initrack.idcl2 = fSeltracks[ta].idcl2;
562  initrack.view2 = fSeltracks[ta].view2;
563  initrack.hits2 = fSeltracks[ta].hits2;
564  initrack.track = track;
565 
566  delete fSeltracks[tb].track;
567  delete fSeltracks[ta].track;
568  fSeltracks.erase(fSeltracks.begin() + tb);
569  fSeltracks.erase(fSeltracks.begin() + ta);
570  fSeltracks.push_back(initrack);
571  }
572  }
573 
574  if (found) break;
575  tb++;
576  }
577 
578  if (!found) ta++;
579  }
580 }
581 
582 std::vector<ems::DirOfGamma*> ems::EMShower3D::CollectShower2D(
583  detinfo::DetectorPropertiesData const& detProp,
584  art::Event const& e)
585 {
586  std::vector<ems::DirOfGamma*> input;
587 
590  for (unsigned int c = 0; c < fCluListHandle->size(); c++) {
591  std::vector<art::Ptr<recob::Hit>> hitlist;
592  hitlist = fb.at(c);
593 
594  if (hitlist.size() > 5) {
595  std::vector<art::Ptr<recob::Hit>> hits_out;
596  FilterOutSmallParts(detProp, 2.0, hitlist, hits_out);
597 
598  if (hits_out.size() > 5) {
599  fClusters.push_back(hits_out);
600 
601  ems::DirOfGamma* sh = new ems::DirOfGamma(detProp, hits_out, 14, c);
602 
603  if (sh->GetHits2D().size()) input.push_back(sh);
604  }
605  }
606  }
607  }
608 
609  return input;
610 }
611 
613  std::vector<ems::DirOfGamma*> input)
614 {
615  std::vector<std::vector<size_t>> saveids;
616  std::vector<size_t> saveidsnotusedcls;
617  size_t i = 0;
618 
619  while (i < input.size()) {
620  if (!input[i]->GetCandidates().size()) {
621  i++;
622  continue;
623  }
624 
625  double mindist = 1.0; // cm
626  std::vector<ems::DirOfGamma*> pairs;
627 
628  size_t startview = input[i]->GetFirstHit()->WireID().Plane;
629  size_t tpc = input[i]->GetFirstHit()->WireID().TPC;
630  size_t cryo = input[i]->GetFirstHit()->WireID().Cryostat;
631 
632  float t1 = detProp.ConvertTicksToX(input[i]->GetFirstHit()->PeakTime(), startview, tpc, cryo);
633 
634  unsigned int idsave = 0;
635  for (unsigned int j = 0; j < input.size(); j++) {
636  if (!input[j]->GetCandidates().size()) continue;
637 
638  size_t secondview = input[j]->GetFirstHit()->WireID().Plane;
639  size_t tpc_j = input[j]->GetFirstHit()->WireID().TPC;
640  size_t cryo_j = input[j]->GetFirstHit()->WireID().Cryostat;
641 
642  if ((i != j) && (secondview != startview) && (tpc == tpc_j) && (cryo == cryo_j)) {
643  float t2 =
644  detProp.ConvertTicksToX(input[j]->GetFirstHit()->PeakTime(), secondview, tpc_j, cryo_j);
645  float dist = fabs(t2 - t1);
646 
647  if (dist < mindist) {
648  mindist = dist;
649  pairs.clear();
650  pairs.push_back(input[i]);
651  pairs.push_back(input[j]);
652  idsave = j;
653  }
654  }
655  }
656 
657  bool exist = false;
658  for (unsigned int v = 0; v < saveids.size(); v++)
659  if ((saveids[v][0] == i) || (saveids[v][0] == idsave))
660  if ((saveids[v][1] == i) || (saveids[v][1] == idsave)) exist = true;
661 
662  if (pairs.size()) {
663  if (!exist) Make3DSeg(detProp, pairs);
664 
665  std::vector<size_t> ids;
666  ids.push_back(i);
667  ids.push_back(idsave);
668  saveids.push_back(ids);
669  }
670  else {
671  saveidsnotusedcls.push_back(i);
672  }
673 
674  i++;
675  }
676 
677  i = 0;
678  while (i < saveidsnotusedcls.size()) {
679  LinkCandidates(detProp, input, i);
680  i++;
681  }
682 }
683 
685  std::vector<ems::DirOfGamma*> input,
686  size_t id)
687 {
688  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
689 
690  size_t index = id;
691  bool found = false;
692 
693  if (input[id]->GetCandidates().size() < 2) { return index; }
694 
695  double mindist = 3.0; // cm
696  std::vector<ems::DirOfGamma*> pairs;
697 
698  size_t idcsave = 0;
699  size_t idcjsave = 0;
700  size_t c = 0;
701  size_t idsave = 0;
702  while (c < input[id]->GetCandidates().size()) {
703 
704  size_t startview = input[id]->GetCandidates()[c].GetPlane();
705  size_t tpc = input[id]->GetCandidates()[c].GetTPC();
706  size_t cryo = input[id]->GetCandidates()[c].GetCryo();
707 
708  float t1 = input[id]->GetCandidates()[c].GetPosition().Y(); // y --> drift in 2D space.
709 
710  // loop over 2D showers
711  for (size_t j = 0; j < input.size(); ++j) {
712  if (!input[j]->GetCandidates().size()) continue;
713  if (j == id) continue;
714 
715  // loop over candidates
716  for (size_t cj = 0; cj < input[j]->GetCandidates().size(); ++cj) {
717  size_t secondview = input[j]->GetCandidates()[cj].GetPlane();
718  size_t tpc_j = input[j]->GetCandidates()[cj].GetTPC();
719  size_t cryo_j = input[j]->GetCandidates()[cj].GetCryo();
720 
721  size_t thirdview = startview;
722 
723  for (geo::PlaneGeo const& plane :
724  wireReadoutGeom.Iterate<geo::PlaneGeo>(geo::CryostatID(cryo))) {
725  auto const p = plane.ID().Plane;
726  if ((p == startview) || (p == secondview)) { continue; }
727  else {
728  thirdview = p;
729  break;
730  }
731  }
732 
733  if ((startview != secondview) && (tpc == tpc_j) && (cryo == cryo_j)) {
734  float t2 = input[j]->GetCandidates()[cj].GetPosition().Y();
735  float dist = fabs(t2 - t1);
736 
737  if ((dist < mindist) && Validate(detProp, input, id, j, c, cj, thirdview)) {
738  mindist = dist;
739  pairs.clear();
740  pairs.push_back(input[id]);
741  pairs.push_back(input[j]);
742  idsave = j;
743  index = j;
744  idcsave = c;
745  idcjsave = cj;
746  found = true;
747  }
748  }
749  }
750  }
751 
752  c++;
753  }
754 
755  if (found && pairs.size()) {
756  input[id]->SetIdCandidate(idcsave);
757  input[idsave]->SetIdCandidate(idcjsave);
758  Make3DSeg(detProp, pairs);
759  }
760 
761  return index;
762 }
763 
765  std::vector<ems::DirOfGamma*> pair)
766 {
767  if (pair.size() < 2) return;
768 
769  // to build a track correctly 2d hits must belong to the same tpc
770  size_t tpc1 = pair[0]->GetFirstHit()->WireID().TPC;
771  size_t tpc2 = pair[1]->GetFirstHit()->WireID().TPC;
772 
773  std::vector<art::Ptr<recob::Hit>> vec1 = pair[0]->GetIniHits();
774  std::vector<art::Ptr<recob::Hit>> vec2 = pair[1]->GetIniHits();
775 
776  if ((vec1.size() < 3) && (vec2.size() < 3)) return;
777 
778  std::vector<art::Ptr<recob::Hit>> hitscl1uniquetpc;
779  std::vector<art::Ptr<recob::Hit>> hitscl2uniquetpc;
780 
781  if (tpc1 == tpc2)
782  for (size_t i = 0; i < vec1.size(); ++i)
783  for (size_t j = 0; j < vec2.size(); ++j)
784  if ((vec1[i]->WireID().TPC == vec2[j]->WireID().TPC) && (tpc1 == vec2[j]->WireID().TPC)) {
785  hitscl1uniquetpc.push_back(vec1[i]);
786  hitscl2uniquetpc.push_back(vec2[j]);
787  }
788 
789  if ((hitscl1uniquetpc.size() > 2) && (hitscl2uniquetpc.size() > 2)) {
790  pma::Track3D* trk =
791  fProjectionMatchingAlg.buildSegment(detProp, hitscl1uniquetpc, hitscl2uniquetpc);
792 
793  // turn the track that front is at vertex - easier to handle associations.
794  if ((trk->back()->Hit2DPtr() == pair[0]->GetFirstHit()) ||
795  (trk->back()->Hit2DPtr() == pair[1]->GetFirstHit()))
796  trk->Flip();
797 
798  IniSeg initrack;
799  initrack.idcl1 = pair[0]->GetIdCl();
800  initrack.view1 = pair[0]->GetFirstHit()->WireID().Plane;
801  initrack.hits1 = hitscl1uniquetpc;
802  initrack.idcl2 = pair[1]->GetIdCl();
803  initrack.view2 = pair[1]->GetFirstHit()->WireID().Plane;
804  initrack.hits2 = hitscl2uniquetpc;
805  initrack.track = trk;
806 
807  fInisegs.push_back(initrack);
808  }
809 }
810 
812  std::vector<ems::DirOfGamma*> input,
813  size_t id1,
814  size_t id2,
815  size_t c1,
816  size_t c2,
817  size_t plane3)
818 {
819  bool result = false;
820  if (id1 == id2) return false;
821 
822  std::vector<art::Ptr<recob::Hit>> vec1 = input[id1]->GetCandidates()[c1].GetIniHits();
823  std::vector<art::Ptr<recob::Hit>> vec2 = input[id2]->GetCandidates()[c2].GetIniHits();
824 
825  if ((vec1.size() < 3) || (vec2.size() < 3)) return false;
826 
827  std::vector<art::Ptr<recob::Hit>> hitscl1uniquetpc;
828  std::vector<art::Ptr<recob::Hit>> hitscl2uniquetpc;
829 
830  size_t tpc = vec1[0]->WireID().TPC;
831  for (size_t i = 0; i < vec1.size(); ++i)
832  for (size_t j = 0; j < vec2.size(); ++j)
833  if ((vec1[i]->WireID().TPC == tpc) && (vec2[j]->WireID().TPC == tpc)) {
834  hitscl1uniquetpc.push_back(vec1[i]);
835  hitscl2uniquetpc.push_back(vec2[j]);
836  }
837 
838  if ((hitscl1uniquetpc.size() < 3) || (hitscl2uniquetpc.size() < 3)) return false;
839 
841  fProjectionMatchingAlg.buildSegment(detProp, hitscl1uniquetpc, hitscl2uniquetpc);
842  for (size_t i = 0; i < input.size(); ++i) {
843  std::vector<Hit2D*> hits2dcl = input[i]->GetHits2D();
844  for (size_t h = 0; h < hits2dcl.size(); ++h) {
845  TVector2 pfront = pma::GetProjectionToPlane(
846  track->front()->Point3D(), plane3, track->FrontTPC(), track->FrontCryo());
847  TVector2 pback = pma::GetProjectionToPlane(
848  track->back()->Point3D(), plane3, track->BackTPC(), track->BackCryo());
849  if ((pma::Dist2(hits2dcl[h]->GetPointCm(), pfront) < 1.0F) &&
850  (pma::Dist2(hits2dcl[h]->GetPointCm(), pback) < 1.0F)) {
851  result = true;
852  break;
853  }
854  }
855  }
856  delete track;
857  return result;
858 }
859 
860 bool ems::EMShower3D::Has(const std::vector<size_t>& v, size_t idx)
861 {
862  for (auto c : v)
863  if (c == idx) return true;
864  return false;
865 }
866 
868  double r2d,
869  const std::vector<art::Ptr<recob::Hit>>& hits_in,
870  std::vector<size_t>& used,
872 {
873 
874  hits_out.clear();
875 
876  const double gapMargin = 5.0; // can be changed to f(id_tpc1, id_tpc2)
877  size_t idx = 0;
878 
879  while ((idx < hits_in.size()) && Has(used, idx))
880  idx++;
881 
882  if (idx < hits_in.size()) {
883  hits_out.push_back(hits_in[idx]);
884  used.push_back(idx);
885 
886  double r2d2 = r2d * r2d;
887  double gapMargin2 = sqrt(2 * gapMargin * gapMargin);
888  gapMargin2 = (gapMargin2 + r2d) * (gapMargin2 + r2d);
889 
890  bool collect = true;
891  while (collect) {
892  collect = false;
893  for (size_t i = 0; i < hits_in.size(); i++)
894  if (!Has(used, i)) {
895  art::Ptr<recob::Hit> hi = hits_in[i];
896  TVector2 hi_cm = pma::WireDriftToCm(detProp,
897  hi->WireID().Wire,
898  hi->PeakTime(),
899  hi->WireID().Plane,
900  hi->WireID().TPC,
901  hi->WireID().Cryostat);
902 
903  bool accept = false;
904  // for (auto const& ho : hits_out)
905  for (size_t idx_o = 0; idx_o < hits_out.size(); idx_o++) {
906  art::Ptr<recob::Hit> ho = hits_out[idx_o];
907 
908  double d2 = pma::Dist2(hi_cm,
909  pma::WireDriftToCm(detProp,
910  ho->WireID().Wire,
911  ho->PeakTime(),
912  ho->WireID().Plane,
913  ho->WireID().TPC,
914  ho->WireID().Cryostat));
915 
916  if (hi->WireID().TPC == ho->WireID().TPC) {
917  if (d2 < r2d2) {
918  accept = true;
919  break;
920  }
921  }
922  else {
923  if (d2 < gapMargin2) {
924  accept = true;
925  break;
926  }
927  }
928  }
929  if (accept) {
930  collect = true;
931  hits_out.push_back(hi);
932  used.push_back(i);
933  }
934  }
935  }
936  return true;
937  }
938  else
939  return false;
940 }
941 
943  double r2d,
944  const std::vector<art::Ptr<recob::Hit>>& hits_in,
946 {
947  size_t min_size = hits_in.size() / 5;
948  if (min_size < 3) min_size = 3;
949 
950  std::vector<size_t> used;
951  std::vector<art::Ptr<recob::Hit>> close_hits;
952 
953  while (GetCloseHits(detProp, r2d, hits_in, used, close_hits)) {
954  if (close_hits.size() > min_size)
955  for (auto h : close_hits)
956  hits_out.push_back(h);
957  }
958 }
void Link(detinfo::DetectorPropertiesData const &detProp, std::vector< ems::DirOfGamma * > input)
Utilities related to art service access.
TTree * t1
Definition: plottest35.C:26
Implementation of the Projection Matching Algorithm.
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:39
std::vector< Vector_t > convertCollToVector(std::vector< Vector > const &coll)
Definition: TrackingTypes.h:78
Declaration of signal hit object.
pma::Hit3D const * front() const
Definition: PmaTrack3D.h:87
std::vector< std::vector< art::Ptr< recob::Hit > > > fClusters
unsigned int Cryo() const noexcept
Definition: PmaHit3D.h:58
TrackTrajectory::Flags_t Flags_t
Definition: Track.h:67
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
art::Handle< std::vector< recob::Cluster > > fCluListHandle
TVector3 const & Point3D() const
Definition: PmaHit3D.h:50
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
ROOT::Math::SMatrix< Double32_t, 5, 5, ROOT::Math::MatRepSym< Double32_t, 5 >> SMatrixSym55
TVector2 WireDriftToCm(detinfo::DetectorPropertiesData const &detProp, unsigned int wire, float drift, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:286
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
Set of hits with a 2D structure.
Definition: Cluster.h:69
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:430
geo::WireID const & WireID() const
Initial tdc tick for hit.
Definition: Hit.h:290
unsigned int BackTPC() const
Definition: PmaTrack3D.h:121
void FilterOutSmallParts(detinfo::DetectorPropertiesData const &detProp, double r2d, const std::vector< art::Ptr< recob::Hit >> &hits_in, std::vector< art::Ptr< recob::Hit >> &hits_out)
unsigned int fIniIndex
unsigned int fClIndex
std::vector< IniSeg > fInisegs
bool Validate(detinfo::DetectorPropertiesData const &detProp, std::vector< ems::DirOfGamma * > input, size_t id1, size_t id2, size_t c1, size_t c2, size_t plane3)
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
unsigned int BackCryo() const
Definition: PmaTrack3D.h:122
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
void produce(art::Event &e) override
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
std::vector< Hit2D * > const & GetHits2D() const
Definition: DirOfGamma.h:133
double selectInitialHits(pma::Track3D &trk, unsigned int view=geo::kZ, unsigned int *nused=0) const
void hits()
Definition: readHits.C:15
TCanvas * c1
Definition: plotHisto.C:7
unsigned int fTrkIndex
EMShower3D(fhicl::ParameterSet const &p)
TCanvas * c2
Definition: plot_hist.C:75
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void Make3DSeg(detinfo::DetectorPropertiesData const &detProp, std::vector< ems::DirOfGamma * > pair)
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
std::string fTrk3DModuleLabel
A trajectory in space reconstructed from hits.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:67
double ConvertXToTicks(double X, int p, int t, int c) const
std::vector< Point_t > convertCollToPoint(std::vector< Point > const &coll)
Definition: TrackingTypes.h:68
unsigned int FrontTPC() const
Definition: PmaTrack3D.h:118
size_t LinkCandidates(detinfo::DetectorPropertiesData const &detProp, std::vector< ems::DirOfGamma * > input, size_t id)
unsigned int FrontCryo() const
Definition: PmaTrack3D.h:119
pma::Track3D * buildSegment(const detinfo::DetectorPropertiesData &clockData, const std::vector< art::Ptr< recob::Hit >> &hits_1, const std::vector< art::Ptr< recob::Hit >> &hits_2={}) const
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Declaration of cluster object.
calo::CalorimetryAlg fCalorimetryAlg
std::vector< ems::DirOfGamma * > CollectShower2D(detinfo::DetectorPropertiesData const &detProp, art::Event const &e)
Definition: DirOfGamma.h:22
size_type size() const
Definition: PtrVector.h:302
TTree * t2
Definition: plottest35.C:36
TFile fb("Li6.root")
double ConvertTicksToX(double ticks, int p, int t, int c) const
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
bool GetCloseHits(detinfo::DetectorPropertiesData const &detProp, double r2d, const std::vector< art::Ptr< recob::Hit >> &hits_in, std::vector< size_t > &used, std::vector< art::Ptr< recob::Hit >> &hits_out)
std::vector< IniSeg > fPMA3D
Implementation of the Projection Matching Algorithm.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:226
recob::Track ConvertFrom(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, pma::Track3D &src)
std::vector< size_t > fTracksNotUsed
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Utility object to perform functions of association.
double dist(const TReal *x, const TReal *y, const unsigned int dimension)
Contains all timing reference information for the detector.
Provides recob::Track data product.
pma::ProjectionMatchingAlg fProjectionMatchingAlg
recob::Track ConvertFrom2(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, pma::Track3D &src)
std::vector< size_t > fClustersNotUsed
TVector2 GetProjectionToPlane(const TVector3 &p, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:263
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
pma::Hit3D const * back() const
Definition: PmaTrack3D.h:88
art::Ptr< recob::Hit > const & Hit2DPtr() const
Definition: PmaHit3D.h:48
bool Has(const std::vector< size_t > &v, size_t idx)
std::vector< IniSeg > fSeltracks
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
Definition: Track.h:992
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
Definition: PmaTrack3D.cxx:527
void Reoptimize(detinfo::DetectorPropertiesData const &detProp)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
unsigned int TPC() const noexcept
Definition: PmaHit3D.h:59
Float_t e
Definition: plot.C:35
size_t size() const
Definition: PmaTrack3D.h:89
std::string fCluModuleLabel
Float_t track
Definition: plot.C:35
void clear()
Definition: PtrVector.h:533
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
The data type to uniquely identify a cryostat.
Definition: geo_types.h:187