All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MasterAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArControlFlow/MasterAlgorithm.cc
3  *
4  * @brief Implementation of the master algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Api/PandoraApi.h"
10 
11 #include "Pandora/AlgorithmHeaders.h"
12 
15 
21 
24 
27 
29 
30 using namespace pandora;
31 
32 namespace lar_content
33 {
34 
35 MasterAlgorithm::MasterAlgorithm() :
36  m_workerInstancesInitialized(false),
37  m_larCaloHitVersion(1),
38  m_shouldRunAllHitsCosmicReco(true),
39  m_shouldRunStitching(true),
40  m_shouldRunCosmicHitRemoval(true),
41  m_shouldRunSlicing(true),
42  m_shouldRunNeutrinoRecoOption(true),
43  m_shouldRunCosmicRecoOption(true),
44  m_shouldPerformSliceId(true),
45  m_printOverallRecoStatus(false),
46  m_visualizeOverallRecoStatus(false),
47  m_shouldRemoveOutOfTimeHits(true),
48  m_pSlicingWorkerInstance(nullptr),
49  m_pSliceNuWorkerInstance(nullptr),
50  m_pSliceCRWorkerInstance(nullptr),
51  m_fullWidthCRWorkerWireGaps(true),
52  m_passMCParticlesToWorkerInstances(false),
53  m_filePathEnvironmentVariable("FW_SEARCH_PATH"),
54  m_inTimeMaxX0(1.f)
55 {
56 }
57 
58 //------------------------------------------------------------------------------------------------------------------------------------------
59 
60 void MasterAlgorithm::ShiftPfoHierarchy(const ParticleFlowObject *const pParentPfo, const PfoToLArTPCMap &pfoToLArTPCMap, const float x0) const
61 {
62  if (!pParentPfo->GetParentPfoList().empty())
63  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
64 
65  PfoToLArTPCMap::const_iterator larTPCIter(pfoToLArTPCMap.find(pParentPfo));
66 
67  if (pfoToLArTPCMap.end() == larTPCIter)
68  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
69 
70  PfoList pfoList;
71  LArPfoHelper::GetAllDownstreamPfos(pParentPfo, pfoList);
72 
74  {
75  std::cout << "ShiftPfoHierarchy: x0 " << x0 << std::endl;
76  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &pfoList, "BeforeShiftCRPfos", GREEN));
77  }
78 
79  for (const ParticleFlowObject *const pDaughterPfo : pfoList)
80  {
81  CaloHitList caloHitList;
82  for (const Cluster *const pCluster : pDaughterPfo->GetClusterList())
83  {
84  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
85  caloHitList.insert(caloHitList.end(), pCluster->GetIsolatedCaloHitList().begin(), pCluster->GetIsolatedCaloHitList().end());
86  }
87 
88  for (const CaloHit *const pCaloHit : caloHitList)
89  {
90  PandoraContentApi::CaloHit::Metadata metadata;
91  metadata.m_x0 = x0;
92  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pCaloHit, metadata));
93  }
94 
95  for (const Vertex *const pVertex : pDaughterPfo->GetVertexList())
96  {
97  PandoraContentApi::Vertex::Metadata metadata;
98  metadata.m_x0 = x0;
99  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::AlterMetadata(*this, pVertex, metadata));
100  }
101  }
102 
104  {
105  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &pfoList, "AfterShiftCRPfos", RED));
106  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
107  }
108 }
109 
110 //------------------------------------------------------------------------------------------------------------------------------------------
111 
113  const ParticleFlowObject *const pPfoToEnlarge, const ParticleFlowObject *const pPfoToDelete, PfoToLArTPCMap &pfoToLArTPCMap) const
114 {
115  if (pPfoToEnlarge == pPfoToDelete)
116  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
117 
118  // ATTN Remove pfos from pfo to lar tpc map here, avoiding problems if stitching across multiple tpcs.
119  pfoToLArTPCMap.erase(pPfoToEnlarge);
120  pfoToLArTPCMap.erase(pPfoToDelete);
121 
122  const PfoList daughterPfos(pPfoToDelete->GetDaughterPfoList());
123  const ClusterVector daughterClusters(pPfoToDelete->GetClusterList().begin(), pPfoToDelete->GetClusterList().end());
124  const VertexVector daughterVertices(pPfoToDelete->GetVertexList().begin(), pPfoToDelete->GetVertexList().end());
125 
126  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfoToDelete, m_recreatedPfoListName));
127 
128  for (const ParticleFlowObject *const pDaughterPfo : daughterPfos)
129  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pPfoToEnlarge, pDaughterPfo));
130 
131  for (const Vertex *const pDaughterVertex : daughterVertices)
132  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pDaughterVertex, m_recreatedVertexListName));
133 
134  for (const Cluster *const pDaughterCluster : daughterClusters)
135  {
136  const HitType daughterHitType(LArClusterHelper::GetClusterHitType(pDaughterCluster));
137  const Cluster *pParentCluster(PfoMopUpBaseAlgorithm::GetParentCluster(pPfoToEnlarge->GetClusterList(), daughterHitType));
138 
139  if (pParentCluster)
140  {
141  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
142  PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pDaughterCluster, m_recreatedClusterListName, m_recreatedClusterListName));
143  }
144  else
145  {
146  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*this, pPfoToEnlarge, pDaughterCluster));
147  }
148  }
149 }
150 
151 //------------------------------------------------------------------------------------------------------------------------------------------
152 
154 {
155  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Reset());
156 
158  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->InitializeWorkerInstances());
159 
161  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->CopyMCParticles());
162 
163  PfoToFloatMap stitchedPfosToX0Map;
164  VolumeIdToHitListMap volumeIdToHitListMap;
165  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetVolumeIdToHitListMap(volumeIdToHitListMap));
166 
168  {
169  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunCosmicRayReconstruction(volumeIdToHitListMap));
170 
171  PfoToLArTPCMap pfoToLArTPCMap;
172  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RecreateCosmicRayPfos(pfoToLArTPCMap));
173 
175  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->StitchCosmicRayPfos(pfoToLArTPCMap, stitchedPfosToX0Map));
176  }
177 
179  {
180  PfoList clearCosmicRayPfos, ambiguousPfos;
181  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->TagCosmicRayPfos(stitchedPfosToX0Map, clearCosmicRayPfos, ambiguousPfos));
182  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunCosmicRayHitRemoval(ambiguousPfos));
183  }
184 
185  SliceVector sliceVector;
186  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunSlicing(volumeIdToHitListMap, sliceVector));
187 
189  {
190  SliceHypotheses nuSliceHypotheses, crSliceHypotheses;
191  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunSliceReconstruction(sliceVector, nuSliceHypotheses, crSliceHypotheses));
192  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->SelectBestSliceHypotheses(nuSliceHypotheses, crSliceHypotheses));
193  }
194 
195  return STATUS_CODE_SUCCESS;
196 }
197 
198 //------------------------------------------------------------------------------------------------------------------------------------------
199 
201 {
202  // ATTN Used to be in the regular Initialize callback, but detector gap list cannot be extracted in client app before the first event
204  return STATUS_CODE_ALREADY_INITIALIZED;
205 
206  try
207  {
208  const LArTPCMap &larTPCMap(this->GetPandora().GetGeometry()->GetLArTPCMap());
209  const DetectorGapList &gapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
210 
211  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
212  {
213  const unsigned int volumeId(mapEntry.second->GetLArTPCVolumeId());
214  m_crWorkerInstances.push_back(
215  this->CreateWorkerInstance(*(mapEntry.second), gapList, m_crSettingsFile, "CRWorkerInstance" + std::to_string(volumeId)));
216  }
217 
218  if (m_shouldRunSlicing)
219  m_pSlicingWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_slicingSettingsFile, "SlicingWorker");
220 
222  m_pSliceNuWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_nuSettingsFile, "SliceNuWorker");
223 
225  m_pSliceCRWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_crSettingsFile, "SliceCRWorker");
226  }
227  catch (const StatusCodeException &statusCodeException)
228  {
229  std::cout << "MasterAlgorithm: Exception during initialization of worker instances " << statusCodeException.ToString() << std::endl;
230  return statusCodeException.GetStatusCode();
231  }
232 
234  return STATUS_CODE_SUCCESS;
235 }
236 
237 //------------------------------------------------------------------------------------------------------------------------------------------
238 
240 {
241  const MCParticleList *pMCParticleList(nullptr);
242  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputMCParticleListName, pMCParticleList));
243 
244  PandoraInstanceList pandoraWorkerInstances(m_crWorkerInstances);
246  pandoraWorkerInstances.push_back(m_pSlicingWorkerInstance);
248  pandoraWorkerInstances.push_back(m_pSliceNuWorkerInstance);
250  pandoraWorkerInstances.push_back(m_pSliceCRWorkerInstance);
251 
252  LArMCParticleFactory mcParticleFactory;
253 
254  for (const Pandora *const pPandoraWorker : pandoraWorkerInstances)
255  {
256  for (const MCParticle *const pMCParticle : *pMCParticleList)
257  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(pPandoraWorker, pMCParticle, &mcParticleFactory));
258  }
259 
260  return STATUS_CODE_SUCCESS;
261 }
262 
263 //------------------------------------------------------------------------------------------------------------------------------------------
264 
265 StatusCode MasterAlgorithm::GetVolumeIdToHitListMap(VolumeIdToHitListMap &volumeIdToHitListMap) const
266 {
267  const LArTPCMap &larTPCMap(this->GetPandora().GetGeometry()->GetLArTPCMap());
268  const unsigned int nLArTPCs(larTPCMap.size());
269 
270  const CaloHitList *pCaloHitList(nullptr);
271  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputHitListName, pCaloHitList));
272 
273  for (const CaloHit *const pCaloHit : *pCaloHitList)
274  {
275  const LArCaloHit *const pLArCaloHit(dynamic_cast<const LArCaloHit *>(pCaloHit));
276 
277  if (!pLArCaloHit && (1 != nLArTPCs))
278  return STATUS_CODE_INVALID_PARAMETER;
279 
280  const unsigned int volumeId(pLArCaloHit ? pLArCaloHit->GetLArTPCVolumeId() : 0);
281  const LArTPC *const pLArTPC(larTPCMap.at(volumeId));
282 
283  LArTPCHitList &larTPCHitList(volumeIdToHitListMap[volumeId]);
284  larTPCHitList.m_allHitList.push_back(pCaloHit);
285 
286  if (((pCaloHit->GetPositionVector().GetX() >= (pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX())) &&
287  (pCaloHit->GetPositionVector().GetX() <= (pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX()))))
288  {
289  larTPCHitList.m_truncatedHitList.push_back(pCaloHit);
290  }
291  }
292 
293  return STATUS_CODE_SUCCESS;
294 }
295 
296 //------------------------------------------------------------------------------------------------------------------------------------------
297 
298 StatusCode MasterAlgorithm::RunCosmicRayReconstruction(const VolumeIdToHitListMap &volumeIdToHitListMap) const
299 {
300  unsigned int workerCounter(0);
301 
302  for (const Pandora *const pCRWorker : m_crWorkerInstances)
303  {
304  const LArTPC &larTPC(pCRWorker->GetGeometry()->GetLArTPC());
305  VolumeIdToHitListMap::const_iterator iter(volumeIdToHitListMap.find(larTPC.GetLArTPCVolumeId()));
306 
307  if (volumeIdToHitListMap.end() == iter)
308  continue;
309 
310  for (const CaloHit *const pCaloHit : iter->second.m_allHitList)
311  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(pCRWorker, pCaloHit));
312 
314  std::cout << "Running cosmic-ray reconstruction worker instance " << ++workerCounter << " of " << m_crWorkerInstances.size() << std::endl;
315 
316  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*pCRWorker));
317  }
318 
319  return STATUS_CODE_SUCCESS;
320 }
321 
322 //------------------------------------------------------------------------------------------------------------------------------------------
323 
325 {
326  for (const Pandora *const pCRWorker : m_crWorkerInstances)
327  {
328  const PfoList *pCRPfos(nullptr);
329  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*pCRWorker, pCRPfos));
330 
331  PfoList newPfoList;
332  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Recreate(*pCRPfos, newPfoList));
333 
334  const LArTPC &larTPC(pCRWorker->GetGeometry()->GetLArTPC());
335 
336  for (const Pfo *const pNewPfo : newPfoList)
337  pfoToLArTPCMap[pNewPfo] = &larTPC;
338  }
339 
340  return STATUS_CODE_SUCCESS;
341 }
342 
343 //------------------------------------------------------------------------------------------------------------------------------------------
344 
345 StatusCode MasterAlgorithm::StitchCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
346 {
347  const PfoList *pRecreatedCRPfos(nullptr);
348  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(this->GetPandora(), pRecreatedCRPfos));
349 
351  {
352  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pRecreatedCRPfos, "RecreatedCRPfos", GREEN));
353  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
354  }
355 
356  for (StitchingBaseTool *const pStitchingTool : m_stitchingToolVector)
357  pStitchingTool->Run(this, pRecreatedCRPfos, pfoToLArTPCMap, stitchedPfosToX0Map);
358 
360  {
361  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pRecreatedCRPfos, "AfterStitchingCRPfos", RED));
362  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
363  }
364 
365  return STATUS_CODE_SUCCESS;
366 }
367 
368 //------------------------------------------------------------------------------------------------------------------------------------------
369 
370 StatusCode MasterAlgorithm::TagCosmicRayPfos(const PfoToFloatMap &stitchedPfosToX0Map, PfoList &clearCosmicRayPfos, PfoList &ambiguousPfos) const
371 {
372  const PfoList *pRecreatedCRPfos(nullptr);
373  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(this->GetPandora(), pRecreatedCRPfos));
374 
375  PfoList nonStitchedParentCosmicRayPfos;
376  for (const Pfo *const pPfo : *pRecreatedCRPfos)
377  {
378  if (!pPfo->GetParentPfoList().empty())
379  continue;
380 
381  PfoToFloatMap::const_iterator pfoToX0Iter = stitchedPfosToX0Map.find(pPfo);
382  const float x0Shift((pfoToX0Iter != stitchedPfosToX0Map.end()) ? pfoToX0Iter->second : 0.f);
383  PfoList &targetList((std::fabs(x0Shift) > m_inTimeMaxX0) ? clearCosmicRayPfos : nonStitchedParentCosmicRayPfos);
384  targetList.push_back(pPfo);
385  }
386 
387  for (CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool : m_cosmicRayTaggingToolVector)
388  pCosmicRayTaggingTool->FindAmbiguousPfos(nonStitchedParentCosmicRayPfos, ambiguousPfos, this);
389 
390  for (const Pfo *const pPfo : nonStitchedParentCosmicRayPfos)
391  {
392  const bool isClearCosmic(ambiguousPfos.end() == std::find(ambiguousPfos.begin(), ambiguousPfos.end(), pPfo));
393 
394  if (isClearCosmic)
395  clearCosmicRayPfos.push_back(pPfo);
396  }
397 
398  for (const Pfo *const pPfo : *pRecreatedCRPfos)
399  {
400  const bool isClearCosmic(ambiguousPfos.end() == std::find(ambiguousPfos.begin(), ambiguousPfos.end(), pPfo));
401  PandoraContentApi::ParticleFlowObject::Metadata metadata;
402  metadata.m_propertiesToAdd["IsClearCosmic"] = (isClearCosmic ? 1.f : 0.f);
403  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
404  }
405 
407  {
408  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &clearCosmicRayPfos, "ClearCRPfos", RED));
409  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &ambiguousPfos, "AmbiguousCRPfos", BLUE));
410  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
411  }
412 
413  return STATUS_CODE_SUCCESS;
414 }
415 
416 //------------------------------------------------------------------------------------------------------------------------------------------
417 
418 StatusCode MasterAlgorithm::RunCosmicRayHitRemoval(const PfoList &ambiguousPfos) const
419 {
420  PfoList allPfosToDelete;
421  LArPfoHelper::GetAllConnectedPfos(ambiguousPfos, allPfosToDelete);
422 
423  for (const Pfo *const pPfoToDelete : allPfosToDelete)
424  {
425  const ClusterList clusterList(pPfoToDelete->GetClusterList());
426  const VertexList vertexList(pPfoToDelete->GetVertexList());
427 
428  // ATTN: If an ambiguous pfo has been stitched, reset the calo hit positions in preparation for subsequent algorithm chains
429  if (LArStitchingHelper::HasPfoBeenStitched(pPfoToDelete))
430  {
431  CaloHitList caloHitList2D;
432  LArPfoHelper::GetCaloHits(pPfoToDelete, TPC_VIEW_U, caloHitList2D);
433  LArPfoHelper::GetCaloHits(pPfoToDelete, TPC_VIEW_V, caloHitList2D);
434  LArPfoHelper::GetCaloHits(pPfoToDelete, TPC_VIEW_W, caloHitList2D);
435  LArPfoHelper::GetIsolatedCaloHits(pPfoToDelete, TPC_VIEW_U, caloHitList2D);
436  LArPfoHelper::GetIsolatedCaloHits(pPfoToDelete, TPC_VIEW_V, caloHitList2D);
437  LArPfoHelper::GetIsolatedCaloHits(pPfoToDelete, TPC_VIEW_W, caloHitList2D);
438 
439  for (const CaloHit *const pCaloHit : caloHitList2D)
440  {
441  PandoraContentApi::CaloHit::Metadata metadata;
442  metadata.m_x0 = 0.f;
443  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pCaloHit, metadata));
444  }
445  }
446 
447  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfoToDelete));
448  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &clusterList));
449  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &vertexList));
450  }
451 
452  return STATUS_CODE_SUCCESS;
453 }
454 
455 //------------------------------------------------------------------------------------------------------------------------------------------
456 
457 StatusCode MasterAlgorithm::RunSlicing(const VolumeIdToHitListMap &volumeIdToHitListMap, SliceVector &sliceVector) const
458 {
459  for (const VolumeIdToHitListMap::value_type &mapEntry : volumeIdToHitListMap)
460  {
461  for (const CaloHit *const pCaloHit : (m_shouldRemoveOutOfTimeHits ? mapEntry.second.m_truncatedHitList : mapEntry.second.m_allHitList))
462  {
463  if (!PandoraContentApi::IsAvailable(*this, pCaloHit))
464  continue;
465 
466  const HitType hitType(pCaloHit->GetHitType());
467  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
468  continue;
469 
470  if (m_shouldRunSlicing)
471  {
472  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSlicingWorkerInstance, pCaloHit));
473  }
474  else
475  {
476  if (sliceVector.empty())
477  sliceVector.push_back(CaloHitList());
478  sliceVector.back().push_back(pCaloHit);
479  }
480  }
481  }
482 
483  if (m_shouldRunSlicing)
484  {
486  std::cout << "Running slicing worker instance" << std::endl;
487 
488  const PfoList *pSlicePfos(nullptr);
489  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSlicingWorkerInstance));
490  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSlicingWorkerInstance, pSlicePfos));
491 
493  {
494  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pSlicePfos, "OnePfoPerSlice", BLUE));
495  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
496  }
497 
498  for (const Pfo *const pSlicePfo : *pSlicePfos)
499  {
500  sliceVector.push_back(CaloHitList());
501  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_U, sliceVector.back());
502  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_V, sliceVector.back());
503  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_W, sliceVector.back());
504  }
505  }
506 
508  std::cout << "Identified " << sliceVector.size() << " slice(s)" << std::endl;
509 
510  return STATUS_CODE_SUCCESS;
511 }
512 
513 //------------------------------------------------------------------------------------------------------------------------------------------
514 
515 StatusCode MasterAlgorithm::RunSliceReconstruction(SliceVector &sliceVector, SliceHypotheses &nuSliceHypotheses, SliceHypotheses &crSliceHypotheses) const
516 {
517  SliceVector selectedSliceVector;
519  {
520  SliceVector inputSliceVector(sliceVector);
521  for (SliceSelectionBaseTool *const pSliceSelectionTool : m_sliceSelectionToolVector)
522  {
523  pSliceSelectionTool->SelectSlices(this, inputSliceVector, selectedSliceVector);
524  inputSliceVector = selectedSliceVector;
525  }
526  }
527  else
528  {
529  selectedSliceVector = std::move(sliceVector);
530  }
531 
532  unsigned int sliceCounter(0);
533 
534  for (const CaloHitList &sliceHits : selectedSliceVector)
535  {
536  for (const CaloHit *const pSliceCaloHit : sliceHits)
537  {
538  // ATTN Must ensure we copy the hit actually owned by master instance; access differs with/without slicing enabled
539  const CaloHit *const pCaloHitInMaster(m_shouldRunSlicing ? static_cast<const CaloHit *>(pSliceCaloHit->GetParentAddress()) : pSliceCaloHit);
540 
542  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceNuWorkerInstance, pCaloHitInMaster));
543 
545  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceCRWorkerInstance, pCaloHitInMaster));
546  }
547 
549  {
551  std::cout << "Running nu worker instance for slice " << (sliceCounter + 1) << " of " << selectedSliceVector.size() << std::endl;
552 
553  const PfoList *pSliceNuPfos(nullptr);
554  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceNuWorkerInstance));
555  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceNuWorkerInstance, pSliceNuPfos));
556  nuSliceHypotheses.push_back(*pSliceNuPfos);
557 
558  for (const ParticleFlowObject *const pPfo : *pSliceNuPfos)
559  {
560  PandoraContentApi::ParticleFlowObject::Metadata metadata;
561  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
562  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
563  }
564  }
565 
567  {
569  std::cout << "Running cr worker instance for slice " << (sliceCounter + 1) << " of " << selectedSliceVector.size() << std::endl;
570 
571  const PfoList *pSliceCRPfos(nullptr);
572  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceCRWorkerInstance));
573  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceCRWorkerInstance, pSliceCRPfos));
574  crSliceHypotheses.push_back(*pSliceCRPfos);
575 
576  for (const ParticleFlowObject *const pPfo : *pSliceCRPfos)
577  {
578  PandoraContentApi::ParticleFlowObject::Metadata metadata;
579  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
580  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
581  }
582  }
583 
584  ++sliceCounter;
585  }
586 
587  // ATTN: If we swapped these objects at the start, be sure to swap them back in case we ever want to use sliceVector
588  // after this function
590  sliceVector = std::move(selectedSliceVector);
591 
592  if (m_shouldRunNeutrinoRecoOption && m_shouldRunCosmicRecoOption && (nuSliceHypotheses.size() != crSliceHypotheses.size()))
593  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
594 
595  return STATUS_CODE_SUCCESS;
596 }
597 
598 //------------------------------------------------------------------------------------------------------------------------------------------
599 
600 StatusCode MasterAlgorithm::SelectBestSliceHypotheses(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses) const
601 {
603  std::cout << "Select best slice hypotheses" << std::endl;
604 
605  PfoList selectedSlicePfos;
606 
608  {
609  for (SliceIdBaseTool *const pSliceIdTool : m_sliceIdToolVector)
610  pSliceIdTool->SelectOutputPfos(this, nuSliceHypotheses, crSliceHypotheses, selectedSlicePfos);
611  }
613  {
614  const SliceHypotheses &sliceHypotheses(m_shouldRunNeutrinoRecoOption ? nuSliceHypotheses : crSliceHypotheses);
615 
616  for (const PfoList &slice : sliceHypotheses)
617  selectedSlicePfos.insert(selectedSlicePfos.end(), slice.begin(), slice.end());
618  }
619 
620  PfoList newSlicePfoList;
621  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Recreate(selectedSlicePfos, newSlicePfoList));
622 
623  return STATUS_CODE_SUCCESS;
624 }
625 
626 //------------------------------------------------------------------------------------------------------------------------------------------
627 
629 {
630  for (const Pandora *const pCRWorker : m_crWorkerInstances)
631  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*pCRWorker));
632 
634  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSlicingWorkerInstance));
635 
637  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceNuWorkerInstance));
638 
640  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceCRWorkerInstance));
641 
642  return STATUS_CODE_SUCCESS;
643 }
644 
645 //------------------------------------------------------------------------------------------------------------------------------------------
646 
647 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const CaloHit *const pCaloHit) const
648 {
649  const LArCaloHit *const pLArCaloHit{dynamic_cast<const LArCaloHit *>(pCaloHit)};
650  if (pLArCaloHit == nullptr)
651  {
652  std::cout << "MasterAlgorithm: Could not cast CaloHit to LArCaloHit" << std::endl;
653  return STATUS_CODE_INVALID_PARAMETER;
654  }
655  LArCaloHitParameters parameters;
656  pLArCaloHit->FillParameters(parameters);
657  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*pPandora, parameters, m_larCaloHitFactory));
658 
660  {
661  MCParticleVector mcParticleVector;
662  for (const auto &weightMapEntry : pLArCaloHit->GetMCParticleWeightMap())
663  mcParticleVector.push_back(weightMapEntry.first);
664  std::sort(mcParticleVector.begin(), mcParticleVector.end(), LArMCParticleHelper::SortByMomentum);
665 
666  for (const MCParticle *const pMCParticle : mcParticleVector)
667  {
668  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
669  PandoraApi::SetCaloHitToMCParticleRelationship(*pPandora, pLArCaloHit, pMCParticle, pLArCaloHit->GetMCParticleWeightMap().at(pMCParticle)));
670  }
671  }
672 
673  return STATUS_CODE_SUCCESS;
674 }
675 
676 //------------------------------------------------------------------------------------------------------------------------------------------
677 
678 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const MCParticle *const pMCParticle, const LArMCParticleFactory *const pMCParticleFactory) const
679 {
680  const LArMCParticle *const pLArMCParticle = dynamic_cast<const LArMCParticle *>(pMCParticle);
681 
682  if (!pLArMCParticle)
683  {
684  std::cout << "MasterAlgorithm::Copy - Expect to pass only LArMCParticles to Pandora worker instances." << std::endl;
685  return STATUS_CODE_INVALID_PARAMETER;
686  }
687 
688  LArMCParticleParameters parameters;
689  pLArMCParticle->FillParameters(parameters);
690  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*pPandora, parameters, *pMCParticleFactory));
691 
692  for (const MCParticle *const pDaughterMCParticle : pMCParticle->GetDaughterList())
693  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pMCParticle, pDaughterMCParticle));
694 
695  for (const MCParticle *const pParentMCParticle : pMCParticle->GetParentList())
696  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pParentMCParticle, pMCParticle));
697 
698  return STATUS_CODE_SUCCESS;
699 }
700 
701 //------------------------------------------------------------------------------------------------------------------------------------------
702 
703 StatusCode MasterAlgorithm::Recreate(const PfoList &inputPfoList, PfoList &newPfoList) const
704 {
705  if (inputPfoList.empty())
706  return STATUS_CODE_SUCCESS;
707 
708  // TODO if no pfo in input list is primary - raise exception
709 
710  std::string clusterListName;
711  const ClusterList *pClusterList(nullptr);
712  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pClusterList, clusterListName));
713 
714  std::string vertexListName;
715  const VertexList *pVertexList(nullptr);
716  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
717 
718  std::string pfoListName;
719  const PfoList *pPfoList(nullptr);
720  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
721 
722  for (const Pfo *const pPfo : inputPfoList)
723  {
724  if (pPfo->GetParentPfoList().empty())
725  this->Recreate(pPfo, nullptr, newPfoList);
726  }
727 
728  if (!pClusterList->empty())
729  {
730  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, m_recreatedClusterListName));
731  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_recreatedClusterListName));
732  }
733 
734  if (!pVertexList->empty())
735  {
736  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_recreatedVertexListName));
737  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_recreatedVertexListName));
738  }
739 
740  if (!pPfoList->empty())
741  {
742  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<ParticleFlowObject>(*this, m_recreatedPfoListName));
743  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<ParticleFlowObject>(*this, m_recreatedPfoListName));
744  }
745 
746  return STATUS_CODE_SUCCESS;
747 }
748 
749 //------------------------------------------------------------------------------------------------------------------------------------------
750 
751 StatusCode MasterAlgorithm::Recreate(const ParticleFlowObject *const pInputPfo, const ParticleFlowObject *const pNewParentPfo, PfoList &newPfoList) const
752 {
753  ClusterList inputClusterList2D, inputClusterList3D, newClusterList;
754  LArPfoHelper::GetTwoDClusterList(pInputPfo, inputClusterList2D);
755  LArPfoHelper::GetThreeDClusterList(pInputPfo, inputClusterList3D);
756 
757  for (const Cluster *const pInputCluster : inputClusterList2D)
758  {
759  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
760  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
761 
762  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
763  newCaloHitList.push_back(static_cast<const CaloHit *>(pInputCaloHit->GetParentAddress()));
764 
765  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
766  newIsolatedCaloHitList.push_back(static_cast<const CaloHit *>(pInputCaloHit->GetParentAddress()));
767 
768  if (!newCaloHitList.empty())
769  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
770  }
771 
772  for (const Cluster *const pInputCluster : inputClusterList3D)
773  {
774  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
775  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
776 
777  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
778  {
779  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit *>(pInputCaloHit->GetParentAddress()));
780  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit *>(pWorkerParentCaloHit->GetParentAddress()));
781  newCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
782  }
783 
784  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
785  {
786  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit *>(pInputCaloHit->GetParentAddress()));
787  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit *>(pWorkerParentCaloHit->GetParentAddress()));
788  newIsolatedCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
789  }
790 
791  if (!newCaloHitList.empty())
792  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
793  }
794 
795  VertexList newVertexList;
796 
797  for (const Vertex *const pInputVertex : pInputPfo->GetVertexList())
798  newVertexList.push_back(this->CreateVertex(pInputVertex));
799 
800  const ParticleFlowObject *const pNewPfo(this->CreatePfo(pInputPfo, newClusterList, newVertexList));
801  newPfoList.push_back(pNewPfo);
802 
803  if (pNewParentPfo)
804  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNewParentPfo, pNewPfo))
805 
806  for (const ParticleFlowObject *const pInputDaughterPfo : pInputPfo->GetDaughterPfoList())
807  this->Recreate(pInputDaughterPfo, pNewPfo, newPfoList);
808 
809  return STATUS_CODE_SUCCESS;
810 }
811 
812 //------------------------------------------------------------------------------------------------------------------------------------------
813 
814 const CaloHit *MasterAlgorithm::CreateCaloHit(const CaloHit *const pInputCaloHit, const CaloHit *const pParentCaloHit) const
815 {
817  parameters.m_positionVector = pInputCaloHit->GetPositionVector();
818  parameters.m_expectedDirection = pInputCaloHit->GetExpectedDirection();
819  parameters.m_cellNormalVector = pInputCaloHit->GetCellNormalVector();
820  parameters.m_cellGeometry = pInputCaloHit->GetCellGeometry();
821  parameters.m_cellSize0 = pInputCaloHit->GetCellSize0();
822  parameters.m_cellSize1 = pInputCaloHit->GetCellSize1();
823  parameters.m_cellThickness = pInputCaloHit->GetCellThickness();
824  parameters.m_nCellRadiationLengths = pInputCaloHit->GetNCellRadiationLengths();
825  parameters.m_nCellInteractionLengths = pInputCaloHit->GetNCellInteractionLengths();
826  parameters.m_time = pInputCaloHit->GetTime();
827  parameters.m_inputEnergy = pInputCaloHit->GetInputEnergy();
828  parameters.m_mipEquivalentEnergy = pInputCaloHit->GetMipEquivalentEnergy();
829  parameters.m_electromagneticEnergy = pInputCaloHit->GetElectromagneticEnergy();
830  parameters.m_hadronicEnergy = pInputCaloHit->GetHadronicEnergy();
831  parameters.m_isDigital = pInputCaloHit->IsDigital();
832  parameters.m_hitType = pInputCaloHit->GetHitType();
833  parameters.m_hitRegion = pInputCaloHit->GetHitRegion();
834  parameters.m_layer = pInputCaloHit->GetLayer();
835  parameters.m_isInOuterSamplingLayer = pInputCaloHit->IsInOuterSamplingLayer();
836  parameters.m_pParentAddress = static_cast<const void *>(pParentCaloHit);
837 
838  const CaloHit *pNewCaloHit(nullptr);
839  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::Create(*this, parameters, pNewCaloHit));
840 
841  PandoraContentApi::CaloHit::Metadata metadata;
842  metadata.m_isIsolated = pInputCaloHit->IsIsolated();
843  metadata.m_isPossibleMip = pInputCaloHit->IsPossibleMip();
844  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pNewCaloHit, metadata));
845 
846  return pNewCaloHit;
847 }
848 
849 //------------------------------------------------------------------------------------------------------------------------------------------
850 
852  const Cluster *const pInputCluster, const CaloHitList &newCaloHitList, const CaloHitList &newIsolatedCaloHitList) const
853 {
855  parameters.m_caloHitList = newCaloHitList;
856  parameters.m_isolatedCaloHitList = newIsolatedCaloHitList;
857 
858  const Cluster *pNewCluster(nullptr);
859  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pNewCluster));
860 
861  PandoraContentApi::Cluster::Metadata metadata;
862  metadata.m_particleId = pInputCluster->GetParticleId();
863  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::AlterMetadata(*this, pNewCluster, metadata));
864 
865  return pNewCluster;
866 }
867 
868 //------------------------------------------------------------------------------------------------------------------------------------------
869 
870 const Vertex *MasterAlgorithm::CreateVertex(const Vertex *const pInputVertex) const
871 {
873  parameters.m_position = pInputVertex->GetPosition();
874  parameters.m_vertexLabel = pInputVertex->GetVertexLabel();
875  parameters.m_vertexType = pInputVertex->GetVertexType();
876 
877  const Vertex *pNewVertex(nullptr);
878  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pNewVertex));
879 
880  return pNewVertex;
881 }
882 
883 //------------------------------------------------------------------------------------------------------------------------------------------
884 
885 const ParticleFlowObject *MasterAlgorithm::CreatePfo(
886  const ParticleFlowObject *const pInputPfo, const ClusterList &newClusterList, const VertexList &newVertexList) const
887 {
889  parameters.m_particleId = pInputPfo->GetParticleId();
890  parameters.m_charge = pInputPfo->GetCharge();
891  parameters.m_mass = pInputPfo->GetMass();
892  parameters.m_energy = pInputPfo->GetEnergy();
893  parameters.m_momentum = pInputPfo->GetMomentum();
894  parameters.m_clusterList = newClusterList;
895  parameters.m_trackList.clear();
896  parameters.m_vertexList = newVertexList;
897  parameters.m_propertiesToAdd = pInputPfo->GetPropertiesMap();
898 
899  const ParticleFlowObject *pNewPfo(nullptr);
900  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, parameters, pNewPfo));
901 
902  return pNewPfo;
903 }
904 
905 //------------------------------------------------------------------------------------------------------------------------------------------
906 
908  const LArTPC &larTPC, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
909 {
910  // The Pandora instance
911  const Pandora *const pPandora(new Pandora(name));
912  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
913  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
914  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
915  PANDORA_THROW_RESULT_IF(
916  STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
917  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RegisterCustomContent(pPandora));
918  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
919 
920  // The LArTPC
922  larTPCParameters.m_larTPCVolumeId = larTPC.GetLArTPCVolumeId();
923  larTPCParameters.m_centerX = larTPC.GetCenterX();
924  larTPCParameters.m_centerY = larTPC.GetCenterY();
925  larTPCParameters.m_centerZ = larTPC.GetCenterZ();
926  larTPCParameters.m_widthX = larTPC.GetWidthX();
927  larTPCParameters.m_widthY = larTPC.GetWidthY();
928  larTPCParameters.m_widthZ = larTPC.GetWidthZ();
929  larTPCParameters.m_wirePitchU = larTPC.GetWirePitchU();
930  larTPCParameters.m_wirePitchV = larTPC.GetWirePitchV();
931  larTPCParameters.m_wirePitchW = larTPC.GetWirePitchW();
932  larTPCParameters.m_wireAngleU = larTPC.GetWireAngleU();
933  larTPCParameters.m_wireAngleV = larTPC.GetWireAngleV();
934  larTPCParameters.m_wireAngleW = larTPC.GetWireAngleW();
935  larTPCParameters.m_sigmaUVW = larTPC.GetSigmaUVW();
936  larTPCParameters.m_isDriftInPositiveX = larTPC.IsDriftInPositiveX();
937  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
938 
939  const float tpcMinX(larTPC.GetCenterX() - 0.5f * larTPC.GetWidthX()), tpcMaxX(larTPC.GetCenterX() + 0.5f * larTPC.GetWidthX());
940 
941  // The Gaps
942  for (const DetectorGap *const pGap : gapList)
943  {
944  const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pGap));
945 
946  if (pLineGap && (((pLineGap->GetLineEndX() >= tpcMinX) && (pLineGap->GetLineEndX() <= tpcMaxX)) ||
947  ((pLineGap->GetLineStartX() >= tpcMinX) && (pLineGap->GetLineStartX() <= tpcMaxX))))
948  {
950  const LineGapType lineGapType(pLineGap->GetLineGapType());
951  lineGapParameters.m_lineGapType = lineGapType;
952  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
953  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
954 
956  ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W)))
957  {
958  lineGapParameters.m_lineStartX = -std::numeric_limits<float>::max();
959  lineGapParameters.m_lineEndX = std::numeric_limits<float>::max();
960  }
961 
962  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
963  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
964  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
965  }
966  }
967 
968  // Configuration
969  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
970  return pPandora;
971 }
972 
973 //------------------------------------------------------------------------------------------------------------------------------------------
974 
976  const LArTPCMap &larTPCMap, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
977 {
978  if (larTPCMap.empty())
979  {
980  std::cout << "MasterAlgorithm::CreateWorkerInstance - no LArTPC details provided" << std::endl;
981  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
982  }
983 
984  // The Pandora instance
985  const Pandora *const pPandora(new Pandora(name));
986  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
987  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
988  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
989  PANDORA_THROW_RESULT_IF(
990  STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
991  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RegisterCustomContent(pPandora));
992  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
993 
994  // The Parent LArTPC
995  const LArTPC *const pFirstLArTPC(larTPCMap.begin()->second);
996  float parentMinX(pFirstLArTPC->GetCenterX() - 0.5f * pFirstLArTPC->GetWidthX());
997  float parentMaxX(pFirstLArTPC->GetCenterX() + 0.5f * pFirstLArTPC->GetWidthX());
998  float parentMinY(pFirstLArTPC->GetCenterY() - 0.5f * pFirstLArTPC->GetWidthY());
999  float parentMaxY(pFirstLArTPC->GetCenterY() + 0.5f * pFirstLArTPC->GetWidthY());
1000  float parentMinZ(pFirstLArTPC->GetCenterZ() - 0.5f * pFirstLArTPC->GetWidthZ());
1001  float parentMaxZ(pFirstLArTPC->GetCenterZ() + 0.5f * pFirstLArTPC->GetWidthZ());
1002 
1003  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
1004  {
1005  const LArTPC *const pLArTPC(mapEntry.second);
1006  parentMinX = std::min(parentMinX, pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX());
1007  parentMaxX = std::max(parentMaxX, pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX());
1008  parentMinY = std::min(parentMinY, pLArTPC->GetCenterY() - 0.5f * pLArTPC->GetWidthY());
1009  parentMaxY = std::max(parentMaxY, pLArTPC->GetCenterY() + 0.5f * pLArTPC->GetWidthY());
1010  parentMinZ = std::min(parentMinZ, pLArTPC->GetCenterZ() - 0.5f * pLArTPC->GetWidthZ());
1011  parentMaxZ = std::max(parentMaxZ, pLArTPC->GetCenterZ() + 0.5f * pLArTPC->GetWidthZ());
1012  }
1013 
1015  larTPCParameters.m_larTPCVolumeId = 0;
1016  larTPCParameters.m_centerX = 0.5f * (parentMaxX + parentMinX);
1017  larTPCParameters.m_centerY = 0.5f * (parentMaxY + parentMinY);
1018  larTPCParameters.m_centerZ = 0.5f * (parentMaxZ + parentMinZ);
1019  larTPCParameters.m_widthX = parentMaxX - parentMinX;
1020  larTPCParameters.m_widthY = parentMaxY - parentMinY;
1021  larTPCParameters.m_widthZ = parentMaxZ - parentMinZ;
1022  larTPCParameters.m_wirePitchU = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
1023  larTPCParameters.m_wirePitchV = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
1024  larTPCParameters.m_wirePitchW = pFirstLArTPC->GetWirePitchW();
1025  larTPCParameters.m_wireAngleU = pFirstLArTPC->GetWireAngleU();
1026  larTPCParameters.m_wireAngleV = pFirstLArTPC->GetWireAngleV();
1027  larTPCParameters.m_wireAngleW = pFirstLArTPC->GetWireAngleW();
1028  larTPCParameters.m_sigmaUVW = pFirstLArTPC->GetSigmaUVW();
1029  larTPCParameters.m_isDriftInPositiveX = pFirstLArTPC->IsDriftInPositiveX();
1030  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
1031 
1032  // The Gaps
1033  for (const DetectorGap *const pGap : gapList)
1034  {
1035  const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pGap));
1036 
1037  if (pLineGap)
1038  {
1040  lineGapParameters.m_lineGapType = pLineGap->GetLineGapType();
1041  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
1042  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
1043  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
1044  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
1045  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
1046  }
1047  }
1048 
1049  // Configuration
1050  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
1051  return pPandora;
1052 }
1053 
1054 //------------------------------------------------------------------------------------------------------------------------------------------
1055 
1056 StatusCode MasterAlgorithm::RegisterCustomContent(const Pandora *const /*pPandora*/) const
1057 {
1058  return STATUS_CODE_SUCCESS;
1059 }
1060 
1061 //------------------------------------------------------------------------------------------------------------------------------------------
1062 
1063 StatusCode MasterAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
1064 {
1065  ExternalSteeringParameters *pExternalParameters(nullptr);
1066 
1067  if (this->ExternalParametersPresent())
1068  {
1069  pExternalParameters = dynamic_cast<ExternalSteeringParameters *>(this->GetExternalParameters());
1070  if (!pExternalParameters)
1071  return STATUS_CODE_FAILURE;
1072  }
1073 
1074  {
1075  AlgorithmToolVector algorithmToolVector;
1076  PANDORA_RETURN_RESULT_IF(
1077  STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceSelectionTools", algorithmToolVector));
1078 
1079  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1080  {
1081  SliceSelectionBaseTool *const pSliceSelectionTool(dynamic_cast<SliceSelectionBaseTool *>(pAlgorithmTool));
1082  if (!pSliceSelectionTool)
1083  return STATUS_CODE_INVALID_PARAMETER;
1084  m_sliceSelectionToolVector.push_back(pSliceSelectionTool);
1085  }
1086  }
1087 
1088  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1089  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunAllHitsCosmicReco,
1090  xmlHandle, "ShouldRunAllHitsCosmicReco", m_shouldRunAllHitsCosmicReco));
1091 
1092  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1093  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunStitching,
1094  xmlHandle, "ShouldRunStitching", m_shouldRunStitching));
1095 
1097  {
1098  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunStitching requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1099  return STATUS_CODE_INVALID_PARAMETER;
1100  }
1101 
1103  {
1104  AlgorithmToolVector algorithmToolVector;
1105  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "StitchingTools", algorithmToolVector));
1106 
1107  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1108  {
1109  StitchingBaseTool *const pStitchingTool(dynamic_cast<StitchingBaseTool *>(pAlgorithmTool));
1110  if (!pStitchingTool)
1111  return STATUS_CODE_INVALID_PARAMETER;
1112  m_stitchingToolVector.push_back(pStitchingTool);
1113  }
1114  }
1115 
1116  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1117  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunCosmicHitRemoval,
1118  xmlHandle, "ShouldRunCosmicHitRemoval", m_shouldRunCosmicHitRemoval));
1119 
1121  {
1122  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunCosmicHitRemoval requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1123  return STATUS_CODE_INVALID_PARAMETER;
1124  }
1125 
1127  {
1128  AlgorithmToolVector algorithmToolVector;
1129  PANDORA_RETURN_RESULT_IF(
1130  STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "CosmicRayTaggingTools", algorithmToolVector));
1131 
1132  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1133  {
1134  CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool(dynamic_cast<CosmicRayTaggingBaseTool *>(pAlgorithmTool));
1135  if (!pCosmicRayTaggingTool)
1136  return STATUS_CODE_INVALID_PARAMETER;
1137  m_cosmicRayTaggingToolVector.push_back(pCosmicRayTaggingTool);
1138  }
1139  }
1140 
1141  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1142  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunSlicing,
1143  xmlHandle, "ShouldRunSlicing", m_shouldRunSlicing));
1144 
1145  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1146  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunNeutrinoRecoOption,
1147  xmlHandle, "ShouldRunNeutrinoRecoOption", m_shouldRunNeutrinoRecoOption));
1148 
1149  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1150  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunCosmicRecoOption,
1151  xmlHandle, "ShouldRunCosmicRecoOption", m_shouldRunCosmicRecoOption));
1152 
1153  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1154  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldPerformSliceId,
1155  xmlHandle, "ShouldPerformSliceId", m_shouldPerformSliceId));
1156 
1158  {
1159  std::cout << "MasterAlgorithm::ReadSettings - ShouldPerformSliceId requires ShouldRunSlicing and both neutrino and cosmic reconstruction options"
1160  << std::endl;
1161  return STATUS_CODE_INVALID_PARAMETER;
1162  }
1163 
1165  {
1166  AlgorithmToolVector algorithmToolVector;
1167  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceIdTools", algorithmToolVector));
1168 
1169  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1170  {
1171  SliceIdBaseTool *const pSliceIdIdTool(dynamic_cast<SliceIdBaseTool *>(pAlgorithmTool));
1172  if (!pSliceIdIdTool)
1173  return STATUS_CODE_INVALID_PARAMETER;
1174  m_sliceIdToolVector.push_back(pSliceIdIdTool);
1175  }
1176  }
1177 
1178  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1179  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_printOverallRecoStatus,
1180  xmlHandle, "PrintOverallRecoStatus", m_printOverallRecoStatus));
1181 
1182  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1183  XmlHelper::ReadValue(xmlHandle, "VisualizeOverallRecoStatus", m_visualizeOverallRecoStatus));
1184 
1185  PANDORA_RETURN_RESULT_IF_AND_IF(
1186  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LArCaloHitVersion", m_larCaloHitVersion));
1187 
1188  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1189  XmlHelper::ReadValue(xmlHandle, "ShouldRemoveOutOfTimeHits", m_shouldRemoveOutOfTimeHits));
1190 
1191  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1192  XmlHelper::ReadValue(xmlHandle, "FullWidthCRWorkerWireGaps", m_fullWidthCRWorkerWireGaps));
1193 
1194  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1195  XmlHelper::ReadValue(xmlHandle, "PassMCParticlesToWorkerInstances", m_passMCParticlesToWorkerInstances));
1196 
1197  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1198  XmlHelper::ReadValue(xmlHandle, "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
1199 
1200  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CRSettingsFile", m_crSettingsFile));
1201  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NuSettingsFile", m_nuSettingsFile));
1202  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "SlicingSettingsFile", m_slicingSettingsFile));
1206 
1208  {
1209  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputMCParticleListName", m_inputMCParticleListName));
1210  }
1211 
1212  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputHitListName", m_inputHitListName));
1213  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedPfoListName", m_recreatedPfoListName));
1214  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedClusterListName", m_recreatedClusterListName));
1215  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedVertexListName", m_recreatedVertexListName));
1216  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InTimeMaxX0", m_inTimeMaxX0));
1217 
1218  return STATUS_CODE_SUCCESS;
1219 }
1220 
1221 //------------------------------------------------------------------------------------------------------------------------------------------
1222 
1223 StatusCode MasterAlgorithm::ReadExternalSettings(const ExternalSteeringParameters *const pExternalParameters, const InputBool inputBool,
1224  const TiXmlHandle xmlHandle, const std::string &xmlTag, bool &outputBool)
1225 {
1226  if (pExternalParameters && inputBool.IsInitialized())
1227  {
1228  outputBool = inputBool.Get();
1229  }
1230  else
1231  {
1232  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, xmlTag, outputBool));
1233  }
1234 
1235  return STATUS_CODE_SUCCESS;
1236 }
1237 
1238 } // namespace lar_content
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoToFloatMap
static void AddDaughterPandoraInstance(const pandora::Pandora *const pPrimaryPandora, const pandora::Pandora *const pDaughterPandora)
Add a pandora daughter instance, associated to a primary pandora instance.
std::string m_inputMCParticleListName
The input mc particle list name.
pandora::InputBool m_shouldRunCosmicHitRemoval
Whether to remove hits from tagged cosmic-rays.
const pandora::ParticleFlowObject * CreatePfo(const pandora::ParticleFlowObject *const pInputPfo, const pandora::ClusterList &newClusterList, const pandora::VertexList &newVertexList) const
Create a new pfo in the current pandora instance, based upon the provided input pfo.
std::vector< pandora::CaloHitList > SliceVector
LArCaloHitFactory m_larCaloHitFactory
Factory for creating LArCaloHits during hit copying.
CosmicRayTaggingToolVector m_cosmicRayTaggingToolVector
The cosmic-ray tagging tool vector.
Header file for the pfo helper class.
pandora::StatusCode Copy(const pandora::Pandora *const pPandora, const pandora::CaloHit *const pCaloHit) const
Copy a specified calo hit to the provided pandora instance.
pandora::InputBool m_shouldRunStitching
Whether to stitch cosmic-ray muons crossing between volumes.
CosmicRayTaggingBaseTool class.
pandora::StatusCode Recreate(const pandora::PfoList &inputPfoList, pandora::PfoList &newPfoList) const
Recreate a specified list of pfos in the current pandora instance.
pandora::StatusCode ReadExternalSettings(const ExternalSteeringParameters *const pExternalParameters, const pandora::InputBool inputBool, const pandora::TiXmlHandle xmlHandle, const std::string &xmlTag, bool &outputBool)
Read settings from external steering parameters block, if present, otherwise from xml as standard...
const pandora::Pandora * m_pSlicingWorkerInstance
The slicing worker instance.
Header file for the lar calo hit class.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
pandora::StatusCode CopyMCParticles() const
Copy mc particles in the named input list to all pandora worker instances.
const pandora::CaloHit * CreateCaloHit(const pandora::CaloHit *const pInputCaloHit, const pandora::CaloHit *const pParentCaloHit) const
Create a new calo hit in the current pandora instance, based upon the provided input calo hit...
bool m_shouldRunNeutrinoRecoOption
Whether to run neutrino reconstruction for each slice.
bool m_shouldRunAllHitsCosmicReco
Whether to run all hits cosmic-ray reconstruction.
bool m_shouldRemoveOutOfTimeHits
Whether to remove out of time hits.
unsigned int GetLArTPCVolumeId() const
Get the lar tpc volume id.
Definition: LArCaloHit.h:167
pandora::InputBool m_shouldRunSlicing
Whether to slice events into separate regions for processing.
bool m_shouldPerformSliceId
Whether to identify slices and select most appropriate pfos.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
LAr calo hit class.
Definition: LArCaloHit.h:39
std::string m_slicingSettingsFile
The slicing settings file.
pandora::StatusCode RunCosmicRayHitRemoval(const pandora::PfoList &ambiguousPfos) const
Run cosmic-ray hit removal, freeing hits in ambiguous pfos for further processing.
std::string m_recreatedVertexListName
The output recreated vertex list name.
std::vector< const pandora::Pandora * > PandoraInstanceList
const pandora::Vertex * CreateVertex(const pandora::Vertex *const pInputVertex) const
Create a new vertex in the current pandora instance, based upon the provided input vertex...
const pandora::Pandora * m_pSliceCRWorkerInstance
The per-slice cosmic-ray reconstruction worker instance.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
SliceSelectionToolVector m_sliceSelectionToolVector
The slice selection tool vector.
pandora::InputBool m_shouldRunAllHitsCosmicReco
Whether to run all hits cosmic-ray reconstruction.
const pandora::Cluster * CreateCluster(const pandora::Cluster *const pInputCluster, const pandora::CaloHitList &newCaloHitList, const pandora::CaloHitList &newIsolatedCaloHitList) const
Create a new cluster in the current pandora instance, based upon the provided input cluster...
bool m_printOverallRecoStatus
Whether to print current operation status messages.
Header file for the master algorithm class.
Header file for the lar monte carlo particle helper helper class.
const pandora::Pandora * CreateWorkerInstance(const pandora::LArTPC &larTPC, const pandora::DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
Create a pandora worker instance to handle a single LArTPC.
Header file for the cluster helper class.
pandora::StatusCode RunSliceReconstruction(SliceVector &sliceVector, SliceHypotheses &nuSliceHypotheses, SliceHypotheses &crSliceHypotheses) const
Process each slice under different reconstruction hypotheses.
std::map< unsigned int, LArTPCHitList > VolumeIdToHitListMap
const pandora::Pandora * m_pSliceNuWorkerInstance
The per-slice neutrino reconstruction worker instance.
static pandora::StatusCode RegisterBasicPlugins(const pandora::Pandora &pandora)
Register the basic lar content plugins with pandora.
Definition: LArContent.cc:466
std::vector< pandora::PfoList > SliceHypotheses
for($it=0;$it< $RaceTrack_number;$it++)
std::string m_nuSettingsFile
The neutrino reconstruction settings file.
pandora::InputBool m_shouldRunNeutrinoRecoOption
Whether to run neutrino reconstruction for each slice.
pandora::StatusCode InitializeWorkerInstances()
Initialize pandora worker instances.
static bool HasPfoBeenStitched(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo has been stitched.
bool m_workerInstancesInitialized
Whether all worker instances have been initialized.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
void ShiftPfoHierarchy(const pandora::ParticleFlowObject *const pParentPfo, const PfoToLArTPCMap &pfoToLArTPCMap, const float x0) const
Shift a Pfo hierarchy by a specified x0 value.
Header file for the rotational transformation plugin class.
StitchingToolVector m_stitchingToolVector
The stitching tool vector.
pandora::StatusCode Reset()
Reset all worker instances.
unsigned int m_larCaloHitVersion
The LArCaloHit version for LArCaloHitFactory.
pandora::InputBool m_printOverallRecoStatus
Whether to print current operation status messages.
std::string m_recreatedClusterListName
The output recreated cluster list name.
static std::string FindFileInPath(const std::string &unqualifiedFileName, const std::string &environmentVariable, const std::string &delimiter=":")
Find the fully-qualified file name by searching through a list of delimiter-separated paths in a name...
Header file for the file helper class.
bool m_visualizeOverallRecoStatus
Whether to display results of current operations.
pandora::StatusCode TagCosmicRayPfos(const PfoToFloatMap &stitchedPfosToX0Map, pandora::PfoList &clearCosmicRayPfos, pandora::PfoList &ambiguousPfos) const
Tag clear, unambiguous cosmic-ray pfos.
std::string m_crSettingsFile
The cosmic-ray reconstruction settings file.
static const pandora::Cluster * GetParentCluster(const pandora::ClusterList &clusterList, const pandora::HitType hitType)
Select the parent cluster (same hit type and most hits) using a provided cluster list and hit type...
void StitchPfos(const pandora::ParticleFlowObject *const pPfoToEnlarge, const pandora::ParticleFlowObject *const pPfoToDelete, PfoToLArTPCMap &pfoToLArTPCMap) const
Stitch together a pair of pfos.
Header file for the lar mc particle class.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
std::string m_recreatedPfoListName
The output recreated pfo list name.
bool m_fullWidthCRWorkerWireGaps
Whether wire-type line gaps in cosmic-ray worker instances should cover all drift time...
createEngine this
LArMCParticleFactory responsible for object creation.
pandora::StatusCode StitchCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
Stitch together cosmic-ray pfos crossing between adjacent lar tpcs.
std::unordered_map< const pandora::ParticleFlowObject *, const pandora::LArTPC * > PfoToLArTPCMap
static pandora::StatusCode RegisterAlgorithms(const pandora::Pandora &pandora)
Register all the lar content algorithms and tools with pandora.
Definition: LArContent.cc:450
std::string m_filePathEnvironmentVariable
The environment variable providing a list of paths to xml files.
SliceIdBaseTool class.
SliceSelectionBaseTool class.
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
StitchingBaseTool class.
Header file for the helper class for multiple drift volumes.
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
Definition: reco_sbnd.fcl:182
pandora::StatusCode GetVolumeIdToHitListMap(VolumeIdToHitListMap &volumeIdToHitListMap) const
Get the mapping from lar tpc volume id to lists of all hits, and truncated hits.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::StatusCode RecreateCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap) const
Recreate cosmic-ray pfos (created by worker instances) in the master instance.
MasterAlgorithm class.
bool m_shouldRunSlicing
Whether to slice events into separate regions for processing.
std::string to_string(WindowPattern const &pattern)
static void GetIsolatedCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of isolated calo hits of a particular hit type from a list of pfos.
Header file for the pfo mop up algorithm base class.
bool m_shouldRunCosmicRecoOption
Whether to run cosmic-ray reconstruction for each slice.
pandora::InputBool m_shouldPerformSliceId
Whether to identify slices and select most appropriate pfos.
static void GetAllDownstreamPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively, of all daughters associated with those pfos in an input lis...
virtual pandora::StatusCode RegisterCustomContent(const pandora::Pandora *const pPandora) const
Register custom content, such as algorithms or algorithm tools, with a specified pandora instance...
pandora::StatusCode Run()
Header file detailing content for use with particle flow reconstruction at liquid argon time projecti...
pandora::InputBool m_shouldRunCosmicRecoOption
Whether to run cosmic-ray reconstruction for each slice.
then echo fcl name
pandora::StatusCode SelectBestSliceHypotheses(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses) const
Examine slice hypotheses to identify the most appropriate to provide in final event output...
PandoraInstanceList m_crWorkerInstances
The list of cosmic-ray reconstruction worker instances.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
SliceIdToolVector m_sliceIdToolVector
The slice id tool vector.
bool m_shouldRunCosmicHitRemoval
Whether to remove hits from tagged cosmic-rays.
Header file for the lar pseudo layer plugin class.
static void GetAllConnectedPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively including all daughters and parents associated with those pf...
pandora::StatusCode RunSlicing(const VolumeIdToHitListMap &volumeIdToHitListMap, SliceVector &sliceVector) const
Run the event slicing procedures, dividing available hits up into distinct 3D regions.
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
bool m_shouldRunStitching
Whether to stitch cosmic-ray muons crossing between volumes.
std::array< float, 2 > VertexVector(const recob::Vertex &vert, const geo::PlaneID &plane, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
std::list< Vertex > VertexList
Definition: DCEL.h:182
LarPandoraPseudoLayerPlugin class.
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
BEGIN_PROLOG could also be cout
float m_inTimeMaxX0
Cut on X0 to determine whether particle is clear cosmic ray.
std::string m_inputHitListName
The input hit list name.
bool m_passMCParticlesToWorkerInstances
Whether to pass mc particle details (and links to calo hits) to worker instances. ...
pandora::StatusCode RunCosmicRayReconstruction(const VolumeIdToHitListMap &volumeIdToHitListMap) const
Run the cosmic-ray reconstruction worker instances.