LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
MasterAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Api/PandoraApi.h"
10 
11 #include "Pandora/AlgorithmHeaders.h"
12 
14 
16 
21 
24 
27 
29 
30 using namespace pandora;
31 
32 namespace lar_content
33 {
34 
35 MasterAlgorithm::MasterAlgorithm() :
36  m_workerInstancesInitialized(false),
37  m_shouldRunAllHitsCosmicReco(true),
38  m_shouldRunStitching(true),
39  m_shouldRunCosmicHitRemoval(true),
40  m_shouldRunSlicing(true),
41  m_shouldRunNeutrinoRecoOption(true),
42  m_shouldRunCosmicRecoOption(true),
43  m_shouldPerformSliceId(true),
44  m_printOverallRecoStatus(false),
45  m_visualizeOverallRecoStatus(false),
46  m_pSlicingWorkerInstance(nullptr),
47  m_pSliceNuWorkerInstance(nullptr),
48  m_pSliceCRWorkerInstance(nullptr),
49  m_fullWidthCRWorkerWireGaps(true),
50  m_passMCParticlesToWorkerInstances(false),
51  m_filePathEnvironmentVariable("FW_SEARCH_PATH"),
52  m_inTimeMaxX0(1.f)
53 {
54 }
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 
58 void MasterAlgorithm::ShiftPfoHierarchy(const ParticleFlowObject *const pParentPfo, const PfoToLArTPCMap &pfoToLArTPCMap, const float x0) const
59 {
60  if (!pParentPfo->GetParentPfoList().empty())
61  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
62 
63  PfoToLArTPCMap::const_iterator larTPCIter(pfoToLArTPCMap.find(pParentPfo));
64 
65  if (pfoToLArTPCMap.end() == larTPCIter)
66  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
67 
68  PfoList pfoList;
69  LArPfoHelper::GetAllDownstreamPfos(pParentPfo, pfoList);
70  const float signedX0(larTPCIter->second->IsDriftInPositiveX() ? -x0 : x0);
71 
73  {
74  std::cout << "ShiftPfoHierarchy: signedX0 " << signedX0 << std::endl;
75  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &pfoList, "BeforeShiftCRPfos", GREEN));
76  }
77 
78  for (const ParticleFlowObject *const pDaughterPfo : pfoList)
79  {
80  CaloHitList caloHitList;
81  for (const Cluster *const pCluster : pDaughterPfo->GetClusterList())
82  {
83  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
84  caloHitList.insert(caloHitList.end(), pCluster->GetIsolatedCaloHitList().begin(), pCluster->GetIsolatedCaloHitList().end());
85  }
86 
87  for (const CaloHit *const pCaloHit : caloHitList)
88  {
89  PandoraContentApi::CaloHit::Metadata metadata;
90  metadata.m_x0 = signedX0;
91  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pCaloHit, metadata));
92  }
93 
94  for (const Vertex *const pVertex : pDaughterPfo->GetVertexList())
95  {
96  PandoraContentApi::Vertex::Metadata metadata;
97  metadata.m_x0 = signedX0;
98  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::AlterMetadata(*this, pVertex, metadata));
99  }
100  }
101 
103  {
104  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &pfoList, "AfterShiftCRPfos", RED));
105  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
106  }
107 }
108 
109 //------------------------------------------------------------------------------------------------------------------------------------------
110 
111 void MasterAlgorithm::StitchPfos(const ParticleFlowObject *const pPfoToEnlarge, const ParticleFlowObject *const pPfoToDelete,
112  PfoToLArTPCMap &pfoToLArTPCMap) const
113 {
114  if (pPfoToEnlarge == pPfoToDelete)
115  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
116 
117  // ATTN Remove pfos from pfo to lar tpc map here, avoiding problems if stitching across multiple tpcs.
118  pfoToLArTPCMap.erase(pPfoToEnlarge);
119  pfoToLArTPCMap.erase(pPfoToDelete);
120 
121  const PfoList daughterPfos(pPfoToDelete->GetDaughterPfoList());
122  const ClusterVector daughterClusters(pPfoToDelete->GetClusterList().begin(), pPfoToDelete->GetClusterList().end());
123  const VertexVector daughterVertices(pPfoToDelete->GetVertexList().begin(), pPfoToDelete->GetVertexList().end());
124 
125  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfoToDelete, m_recreatedPfoListName));
126 
127  for (const ParticleFlowObject *const pDaughterPfo : daughterPfos)
128  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pPfoToEnlarge, pDaughterPfo));
129 
130  for (const Vertex *const pDaughterVertex : daughterVertices)
131  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pDaughterVertex, m_recreatedVertexListName));
132 
133  for (const Cluster *const pDaughterCluster : daughterClusters)
134  {
135  const HitType daughterHitType(LArClusterHelper::GetClusterHitType(pDaughterCluster));
136  const Cluster *pParentCluster(PfoMopUpBaseAlgorithm::GetParentCluster(pPfoToEnlarge->GetClusterList(), daughterHitType));
137 
138  if (pParentCluster)
139  {
140  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pDaughterCluster,
142  }
143  else
144  {
145  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*this, pPfoToEnlarge, pDaughterCluster));
146  }
147  }
148 }
149 
150 //------------------------------------------------------------------------------------------------------------------------------------------
151 
153 {
154  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Reset());
155 
157  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->InitializeWorkerInstances());
158 
160  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->CopyMCParticles());
161 
162  PfoToFloatMap stitchedPfosToX0Map;
163  VolumeIdToHitListMap volumeIdToHitListMap;
164  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetVolumeIdToHitListMap(volumeIdToHitListMap));
165 
167  {
168  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunCosmicRayReconstruction(volumeIdToHitListMap));
169 
170  PfoToLArTPCMap pfoToLArTPCMap;
171  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RecreateCosmicRayPfos(pfoToLArTPCMap));
172 
174  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->StitchCosmicRayPfos(pfoToLArTPCMap, stitchedPfosToX0Map));
175  }
176 
178  {
179  PfoList clearCosmicRayPfos, ambiguousPfos;
180  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->TagCosmicRayPfos(stitchedPfosToX0Map, clearCosmicRayPfos, ambiguousPfos));
181  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunCosmicRayHitRemoval(ambiguousPfos));
182  }
183 
184  SliceVector sliceVector;
185  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunSlicing(volumeIdToHitListMap, sliceVector));
186 
188  {
189  SliceHypotheses nuSliceHypotheses, crSliceHypotheses;
190  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RunSliceReconstruction(sliceVector, nuSliceHypotheses, crSliceHypotheses));
191  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->SelectBestSliceHypotheses(nuSliceHypotheses, crSliceHypotheses));
192  }
193 
194  return STATUS_CODE_SUCCESS;
195 }
196 
197 //------------------------------------------------------------------------------------------------------------------------------------------
198 
200 {
201  // ATTN Used to be in the regular Initialize callback, but detector gap list cannot be extracted in client app before the first event
203  return STATUS_CODE_ALREADY_INITIALIZED;
204 
205  try
206  {
207  const LArTPCMap &larTPCMap(this->GetPandora().GetGeometry()->GetLArTPCMap());
208  const DetectorGapList &gapList(this->GetPandora().GetGeometry()->GetDetectorGapList());
209 
210  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
211  {
212  const unsigned int volumeId(mapEntry.second->GetLArTPCVolumeId());
213  m_crWorkerInstances.push_back(this->CreateWorkerInstance(*(mapEntry.second), gapList, m_crSettingsFile, "CRWorkerInstance" + std::to_string(volumeId)));
214  }
215 
216  if (m_shouldRunSlicing)
217  m_pSlicingWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_slicingSettingsFile, "SlicingWorker");
218 
220  m_pSliceNuWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_nuSettingsFile, "SliceNuWorker");
221 
223  m_pSliceCRWorkerInstance = this->CreateWorkerInstance(larTPCMap, gapList, m_crSettingsFile, "SliceCRWorker");
224  }
225  catch (const StatusCodeException &statusCodeException)
226  {
227  std::cout << "MasterAlgorithm: Exception during initialization of worker instances " << statusCodeException.ToString() << std::endl;
228  return statusCodeException.GetStatusCode();
229  }
230 
232  return STATUS_CODE_SUCCESS;
233 }
234 
235 //------------------------------------------------------------------------------------------------------------------------------------------
236 
238 {
239  const MCParticleList *pMCParticleList(nullptr);
240  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputMCParticleListName, pMCParticleList));
241 
242  PandoraInstanceList pandoraWorkerInstances(m_crWorkerInstances);
243  if (m_pSlicingWorkerInstance) pandoraWorkerInstances.push_back(m_pSlicingWorkerInstance);
244  if (m_pSliceNuWorkerInstance) pandoraWorkerInstances.push_back(m_pSliceNuWorkerInstance);
245  if (m_pSliceCRWorkerInstance) pandoraWorkerInstances.push_back(m_pSliceCRWorkerInstance);
246 
247  LArMCParticleFactory mcParticleFactory;
248 
249  for (const Pandora *const pPandoraWorker : pandoraWorkerInstances)
250  {
251  for (const MCParticle *const pMCParticle : *pMCParticleList)
252  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(pPandoraWorker, pMCParticle, &mcParticleFactory));
253  }
254 
255  return STATUS_CODE_SUCCESS;
256 }
257 
258 //------------------------------------------------------------------------------------------------------------------------------------------
259 
260 StatusCode MasterAlgorithm::GetVolumeIdToHitListMap(VolumeIdToHitListMap &volumeIdToHitListMap) const
261 {
262  const LArTPCMap &larTPCMap(this->GetPandora().GetGeometry()->GetLArTPCMap());
263  const unsigned int nLArTPCs(larTPCMap.size());
264 
265  const CaloHitList *pCaloHitList(nullptr);
266  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputHitListName, pCaloHitList));
267 
268  for (const CaloHit *const pCaloHit : *pCaloHitList)
269  {
270  const LArCaloHit *const pLArCaloHit(dynamic_cast<const LArCaloHit*>(pCaloHit));
271 
272  if (!pLArCaloHit && (1 != nLArTPCs))
273  return STATUS_CODE_INVALID_PARAMETER;
274 
275  const unsigned int volumeId(pLArCaloHit ? pLArCaloHit->GetLArTPCVolumeId() : 0);
276  const LArTPC *const pLArTPC(larTPCMap.at(volumeId));
277 
278  LArTPCHitList &larTPCHitList(volumeIdToHitListMap[volumeId]);
279  larTPCHitList.m_allHitList.push_back(pCaloHit);
280 
281  if (((pCaloHit->GetPositionVector().GetX() >= (pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX())) &&
282  (pCaloHit->GetPositionVector().GetX() <= (pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX()))))
283  {
284  larTPCHitList.m_truncatedHitList.push_back(pCaloHit);
285  }
286  }
287 
288  return STATUS_CODE_SUCCESS;
289 }
290 
291 //------------------------------------------------------------------------------------------------------------------------------------------
292 
293 StatusCode MasterAlgorithm::RunCosmicRayReconstruction(const VolumeIdToHitListMap &volumeIdToHitListMap) const
294 {
295  unsigned int workerCounter(0);
296 
297  for (const Pandora *const pCRWorker : m_crWorkerInstances)
298  {
299  const LArTPC &larTPC(pCRWorker->GetGeometry()->GetLArTPC());
300  VolumeIdToHitListMap::const_iterator iter(volumeIdToHitListMap.find(larTPC.GetLArTPCVolumeId()));
301 
302  if (volumeIdToHitListMap.end() == iter)
303  continue;
304 
305  for (const CaloHit *const pCaloHit : iter->second.m_allHitList)
306  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(pCRWorker, pCaloHit));
307 
309  std::cout << "Running cosmic-ray reconstruction worker instance " << ++workerCounter << " of " << m_crWorkerInstances.size() << std::endl;
310 
311  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*pCRWorker));
312  }
313 
314  return STATUS_CODE_SUCCESS;
315 }
316 
317 //------------------------------------------------------------------------------------------------------------------------------------------
318 
320 {
321  for (const Pandora *const pCRWorker : m_crWorkerInstances)
322  {
323  const PfoList *pCRPfos(nullptr);
324  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*pCRWorker, pCRPfos));
325 
326  PfoList newPfoList;
327  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Recreate(*pCRPfos, newPfoList));
328 
329  const LArTPC &larTPC(pCRWorker->GetGeometry()->GetLArTPC());
330 
331  for (const Pfo *const pNewPfo : newPfoList)
332  pfoToLArTPCMap[pNewPfo] = &larTPC;
333  }
334 
335  return STATUS_CODE_SUCCESS;
336 }
337 
338 //------------------------------------------------------------------------------------------------------------------------------------------
339 
340 StatusCode MasterAlgorithm::StitchCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
341 {
342  const PfoList *pRecreatedCRPfos(nullptr);
343  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(this->GetPandora(), pRecreatedCRPfos));
344 
346  {
347  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pRecreatedCRPfos, "RecreatedCRPfos", GREEN));
348  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
349  }
350 
351  for (StitchingBaseTool *const pStitchingTool : m_stitchingToolVector)
352  pStitchingTool->Run(this, pRecreatedCRPfos, pfoToLArTPCMap, stitchedPfosToX0Map);
353 
355  {
356  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pRecreatedCRPfos, "AfterStitchingCRPfos", RED));
357  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
358  }
359 
360  return STATUS_CODE_SUCCESS;
361 }
362 
363 //------------------------------------------------------------------------------------------------------------------------------------------
364 
365 StatusCode MasterAlgorithm::TagCosmicRayPfos(const PfoToFloatMap &stitchedPfosToX0Map, PfoList &clearCosmicRayPfos, PfoList &ambiguousPfos) const
366 {
367  const PfoList *pRecreatedCRPfos(nullptr);
368  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(this->GetPandora(), pRecreatedCRPfos));
369 
370  PfoList nonStitchedParentCosmicRayPfos;
371  for (const Pfo *const pPfo : *pRecreatedCRPfos)
372  {
373  if (!pPfo->GetParentPfoList().empty())
374  continue;
375 
376  PfoToFloatMap::const_iterator pfoToX0Iter = stitchedPfosToX0Map.find(pPfo);
377  const float x0Shift((pfoToX0Iter != stitchedPfosToX0Map.end()) ? pfoToX0Iter->second : 0.f);
378  PfoList &targetList((std::fabs(x0Shift) > m_inTimeMaxX0) ? clearCosmicRayPfos : nonStitchedParentCosmicRayPfos);
379  targetList.push_back(pPfo);
380  }
381 
382  for (CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool : m_cosmicRayTaggingToolVector)
383  pCosmicRayTaggingTool->FindAmbiguousPfos(nonStitchedParentCosmicRayPfos, ambiguousPfos, this);
384 
385  for (const Pfo *const pPfo : nonStitchedParentCosmicRayPfos)
386  {
387  const bool isClearCosmic(ambiguousPfos.end() == std::find(ambiguousPfos.begin(), ambiguousPfos.end(), pPfo));
388 
389  if (isClearCosmic)
390  clearCosmicRayPfos.push_back(pPfo);
391 
392  PandoraContentApi::ParticleFlowObject::Metadata metadata;
393  metadata.m_propertiesToAdd["IsClearCosmic"] = (isClearCosmic ? 1.f : 0.f);
394  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
395  }
396 
398  {
399  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &clearCosmicRayPfos, "ClearCRPfos", RED));
400  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &ambiguousPfos, "AmbiguousCRPfos", BLUE));
401  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
402  }
403 
404  return STATUS_CODE_SUCCESS;
405 }
406 
407 //------------------------------------------------------------------------------------------------------------------------------------------
408 
409 StatusCode MasterAlgorithm::RunCosmicRayHitRemoval(const PfoList &ambiguousPfos) const
410 {
411  PfoList allPfosToDelete;
412  LArPfoHelper::GetAllConnectedPfos(ambiguousPfos, allPfosToDelete);
413 
414  for (const Pfo *const pPfoToDelete : allPfosToDelete)
415  {
416  const ClusterList clusterList(pPfoToDelete->GetClusterList());
417  const VertexList vertexList(pPfoToDelete->GetVertexList());
418  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfoToDelete));
419  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &clusterList));
420  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &vertexList));
421  }
422 
423  return STATUS_CODE_SUCCESS;
424 }
425 
426 //------------------------------------------------------------------------------------------------------------------------------------------
427 
428 StatusCode MasterAlgorithm::RunSlicing(const VolumeIdToHitListMap &volumeIdToHitListMap, SliceVector &sliceVector) const
429 {
430  for (const VolumeIdToHitListMap::value_type &mapEntry : volumeIdToHitListMap)
431  {
432  for (const CaloHit *const pCaloHit : mapEntry.second.m_truncatedHitList)
433  {
434  if (!PandoraContentApi::IsAvailable(*this, pCaloHit))
435  continue;
436 
437  const HitType hitType(pCaloHit->GetHitType());
438  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
439  continue;
440 
441  if (m_shouldRunSlicing)
442  {
443  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSlicingWorkerInstance, pCaloHit));
444  }
445  else
446  {
447  if (sliceVector.empty()) sliceVector.push_back(CaloHitList());
448  sliceVector.back().push_back(pCaloHit);
449  }
450  }
451  }
452 
453  if (m_shouldRunSlicing)
454  {
456  std::cout << "Running slicing worker instance" << std::endl;
457 
458  const PfoList *pSlicePfos(nullptr);
459  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSlicingWorkerInstance));
460  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSlicingWorkerInstance, pSlicePfos));
461 
463  {
464  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pSlicePfos, "OnePfoPerSlice", BLUE));
465  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
466  }
467 
468  for (const Pfo *const pSlicePfo : *pSlicePfos)
469  {
470  sliceVector.push_back(CaloHitList());
471  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_U, sliceVector.back());
472  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_V, sliceVector.back());
473  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_W, sliceVector.back());
474  }
475  }
476 
478  std::cout << "Identified " << sliceVector.size() << " slice(s)" << std::endl;
479 
480  return STATUS_CODE_SUCCESS;
481 }
482 
483 //------------------------------------------------------------------------------------------------------------------------------------------
484 
485 StatusCode MasterAlgorithm::RunSliceReconstruction(SliceVector &sliceVector, SliceHypotheses &nuSliceHypotheses, SliceHypotheses &crSliceHypotheses) const
486 {
487  unsigned int sliceCounter(0);
488 
489  for (const CaloHitList &sliceHits : sliceVector)
490  {
491  for (const CaloHit *const pSliceCaloHit : sliceHits)
492  {
493  // ATTN Must ensure we copy the hit actually owned by master instance; access differs with/without slicing enabled
494  const CaloHit *const pCaloHitInMaster(m_shouldRunSlicing ? static_cast<const CaloHit*>(pSliceCaloHit->GetParentAddress()) : pSliceCaloHit);
495 
497  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceNuWorkerInstance, pCaloHitInMaster));
498 
500  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceCRWorkerInstance, pCaloHitInMaster));
501  }
502 
503  ++sliceCounter;
504 
506  {
508  std::cout << "Running nu worker instance for slice " << sliceCounter << " of " << sliceVector.size() << std::endl;
509 
510  const PfoList *pSliceNuPfos(nullptr);
511  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceNuWorkerInstance));
512  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceNuWorkerInstance, pSliceNuPfos));
513  nuSliceHypotheses.push_back(*pSliceNuPfos);
514 
515  for (const ParticleFlowObject *const pPfo : *pSliceNuPfos)
516  {
517  PandoraContentApi::ParticleFlowObject::Metadata metadata;
518  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
519  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
520  }
521  }
522 
524  {
526  std::cout << "Running cr worker instance for slice " << sliceCounter << " of " << sliceVector.size() << std::endl;
527 
528  const PfoList *pSliceCRPfos(nullptr);
529  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceCRWorkerInstance));
530  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceCRWorkerInstance, pSliceCRPfos));
531  crSliceHypotheses.push_back(*pSliceCRPfos);
532 
533  for (const ParticleFlowObject *const pPfo : *pSliceCRPfos)
534  {
535  PandoraContentApi::ParticleFlowObject::Metadata metadata;
536  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
537  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
538  }
539  }
540  }
541 
542  if (m_shouldRunNeutrinoRecoOption && m_shouldRunCosmicRecoOption && (nuSliceHypotheses.size() != crSliceHypotheses.size()))
543  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
544 
545  return STATUS_CODE_SUCCESS;
546 }
547 
548 //------------------------------------------------------------------------------------------------------------------------------------------
549 
550 StatusCode MasterAlgorithm::SelectBestSliceHypotheses(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses) const
551 {
553  std::cout << "Select best slice hypotheses" << std::endl;
554 
555  PfoList selectedSlicePfos;
556 
558  {
559  for (SliceIdBaseTool *const pSliceIdTool : m_sliceIdToolVector)
560  pSliceIdTool->SelectOutputPfos(this, nuSliceHypotheses, crSliceHypotheses, selectedSlicePfos);
561  }
563  {
564  const SliceHypotheses &sliceHypotheses(m_shouldRunNeutrinoRecoOption ? nuSliceHypotheses : crSliceHypotheses);
565 
566  for (const PfoList &slice : sliceHypotheses)
567  selectedSlicePfos.insert(selectedSlicePfos.end(), slice.begin(), slice.end());
568  }
569 
570  PfoList newSlicePfoList;
571  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Recreate(selectedSlicePfos, newSlicePfoList));
572 
573  return STATUS_CODE_SUCCESS;
574 }
575 
576 //------------------------------------------------------------------------------------------------------------------------------------------
577 
579 {
580  for (const Pandora *const pCRWorker : m_crWorkerInstances)
581  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*pCRWorker));
582 
584  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSlicingWorkerInstance));
585 
587  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceNuWorkerInstance));
588 
590  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceCRWorkerInstance));
591 
592  return STATUS_CODE_SUCCESS;
593 }
594 
595 //------------------------------------------------------------------------------------------------------------------------------------------
596 
597 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const CaloHit *const pCaloHit) const
598 {
599  // TODO Protection to ensure that only calo hits owned by the master instance are copied?
600  // TODO Might ultimately want to create LArCaloHits in worker instances, rather than CaloHits, just as we create LArMCParticles, below
601  PandoraApi::CaloHit::Parameters parameters;
602  parameters.m_positionVector = pCaloHit->GetPositionVector();
603  parameters.m_expectedDirection = pCaloHit->GetExpectedDirection();
604  parameters.m_cellNormalVector = pCaloHit->GetCellNormalVector();
605  parameters.m_cellGeometry = pCaloHit->GetCellGeometry();
606  parameters.m_cellSize0 = pCaloHit->GetCellSize0();
607  parameters.m_cellSize1 = pCaloHit->GetCellSize1();
608  parameters.m_cellThickness = pCaloHit->GetCellThickness();
609  parameters.m_nCellRadiationLengths = pCaloHit->GetNCellRadiationLengths();
610  parameters.m_nCellInteractionLengths = pCaloHit->GetNCellInteractionLengths();
611  parameters.m_time = pCaloHit->GetTime();
612  parameters.m_inputEnergy = pCaloHit->GetInputEnergy();
613  parameters.m_mipEquivalentEnergy = pCaloHit->GetMipEquivalentEnergy();
614  parameters.m_electromagneticEnergy = pCaloHit->GetElectromagneticEnergy();
615  parameters.m_hadronicEnergy = pCaloHit->GetHadronicEnergy();
616  parameters.m_isDigital = pCaloHit->IsDigital();
617  parameters.m_hitType = pCaloHit->GetHitType();
618  parameters.m_hitRegion = pCaloHit->GetHitRegion();
619  parameters.m_layer = pCaloHit->GetLayer();
620  parameters.m_isInOuterSamplingLayer = pCaloHit->IsInOuterSamplingLayer();
621  // ATTN Parent of calo hit in worker is corresponding calo hit in master
622  parameters.m_pParentAddress = static_cast<const void*>(pCaloHit);
623  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*pPandora, parameters));
624 
626  {
627  MCParticleVector mcParticleVector;
628  for (const auto &weightMapEntry : pCaloHit->GetMCParticleWeightMap()) mcParticleVector.push_back(weightMapEntry.first);
629  std::sort(mcParticleVector.begin(), mcParticleVector.end(), LArMCParticleHelper::SortByMomentum);
630 
631  for (const MCParticle *const pMCParticle : mcParticleVector)
632  {
633  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*pPandora, pCaloHit,
634  pMCParticle, pCaloHit->GetMCParticleWeightMap().at(pMCParticle)));
635  }
636  }
637 
638  return STATUS_CODE_SUCCESS;
639 }
640 
641 //------------------------------------------------------------------------------------------------------------------------------------------
642 
643 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const MCParticle *const pMCParticle, const LArMCParticleFactory *const pMCParticleFactory) const
644 {
645  LArMCParticleParameters parameters;
646  const LArMCParticle *const pLArMCParticle = dynamic_cast<const LArMCParticle*>(pMCParticle);
647 
648  if (!pLArMCParticle)
649  {
650  std::cout << "MasterAlgorithm::Copy - Expect to pass only LArMCParticles to Pandora worker instances." << std::endl;
651  return STATUS_CODE_INVALID_PARAMETER;
652  }
653 
654  parameters.m_nuanceCode = pLArMCParticle->GetNuanceCode();
655  parameters.m_energy = pMCParticle->GetEnergy();
656  parameters.m_momentum = pMCParticle->GetMomentum();
657  parameters.m_vertex = pMCParticle->GetVertex();
658  parameters.m_endpoint = pMCParticle->GetEndpoint();
659  parameters.m_particleId = pMCParticle->GetParticleId();
660  parameters.m_mcParticleType = pMCParticle->GetMCParticleType();
661  // ATTN Parent of mc particle in worker is corresponding mc particle in master
662  parameters.m_pParentAddress = static_cast<const void*>(pMCParticle);
663  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*pPandora, parameters, *pMCParticleFactory));
664 
665  for (const MCParticle *const pDaughterMCParticle : pMCParticle->GetDaughterList())
666  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pMCParticle, pDaughterMCParticle));
667 
668  for (const MCParticle *const pParentMCParticle : pMCParticle->GetParentList())
669  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pParentMCParticle, pMCParticle));
670 
671  return STATUS_CODE_SUCCESS;
672 }
673 
674 //------------------------------------------------------------------------------------------------------------------------------------------
675 
676 StatusCode MasterAlgorithm::Recreate(const PfoList &inputPfoList, PfoList &newPfoList) const
677 {
678  if (inputPfoList.empty())
679  return STATUS_CODE_SUCCESS;
680 
681  // TODO if no pfo in input list is primary - raise exception
682 
683  std::string clusterListName;
684  const ClusterList *pClusterList(nullptr);
685  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pClusterList, clusterListName));
686 
687  std::string vertexListName;
688  const VertexList *pVertexList(nullptr);
689  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
690 
691  std::string pfoListName;
692  const PfoList *pPfoList(nullptr);
693  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
694 
695  for (const Pfo *const pPfo : inputPfoList)
696  {
697  if (pPfo->GetParentPfoList().empty())
698  this->Recreate(pPfo, nullptr, newPfoList);
699  }
700 
701  if (!pClusterList->empty())
702  {
703  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, m_recreatedClusterListName));
704  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_recreatedClusterListName));
705  }
706 
707  if (!pVertexList->empty())
708  {
709  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_recreatedVertexListName));
710  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_recreatedVertexListName));
711  }
712 
713  if (!pPfoList->empty())
714  {
715  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<ParticleFlowObject>(*this, m_recreatedPfoListName));
716  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<ParticleFlowObject>(*this, m_recreatedPfoListName));
717  }
718 
719  return STATUS_CODE_SUCCESS;
720 }
721 
722 //------------------------------------------------------------------------------------------------------------------------------------------
723 
724 StatusCode MasterAlgorithm::Recreate(const ParticleFlowObject *const pInputPfo, const ParticleFlowObject *const pNewParentPfo, PfoList &newPfoList) const
725 {
726  ClusterList inputClusterList2D, inputClusterList3D, newClusterList;
727  LArPfoHelper::GetTwoDClusterList(pInputPfo, inputClusterList2D);
728  LArPfoHelper::GetThreeDClusterList(pInputPfo, inputClusterList3D);
729 
730  for (const Cluster *const pInputCluster : inputClusterList2D)
731  {
732  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
733  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
734 
735  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
736  newCaloHitList.push_back(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
737 
738  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
739  newIsolatedCaloHitList.push_back(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
740 
741  if (!newCaloHitList.empty())
742  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
743  }
744 
745  for (const Cluster *const pInputCluster : inputClusterList3D)
746  {
747  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
748  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
749 
750  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
751  {
752  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
753  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit*>(pWorkerParentCaloHit->GetParentAddress()));
754  newCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
755  }
756 
757  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
758  {
759  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
760  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit*>(pWorkerParentCaloHit->GetParentAddress()));
761  newIsolatedCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
762  }
763 
764  if (!newCaloHitList.empty())
765  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
766  }
767 
768  VertexList newVertexList;
769 
770  for (const Vertex *const pInputVertex : pInputPfo->GetVertexList())
771  newVertexList.push_back(this->CreateVertex(pInputVertex));
772 
773  const ParticleFlowObject *const pNewPfo(this->CreatePfo(pInputPfo, newClusterList, newVertexList));
774  newPfoList.push_back(pNewPfo);
775 
776  if (pNewParentPfo)
777  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNewParentPfo, pNewPfo))
778 
779  for (const ParticleFlowObject *const pInputDaughterPfo : pInputPfo->GetDaughterPfoList())
780  this->Recreate(pInputDaughterPfo, pNewPfo, newPfoList);
781 
782  return STATUS_CODE_SUCCESS;
783 }
784 
785 //------------------------------------------------------------------------------------------------------------------------------------------
786 
787 const CaloHit *MasterAlgorithm::CreateCaloHit(const CaloHit *const pInputCaloHit, const CaloHit *const pParentCaloHit) const
788 {
789  PandoraContentApi::CaloHit::Parameters parameters;
790  parameters.m_positionVector = pInputCaloHit->GetPositionVector();
791  parameters.m_expectedDirection = pInputCaloHit->GetExpectedDirection();
792  parameters.m_cellNormalVector = pInputCaloHit->GetCellNormalVector();
793  parameters.m_cellGeometry = pInputCaloHit->GetCellGeometry();
794  parameters.m_cellSize0 = pInputCaloHit->GetCellSize0();
795  parameters.m_cellSize1 = pInputCaloHit->GetCellSize1();
796  parameters.m_cellThickness = pInputCaloHit->GetCellThickness();
797  parameters.m_nCellRadiationLengths = pInputCaloHit->GetNCellRadiationLengths();
798  parameters.m_nCellInteractionLengths = pInputCaloHit->GetNCellInteractionLengths();
799  parameters.m_time = pInputCaloHit->GetTime();
800  parameters.m_inputEnergy = pInputCaloHit->GetInputEnergy();
801  parameters.m_mipEquivalentEnergy = pInputCaloHit->GetMipEquivalentEnergy();
802  parameters.m_electromagneticEnergy = pInputCaloHit->GetElectromagneticEnergy();
803  parameters.m_hadronicEnergy = pInputCaloHit->GetHadronicEnergy();
804  parameters.m_isDigital = pInputCaloHit->IsDigital();
805  parameters.m_hitType = pInputCaloHit->GetHitType();
806  parameters.m_hitRegion = pInputCaloHit->GetHitRegion();
807  parameters.m_layer = pInputCaloHit->GetLayer();
808  parameters.m_isInOuterSamplingLayer = pInputCaloHit->IsInOuterSamplingLayer();
809  parameters.m_pParentAddress = static_cast<const void*>(pParentCaloHit);
810 
811  const CaloHit *pNewCaloHit(nullptr);
812  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::Create(*this, parameters, pNewCaloHit));
813 
814  PandoraContentApi::CaloHit::Metadata metadata;
815  metadata.m_isIsolated = pInputCaloHit->IsIsolated();
816  metadata.m_isPossibleMip = pInputCaloHit->IsPossibleMip();
817  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pNewCaloHit, metadata));
818 
819  return pNewCaloHit;
820 }
821 
822 //------------------------------------------------------------------------------------------------------------------------------------------
823 
824 const Cluster *MasterAlgorithm::CreateCluster(const Cluster *const pInputCluster, const CaloHitList &newCaloHitList,
825  const CaloHitList &newIsolatedCaloHitList) const
826 {
827  PandoraContentApi::Cluster::Parameters parameters;
828  parameters.m_caloHitList = newCaloHitList;
829  parameters.m_isolatedCaloHitList = newIsolatedCaloHitList;
830 
831  const Cluster *pNewCluster(nullptr);
832  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pNewCluster));
833 
834  PandoraContentApi::Cluster::Metadata metadata;
835  metadata.m_particleId = pInputCluster->GetParticleId();
836  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::AlterMetadata(*this, pNewCluster, metadata));
837 
838  return pNewCluster;
839 }
840 
841 //------------------------------------------------------------------------------------------------------------------------------------------
842 
843 const Vertex *MasterAlgorithm::CreateVertex(const Vertex *const pInputVertex) const
844 {
845  PandoraContentApi::Vertex::Parameters parameters;
846  parameters.m_position = pInputVertex->GetPosition();
847  parameters.m_vertexLabel = pInputVertex->GetVertexLabel();
848  parameters.m_vertexType = pInputVertex->GetVertexType();
849 
850  const Vertex *pNewVertex(nullptr);
851  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pNewVertex));
852 
853  return pNewVertex;
854 }
855 
856 //------------------------------------------------------------------------------------------------------------------------------------------
857 
858 const ParticleFlowObject *MasterAlgorithm::CreatePfo(const ParticleFlowObject *const pInputPfo, const ClusterList &newClusterList,
859  const VertexList &newVertexList) const
860 {
861  PandoraContentApi::ParticleFlowObject::Parameters parameters;
862  parameters.m_particleId = pInputPfo->GetParticleId();
863  parameters.m_charge = pInputPfo->GetCharge();
864  parameters.m_mass = pInputPfo->GetMass();
865  parameters.m_energy = pInputPfo->GetEnergy();
866  parameters.m_momentum = pInputPfo->GetMomentum();
867  parameters.m_clusterList = newClusterList;
868  parameters.m_trackList.clear();
869  parameters.m_vertexList = newVertexList;
870  parameters.m_propertiesToAdd = pInputPfo->GetPropertiesMap();
871 
872  const ParticleFlowObject *pNewPfo(nullptr);
873  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, parameters, pNewPfo));
874 
875  return pNewPfo;
876 }
877 
878 //------------------------------------------------------------------------------------------------------------------------------------------
879 
880 const Pandora *MasterAlgorithm::CreateWorkerInstance(const LArTPC &larTPC, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
881 {
882  // The Pandora instance
883  const Pandora *const pPandora(new Pandora(name));
884  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
885  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
886  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
887  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
888  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
889 
890  // The LArTPC
891  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
892  larTPCParameters.m_larTPCVolumeId = larTPC.GetLArTPCVolumeId();
893  larTPCParameters.m_centerX = larTPC.GetCenterX();
894  larTPCParameters.m_centerY = larTPC.GetCenterY();
895  larTPCParameters.m_centerZ = larTPC.GetCenterZ();
896  larTPCParameters.m_widthX = larTPC.GetWidthX();
897  larTPCParameters.m_widthY = larTPC.GetWidthY();
898  larTPCParameters.m_widthZ = larTPC.GetWidthZ();
899  larTPCParameters.m_wirePitchU = larTPC.GetWirePitchU();
900  larTPCParameters.m_wirePitchV = larTPC.GetWirePitchV();
901  larTPCParameters.m_wirePitchW = larTPC.GetWirePitchW();
902  larTPCParameters.m_wireAngleU = larTPC.GetWireAngleU();
903  larTPCParameters.m_wireAngleV = larTPC.GetWireAngleV();
904  larTPCParameters.m_wireAngleW = larTPC.GetWireAngleW();
905  larTPCParameters.m_sigmaUVW = larTPC.GetSigmaUVW();
906  larTPCParameters.m_isDriftInPositiveX = larTPC.IsDriftInPositiveX();
907  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
908 
909  const float tpcMinX(larTPC.GetCenterX() - 0.5f * larTPC.GetWidthX()), tpcMaxX(larTPC.GetCenterX() + 0.5f * larTPC.GetWidthX());
910 
911  // The Gaps
912  for (const DetectorGap *const pGap : gapList)
913  {
914  const LineGap *const pLineGap(dynamic_cast<const LineGap*>(pGap));
915 
916  if (pLineGap && (((pLineGap->GetLineEndX() >= tpcMinX) && (pLineGap->GetLineEndX() <= tpcMaxX)) ||
917  ((pLineGap->GetLineStartX() >= tpcMinX) && (pLineGap->GetLineStartX() <= tpcMaxX))) )
918  {
919  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
920  const LineGapType lineGapType(pLineGap->GetLineGapType());
921  lineGapParameters.m_lineGapType = lineGapType;
922  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
923  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
924 
925  if (m_fullWidthCRWorkerWireGaps && ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W)))
926  {
927  lineGapParameters.m_lineStartX = -std::numeric_limits<float>::max();
928  lineGapParameters.m_lineEndX = std::numeric_limits<float>::max();
929  }
930 
931  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
932  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
933  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
934  }
935  }
936 
937  // Configuration
938  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
939  return pPandora;
940 }
941 
942 //------------------------------------------------------------------------------------------------------------------------------------------
943 
944 const Pandora *MasterAlgorithm::CreateWorkerInstance(const LArTPCMap &larTPCMap, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
945 {
946  if (larTPCMap.empty())
947  {
948  std::cout << "MasterAlgorithm::CreateWorkerInstance - no LArTPC details provided" << std::endl;
949  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
950  }
951 
952  // The Pandora instance
953  const Pandora *const pPandora(new Pandora(name));
954  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
955  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
956  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
957  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
958  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
959 
960  // The Parent LArTPC
961  const LArTPC *const pFirstLArTPC(larTPCMap.begin()->second);
962  float parentMinX(pFirstLArTPC->GetCenterX() - 0.5f * pFirstLArTPC->GetWidthX());
963  float parentMaxX(pFirstLArTPC->GetCenterX() + 0.5f * pFirstLArTPC->GetWidthX());
964  float parentMinY(pFirstLArTPC->GetCenterY() - 0.5f * pFirstLArTPC->GetWidthY());
965  float parentMaxY(pFirstLArTPC->GetCenterY() + 0.5f * pFirstLArTPC->GetWidthY());
966  float parentMinZ(pFirstLArTPC->GetCenterZ() - 0.5f * pFirstLArTPC->GetWidthZ());
967  float parentMaxZ(pFirstLArTPC->GetCenterZ() + 0.5f * pFirstLArTPC->GetWidthZ());
968 
969  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
970  {
971  const LArTPC *const pLArTPC(mapEntry.second);
972  parentMinX = std::min(parentMinX, pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX());
973  parentMaxX = std::max(parentMaxX, pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX());
974  parentMinY = std::min(parentMinY, pLArTPC->GetCenterY() - 0.5f * pLArTPC->GetWidthY());
975  parentMaxY = std::max(parentMaxY, pLArTPC->GetCenterY() + 0.5f * pLArTPC->GetWidthY());
976  parentMinZ = std::min(parentMinZ, pLArTPC->GetCenterZ() - 0.5f * pLArTPC->GetWidthZ());
977  parentMaxZ = std::max(parentMaxZ, pLArTPC->GetCenterZ() + 0.5f * pLArTPC->GetWidthZ());
978  }
979 
980  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
981  larTPCParameters.m_larTPCVolumeId = 0;
982  larTPCParameters.m_centerX = 0.5f * (parentMaxX + parentMinX);
983  larTPCParameters.m_centerY = 0.5f * (parentMaxY + parentMinY);
984  larTPCParameters.m_centerZ = 0.5f * (parentMaxZ + parentMinZ);
985  larTPCParameters.m_widthX = parentMaxX - parentMinX;
986  larTPCParameters.m_widthY = parentMaxY - parentMinY;
987  larTPCParameters.m_widthZ = parentMaxZ - parentMinZ;
988  larTPCParameters.m_wirePitchU = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
989  larTPCParameters.m_wirePitchV = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
990  larTPCParameters.m_wirePitchW = pFirstLArTPC->GetWirePitchW();
991  larTPCParameters.m_wireAngleU = pFirstLArTPC->GetWireAngleU();
992  larTPCParameters.m_wireAngleV = pFirstLArTPC->GetWireAngleV();
993  larTPCParameters.m_wireAngleW = pFirstLArTPC->GetWireAngleW();
994  larTPCParameters.m_sigmaUVW = pFirstLArTPC->GetSigmaUVW();
995  larTPCParameters.m_isDriftInPositiveX = pFirstLArTPC->IsDriftInPositiveX();
996  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
997 
998  // The Gaps
999  for (const DetectorGap *const pGap : gapList)
1000  {
1001  const LineGap *const pLineGap(dynamic_cast<const LineGap*>(pGap));
1002 
1003  if (pLineGap)
1004  {
1005  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
1006  lineGapParameters.m_lineGapType = pLineGap->GetLineGapType();
1007  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
1008  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
1009  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
1010  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
1011  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
1012  }
1013  }
1014 
1015  // Configuration
1016  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
1017  return pPandora;
1018 }
1019 
1020 //------------------------------------------------------------------------------------------------------------------------------------------
1021 
1022 StatusCode MasterAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
1023 {
1024  ExternalSteeringParameters *pExternalParameters(nullptr);
1025 
1026  if (this->ExternalParametersPresent())
1027  {
1028  pExternalParameters = dynamic_cast<ExternalSteeringParameters*>(this->GetExternalParameters());
1029  if (!pExternalParameters) return STATUS_CODE_FAILURE;
1030  }
1031 
1032  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1033  pExternalParameters->m_shouldRunAllHitsCosmicReco, xmlHandle, "ShouldRunAllHitsCosmicReco", m_shouldRunAllHitsCosmicReco));
1034 
1035  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1036  pExternalParameters->m_shouldRunStitching, xmlHandle, "ShouldRunStitching", m_shouldRunStitching));
1037 
1039  {
1040  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunStitching requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1041  return STATUS_CODE_INVALID_PARAMETER;
1042  }
1043 
1045  {
1046  AlgorithmToolVector algorithmToolVector;
1047  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "StitchingTools", algorithmToolVector));
1048 
1049  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1050  {
1051  StitchingBaseTool *const pStitchingTool(dynamic_cast<StitchingBaseTool*>(pAlgorithmTool));
1052  if (!pStitchingTool) return STATUS_CODE_INVALID_PARAMETER;
1053  m_stitchingToolVector.push_back(pStitchingTool);
1054  }
1055  }
1056 
1057  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1058  pExternalParameters->m_shouldRunCosmicHitRemoval, xmlHandle, "ShouldRunCosmicHitRemoval", m_shouldRunCosmicHitRemoval));
1059 
1061  {
1062  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunCosmicHitRemoval requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1063  return STATUS_CODE_INVALID_PARAMETER;
1064  }
1065 
1067  {
1068  AlgorithmToolVector algorithmToolVector;
1069  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "CosmicRayTaggingTools", algorithmToolVector));
1070 
1071  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1072  {
1073  CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool(dynamic_cast<CosmicRayTaggingBaseTool*>(pAlgorithmTool));
1074  if (!pCosmicRayTaggingTool) return STATUS_CODE_INVALID_PARAMETER;
1075  m_cosmicRayTaggingToolVector.push_back(pCosmicRayTaggingTool);
1076  }
1077  }
1078 
1079  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1080  pExternalParameters->m_shouldRunSlicing, xmlHandle, "ShouldRunSlicing", m_shouldRunSlicing));
1081 
1082  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1083  pExternalParameters->m_shouldRunNeutrinoRecoOption, xmlHandle, "ShouldRunNeutrinoRecoOption", m_shouldRunNeutrinoRecoOption));
1084 
1085  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1086  pExternalParameters->m_shouldRunCosmicRecoOption, xmlHandle, "ShouldRunCosmicRecoOption", m_shouldRunCosmicRecoOption));
1087 
1088  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1089  pExternalParameters->m_shouldPerformSliceId, xmlHandle, "ShouldPerformSliceId", m_shouldPerformSliceId));
1090 
1092  {
1093  std::cout << "MasterAlgorithm::ReadSettings - ShouldPerformSliceId requires ShouldRunSlicing and both neutrino and cosmic reconstruction options" << std::endl;
1094  return STATUS_CODE_INVALID_PARAMETER;
1095  }
1096 
1098  {
1099  AlgorithmToolVector algorithmToolVector;
1100  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceIdTools", algorithmToolVector));
1101 
1102  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1103  {
1104  SliceIdBaseTool *const pSliceIdIdTool(dynamic_cast<SliceIdBaseTool*>(pAlgorithmTool));
1105  if (!pSliceIdIdTool) return STATUS_CODE_INVALID_PARAMETER;
1106  m_sliceIdToolVector.push_back(pSliceIdIdTool);
1107  }
1108  }
1109 
1110  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1111  pExternalParameters->m_printOverallRecoStatus, xmlHandle, "PrintOverallRecoStatus", m_printOverallRecoStatus));
1112 
1113  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1114  "VisualizeOverallRecoStatus", m_visualizeOverallRecoStatus));
1115 
1116  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1117  "FullWidthCRWorkerWireGaps", m_fullWidthCRWorkerWireGaps));
1118 
1119  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1120  "PassMCParticlesToWorkerInstances", m_passMCParticlesToWorkerInstances));
1121 
1122  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1123  "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
1124 
1125  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CRSettingsFile", m_crSettingsFile));
1126  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NuSettingsFile", m_nuSettingsFile));
1127  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "SlicingSettingsFile", m_slicingSettingsFile));
1131 
1133  {
1134  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputMCParticleListName", m_inputMCParticleListName));
1135  }
1136 
1137  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputHitListName", m_inputHitListName));
1138  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedPfoListName", m_recreatedPfoListName));
1139  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedClusterListName", m_recreatedClusterListName));
1140  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedVertexListName", m_recreatedVertexListName));
1141  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InTimeMaxX0", m_inTimeMaxX0));
1142 
1143  return STATUS_CODE_SUCCESS;
1144 }
1145 
1146 //------------------------------------------------------------------------------------------------------------------------------------------
1147 
1148 StatusCode MasterAlgorithm::ReadExternalSettings(const ExternalSteeringParameters *const pExternalParameters, const InputBool inputBool,
1149  const TiXmlHandle xmlHandle, const std::string &xmlTag, bool &outputBool)
1150 {
1151  if (pExternalParameters && inputBool.IsInitialized())
1152  {
1153  outputBool = inputBool.Get();
1154  }
1155  else
1156  {
1157  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, xmlTag, outputBool));
1158  }
1159 
1160  return STATUS_CODE_SUCCESS;
1161 }
1162 
1163 } // 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.
std::vector< pandora::CaloHitList > SliceVector
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.
Definition: LArPfoHelper.cc:97
int GetNuanceCode() const
Get the nuance code.
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:172
unsigned int GetLArTPCVolumeId() const
Get the lar tpc volume id.
Definition: LArCaloHit.h:110
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.
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoToFloatMap
LAr calo hit class.
Definition: LArCaloHit.h:38
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
std::string m_slicingSettingsFile
The slicing settings file.
std::unordered_map< const pandora::ParticleFlowObject *, const pandora::LArTPC * > PfoToLArTPCMap
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.
LAr mc particle class.
Definition: LArMCParticle.h:38
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...
Int_t max
Definition: plot.C:27
bool m_printOverallRecoStatus
Whether to print current operation status messages.
intermediate_table::const_iterator const_iterator
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
ntupleExperimental Reset()
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:388
std::vector< pandora::PfoList > SliceHypotheses
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.
bool m_workerInstancesInitialized
Whether all worker instances have been initialized.
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.
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.
Definition: LArMCParticle.h:64
pandora::StatusCode StitchCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
Stitch together cosmic-ray pfos crossing between adjacent lar tpcs.
static pandora::StatusCode RegisterAlgorithms(const pandora::Pandora &pandora)
Register all the lar content algorithms and tools with pandora.
Definition: LArContent.cc:372
std::string m_filePathEnvironmentVariable
The environment variable providing a list of paths to xml files.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
SliceIdBaseTool class.
LAr mc particle parameters.
Definition: LArMCParticle.h:27
StitchingBaseTool class.
pandora::StatusCode GetVolumeIdToHitListMap(VolumeIdToHitListMap &volumeIdToHitListMap) const
Get the mapping from lar tpc volume id to lists of all hits, and truncated hits.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Int_t min
Definition: plot.C:26
pandora::StatusCode RecreateCosmicRayPfos(PfoToLArTPCMap &pfoToLArTPCMap) const
Recreate cosmic-ray pfos (created by worker instances) in the master instance.
bool m_shouldRunSlicing
Whether to slice events into separate regions for processing.
pandora::InputInt m_nuanceCode
The nuance code.
Definition: LArMCParticle.h:30
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...
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.
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.
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::list< Vertex > VertexList
Definition: DCEL.h:178
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. ...
std::vector< art::Ptr< recob::Vertex > > VertexVector
pandora::StatusCode RunCosmicRayReconstruction(const VolumeIdToHitListMap &volumeIdToHitListMap) const
Run the cosmic-ray reconstruction worker instances.