ParticleDecayId_module.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////////
2 // Class: ParticleDecayId
3 // Module Type: producer
4 // File: ParticleDecayId_module.cc
5 // Authors: dorota.stefan@cern.ch pplonski86@gmail.com robert.sulej@cern.ch
6 //
7 // THIS IS STIIL DEVELOPMENT NOW - CODE MAKING VERTICES MAY STILL CHANGE STRATEGY
8 //
9 /////////////////////////////////////////////////////////////////////////////////
10 
17 #include "fhiclcpp/types/Atom.h"
18 #include "fhiclcpp/types/Table.h"
20 
27 
29 
30 #include <memory>
31 #include <TVector3.h>
32 
33 namespace nnet {
34 
36 public:
37 
38  struct Config {
39  using Name = fhicl::Name;
41 
43  Name("PointIdAlg")
44  };
45 
47  Name("WireLabel"),
48  Comment("tag of deconvoluted ADC on wires (recob::Wire)")
49  };
50 
52  Name("TrackModuleLabel"),
53  Comment("tag of tracks where decays points are to be found")
54  };
55 
57  Name("RoiThreshold"),
58  Comment("search for decay points where the net output > ROI threshold")
59  };
60 
62  Name("PointThreshold"),
63  Comment("tag decay point if it is detected in at least two planes with net outputs product > POINT threshold")
64  };
65 
67  Name("SkipView"),
68  Comment("use all views to find decays if -1, or skip the view with provided index and use only the two other views")
69  };
70  };
72  explicit ParticleDecayId(Parameters const & p);
73 
74  ParticleDecayId(ParticleDecayId const &) = delete;
75  ParticleDecayId(ParticleDecayId &&) = delete;
76  ParticleDecayId & operator = (ParticleDecayId const &) = delete;
78 
79 private:
80  void produce(art::Event & e) override;
81 
82  bool DetectDecay(
83  const std::vector<recob::Wire> & wires,
84  const std::vector< art::Ptr<recob::Hit> > & hits,
85  std::map< size_t, TVector3 > & spoints,
86  std::vector< std::pair<TVector3, double> > & result);
87 
89 
92 
94 
95  int fSkipView;
96 };
97 // ------------------------------------------------------
98 
100  EDProducer{config},
102  fWireProducerLabel(config().WireLabel()),
103  fTrackModuleLabel(config().TrackModuleLabel()),
104  fRoiThreshold(config().RoiThreshold()),
105  fPointThreshold(config().PointThreshold()),
106  fSkipView(config().SkipView())
107 {
108  produces< std::vector<recob::Vertex> >();
109  produces< art::Assns<recob::Vertex, recob::Track> >();
110 }
111 // ------------------------------------------------------
112 
114 {
115  std::cout << std::endl << "event " << evt.id().event() << std::endl;
116 
117  auto vtxs = std::make_unique< std::vector< recob::Vertex > >();
118  auto vtx2trk = std::make_unique< art::Assns< recob::Vertex, recob::Track > >();
119 
120  //auto vid = getProductID< std::vector<recob::Vertex> >(evt);
121 
122  auto wireHandle = evt.getValidHandle< std::vector<recob::Wire> >(fWireProducerLabel);
123  auto trkListHandle = evt.getValidHandle< std::vector<recob::Track> >(fTrackModuleLabel);
124  auto spListHandle = evt.getValidHandle< std::vector<recob::SpacePoint> >(fTrackModuleLabel);
125 
126  art::FindManyP< recob::Hit > hitsFromTracks(trkListHandle, evt, fTrackModuleLabel);
127  art::FindManyP< recob::SpacePoint > spFromTracks(trkListHandle, evt, fTrackModuleLabel);
128  art::FindManyP< recob::Hit > hitsFromSPoints(spListHandle, evt, fTrackModuleLabel);
129 
130  std::vector< std::pair<TVector3, double> > decays;
131  for (size_t i = 0; i < hitsFromTracks.size(); ++i)
132  {
133  auto hits = hitsFromTracks.at(i);
134  auto spoints = spFromTracks.at(i);
135  if (hits.empty()) continue;
136 
137  std::map< size_t, TVector3 > trkSpacePoints;
138  for (const auto & p : spoints)
139  {
140  auto sp_hits = hitsFromSPoints.at(p.key());
141  for (const auto & h : sp_hits)
142  {
143  trkSpacePoints[h.key()] = TVector3(p->XYZ()[0], p->XYZ()[1], p->XYZ()[2]);
144  }
145  }
146 
147  DetectDecay(*wireHandle, hits, trkSpacePoints, decays);
148  }
149 
150  double xyz[3];
151  for (const auto & p3d : decays)
152  {
153 
154  xyz[0] = p3d.first.X(); xyz[1] = p3d.first.Y(); xyz[2] = p3d.first.Z();
155  std::cout << " detected: [" << xyz[0] << ", " << xyz[1] << ", " << xyz[2] << "] p:" << p3d.second << std::endl;
156 
157  size_t vidx = vtxs->size();
158  vtxs->push_back(recob::Vertex(xyz, vidx));
159 
160  // to do: assn to eg. appropriate track
161  // selected among set of connected tracks
162  //art::Ptr<recob::Track> tptr(trkListHandle, i);
163  //art::Ptr<recob::Vertex> vptr(vid, vidx, evt.productGetter(vid));
164  //vtx2trk->addSingle(vptr, tptr);
165  }
166 
167  evt.put(std::move(vtxs));
168  evt.put(std::move(vtx2trk));
169 }
170 // ------------------------------------------------------
171 
173  const std::vector<recob::Wire> & wires,
174  const std::vector< art::Ptr<recob::Hit> > & hits,
175  std::map< size_t, TVector3 > & spoints,
176  std::vector< std::pair<TVector3, double> > & result)
177 {
178  const size_t nviews = 3;
179 
180  std::vector< art::Ptr<recob::Hit> > wire_drift[nviews];
181  for (size_t i = 0; i < hits.size(); ++i) // split hits between views
182  {
183  wire_drift[hits[i]->View()].push_back(hits[i]);
184  }
185 
186  std::vector< float > outputs[nviews];
187  for (size_t v = 0; v < nviews; ++v) // calculate nn outputs for each view (hopefully not changing cryo/tpc many times)
188  {
189  outputs[v].resize(wire_drift[v].size(), 0);
190  for (size_t i = 0; i < wire_drift[v].size(); ++i)
191  {
192  int tpc = wire_drift[v][i]->WireID().TPC;
193  int cryo = wire_drift[v][i]->WireID().Cryostat;
194 
195  fPointIdAlg.setWireDriftData(wires, v, tpc, cryo);
196 
197  outputs[v][i] = fPointIdAlg.predictIdVector(wire_drift[v][i]->WireID().Wire, wire_drift[v][i]->PeakTime())[0]; // p(decay)
198  }
199  }
200 
201  std::vector< std::pair<size_t, float> > candidates2d[nviews];
202  std::vector< std::pair<TVector3, float> > candidates3d[nviews];
203  for (size_t v = 0; v < nviews; ++v)
204  {
205  size_t idx = 0;
206  while (idx < outputs[v].size())
207  {
208  if (outputs[v][idx] > fRoiThreshold)
209  {
210  size_t ci = idx;
211  float max = outputs[v][idx];
212  ++idx;
213 
214  while ((idx < outputs[v].size()) && (outputs[v][idx] > fRoiThreshold))
215  {
216  if (outputs[v][idx] > max) { max = outputs[v][idx]; ci = idx; }
217  ++idx;
218  }
219  candidates2d[v].emplace_back(ci, max);
220  candidates3d[v].emplace_back(spoints[wire_drift[v][ci].key()], max);
221  }
222  else ++idx;
223  }
224  }
225 
226  double min_dist = 2.0; // [cm], threshold for today to distinguish between two different candidates,
227  // if belo threshold, then use 3D point corresponding to higher cnn output
228 
229  // need coincidence of high cnn out in two views, then look if there is another close candidate
230  // and again select by cnn output value, would like to have few strong candidates
231  bool found = false;
232  for (size_t v = 0; v < nviews - 1; ++v)
233  {
234  for (size_t i = 0; i < candidates3d[v].size(); ++i)
235  {
236  TVector3 c0(candidates3d[v][i].first);
237  float p0 = candidates3d[v][i].second;
238 
239  for (size_t u = v + 1; u < nviews; ++u)
240  {
241  for (size_t j = 0; j < candidates3d[v].size(); ++j)
242  {
243  TVector3 c1(candidates3d[v][j].first);
244  float p1 = candidates3d[v][j].second;
245 
246  if ((c0 - c1).Mag() < min_dist)
247  {
248  TVector3 c(c0);
249  if (p1 > p0) { c = c1; }
250  double p = p0 * p1;
251 
252  if (p > fPointThreshold)
253  {
254  double d, dmin = min_dist;
255  size_t kmin = 0;
256  for (size_t k = 0; k < result.size(); ++k)
257  {
258  d = (result[k].first - c).Mag();
259  if (d < dmin)
260  {
261  dmin = d; kmin = k;
262  }
263  }
264  if (dmin < min_dist)
265  {
266  if (result[kmin].second < p) // replace previously found point
267  {
268  result[kmin].first = c;
269  result[kmin].second = p;
270  found = true;
271  }
272  }
273  else // nothing close in the list, add new point
274  {
275  result.emplace_back(c, p);
276  found = true;
277  }
278  } // if (p > fPointThreshold)
279  } // coincidence: points from views u and v are close
280  } // loop over points in view u
281  } // loop over views u
282  } // loop over points in view v
283  } // loop over views v
284  return found;
285 }
286 
288 
289 }
static QCString result
bool DetectDecay(const std::vector< recob::Wire > &wires, const std::vector< art::Ptr< recob::Hit > > &hits, std::map< size_t, TVector3 > &spoints, std::vector< std::pair< TVector3, double > > &result)
fhicl::Atom< art::InputTag > TrackModuleLabel
Declaration of signal hit object.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
struct vector vector
ParticleDecayId & operator=(ParticleDecayId const &)=delete
uint size() const
Definition: qcstring.h:201
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
void produce(art::Event &e) override
bool setWireDriftData(const std::vector< recob::Wire > &wires, unsigned int plane, unsigned int tpc, unsigned int cryo)
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
std::vector< float > predictIdVector(unsigned int wire, float drift) const
calculate multi-class probabilities for [wire, drift] point
Definition: PointIdAlg.cxx:223
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:69
def key(type, name=None)
Definition: graph.py:13
static Config * config
Definition: config.cpp:1054
def move(depos, offset)
Definition: depos.py:107
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:491
static int max(int a, int b)
Provides recob::Track data product.
p
Definition: test.py:223
AdcCodeMitigator::Name Name
#define Comment
Utility object to perform functions of association.
EventNumber_t event() const
Definition: EventID.h:116
ParticleDecayId(Parameters const &p)
TCEvent evt
Definition: DataStructs.cxx:7
fhicl::Atom< art::InputTag > WireLabel
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
ProductID put(std::unique_ptr< PROD > &&edp, FullSemantic< Level::Run > const semantic)
Definition: DataViewImpl.h:730
EventID id() const
Definition: Event.cc:37
QTextStream & endl(QTextStream &s)
h
training ###############################
Definition: train_cnn.py:186