EmTrack.h
Go to the documentation of this file.
1 #ifndef EMTRACK_H
2 #define EMTRACK_H
3 
10 #include "fhiclcpp/types/Atom.h"
12 #include "fhiclcpp/types/Table.h"
14 
24 
25 #include <memory>
26 #include <unordered_map>
27 #include <vector>
28 
29 namespace nnet {
30  template <size_t N>
31  class EmTrack {
32  public:
33  using key = std::tuple<unsigned int, unsigned int, unsigned int>;
34  using cryo_tpc_view_keymap = std::map<key, std::vector<size_t>>;
35 
36  struct Config {
37  using Name = fhicl::Name;
39 
41  Name("PointIdAlg")};
43  Name("BatchSize"),
44  Comment("number of samples processed in one batch")};
45 
47  Name("WireLabel"),
48  Comment("tag of deconvoluted ADC on wires (recob::Wire)")};
49 
51  Name("HitModuleLabel"),
52  Comment("tag of hits to be EM/track / Michel tagged")};
53 
55  Name("ClusterModuleLabel"),
56  Comment("tag of clusters to be used as a source of EM/track / Michel "
57  "tagged new clusters (incl. single-hit clusters ) using "
58  "accumulated results from hits")};
59 
61  Name("TrackModuleLabel"),
62  Comment("tag of 3D tracks to be EM/track / Michel tagged using "
63  "accumulated results from hits in the best 2D projection")};
64 
66  Comment("tag clusters in selected views only, "
67  "or in all views if empty list")};
68  };
69  explicit EmTrack(Config const& c,
70  std::string const& s,
72  void produce(art::Event& e);
73 
74  private:
75  bool isViewSelected(int view) const;
76  const size_t fBatchSize;
77  std::unique_ptr<PointIdAlgTools::IPointIdAlg> fPointIdAlgTool;
84  const bool fDoClusters;
85  const bool fDoTracks;
86  const std::vector<int> fViews;
87  const art::InputTag
88  fNewClustersTag; // input tag for the clusters produced by this module
90  std::vector<art::Ptr<recob::Hit>> const& hitPtrList,
91  std::vector<char> const& hitInFA,
92  EmTrack::cryo_tpc_view_keymap const& hitMap);
93  void make_tracks(art::Event const& evt, std::vector<char> const& hitInFA);
95  std::vector<art::Ptr<recob::Hit>> const& hitPtrList) const;
96  std::vector<char> classify_hits(
97  art::Event const& evt,
98  EmTrack::cryo_tpc_view_keymap const& hitMap,
99  std::vector<art::Ptr<recob::Hit>> const& hitPtrList);
100  };
101 
102  template <size_t N>
103  void
105  std::vector<art::Ptr<recob::Hit>> const& hitPtrList,
106  std::vector<char> const& hitInFA,
107  EmTrack::cryo_tpc_view_keymap const& hitMap)
108  {
109  // **************** prepare for new clusters ****************
110  auto clusters = std::make_unique<std::vector<recob::Cluster>>();
111  auto clu2hit = std::make_unique<art::Assns<recob::Cluster, recob::Hit>>();
112 
113  // ************** get and sort input clusters ***************
114  auto cluListHandle =
115  evt.getValidHandle<std::vector<recob::Cluster>>(fClusterModuleLabel);
116  std::vector<art::Ptr<recob::Cluster>> cluPtrList;
117  art::fill_ptr_vector(cluPtrList, cluListHandle);
118 
120  for (auto const& c : cluPtrList) {
121  unsigned int view = c->Plane().Plane;
122  if (!isViewSelected(view))
123  continue;
124 
125  unsigned int cryo = c->Plane().Cryostat;
126  unsigned int tpc = c->Plane().TPC;
127 
128  cluMap[{cryo, tpc, view}].push_back(c.key());
129  }
130 
131  auto cluID = fMVAWriter.template initOutputs<recob::Cluster>(
132  fNewClustersTag, fPointIdAlgTool->outputLabels());
133 
134  unsigned int cidx = 0; // new clusters index
135  art::FindManyP<recob::Hit> hitsFromClusters(
136  cluListHandle, evt, fClusterModuleLabel);
137  std::vector<bool> hitUsed(hitPtrList.size(),
138  false); // tag hits used in clusters
139  // clang-format off
140  for (auto const & [key, clusters_keys] : cluMap)
141  {
142  auto const& [cryo, tpc, view]= key;
143  // clang-format on
144  if (!isViewSelected(view))
145  continue; // should not happen, clusters were pre-selected
146 
147  for (size_t c : clusters_keys) // c is the Ptr< recob::Cluster >::key()
148  {
149  auto v = hitsFromClusters.at(c);
150  if (v.empty())
151  continue;
152 
153  for (auto const& hit : v) {
154  if (hitUsed[hit.key()]) {
155  mf::LogWarning("EmTrack") << "hit already used in another cluster";
156  }
157  hitUsed[hit.key()] = true;
158  }
159 
160  auto vout = fMVAWriter.template getOutput<recob::Hit>(
161  v, [&](art::Ptr<recob::Hit> const& ptr) {
162  return (float)hitInFA[ptr.key()];
163  });
164 
165  float pvalue = vout[0] / (vout[0] + vout[1]);
166  mf::LogVerbatim("EmTrack")
167  << "cluster in tpc:" << tpc << " view:" << view
168  << " size:" << v.size() << " p:" << pvalue;
169 
170  clusters->emplace_back(recob::Cluster(0.0F,
171  0.0F,
172  0.0F,
173  0.0F,
174  0.0F,
175  0.0F,
176  0.0F,
177  0.0F,
178  0.0F,
179  0.0F,
180  0.0F,
181  0.0F,
182  0.0F,
183  0.0F,
184  0.0F,
185  0.0F,
186  0.0F,
187  0.0F,
188  v.size(),
189  0.0F,
190  0.0F,
191  cidx,
192  (geo::View_t)view,
193  v.front()->WireID().planeID()));
194  util::CreateAssn(evt, *clusters, v, *clu2hit);
195  cidx++;
196 
197  fMVAWriter.addOutput(cluID,
198  vout); // add copy of the input cluster
199  }
200 
201  // (2b) make single-hit clusters
202  // --------------------------------------------
203  for (size_t h :
204  hitMap.at({cryo, tpc, view})) // h is the Ptr< recob::Hit >::key()
205  {
206  if (hitUsed[h])
207  continue;
208 
209  auto vout = fMVAWriter.template getOutput<recob::Hit>(h);
210  float pvalue = vout[0] / (vout[0] + vout[1]);
211 
212  mf::LogVerbatim("EmTrack")
213  << "single hit in tpc:" << tpc << " view:" << view
214  << " wire:" << hitPtrList[h]->WireID().Wire
215  << " drift:" << hitPtrList[h]->PeakTime() << " p:" << pvalue;
216 
217  art::PtrVector<recob::Hit> cluster_hits;
218  cluster_hits.push_back(hitPtrList[h]);
219  clusters->emplace_back(
220  recob::Cluster(0.0F,
221  0.0F,
222  0.0F,
223  0.0F,
224  0.0F,
225  0.0F,
226  0.0F,
227  0.0F,
228  0.0F,
229  0.0F,
230  0.0F,
231  0.0F,
232  0.0F,
233  0.0F,
234  0.0F,
235  0.0F,
236  0.0F,
237  0.0F,
238  1,
239  0.0F,
240  0.0F,
241  cidx,
242  (geo::View_t)view,
243  hitPtrList[h]->WireID().planeID()));
244  util::CreateAssn(evt, *clusters, cluster_hits, *clu2hit);
245  cidx++;
246 
248  cluID, vout); // add single-hit cluster tagging unclutered hit
249  }
250  mf::LogVerbatim("EmTrack")
251  << "...produced " << cidx - clusters_keys.size()
252  << " single-hit clusters.";
253  }
254 
255  evt.put(std::move(clusters));
256  evt.put(std::move(clu2hit));
257  }
258 
259  /// make tracks
260  template <size_t N>
261  void
263  std::vector<char> const& hitInFA)
264  {
265  auto trkListHandle =
266  evt.getValidHandle<std::vector<recob::Track>>(fTrackModuleLabel);
267  art::FindManyP<recob::Hit> hitsFromTracks(
268  trkListHandle, evt, fTrackModuleLabel);
269  std::vector<std::vector<art::Ptr<recob::Hit>>> trkHitPtrList(
270  trkListHandle->size());
271  for (size_t t = 0; t < trkListHandle->size(); ++t) {
272  auto v = hitsFromTracks.at(t);
273  size_t nh[3] = {0, 0, 0};
274  for (auto const& hptr : v) {
275  ++nh[hptr->View()];
276  }
277  size_t best_view = 2; // collection
278  if ((nh[0] >= nh[1]) && (nh[0] > 2 * nh[2]))
279  best_view = 0; // ind1
280  if ((nh[1] >= nh[0]) && (nh[1] > 2 * nh[2]))
281  best_view = 1; // ind2
282 
283  size_t k = 0;
284  while (!isViewSelected(best_view)) {
285  best_view = (best_view + 1) % 3;
286  if (++k > 3) {
287  throw cet::exception("EmTrack")
288  << "No views selected at all?" << std::endl;
289  }
290  }
291 
292  for (auto const& hptr : v) {
293  if (hptr->View() == best_view)
294  trkHitPtrList[t].emplace_back(hptr);
295  }
296  }
297 
298  auto trkID = fMVAWriter.template initOutputs<recob::Track>(
299  fTrackModuleLabel, trkHitPtrList.size(), fPointIdAlgTool->outputLabels());
300  for (size_t t = 0; t < trkHitPtrList.size();
301  ++t) // t is the Ptr< recob::Track >::key()
302  {
303  auto vout = fMVAWriter.template getOutput<recob::Hit>(
304  trkHitPtrList[t], [&](art::Ptr<recob::Hit> const& ptr) {
305  return (float)hitInFA[ptr.key()];
306  });
307  fMVAWriter.setOutput(trkID, t, vout);
308  }
309  }
310  template <size_t N>
313  std::vector<art::Ptr<recob::Hit>> const& hitPtrList) const
314  {
315  cryo_tpc_view_keymap hitMap;
316  for (auto const& hptr : hitPtrList) {
317  auto const& h = *hptr;
318  unsigned int view = h.WireID().Plane;
319  if (!isViewSelected(view))
320  continue;
321 
322  unsigned int cryo = h.WireID().Cryostat;
323  unsigned int tpc = h.WireID().TPC;
324 
325  hitMap[{cryo, tpc, view}].push_back(hptr.key());
326  }
327  return hitMap;
328  }
329 
330  template <size_t N>
331  std::vector<char>
333  EmTrack::cryo_tpc_view_keymap const& hitMap,
334  std::vector<art::Ptr<recob::Hit>> const& hitPtrList)
335  {
336  auto hitID = fMVAWriter.template initOutputs<recob::Hit>(
337  fHitModuleLabel, hitPtrList.size(), fPointIdAlgTool->outputLabels());
338 
339  auto const clockData =
341  auto const detProp =
343  evt, clockData);
344  auto wireHandle =
345  evt.getValidHandle<std::vector<recob::Wire>>(fWireProducerLabel);
346  std::vector<char> hitInFA(hitPtrList.size(),
347  0); // tag hits in fid. area as 1, use 0 for hits
348  // close to the projectrion edges
349  for (auto const& [key, hits] : hitMap) {
350  auto const& [cryo, tpc, view] = key;
351  if (!isViewSelected(view))
352  continue; // should not happen, hits were selected
353 
354  fPointIdAlgTool->setWireDriftData(
355  clockData, detProp, *wireHandle, view, tpc, cryo);
356 
357  // (1) do all hits in this plane
358  // ------------------------------------------------
359  for (size_t idx = 0; idx < hits.size(); idx += fBatchSize) {
360  std::vector<std::pair<unsigned int, float>> points;
361  std::vector<size_t> keys;
362  for (size_t k = 0; k < fBatchSize; ++k) {
363  if (idx + k >= hits.size()) {
364  break;
365  } // careful about the tail
366 
367  size_t h = hits[idx + k]; // h is the Ptr< recob::Hit >::key()
368  const recob::Hit& hit = *(hitPtrList[h]);
369  points.emplace_back(hit.WireID().Wire, hit.PeakTime());
370  keys.push_back(h);
371  }
372 
373  auto batch_out = fPointIdAlgTool->predictIdVectors(points);
374  if (points.size() != batch_out.size()) {
375  throw cet::exception("EmTrack")
376  << "hits processing failed" << std::endl;
377  }
378 
379  for (size_t k = 0; k < points.size(); ++k) {
380  size_t h = keys[k];
381  fMVAWriter.setOutput(hitID, h, batch_out[k]);
382  if (fPointIdAlgTool->isInsideFiducialRegion(points[k].first,
383  points[k].second)) {
384  hitInFA[h] = 1;
385  }
386  }
387  } // hits done
388  // ------------------------------------------------------------------
389  }
390  return hitInFA;
391  }
392  // make sure fMVAWriter is getting a variable string
393  template <size_t N>
395  std::string const& module_label,
396  art::ProducesCollector& collector)
397  : fBatchSize(config.BatchSize())
398  , fPointIdAlgTool(art::make_tool<PointIdAlgTools::IPointIdAlg>(
399  config.PointIdAlg.get_PSet()))
400  , fMVAWriter(collector, "emtrkmichel")
401  , fWireProducerLabel(config.WireLabel())
402  , fHitModuleLabel(config.HitModuleLabel())
407  , fViews(config.Views())
408  , fNewClustersTag(
409  module_label,
410  "",
411  art::ServiceHandle<art::TriggerNamesService const>()->getProcessName())
412  {
413  fMVAWriter.template produces_using<recob::Hit>();
414 
415  if (!fClusterModuleLabel.label().empty()) {
416  collector.produces<std::vector<recob::Cluster>>();
418 
419  fMVAWriter.template produces_using<recob::Cluster>();
420  }
421 
422  if (!fTrackModuleLabel.label().empty()) {
423  fMVAWriter.template produces_using<recob::Track>();
424  }
425  }
426  // ------------------------------------------------------
427 
428  template <size_t N>
429  void
431  {
432  mf::LogVerbatim("EmTrack")
433  << "next event: " << evt.run() << " / " << evt.id().event();
434  auto hitListHandle =
435  evt.getValidHandle<std::vector<recob::Hit>>(fHitModuleLabel);
436  std::vector<art::Ptr<recob::Hit>> hitPtrList;
437  art::fill_ptr_vector(hitPtrList, hitListHandle);
438  const EmTrack::cryo_tpc_view_keymap hitMap = create_hitmap(hitPtrList);
439  const std::vector<char> hitInFA = classify_hits(evt, hitMap, hitPtrList);
440 
441  if (fDoClusters)
442  make_clusters(evt, hitPtrList, hitInFA, hitMap);
443 
444  if (fDoTracks)
445  make_tracks(evt, hitInFA);
446  fMVAWriter.saveOutputs(evt);
447  }
448  // ------------------------------------------------------
449 
450  template <size_t N>
451  bool
453  {
454  if (fViews.empty())
455  return true;
456  return cet::search_all(fViews, view);
457  }
458  // ------------------------------------------------------
459 
460 }
461 #endif
const art::InputTag fTrackModuleLabel
Definition: EmTrack.h:83
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const art::InputTag fWireProducerLabel
Definition: EmTrack.h:80
std::enable_if_t< std::is_class< T >::value, tool_return_type< T > > make_tool(fhicl::ParameterSet const &pset)
Definition: make_tool.h:18
writer fMVAWriter
Definition: EmTrack.h:79
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
fhicl::Comment Comment
Definition: EmTrack.h:38
void make_tracks(art::Event const &evt, std::vector< char > const &hitInFA)
make tracks
Definition: EmTrack.h:262
geo::WireID WireID() const
Definition: Hit.h:233
void setOutput(FVector_ID id, size_t key, std::array< float, N > const &values)
Definition: MVAWriter.h:175
struct vector vector
ChannelGroupService::Name Name
std::unique_ptr< PointIdAlgTools::IPointIdAlg > fPointIdAlgTool
Definition: EmTrack.h:77
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
const std::vector< int > fViews
Definition: EmTrack.h:86
std::vector< char > classify_hits(art::Event const &evt, EmTrack::cryo_tpc_view_keymap const &hitMap, std::vector< art::Ptr< recob::Hit >> const &hitPtrList)
Definition: EmTrack.h:332
fhicl::Atom< art::InputTag > TrackModuleLabel
Definition: EmTrack.h:60
art framework interface to geometry description
fhicl::Atom< art::InputTag > HitModuleLabel
Definition: EmTrack.h:50
std::string const & label() const noexcept
Definition: InputTag.cc:79
const bool fDoClusters
Definition: EmTrack.h:84
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
bool search_all(FwdCont const &, Datum const &)
const double e
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
void produce(art::Event &e)
Definition: EmTrack.h:430
static Config * config
Definition: config.cpp:1054
EmTrack(Config const &c, std::string const &s, art::ProducesCollector &pc)
Definition: EmTrack.h:394
def move(depos, offset)
Definition: depos.py:107
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
std::map< key, std::vector< size_t >> cryo_tpc_view_keymap
Definition: EmTrack.h:34
fhicl::Atom< art::InputTag > ClusterModuleLabel
Definition: EmTrack.h:54
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.
const art::InputTag fHitModuleLabel
Definition: EmTrack.h:81
RunNumber_t run() const
Definition: DataViewImpl.cc:71
void make_clusters(art::Event &evt, std::vector< art::Ptr< recob::Hit >> const &hitPtrList, std::vector< char > const &hitInFA, EmTrack::cryo_tpc_view_keymap const &hitMap)
Definition: EmTrack.h:104
void saveOutputs(art::Event &evt)
Check consistency and save all the results in the event.
Definition: MVAWriter.h:325
Detector simulation of raw signals on wires.
fhicl::Atom< size_t > BatchSize
Definition: EmTrack.h:42
bool isViewSelected(int view) const
Definition: EmTrack.h:452
void addOutput(FVector_ID id, std::array< float, N > const &values)
Definition: MVAWriter.h:180
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
Declaration of signal hit object.
#define Comment
fhicl::Sequence< int > Views
Definition: EmTrack.h:65
const art::InputTag fNewClustersTag
Definition: EmTrack.h:88
fhicl::Atom< art::InputTag > WireLabel
Definition: EmTrack.h:46
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Provides recob::Track data product.
fhicl::Name Name
Definition: EmTrack.h:37
EventNumber_t event() const
Definition: EventID.h:116
cryo_tpc_view_keymap create_hitmap(std::vector< art::Ptr< recob::Hit >> const &hitPtrList) const
Definition: EmTrack.h:312
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
const size_t fBatchSize
Definition: EmTrack.h:76
TCEvent evt
Definition: DataStructs.cxx:7
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
const art::InputTag fClusterModuleLabel
Definition: EmTrack.h:82
const bool fDoTracks
Definition: EmTrack.h:85
static QCString * s
Definition: config.cpp:1042
EventID id() const
Definition: Event.cc:34
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)
std::tuple< unsigned int, unsigned int, unsigned int > key
Definition: EmTrack.h:33