LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
Track3DKalmanHit_module.cc
Go to the documentation of this file.
1 //
3 // Class: Track3DKalmanHit
4 // Module Type: producer
5 // File: Track3DKalmanHit_module.cc
6 //
7 // This module produces RecoBase/Track objects using KalmanFilterAlgorithm.
8 //
9 // Configuration parameters:
10 //
11 // Hist - Histogram flag (generate histograms if true).
12 // UseClusterHits - Use clustered hits if true.
13 // UsePFParticleHits - Use PFParticle hits if true.
14 // UsePFParticleSeeds - If true, use seeds associated with PFParticles.
15 // HitModuleLabel - Module label for unclustered Hits.
16 // ClusterModuleLabel - Module label for Clusters.
17 // PFParticleModuleLabel - Module label for PFParticles.
18 // Track3DKalmanHitAlg - Algorithm class for Track3DKalmanHit module
19 // SpacePointAlg - Parmaeter set for space points.
20 //
21 // Usage Notes.
22 //
23 // 1. It is an error if UseClusterHits and UsePFParticleHits are both
24 // true (throw exception in that case). However, both can be false,
25 // in which case all hits are used as input.
26 //
27 // 2. If clustered hits are used as input, then tracks can span clusters
28 // (cluster structure of hits is ignored).
29 //
30 // 3. If PFParticle hits are used as input, then tracks do not span
31 // PFParticles. However, it is possible for one the hits from
32 // one PFParticle to give rise to multiple Tracks.
33 //
34 // 4. UsePFParticleSeeds has no effect unless UsePFParticleHits is true.
35 //
37 
38 #include <cmath>
39 #include <algorithm>
40 #include <vector>
41 #include <deque>
42 
48 
49 #include "TMath.h"
50 
63 
64 
65 #include "TH1F.h"
66 
67 namespace trkf {
68 
70  public:
71  // Copnstructors, destructor.
72  explicit Track3DKalmanHit(fhicl::ParameterSet const & pset);
73 
74  // Overrides.
75  // Put override right next to each function
76  virtual void reconfigure(fhicl::ParameterSet const & pset) ;
77  virtual void produce(art::Event & e) override;
78  virtual void beginJob() override;
79  virtual void endJob() override;
80 
81  private:
82 
83  //Member functions that depend on art::event and use art::Assns
84  //note that return types are move aware
85  void prepareForInput();
86  KalmanInputs getInput(const art::Event &evt) const;
87  Hits getClusteredHits(const art::Event &evt) const;
88  KalmanInputs getPFParticleStuff(const art::Event &evt) const;
89  Hits getAllHits(const art::Event &evt) const;
90  void createOutputs(const art::Event &evt,
91  const std::vector<KalmanOutput> &outputs,
92  const KalmanInputs &inputs,
93  std::vector<recob::Track> &tracks,
94  std::vector<recob::SpacePoint> &spts,
100  void fillHistograms(std::vector<KalmanOutput>& outputs);
101 
102 
103  // Fcl parameters.
104  bool fHist;
108  std::string fHitModuleLabel;
109  std::string fClusterModuleLabel;
113 
114  // Histograms.
115  TH1F* fHIncChisq;
116  TH1F* fHPull;
117 
118  // Statistics.
119  int fNumEvent;
120  };
122 } // namespace trkf
123 
124 //----------------------------------------------------------------------------
132 fHist(false),
133 fUseClusterHits(false),
134 fUsePFParticleHits(false),
135 fUsePFParticleSeeds(false),
136 fTKHAlg(pset.get<fhicl::ParameterSet>("Track3DKalmanHitAlg")),
137 fSpacePointAlg(pset.get<fhicl::ParameterSet>("SpacePointAlg")),
138 fHIncChisq(0),
139 fHPull(0),
140 fNumEvent(0)
141 {
142  reconfigure(pset);
143  produces<std::vector<recob::Track> >();
144  produces<std::vector<recob::SpacePoint> >();
145  produces<art::Assns<recob::Track, recob::Hit> >(); // ****** REMEMBER to remove when FindMany improved ******
146  produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta> >();
147  produces<art::Assns<recob::Track, recob::SpacePoint> >();
148  produces<art::Assns<recob::SpacePoint, recob::Hit> >();
149  produces<art::Assns<recob::PFParticle, recob::Track> >();
150 
151  // Report.
152 
153  mf::LogInfo("Track3DKalmanHit")
154  << "Track3DKalmanHit configured with the following parameters:\n"
155  << " UseClusterHits = " << fUseClusterHits << "\n"
156  << " HitModuleLabel = " << fHitModuleLabel << "\n"
157  << " ClusterModuleLabel = " << fClusterModuleLabel;
158 }
159 
160 //----------------------------------------------------------------------------
167 // SS: talk to Kyle about using parameter set validation
169 {
170  fHist = pset.get<bool>("Hist");
171  fTKHAlg.reconfigure(pset.get<fhicl::ParameterSet>("Track3DKalmanHitAlg"));
172  fSpacePointAlg.reconfigure(pset.get<fhicl::ParameterSet>("SpacePointAlg"));
173  fUseClusterHits = pset.get<bool>("UseClusterHits");
174  fUsePFParticleHits = pset.get<bool>("UsePFParticleHits");
175  fUsePFParticleSeeds = pset.get<bool>("UsePFParticleSeeds");
176  fHitModuleLabel = pset.get<std::string>("HitModuleLabel");
177  fClusterModuleLabel = pset.get<std::string>("ClusterModuleLabel");
178  fPFParticleModuleLabel = pset.get<std::string>("PFParticleModuleLabel");
179  if(fUseClusterHits && fUsePFParticleHits) {
180  throw cet::exception("Track3DKalmanHit")
181  << "Using input from both clustered and PFParticle hits.\n";
182  }
183 }
184 
185 //----------------------------------------------------------------------------
188 {
189  if(fHist) {
190  // Book histograms.
192  art::TFileDirectory dir = tfs->mkdir("hitkalman", "Track3DKalmanHit histograms");
193 
194  fHIncChisq = dir.make<TH1F>("IncChisq", "Incremental Chisquare", 100, 0., 20.);
195  fHPull = dir.make<TH1F>("Pull", "Hit Pull", 100, -10., 10.);
196  }
197 }
198 
199 //----------------------------------------------------------------------------
203 {
204  ++fNumEvent;
205  auto tracks = std::make_unique<std::vector<recob::Track>>();
206  auto th_assn = std::make_unique<art::Assns<recob::Track, recob::Hit>>();
207  auto thm_assn = std::make_unique< art::Assns< recob::Track, recob::Hit, recob::TrackHitMeta > >();
208  auto tsp_assn = std::make_unique<art::Assns<recob::Track, recob::SpacePoint>>();
209  auto pfPartTrack_assns = std::make_unique<art::Assns<recob::PFParticle, recob::Track>>();
210  auto spts = std::make_unique<std::vector<recob::SpacePoint>>();
211  auto sph_assn = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
212 
213  prepareForInput();
214  auto inputs = getInput(evt);
215 
216  auto outputs = fTKHAlg.makeTracks(inputs);
217 
218  if(fHist) {
219  fillHistograms(outputs);
220  }
221 
222  createOutputs(evt, outputs, inputs, *tracks, *spts, *th_assn, *thm_assn, *tsp_assn, *sph_assn, *pfPartTrack_assns);
223 
225 
226  evt.put(std::move(tracks));
227  evt.put(std::move(spts));
228  evt.put(std::move(th_assn));
229  evt.put(std::move(thm_assn));
230  evt.put(std::move(tsp_assn));
231  evt.put(std::move(sph_assn));
232  evt.put(std::move(pfPartTrack_assns));
233 }
234 
235 //----------------------------------------------------------------------------
238 {
239  mf::LogInfo("Track3DKalmanHit")
240  << "Track3DKalmanHit statistics:\n"
241  << " Number of events = " << fNumEvent << "\n";
242 }
243 
244 
245 //----------------------------------------------------------------------------
246 //A temporary method till we find an alternative
249 }
250 
251 //----------------------------------------------------------------------------
252 // There are three modes of operation:
253 // 1. Clustered hits (produces one hit collection).
254 // 2. PFParticle hits (products one hit collection for each PFParticle).
255 // 3. All hits (produces one hit collection).
256 
258  if (fUsePFParticleHits) return getPFParticleStuff(evt);
260  getClusteredHits(evt):
261  getAllHits(evt)));
262 }
263 
264 //----------------------------------------------------------------------------
267  Hits hits;
269  evt.getByLabel(fClusterModuleLabel, clusterh);
270 
271  if (!clusterh.isValid()) return hits;
272  // Get hits from all clusters.
273  art::FindManyP<recob::Hit> hitsbycluster(clusterh, evt, fClusterModuleLabel);
274 
275  for(size_t i = 0; i < clusterh->size(); ++i) {
276  std::vector< art::Ptr<recob::Hit> > clushits = hitsbycluster.at(i);
277  hits.insert(hits.end(), clushits.begin(), clushits.end());
278  }
279  return hits;
280 }
281 
282 //----------------------------------------------------------------------------
285  Hits hits;
287  evt.getByLabel(fHitModuleLabel, hith);
288  if(!hith.isValid()) return hits;
289  size_t nhits = hith->size();
290  hits.reserve(nhits);
291 
292  for(size_t i = 0; i < nhits; ++i) {
293  hits.push_back(art::Ptr<recob::Hit>(hith, i));
294  }
295  return hits;
296 }
297 
298 //----------------------------------------------------------------------------
301  KalmanInputs inputs;
302  // Our program is to drive the track creation/fitting off the PFParticles in the data store
303  // We'll use the hits associated to the PFParticles for each track - and only those hits.
304  // Without a valid collection of PFParticles there is nothing to do here
305  // We need a handle to the collection of clusters in the data store so we can
306  // handle associations to hits.
308  evt.getByLabel(fPFParticleModuleLabel, pfParticleHandle);
309  if (!pfParticleHandle.isValid()) return inputs;
310 
312  evt.getByLabel(fClusterModuleLabel, clusterHandle);
313 
314  // If there are no clusters then something is really wrong
315  if (!clusterHandle.isValid()) return inputs;
316 
317  // Recover the collection of associations between PFParticles and clusters, this will
318  // be the mechanism by which we actually deal with clusters
319  art::FindManyP<recob::Cluster> clusterAssns(pfParticleHandle, evt, fPFParticleModuleLabel);
320 
321  // Associations to seeds.
322  art::FindManyP<recob::Seed> seedAssns(pfParticleHandle, evt, fPFParticleModuleLabel);
323 
324  // Likewise, recover the collection of associations to hits
325  art::FindManyP<recob::Hit> clusterHitAssns(clusterHandle, evt, fClusterModuleLabel);
326 
327  inputs.reserve(pfParticleHandle->size());
328 
329  // While PFParticle describes a hierarchal structure, for now we simply loop over the collection
330  for(size_t partIdx = 0; partIdx < pfParticleHandle->size(); partIdx++) {
331 
332  // Add a new empty hit collection.
333  inputs.emplace_back();
334  KalmanInput& kalman_input = inputs.back();
335  kalman_input.pfPartPtr = art::Ptr<recob::PFParticle>(pfParticleHandle, partIdx);
336  Hits& hits = kalman_input.hits;
337 
338  // Fill this hit vector by looping over associated clusters and finding the
339  // hits associated to them
340  std::vector<art::Ptr<recob::Cluster> > clusterVec = clusterAssns.at(partIdx);
341 
342  for(auto const &cluster : clusterVec) {
343  std::vector<art::Ptr<recob::Hit> > hitVec = clusterHitAssns.at(cluster.key());
344  hits.insert(hits.end(), hitVec.begin(), hitVec.end());
345  }
346 
347  // If requested, fill associated seeds.
348  if(!fUsePFParticleSeeds) continue;
349  art::PtrVector<recob::Seed>& seeds = kalman_input.seeds;
350  std::vector<art::Ptr<recob::Seed> > seedVec = seedAssns.at(partIdx);
351  seeds.insert(seeds.end(), seedVec.begin(), seedVec.end());
352  art::FindManyP<recob::Hit> seedHitAssns(seedVec, evt, fPFParticleModuleLabel);
353 
354  for(size_t seedIdx = 0; seedIdx < seedVec.size(); ++seedIdx) {
355  std::vector<art::Ptr<recob::Hit> > seedHitVec;
356  //SS: why seedIdx can have an invalid value?
357  try {
358  seedHitVec = seedHitAssns.at(seedIdx);
359  }
360  catch(art::Exception x) {
361  seedHitVec.clear();
362  }
363  kalman_input.seedhits.emplace_back();
364  Hits& seedhits = kalman_input.seedhits.back();
365  seedhits.insert(seedhits.end(), seedHitVec.begin(), seedHitVec.end());
366  }
367  }
368  return inputs;
369 }
370 
371 //-------------------------------------------------------------------------------------
373  std::vector<KalmanOutput> const &outputs,
374  KalmanInputs const &inputs,
375  std::vector<recob::Track> &tracks,
376  std::vector<recob::SpacePoint> &spts,
382 {
383  if(outputs.size()!= inputs.size()) return;
384 
385  size_t tracksSize(0);
386  for(auto const &kalman_output : outputs) {
387  tracksSize += kalman_output.tracks.size();
388  }
389  tracks.reserve(tracksSize);
390 
391  auto const tid = getProductID<std::vector<recob::Track> >();
392  auto const tidgetter = evt.productGetter(tid);
393 
394  auto const spacepointId = getProductID<std::vector<recob::SpacePoint> >();
395  auto const getter = evt.productGetter(spacepointId);
396  for (size_t i = 0; i<outputs.size();++i) {
397  // Recover the kalman tracks double ended queue
398  const std::deque<KGTrack>& kalman_tracks = outputs[i].tracks;
399 
400  for(auto const& kalman_track:kalman_tracks) {
401 
402  // Add Track object to collection.
404  kalman_track.fillTrack(track, tracks.size());
405  if(track.NumberTrajectoryPoints() < 2) {
406  continue;
407  }
408  unsigned int numtrajpts = track.NumberTrajectoryPoints();
409  tracks.emplace_back(std::move(track));
410  // SS: tracks->size() does not change after this point in each iteration
411 
412  //fill hits from this track
413  Hits trhits;
414  std::vector<unsigned int> hittpindex; //hit-trajectory point index
415  kalman_track.fillHits(trhits, hittpindex);
416  if (hittpindex.back()>=numtrajpts){ //something is wrong
417  throw cet::exception("Track3DKalmanHit")
418  << "Last hit corresponds to trajectory point index "<<hittpindex.back()<<" while the number of trajectory points is "<<numtrajpts<<'\n';
419  }
420 
421  // Make space points from this track.
422  auto nspt = spts.size();
423  fSpacePointAlg.fillSpacePoints(spts, kalman_track.TrackMap());
424 
425  std::vector<art::Ptr<recob::SpacePoint>> sptvec;
426  for(auto ispt = nspt; ispt < spts.size(); ++ispt) {
427  sptvec.emplace_back(spacepointId, ispt, getter);
428  // Associate newly created space points with hits.
429  // Make space point to hit associations.
430  auto const &sphits = fSpacePointAlg.getAssociatedHits((spts)[ispt]);
431  for(auto const& sphit: sphits) {
432  sph_assn.addSingle(sptvec.back(), sphit);
433  }
434  }
435 
436  art::Ptr<recob::Track> aptr(tid, tracks.size()-1, tidgetter);
437 
438  // Make Track to Hit associations.
439  for (size_t h = 0; h< trhits.size(); ++h){
440  th_assn.addSingle(aptr, trhits[h]);
441  recob::TrackHitMeta metadata(hittpindex[h], -1);
442  thm_assn.addSingle(aptr, trhits[h], metadata);
443  }
444 
445  // Make track to space point associations
446  for (auto const& spt: sptvec) {
447  tsp_assn.addSingle(aptr, spt);
448  }
449 
450  // Optionally fill track-to-PFParticle associations.
451  if (fUsePFParticleHits) {
452  pfPartTrack_assns.addSingle(inputs[i].pfPartPtr, aptr);
453  }
454  } // end of loop over a given collection
455  }
456 }
457 
458 //----------------------------------------------------------------------------
460 //fHPull and fHIncChisq are private data members of the class Track3DKalmanHit
461 
462 void trkf::Track3DKalmanHit::fillHistograms(std::vector<KalmanOutput>& outputs)
463 {
464  for(auto const &output : outputs) {
465  const std::deque<KGTrack>& kalman_tracks = output.tracks;
466  for (size_t i = 0; i < kalman_tracks.size(); ++i) {
467  const KGTrack& trg = kalman_tracks[i];
468  // Loop over measurements in this track.
469  const std::multimap<double, KHitTrack>& trackmap = trg.getTrackMap();
470  for(std::multimap<double, KHitTrack>::const_iterator ih = trackmap.begin();
471  ih != trackmap.end(); ++ih) {
472  const KHitTrack& trh = (*ih).second;
473  const std::shared_ptr<const KHitBase>& hit = trh.getHit();
474  double chisq = hit->getChisq();
475  fHIncChisq->Fill(chisq);
476  const KHit<1>* ph1 = dynamic_cast<const KHit<1>*>(&*hit);
477  if(ph1 != 0) {
478  double pull = ph1->getResVector()(0) / std::sqrt(ph1->getResError()(0, 0));
479  fHPull->Fill(pull);
480  }
481  }
482  }
483  }
484 }
485 
486 
487 
Float_t x
Definition: compare.C:6
art::Ptr< recob::PFParticle > pfPartPtr
void reserve(size_type n)
Definition: PtrVector.h:343
bool fUseClusterHits
Use clustered hits as input.
const std::shared_ptr< const KHitBase > & getHit() const
Measurement.
Definition: KHitTrack.h:53
std::string fHitModuleLabel
Unclustered Hits.
Track3DKalmanHitAlg fTKHAlg
Track3DKalmanHit algorithm.
bool fUsePFParticleSeeds
Use PFParticle seeds.
KalmanInputs getInput(const art::Event &evt) const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
virtual void beginJob() override
Begin job method.
Declaration of signal hit object.
std::string fPFParticleModuleLabel
PFParticle label.
std::vector< trkf::KalmanOutput > makeTracks(KalmanInputs &kalman_inputs)
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:109
Class to keep data related to recob::Hit associated with recob::Track.
std::string fClusterModuleLabel
Clustered Hits.
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
Cluster finding and building.
EDProductGetter const * productGetter(ProductID const) const
Definition: Event.cc:64
Track3DKalmanHit(fhicl::ParameterSet const &pset)
const KVector< N >::type & getResVector() const
Residual vector.
Definition: KHit.h:114
Track3DKalmanHit Algorithm.
const art::PtrVector< recob::Hit > & getAssociatedHits(const recob::SpacePoint &spt) const
SpacePointAlg fSpacePointAlg
Space point algorithm.
const std::multimap< double, KHitTrack > & getTrackMap() const
KHitTrack collection, indexed by path distance.
Definition: KGTrack.h:54
TFileDirectory mkdir(std::string const &dir, std::string const &descr="")
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
bool isValid() const
Definition: Handle.h:190
void fillSpacePoints(std::vector< recob::SpacePoint > &spts, std::multimap< double, KHitTrack > const &trackMap) const
Fill a collection of space points.
const KSymMatrix< N >::type & getResError() const
Residual error matrix.
Definition: KHit.h:117
Hits getClusteredHits(const art::Event &evt) const
Fill a collection using clustered hits.
void hits()
Definition: readHits.C:15
art::PtrVector< recob::Hit > hits
intermediate_table::const_iterator const_iterator
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:441
parameter set interface
T get(std::string const &key) const
Definition: ParameterSet.h:231
iterator end()
Definition: PtrVector.h:237
Hits getAllHits(const art::Event &evt) const
If both UseClusteredHits and UsePFParticles is false use this method to fill in hits.
std::vector< art::PtrVector< recob::Hit > > seedhits
void fillHistograms(std::vector< KalmanOutput > &outputs)
Fill Histograms method.
Declaration of cluster object.
Provides recob::Track data product.
void reconfigure(const fhicl::ParameterSet &pset)
Reconfigure method.
size_type size() const
Definition: PtrVector.h:308
Detector simulation of raw signals on wires.
void createOutputs(const art::Event &evt, const std::vector< KalmanOutput > &outputs, const KalmanInputs &inputs, std::vector< recob::Track > &tracks, std::vector< recob::SpacePoint > &spts, art::Assns< recob::Track, recob::Hit > &th_assn, art::Assns< recob::Track, recob::Hit, recob::TrackHitMeta > &thm_assn, art::Assns< recob::Track, recob::SpacePoint > &tsp_assn, art::Assns< recob::SpacePoint, recob::Hit > &sph_assn, art::Assns< recob::PFParticle, recob::Track > &pfPartTrack_assns)
void reconfigure(const fhicl::ParameterSet &pset)
int fNumEvent
Number of events seen.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void clearHitMap() const
iterator insert(iterator position, Ptr< U > const &p)
T * make(ARGS...args) const
Utility object to perform functions of association.
bool fUsePFParticleHits
Use PFParticle hits as input.
TDirectory * dir
Definition: macro.C:5
virtual void produce(art::Event &e) override
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
void addSingle(Ptr< left_t > const &left, Ptr< right_t > const &right, data_t const &data)
Definition: Assns.h:489
virtual void reconfigure(fhicl::ParameterSet const &pset)
Float_t e
Definition: plot.C:34
Algorithm for generating space points from hits.
Float_t track
Definition: plot.C:34
std::vector< KalmanInput > KalmanInputs
virtual void endJob() override
End job method.
TH1F * fHIncChisq
Incremental chisquare.
art framework interface to geometry description
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:51
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
art::PtrVector< recob::Seed > seeds
KalmanInputs getPFParticleStuff(const art::Event &evt) const
If UsePFParticles is true use this method to fill in hits.