LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 <algorithm>
23 
33 
38 
39 // Local functions.
40 namespace {
41  //----------------------------------------------------------------------------
42  // Filter a collection of hits (set difference).
43  // This function is copied from Track3DKalmanHit_module.cc
44  //
45  // Arguments:
46  //
47  // hits - Hit collection from which hits should be removed.
48  // used_hits - Hits to remove.
49  //
50  void FilterHits(art::PtrVector<recob::Hit>& hits, art::PtrVector<recob::Hit>& used_hits)
51  {
52  if (used_hits.size() > 0) {
53  // Make sure both hit collections are sorted.
54  std::stable_sort(hits.begin(), hits.end());
55  std::stable_sort(used_hits.begin(), used_hits.end());
56 
57  // Do set difference operation.
58  art::PtrVector<recob::Hit>::iterator it = std::set_difference(
59  hits.begin(), hits.end(), used_hits.begin(), used_hits.end(), hits.begin());
60 
61  // Truncate hit collection.
62  hits.erase(it, hits.end());
63  }
64  }
65 }
66 
67 // class Propagator;
68 
70 public:
71  // Copnstructors, destructor.
72  explicit CRHitRemovalByPCA(fhicl::ParameterSet const& pset);
73 
74  // Overrides.
75  virtual void produce(art::Event& e);
76  virtual void endJob();
77 
78 private:
79  // Methods
80  void removeTaggedHits(const recob::PFParticle* pfParticle,
81  const art::Handle<std::vector<recob::PFParticle>>& pfParticleHandle,
82  const art::FindManyP<recob::Cluster>& partToClusAssns,
83  const art::FindManyP<recob::Hit>& clusToHitAssns,
84  std::set<const recob::PFParticle*>& taggedParticles,
86 
87  // Fcl parameters.
88  std::string fCosmicProducerLabel;
89  std::string fHitProducerLabel;
91 
93 
94  // Statistics.
95  int fNumEvent;
97 };
98 
100 
101 //----------------------------------------------------------------------------
108 CRHitRemovalByPCA::CRHitRemovalByPCA(fhicl::ParameterSet const& pset)
109  : EDProducer{pset}, fNumEvent(0), fNumCRRejects(0)
110 {
111  fCosmicProducerLabel = pset.get<std::string>("CosmicProducerLabel");
112  fHitProducerLabel = pset.get<std::string>("HitProducerLabel");
113  fPFParticleProducerLabel = pset.get<std::string>("PFParticleProducerLabel");
114  fCosmicTagThreshold = pset.get<double>("CosmicTagThreshold");
115 
116  produces<std::vector<recob::Hit>>();
117 
118  // Report.
119  mf::LogInfo("CRHitRemovalByPCA") << "CRHitRemovalByPCA configured\n";
120 }
121 
122 //----------------------------------------------------------------------------
136 {
137  ++fNumEvent;
138 
139  // Start by looking up the original hits
141  evt.getByLabel(fHitProducerLabel, hitHandle);
142 
143  // If there are no hits then there should be no output
144  if (!hitHandle.isValid()) return;
145 
146  // If there are hits then we are going to output something so get a new
147  // output hit vector
148  std::unique_ptr<std::vector<recob::Hit>> outputHits(new std::vector<recob::Hit>);
149 
150  // And fill it with the complete original list of hits
151  *outputHits = *hitHandle;
152 
153  // Recover the PFParticles that are responsible for making the tracks
155  evt.getByLabel(fPFParticleProducerLabel, pfParticleHandle);
156 
157  // Without a valid collection of PFParticles we can't do the hit removal
158  if (!pfParticleHandle.isValid()) {
159  evt.put(std::move(outputHits));
160  return;
161  }
162 
163  // Recover the clusters so we can do associations to the hits
164  // In theory the clusters come from the same producer as the PFParticles
166  evt.getByLabel(fPFParticleProducerLabel, clusterHandle);
167 
168  // If there are no clusters then something is really wrong
169  if (!clusterHandle.isValid()) {
170  evt.put(std::move(outputHits));
171  return;
172  }
173 
174  // Recover the list of cosmic tags
176  evt.getByLabel(fCosmicProducerLabel, cosmicTagHandle);
177 
178  // No cosmic tags then nothing to do here
179  if (!cosmicTagHandle.isValid() || cosmicTagHandle->empty()) {
180  evt.put(std::move(outputHits));
181  return;
182  }
183 
184  // Start recovering the necessary associations
185  // Start by finding the associations going from cosmic tags to PFParticles
186  art::FindManyP<recob::PFParticle> cosmicTagToPFPartAssns(
187  cosmicTagHandle, evt, fCosmicProducerLabel);
188 
189  // From PFParticles we go to clusters
190  art::FindManyP<recob::Cluster> clusterAssns(pfParticleHandle, evt, fPFParticleProducerLabel);
191 
192  // Likewise, recover the collection of associations to hits
193  art::FindManyP<recob::Hit> clusterHitAssns(clusterHandle, evt, fPFParticleProducerLabel);
194 
195  // Container to contain the "bad" hits...
196  art::PtrVector<recob::Hit> taggedHits;
197 
198  // No point double counting hits
199  std::set<const recob::PFParticle*> taggedSet;
200 
201  // Start the identification of hits to remove. The outer loop is over the various producers of
202  // the CosmicTag objects we're examininig
203  for (size_t crIdx = 0; crIdx != cosmicTagHandle->size(); crIdx++) {
204  art::Ptr<anab::CosmicTag> cosmicTag(cosmicTagHandle, crIdx);
205 
206  // If this was tagged as a CR muon then we have work to do!
207  if (cosmicTag->CosmicScore() > fCosmicTagThreshold) {
208  // Recover the associated PFParticle
209  std::vector<art::Ptr<recob::PFParticle>> pfPartVec = cosmicTagToPFPartAssns.at(crIdx);
210 
211  if (pfPartVec.empty()) continue;
212 
213  art::Ptr<recob::PFParticle> pfParticle = pfPartVec.front();
214 
215  // Again, most likely needless
216  if (!pfParticle) continue;
217 
218  // A cosmic ray must be a primary (by fiat)
219  if (!pfParticle->IsPrimary()) continue;
220 
221  // Avoid double counting if more than one tagger running
222  if (taggedSet.find(pfParticle.get()) != taggedSet.end()) continue;
223 
224  // Remove all hits associated to this particle and its daughters
226  pfParticle.get(), pfParticleHandle, clusterAssns, clusterHitAssns, taggedSet, taggedHits);
227  }
228  }
229 
230  // Are there any tagged hits?
231  if (!taggedHits.empty()) {
232  // First order of business is to attempt to restore any hits which are shared between a tagged
233  // CR PFParticle and an untagged one. We can do this by going through the PFParticles and
234  // "removing" hits which are in the not tagged set.
235  art::PtrVector<recob::Hit> untaggedHits;
236 
237  for (const auto& pfParticle : *pfParticleHandle) {
238  if (taggedSet.find(&pfParticle) != taggedSet.end()) continue;
239 
240  // Recover the clusters associated to the input PFParticle
241  std::vector<art::Ptr<recob::Cluster>> clusterVec = clusterAssns.at(pfParticle.Self());
242 
243  // Loop over the clusters and grab the associated hits
244  for (const auto& cluster : clusterVec) {
245  std::vector<art::Ptr<recob::Hit>> clusHitVec = clusterHitAssns.at(cluster->ID());
246  untaggedHits.insert(untaggedHits.end(), clusHitVec.begin(), clusHitVec.end());
247  }
248  }
249 
250  // Filter out the hits we want to save
251  FilterHits(taggedHits, untaggedHits);
252 
253  // The below is rather ugly but there is an interplay between art::Ptr's and the
254  // actual pointers to objects that I might be missing and this is what I see how to do
255  // First move all the original art::Ptr hits into a local art::PtrVector
256  art::PtrVector<recob::Hit> originalHits;
257 
258  // Fill this one hit at a time...
259  for (size_t hitIdx = 0; hitIdx != hitHandle->size(); hitIdx++) {
260  art::Ptr<recob::Hit> hit(hitHandle, hitIdx);
261 
262  originalHits.push_back(hit);
263  }
264 
265  // Remove the cosmic ray tagged hits
266  FilterHits(originalHits, taggedHits);
267 
268  // Clear the current outputHits vector since we're going to refill...
269  outputHits->clear();
270 
271  // Now make the new list of output hits
272  for (const auto& hit : originalHits) {
273  // Kludge to remove out of time hits
274  if (hit->StartTick() > 6400 || hit->EndTick() < 3200) continue;
275 
276  outputHits->emplace_back(*hit);
277  }
278  }
279 
280  // Add tracks and associations to event.
281  evt.put(std::move(outputHits));
282 }
283 
284 //----------------------------------------------------------------------------
300  const recob::PFParticle* pfParticle,
301  const art::Handle<std::vector<recob::PFParticle>>& pfParticleHandle,
302  const art::FindManyP<recob::Cluster>& partToClusAssns,
303  const art::FindManyP<recob::Hit>& clusToHitAssns,
304  std::set<const recob::PFParticle*>& taggedParticles,
306 {
307  // Recover the clusters associated to the input PFParticle
308  std::vector<art::Ptr<recob::Cluster>> clusterVec = partToClusAssns.at(pfParticle->Self());
309 
310  // Record this PFParticle as tagged
311  taggedParticles.insert(pfParticle);
312 
313  // Loop over the clusters and grab the associated hits
314  for (const auto& cluster : clusterVec) {
315  std::vector<art::Ptr<recob::Hit>> clusHitVec = clusToHitAssns.at(cluster->ID());
316  hitVec.insert(hitVec.end(), clusHitVec.begin(), clusHitVec.end());
317  }
318 
319  // Loop over the daughters of this particle and remove their hits as well
320  for (const auto& daughterId : pfParticle->Daughters()) {
321  art::Ptr<recob::PFParticle> daughter(pfParticleHandle, daughterId);
322 
324  daughter.get(), pfParticleHandle, partToClusAssns, clusToHitAssns, taggedParticles, hitVec);
325  }
326 
327  return;
328 }
329 
330 //----------------------------------------------------------------------------
333 {
334  double aveCRPerEvent = fNumEvent > 0 ? double(fNumCRRejects) / double(fNumEvent) : 0.;
335 
336  mf::LogInfo("CRHitRemovalByPCA") << "CRHitRemovalByPCA statistics:\n"
337  << " Number of events = " << fNumEvent << "\n"
338  << " Number of Cosmic Rays found = " << fNumCRRejects << ", "
339  << aveCRPerEvent << " average/event";
340 }
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)
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
Definition: PFParticle.h:110
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:88
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
iterator begin()
Definition: PtrVector.h:217
Declaration of signal hit object.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
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:54
std::string fPFParticleProducerLabel
PFParticle producer.
int fNumCRRejects
Number of tracks produced.
bool isValid() const noexcept
Definition: Handle.h:203
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
void hits()
Definition: readHits.C:15
int fNumEvent
Number of events seen.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
virtual void produce(art::Event &e)
parameter set interface
iterator end()
Definition: PtrVector.h:231
bool IsPrimary() const
Returns whether the particle is the root of the flow.
Definition: PFParticle.h:82
Declaration of cluster object.
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)
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
std::string fHitProducerLabel
The full collection of hits.
TCEvent evt
Definition: DataStructs.cxx:8
Float_t e
Definition: plot.C:35
T const * get() const
Definition: Ptr.h:138
Definition: fwd.h:26