LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
LArPandoraExternalEventBuilding_module.cc
Go to the documentation of this file.
1 
11 
13 
14 #include "fhiclcpp/ParameterSet.h"
15 
17 
19 
23 
26 
27 namespace lar_pandora
28 {
29 
31 {
32 public:
34 
39 
40  void produce(art::Event &evt) override;
41 
42 private:
43  typedef std::map<art::Ptr<recob::PFParticle>, art::Ptr<larpandoraobj::PFParticleMetadata> > PFParticleToMetadata;
44 
52  void CollectPFParticles(const art::Event &evt, PFParticleToMetadata &particlesToMetadata, PFParticleVector &particles) const;
53 
60  void BuildPFParticleMap(const PFParticleToMetadata &particlesToMetadata, PFParticleMap &particleMap) const;
61 
70  void CollectClearCosmicRays(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, PFParticleVector &clearCosmics) const;
71 
80  void CollectSlices(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, SliceVector &slices) const;
81 
90  void CollectConsolidatedParticles(const PFParticleVector &allParticles, const PFParticleVector &clearCosmics, const SliceVector &slices, PFParticleVector &consolidatedParticles) const;
91 
100  float GetMetadataValue(const art::Ptr<larpandoraobj::PFParticleMetadata> &metadata, const std::string &key) const;
101 
102  std::string m_inputProducerLabel;
103  std::string m_trackProducerLabel;
104  std::string m_showerProducerLabel;
105  std::string m_hitProducerLabel;
108  std::unique_ptr<NeutrinoIdBaseTool> m_neutrinoIdTool;
109 };
110 
112 
113 } // namespace lar_pandora
114 
115 //------------------------------------------------------------------------------------------------------------------------------------------
116 // implementation follows
117 
118 #include "Pandora/PdgTable.h"
119 
120 namespace lar_pandora
121 {
122 
124  m_inputProducerLabel(pset.get<std::string>("InputProducerLabel")),
125  m_trackProducerLabel(pset.get<std::string>("TrackProducerLabel")),
126  m_showerProducerLabel(pset.get<std::string>("ShowerProducerLabel")),
127  m_hitProducerLabel(pset.get<std::string>("HitProducerLabel")),
128  m_shouldProduceT0s(pset.get<bool>("ShouldProduceT0s")),
130  m_neutrinoIdTool(art::make_tool<NeutrinoIdBaseTool>(pset.get<fhicl::ParameterSet>("NeutrinoIdTool")))
131 {
132  produces< std::vector<recob::PFParticle> >();
133  produces< std::vector<recob::SpacePoint> >();
134  produces< std::vector<recob::Cluster> >();
135  produces< std::vector<recob::Vertex> >();
136  produces< std::vector<recob::Track> >();
137  produces< std::vector<recob::Shower> >();
138  produces< std::vector<recob::PCAxis> >();
139  produces< std::vector<larpandoraobj::PFParticleMetadata> >();
140 
141  produces< art::Assns<recob::PFParticle, recob::SpacePoint> >();
142  produces< art::Assns<recob::PFParticle, recob::Cluster> >();
143  produces< art::Assns<recob::PFParticle, recob::Vertex> >();
144  produces< art::Assns<recob::PFParticle, recob::Track> >();
145  produces< art::Assns<recob::PFParticle, recob::Shower> >();
146  produces< art::Assns<recob::PFParticle, recob::PCAxis> >();
147  produces< art::Assns<recob::PFParticle, larpandoraobj::PFParticleMetadata> >();
148  produces< art::Assns<recob::Track, recob::Hit> >();
149  produces< art::Assns<recob::Shower, recob::Hit> >();
150  produces< art::Assns<recob::Shower, recob::PCAxis> >();
151  produces< art::Assns<recob::SpacePoint, recob::Hit> >();
152  produces< art::Assns<recob::Cluster, recob::Hit> >();
153 
154  if (m_shouldProduceT0s)
155  {
156  produces< std::vector<anab::T0> >();
157  produces< art::Assns<recob::PFParticle, anab::T0> >();
158  }
159 }
160 
161 //------------------------------------------------------------------------------------------------------------------------------------------
162 
164 {
165  PFParticleVector particles;
166  PFParticleToMetadata particlesToMetadata;
167  this->CollectPFParticles(evt, particlesToMetadata, particles);
168 
169  PFParticleMap particleMap;
170  this->BuildPFParticleMap(particlesToMetadata, particleMap);
171 
172  PFParticleVector clearCosmics;
173  this->CollectClearCosmicRays(particles, particlesToMetadata, particleMap, clearCosmics);
174 
176  this->CollectSlices(particles, particlesToMetadata, particleMap, slices);
177 
178  m_neutrinoIdTool->ClassifySlices(slices, evt);
179 
180  PFParticleVector consolidatedParticles;
181  this->CollectConsolidatedParticles(particles, clearCosmics, slices, consolidatedParticles);
182 
184  const LArPandoraEvent consolidatedEvent(LArPandoraEvent(this, &evt, labels, m_shouldProduceT0s), consolidatedParticles);
185 
186  consolidatedEvent.WriteToEvent();
187 }
188 
189 //------------------------------------------------------------------------------------------------------------------------------------------
190 
192 {
194  evt.getByLabel(m_pandoraTag, pfParticleHandle);
195 
196  art::FindManyP<larpandoraobj::PFParticleMetadata> pfParticleMetadataAssoc(pfParticleHandle, evt, m_pandoraTag);
197 
198  for (unsigned int i = 0; i < pfParticleHandle->size(); ++i)
199  {
200  const art::Ptr<recob::PFParticle> part(pfParticleHandle, i);
201  const auto &metadata(pfParticleMetadataAssoc.at(part.key()));
202 
203  particles.push_back(part);
204 
205  if (metadata.size() != 1)
206  throw cet::exception("LArPandora") << " LArPandoraExternalEventBuilding::CollectPFParticles -- Found a PFParticle without exactly 1 metadata associated." << std::endl;
207 
208  if (!particlesToMetadata.insert(PFParticleToMetadata::value_type(part, metadata.front())).second)
209  throw cet::exception("LArPandoraExternalEventBuilding") << "Repeated PFParticles" << std::endl;
210  }
211 }
212 
213 //------------------------------------------------------------------------------------------------------------------------------------------
214 
216 {
217  for (const auto &entry : particlesToMetadata)
218  {
219  if (!particleMap.insert(PFParticleMap::value_type(entry.first->Self(), entry.first)).second)
220  throw cet::exception("LArPandoraExternalEventBuilding") << "Repeated PFParticles" << std::endl;
221  }
222 }
223 
224 //------------------------------------------------------------------------------------------------------------------------------------------
225 
226 void LArPandoraExternalEventBuilding::CollectClearCosmicRays(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, PFParticleVector &clearCosmics) const
227 {
228  for (const auto &part : allParticles)
229  {
230  // Get the parent of the particle
231  const auto parentIt(particlesToMetadata.find(LArPandoraHelper::GetParentPFParticle(particleMap, part)));
232  if (parentIt == particlesToMetadata.end())
233  throw cet::exception("LArPandoraExternalEventBuilding") << "Found PFParticle without metadata" << std::endl;
234 
235  // ATTN particles without the "IsClearCosmic" parameter are not clear cosmics
236  try
237  {
238  if (static_cast<bool>(std::round(this->GetMetadataValue(parentIt->second, "IsClearCosmic"))))
239  clearCosmics.push_back(part);
240  }
241  catch (const cet::exception &)
242  {
243  }
244  }
245 }
246 
247 //------------------------------------------------------------------------------------------------------------------------------------------
248 
249 void LArPandoraExternalEventBuilding::CollectSlices(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, SliceVector &slices) const
250 {
251  std::map<unsigned int, float> nuScores;
252  std::map<unsigned int, PFParticleVector> crHypotheses;
253  std::map<unsigned int, PFParticleVector> nuHypotheses;
254 
255  // Collect the slice information
256  for (const auto &part : allParticles)
257  {
258  // Find the parent PFParticle
259  const auto parentIt(particlesToMetadata.find(LArPandoraHelper::GetParentPFParticle(particleMap, part)));
260  if (parentIt == particlesToMetadata.end())
261  throw cet::exception("LArPandoraExternalEventBuilding") << "Found PFParticle without metadata" << std::endl;
262 
263  // Skip PFParticles that are clear cosmics
264  try
265  {
266  if (static_cast<bool>(std::round(this->GetMetadataValue(parentIt->second, "IsClearCosmic"))))
267  continue;
268  }
269  catch (const cet::exception &)
270  {
271  }
272 
273  const unsigned int sliceId(static_cast<unsigned int>(std::round(this->GetMetadataValue(parentIt->second, "SliceIndex"))));
274  const float nuScore(this->GetMetadataValue(parentIt->second, "NuScore"));
275  // ATTN all PFParticles in the same slice will have the same nuScore
276  nuScores[sliceId] = nuScore;
277 
278  if (LArPandoraHelper::IsNeutrino(parentIt->first))
279  {
280  nuHypotheses[sliceId].push_back(part);
281  }
282  else
283  {
284  crHypotheses[sliceId].push_back(part);
285  }
286  }
287 
288  // ATTN: we need to ensure that for each slice there is a cosmic and neutrino hypothesis, even if the pass created no PFOs
289  // in such a case we add an empty vector of pfparticles
290  const PFParticleVector emptyPFParticleVector;
291 
292  // Produce the slices
293  // ATTN slice indices are enumerated from 1
294  for (unsigned int sliceId = 1; sliceId <= nuScores.size(); ++sliceId)
295  {
296  // Get the neutrino score
297  const auto nuScoresIter(nuScores.find(sliceId));
298  if (nuScoresIter == nuScores.end())
299  throw cet::exception("LArPandoraExternalEventBuilding") << "Scrambled slice information - can't find nuScore with id = " << sliceId << std::endl;
300 
301  PFParticleVector nuPFParticleVector, crPFParticleVector;
302  // Get the neutrino hypothesis
303  const auto nuHypothesisIter(nuHypotheses.find(sliceId));
304  nuPFParticleVector = ((nuHypothesisIter == nuHypotheses.end()) ? emptyPFParticleVector : nuHypothesisIter->second);
305 
306  // Get the cosmic hypothesis
307  const auto crHypothesisIter(crHypotheses.find(sliceId));
308  crPFParticleVector = ((crHypothesisIter == crHypotheses.end()) ? emptyPFParticleVector : crHypothesisIter->second);
309 
310  slices.emplace_back(nuScoresIter->second, nuPFParticleVector, crPFParticleVector);
311  }
312 }
313 
314 //------------------------------------------------------------------------------------------------------------------------------------------
315 
317 {
318  const auto &propertiesMap(metadata->GetPropertiesMap());
319  const auto &it(propertiesMap.find(key));
320 
321  if (it == propertiesMap.end())
322  throw cet::exception("LArPandoraExternalEventBuilding") << "No key \"" << key << "\" found in metadata properties map" << std::endl;
323 
324  return it->second;
325 }
326 
327 //------------------------------------------------------------------------------------------------------------------------------------------
328 
329 void LArPandoraExternalEventBuilding::CollectConsolidatedParticles(const PFParticleVector &allParticles, const PFParticleVector &clearCosmics, const SliceVector &slices, PFParticleVector &consolidatedParticles) const
330 {
331  PFParticleVector collectedParticles;
332  collectedParticles.insert(collectedParticles.end(), clearCosmics.begin(), clearCosmics.end());
333 
334  for (const auto &slice : slices)
335  {
336  const PFParticleVector &particles(slice.IsTaggedAsNeutrino() ? slice.GetNeutrinoHypothesis() : slice.GetCosmicRayHypothesis());
337  collectedParticles.insert(collectedParticles.end(), particles.begin(), particles.end());
338  }
339 
340  // ATTN the collected particles are the ones we want to output, but here we loop over all particles to ensure that the consolidated
341  // particles have the same ordering.
342  for (const auto &part : allParticles)
343  {
344  if (std::find(collectedParticles.begin(), collectedParticles.end(), part) != collectedParticles.end())
345  consolidatedParticles.push_back(part);
346  }
347 }
348 
349 } // namespace lar_pandora
350 
void CollectSlices(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, SliceVector &slices) const
Collect slices.
key_type key() const
Definition: Ptr.h:356
void CollectPFParticles(const art::Event &evt, PFParticleToMetadata &particlesToMetadata, PFParticleVector &particles) const
Collect PFParticles from the ART event and their mapping to metadata objects.
std::map< art::Ptr< recob::PFParticle >, art::Ptr< larpandoraobj::PFParticleMetadata > > PFParticleToMetadata
LArPandoraEvent class.
std::enable_if_t< std::is_class< T >::value, tool_return_type< T > > make_tool(fhicl::ParameterSet const &pset)
Definition: make_tool.h:19
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
LArPandoraExternalEventBuilding & operator=(LArPandoraExternalEventBuilding const &)=delete
header for the lar pandora slice class
STL namespace.
static art::Ptr< recob::PFParticle > GetParentPFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
Abstract base class for a neutrino ID tool.
std::unique_ptr< NeutrinoIdBaseTool > m_neutrinoIdTool
The neutrino id tool.
void CollectClearCosmicRays(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, PFParticleVector &clearCosmics) const
Collect PFParticles that have been identified as clear cosmic ray muons by pandora.
std::map< int, art::Ptr< recob::PFParticle > > PFParticleMap
std::string m_trackProducerLabel
Label for the track producer using the Pandora instance that produced the collections we want to cons...
std::string m_showerProducerLabel
Label for the shower producer using the Pandora instance that produced the collections we want to con...
std::string m_hitProducerLabel
Label for the hit producer that was used as input to the Pandora instance specified.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
A description of all outputs from an instance of pandora with functionality to filter and merge multi...
parameter set interface
TString part[npart]
Definition: Style.C:32
const PropertiesMap & GetPropertiesMap() const
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
float GetMetadataValue(const art::Ptr< larpandoraobj::PFParticleMetadata > &metadata, const std::string &key) const
Query a metadata object for a given key and return the corresponding value.
std::vector< Slice > SliceVector
Definition: Slice.h:68
Utility object to perform functions of association.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
bool m_shouldProduceT0s
If we should produce T0s (relevant when stitching over multiple drift volumes)
art::InputTag m_pandoraTag
The input tag for the pandora producer.
Class to handle the required producer labels.
std::string m_inputProducerLabel
Label for the Pandora instance that produced the collections we want to consolidated.
HLT enums.
void BuildPFParticleMap(const PFParticleToMetadata &particlesToMetadata, PFParticleMap &particleMap) const
Build mapping from ID to PFParticle for fast navigation through the hierarchy.
void CollectConsolidatedParticles(const PFParticleVector &allParticles, const PFParticleVector &clearCosmics, const SliceVector &slices, PFParticleVector &consolidatedParticles) const
Get the consolidated collection of particles based on the slice ids.
TCEvent evt
Definition: DataStructs.cxx:5
helper function for LArPandoraInterface producer module
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void WriteToEvent() const
Write (put) the collections in this LArPandoraEvent to the art::Event.