All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrajCluster_module.cc
Go to the documentation of this file.
1 /**
2  * @file TrajCluster_module.cc
3  * @brief Cluster finder using trajectories
4  * @author Bruce Baller (baller@fnal.gov)
5  *
6 *
7  */
8 
9 // C/C++ standard libraries
10 #include <string>
11 
12 // Framework libraries
13 #include "art/Framework/Core/EDProducer.h"
14 #include "art/Framework/Core/ModuleMacros.h"
15 #include "art/Framework/Principal/Event.h"
16 #include "art_root_io/TFileService.h"
17 #include "canvas/Persistency/Common/FindManyP.h"
18 #include "canvas/Utilities/InputTag.h"
19 #include "fhiclcpp/ParameterSet.h"
20 
21 // LArSoft includes
37 
38 //root includes
39 #include "TTree.h"
40 
41 // ... more includes in the implementation section
42 
43 namespace cluster {
44  /**
45  * @brief Produces clusters by the TrajCluster algorithm
46  *
47  * Configuration parameters
48  * -------------------------
49  *
50  * - *HitFinderModuleLabel* (InputTag, mandatory): label of the hits to be
51  * used as input (usually the label of the producing module is enough)
52  * - *TrajClusterAlg* (parameter set, mandatory): full configuration for
53  * TrajClusterAlg algorithm
54  *
55  */
56  class TrajCluster : public art::EDProducer {
57  public:
58  explicit TrajCluster(fhicl::ParameterSet const& pset);
59 
60  private:
61  void produce(art::Event& evt) override;
62  void beginJob() override;
63  void endJob() override;
64 
65  tca::TrajClusterAlg fTCAlg; // define TrajClusterAlg object
66  TTree* showertree;
67  void GetHits(const std::vector<recob::Hit>& inputHits,
68  const geo::TPCID& tpcid,
69  std::vector<std::vector<unsigned int>>& tpcHits);
70  void GetHits(const std::vector<recob::Hit>& inputHits,
71  const geo::TPCID& tpcid,
72  const std::vector<recob::Slice>& inputSlices,
73  art::FindManyP<recob::Hit>& hitFromSlc,
74  std::vector<std::vector<unsigned int>>& tpcHits,
75  std::vector<int>& slcIDs);
76 
77  art::InputTag fHitModuleLabel;
78  art::InputTag fSliceModuleLabel;
79  art::InputTag fSpacePointModuleLabel;
80  art::InputTag fSpacePointHitAssnLabel;
81 
82  unsigned int fMaxSliceHits;
86  }; // class TrajCluster
87 
88 } // namespace cluster
89 
90 //******************************************************************************
91 //*** implementation
92 //***
93 
94 // C/C++ standard libraries
95 #include <memory> // std::move()
96 
97 // Framework libraries
98 #include "art/Framework/Principal/Handle.h"
99 #include "canvas/Persistency/Common/Assns.h"
100 #include "canvas/Persistency/Common/FindManyP.h"
101 #include "canvas/Utilities/Exception.h"
102 
103 //LArSoft includes
105 #include "lardata/ArtDataHelper/HitCreator.h" // recob::HitCollectionAssociator
109 #include "lardataobj/RecoBase/Hit.h"
113 
114 namespace cluster {
115 
116  struct HitLoc {
117  unsigned int index; // index of this entry in a sort vector
118  unsigned int ctp; // encoded Cryostat, TPC and Plane
119  unsigned int wire;
120  int tick; // hit StartTick using typedef int TDCtick_t in RawTypes.h
121  short localIndex; // defined in Hit.h
122  };
123 
124  //----------------------------------------------------------------------------
125  bool
126  SortHits(HitLoc const& h1, HitLoc const& h2)
127  {
128  // sort by hit location (Cryostat, TPC, Plane, Wire, StartTick, hit LocalIndex)
129  if (h1.ctp != h2.ctp) return h1.ctp < h2.ctp;
130  if (h1.wire != h2.wire) return h1.wire < h2.wire;
131  if (h1.tick != h2.tick) return h1.tick < h2.tick;
132  return h1.localIndex < h2.localIndex;
133  } // SortHits
134 
135  //----------------------------------------------------------------------------
136  TrajCluster::TrajCluster(fhicl::ParameterSet const& pset)
137  : EDProducer{pset}, fTCAlg{pset.get<fhicl::ParameterSet>("TrajClusterAlg")}
138  {
139  fHitModuleLabel = "NA";
140  if (pset.has_key("HitModuleLabel")) fHitModuleLabel = pset.get<art::InputTag>("HitModuleLabel");
141  fSliceModuleLabel = "NA";
142  if (pset.has_key("SliceModuleLabel"))
143  fSliceModuleLabel = pset.get<art::InputTag>("SliceModuleLabel");
144  fMaxSliceHits = UINT_MAX;
145  if (pset.has_key("MaxSliceHits")) fMaxSliceHits = pset.get<unsigned int>("MaxSliceHits");
146  fSpacePointModuleLabel = "NA";
147  if (pset.has_key("SpacePointModuleLabel"))
148  fSpacePointModuleLabel = pset.get<art::InputTag>("SpacePointModuleLabel");
149  fSpacePointHitAssnLabel = "NA";
150  if (pset.has_key("SpacePointHitAssnLabel"))
151  fSpacePointHitAssnLabel = pset.get<art::InputTag>("SpacePointHitAssnLabel");
152  fDoWireAssns = pset.get<bool>("DoWireAssns", true);
153  fDoRawDigitAssns = pset.get<bool>("DoRawDigitAssns", true);
154  fSaveAll2DVertices = false;
155  if (pset.has_key("SaveAll2DVertices")) fSaveAll2DVertices = pset.get<bool>("SaveAll2DVertices");
156 
157  // let HitCollectionAssociator declare that we are going to produce
158  // hits and associations with wires and raw digits
159  // (with no particular product label)
161  producesCollector(), "", fDoWireAssns, fDoRawDigitAssns);
162 
163  produces<std::vector<recob::Cluster>>();
164  produces<std::vector<recob::Vertex>>();
165  produces<std::vector<recob::EndPoint2D>>();
166  produces<std::vector<recob::Seed>>();
167  produces<std::vector<recob::Shower>>();
168  produces<art::Assns<recob::Cluster, recob::Hit>>();
169  produces<art::Assns<recob::Cluster, recob::EndPoint2D, unsigned short>>();
170  produces<art::Assns<recob::Cluster, recob::Vertex, unsigned short>>();
171  produces<art::Assns<recob::Shower, recob::Hit>>();
172 
173  produces<std::vector<recob::PFParticle>>();
174  produces<art::Assns<recob::PFParticle, recob::Cluster>>();
175  produces<art::Assns<recob::PFParticle, recob::Shower>>();
176  produces<art::Assns<recob::PFParticle, recob::Vertex>>();
177  produces<art::Assns<recob::PFParticle, recob::Seed>>();
178 
179  produces<art::Assns<recob::Slice, recob::Cluster>>();
180  produces<art::Assns<recob::Slice, recob::PFParticle>>();
181  produces<art::Assns<recob::Slice, recob::Hit>>();
182 
183  produces<std::vector<anab::CosmicTag>>();
184  produces<art::Assns<recob::PFParticle, anab::CosmicTag>>();
185 
186  // www: declear/create SpacePoint and association between SpacePoint and Hits from TrajCluster (Hit->SpacePoint)
187  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
188  } // TrajCluster::TrajCluster()
189 
190  //----------------------------------------------------------------------------
191  void
193  {
194  art::ServiceHandle<art::TFileService const> tfs;
195 
196  showertree = tfs->make<TTree>("showervarstree", "showerVarsTree");
198  }
199 
200  //----------------------------------------------------------------------------
201  void
203  {
204  std::vector<unsigned int> const& fAlgModCount = fTCAlg.GetAlgModCount();
205  std::vector<std::string> const& fAlgBitNames = fTCAlg.GetAlgBitNames();
206  if (fAlgBitNames.size() != fAlgModCount.size()) return;
207  mf::LogVerbatim myprt("TC");
208  myprt << "TrajCluster algorithm counts\n";
209  unsigned short icol = 0;
210  for (unsigned short ib = 0; ib < fAlgModCount.size(); ++ib) {
211  if (ib == tca::kKilled) continue;
212  myprt << std::left << std::setw(18) << fAlgBitNames[ib] << std::right << std::setw(10)
213  << fAlgModCount[ib] << " ";
214  ++icol;
215  if (icol == 4) {
216  myprt << "\n";
217  icol = 0;
218  }
219  } // ib
220  } // endJob
221 
222  //----------------------------------------------------------------------------
223  void
225  {
226  // Get a single hit collection from a HitsModuleLabel or multiple sets of "sliced" hits
227  // (aka clusters of hits that are close to each other in 3D) from a SliceModuleLabel.
228  // A pointer to the full hit collection is passed to TrajClusterAlg. The hits that are
229  // in each slice are reconstructed to find 2D trajectories (that become clusters),
230  // 2D vertices (EndPoint2D), 3D vertices, PFParticles and Showers. These data products
231  // are then collected and written to the event. Each slice is considered as an independent
232  // collection of hits with the additional requirement that all hits in a slice reside in
233  // one TPC
234 
235  // pointers to the slices in the event
236  std::vector<art::Ptr<recob::Slice>> slices;
237  std::vector<int> slcIDs;
238  unsigned int nInputHits = 0;
239 
240  // get a reference to the Hit collection
241  auto inputHits = art::Handle<std::vector<recob::Hit>>();
242  if (!evt.getByLabel(fHitModuleLabel, inputHits))
243  throw cet::exception("TrajClusterModule")
244  << "Failed to get a handle to hit collection '" << fHitModuleLabel.label() << "'\n";
245  nInputHits = (*inputHits).size();
246  if (!fTCAlg.SetInputHits(*inputHits, evt.run(), evt.event()))
247  throw cet::exception("TrajClusterModule")
248  << "Failed to process hits from '" << fHitModuleLabel.label() << "'\n";
249  // Try to determine the source of the hit collection using the assumption that it was
250  // derived from gaushit. If this is successful, pass the handle to TrajClusterAlg to
251  // recover hits that were incorrectly removed by disambiguation (DUNE)
252  if (fHitModuleLabel != "gaushit") {
253  auto sourceHits = art::Handle<std::vector<recob::Hit>>();
254  art::InputTag sourceModuleLabel("gaushit");
255  if (evt.getByLabel(sourceModuleLabel, sourceHits)) fTCAlg.SetSourceHits(*sourceHits);
256  } // look for gaushit collection
257 
258  // get an optional reference to the Slice collection
259  auto inputSlices = art::Handle<std::vector<recob::Slice>>();
260  if (fSliceModuleLabel != "NA") {
262  if (!evt.getByLabel(fSliceModuleLabel, inputSlices))
263  throw cet::exception("TrajClusterModule") << "Failed to get a inputSlices";
264  } // fSliceModuleLabel specified
265 
266  // get an optional reference to the SpacePoint collection
267  auto InputSpts = art::Handle<std::vector<recob::SpacePoint>>();
268  if (fSpacePointModuleLabel != "NA") {
269  if (!evt.getByLabel(fSpacePointModuleLabel, InputSpts))
270  throw cet::exception("TrajClusterModule") << "Failed to get a handle to SpacePoints\n";
271  tca::evt.sptHits.resize((*InputSpts).size(), {{UINT_MAX, UINT_MAX, UINT_MAX}});
272  art::FindManyP<recob::Hit> hitsFromSpt(InputSpts, evt, fSpacePointHitAssnLabel);
273  // TrajClusterAlg doesn't use the SpacePoint positions (only the assns to hits) but pass it
274  // anyway in case it is useful
275  fTCAlg.SetInputSpts(*InputSpts);
276  if (!hitsFromSpt.isValid())
277  throw cet::exception("TrajClusterModule")
278  << "Failed to get a handle to SpacePoint -> Hit assns\n";
279  // ensure that the assn is to the inputHit collection
280  auto& firstHit = hitsFromSpt.at(0)[0];
281  if (firstHit.id() != inputHits.id())
282  throw cet::exception("TrajClusterModule")
283  << "The SpacePoint -> Hit assn doesn't reference the input hit collection\n";
284  tca::evt.sptHits.resize((*InputSpts).size(), {{UINT_MAX, UINT_MAX, UINT_MAX}});
285  for (unsigned int isp = 0; isp < (*InputSpts).size(); ++isp) {
286  auto& hits = hitsFromSpt.at(isp);
287  for (unsigned short iht = 0; iht < hits.size(); ++iht) {
288  unsigned short plane = hits[iht]->WireID().Plane;
289  tca::evt.sptHits[isp][plane] = hits[iht].key();
290  } // iht
291  } // isp
292  } // fSpacePointModuleLabel specified
293 
294  if (nInputHits > 0) {
295  auto const clockData =
296  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
297  auto const detProp =
298  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
299  auto const* geom = lar::providerFrom<geo::Geometry>();
300  for (const auto& tpcid : geom->IterateTPCIDs()) {
301  // ignore protoDUNE dummy TPCs
302  if (geom->TPC(tpcid).DriftDistance() < 25.0) continue;
303  // a vector for the subset of hits in each slice in a TPC
304  // slice hits in this tpc
305  std::vector<std::vector<unsigned int>> sltpcHits;
306  if (inputSlices.isValid()) {
307  // get hits in this TPC and slice
308  art::FindManyP<recob::Hit> hitFromSlc(inputSlices, evt, fSliceModuleLabel);
309  GetHits(*inputHits, tpcid, *inputSlices, hitFromSlc, sltpcHits, slcIDs);
310  }
311  else {
312  // get hits in this TPC
313  // All hits are in one "fake" slice
314  GetHits(*inputHits, tpcid, sltpcHits);
315  slcIDs.resize(1);
316  slcIDs[0] = 1;
317  }
318  if (sltpcHits.empty()) continue;
319  for (unsigned short isl = 0; isl < sltpcHits.size(); ++isl) {
320  auto& tpcHits = sltpcHits[isl];
321  if (tpcHits.empty()) continue;
322  // only reconstruct slices with MC-matched hits?
323  // sort the slice hits by Cryostat, TPC, Wire, Plane, Start Tick and LocalIndex.
324  // This assumes that hits with larger LocalIndex are at larger Tick.
325  std::vector<HitLoc> sortVec(tpcHits.size());
326  for (unsigned int indx = 0; indx < tpcHits.size(); ++indx) {
327  auto& hit = (*inputHits)[tpcHits[indx]];
328  sortVec[indx].index = indx;
329  sortVec[indx].ctp = tca::EncodeCTP(hit.WireID());
330  sortVec[indx].wire = hit.WireID().Wire;
331  sortVec[indx].tick = hit.StartTick();
332  sortVec[indx].localIndex = hit.LocalIndex();
333  } // iht
334  std::sort(sortVec.begin(), sortVec.end(), SortHits);
335  std::vector tmp = tpcHits;
336  for (unsigned int ii = 0; ii < tpcHits.size(); ++ii)
337  tpcHits[ii] = tmp[sortVec[ii].index];
338  // clear the temp vector
339  tmp.resize(0);
340  sortVec.resize(0);
341  // look for a debug hit
342  if (tca::tcc.dbgStp) {
343  tca::debug.Hit = UINT_MAX;
344  for (unsigned short indx = 0; indx < tpcHits.size(); ++indx) {
345  auto& hit = (*inputHits)[tpcHits[indx]];
346  if ((int)hit.WireID().TPC == tca::debug.TPC &&
347  (int)hit.WireID().Plane == tca::debug.Plane &&
348  (int)hit.WireID().Wire == tca::debug.Wire &&
349  hit.PeakTime() > tca::debug.Tick - 10 && hit.PeakTime() < tca::debug.Tick + 10) {
350  std::cout << "Debug hit " << tpcHits[indx] << " found in slice ID " << slcIDs[isl];
351  std::cout << " RMS " << hit.RMS();
352  std::cout << " Multiplicity " << hit.Multiplicity();
353  std::cout << " GoodnessOfFit " << hit.GoodnessOfFit();
354  std::cout << "\n";
355  tca::debug.Hit = tpcHits[indx];
356  break;
357  } // Look for debug hit
358  } // iht
359  } // tca::tcc.dbgStp
360  fTCAlg.RunTrajClusterAlg(clockData, detProp, tpcHits, slcIDs[isl]);
361  } // isl
362  } // TPC
363  // stitch PFParticles between TPCs, create PFP start vertices, etc
365  if (tca::tcc.dbgSummary) tca::PrintAll(detProp, "TCM");
366  } // nInputHits > 0
367 
368  // Vectors to hold all data products that will go into the event
369  std::vector<recob::Hit> hitCol; // output hit collection
370  std::vector<recob::Cluster> clsCol;
371  std::vector<recob::PFParticle> pfpCol;
372  std::vector<recob::Vertex> vx3Col;
373  std::vector<recob::EndPoint2D> vx2Col;
374  std::vector<recob::Seed> sedCol;
375  std::vector<recob::Shower> shwCol;
376  std::vector<anab::CosmicTag> ctCol;
377  // a vector to correlate inputHits with output hits
378  std::vector<unsigned int> newIndex(nInputHits, UINT_MAX);
379 
380  // assns for those data products
381  // Cluster -> ...
382  std::unique_ptr<art::Assns<recob::Cluster, recob::Hit>> cls_hit_assn(
383  new art::Assns<recob::Cluster, recob::Hit>);
384  // unsigned short is the end to which a vertex is attached
385  std::unique_ptr<art::Assns<recob::Cluster, recob::EndPoint2D, unsigned short>> cls_vx2_assn(
386  new art::Assns<recob::Cluster, recob::EndPoint2D, unsigned short>);
387  std::unique_ptr<art::Assns<recob::Cluster, recob::Vertex, unsigned short>> cls_vx3_assn(
388  new art::Assns<recob::Cluster, recob::Vertex, unsigned short>);
389  // Shower -> ...
390  std::unique_ptr<art::Assns<recob::Shower, recob::Hit>> shwr_hit_assn(
391  new art::Assns<recob::Shower, recob::Hit>);
392  // PFParticle -> ...
393  std::unique_ptr<art::Assns<recob::PFParticle, recob::Cluster>> pfp_cls_assn(
394  new art::Assns<recob::PFParticle, recob::Cluster>);
395  std::unique_ptr<art::Assns<recob::PFParticle, recob::Shower>> pfp_shwr_assn(
396  new art::Assns<recob::PFParticle, recob::Shower>);
397  std::unique_ptr<art::Assns<recob::PFParticle, recob::Vertex>> pfp_vx3_assn(
398  new art::Assns<recob::PFParticle, recob::Vertex>);
399  std::unique_ptr<art::Assns<recob::PFParticle, anab::CosmicTag>> pfp_cos_assn(
400  new art::Assns<recob::PFParticle, anab::CosmicTag>);
401  std::unique_ptr<art::Assns<recob::PFParticle, recob::Seed>> pfp_sed_assn(
402  new art::Assns<recob::PFParticle, recob::Seed>);
403  // Slice -> ...
404  std::unique_ptr<art::Assns<recob::Slice, recob::Cluster>> slc_cls_assn(
405  new art::Assns<recob::Slice, recob::Cluster>);
406  std::unique_ptr<art::Assns<recob::Slice, recob::PFParticle>> slc_pfp_assn(
407  new art::Assns<recob::Slice, recob::PFParticle>);
408  std::unique_ptr<art::Assns<recob::Slice, recob::Hit>> slc_hit_assn(
409  new art::Assns<recob::Slice, recob::Hit>);
410  // www: Hit -> SpacePoint
411  std::unique_ptr<art::Assns<recob::SpacePoint, recob::Hit>> sp_hit_assn(
412  new art::Assns<recob::SpacePoint, recob::Hit>);
413 
414  // temp struct to get the index of a 2D (or 3D vertex) into vx2Col (or vx3Col)
415  // given a slice index and a vertex ID (not UID)
416  struct slcVxStruct {
417  unsigned short slIndx;
418  int ID;
419  unsigned short vxColIndx;
420  };
421  std::vector<slcVxStruct> vx2StrList;
422  // vector to map 3V UID -> ID in each sub-slice
423  std::vector<slcVxStruct> vx3StrList;
424 
425  if (nInputHits > 0) {
426  unsigned short nSlices = fTCAlg.GetSlicesSize();
427  // define a hit collection begin index to pass to CreateAssn for each cluster
428  unsigned int hitColBeginIndex = 0;
429  for (unsigned short isl = 0; isl < nSlices; ++isl) {
430  unsigned short slcIndex = 0;
431  if (!slices.empty()) {
432  for (slcIndex = 0; slcIndex < slices.size(); ++slcIndex)
433  if (slices[slcIndex]->ID() == slcIDs[isl]) break;
434  if (slcIndex == slices.size()) continue;
435  }
436  auto& slc = fTCAlg.GetSlice(isl);
437  // See if there was a serious reconstruction failure that made the sub-slice invalid
438  if (!slc.isValid) continue;
439  // make EndPoint2Ds
440  for (auto& vx2 : slc.vtxs) {
441  if (vx2.ID <= 0) continue;
442  // skip complete 2D vertices?
443  if (!fSaveAll2DVertices && vx2.Vx3ID != 0) continue;
444  unsigned int vtxID = vx2.UID;
445  unsigned int wire = std::nearbyint(vx2.Pos[0]);
446  geo::PlaneID plID = tca::DecodeCTP(vx2.CTP);
447  geo::WireID wID = geo::WireID(plID.Cryostat, plID.TPC, plID.Plane, wire);
448  geo::View_t view = tca::tcc.geom->View(wID);
449  vx2Col.emplace_back((double)vx2.Pos[1] / tca::tcc.unitsPerTick, // Time
450  wID, // WireID
451  vx2.Score, // strength = score
452  vtxID, // ID
453  view, // View
454  0); // total charge - not relevant
455 
456  // fill the mapping struct
457  slcVxStruct tmp;
458  tmp.slIndx = isl;
459  tmp.ID = vx2.ID;
460  tmp.vxColIndx = vx2Col.size() - 1;
461  vx2StrList.push_back(tmp);
462 
463  } // vx2
464  // make Vertices
465  for (auto& vx3 : slc.vtx3s) {
466  if (vx3.ID <= 0) continue;
467  // ignore incomplete vertices
468  if (vx3.Wire >= 0) continue;
469  unsigned int vtxID = vx3.UID;
470  double xyz[3];
471  xyz[0] = vx3.X;
472  xyz[1] = vx3.Y;
473  xyz[2] = vx3.Z;
474  vx3Col.emplace_back(xyz, vtxID);
475  // fill the mapping struct
476  slcVxStruct tmp;
477  tmp.slIndx = isl;
478  tmp.ID = vx3.ID;
479  tmp.vxColIndx = vx3Col.size() - 1;
480  vx3StrList.push_back(tmp);
481  } // vx3
482  // Convert the tjs to clusters
483  for (auto& tj : slc.tjs) {
484  if (tj.AlgMod[tca::kKilled]) continue;
485  hitColBeginIndex = hitCol.size();
486  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
487  auto& tp = tj.Pts[ipt];
488  if (tp.Chg <= 0) continue;
489  // index of inputHits indices of hits used in one TP
490  std::vector<unsigned int> tpHits;
491  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
492  if (!tp.UseHit[ii]) continue;
493  if (tp.Hits[ii] > slc.slHits.size() - 1) { break; } // bad slHits index
494  unsigned int allHitsIndex = slc.slHits[tp.Hits[ii]].allHitsIndex;
495  if (allHitsIndex > nInputHits - 1) { break; } // bad allHitsIndex
496  tpHits.push_back(allHitsIndex);
497  if (newIndex[allHitsIndex] != UINT_MAX) {
498  std::cout << "Bad Slice " << isl << " tp.Hits " << tp.Hits[ii] << " allHitsIndex "
499  << allHitsIndex;
500  std::cout << " old newIndex " << newIndex[allHitsIndex];
501  auto& oldhit = (*inputHits)[allHitsIndex];
502  std::cout << " old " << oldhit.WireID().Plane << ":" << oldhit.WireID().Wire << ":"
503  << (int)oldhit.PeakTime();
504  auto& newhit = hitCol[newIndex[allHitsIndex]];
505  std::cout << " new " << newhit.WireID().Plane << ":" << newhit.WireID().Wire << ":"
506  << (int)newhit.PeakTime();
507  std::cout << " hitCol size " << hitCol.size();
508  std::cout << "\n";
509  break;
510  }
511  } // ii
512  // Let the alg define the hit either by merging multiple hits or by a simple copy
513  // of a single hit from inputHits
514  // Merge hits in the TP that are on the same wire or create hits on multiple wires
515  // and update the old hits -> new hits assn (newIndex)
516  if (tj.AlgMod[tca::kHaloTj]) {
517  // dressed muon - don't merge hits
518  for (auto iht : tpHits) {
519  hitCol.push_back((*inputHits)[iht]);
520  newIndex[iht] = hitCol.size() - 1;
521  } // iht
522  }
523  else {
524  fTCAlg.MergeTPHits(tpHits, hitCol, newIndex);
525  }
526  } // tp
527  if (hitCol.empty()) continue;
528  // Sum the charge and make the associations
529  float sumChg = 0;
530  float sumADC = 0;
531  for (unsigned int indx = hitColBeginIndex; indx < hitCol.size(); ++indx) {
532  auto& hit = hitCol[indx];
533  sumChg += hit.Integral();
534  sumADC += hit.SummedADC();
535  if (!slices.empty() &&
536  !util::CreateAssn(*this, evt, hitCol, slices[slcIndex], *slc_hit_assn, indx)) {
537  throw art::Exception(art::errors::ProductRegistrationFailure)
538  << "Failed to associate hits with Slice";
539  }
540  } // indx
541  geo::View_t view = hitCol[hitColBeginIndex].View();
542  auto& firstTP = tj.Pts[tj.EndPt[0]];
543  auto& lastTP = tj.Pts[tj.EndPt[1]];
544  int clsID = tj.UID;
545  if (tj.AlgMod[tca::kShowerLike]) clsID = -clsID;
546  // dressed muon - give the halo cluster the same ID as the parent
547  if (tj.AlgMod[tca::kHaloTj]) clsID = -tj.ParentID;
548  unsigned int nclhits = hitCol.size() - hitColBeginIndex + 1;
549  clsCol.emplace_back(firstTP.Pos[0], // Start wire
550  0, // sigma start wire
551  firstTP.Pos[1] / tca::tcc.unitsPerTick, // start tick
552  0, // sigma start tick
553  firstTP.AveChg, // start charge
554  firstTP.Ang, // start angle
555  0, // start opening angle (0 for line-like clusters)
556  lastTP.Pos[0], // end wire
557  0, // sigma end wire
558  lastTP.Pos[1] / tca::tcc.unitsPerTick, // end tick
559  0, // sigma end tick
560  lastTP.AveChg, // end charge
561  lastTP.Ang, // end angle
562  0, // end opening angle (0 for line-like clusters)
563  sumChg, // integral
564  0, // sigma integral
565  sumADC, // summed ADC
566  0, // sigma summed ADC
567  nclhits, // n hits
568  0, // wires over hits
569  0, // width (0 for line-like clusters)
570  clsID, // ID from TrajClusterAlg
571  view, // view
572  tca::DecodeCTP(tj.CTP), // planeID
573  recob::Cluster::Sentry // sentry
574  );
575  if (!util::CreateAssn(
576  *this, evt, clsCol, hitCol, *cls_hit_assn, hitColBeginIndex, hitCol.size())) {
577  throw art::Exception(art::errors::ProductRegistrationFailure)
578  << "Failed to associate hits with cluster ID " << tj.UID;
579  } // exception
580  // make Slice -> cluster assn
581  if (!slices.empty()) {
582  if (!util::CreateAssn(*this, evt, clsCol, slices[slcIndex], *slc_cls_assn)) {
583  throw art::Exception(art::errors::ProductRegistrationFailure)
584  << "Failed to associate slice with PFParticle";
585  } // exception
586  } // slices exist
587  // Make cluster -> 2V and cluster -> 3V assns
588  for (unsigned short end = 0; end < 2; ++end) {
589  if (tj.VtxID[end] <= 0) continue;
590  for (auto& vx2str : vx2StrList) {
591  if (vx2str.slIndx != isl) continue;
592  if (vx2str.ID != tj.VtxID[end]) continue;
593  if (!util::CreateAssnD(
594  *this, evt, *cls_vx2_assn, clsCol.size() - 1, vx2str.vxColIndx, end)) {
595  throw art::Exception(art::errors::ProductRegistrationFailure)
596  << "Failed to associate cluster " << tj.UID << " with EndPoint2D";
597  } // exception
598  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
599  if (vx2.Vx3ID > 0) {
600  for (auto vx3str : vx3StrList) {
601  if (vx3str.slIndx != isl) continue;
602  if (vx3str.ID != vx2.Vx3ID) continue;
603  if (!util::CreateAssnD(
604  *this, evt, *cls_vx3_assn, clsCol.size() - 1, vx3str.vxColIndx, end)) {
605  throw art::Exception(art::errors::ProductRegistrationFailure)
606  << "Failed to associate cluster " << tj.UID << " with Vertex";
607  } // exception
608  break;
609  } // vx3str
610  } // vx2.Vx3ID > 0
611  break;
612  } // vx2str
613  } // end
614  } // tj (aka cluster)
615 
616  // make Showers
617  for (auto& ss3 : slc.showers) {
618  if (ss3.ID <= 0) continue;
620  shower.set_id(ss3.UID);
621  shower.set_total_energy(ss3.Energy);
622  shower.set_total_energy_err(ss3.EnergyErr);
623  shower.set_total_MIPenergy(ss3.MIPEnergy);
624  shower.set_total_MIPenergy_err(ss3.MIPEnergyErr);
625  shower.set_total_best_plane(ss3.BestPlane);
626  TVector3 dir = {ss3.Dir[0], ss3.Dir[1], ss3.Dir[2]};
627  shower.set_direction(dir);
628  TVector3 dirErr = {ss3.DirErr[0], ss3.DirErr[1], ss3.DirErr[2]};
629  shower.set_direction_err(dirErr);
630  TVector3 pos = {ss3.Start[0], ss3.Start[1], ss3.Start[2]};
631  shower.set_start_point(pos);
632  TVector3 posErr = {ss3.StartErr[0], ss3.StartErr[1], ss3.StartErr[2]};
633  shower.set_start_point_err(posErr);
634  shower.set_dedx(ss3.dEdx);
635  shower.set_dedx_err(ss3.dEdxErr);
636  shower.set_length(ss3.Len);
637  shower.set_open_angle(ss3.OpenAngle);
638  shwCol.push_back(shower);
639  // make the shower - hit association
640  std::vector<unsigned int> shwHits(ss3.Hits.size());
641  for (unsigned int iht = 0; iht < ss3.Hits.size(); ++iht)
642  shwHits[iht] = newIndex[ss3.Hits[iht]];
644  *this, evt, *shwr_hit_assn, shwCol.size() - 1, shwHits.begin(), shwHits.end())) {
645  throw art::Exception(art::errors::ProductRegistrationFailure)
646  << "Failed to associate hits with Shower";
647  } // exception
648  } // ss3
649  } // slice isl
650 
651  // Add PFParticles now that clsCol is filled
652  for (unsigned short isl = 0; isl < nSlices; ++isl) {
653  unsigned short slcIndex = 0;
654  if (!slices.empty()) {
655  for (slcIndex = 0; slcIndex < slices.size(); ++slcIndex)
656  if (slices[slcIndex]->ID() == slcIDs[isl]) break;
657  if (slcIndex == slices.size()) continue;
658  }
659  auto& slc = fTCAlg.GetSlice(isl);
660  // See if there was a serious reconstruction failure that made the slice invalid
661  if (!slc.isValid) continue;
662  // make PFParticles
663  for (size_t ipfp = 0; ipfp < slc.pfps.size(); ++ipfp) {
664  auto& pfp = slc.pfps[ipfp];
665  if (pfp.ID <= 0) continue;
666  // parents and daughters are indexed within a slice so find the index offset in pfpCol
667  size_t self = pfpCol.size();
668  size_t offset = self - ipfp;
669  size_t parentIndex = UINT_MAX;
670  if (pfp.ParentUID > 0) parentIndex = pfp.ParentUID + offset - 1;
671  std::vector<size_t> dtrIndices(pfp.DtrUIDs.size());
672  for (unsigned short idtr = 0; idtr < pfp.DtrUIDs.size(); ++idtr)
673  dtrIndices[idtr] = pfp.DtrUIDs[idtr] + offset - 1;
674  pfpCol.emplace_back(pfp.PDGCode, self, parentIndex, dtrIndices);
675  auto pos = PosAtEnd(pfp, 0);
676  auto dir = DirAtEnd(pfp, 0);
677  double sp[] = {pos[0], pos[1], pos[2]};
678  double sd[] = {dir[0], dir[1], dir[2]};
679  double spe[] = {0., 0., 0.};
680  double sde[] = {0., 0., 0.};
681  sedCol.emplace_back(sp, sd, spe, sde);
682  // PFParticle -> clusters
683  std::vector<unsigned int> clsIndices;
684  for (auto tuid : pfp.TjUIDs) {
685  unsigned int clsIndex = 0;
686  for (clsIndex = 0; clsIndex < clsCol.size(); ++clsIndex)
687  if (abs(clsCol[clsIndex].ID()) == tuid) break;
688  if (clsIndex == clsCol.size()) continue;
689  clsIndices.push_back(clsIndex);
690  } // tjid
691  if (!util::CreateAssn(*this,
692  evt,
693  *pfp_cls_assn,
694  pfpCol.size() - 1,
695  clsIndices.begin(),
696  clsIndices.end())) {
697  throw art::Exception(art::errors::ProductRegistrationFailure)
698  << "Failed to associate clusters with PFParticle";
699  } // exception
700  // PFParticle -> Vertex
701  if (pfp.Vx3ID[0] > 0) {
702  for (auto vx3str : vx3StrList) {
703  if (vx3str.slIndx != isl) continue;
704  if (vx3str.ID != pfp.Vx3ID[0]) continue;
705  std::vector<unsigned short> indx(1, vx3str.vxColIndx);
706  if (!util::CreateAssn(
707  *this, evt, *pfp_vx3_assn, pfpCol.size() - 1, indx.begin(), indx.end())) {
708  throw art::Exception(art::errors::ProductRegistrationFailure)
709  << "Failed to associate PFParticle " << pfp.UID << " with Vertex";
710  } // exception
711  break;
712  } // vx3Index
713  } // start vertex exists
714  // PFParticle -> Seed
715  if (!sedCol.empty()) {
716  if (!util::CreateAssn(*this,
717  evt,
718  pfpCol,
719  sedCol,
720  *pfp_sed_assn,
721  sedCol.size() - 1,
722  sedCol.size(),
723  pfpCol.size() - 1)) {
724  throw art::Exception(art::errors::ProductRegistrationFailure)
725  << "Failed to associate seed with PFParticle";
726  } // exception
727  } // seeds exist
728  // PFParticle -> Slice
729  if (!slices.empty()) {
730  if (!util::CreateAssn(*this, evt, pfpCol, slices[slcIndex], *slc_pfp_assn)) {
731  throw art::Exception(art::errors::ProductRegistrationFailure)
732  << "Failed to associate slice with PFParticle";
733  } // exception
734  } // slices exist
735  // PFParticle -> Shower
736  if (pfp.PDGCode == 1111) {
737  std::vector<unsigned short> shwIndex(1, 0);
738  for (auto& ss3 : slc.showers) {
739  if (ss3.ID <= 0) continue;
740  if (ss3.PFPIndex == ipfp) break;
741  ++shwIndex[0];
742  } // ss3
743  if (shwIndex[0] < shwCol.size()) {
744  if (!util::CreateAssn(*this,
745  evt,
746  *pfp_shwr_assn,
747  pfpCol.size() - 1,
748  shwIndex.begin(),
749  shwIndex.end())) {
750  throw art::Exception(art::errors::ProductRegistrationFailure)
751  << "Failed to associate shower with PFParticle";
752  } // exception
753  } // valid shwIndex
754  } // pfp -> Shower
755  // PFParticle cosmic tag
756  if (tca::tcc.modes[tca::kTagCosmics]) {
757  std::vector<float> tempPt1, tempPt2;
758  tempPt1.push_back(-999);
759  tempPt1.push_back(-999);
760  tempPt1.push_back(-999);
761  tempPt2.push_back(-999);
762  tempPt2.push_back(-999);
763  tempPt2.push_back(-999);
764  ctCol.emplace_back(tempPt1, tempPt2, pfp.CosmicScore, anab::CosmicTagID_t::kNotTagged);
765  if (!util::CreateAssn(
766  *this, evt, pfpCol, ctCol, *pfp_cos_assn, ctCol.size() - 1, ctCol.size())) {
767  throw art::Exception(art::errors::ProductRegistrationFailure)
768  << "Failed to associate CosmicTag with PFParticle";
769  }
770  } // cosmic tag
771  } // ipfp
772  } // isl
773 
774  // add the hits that weren't used in any slice to hitCol unless this is a
775  // special debugging mode and would be a waste of time
776  if (!slices.empty() && tca::tcc.recoSlice == 0) {
777  auto inputSlices = evt.getValidHandle<std::vector<recob::Slice>>(fSliceModuleLabel);
778  art::FindManyP<recob::Hit> hitFromSlc(inputSlices, evt, fSliceModuleLabel);
779  for (unsigned int allHitsIndex = 0; allHitsIndex < nInputHits; ++allHitsIndex) {
780  if (newIndex[allHitsIndex] != UINT_MAX) continue;
781  std::vector<unsigned int> oneHit(1, allHitsIndex);
782  fTCAlg.MergeTPHits(oneHit, hitCol, newIndex);
783  // find out which slice it is in
784  bool gotit = false;
785  for (size_t isl = 0; isl < slices.size(); ++isl) {
786  auto& hit_in_slc = hitFromSlc.at(isl);
787  for (auto& hit : hit_in_slc) {
788  if (hit.key() != allHitsIndex) continue;
789  gotit = true;
790  // Slice -> Hit assn
791  if (!util::CreateAssn(*this, evt, hitCol, slices[isl], *slc_hit_assn)) {
792  throw art::Exception(art::errors::ProductRegistrationFailure)
793  << "Failed to associate old Hit with Slice";
794  } // exception
795  break;
796  } // hit
797  if (gotit) break;
798  } // isl
799  } // allHitsIndex
800  } // slices exist
801  else {
802  // no recob::Slices. Just copy the unused hits
803  for (unsigned int allHitsIndex = 0; allHitsIndex < nInputHits; ++allHitsIndex) {
804  if (newIndex[allHitsIndex] != UINT_MAX) continue;
805  std::vector<unsigned int> oneHit(1, allHitsIndex);
806  fTCAlg.MergeTPHits(oneHit, hitCol, newIndex);
807  } // allHitsIndex
808  } // recob::Slices
809  } // input hits exist
810 
811  // www: find spacepoint from hits (inputHits) through SpacePoint->Hit assns, then create association between spacepoint and trajcluster hits (here, hits in hitCol)
812  if (nInputHits > 0) {
813  // www: expecting to find spacepoint from hits (inputHits): SpacePoint->Hit assns
814  if (fSpacePointModuleLabel != "NA") {
815  art::FindManyP<recob::SpacePoint> spFromHit(inputHits, evt, fSpacePointModuleLabel);
816  // www: using sp from hit
817  for (unsigned int allHitsIndex = 0; allHitsIndex < nInputHits; ++allHitsIndex) {
818  if (newIndex[allHitsIndex] == UINT_MAX)
819  continue; // skip hits not used in slice (not TrajCluster hits)
820  auto& sp_from_hit = spFromHit.at(allHitsIndex);
821  for (auto& sp : sp_from_hit) {
822  // SpacePoint -> Hit assn
823  if (!util::CreateAssn(*this, evt, hitCol, sp, *sp_hit_assn, newIndex[allHitsIndex])) {
824  throw art::Exception(art::errors::ProductRegistrationFailure)
825  << "Failed to associate new Hit with SpacePoint";
826  } // exception
827  } // sp
828  } // allHitsIndex
829  } // fSpacePointModuleLabel != "NA"
830  } // nInputHits > 0
831 
832  // clear the alg data structures
834 
835  // convert vectors to unique_ptrs
836  std::unique_ptr<std::vector<recob::Hit>> hcol(new std::vector<recob::Hit>(std::move(hitCol)));
837  std::unique_ptr<std::vector<recob::Cluster>> ccol(
838  new std::vector<recob::Cluster>(std::move(clsCol)));
839  std::unique_ptr<std::vector<recob::EndPoint2D>> v2col(
840  new std::vector<recob::EndPoint2D>(std::move(vx2Col)));
841  std::unique_ptr<std::vector<recob::Vertex>> v3col(
842  new std::vector<recob::Vertex>(std::move(vx3Col)));
843  std::unique_ptr<std::vector<recob::PFParticle>> pcol(
844  new std::vector<recob::PFParticle>(std::move(pfpCol)));
845  std::unique_ptr<std::vector<recob::Seed>> sdcol(
846  new std::vector<recob::Seed>(std::move(sedCol)));
847  std::unique_ptr<std::vector<recob::Shower>> scol(
848  new std::vector<recob::Shower>(std::move(shwCol)));
849  std::unique_ptr<std::vector<anab::CosmicTag>> ctgcol(
850  new std::vector<anab::CosmicTag>(std::move(ctCol)));
851 
852  // move the cluster collection and the associations into the event:
853  if (fHitModuleLabel != "NA") {
854  recob::HitRefinerAssociator shcol(evt, fHitModuleLabel, fDoWireAssns, fDoRawDigitAssns);
855  shcol.use_hits(std::move(hcol));
856  shcol.put_into(evt);
857  }
858  else {
859  recob::HitRefinerAssociator shcol(evt, fSliceModuleLabel, fDoWireAssns, fDoRawDigitAssns);
860  shcol.use_hits(std::move(hcol));
861  shcol.put_into(evt);
862  }
863  evt.put(std::move(ccol));
864  evt.put(std::move(cls_hit_assn));
865  evt.put(std::move(v2col));
866  evt.put(std::move(v3col));
867  evt.put(std::move(scol));
868  evt.put(std::move(sdcol));
869  evt.put(std::move(shwr_hit_assn));
870  evt.put(std::move(cls_vx2_assn));
871  evt.put(std::move(cls_vx3_assn));
872  evt.put(std::move(pcol));
873  evt.put(std::move(pfp_cls_assn));
874  evt.put(std::move(pfp_shwr_assn));
875  evt.put(std::move(pfp_vx3_assn));
876  evt.put(std::move(pfp_sed_assn));
877  evt.put(std::move(slc_cls_assn));
878  evt.put(std::move(slc_pfp_assn));
879  evt.put(std::move(slc_hit_assn));
880  evt.put(std::move(ctgcol));
881  evt.put(std::move(pfp_cos_assn));
882  evt.put(std::move(sp_hit_assn)); // www: association between sp and hit (trjaclust)
883  } // TrajCluster::produce()
884 
885  ////////////////////////////////////////////////
886  void
887  TrajCluster::GetHits(const std::vector<recob::Hit>& inputHits,
888  const geo::TPCID& tpcid,
889  std::vector<std::vector<unsigned int>>& tpcHits)
890  {
891  // Put hits in this TPC into a single "slice", unless a special debugging mode is specified to
892  // only reconstruct hits that are MC-matched
893  unsigned int tpc = tpcid.TPC;
894  tpcHits.resize(1);
895  for (size_t iht = 0; iht < inputHits.size(); ++iht) {
896  auto& hit = inputHits[iht];
897  if (hit.WireID().TPC == tpc) tpcHits[0].push_back(iht);
898  }
899  } // GetHits
900 
901  ////////////////////////////////////////////////
902  void
903  TrajCluster::GetHits(const std::vector<recob::Hit>& inputHits,
904  const geo::TPCID& tpcid,
905  const std::vector<recob::Slice>& inputSlices,
906  art::FindManyP<recob::Hit>& hitFromSlc,
907  std::vector<std::vector<unsigned int>>& tpcHits,
908  std::vector<int>& slcIDs)
909  {
910  // Put the hits in all slices into tpcHits in this TPC
911  tpcHits.clear();
912  slcIDs.clear();
913  if (!hitFromSlc.isValid()) return;
914 
915  unsigned int tpc = tpcid.TPC;
916 
917  for (size_t isl = 0; isl < inputSlices.size(); ++isl) {
918  auto& hit_in_slc = hitFromSlc.at(isl);
919  if (hit_in_slc.size() < 3) continue;
920  int slcID = inputSlices[isl].ID();
921  for (auto& hit : hit_in_slc) {
922  if (hit->WireID().TPC != tpc) continue;
923  unsigned short indx = 0;
924  for (indx = 0; indx < slcIDs.size(); ++indx)
925  if (slcID == slcIDs[indx]) break;
926  if (indx == slcIDs.size()) {
927  slcIDs.push_back(slcID);
928  tpcHits.resize(tpcHits.size() + 1);
929  }
930  tpcHits[indx].push_back(hit.key());
931  } // hit
932  } // isl
933 
934  } // GetHits
935 
936  //----------------------------------------------------------------------------
937  DEFINE_ART_MODULE(TrajCluster)
938 
939 } // namespace cluster
void PrintAll(detinfo::DetectorPropertiesData const &detProp, std::string someText)
Definition: Utils.cxx:5521
void ClearResults()
Deletes all the results.
bool CreateAssnD(art::Event &evt, art::Assns< T, U, D > &assn, size_t first_index, size_t second_index, typename art::Assns< T, U, D >::data_t &&data)
Creates a single one-to-one association with associated data.
void set_start_point_err(const TVector3 &xyz_e)
Definition: Shower.h:138
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
void set_dedx_err(const std::vector< double > &q)
Definition: Shower.h:140
void set_direction_err(const TVector3 &dir_e)
Definition: Shower.h:136
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
Definition: CORSIKAGen.fcl:7
Utilities related to art service access.
process_name cluster
Definition: cheaterreco.fcl:51
tca::TrajClusterAlg fTCAlg
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
TCConfig tcc
Definition: DataStructs.cxx:9
Declaration of signal hit object.
walls no right
Definition: selectors.fcl:105
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
void set_total_energy(const std::vector< double > &q)
Definition: Shower.h:129
void RunTrajClusterAlg(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< unsigned int > &hitsInSlice, int sliceID)
art::InputTag fSliceModuleLabel
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
void set_total_MIPenergy_err(const std::vector< double > &q)
Definition: Shower.h:132
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
process_name hit
Definition: cheaterreco.fcl:51
std::vector< std::string > const & GetAlgBitNames() const
bool SortHits(HitLoc const &h1, HitLoc const &h2)
process_name shower
Definition: cheaterreco.fcl:51
std::vector< std::array< unsigned int, 3 > > sptHits
SpacePoint -&gt; Hits assns by plane.
Definition: DataStructs.h:633
static void declare_products(art::ProducesCollector &collector, std::string instance_name="", bool doWireAssns=true, bool doRawDigitAssns=true)
Declares the hit products we are going to fill.
Definition: HitCreator.cxx:248
void set_total_energy_err(const std::vector< double > &q)
Definition: Shower.h:130
static const SentryArgument_t Sentry
An instance of the sentry object.
Definition: Cluster.h:182
void set_id(const int id)
Definition: Shower.h:128
bool SetInputHits(std::vector< recob::Hit > const &inputHits, unsigned int run, unsigned int event)
void DefineShTree(TTree *t)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:26
T abs(T value)
Helper functions to create a hit.
art::InputTag fHitModuleLabel
void set_direction(const TVector3 &dir)
Definition: Shower.h:135
void use_hits(std::unique_ptr< std::vector< recob::Hit >> &&srchits)
Uses the specified collection as data product.
Definition: HitCreator.cxx:528
int Wire
Select hit Wire for debugging.
Definition: DebugStruct.h:24
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
DebugStuff debug
Definition: DebugStruct.cxx:4
void put_into(art::Event &)
Moves the data into the event.
Definition: HitCreator.h:908
unsigned short GetSlicesSize() const
void set_length(const double &l)
Definition: Shower.h:141
int Plane
Select plane.
Definition: DebugStruct.h:22
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void set_open_angle(const double &a)
Definition: Shower.h:142
A class handling a collection of hits and its associations.
Definition: HitCreator.h:842
walls no left
Definition: selectors.fcl:105
const geo::GeometryCore * geom
Definition: DataStructs.h:576
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Declaration of cluster object.
void set_total_best_plane(const int q)
Definition: Shower.h:133
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
Definition of data types for geometry description.
void set_total_MIPenergy(const std::vector< double > &q)
Definition: Shower.h:131
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
TCSlice const & GetSlice(unsigned short sliceIndex) const
art::InputTag fSpacePointModuleLabel
tuple dir
Definition: dropbox.py:28
void GetHits(const std::vector< recob::Hit > &inputHits, const geo::TPCID &tpcid, std::vector< std::vector< unsigned int >> &tpcHits)
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.
int Tick
Select hit PeakTime for debugging (&lt; 0 for vertex finding)
Definition: DebugStruct.h:25
int TPC
Select TPC.
Definition: DebugStruct.h:21
geo::PlaneID DecodeCTP(CTP_t CTP)
Produces clusters by the TrajCluster algorithm.
void produce(art::Event &evt) override
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
void MergeTPHits(std::vector< unsigned int > &tpHits, std::vector< recob::Hit > &newHitCol, std::vector< unsigned int > &newHitAssns) const
void SetSourceHits(std::vector< recob::Hit > const &srcHits)
std::vector< PFPStruct > pfps
Definition: DataStructs.h:678
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8
void set_start_point(const TVector3 &xyz)
Definition: Shower.h:137
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
void SetInputSpts(std::vector< recob::SpacePoint > const &sptHandle)
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3284
short recoSlice
only reconstruct the slice with ID (0 = all)
Definition: DataStructs.h:588
tag cosmic rays
Definition: DataStructs.h:539
BEGIN_PROLOG could also be cout
auto const detProp
art::InputTag fSpacePointHitAssnLabel
void set_dedx(const std::vector< double > &q)
Definition: Shower.h:139
std::vector< unsigned int > const & GetAlgModCount() const
TrajCluster(fhicl::ParameterSet const &pset)