CRHitRemovalByPCA_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
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 //
20 ////////////////////////////////////////////////////////////////////////
21 
22 #include <algorithm>
23 
29 #include "canvas/Persistency/Common/FindManyP.h"
33 
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 
77  // Overrides.
78  virtual void produce(art::Event & e);
79  virtual void endJob();
80 
81 private:
82  // Methods
83  void removeTaggedHits(const recob::PFParticle* pfParticle,
84  const art::Handle<std::vector<recob::PFParticle> >& pfParticleHandle,
85  const art::FindManyP<recob::Cluster>& partToClusAssns,
86  const art::FindManyP<recob::Hit>& clusToHitAssns,
87  std::set<const recob::PFParticle*>& taggedParticles,
89 
90  // Fcl parameters.
91  std::string fCosmicProducerLabel; ///< Module that produced the PCA based cosmic tags
92  std::string fHitProducerLabel; ///< The full collection of hits
93  std::string fPFParticleProducerLabel; ///< PFParticle producer
94 
95  double fCosmicTagThreshold; ///< Thresholds for tagging
96 
97  // Statistics.
98  int fNumEvent; ///< Number of events seen.
99  int fNumCRRejects; ///< Number of tracks produced.
100 };
101 
103 
104 //----------------------------------------------------------------------------
105 /// Constructor.
106 ///
107 /// Arguments:
108 ///
109 /// pset - Fcl parameters.
110 ///
112  EDProducer{pset},
113  fNumEvent(0),
114  fNumCRRejects(0)
115 {
116  fCosmicProducerLabel = pset.get<std::string>("CosmicProducerLabel");
117  fHitProducerLabel = pset.get<std::string>("HitProducerLabel");
118  fPFParticleProducerLabel = pset.get<std::string>("PFParticleProducerLabel");
119  fCosmicTagThreshold = pset.get<double> ("CosmicTagThreshold");
120 
121  produces<std::vector<recob::Hit> >();
122 
123  // Report.
124  mf::LogInfo("CRHitRemovalByPCA") << "CRHitRemovalByPCA configured\n";
125 }
126 
127 //----------------------------------------------------------------------------
128 /// Produce method.
129 ///
130 /// Arguments:
131 ///
132 /// evt - Art event.
133 ///
134 /// This is the primary method. The goal is to produce a list of recob::Hit
135 /// objects which are a "clean" subset of all hits and which are believed to
136 /// be due to a neutrino interaction. It does this by considering input CosmicTag
137 /// objects, relating them to PFParticles/Tracks and removing the hits
138 /// associated to those objects which are believed to be Cosmic Rays.
139 ///
141 {
142  ++fNumEvent;
143 
144  // Start by looking up the original hits
146  evt.getByLabel(fHitProducerLabel, hitHandle);
147 
148  // If there are no hits then there should be no output
149  if (!hitHandle.isValid()) return;
150 
151  // If there are hits then we are going to output something so get a new
152  // output hit vector
153  std::unique_ptr<std::vector<recob::Hit> > outputHits(new std::vector<recob::Hit>);
154 
155  // And fill it with the complete original list of hits
156  *outputHits = *hitHandle;
157 
158  // Recover the PFParticles that are responsible for making the tracks
160  evt.getByLabel(fPFParticleProducerLabel, pfParticleHandle);
161 
162  // Without a valid collection of PFParticles we can't do the hit removal
163  if (!pfParticleHandle.isValid())
164  {
165  evt.put(std::move(outputHits));
166  return;
167  }
168 
169  // Recover the clusters so we can do associations to the hits
170  // In theory the clusters come from the same producer as the PFParticles
172  evt.getByLabel(fPFParticleProducerLabel, clusterHandle);
173 
174  // If there are no clusters then something is really wrong
175  if (!clusterHandle.isValid())
176  {
177  evt.put(std::move(outputHits));
178  return;
179  }
180 
181  // Recover the list of cosmic tags
183  evt.getByLabel(fCosmicProducerLabel, cosmicTagHandle);
184 
185  // No cosmic tags then nothing to do here
186  if (!cosmicTagHandle.isValid() || cosmicTagHandle->empty())
187  {
188  evt.put(std::move(outputHits));
189  return;
190  }
191 
192  // Start recovering the necessary associations
193  // Start by finding the associations going from cosmic tags to PFParticles
194  art::FindManyP<recob::PFParticle> cosmicTagToPFPartAssns(cosmicTagHandle, evt, fCosmicProducerLabel);
195 
196  // From PFParticles we go to clusters
197  art::FindManyP<recob::Cluster> clusterAssns(pfParticleHandle, evt, fPFParticleProducerLabel);
198 
199  // Likewise, recover the collection of associations to hits
200  art::FindManyP<recob::Hit> clusterHitAssns(clusterHandle, evt, fPFParticleProducerLabel);
201 
202  // Container to contain the "bad" hits...
203  art::PtrVector<recob::Hit> taggedHits;
204 
205  // No point double counting hits
206  std::set<const recob::PFParticle*> taggedSet;
207 
208  // Start the identification of hits to remove. The outer loop is over the various producers of
209  // the CosmicTag objects we're examininig
210  for(size_t crIdx = 0; crIdx != cosmicTagHandle->size(); crIdx++)
211  {
212  art::Ptr<anab::CosmicTag> cosmicTag(cosmicTagHandle, crIdx);
213 
214  // If this was tagged as a CR muon then we have work to do!
215  if (cosmicTag->CosmicScore() > fCosmicTagThreshold)
216  {
217  // Recover the associated PFParticle
218  std::vector<art::Ptr<recob::PFParticle> > pfPartVec = cosmicTagToPFPartAssns.at(crIdx);
219 
220  if (pfPartVec.empty()) continue;
221 
222  art::Ptr<recob::PFParticle> pfParticle = pfPartVec.front();
223 
224  // Again, most likely needless
225  if (!pfParticle) continue;
226 
227  // A cosmic ray must be a primary (by fiat)
228  if (!pfParticle->IsPrimary()) continue;
229 
230  // Avoid double counting if more than one tagger running
231  if (taggedSet.find(pfParticle.get()) != taggedSet.end()) continue;
232 
233  // Remove all hits associated to this particle and its daughters
234  removeTaggedHits(pfParticle.get(), pfParticleHandle, clusterAssns, clusterHitAssns, taggedSet, taggedHits);
235  }
236  }
237 
238  // Are there any tagged hits?
239  if (!taggedHits.empty())
240  {
241  // First order of business is to attempt to restore any hits which are shared between a tagged
242  // CR PFParticle and an untagged one. We can do this by going through the PFParticles and
243  // "removing" hits which are in the not tagged set.
244  art::PtrVector<recob::Hit> untaggedHits;
245 
246  for(const auto& pfParticle : *pfParticleHandle)
247  {
248  if (taggedSet.find(&pfParticle) != taggedSet.end()) continue;
249 
250  // Recover the clusters associated to the input PFParticle
251  std::vector<art::Ptr<recob::Cluster> > clusterVec = clusterAssns.at(pfParticle.Self());
252 
253  // Loop over the clusters and grab the associated hits
254  for(const auto& cluster : clusterVec)
255  {
256  std::vector<art::Ptr<recob::Hit> > clusHitVec = clusterHitAssns.at(cluster->ID());
257  untaggedHits.insert(untaggedHits.end(), clusHitVec.begin(), clusHitVec.end());
258  }
259  }
260 
261  // Filter out the hits we want to save
262  FilterHits(taggedHits, untaggedHits);
263 
264  // The below is rather ugly but there is an interplay between art::Ptr's and the
265  // actual pointers to objects that I might be missing and this is what I see how to do
266  // First move all the original art::Ptr hits into a local art::PtrVector
267  art::PtrVector<recob::Hit> originalHits;
268 
269  // Fill this one hit at a time...
270  for(size_t hitIdx = 0; hitIdx != hitHandle->size(); hitIdx++)
271  {
272  art::Ptr<recob::Hit> hit(hitHandle, hitIdx);
273 
274  originalHits.push_back(hit);
275  }
276 
277  // Remove the cosmic ray tagged hits
278  FilterHits(originalHits, taggedHits);
279 
280  // Clear the current outputHits vector since we're going to refill...
281  outputHits->clear();
282 
283  // Now make the new list of output hits
284  for (const auto& hit : originalHits)
285  {
286  // Kludge to remove out of time hits
287  if (hit->StartTick() > 6400 || hit->EndTick() < 3200) continue;
288 
289  outputHits->emplace_back(*hit);
290  }
291  }
292 
293  // Add tracks and associations to event.
294  evt.put(std::move(outputHits));
295 }
296 
297 //----------------------------------------------------------------------------
298 /// Hit removal method
299 ///
300 /// Arguments:
301 ///
302 /// pfParticle - the top level PFParticle to have hits removed
303 /// pfParticleHandle - handle to the PFParticle objects
304 /// partToClusAssns - list of PFParticle to Cluster associations
305 /// clusToHitAssns - list of Cluster to Hit associations
306 /// hitVec - the current list of hits
307 ///
308 /// This recursively called method will remove all hits associated to an input
309 /// PFParticle and, in addition, will call itself for all daughters of the input
310 /// PFParticle
311 ///
313  const art::Handle<std::vector<recob::PFParticle> >& pfParticleHandle,
314  const art::FindManyP<recob::Cluster>& partToClusAssns,
315  const art::FindManyP<recob::Hit>& clusToHitAssns,
316  std::set<const recob::PFParticle*>& taggedParticles,
318 {
319  // Recover the clusters associated to the input PFParticle
320  std::vector<art::Ptr<recob::Cluster> > clusterVec = partToClusAssns.at(pfParticle->Self());
321 
322  // Record this PFParticle as tagged
323  taggedParticles.insert(pfParticle);
324 
325  // Loop over the clusters and grab the associated hits
326  for(const auto& cluster : clusterVec)
327  {
328  std::vector<art::Ptr<recob::Hit> > clusHitVec = clusToHitAssns.at(cluster->ID());
329  hitVec.insert(hitVec.end(), clusHitVec.begin(), clusHitVec.end());
330  }
331 
332  // Loop over the daughters of this particle and remove their hits as well
333  for(const auto& daughterId : pfParticle->Daughters())
334  {
335  art::Ptr<recob::PFParticle> daughter(pfParticleHandle, daughterId);
336 
337  removeTaggedHits(daughter.get(), pfParticleHandle, partToClusAssns, clusToHitAssns, taggedParticles, hitVec);
338  }
339 
340  return;
341 }
342 
343 
344 //----------------------------------------------------------------------------
345 /// End job method.
347 {
348  double aveCRPerEvent = fNumEvent > 0 ? double(fNumCRRejects) / double(fNumEvent) : 0.;
349 
350  mf::LogInfo("CRHitRemovalByPCA")
351  << "CRHitRemovalByPCA statistics:\n"
352  << " Number of events = " << fNumEvent << "\n"
353  << " Number of Cosmic Rays found = " << fNumCRRejects
354  << ", " << aveCRPerEvent << " average/event";
355 }
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
Definition: PFParticle.h:114
typename data_t::iterator iterator
Definition: PtrVector.h:54
virtual void endJob()
End job method.
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:92
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
iterator begin()
Definition: PtrVector.h:217
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
iterator erase(iterator position)
Definition: PtrVector.h:504
std::string fCosmicProducerLabel
Module that produced the PCA based cosmic tags.
CRHitRemovalByPCA(fhicl::ParameterSet const &pset)
Cluster finding and building.
float & CosmicScore()
Definition: CosmicTag.h:61
std::string fPFParticleProducerLabel
PFParticle producer.
int fNumCRRejects
Number of tracks produced.
bool isValid() const noexcept
Definition: Handle.h:191
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:633
int fNumEvent
Number of events seen.
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
virtual void produce(art::Event &e)
def move(depos, offset)
Definition: depos.py:107
iterator end()
Definition: PtrVector.h:231
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
bool IsPrimary() const
Returns whether the particle is the root of the flow.
Definition: PFParticle.h:86
reference at(size_type n)
Definition: PtrVector.h:359
bool empty() const
Definition: PtrVector.h:330
size_type size() const
Definition: PtrVector.h:302
Detector simulation of raw signals on wires.
double fCosmicTagThreshold
Thresholds for tagging.
iterator insert(iterator position, Ptr< U > const &p)
Declaration of signal hit object.
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
std::string fHitProducerLabel
The full collection of hits.
TCEvent evt
Definition: DataStructs.cxx:7
T const * get() const
Definition: Ptr.h:149
Definition: fwd.h:31