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