LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
MasterAlgorithm.cc
Go to the documentation of this file.
1 
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 {
816  PandoraContentApi::CaloHit::Parameters parameters;
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 {
854  PandoraContentApi::Cluster::Parameters parameters;
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 {
872  PandoraContentApi::Vertex::Parameters parameters;
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 {
888  PandoraContentApi::ParticleFlowObject::Parameters parameters;
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
921  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
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 &&
947  (((pLineGap->GetLineEndX() >= tpcMinX) && (pLineGap->GetLineEndX() <= tpcMaxX)) ||
948  ((pLineGap->GetLineStartX() >= tpcMinX) && (pLineGap->GetLineStartX() <= tpcMaxX))))
949  {
950  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
951  const LineGapType lineGapType(pLineGap->GetLineGapType());
952  lineGapParameters.m_lineGapType = lineGapType;
953  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
954  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
955 
957  ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W)))
958  {
959  lineGapParameters.m_lineStartX = -std::numeric_limits<float>::max();
960  lineGapParameters.m_lineEndX = std::numeric_limits<float>::max();
961  }
962 
963  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
964  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
965  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
966  }
967  }
968 
969  // Configuration
970  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
971  return pPandora;
972 }
973 
974 //------------------------------------------------------------------------------------------------------------------------------------------
975 
977  const LArTPCMap &larTPCMap, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
978 {
979  if (larTPCMap.empty())
980  {
981  std::cout << "MasterAlgorithm::CreateWorkerInstance - no LArTPC details provided" << std::endl;
982  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
983  }
984 
985  // The Pandora instance
986  const Pandora *const pPandora(new Pandora(name));
987  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
988  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
989  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
990  PANDORA_THROW_RESULT_IF(
991  STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
992  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RegisterCustomContent(pPandora));
993  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
994 
995  // The Parent LArTPC
996  const LArTPC *const pFirstLArTPC(larTPCMap.begin()->second);
997  float parentMinX(pFirstLArTPC->GetCenterX() - 0.5f * pFirstLArTPC->GetWidthX());
998  float parentMaxX(pFirstLArTPC->GetCenterX() + 0.5f * pFirstLArTPC->GetWidthX());
999  float parentMinY(pFirstLArTPC->GetCenterY() - 0.5f * pFirstLArTPC->GetWidthY());
1000  float parentMaxY(pFirstLArTPC->GetCenterY() + 0.5f * pFirstLArTPC->GetWidthY());
1001  float parentMinZ(pFirstLArTPC->GetCenterZ() - 0.5f * pFirstLArTPC->GetWidthZ());
1002  float parentMaxZ(pFirstLArTPC->GetCenterZ() + 0.5f * pFirstLArTPC->GetWidthZ());
1003 
1004  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
1005  {
1006  const LArTPC *const pLArTPC(mapEntry.second);
1007  parentMinX = std::min(parentMinX, pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX());
1008  parentMaxX = std::max(parentMaxX, pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX());
1009  parentMinY = std::min(parentMinY, pLArTPC->GetCenterY() - 0.5f * pLArTPC->GetWidthY());
1010  parentMaxY = std::max(parentMaxY, pLArTPC->GetCenterY() + 0.5f * pLArTPC->GetWidthY());
1011  parentMinZ = std::min(parentMinZ, pLArTPC->GetCenterZ() - 0.5f * pLArTPC->GetWidthZ());
1012  parentMaxZ = std::max(parentMaxZ, pLArTPC->GetCenterZ() + 0.5f * pLArTPC->GetWidthZ());
1013  }
1014 
1015  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
1016  larTPCParameters.m_larTPCVolumeId = 0;
1017  larTPCParameters.m_centerX = 0.5f * (parentMaxX + parentMinX);
1018  larTPCParameters.m_centerY = 0.5f * (parentMaxY + parentMinY);
1019  larTPCParameters.m_centerZ = 0.5f * (parentMaxZ + parentMinZ);
1020  larTPCParameters.m_widthX = parentMaxX - parentMinX;
1021  larTPCParameters.m_widthY = parentMaxY - parentMinY;
1022  larTPCParameters.m_widthZ = parentMaxZ - parentMinZ;
1023  larTPCParameters.m_wirePitchU = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
1024  larTPCParameters.m_wirePitchV = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
1025  larTPCParameters.m_wirePitchW = pFirstLArTPC->GetWirePitchW();
1026  larTPCParameters.m_wireAngleU = pFirstLArTPC->GetWireAngleU();
1027  larTPCParameters.m_wireAngleV = pFirstLArTPC->GetWireAngleV();
1028  larTPCParameters.m_wireAngleW = pFirstLArTPC->GetWireAngleW();
1029  larTPCParameters.m_sigmaUVW = pFirstLArTPC->GetSigmaUVW();
1030  larTPCParameters.m_isDriftInPositiveX = pFirstLArTPC->IsDriftInPositiveX();
1031  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
1032 
1033  // The Gaps
1034  for (const DetectorGap *const pGap : gapList)
1035  {
1036  const LineGap *const pLineGap(dynamic_cast<const LineGap *>(pGap));
1037 
1038  if (pLineGap)
1039  {
1040  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
1041  lineGapParameters.m_lineGapType = pLineGap->GetLineGapType();
1042  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
1043  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
1044  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
1045  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
1046  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
1047  }
1048  }
1049 
1050  // Configuration
1051  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
1052  return pPandora;
1053 }
1054 
1055 //------------------------------------------------------------------------------------------------------------------------------------------
1056 
1057 StatusCode MasterAlgorithm::RegisterCustomContent(const Pandora *const /*pPandora*/) const
1058 {
1059  return STATUS_CODE_SUCCESS;
1060 }
1061 
1062 //------------------------------------------------------------------------------------------------------------------------------------------
1063 
1064 StatusCode MasterAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
1065 {
1066  ExternalSteeringParameters *pExternalParameters(nullptr);
1067 
1068  if (this->ExternalParametersPresent())
1069  {
1070  pExternalParameters = dynamic_cast<ExternalSteeringParameters *>(this->GetExternalParameters());
1071  if (!pExternalParameters)
1072  return STATUS_CODE_FAILURE;
1073  }
1074 
1075  {
1076  AlgorithmToolVector algorithmToolVector;
1077  PANDORA_RETURN_RESULT_IF(
1078  STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceSelectionTools", algorithmToolVector));
1079 
1080  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1081  {
1082  SliceSelectionBaseTool *const pSliceSelectionTool(dynamic_cast<SliceSelectionBaseTool *>(pAlgorithmTool));
1083  if (!pSliceSelectionTool)
1084  return STATUS_CODE_INVALID_PARAMETER;
1085  m_sliceSelectionToolVector.push_back(pSliceSelectionTool);
1086  }
1087  }
1088 
1089  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1090  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunAllHitsCosmicReco,
1091  xmlHandle, "ShouldRunAllHitsCosmicReco", m_shouldRunAllHitsCosmicReco));
1092 
1093  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1094  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunStitching,
1095  xmlHandle, "ShouldRunStitching", m_shouldRunStitching));
1096 
1098  {
1099  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunStitching requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1100  return STATUS_CODE_INVALID_PARAMETER;
1101  }
1102 
1104  {
1105  AlgorithmToolVector algorithmToolVector;
1106  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "StitchingTools", algorithmToolVector));
1107 
1108  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1109  {
1110  StitchingBaseTool *const pStitchingTool(dynamic_cast<StitchingBaseTool *>(pAlgorithmTool));
1111  if (!pStitchingTool)
1112  return STATUS_CODE_INVALID_PARAMETER;
1113  m_stitchingToolVector.push_back(pStitchingTool);
1114  }
1115  }
1116 
1117  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1118  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunCosmicHitRemoval,
1119  xmlHandle, "ShouldRunCosmicHitRemoval", m_shouldRunCosmicHitRemoval));
1120 
1122  {
1123  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunCosmicHitRemoval requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1124  return STATUS_CODE_INVALID_PARAMETER;
1125  }
1126 
1128  {
1129  AlgorithmToolVector algorithmToolVector;
1130  PANDORA_RETURN_RESULT_IF(
1131  STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "CosmicRayTaggingTools", algorithmToolVector));
1132 
1133  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1134  {
1135  CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool(dynamic_cast<CosmicRayTaggingBaseTool *>(pAlgorithmTool));
1136  if (!pCosmicRayTaggingTool)
1137  return STATUS_CODE_INVALID_PARAMETER;
1138  m_cosmicRayTaggingToolVector.push_back(pCosmicRayTaggingTool);
1139  }
1140  }
1141 
1142  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1143  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunSlicing,
1144  xmlHandle, "ShouldRunSlicing", m_shouldRunSlicing));
1145 
1146  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1147  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunNeutrinoRecoOption,
1148  xmlHandle, "ShouldRunNeutrinoRecoOption", m_shouldRunNeutrinoRecoOption));
1149 
1150  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1151  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldRunCosmicRecoOption,
1152  xmlHandle, "ShouldRunCosmicRecoOption", m_shouldRunCosmicRecoOption));
1153 
1154  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1155  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_shouldPerformSliceId,
1156  xmlHandle, "ShouldPerformSliceId", m_shouldPerformSliceId));
1157 
1159  {
1160  std::cout << "MasterAlgorithm::ReadSettings - ShouldPerformSliceId requires ShouldRunSlicing and both neutrino and cosmic reconstruction options"
1161  << std::endl;
1162  return STATUS_CODE_INVALID_PARAMETER;
1163  }
1164 
1166  {
1167  AlgorithmToolVector algorithmToolVector;
1168  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceIdTools", algorithmToolVector));
1169 
1170  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1171  {
1172  SliceIdBaseTool *const pSliceIdIdTool(dynamic_cast<SliceIdBaseTool *>(pAlgorithmTool));
1173  if (!pSliceIdIdTool)
1174  return STATUS_CODE_INVALID_PARAMETER;
1175  m_sliceIdToolVector.push_back(pSliceIdIdTool);
1176  }
1177  }
1178 
1179  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
1180  this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() : pExternalParameters->m_printOverallRecoStatus,
1181  xmlHandle, "PrintOverallRecoStatus", m_printOverallRecoStatus));
1182 
1183  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1184  XmlHelper::ReadValue(xmlHandle, "VisualizeOverallRecoStatus", m_visualizeOverallRecoStatus));
1185 
1186  PANDORA_RETURN_RESULT_IF_AND_IF(
1187  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LArCaloHitVersion", m_larCaloHitVersion));
1188 
1189  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1190  XmlHelper::ReadValue(xmlHandle, "ShouldRemoveOutOfTimeHits", m_shouldRemoveOutOfTimeHits));
1191 
1192  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1193  XmlHelper::ReadValue(xmlHandle, "FullWidthCRWorkerWireGaps", m_fullWidthCRWorkerWireGaps));
1194 
1195  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1196  XmlHelper::ReadValue(xmlHandle, "PassMCParticlesToWorkerInstances", m_passMCParticlesToWorkerInstances));
1197 
1198  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1199  XmlHelper::ReadValue(xmlHandle, "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
1200 
1201  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CRSettingsFile", m_crSettingsFile));
1202  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NuSettingsFile", m_nuSettingsFile));
1203  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "SlicingSettingsFile", m_slicingSettingsFile));
1207 
1209  {
1210  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputMCParticleListName", m_inputMCParticleListName));
1211  }
1212 
1213  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputHitListName", m_inputHitListName));
1214  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedPfoListName", m_recreatedPfoListName));
1215  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedClusterListName", m_recreatedClusterListName));
1216  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedVertexListName", m_recreatedVertexListName));
1217  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InTimeMaxX0", m_inTimeMaxX0));
1218 
1219  return STATUS_CODE_SUCCESS;
1220 }
1221 
1222 //------------------------------------------------------------------------------------------------------------------------------------------
1223 
1224 StatusCode MasterAlgorithm::ReadExternalSettings(const ExternalSteeringParameters *const pExternalParameters, const InputBool inputBool,
1225  const TiXmlHandle xmlHandle, const std::string &xmlTag, bool &outputBool)
1226 {
1227  if (pExternalParameters && inputBool.IsInitialized())
1228  {
1229  outputBool = inputBool.Get();
1230  }
1231  else
1232  {
1233  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, xmlTag, outputBool));
1234  }
1235 
1236  return STATUS_CODE_SUCCESS;
1237 }
1238 
1239 } // namespace lar_content
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.
LArCaloHitFactory m_larCaloHitFactory
Factory for creating LArCaloHits during hit copying.
std::vector< pandora::PfoList > SliceHypotheses
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.
void ProcessEvent(G4int iProp, size_t nEv)
Definition: errprop.cc:171
intermediate_table::const_iterator const_iterator
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.
void FillParameters(LArMCParticleParameters &parameters) const
Fill the parameters associated with this MC particle.
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
TFile f
Definition: plotHisto.C:6
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.
LAr calo hit parameters.
Definition: LArCaloHit.h:27
LAr mc particle class.
Definition: LArMCParticle.h:94
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.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
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
ntupleExperimental Reset()
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoToFloatMap
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:484
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...
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:468
std::string m_filePathEnvironmentVariable
The environment variable providing a list of paths to xml files.
SliceIdBaseTool class.
SliceSelectionBaseTool class.
LAr mc particle parameters.
Definition: LArMCParticle.h:82
StitchingBaseTool class.
Header file for the helper class for multiple drift volumes.
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.
HitType
Definition: HitType.h:12
bool m_shouldRunSlicing
Whether to slice events into separate regions for processing.
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...
std::vector< art::Ptr< recob::Vertex > > VertexVector
pandora::InputBool m_shouldRunCosmicRecoOption
Whether to run cosmic-ray reconstruction for each slice.
pandora::StatusCode SelectBestSliceHypotheses(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses) const
Examine slice hypotheses to identify the most appropriate to provide in final event output...
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
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.
std::vector< pandora::CaloHitList > SliceVector
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::list< Vertex > VertexList
Definition: DCEL.h:169
LarPandoraPseudoLayerPlugin class.
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.