All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LArPandoraModularShowerCreation_module.cc
Go to the documentation of this file.
1 //################################################################################
2 //### Name: LArPandoraModularShowerCreation ###
3 //### Author: Dominic Barker and Ed Tyley (e.tyley@sheffield.ac.uk) ###
4 //### Date: 15.05.19 ###
5 //### Description: Generic Shower Charaterisation module which allows the ###
6 //### the user choose which tool to calculate shower metrics. ###
7 //### For a complete shower the tools must define (use the exact ###
8 //### name) the following metrics in the shower property holder: ###
9 //### ShowerStartPosition ###
10 //### ShowerDirection ###
11 //### ShowerEnergy ###
12 //### ShowerdEdx ###
13 //### ShowerLength ###
14 //### ShowerOpeningAngle ###
15 //################################################################################
16 
17 //Framework includes
18 #include "art/Framework/Core/EDProducer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Utilities/make_tool.h"
21 
22 //LArSoft includes
30 
31 namespace reco::shower {
32  class LArPandoraModularShowerCreation;
33 }
34 
35 //Class
36 
37 class reco::shower::LArPandoraModularShowerCreation : public art::EDProducer {
38 public:
39  LArPandoraModularShowerCreation(fhicl::ParameterSet const& pset);
40 
41 private:
42  void produce(art::Event& evt);
43 
44  //This function returns the art::Ptr to the data object InstanceName.
45  //In the background it uses the PtrMaker which requires the element index of
46  //the unique ptr (iter).
47  template <class T>
48  art::Ptr<T> GetProducedElementPtr(const std::string& InstanceName,
49  const reco::shower::ShowerElementHolder& ShowerEleHolder,
50  const int& iter = -1);
51 
52  //fcl object names
53  unsigned int fNumPlanes;
54  const art::InputTag fPFParticleLabel;
56  const int fVerbose;
57  const bool fUseAllParticles;
58 
59  //tool tags which calculate the characteristics of the shower
60  const std::string fShowerStartPositionLabel;
61  const std::string fShowerDirectionLabel;
62  const std::string fShowerEnergyLabel;
63  const std::string fShowerLengthLabel;
64  const std::string fShowerOpeningAngleLabel;
65  const std::string fShowerdEdxLabel;
66  const std::string fShowerBestPlaneLabel;
67 
68  //fcl tools
69  std::vector<std::unique_ptr<ShowerRecoTools::IShowerTool>> fShowerTools;
70  std::vector<std::string> fShowerToolNames;
71 
72  //map to the unique ptrs to
74 
75  // Required services
76  art::ServiceHandle<geo::Geometry> fGeom;
77 };
78 
79 //This function returns the art::Ptr to the data object InstanceName.
80 //In the background it uses the PtrMaker which requires the element index of
81 //the unique ptr (iter).
82 template <class T>
83 art::Ptr<T>
85  const std::string& InstanceName,
86  const reco::shower::ShowerElementHolder& ShowerEleHolder,
87  const int& iter)
88 {
89 
90  bool check_element = ShowerEleHolder.CheckElement(InstanceName);
91  if (!check_element) {
92  throw cet::exception("LArPandoraModularShowerCreation")
93  << "To get a element that does not exist" << std::endl;
94  }
95 
96  bool check_ptr = uniqueproducerPtrs.CheckUniqueProduerPtr(InstanceName);
97  if (!check_ptr) {
98  throw cet::exception("LArPandoraModularShowerCreation")
99  << "Tried to get a ptr that does not exist" << std::endl;
100  }
101 
102  //Get the number of the shower we are on.
103  int index;
104  if (iter != -1) { index = iter; }
105  else {
106  index = ShowerEleHolder.GetShowerNumber();
107  }
108 
109  //Make the ptr
110  art::Ptr<T> artptr = uniqueproducerPtrs.GetArtPtr<T>(InstanceName, index);
111  return artptr;
112 }
113 
115  fhicl::ParameterSet const& pset)
116  : EDProducer{pset}
117  , fPFParticleLabel(pset.get<art::InputTag>("PFParticleLabel"))
118  , fAllowPartialShowers(pset.get<bool>("AllowPartialShowers"))
119  , fVerbose(pset.get<int>("Verbose", 0))
120  , fUseAllParticles(pset.get<bool>("UseAllParticles", false))
121  , fShowerStartPositionLabel(pset.get<std::string>("ShowerStartPositionLabel"))
122  , fShowerDirectionLabel(pset.get<std::string>("ShowerDirectionLabel"))
123  , fShowerEnergyLabel(pset.get<std::string>("ShowerEnergyLabel"))
124  , fShowerLengthLabel(pset.get<std::string>("ShowerLengthLabel"))
125  , fShowerOpeningAngleLabel(pset.get<std::string>("ShowerOpeningAngleLabel"))
126  , fShowerdEdxLabel(pset.get<std::string>("ShowerdEdxLabel"))
127  , fShowerBestPlaneLabel(pset.get<std::string>("ShowerBestPlaneLabel"))
128 {
129  //Intialise the tools
130  auto tool_psets = pset.get<std::vector<fhicl::ParameterSet>>("ShowerFinderTools");
131  for (auto& tool_pset : tool_psets) {
132 
133  const std::string tool_name(tool_pset.get<std::string>("tool_type"));
134  // If the PFPaticle label is not set for the tool, make it use the one for the module
135  // Note we also need to set the label in the Alg, via the base tool
136  if (!tool_pset.has_key("PFParticleLabel")) {
137 
138  // I cannot pass an art::InputTag as it is mangled, so lets make a string instead
139  const std::string PFParticleLabelString(fPFParticleLabel.label() + ":" +
140  fPFParticleLabel.instance() + ":" +
141  fPFParticleLabel.process());
142 
143  tool_pset.put<std::string>("PFParticleLabel", PFParticleLabelString);
144  fhicl::ParameterSet base_pset = tool_pset.get<fhicl::ParameterSet>("BaseTools");
145  fhicl::ParameterSet alg_pset = base_pset.get<fhicl::ParameterSet>("LArPandoraShowerAlg");
146  alg_pset.put<std::string>("PFParticleLabel", PFParticleLabelString);
147  base_pset.put_or_replace<fhicl::ParameterSet>("LArPandoraShowerAlg", alg_pset);
148  tool_pset.put_or_replace<fhicl::ParameterSet>("BaseTools", base_pset);
149 
150  if (tool_pset.has_key("LArPandoraShowerCheatingAlg")) {
151  fhicl::ParameterSet cheat_alg_pset =
152  tool_pset.get<fhicl::ParameterSet>("LArPandoraShowerCheatingAlg");
153  cheat_alg_pset.put<std::string>("PFParticleLabel", PFParticleLabelString);
154  cheat_alg_pset.put_or_replace<fhicl::ParameterSet>("LArPandoraShowerAlg", alg_pset);
155  tool_pset.put_or_replace<fhicl::ParameterSet>("LArPandoraShowerCheatingAlg",
156  cheat_alg_pset);
157  }
158  }
159 
160  // If we have not explicitly set verboseness for a given tool, use global level
161  if (!tool_pset.has_key("Verbose")) { tool_pset.put<int>("Verbose", fVerbose); }
162 
163  fShowerTools.push_back(art::make_tool<ShowerRecoTools::IShowerTool>(tool_pset));
164  fShowerToolNames.push_back(tool_name);
165 
166  fNumPlanes = fGeom->Nplanes();
167  }
168 
169  // Initialise the EDProducer ptr in the tools
170  std::vector<std::string> SetupTools;
171  for (unsigned int i = 0; i < fShowerTools.size(); ++i) {
172  if (std::find(SetupTools.begin(), SetupTools.end(), fShowerToolNames[i]) != SetupTools.end()) {
173  continue;
174  }
175  fShowerTools[i]->SetPtr(&producesCollector());
176  fShowerTools[i]->InitaliseProducerPtr(uniqueproducerPtrs);
177  fShowerTools[i]->InitialiseProducers();
178  }
179 
180  //Initialise the other paramters.
181 
182  produces<std::vector<recob::Shower>>();
183  produces<art::Assns<recob::Shower, recob::Hit>>();
184  produces<art::Assns<recob::Shower, recob::Cluster>>();
185  produces<art::Assns<recob::Shower, recob::SpacePoint>>();
186  produces<art::Assns<recob::Shower, recob::PFParticle>>();
187 
188  // Output -- showers and associations with hits and clusters
189  uniqueproducerPtrs.SetShowerUniqueProduerPtr(type<std::vector<recob::Shower>>(), "shower");
190  uniqueproducerPtrs.SetShowerUniqueProduerPtr(type<art::Assns<recob::Shower, recob::Cluster>>(),
191  "clusterAssociationsbase");
192  uniqueproducerPtrs.SetShowerUniqueProduerPtr(type<art::Assns<recob::Shower, recob::Hit>>(),
193  "hitAssociationsbase");
194  uniqueproducerPtrs.SetShowerUniqueProduerPtr(type<art::Assns<recob::Shower, recob::SpacePoint>>(),
195  "spShowerAssociationsbase");
196  uniqueproducerPtrs.SetShowerUniqueProduerPtr(type<art::Assns<recob::Shower, recob::PFParticle>>(),
197  "pfShowerAssociationsbase");
198 
199  uniqueproducerPtrs.PrintPtrs();
200 }
201 
202 void
204 {
205 
206  //Ptr makers for the products
207  uniqueproducerPtrs.SetPtrMakers(evt);
208  reco::shower::ShowerElementHolder showerEleHolder;
209 
210  //Get the PFParticles
211  auto const pfpHandle = evt.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
212  std::vector<art::Ptr<recob::PFParticle>> pfps;
213  art::fill_ptr_vector(pfps, pfpHandle);
214 
215  //Handle to access the pandora hits assans
216  auto const clusterHandle = evt.getValidHandle<std::vector<recob::Cluster>>(fPFParticleLabel);
217 
218  //Get the assoications to hits, clusters and spacespoints
219  const art::FindManyP<recob::Hit>& fmh =
220  showerEleHolder.GetFindManyP<recob::Hit>(clusterHandle, evt, fPFParticleLabel);
221  const art::FindManyP<recob::Cluster>& fmcp =
222  showerEleHolder.GetFindManyP<recob::Cluster>(pfpHandle, evt, fPFParticleLabel);
223  const art::FindManyP<recob::SpacePoint>& fmspp =
224  showerEleHolder.GetFindManyP<recob::SpacePoint>(pfpHandle, evt, fPFParticleLabel);
225 
226  //Holder to pass to the functions, contains the 6 properties of the shower
227  // - Start Poistion
228  // - Direction
229  // - Initial Track
230  // - Initial Track Hits
231  // - Energy
232  // - dEdx
233  // - Length
234  // - Opening Angle
235 
236  int shower_iter = 0;
237  //Loop of the pf particles
238  for (auto const& pfp : pfps) {
239 
240  //Update the shower iterator
241  showerEleHolder.SetShowerNumber(shower_iter);
242 
243  //loop only over showers unless otherwise specified
244  if (!fUseAllParticles && pfp->PdgCode() != 11 && pfp->PdgCode() != 22) continue;
245 
246  //Get the associated hits,clusters and spacepoints
247  const std::vector<art::Ptr<recob::Cluster>> showerClusters = fmcp.at(pfp.key());
248  const std::vector<art::Ptr<recob::SpacePoint>> showerSpacePoints = fmspp.at(pfp.key());
249 
250  // Check the pfp has at least 1 cluster (i.e. not a pfp neutrino)
251  if (!showerClusters.size()) continue;
252 
253  if (fVerbose > 1)
254  mf::LogInfo("LArPandoraModularShowerCreation")
255  << "Running on shower: " << shower_iter << std::endl;
256 
257  //Calculate the shower properties
258  //Loop over the shower tools
259  int err = 0;
260  for (unsigned int i = 0; i < fShowerTools.size(); i++) {
261 
262  //Calculate the metric
263  if (fVerbose > 1)
264  mf::LogInfo("LArPandoraModularShowerCreation")
265  << "Running shower tool: " << fShowerToolNames[i] << std::endl;
266  std::string evd_disp_append = fShowerToolNames[i] + "_iteration" + std::to_string(0) + "_" +
267  this->moduleDescription().moduleLabel();
268 
269  err = fShowerTools[i]->RunShowerTool(pfp, evt, showerEleHolder, evd_disp_append);
270 
271  if (err && fVerbose) {
272  mf::LogError("LArPandoraModularShowerCreation")
273  << "Error in shower tool: " << fShowerToolNames[i] << " with code: " << err << std::endl;
274  }
275  }
276 
277  //If we are are not allowing partial shower check all of the things
278  if (!fAllowPartialShowers) {
279  // If we recieved an error call from a tool return;
280 
281  // Check everything we need is in the shower element holder
282  if (!showerEleHolder.CheckElement(fShowerStartPositionLabel)) {
283  if (fVerbose)
284  mf::LogError("LArPandoraModularShowerCreation")
285  << "The start position is not set in the element holder. bailing" << std::endl;
286  continue;
287  }
288  if (!showerEleHolder.CheckElement(fShowerDirectionLabel)) {
289  if (fVerbose)
290  mf::LogError("LArPandoraModularShowerCreation")
291  << "The direction is not set in the element holder. bailing" << std::endl;
292  continue;
293  }
294  if (!showerEleHolder.CheckElement(fShowerEnergyLabel)) {
295  if (fVerbose)
296  mf::LogError("LArPandoraModularShowerCreation")
297  << "The energy is not set in the element holder. bailing" << std::endl;
298  continue;
299  }
300  if (!showerEleHolder.CheckElement(fShowerdEdxLabel)) {
301  if (fVerbose)
302  mf::LogError("LArPandoraModularShowerCreation")
303  << "The dEdx is not set in the element holder. bailing" << std::endl;
304  continue;
305  }
306  if (!showerEleHolder.CheckElement(fShowerBestPlaneLabel)) {
307  if (fVerbose)
308  mf::LogError("LArPandoraModularShowerCreation")
309  << "The BestPlane is not set in the element holder. bailing" << std::endl;
310  continue;
311  }
312  if (!showerEleHolder.CheckElement(fShowerLengthLabel)) {
313  if (fVerbose)
314  mf::LogError("LArPandoraModularShowerCreation")
315  << "The length is not set in the element holder. bailing" << std::endl;
316  continue;
317  }
318  if (!showerEleHolder.CheckElement(fShowerOpeningAngleLabel)) {
319  if (fVerbose)
320  mf::LogError("LArPandoraModularShowerCreation")
321  << "The opening angle is not set in the element holder. bailing" << std::endl;
322  continue;
323  }
324 
325  //Check All of the products that have been asked to be checked.
326  bool elements_are_set = showerEleHolder.CheckAllElementTags();
327  if (!elements_are_set) {
328  if (fVerbose)
329  mf::LogError("LArPandoraModularShowerCreation")
330  << "Not all the elements in the property holder which should be set are not. Bailing. "
331  << std::endl;
332  continue;
333  }
334 
335  ///Check all the producers
336  bool producers_are_set = uniqueproducerPtrs.CheckAllProducedElements(showerEleHolder);
337  if (!producers_are_set) {
338  if (fVerbose)
339  mf::LogError("LArPandoraModularShowerCreation")
340  << "Not all the elements in the property holder which are produced are not set. "
341  "Bailing. "
342  << std::endl;
343  continue;
344  }
345  }
346 
347  //Get the properties
348  TVector3 ShowerStartPosition(-999, -999, -999);
349  TVector3 ShowerDirection(-999, -999, -999);
350  std::vector<double> ShowerEnergy(fNumPlanes, -999);
351  std::vector<double> ShowerdEdx(fNumPlanes, -999);
352  int BestPlane(-999);
353  double ShowerLength(-999);
354  double ShowerOpeningAngle(-999);
355 
356  TVector3 ShowerStartPositionErr(-999, -999, -999);
357  TVector3 ShowerDirectionErr(-999, -999, -999);
358  std::vector<double> ShowerEnergyErr(fNumPlanes, -999);
359  std::vector<double> ShowerdEdxErr(fNumPlanes, -999);
360 
361  err = 0;
362  if (showerEleHolder.CheckElement(fShowerStartPositionLabel))
363  err += showerEleHolder.GetElementAndError(
364  fShowerStartPositionLabel, ShowerStartPosition, ShowerStartPositionErr);
365  if (showerEleHolder.CheckElement(fShowerDirectionLabel))
366  err += showerEleHolder.GetElementAndError(
367  fShowerDirectionLabel, ShowerDirection, ShowerDirectionErr);
368  if (showerEleHolder.CheckElement(fShowerEnergyLabel))
369  err += showerEleHolder.GetElementAndError(fShowerEnergyLabel, ShowerEnergy, ShowerEnergyErr);
370  if (showerEleHolder.CheckElement(fShowerdEdxLabel))
371  err += showerEleHolder.GetElementAndError(fShowerdEdxLabel, ShowerdEdx, ShowerdEdxErr);
372  if (showerEleHolder.CheckElement(fShowerBestPlaneLabel))
373  err += showerEleHolder.GetElement(fShowerBestPlaneLabel, BestPlane);
374  if (showerEleHolder.CheckElement(fShowerLengthLabel))
375  err += showerEleHolder.GetElement(fShowerLengthLabel, ShowerLength);
376  if (showerEleHolder.CheckElement(fShowerOpeningAngleLabel))
377  err += showerEleHolder.GetElement(fShowerOpeningAngleLabel, ShowerOpeningAngle);
378 
379  if (err) {
380  throw cet::exception("LArPandoraModularShowerCreation")
381  << "Error in LArPandoraModularShowerCreation Module. A Check on a shower property failed "
382  << std::endl;
383  }
384 
385  if (fVerbose > 1) {
386  //Check the shower
387  std::cout << "Shower Vertex: X:" << ShowerStartPosition.X()
388  << " Y: " << ShowerStartPosition.Y() << " Z: " << ShowerStartPosition.Z()
389  << std::endl;
390  std::cout << "Shower Direction: X:" << ShowerDirection.X() << " Y: " << ShowerDirection.Y()
391  << " Z: " << ShowerDirection.Z() << std::endl;
392  std::cout << "Shower dEdx:";
393  for (unsigned int i = 0; i < fNumPlanes; i++) {
394  std::cout << " Plane " << i << ": " << ShowerdEdx.at(i);
395  }
396  std::cout << std::endl;
397  std::cout << "Shower Energy:";
398  for (unsigned int i = 0; i < fNumPlanes; i++) {
399  std::cout << " Plane " << i << ": " << ShowerEnergy.at(i);
400  }
401  std::cout << std::endl;
402  std::cout << "Shower Best Plane: " << BestPlane << std::endl;
403  std::cout << "Shower Length: " << ShowerLength << std::endl;
404  std::cout << "Shower Opening Angle: " << ShowerOpeningAngle << std::endl;
405 
406  //Print what has been created in the shower
407  showerEleHolder.PrintElements();
408  }
409 
410  if (ShowerdEdx.size() != fNumPlanes) {
411  throw cet::exception("LArPandoraModularShowerCreation")
412  << "dEdx vector is wrong size: " << ShowerdEdx.size()
413  << " compared to Nplanes: " << fNumPlanes << std::endl;
414  }
415  if (ShowerEnergy.size() != fNumPlanes) {
416  throw cet::exception("LArPandoraModularShowerCreation")
417  << "Energy vector is wrong size: " << ShowerEnergy.size()
418  << " compared to Nplanes: " << fNumPlanes << std::endl;
419  }
420 
421  //Make the shower
422  recob::Shower shower(ShowerDirection,
423  ShowerDirectionErr,
424  ShowerStartPosition,
425  ShowerDirectionErr,
426  ShowerEnergy,
427  ShowerEnergyErr,
428  ShowerdEdx,
429  ShowerdEdxErr,
430  BestPlane,
432  ShowerLength,
433  ShowerOpeningAngle);
434  showerEleHolder.SetElement(shower, "shower");
435  ++shower_iter;
436  art::Ptr<recob::Shower> ShowerPtr =
437  this->GetProducedElementPtr<recob::Shower>("shower", showerEleHolder);
438 
439  //Associate the pfparticle
440  uniqueproducerPtrs.AddSingle<art::Assns<recob::Shower, recob::PFParticle>>(
441  ShowerPtr, pfp, "pfShowerAssociationsbase");
442 
443  //Add the hits for each "cluster"
444  for (auto const& cluster : showerClusters) {
445 
446  //Associate the clusters
447  std::vector<art::Ptr<recob::Hit>> ClusterHits = fmh.at(cluster.key());
448  uniqueproducerPtrs.AddSingle<art::Assns<recob::Shower, recob::Cluster>>(
449  ShowerPtr, cluster, "clusterAssociationsbase");
450 
451  //Associate the hits
452  for (auto const& hit : ClusterHits) {
453  uniqueproducerPtrs.AddSingle<art::Assns<recob::Shower, recob::Hit>>(
454  ShowerPtr, hit, "hitAssociationsbase");
455  }
456  }
457 
458  //Associate the spacepoints
459  for (auto const& sp : showerSpacePoints) {
460  uniqueproducerPtrs.AddSingle<art::Assns<recob::Shower, recob::SpacePoint>>(
461  ShowerPtr, sp, "spShowerAssociationsbase");
462  }
463 
464  //Loop over the tool data products and add them.
465  uniqueproducerPtrs.AddDataProducts(showerEleHolder);
466 
467  //AddAssociations
468  int assn_err = 0;
469  for (auto const& fShowerTool : fShowerTools) {
470  //AddAssociations
471  assn_err += fShowerTool->AddAssociations(pfp, evt, showerEleHolder);
472  }
473  if (!fAllowPartialShowers && assn_err > 0) {
474  if (fVerbose)
475  mf::LogError("LArPandoraModularShowerCreation")
476  << "A association failed and not allowing partial showers. The association will not be "
477  "added to the event "
478  << std::endl;
479  }
480 
481  //Reset the showerproperty holder.
482  showerEleHolder.ClearShower();
483  }
484 
485  //Put everything in the event.
486  uniqueproducerPtrs.MoveAllToEvent(evt);
487 
488  //Reset the ptrs to the data products
489  uniqueproducerPtrs.reset();
490 }
491 
process_name cluster
Definition: cheaterreco.fcl:51
Declaration of signal hit object.
EResult err(const char *call)
void SetElement(T &dataproduct, const std::string &Name, bool checktag=false)
constexpr int kBogusI
obviously bogus integer value
Set of hits with a 2D structure.
Definition: Cluster.h:71
const art::FindManyP< T1 > & GetFindManyP(const art::ValidHandle< std::vector< T2 > > &handle, const art::Event &evt, const art::InputTag &moduleTag)
double ShowerEnergy(const ShowerStruct3D &ss3)
Definition: TCShower.cxx:3954
process_name hit
Definition: cheaterreco.fcl:51
process_name shower
Definition: cheaterreco.fcl:51
bool CheckUniqueProduerPtr(const std::string &Name) const
art::Ptr< T > GetProducedElementPtr(const std::string &InstanceName, const reco::shower::ShowerElementHolder &ShowerEleHolder, const int &iter=-1)
bool CheckElement(const std::string &Name) const
int GetElement(const std::string &Name, T &Element) const
Declaration of cluster object.
std::string to_string(WindowPattern const &pattern)
std::vector< std::unique_ptr< ShowerRecoTools::IShowerTool > > fShowerTools
int GetElementAndError(const std::string &Name, T &Element, T2 &ElementErr) const
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::Ptr< T > GetArtPtr(const std::string &Name, const int &iter) const
TCEvent evt
Definition: DataStructs.cxx:8
BEGIN_PROLOG could also be cout