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