LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
CRHitRemovalByPCA_module.cc
Go to the documentation of this file.
1 //
3 // Class: CRHitRemovalByPCA
4 // Module Type: producer
5 // File: CRHitRemovalByPCA_module.cc
6 //
7 // This module produces RecoBase/Hit objects after removing those
8 // deemed to be due to CR muons. Note that it operates ONLY on
9 // CosmicTags which have been produced by the PCAxis CR tagger
10 //
11 // Configuration parameters:
12 //
13 // CosmicProducerLabels - a list of cosmic ray producers which should be or'ed
14 // HitProducerLabel - the producer of the recob::Hit objects
15 // PFParticleProducerLabel - the producer of the recob::PFParticles to consider
16 // CosmicTagThresholds - a vector of thresholds to apply to label as cosmic
17 //
18 // Created by Tracy Usher (usher@slac.stanford.edu) on September 18, 2014
19 //
21 
22 #include <cmath>
23 #include <algorithm>
24 #include <vector>
25 
30 
38 
39 // Local functions.
40 namespace
41 {
42  //----------------------------------------------------------------------------
43  // Filter a collection of hits (set difference).
44  // This function is copied from Track3DKalmanHit_module.cc
45  //
46  // Arguments:
47  //
48  // hits - Hit collection from which hits should be removed.
49  // used_hits - Hits to remove.
50  //
51  void FilterHits(art::PtrVector<recob::Hit>& hits, art::PtrVector<recob::Hit>& used_hits)
52  {
53  if(used_hits.size() > 0)
54  {
55  // Make sure both hit collections are sorted.
56  std::stable_sort(hits.begin(), hits.end());
57  std::stable_sort(used_hits.begin(), used_hits.end());
58 
59  // Do set difference operation.
60  art::PtrVector<recob::Hit>::iterator it = std::set_difference(hits.begin(), hits.end(), used_hits.begin(), used_hits.end(), hits.begin());
61 
62  // Truncate hit collection.
63  hits.erase(it, hits.end());
64  }
65  }
66 }
67 
68 class Propagator;
69 
71 {
72 public:
73 
74  // Copnstructors, destructor.
75  explicit CRHitRemovalByPCA(fhicl::ParameterSet const & pset);
76  virtual ~CRHitRemovalByPCA();
77 
78  // Overrides.
79  virtual void reconfigure(fhicl::ParameterSet const & pset);
80  virtual void produce(art::Event & e);
81  virtual void beginJob();
82  virtual void endJob();
83 
84 private:
85  // Methods
86  void removeTaggedHits(const recob::PFParticle* pfParticle,
87  const art::Handle<std::vector<recob::PFParticle> >& pfParticleHandle,
88  const art::FindManyP<recob::Cluster>& partToClusAssns,
89  const art::FindManyP<recob::Hit>& clusToHitAssns,
90  std::set<const recob::PFParticle*>& taggedParticles,
92 
93  // Fcl parameters.
94  std::string fCosmicProducerLabel;
95  std::string fHitProducerLabel;
97 
99 
100  // Statistics.
101  int fNumEvent;
103 };
104 
106 
107 //----------------------------------------------------------------------------
114 CRHitRemovalByPCA::CRHitRemovalByPCA(fhicl::ParameterSet const & pset) :
115  fNumEvent(0),
116  fNumCRRejects(0)
117 {
118  reconfigure(pset);
119  produces<std::vector<recob::Hit> >();
120 
121  // Report.
122  mf::LogInfo("CRHitRemovalByPCA") << "CRHitRemovalByPCA configured\n";
123 }
124 
125 //----------------------------------------------------------------------------
128 {}
129 
130 //----------------------------------------------------------------------------
138 {
139  fCosmicProducerLabel = pset.get<std::string>("CosmicProducerLabel");
140  fHitProducerLabel = pset.get<std::string>("HitProducerLabel");
141  fPFParticleProducerLabel = pset.get<std::string>("PFParticleProducerLabel");
142  fCosmicTagThreshold = pset.get<double> ("CosmicTagThreshold");
143 }
144 
145 //----------------------------------------------------------------------------
148 {
149 }
150 
151 //----------------------------------------------------------------------------
165 {
166  ++fNumEvent;
167 
168  // Start by looking up the original hits
170  evt.getByLabel(fHitProducerLabel, hitHandle);
171 
172  // If there are no hits then there should be no output
173  if (!hitHandle.isValid()) return;
174 
175  // If there are hits then we are going to output something so get a new
176  // output hit vector
177  std::unique_ptr<std::vector<recob::Hit> > outputHits(new std::vector<recob::Hit>);
178 
179  // And fill it with the complete original list of hits
180  *outputHits = *hitHandle;
181 
182  // Recover the PFParticles that are responsible for making the tracks
184  evt.getByLabel(fPFParticleProducerLabel, pfParticleHandle);
185 
186  // Without a valid collection of PFParticles we can't do the hit removal
187  if (!pfParticleHandle.isValid())
188  {
189  evt.put(std::move(outputHits));
190  return;
191  }
192 
193  // Recover the clusters so we can do associations to the hits
194  // In theory the clusters come from the same producer as the PFParticles
196  evt.getByLabel(fPFParticleProducerLabel, clusterHandle);
197 
198  // If there are no clusters then something is really wrong
199  if (!clusterHandle.isValid())
200  {
201  evt.put(std::move(outputHits));
202  return;
203  }
204 
205  // Recover the list of cosmic tags
207  evt.getByLabel(fCosmicProducerLabel, cosmicTagHandle);
208 
209  // No cosmic tags then nothing to do here
210  if (!cosmicTagHandle.isValid() || cosmicTagHandle->empty())
211  {
212  evt.put(std::move(outputHits));
213  return;
214  }
215 
216  // Start recovering the necessary associations
217  // Start by finding the associations going from cosmic tags to PFParticles
218  art::FindManyP<recob::PFParticle> cosmicTagToPFPartAssns(cosmicTagHandle, evt, fCosmicProducerLabel);
219 
220  // From PFParticles we go to clusters
221  art::FindManyP<recob::Cluster> clusterAssns(pfParticleHandle, evt, fPFParticleProducerLabel);
222 
223  // Likewise, recover the collection of associations to hits
224  art::FindManyP<recob::Hit> clusterHitAssns(clusterHandle, evt, fPFParticleProducerLabel);
225 
226  // Container to contain the "bad" hits...
227  art::PtrVector<recob::Hit> taggedHits;
228 
229  // No point double counting hits
230  std::set<const recob::PFParticle*> taggedSet;
231 
232  // Start the identification of hits to remove. The outer loop is over the various producers of
233  // the CosmicTag objects we're examininig
234  for(size_t crIdx = 0; crIdx != cosmicTagHandle->size(); crIdx++)
235  {
236  art::Ptr<anab::CosmicTag> cosmicTag(cosmicTagHandle, crIdx);
237 
238  // If this was tagged as a CR muon then we have work to do!
239  if (cosmicTag->CosmicScore() > fCosmicTagThreshold)
240  {
241  // Recover the associated PFParticle
242  std::vector<art::Ptr<recob::PFParticle> > pfPartVec = cosmicTagToPFPartAssns.at(crIdx);
243 
244  if (pfPartVec.empty()) continue;
245 
246  art::Ptr<recob::PFParticle> pfParticle = pfPartVec.front();
247 
248  // Again, most likely needless
249  if (!pfParticle) continue;
250 
251  // A cosmic ray must be a primary (by fiat)
252  if (!pfParticle->IsPrimary()) continue;
253 
254  // Avoid double counting if more than one tagger running
255  if (taggedSet.find(pfParticle.get()) != taggedSet.end()) continue;
256 
257  // Remove all hits associated to this particle and its daughters
258  removeTaggedHits(pfParticle.get(), pfParticleHandle, clusterAssns, clusterHitAssns, taggedSet, taggedHits);
259  }
260  }
261 
262  // Are there any tagged hits?
263  if (!taggedHits.empty())
264  {
265  // First order of business is to attempt to restore any hits which are shared between a tagged
266  // CR PFParticle and an untagged one. We can do this by going through the PFParticles and
267  // "removing" hits which are in the not tagged set.
268  art::PtrVector<recob::Hit> untaggedHits;
269 
270  for(const auto& pfParticle : *pfParticleHandle)
271  {
272  if (taggedSet.find(&pfParticle) != taggedSet.end()) continue;
273 
274  // Recover the clusters associated to the input PFParticle
275  std::vector<art::Ptr<recob::Cluster> > clusterVec = clusterAssns.at(pfParticle.Self());
276 
277  // Loop over the clusters and grab the associated hits
278  for(const auto& cluster : clusterVec)
279  {
280  std::vector<art::Ptr<recob::Hit> > clusHitVec = clusterHitAssns.at(cluster->ID());
281  untaggedHits.insert(untaggedHits.end(), clusHitVec.begin(), clusHitVec.end());
282  }
283  }
284 
285  // Filter out the hits we want to save
286  FilterHits(taggedHits, untaggedHits);
287 
288  // The below is rather ugly but there is an interplay between art::Ptr's and the
289  // actual pointers to objects that I might be missing and this is what I see how to do
290  // First move all the original art::Ptr hits into a local art::PtrVector
291  art::PtrVector<recob::Hit> originalHits;
292 
293  // Fill this one hit at a time...
294  for(size_t hitIdx = 0; hitIdx != hitHandle->size(); hitIdx++)
295  {
296  art::Ptr<recob::Hit> hit(hitHandle, hitIdx);
297 
298  originalHits.push_back(hit);
299  }
300 
301  // Remove the cosmic ray tagged hits
302  FilterHits(originalHits, taggedHits);
303 
304  // Clear the current outputHits vector since we're going to refill...
305  outputHits->clear();
306 
307  // Now make the new list of output hits
308  for (const auto& hit : originalHits)
309  {
310  // Kludge to remove out of time hits
311  if (hit->StartTick() > 6400 || hit->EndTick() < 3200) continue;
312 
313  outputHits->emplace_back(*hit);
314  }
315  }
316 
317  // Add tracks and associations to event.
318  evt.put(std::move(outputHits));
319 }
320 
321 //----------------------------------------------------------------------------
337  const art::Handle<std::vector<recob::PFParticle> >& pfParticleHandle,
338  const art::FindManyP<recob::Cluster>& partToClusAssns,
339  const art::FindManyP<recob::Hit>& clusToHitAssns,
340  std::set<const recob::PFParticle*>& taggedParticles,
342 {
343  // Recover the clusters associated to the input PFParticle
344  std::vector<art::Ptr<recob::Cluster> > clusterVec = partToClusAssns.at(pfParticle->Self());
345 
346  // Record this PFParticle as tagged
347  taggedParticles.insert(pfParticle);
348 
349  // Loop over the clusters and grab the associated hits
350  for(const auto& cluster : clusterVec)
351  {
352  std::vector<art::Ptr<recob::Hit> > clusHitVec = clusToHitAssns.at(cluster->ID());
353  hitVec.insert(hitVec.end(), clusHitVec.begin(), clusHitVec.end());
354  }
355 
356  // Loop over the daughters of this particle and remove their hits as well
357  for(const auto& daughterId : pfParticle->Daughters())
358  {
359  art::Ptr<recob::PFParticle> daughter(pfParticleHandle, daughterId);
360 
361  removeTaggedHits(daughter.get(), pfParticleHandle, partToClusAssns, clusToHitAssns, taggedParticles, hitVec);
362  }
363 
364  return;
365 }
366 
367 
368 //----------------------------------------------------------------------------
371 {
372  double aveCRPerEvent = fNumEvent > 0 ? double(fNumCRRejects) / double(fNumEvent) : 0.;
373 
374  mf::LogInfo("CRHitRemovalByPCA")
375  << "CRHitRemovalByPCA statistics:\n"
376  << " Number of events = " << fNumEvent << "\n"
377  << " Number of Cosmic Rays found = " << fNumCRRejects
378  << ", " << aveCRPerEvent << " average/event";
379 }
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
Definition: PFParticle.h:114
virtual void endJob()
End job method.
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:92
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
iterator begin()
Definition: PtrVector.h:223
Declaration of signal hit object.
iterator erase(iterator position)
Definition: PtrVector.h:508
std::string fCosmicProducerLabel
Module that produced the PCA based cosmic tags.
virtual void beginJob()
Begin job method.
virtual void reconfigure(fhicl::ParameterSet const &pset)
CRHitRemovalByPCA(fhicl::ParameterSet const &pset)
Cluster finding and building.
float & CosmicScore()
Definition: CosmicTag.h:65
std::string fPFParticleProducerLabel
PFParticle producer.
int fNumCRRejects
Number of tracks produced.
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
bool isValid() const
Definition: Handle.h:190
void hits()
Definition: readHits.C:15
int fNumEvent
Number of events seen.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
Provides recob::Track data product.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:441
virtual void produce(art::Event &e)
parameter set interface
T get(std::string const &key) const
Definition: ParameterSet.h:231
iterator end()
Definition: PtrVector.h:237
bool IsPrimary() const
Returns whether the particle is the root of the flow.
Definition: PFParticle.h:86
Declaration of cluster object.
data_t::iterator iterator
Definition: PtrVector.h:60
bool empty() const
Definition: PtrVector.h:336
size_type size() const
Definition: PtrVector.h:308
Detector simulation of raw signals on wires.
double fCosmicTagThreshold
Thresholds for tagging.
iterator insert(iterator position, Ptr< U > const &p)
void removeTaggedHits(const recob::PFParticle *pfParticle, const art::Handle< std::vector< recob::PFParticle > > &pfParticleHandle, const art::FindManyP< recob::Cluster > &partToClusAssns, const art::FindManyP< recob::Hit > &clusToHitAssns, std::set< const recob::PFParticle * > &taggedParticles, art::PtrVector< recob::Hit > &hitVec)
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
Utility object to perform functions of association.
T const * get() const
Definition: Ptr.h:321
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
std::string fHitProducerLabel
The full collection of hits.
TCEvent evt
Definition: DataStructs.cxx:5
Float_t e
Definition: plot.C:34
virtual ~CRHitRemovalByPCA()
Destructor.
Definition: fwd.h:25
art framework interface to geometry description