All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackKalmanCheater_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // 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 //
20 ////////////////////////////////////////////////////////////////////////
21 
22 #include <deque>
23 
24 #include "art/Framework/Core/EDProducer.h"
25 #include "art/Framework/Core/ModuleMacros.h"
26 #include "art/Framework/Principal/Event.h"
27 #include "art_root_io/TFileService.h"
28 #include "canvas/Persistency/Common/FindManyP.h"
29 #include "cetlib_except/exception.h"
30 #include "messagefacility/MessageLogger/MessageLogger.h"
31 
49 #include "nusimdata/SimulationBase/MCParticle.h"
50 
51 #include "TH1F.h"
52 
53 namespace {
54  bool
55  accepted_particle(int apdg)
56  {
57  return apdg == 13 || // Muon
58  apdg == 211 || // Charged pion
59  apdg == 321 || // Charged kaon
60  apdg == 2212; // (Anti)proton
61  }
62 }
63 
64 namespace trkf {
65 
66  class TrackKalmanCheater : public art::EDProducer {
67  public:
68  explicit TrackKalmanCheater(fhicl::ParameterSet const& pset);
69 
70  private:
71  void produce(art::Event& e) override;
72  void beginJob() override;
73  void endJob() override;
74 
75  // Fcl parameters.
76 
77  bool fHist; ///< Make histograms.
78  KalmanFilterAlg fKFAlg; ///< Kalman filter algorithm.
79  SpacePointAlg fSpacePointAlg; ///< Space point algorithm.
80  bool fUseClusterHits; ///< Use cluster hits or all hits?
81  std::string fHitModuleLabel; ///< Unclustered Hits.
82  std::string fClusterModuleLabel; ///< Clustered Hits.
83  double fMaxTcut; ///< Maximum delta ray energy in MeV for restricted dE/dx.
84 
85  // Histograms.
86 
87  TH1F* fHIncChisq{nullptr}; ///< Incremental chisquare.
88  TH1F* fHPull{nullptr}; ///< Hit pull.
89 
90  // Statistics.
91 
92  int fNumEvent{0}; ///< Number of events seen.
93  int fNumTrack{0}; ///< Number of tracks produced.
94  };
95 
96  DEFINE_ART_MODULE(TrackKalmanCheater)
97 
98 } // namespace trkf
99 
100 //------------------------------------------------------------------------------
101 /// Constructor.
102 ///
103 /// Arguments:
104 ///
105 /// p - Fcl parameters.
106 ///
107 trkf::TrackKalmanCheater::TrackKalmanCheater(fhicl::ParameterSet const& pset)
108  : EDProducer{pset}
109  , fHist(pset.get<bool>("Hist"))
110  , fKFAlg(pset.get<fhicl::ParameterSet>("KalmanFilterAlg"))
111  , fSpacePointAlg(pset.get<fhicl::ParameterSet>("SpacePointAlg"))
112  , fUseClusterHits(pset.get<bool>("UseClusterHits"))
113  , fHitModuleLabel{pset.get<std::string>("HitModuleLabel")}
114  , fClusterModuleLabel{pset.get<std::string>("ClusterModuleLabel")}
115  , fMaxTcut(pset.get<double>("MaxTcut"))
116 {
117  produces<std::vector<recob::Track>>();
118  produces<std::vector<recob::SpacePoint>>();
119  produces<art::Assns<recob::Track, recob::Hit>>();
120  produces<art::Assns<recob::Track, recob::SpacePoint>>();
121  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
122 
123  // Report.
124 
125  mf::LogInfo("TrackKalmanCheater")
126  << "TrackKalmanCheater configured with the following parameters:\n"
127  << " UseClusterHits = " << fUseClusterHits << "\n"
128  << " HitModuleLabel = " << fHitModuleLabel << "\n"
129  << " ClusterModuleLabel = " << fClusterModuleLabel;
130 }
131 
132 //------------------------------------------------------------------------------
133 /// Begin job method.
134 void
136 {
137  if (fHist) {
138 
139  // Book histograms.
140 
141  art::ServiceHandle<art::TFileService> tfs;
142  art::TFileDirectory dir = tfs->mkdir("hitkalman", "TrackKalmanCheater histograms");
143 
144  fHIncChisq = dir.make<TH1F>("IncChisq", "Incremental Chisquare", 100, 0., 20.);
145  fHPull = dir.make<TH1F>("Pull", "Hit Pull", 100, -10., 10.);
146  }
147 }
148 
149 //------------------------------------------------------------------------------
150 /// Produce method.
151 ///
152 /// Arguments:
153 ///
154 /// e - Art event.
155 ///
156 /// This method extracts Hit from the event and produces and adds
157 /// Track objects.
158 ///
159 void
161 {
162  ++fNumEvent;
163 
164  // Make a collection of tracks, plus associations, that will
165  // eventually be inserted into the event.
166 
167  std::unique_ptr<std::vector<recob::Track>> tracks(new std::vector<recob::Track>);
168  std::unique_ptr<art::Assns<recob::Track, recob::Hit>> th_assn(
169  new art::Assns<recob::Track, recob::Hit>);
170  std::unique_ptr<art::Assns<recob::Track, recob::SpacePoint>> tsp_assn(
171  new art::Assns<recob::Track, recob::SpacePoint>);
172 
173  // Make a collection of space points, plus associations, that will
174  // be inserted into the event.
175 
176  std::unique_ptr<std::vector<recob::SpacePoint>> spts(new std::vector<recob::SpacePoint>);
177  std::unique_ptr<art::Assns<recob::SpacePoint, recob::Hit>> sph_assn(
178  new art::Assns<recob::SpacePoint, recob::Hit>);
179 
180  // Make a collection of KGTracks where we will save our results.
181 
182  std::deque<KGTrack> kalman_tracks;
183 
184  // Get Services.
185 
186  art::ServiceHandle<geo::Geometry const> geom;
187  art::ServiceHandle<cheat::BackTrackerService const> bt_serv;
188  art::ServiceHandle<cheat::ParticleInventoryService const> pi_serv;
189  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
190 
191  // Reset space point algorithm.
192 
193  fSpacePointAlg.clearHitMap();
194 
195  // Get Hits.
196 
197  art::PtrVector<recob::Hit> hits;
198 
199  if (fUseClusterHits) {
200 
201  // Get clusters.
202 
203  art::Handle<std::vector<recob::Cluster>> clusterh;
204  evt.getByLabel(fClusterModuleLabel, clusterh);
205 
206  // Get hits from all clusters.
207  art::FindManyP<recob::Hit> fm(clusterh, evt, fClusterModuleLabel);
208 
209  if (clusterh.isValid()) {
210  int nclus = clusterh->size();
211 
212  for (int i = 0; i < nclus; ++i) {
213  art::Ptr<recob::Cluster> pclus(clusterh, i);
214  std::vector<art::Ptr<recob::Hit>> clushits = fm.at(i);
215  int nhits = clushits.size();
216  hits.reserve(hits.size() + nhits);
217 
218  for (std::vector<art::Ptr<recob::Hit>>::const_iterator ihit = clushits.begin();
219  ihit != clushits.end();
220  ++ihit) {
221  hits.push_back(*ihit);
222  }
223  }
224  }
225  }
226  else {
227 
228  // Get unclustered hits.
229 
230  art::Handle<std::vector<recob::Hit>> hith;
231  evt.getByLabel(fHitModuleLabel, hith);
232  if (hith.isValid()) {
233  int nhits = hith->size();
234  hits.reserve(nhits);
235 
236  for (int i = 0; i < nhits; ++i)
237  hits.push_back(art::Ptr<recob::Hit>(hith, i));
238  }
239  }
240 
241  // Sort hits into separate PtrVectors based on track id.
242 
243  std::map<int, art::PtrVector<recob::Hit>> hitmap;
244 
245  // Loop over hits.
246 
247  for (art::PtrVector<recob::Hit>::const_iterator ihit = hits.begin(); ihit != hits.end(); ++ihit) {
248  //const recob::Hit& hit = **ihit;
249 
250  // Get track ids for this hit.
251 
252  std::vector<sim::TrackIDE> tids = bt_serv->HitToTrackIDEs(clockData, *ihit);
253 
254  // Loop over track ids.
255 
256  for (std::vector<sim::TrackIDE>::const_iterator itid = tids.begin(); itid != tids.end();
257  ++itid) {
258  int trackID = itid->trackID;
259 
260  // Add hit to PtrVector corresponding to this track id.
261 
262  hitmap[trackID].push_back(*ihit);
263  }
264  }
265 
266  // Extract geant mc particles.
267 
268  sim::ParticleList const& plist = pi_serv->ParticleList();
269 
270  auto const det_prop =
271  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt);
272 
273  PropYZPlane const prop{det_prop, fMaxTcut, true};
274 
275  // Loop over geant particles.
276 
277  {
278  // use mf::LogDebug instead of MF_LOG_DEBUG because we reuse it in many lines;
279  // insertions are protected by mf::isDebugEnabled()
280  mf::LogDebug log("TrackKalmanCheater");
281  for (sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
282  const simb::MCParticle* part = (*ipart).second;
283  if (!part) throw cet::exception("TrackKalmanCheater") << "no particle!\n";
284  int pdg = part->PdgCode();
285 
286  // Ignore everything except stable charged nonshowering particles.
287 
288  int apdg = std::abs(pdg);
289  if (not accepted_particle(apdg)) { continue; }
290 
291  int trackid = part->TrackId();
292  int stat = part->StatusCode();
293  int nhit = 0;
294  if (hitmap.count(trackid) != 0) nhit = hitmap[trackid].size();
295  const TLorentzVector& pos = part->Position();
296  const TLorentzVector& mom = part->Momentum();
297 
298  if (mf::isDebugEnabled()) {
299  log << "Trackid=" << trackid << ", pdgid=" << pdg << ", status=" << stat
300  << ", NHit=" << nhit << "\n"
301  << " x = " << pos.X() << ", y = " << pos.Y() << ", z = " << pos.Z() << "\n"
302  << " px= " << mom.Px() << ", py= " << mom.Py() << ", pz= " << mom.Pz() << "\n";
303  } // if debugging
304 
305  double x = pos.X();
306  double y = pos.Y();
307  double z = pos.Z();
308  double px = mom.Px();
309  double py = mom.Py();
310  double pz = mom.Pz();
311  double p = std::hypot(px, py, pz);
312 
313  if (nhit > 0 && pz != 0.) {
314  const art::PtrVector<recob::Hit>& trackhits = hitmap[trackid];
315  if (trackhits.empty()) throw cet::exception("TrackKalmanCheater") << "No hits in track\n";
316 
317  // Make a seed track (KTrack).
318 
319  std::shared_ptr<const Surface> psurf(new SurfYZPlane(0., y, z, 0.));
320  TrackVector vec(5);
321  vec(0) = x;
322  vec(1) = 0.;
323  vec(2) = px / pz;
324  vec(3) = py / pz;
325  vec(4) = 1. / p;
327  KTrack trk(psurf, vec, dir, pdg);
328 
329  // Fill KHitContainer with hits.
330 
331  KHitContainerWireX cont;
332  cont.fill(det_prop, trackhits, -1);
333 
334  // Count hits in each plane. Set the preferred plane to be
335  // the one with the most hits.
336 
337  std::vector<unsigned int> planehits(3, 0);
338  for (art::PtrVector<recob::Hit>::const_iterator ih = trackhits.begin();
339  ih != trackhits.end();
340  ++ih) {
341  const recob::Hit& hit = **ih;
342  unsigned int plane = hit.WireID().Plane;
343 
344  if (plane >= planehits.size()) {
345  throw cet::exception("TrackKalmanCheater") << "plane " << plane << "...\n";
346  }
347  ++planehits[plane];
348  }
349  unsigned int prefplane = 0;
350  for (unsigned int i = 0; i < planehits.size(); ++i) {
351  if (planehits[i] > planehits[prefplane]) prefplane = i;
352  }
353  if (mf::isDebugEnabled()) log << "Preferred plane = " << prefplane << "\n";
354 
355  // Build and smooth track.
356 
357  KGTrack trg(prefplane);
358  fKFAlg.setPlane(prefplane);
359  if (fKFAlg.buildTrack(trk, trg, prop, Propagator::FORWARD, cont, false)) {
360  if (fKFAlg.smoothTrackIter(5, trg, prop)) {
361  KETrack tremom;
362  if (fKFAlg.fitMomentum(trg, prop, tremom)) { fKFAlg.updateMomentum(tremom, prop, trg); }
363  ++fNumTrack;
364  kalman_tracks.push_back(trg);
365  }
366  }
367  }
368  }
369  }
370 
371  // Fill histograms.
372 
373  if (fHist) {
374 
375  // First loop over tracks.
376 
377  for (auto const& trg : kalman_tracks) {
378 
379  // Loop over measurements in this track.
380 
381  const std::multimap<double, KHitTrack>& trackmap = trg.getTrackMap();
382  for (std::multimap<double, KHitTrack>::const_iterator ih = trackmap.begin();
383  ih != trackmap.end();
384  ++ih) {
385  const KHitTrack& trh = (*ih).second;
386  const std::shared_ptr<const KHitBase>& hit = trh.getHit();
387  double chisq = hit->getChisq();
388  fHIncChisq->Fill(chisq);
389  const KHit<1>* ph1 = dynamic_cast<const KHit<1>*>(&*hit);
390  if (ph1 != 0) {
391  double pull = ph1->getResVector()(0) / std::sqrt(ph1->getResError()(0, 0));
392  fHPull->Fill(pull);
393  }
394  }
395  }
396  }
397 
398  // Process Kalman filter tracks into persistent objects.
399 
400  tracks->reserve(kalman_tracks.size());
401  for (auto const& kalman_track : kalman_tracks) {
402  tracks->push_back(recob::Track());
403  kalman_track.fillTrack(det_prop, tracks->back(), tracks->size() - 1);
404 
405  // Make Track to Hit associations.
406 
407  art::PtrVector<recob::Hit> trhits;
408  std::vector<unsigned int> hittpindex;
409  kalman_track.fillHits(hits, hittpindex);
410  util::CreateAssn(evt, *tracks, trhits, *th_assn, tracks->size() - 1);
411 
412  // Make space points from this track.
413 
414  int nspt = spts->size();
415  fSpacePointAlg.fillSpacePoints(det_prop, *spts, kalman_track.TrackMap());
416 
417  // Associate newly created space points with hits.
418  // Also associate track with newly created space points.
419 
420  art::PtrVector<recob::SpacePoint> sptvec;
421 
422  // Loop over newly created space points.
423 
424  for (unsigned int ispt = nspt; ispt < spts->size(); ++ispt) {
425  const recob::SpacePoint& spt = (*spts)[ispt];
426  art::ProductID sptid = evt.getProductID<std::vector<recob::SpacePoint>>();
427  art::Ptr<recob::SpacePoint> sptptr(sptid, ispt, evt.productGetter(sptid));
428  sptvec.push_back(sptptr);
429 
430  // Make space point to hit associations.
431 
432  const art::PtrVector<recob::Hit>& sphits = fSpacePointAlg.getAssociatedHits(spt);
433  util::CreateAssn(evt, *spts, sphits, *sph_assn, ispt);
434  }
435 
436  // Make track to space point associations.
437 
438  util::CreateAssn(evt, *tracks, sptvec, *tsp_assn, tracks->size() - 1);
439  }
440 
441  // Add tracks and associations to event.
442 
443  evt.put(std::move(tracks));
444  evt.put(std::move(spts));
445  evt.put(std::move(th_assn));
446  evt.put(std::move(tsp_assn));
447  evt.put(std::move(sph_assn));
448 }
449 
450 //------------------------------------------------------------------------------
451 /// End job method.
452 void
454 {
455  mf::LogInfo("TrackKalmanCheater") << "TrackKalmanCheater statistics:\n"
456  << " Number of events = " << fNumEvent << "\n"
457  << " Number of tracks created = " << fNumTrack;
458 }
void endJob() override
End job method.
process_name opflash particleana ie ie ie z
TrackDirection
Track direction enum.
Basic Kalman filter track class, plus one measurement on same surface.
const std::shared_ptr< const KHitBase > & getHit() const
Measurement.
Definition: KHitTrack.h:53
Propagate to PropYZPlane surface.
var pdg
Definition: selectors.fcl:14
void fill(const detinfo::DetectorPropertiesData &clock_data, const art::PtrVector< recob::Hit > &hits, int only_plane) override
ClusterModuleLabel join with tracks
A KHitContainer for KHitWireX type measurements.
process_name opflash particleana ie x
BEGIN_PROLOG pz
Definition: filemuons.fcl:10
std::string fClusterModuleLabel
Clustered Hits.
geo::WireID WireID() const
Definition: Hit.h:233
Planar surface parallel to x-axis.
Declaration of signal hit object.
pdgs p
Definition: selectors.fcl:22
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
process_name hit
Definition: cheaterreco.fcl:51
KalmanFilterAlg fKFAlg
Kalman filter algorithm.
const KVector< N >::type & getResVector() const
Residual vector.
Definition: KHit.h:138
int fNumEvent
Number of events seen.
std::string fHitModuleLabel
Unclustered Hits.
void produce(art::Event &e) override
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:265
T abs(T value)
TrackKalmanCheater(fhicl::ParameterSet const &pset)
const KSymMatrix< N >::type & getResError() const
Residual error matrix.
Definition: KHit.h:145
process_name opflash particleana ie ie y
Kalman filter measurement class template.
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:493
Declaration of cluster object.
Kalman Filter.
Provides recob::Track data product.
tuple dir
Definition: dropbox.py:28
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.
BEGIN_PROLOG px
Definition: filemuons.fcl:10
int fNumTrack
Number of tracks produced.
process_name physics producers generator physics producers generator physics producers generator py
SpacePointAlg fSpacePointAlg
Space point algorithm.
do i e
TH1F * fHIncChisq
Incremental chisquare.
A collection of KHitTracks.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8
double fMaxTcut
Maximum delta ray energy in MeV for restricted dE/dx.
Algorithm for generating space points from hits.
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 &quot;fitted&quot; track: