LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
TrackKalmanCheater_module.cc
Go to the documentation of this file.
1 // Class: TrackKalmanCheater
3 // Module Type: producer
4 // File: TrackKalmanCheater.h
5 //
6 // This class produces RecoBase/Track objects using KalmanFilterService.
7 // MC truth information is used to associate Hits used as input to
8 // the Kalman filter.
9 //
10 // Configuration parameters:
11 //
12 // Hist - Histogram flag (generate histograms if true).
13 // UseClusterHits - Use clustered hits if true, use all hits if false.
14 // HitModuleLabel - Module label for unclustered Hits.
15 // ClusterModuleLabel - Module label for Clusters.
16 // MaxTcut - Maximum delta ray energy in Mev for dE/dx.
17 // KalmanFilterAlg - Parameter set for KalmanFilterAlg.
18 // SpacePointAlg - Parmaeter set for space points.
19 //
21 
22 #include <deque>
23 
27 #include "art_root_io/TFileService.h"
29 #include "cetlib_except/exception.h"
31 
50 
51 #include "TH1F.h"
52 
53 namespace {
54  bool accepted_particle(int apdg)
55  {
56  return apdg == 13 || // Muon
57  apdg == 211 || // Charged pion
58  apdg == 321 || // Charged kaon
59  apdg == 2212; // (Anti)proton
60  }
61 }
62 
63 namespace trkf {
64 
66  public:
67  explicit TrackKalmanCheater(fhicl::ParameterSet const& pset);
68 
69  private:
70  void produce(art::Event& e) override;
71  void beginJob() override;
72  void endJob() override;
73 
74  // Fcl parameters.
75 
76  bool fHist;
80  std::string fHitModuleLabel;
81  std::string fClusterModuleLabel;
82  double fMaxTcut;
83 
84  // Histograms.
85 
86  TH1F* fHIncChisq{nullptr};
87  TH1F* fHPull{nullptr};
88 
89  // Statistics.
90 
91  int fNumEvent{0};
92  int fNumTrack{0};
93  };
94 
96 
97 } // namespace trkf
98 
99 //------------------------------------------------------------------------------
107  : EDProducer{pset}
108  , fHist(pset.get<bool>("Hist"))
109  , fKFAlg(pset.get<fhicl::ParameterSet>("KalmanFilterAlg"))
110  , fSpacePointAlg(pset.get<fhicl::ParameterSet>("SpacePointAlg"))
111  , fUseClusterHits(pset.get<bool>("UseClusterHits"))
112  , fHitModuleLabel{pset.get<std::string>("HitModuleLabel")}
113  , fClusterModuleLabel{pset.get<std::string>("ClusterModuleLabel")}
114  , fMaxTcut(pset.get<double>("MaxTcut"))
115 {
116  produces<std::vector<recob::Track>>();
117  produces<std::vector<recob::SpacePoint>>();
118  produces<art::Assns<recob::Track, recob::Hit>>();
119  produces<art::Assns<recob::Track, recob::SpacePoint>>();
120  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
121 
122  // Report.
123 
124  mf::LogInfo("TrackKalmanCheater")
125  << "TrackKalmanCheater configured with the following parameters:\n"
126  << " UseClusterHits = " << fUseClusterHits << "\n"
127  << " HitModuleLabel = " << fHitModuleLabel << "\n"
128  << " ClusterModuleLabel = " << fClusterModuleLabel;
129 }
130 
131 //------------------------------------------------------------------------------
134 {
135  if (fHist) {
136 
137  // Book histograms.
138 
140  art::TFileDirectory dir = tfs->mkdir("hitkalman", "TrackKalmanCheater histograms");
141 
142  fHIncChisq = dir.make<TH1F>("IncChisq", "Incremental Chisquare", 100, 0., 20.);
143  fHPull = dir.make<TH1F>("Pull", "Hit Pull", 100, -10., 10.);
144  }
145 }
146 
147 //------------------------------------------------------------------------------
158 {
159  ++fNumEvent;
160 
161  // Make a collection of tracks, plus associations, that will
162  // eventually be inserted into the event.
163 
164  std::unique_ptr<std::vector<recob::Track>> tracks(new std::vector<recob::Track>);
165  std::unique_ptr<art::Assns<recob::Track, recob::Hit>> th_assn(
167  std::unique_ptr<art::Assns<recob::Track, recob::SpacePoint>> tsp_assn(
169 
170  // Make a collection of space points, plus associations, that will
171  // be inserted into the event.
172 
173  std::unique_ptr<std::vector<recob::SpacePoint>> spts(new std::vector<recob::SpacePoint>);
174  std::unique_ptr<art::Assns<recob::SpacePoint, recob::Hit>> sph_assn(
176 
177  // Make a collection of KGTracks where we will save our results.
178 
179  std::deque<KGTrack> kalman_tracks;
180 
181  // Get Services.
182 
186  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
187 
188  // Reset space point algorithm.
189 
191 
192  // Get Hits.
193 
195 
196  if (fUseClusterHits) {
197 
198  // Get clusters.
199 
201  evt.getByLabel(fClusterModuleLabel, clusterh);
202 
203  // Get hits from all clusters.
205 
206  if (clusterh.isValid()) {
207  int nclus = clusterh->size();
208 
209  for (int i = 0; i < nclus; ++i) {
210  art::Ptr<recob::Cluster> pclus(clusterh, i);
211  std::vector<art::Ptr<recob::Hit>> clushits = fm.at(i);
212  int nhits = clushits.size();
213  hits.reserve(hits.size() + nhits);
214 
215  for (std::vector<art::Ptr<recob::Hit>>::const_iterator ihit = clushits.begin();
216  ihit != clushits.end();
217  ++ihit) {
218  hits.push_back(*ihit);
219  }
220  }
221  }
222  }
223  else {
224 
225  // Get unclustered hits.
226 
228  evt.getByLabel(fHitModuleLabel, hith);
229  if (hith.isValid()) {
230  int nhits = hith->size();
231  hits.reserve(nhits);
232 
233  for (int i = 0; i < nhits; ++i)
234  hits.push_back(art::Ptr<recob::Hit>(hith, i));
235  }
236  }
237 
238  // Sort hits into separate PtrVectors based on track id.
239 
240  std::map<int, art::PtrVector<recob::Hit>> hitmap;
241 
242  // Loop over hits.
243 
244  for (art::PtrVector<recob::Hit>::const_iterator ihit = hits.begin(); ihit != hits.end(); ++ihit) {
245  //const recob::Hit& hit = **ihit;
246 
247  // Get track ids for this hit.
248 
249  std::vector<sim::TrackIDE> tids = bt_serv->HitToTrackIDEs(clockData, *ihit);
250 
251  // Loop over track ids.
252 
253  for (std::vector<sim::TrackIDE>::const_iterator itid = tids.begin(); itid != tids.end();
254  ++itid) {
255  int trackID = itid->trackID;
256 
257  // Add hit to PtrVector corresponding to this track id.
258 
259  hitmap[trackID].push_back(*ihit);
260  }
261  }
262 
263  // Extract geant mc particles.
264 
265  sim::ParticleList const& plist = pi_serv->ParticleList();
266 
267  auto const det_prop =
269 
270  PropYZPlane const prop{det_prop, fMaxTcut, true};
271 
272  // Loop over geant particles.
273 
274  {
275  // use mf::LogDebug instead of MF_LOG_DEBUG because we reuse it in many lines;
276  // insertions are protected by mf::isDebugEnabled()
277  mf::LogDebug log("TrackKalmanCheater");
278  for (sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
279  const simb::MCParticle* part = (*ipart).second;
280  if (!part) throw cet::exception("TrackKalmanCheater") << "no particle!\n";
281  int pdg = part->PdgCode();
282 
283  // Ignore everything except stable charged nonshowering particles.
284 
285  int apdg = std::abs(pdg);
286  if (not accepted_particle(apdg)) { continue; }
287 
288  int trackid = part->TrackId();
289  int stat = part->StatusCode();
290  int nhit = 0;
291  if (hitmap.count(trackid) != 0) nhit = hitmap[trackid].size();
292  const TLorentzVector& pos = part->Position();
293  const TLorentzVector& mom = part->Momentum();
294 
295  if (mf::isDebugEnabled()) {
296  log << "Trackid=" << trackid << ", pdgid=" << pdg << ", status=" << stat
297  << ", NHit=" << nhit << "\n"
298  << " x = " << pos.X() << ", y = " << pos.Y() << ", z = " << pos.Z() << "\n"
299  << " px= " << mom.Px() << ", py= " << mom.Py() << ", pz= " << mom.Pz() << "\n";
300  } // if debugging
301 
302  double x = pos.X();
303  double y = pos.Y();
304  double z = pos.Z();
305  double px = mom.Px();
306  double py = mom.Py();
307  double pz = mom.Pz();
308  double p = std::hypot(px, py, pz);
309 
310  if (nhit > 0 && pz != 0.) {
311  const art::PtrVector<recob::Hit>& trackhits = hitmap[trackid];
312  if (trackhits.empty()) throw cet::exception("TrackKalmanCheater") << "No hits in track\n";
313 
314  // Make a seed track (KTrack).
315 
316  std::shared_ptr<const Surface> psurf(new SurfYZPlane(0., y, z, 0.));
317  TrackVector vec(5);
318  vec(0) = x;
319  vec(1) = 0.;
320  vec(2) = px / pz;
321  vec(3) = py / pz;
322  vec(4) = 1. / p;
324  KTrack trk(psurf, vec, dir, pdg);
325 
326  // Fill KHitContainer with hits.
327 
328  KHitContainerWireX cont;
329  cont.fill(det_prop, trackhits, -1);
330 
331  // Count hits in each plane. Set the preferred plane to be
332  // the one with the most hits.
333 
334  std::vector<unsigned int> planehits(3, 0);
336  ih != trackhits.end();
337  ++ih) {
338  const recob::Hit& hit = **ih;
339  unsigned int plane = hit.WireID().Plane;
340 
341  if (plane >= planehits.size()) {
342  throw cet::exception("TrackKalmanCheater") << "plane " << plane << "...\n";
343  }
344  ++planehits[plane];
345  }
346  unsigned int prefplane = 0;
347  for (unsigned int i = 0; i < planehits.size(); ++i) {
348  if (planehits[i] > planehits[prefplane]) prefplane = i;
349  }
350  if (mf::isDebugEnabled()) log << "Preferred plane = " << prefplane << "\n";
351 
352  // Build and smooth track.
353 
354  KGTrack trg(prefplane);
355  fKFAlg.setPlane(prefplane);
356  if (fKFAlg.buildTrack(trk, trg, prop, Propagator::FORWARD, cont, false)) {
357  if (fKFAlg.smoothTrackIter(5, trg, prop)) {
358  KETrack tremom;
359  if (fKFAlg.fitMomentum(trg, prop, tremom)) { fKFAlg.updateMomentum(tremom, prop, trg); }
360  ++fNumTrack;
361  kalman_tracks.push_back(trg);
362  }
363  }
364  }
365  }
366  }
367 
368  // Fill histograms.
369 
370  if (fHist) {
371 
372  // First loop over tracks.
373 
374  for (auto const& trg : kalman_tracks) {
375 
376  // Loop over measurements in this track.
377 
378  const std::multimap<double, KHitTrack>& trackmap = trg.getTrackMap();
379  for (std::multimap<double, KHitTrack>::const_iterator ih = trackmap.begin();
380  ih != trackmap.end();
381  ++ih) {
382  const KHitTrack& trh = (*ih).second;
383  const std::shared_ptr<const KHitBase>& hit = trh.getHit();
384  double chisq = hit->getChisq();
385  fHIncChisq->Fill(chisq);
386  const KHit<1>* ph1 = dynamic_cast<const KHit<1>*>(&*hit);
387  if (ph1 != 0) {
388  double pull = ph1->getResVector()(0) / std::sqrt(ph1->getResError()(0, 0));
389  fHPull->Fill(pull);
390  }
391  }
392  }
393  }
394 
395  // Process Kalman filter tracks into persistent objects.
396 
397  tracks->reserve(kalman_tracks.size());
398  for (auto const& kalman_track : kalman_tracks) {
399  tracks->push_back(recob::Track());
400  kalman_track.fillTrack(det_prop, tracks->back(), tracks->size() - 1);
401 
402  // Make Track to Hit associations.
403 
405  std::vector<unsigned int> hittpindex;
406  kalman_track.fillHits(hits, hittpindex);
407  util::CreateAssn(evt, *tracks, trhits, *th_assn, tracks->size() - 1);
408 
409  // Make space points from this track.
410 
411  int nspt = spts->size();
412  fSpacePointAlg.fillSpacePoints(det_prop, *spts, kalman_track.TrackMap());
413 
414  // Associate newly created space points with hits.
415  // Also associate track with newly created space points.
416 
418 
419  // Loop over newly created space points.
420 
421  for (unsigned int ispt = nspt; ispt < spts->size(); ++ispt) {
422  const recob::SpacePoint& spt = (*spts)[ispt];
423  art::ProductID sptid = evt.getProductID<std::vector<recob::SpacePoint>>();
424  art::Ptr<recob::SpacePoint> sptptr(sptid, ispt, evt.productGetter(sptid));
425  sptvec.push_back(sptptr);
426 
427  // Make space point to hit associations.
428 
430  util::CreateAssn(evt, *spts, sphits, *sph_assn, ispt);
431  }
432 
433  // Make track to space point associations.
434 
435  util::CreateAssn(evt, *tracks, sptvec, *tsp_assn, tracks->size() - 1);
436  }
437 
438  // Add tracks and associations to event.
439 
440  evt.put(std::move(tracks));
441  evt.put(std::move(spts));
442  evt.put(std::move(th_assn));
443  evt.put(std::move(tsp_assn));
444  evt.put(std::move(sph_assn));
445 }
446 
447 //------------------------------------------------------------------------------
450 {
451  mf::LogInfo("TrackKalmanCheater") << "TrackKalmanCheater statistics:\n"
452  << " Number of events = " << fNumEvent << "\n"
453  << " Number of tracks created = " << fNumTrack;
454 }
Float_t x
Definition: compare.C:6
void endJob() override
End job method.
void reserve(size_type n)
Definition: PtrVector.h:337
TrackDirection
Track direction enum.
Definition: Surface.h:54
Basic Kalman filter track class, plus one measurement on same surface.
const std::shared_ptr< const KHitBase > & getHit() const
Measurement.
Definition: KHitTrack.h:51
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:220
int PdgCode() const
Definition: MCParticle.h:213
Propagate to PropYZPlane surface.
void fill(const detinfo::DetectorPropertiesData &clock_data, const art::PtrVector< recob::Hit > &hits, int only_plane) override
Int_t ipart
Definition: Style.C:10
A KHitContainer for KHitWireX type measurements.
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
bool smoothTrackIter(int niter, KGTrack &trg, const Propagator &prop) const
Iteratively smooth a track.
ProductID getProductID(std::string const &instance_name="") const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::string fClusterModuleLabel
Clustered Hits.
iterator begin()
Definition: PtrVector.h:217
Planar surface parallel to x-axis.
Declaration of signal hit object.
Float_t y
Definition: compare.C:6
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
Double_t z
Definition: plot.C:276
constexpr auto abs(T v)
Returns the absolute value of the argument.
int StatusCode() const
Definition: MCParticle.h:212
intermediate_table::const_iterator const_iterator
geo::WireID const & WireID() const
Initial tdc tick for hit.
Definition: Hit.h:280
KalmanFilterAlg fKFAlg
Kalman filter algorithm.
Particle class.
const KVector< N >::type & getResVector() const
Residual vector.
Definition: KHit.h:113
const art::PtrVector< recob::Hit > & getAssociatedHits(const recob::SpacePoint &spt) const
int fNumEvent
Number of events seen.
int TrackId() const
Definition: MCParticle.h:211
std::string fHitModuleLabel
Unclustered Hits.
void produce(art::Event &e) override
bool isValid() const noexcept
Definition: Handle.h:203
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
bool fUseClusterHits
Use cluster hits or all hits?
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
TString part[npart]
Definition: Style.C:32
TrackKalmanCheater(fhicl::ParameterSet const &pset)
const KSymMatrix< N >::type & getResError() const
Residual error matrix.
Definition: KHit.h:116
void hits()
Definition: readHits.C:15
typename data_t::const_iterator const_iterator
Definition: PtrVector.h:55
bool buildTrack(const KTrack &trk, KGTrack &trg, const Propagator &prop, const Propagator::PropDirection dir, KHitContainer &hits, bool linear) const
Make a new track.
EDProductGetter const * productGetter(ProductID const pid) const
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
Kalman filter measurement class template.
iterator end()
Definition: PtrVector.h:231
iterator begin()
Definition: ParticleList.h:305
Provides recob::Track data product.
bool isDebugEnabled()
void beginJob() override
Begin job method.
KVector< 5 >::type TrackVector
Track state vector, dimension 5.
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
Declaration of cluster object.
bool empty() const
Definition: PtrVector.h:330
Kalman Filter.
size_type size() const
Definition: PtrVector.h:302
void fillSpacePoints(detinfo::DetectorPropertiesData const &detProp, std::vector< recob::SpacePoint > &spts, std::multimap< double, KHitTrack > const &trackMap) const
Fill a collection of space points.
Detector simulation of raw signals on wires.
const sim::ParticleList & ParticleList() const
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.
void clearHitMap() const
int fNumTrack
Number of tracks produced.
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Utility object to perform functions of association.
TDirectory * dir
Definition: macro.C:5
void setPlane(int plane)
Set preferred view plane.
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:221
SpacePointAlg fSpacePointAlg
Space point algorithm.
TH1F * fHIncChisq
Incremental chisquare.
A collection of KHitTracks.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
TCEvent evt
Definition: DataStructs.cxx:8
double fMaxTcut
Maximum delta ray energy in MeV for restricted dE/dx.
Float_t e
Definition: plot.C:35
Algorithm for generating space points from hits.
bool fitMomentum(const KGTrack &trg, const Propagator &prop, KETrack &tremom) const
Estimate track momentum using either range or multiple scattering.
bool updateMomentum(const KETrack &tremom, const Propagator &prop, KGTrack &trg) const
Set track momentum at each track surface.
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:49
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33