LArSoft  v07_13_02
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 
393  for (const Pfo *const pPfo : *pRecreatedCRPfos)
394  {
395  const bool isClearCosmic(ambiguousPfos.end() == std::find(ambiguousPfos.begin(), ambiguousPfos.end(), pPfo));
396  PandoraContentApi::ParticleFlowObject::Metadata metadata;
397  metadata.m_propertiesToAdd["IsClearCosmic"] = (isClearCosmic ? 1.f : 0.f);
398  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
399  }
400 
402  {
403  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &clearCosmicRayPfos, "ClearCRPfos", RED));
404  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &ambiguousPfos, "AmbiguousCRPfos", BLUE));
405  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
406  }
407 
408  return STATUS_CODE_SUCCESS;
409 }
410 
411 //------------------------------------------------------------------------------------------------------------------------------------------
412 
413 StatusCode MasterAlgorithm::RunCosmicRayHitRemoval(const PfoList &ambiguousPfos) const
414 {
415  PfoList allPfosToDelete;
416  LArPfoHelper::GetAllConnectedPfos(ambiguousPfos, allPfosToDelete);
417 
418  for (const Pfo *const pPfoToDelete : allPfosToDelete)
419  {
420  const ClusterList clusterList(pPfoToDelete->GetClusterList());
421  const VertexList vertexList(pPfoToDelete->GetVertexList());
422  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, pPfoToDelete));
423  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &clusterList));
424  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete(*this, &vertexList));
425  }
426 
427  return STATUS_CODE_SUCCESS;
428 }
429 
430 //------------------------------------------------------------------------------------------------------------------------------------------
431 
432 StatusCode MasterAlgorithm::RunSlicing(const VolumeIdToHitListMap &volumeIdToHitListMap, SliceVector &sliceVector) const
433 {
434  for (const VolumeIdToHitListMap::value_type &mapEntry : volumeIdToHitListMap)
435  {
436  for (const CaloHit *const pCaloHit : mapEntry.second.m_truncatedHitList)
437  {
438  if (!PandoraContentApi::IsAvailable(*this, pCaloHit))
439  continue;
440 
441  const HitType hitType(pCaloHit->GetHitType());
442  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
443  continue;
444 
445  if (m_shouldRunSlicing)
446  {
447  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSlicingWorkerInstance, pCaloHit));
448  }
449  else
450  {
451  if (sliceVector.empty()) sliceVector.push_back(CaloHitList());
452  sliceVector.back().push_back(pCaloHit);
453  }
454  }
455  }
456 
457  if (m_shouldRunSlicing)
458  {
460  std::cout << "Running slicing worker instance" << std::endl;
461 
462  const PfoList *pSlicePfos(nullptr);
463  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSlicingWorkerInstance));
464  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSlicingWorkerInstance, pSlicePfos));
465 
467  {
468  PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), pSlicePfos, "OnePfoPerSlice", BLUE));
469  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
470  }
471 
472  for (const Pfo *const pSlicePfo : *pSlicePfos)
473  {
474  sliceVector.push_back(CaloHitList());
475  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_U, sliceVector.back());
476  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_V, sliceVector.back());
477  LArPfoHelper::GetCaloHits(pSlicePfo, TPC_VIEW_W, sliceVector.back());
478  }
479  }
480 
482  std::cout << "Identified " << sliceVector.size() << " slice(s)" << std::endl;
483 
484  return STATUS_CODE_SUCCESS;
485 }
486 
487 //------------------------------------------------------------------------------------------------------------------------------------------
488 
489 StatusCode MasterAlgorithm::RunSliceReconstruction(SliceVector &sliceVector, SliceHypotheses &nuSliceHypotheses, SliceHypotheses &crSliceHypotheses) const
490 {
491  unsigned int sliceCounter(0);
492 
493  for (const CaloHitList &sliceHits : sliceVector)
494  {
495  for (const CaloHit *const pSliceCaloHit : sliceHits)
496  {
497  // ATTN Must ensure we copy the hit actually owned by master instance; access differs with/without slicing enabled
498  const CaloHit *const pCaloHitInMaster(m_shouldRunSlicing ? static_cast<const CaloHit*>(pSliceCaloHit->GetParentAddress()) : pSliceCaloHit);
499 
501  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceNuWorkerInstance, pCaloHitInMaster));
502 
504  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Copy(m_pSliceCRWorkerInstance, pCaloHitInMaster));
505  }
506 
508  {
510  std::cout << "Running nu worker instance for slice " << (sliceCounter + 1) << " of " << sliceVector.size() << std::endl;
511 
512  const PfoList *pSliceNuPfos(nullptr);
513  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceNuWorkerInstance));
514  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceNuWorkerInstance, pSliceNuPfos));
515  nuSliceHypotheses.push_back(*pSliceNuPfos);
516 
517  for (const ParticleFlowObject *const pPfo : *pSliceNuPfos)
518  {
519  PandoraContentApi::ParticleFlowObject::Metadata metadata;
520  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
521  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
522  }
523  }
524 
526  {
528  std::cout << "Running cr worker instance for slice " << (sliceCounter + 1) << " of " << sliceVector.size() << std::endl;
529 
530  const PfoList *pSliceCRPfos(nullptr);
531  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pSliceCRWorkerInstance));
532  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pSliceCRWorkerInstance, pSliceCRPfos));
533  crSliceHypotheses.push_back(*pSliceCRPfos);
534 
535  for (const ParticleFlowObject *const pPfo : *pSliceCRPfos)
536  {
537  PandoraContentApi::ParticleFlowObject::Metadata metadata;
538  metadata.m_propertiesToAdd["SliceIndex"] = sliceCounter;
539  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
540  }
541  }
542 
543  ++sliceCounter;
544  }
545 
546  if (m_shouldRunNeutrinoRecoOption && m_shouldRunCosmicRecoOption && (nuSliceHypotheses.size() != crSliceHypotheses.size()))
547  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
548 
549  return STATUS_CODE_SUCCESS;
550 }
551 
552 //------------------------------------------------------------------------------------------------------------------------------------------
553 
554 StatusCode MasterAlgorithm::SelectBestSliceHypotheses(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses) const
555 {
557  std::cout << "Select best slice hypotheses" << std::endl;
558 
559  PfoList selectedSlicePfos;
560 
562  {
563  for (SliceIdBaseTool *const pSliceIdTool : m_sliceIdToolVector)
564  pSliceIdTool->SelectOutputPfos(this, nuSliceHypotheses, crSliceHypotheses, selectedSlicePfos);
565  }
567  {
568  const SliceHypotheses &sliceHypotheses(m_shouldRunNeutrinoRecoOption ? nuSliceHypotheses : crSliceHypotheses);
569 
570  for (const PfoList &slice : sliceHypotheses)
571  selectedSlicePfos.insert(selectedSlicePfos.end(), slice.begin(), slice.end());
572  }
573 
574  PfoList newSlicePfoList;
575  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->Recreate(selectedSlicePfos, newSlicePfoList));
576 
577  return STATUS_CODE_SUCCESS;
578 }
579 
580 //------------------------------------------------------------------------------------------------------------------------------------------
581 
583 {
584  for (const Pandora *const pCRWorker : m_crWorkerInstances)
585  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*pCRWorker));
586 
588  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSlicingWorkerInstance));
589 
591  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceNuWorkerInstance));
592 
594  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pSliceCRWorkerInstance));
595 
596  return STATUS_CODE_SUCCESS;
597 }
598 
599 //------------------------------------------------------------------------------------------------------------------------------------------
600 
601 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const CaloHit *const pCaloHit) const
602 {
603  // TODO Protection to ensure that only calo hits owned by the master instance are copied?
604  // TODO Might ultimately want to create LArCaloHits in worker instances, rather than CaloHits, just as we create LArMCParticles, below
605  PandoraApi::CaloHit::Parameters parameters;
606  parameters.m_positionVector = pCaloHit->GetPositionVector();
607  parameters.m_expectedDirection = pCaloHit->GetExpectedDirection();
608  parameters.m_cellNormalVector = pCaloHit->GetCellNormalVector();
609  parameters.m_cellGeometry = pCaloHit->GetCellGeometry();
610  parameters.m_cellSize0 = pCaloHit->GetCellSize0();
611  parameters.m_cellSize1 = pCaloHit->GetCellSize1();
612  parameters.m_cellThickness = pCaloHit->GetCellThickness();
613  parameters.m_nCellRadiationLengths = pCaloHit->GetNCellRadiationLengths();
614  parameters.m_nCellInteractionLengths = pCaloHit->GetNCellInteractionLengths();
615  parameters.m_time = pCaloHit->GetTime();
616  parameters.m_inputEnergy = pCaloHit->GetInputEnergy();
617  parameters.m_mipEquivalentEnergy = pCaloHit->GetMipEquivalentEnergy();
618  parameters.m_electromagneticEnergy = pCaloHit->GetElectromagneticEnergy();
619  parameters.m_hadronicEnergy = pCaloHit->GetHadronicEnergy();
620  parameters.m_isDigital = pCaloHit->IsDigital();
621  parameters.m_hitType = pCaloHit->GetHitType();
622  parameters.m_hitRegion = pCaloHit->GetHitRegion();
623  parameters.m_layer = pCaloHit->GetLayer();
624  parameters.m_isInOuterSamplingLayer = pCaloHit->IsInOuterSamplingLayer();
625  // ATTN Parent of calo hit in worker is corresponding calo hit in master
626  parameters.m_pParentAddress = static_cast<const void*>(pCaloHit);
627  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*pPandora, parameters));
628 
630  {
631  MCParticleVector mcParticleVector;
632  for (const auto &weightMapEntry : pCaloHit->GetMCParticleWeightMap()) mcParticleVector.push_back(weightMapEntry.first);
633  std::sort(mcParticleVector.begin(), mcParticleVector.end(), LArMCParticleHelper::SortByMomentum);
634 
635  for (const MCParticle *const pMCParticle : mcParticleVector)
636  {
637  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*pPandora, pCaloHit,
638  pMCParticle, pCaloHit->GetMCParticleWeightMap().at(pMCParticle)));
639  }
640  }
641 
642  return STATUS_CODE_SUCCESS;
643 }
644 
645 //------------------------------------------------------------------------------------------------------------------------------------------
646 
647 StatusCode MasterAlgorithm::Copy(const Pandora *const pPandora, const MCParticle *const pMCParticle, const LArMCParticleFactory *const pMCParticleFactory) const
648 {
649  LArMCParticleParameters parameters;
650  const LArMCParticle *const pLArMCParticle = dynamic_cast<const LArMCParticle*>(pMCParticle);
651 
652  if (!pLArMCParticle)
653  {
654  std::cout << "MasterAlgorithm::Copy - Expect to pass only LArMCParticles to Pandora worker instances." << std::endl;
655  return STATUS_CODE_INVALID_PARAMETER;
656  }
657 
658  parameters.m_nuanceCode = pLArMCParticle->GetNuanceCode();
659  parameters.m_energy = pMCParticle->GetEnergy();
660  parameters.m_momentum = pMCParticle->GetMomentum();
661  parameters.m_vertex = pMCParticle->GetVertex();
662  parameters.m_endpoint = pMCParticle->GetEndpoint();
663  parameters.m_particleId = pMCParticle->GetParticleId();
664  parameters.m_mcParticleType = pMCParticle->GetMCParticleType();
665  // ATTN Parent of mc particle in worker is corresponding mc particle in master
666  parameters.m_pParentAddress = static_cast<const void*>(pMCParticle);
667  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*pPandora, parameters, *pMCParticleFactory));
668 
669  for (const MCParticle *const pDaughterMCParticle : pMCParticle->GetDaughterList())
670  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pMCParticle, pDaughterMCParticle));
671 
672  for (const MCParticle *const pParentMCParticle : pMCParticle->GetParentList())
673  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*pPandora, pParentMCParticle, pMCParticle));
674 
675  return STATUS_CODE_SUCCESS;
676 }
677 
678 //------------------------------------------------------------------------------------------------------------------------------------------
679 
680 StatusCode MasterAlgorithm::Recreate(const PfoList &inputPfoList, PfoList &newPfoList) const
681 {
682  if (inputPfoList.empty())
683  return STATUS_CODE_SUCCESS;
684 
685  // TODO if no pfo in input list is primary - raise exception
686 
687  std::string clusterListName;
688  const ClusterList *pClusterList(nullptr);
689  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pClusterList, clusterListName));
690 
691  std::string vertexListName;
692  const VertexList *pVertexList(nullptr);
693  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
694 
695  std::string pfoListName;
696  const PfoList *pPfoList(nullptr);
697  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
698 
699  for (const Pfo *const pPfo : inputPfoList)
700  {
701  if (pPfo->GetParentPfoList().empty())
702  this->Recreate(pPfo, nullptr, newPfoList);
703  }
704 
705  if (!pClusterList->empty())
706  {
707  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, m_recreatedClusterListName));
708  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_recreatedClusterListName));
709  }
710 
711  if (!pVertexList->empty())
712  {
713  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_recreatedVertexListName));
714  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_recreatedVertexListName));
715  }
716 
717  if (!pPfoList->empty())
718  {
719  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<ParticleFlowObject>(*this, m_recreatedPfoListName));
720  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<ParticleFlowObject>(*this, m_recreatedPfoListName));
721  }
722 
723  return STATUS_CODE_SUCCESS;
724 }
725 
726 //------------------------------------------------------------------------------------------------------------------------------------------
727 
728 StatusCode MasterAlgorithm::Recreate(const ParticleFlowObject *const pInputPfo, const ParticleFlowObject *const pNewParentPfo, PfoList &newPfoList) const
729 {
730  ClusterList inputClusterList2D, inputClusterList3D, newClusterList;
731  LArPfoHelper::GetTwoDClusterList(pInputPfo, inputClusterList2D);
732  LArPfoHelper::GetThreeDClusterList(pInputPfo, inputClusterList3D);
733 
734  for (const Cluster *const pInputCluster : inputClusterList2D)
735  {
736  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
737  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
738 
739  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
740  newCaloHitList.push_back(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
741 
742  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
743  newIsolatedCaloHitList.push_back(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
744 
745  if (!newCaloHitList.empty())
746  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
747  }
748 
749  for (const Cluster *const pInputCluster : inputClusterList3D)
750  {
751  CaloHitList inputCaloHitList, newCaloHitList, newIsolatedCaloHitList;
752  pInputCluster->GetOrderedCaloHitList().FillCaloHitList(inputCaloHitList);
753 
754  for (const CaloHit *const pInputCaloHit : inputCaloHitList)
755  {
756  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
757  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit*>(pWorkerParentCaloHit->GetParentAddress()));
758  newCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
759  }
760 
761  for (const CaloHit *const pInputCaloHit : pInputCluster->GetIsolatedCaloHitList())
762  {
763  const CaloHit *const pWorkerParentCaloHit(static_cast<const CaloHit*>(pInputCaloHit->GetParentAddress()));
764  const CaloHit *const pMasterParentCaloHit(static_cast<const CaloHit*>(pWorkerParentCaloHit->GetParentAddress()));
765  newIsolatedCaloHitList.push_back(this->CreateCaloHit(pInputCaloHit, pMasterParentCaloHit));
766  }
767 
768  if (!newCaloHitList.empty())
769  newClusterList.push_back(this->CreateCluster(pInputCluster, newCaloHitList, newIsolatedCaloHitList));
770  }
771 
772  VertexList newVertexList;
773 
774  for (const Vertex *const pInputVertex : pInputPfo->GetVertexList())
775  newVertexList.push_back(this->CreateVertex(pInputVertex));
776 
777  const ParticleFlowObject *const pNewPfo(this->CreatePfo(pInputPfo, newClusterList, newVertexList));
778  newPfoList.push_back(pNewPfo);
779 
780  if (pNewParentPfo)
781  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNewParentPfo, pNewPfo))
782 
783  for (const ParticleFlowObject *const pInputDaughterPfo : pInputPfo->GetDaughterPfoList())
784  this->Recreate(pInputDaughterPfo, pNewPfo, newPfoList);
785 
786  return STATUS_CODE_SUCCESS;
787 }
788 
789 //------------------------------------------------------------------------------------------------------------------------------------------
790 
791 const CaloHit *MasterAlgorithm::CreateCaloHit(const CaloHit *const pInputCaloHit, const CaloHit *const pParentCaloHit) const
792 {
793  PandoraContentApi::CaloHit::Parameters parameters;
794  parameters.m_positionVector = pInputCaloHit->GetPositionVector();
795  parameters.m_expectedDirection = pInputCaloHit->GetExpectedDirection();
796  parameters.m_cellNormalVector = pInputCaloHit->GetCellNormalVector();
797  parameters.m_cellGeometry = pInputCaloHit->GetCellGeometry();
798  parameters.m_cellSize0 = pInputCaloHit->GetCellSize0();
799  parameters.m_cellSize1 = pInputCaloHit->GetCellSize1();
800  parameters.m_cellThickness = pInputCaloHit->GetCellThickness();
801  parameters.m_nCellRadiationLengths = pInputCaloHit->GetNCellRadiationLengths();
802  parameters.m_nCellInteractionLengths = pInputCaloHit->GetNCellInteractionLengths();
803  parameters.m_time = pInputCaloHit->GetTime();
804  parameters.m_inputEnergy = pInputCaloHit->GetInputEnergy();
805  parameters.m_mipEquivalentEnergy = pInputCaloHit->GetMipEquivalentEnergy();
806  parameters.m_electromagneticEnergy = pInputCaloHit->GetElectromagneticEnergy();
807  parameters.m_hadronicEnergy = pInputCaloHit->GetHadronicEnergy();
808  parameters.m_isDigital = pInputCaloHit->IsDigital();
809  parameters.m_hitType = pInputCaloHit->GetHitType();
810  parameters.m_hitRegion = pInputCaloHit->GetHitRegion();
811  parameters.m_layer = pInputCaloHit->GetLayer();
812  parameters.m_isInOuterSamplingLayer = pInputCaloHit->IsInOuterSamplingLayer();
813  parameters.m_pParentAddress = static_cast<const void*>(pParentCaloHit);
814 
815  const CaloHit *pNewCaloHit(nullptr);
816  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::Create(*this, parameters, pNewCaloHit));
817 
818  PandoraContentApi::CaloHit::Metadata metadata;
819  metadata.m_isIsolated = pInputCaloHit->IsIsolated();
820  metadata.m_isPossibleMip = pInputCaloHit->IsPossibleMip();
821  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::AlterMetadata(*this, pNewCaloHit, metadata));
822 
823  return pNewCaloHit;
824 }
825 
826 //------------------------------------------------------------------------------------------------------------------------------------------
827 
828 const Cluster *MasterAlgorithm::CreateCluster(const Cluster *const pInputCluster, const CaloHitList &newCaloHitList,
829  const CaloHitList &newIsolatedCaloHitList) const
830 {
831  PandoraContentApi::Cluster::Parameters parameters;
832  parameters.m_caloHitList = newCaloHitList;
833  parameters.m_isolatedCaloHitList = newIsolatedCaloHitList;
834 
835  const Cluster *pNewCluster(nullptr);
836  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, parameters, pNewCluster));
837 
838  PandoraContentApi::Cluster::Metadata metadata;
839  metadata.m_particleId = pInputCluster->GetParticleId();
840  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::AlterMetadata(*this, pNewCluster, metadata));
841 
842  return pNewCluster;
843 }
844 
845 //------------------------------------------------------------------------------------------------------------------------------------------
846 
847 const Vertex *MasterAlgorithm::CreateVertex(const Vertex *const pInputVertex) const
848 {
849  PandoraContentApi::Vertex::Parameters parameters;
850  parameters.m_position = pInputVertex->GetPosition();
851  parameters.m_vertexLabel = pInputVertex->GetVertexLabel();
852  parameters.m_vertexType = pInputVertex->GetVertexType();
853 
854  const Vertex *pNewVertex(nullptr);
855  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pNewVertex));
856 
857  return pNewVertex;
858 }
859 
860 //------------------------------------------------------------------------------------------------------------------------------------------
861 
862 const ParticleFlowObject *MasterAlgorithm::CreatePfo(const ParticleFlowObject *const pInputPfo, const ClusterList &newClusterList,
863  const VertexList &newVertexList) const
864 {
865  PandoraContentApi::ParticleFlowObject::Parameters parameters;
866  parameters.m_particleId = pInputPfo->GetParticleId();
867  parameters.m_charge = pInputPfo->GetCharge();
868  parameters.m_mass = pInputPfo->GetMass();
869  parameters.m_energy = pInputPfo->GetEnergy();
870  parameters.m_momentum = pInputPfo->GetMomentum();
871  parameters.m_clusterList = newClusterList;
872  parameters.m_trackList.clear();
873  parameters.m_vertexList = newVertexList;
874  parameters.m_propertiesToAdd = pInputPfo->GetPropertiesMap();
875 
876  const ParticleFlowObject *pNewPfo(nullptr);
877  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, parameters, pNewPfo));
878 
879  return pNewPfo;
880 }
881 
882 //------------------------------------------------------------------------------------------------------------------------------------------
883 
884 const Pandora *MasterAlgorithm::CreateWorkerInstance(const LArTPC &larTPC, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
885 {
886  // The Pandora instance
887  const Pandora *const pPandora(new Pandora(name));
888  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
889  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
890  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
891  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
892  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
893 
894  // The LArTPC
895  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
896  larTPCParameters.m_larTPCVolumeId = larTPC.GetLArTPCVolumeId();
897  larTPCParameters.m_centerX = larTPC.GetCenterX();
898  larTPCParameters.m_centerY = larTPC.GetCenterY();
899  larTPCParameters.m_centerZ = larTPC.GetCenterZ();
900  larTPCParameters.m_widthX = larTPC.GetWidthX();
901  larTPCParameters.m_widthY = larTPC.GetWidthY();
902  larTPCParameters.m_widthZ = larTPC.GetWidthZ();
903  larTPCParameters.m_wirePitchU = larTPC.GetWirePitchU();
904  larTPCParameters.m_wirePitchV = larTPC.GetWirePitchV();
905  larTPCParameters.m_wirePitchW = larTPC.GetWirePitchW();
906  larTPCParameters.m_wireAngleU = larTPC.GetWireAngleU();
907  larTPCParameters.m_wireAngleV = larTPC.GetWireAngleV();
908  larTPCParameters.m_wireAngleW = larTPC.GetWireAngleW();
909  larTPCParameters.m_sigmaUVW = larTPC.GetSigmaUVW();
910  larTPCParameters.m_isDriftInPositiveX = larTPC.IsDriftInPositiveX();
911  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
912 
913  const float tpcMinX(larTPC.GetCenterX() - 0.5f * larTPC.GetWidthX()), tpcMaxX(larTPC.GetCenterX() + 0.5f * larTPC.GetWidthX());
914 
915  // The Gaps
916  for (const DetectorGap *const pGap : gapList)
917  {
918  const LineGap *const pLineGap(dynamic_cast<const LineGap*>(pGap));
919 
920  if (pLineGap && (((pLineGap->GetLineEndX() >= tpcMinX) && (pLineGap->GetLineEndX() <= tpcMaxX)) ||
921  ((pLineGap->GetLineStartX() >= tpcMinX) && (pLineGap->GetLineStartX() <= tpcMaxX))) )
922  {
923  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
924  const LineGapType lineGapType(pLineGap->GetLineGapType());
925  lineGapParameters.m_lineGapType = lineGapType;
926  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
927  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
928 
929  if (m_fullWidthCRWorkerWireGaps && ((lineGapType == TPC_WIRE_GAP_VIEW_U) || (lineGapType == TPC_WIRE_GAP_VIEW_V) || (lineGapType == TPC_WIRE_GAP_VIEW_W)))
930  {
931  lineGapParameters.m_lineStartX = -std::numeric_limits<float>::max();
932  lineGapParameters.m_lineEndX = std::numeric_limits<float>::max();
933  }
934 
935  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
936  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
937  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
938  }
939  }
940 
941  // Configuration
942  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
943  return pPandora;
944 }
945 
946 //------------------------------------------------------------------------------------------------------------------------------------------
947 
948 const Pandora *MasterAlgorithm::CreateWorkerInstance(const LArTPCMap &larTPCMap, const DetectorGapList &gapList, const std::string &settingsFile, const std::string &name) const
949 {
950  if (larTPCMap.empty())
951  {
952  std::cout << "MasterAlgorithm::CreateWorkerInstance - no LArTPC details provided" << std::endl;
953  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
954  }
955 
956  // The Pandora instance
957  const Pandora *const pPandora(new Pandora(name));
958  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterAlgorithms(*pPandora));
959  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArContent::RegisterBasicPlugins(*pPandora));
960  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetPseudoLayerPlugin(*pPandora, new lar_content::LArPseudoLayerPlugin));
961  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::SetLArTransformationPlugin(*pPandora, new lar_content::LArRotationalTransformationPlugin));
962  MultiPandoraApi::AddDaughterPandoraInstance(&(this->GetPandora()), pPandora);
963 
964  // The Parent LArTPC
965  const LArTPC *const pFirstLArTPC(larTPCMap.begin()->second);
966  float parentMinX(pFirstLArTPC->GetCenterX() - 0.5f * pFirstLArTPC->GetWidthX());
967  float parentMaxX(pFirstLArTPC->GetCenterX() + 0.5f * pFirstLArTPC->GetWidthX());
968  float parentMinY(pFirstLArTPC->GetCenterY() - 0.5f * pFirstLArTPC->GetWidthY());
969  float parentMaxY(pFirstLArTPC->GetCenterY() + 0.5f * pFirstLArTPC->GetWidthY());
970  float parentMinZ(pFirstLArTPC->GetCenterZ() - 0.5f * pFirstLArTPC->GetWidthZ());
971  float parentMaxZ(pFirstLArTPC->GetCenterZ() + 0.5f * pFirstLArTPC->GetWidthZ());
972 
973  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
974  {
975  const LArTPC *const pLArTPC(mapEntry.second);
976  parentMinX = std::min(parentMinX, pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX());
977  parentMaxX = std::max(parentMaxX, pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX());
978  parentMinY = std::min(parentMinY, pLArTPC->GetCenterY() - 0.5f * pLArTPC->GetWidthY());
979  parentMaxY = std::max(parentMaxY, pLArTPC->GetCenterY() + 0.5f * pLArTPC->GetWidthY());
980  parentMinZ = std::min(parentMinZ, pLArTPC->GetCenterZ() - 0.5f * pLArTPC->GetWidthZ());
981  parentMaxZ = std::max(parentMaxZ, pLArTPC->GetCenterZ() + 0.5f * pLArTPC->GetWidthZ());
982  }
983 
984  PandoraApi::Geometry::LArTPC::Parameters larTPCParameters;
985  larTPCParameters.m_larTPCVolumeId = 0;
986  larTPCParameters.m_centerX = 0.5f * (parentMaxX + parentMinX);
987  larTPCParameters.m_centerY = 0.5f * (parentMaxY + parentMinY);
988  larTPCParameters.m_centerZ = 0.5f * (parentMaxZ + parentMinZ);
989  larTPCParameters.m_widthX = parentMaxX - parentMinX;
990  larTPCParameters.m_widthY = parentMaxY - parentMinY;
991  larTPCParameters.m_widthZ = parentMaxZ - parentMinZ;
992  larTPCParameters.m_wirePitchU = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
993  larTPCParameters.m_wirePitchV = std::max(pFirstLArTPC->GetWirePitchU(), pFirstLArTPC->GetWirePitchV());
994  larTPCParameters.m_wirePitchW = pFirstLArTPC->GetWirePitchW();
995  larTPCParameters.m_wireAngleU = pFirstLArTPC->GetWireAngleU();
996  larTPCParameters.m_wireAngleV = pFirstLArTPC->GetWireAngleV();
997  larTPCParameters.m_wireAngleW = pFirstLArTPC->GetWireAngleW();
998  larTPCParameters.m_sigmaUVW = pFirstLArTPC->GetSigmaUVW();
999  larTPCParameters.m_isDriftInPositiveX = pFirstLArTPC->IsDriftInPositiveX();
1000  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LArTPC::Create(*pPandora, larTPCParameters));
1001 
1002  // The Gaps
1003  for (const DetectorGap *const pGap : gapList)
1004  {
1005  const LineGap *const pLineGap(dynamic_cast<const LineGap*>(pGap));
1006 
1007  if (pLineGap)
1008  {
1009  PandoraApi::Geometry::LineGap::Parameters lineGapParameters;
1010  lineGapParameters.m_lineGapType = pLineGap->GetLineGapType();
1011  lineGapParameters.m_lineStartX = pLineGap->GetLineStartX();
1012  lineGapParameters.m_lineEndX = pLineGap->GetLineEndX();
1013  lineGapParameters.m_lineStartZ = pLineGap->GetLineStartZ();
1014  lineGapParameters.m_lineEndZ = pLineGap->GetLineEndZ();
1015  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::LineGap::Create(*pPandora, lineGapParameters));
1016  }
1017  }
1018 
1019  // Configuration
1020  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*pPandora, settingsFile));
1021  return pPandora;
1022 }
1023 
1024 //------------------------------------------------------------------------------------------------------------------------------------------
1025 
1026 StatusCode MasterAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
1027 {
1028  ExternalSteeringParameters *pExternalParameters(nullptr);
1029 
1030  if (this->ExternalParametersPresent())
1031  {
1032  pExternalParameters = dynamic_cast<ExternalSteeringParameters*>(this->GetExternalParameters());
1033  if (!pExternalParameters) return STATUS_CODE_FAILURE;
1034  }
1035 
1036  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1037  pExternalParameters->m_shouldRunAllHitsCosmicReco, xmlHandle, "ShouldRunAllHitsCosmicReco", m_shouldRunAllHitsCosmicReco));
1038 
1039  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1040  pExternalParameters->m_shouldRunStitching, xmlHandle, "ShouldRunStitching", m_shouldRunStitching));
1041 
1043  {
1044  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunStitching requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1045  return STATUS_CODE_INVALID_PARAMETER;
1046  }
1047 
1049  {
1050  AlgorithmToolVector algorithmToolVector;
1051  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "StitchingTools", algorithmToolVector));
1052 
1053  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1054  {
1055  StitchingBaseTool *const pStitchingTool(dynamic_cast<StitchingBaseTool*>(pAlgorithmTool));
1056  if (!pStitchingTool) return STATUS_CODE_INVALID_PARAMETER;
1057  m_stitchingToolVector.push_back(pStitchingTool);
1058  }
1059  }
1060 
1061  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1062  pExternalParameters->m_shouldRunCosmicHitRemoval, xmlHandle, "ShouldRunCosmicHitRemoval", m_shouldRunCosmicHitRemoval));
1063 
1065  {
1066  std::cout << "MasterAlgorithm::ReadSettings - ShouldRunCosmicHitRemoval requires ShouldRunAllHitsCosmicReco to be true" << std::endl;
1067  return STATUS_CODE_INVALID_PARAMETER;
1068  }
1069 
1071  {
1072  AlgorithmToolVector algorithmToolVector;
1073  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "CosmicRayTaggingTools", algorithmToolVector));
1074 
1075  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1076  {
1077  CosmicRayTaggingBaseTool *const pCosmicRayTaggingTool(dynamic_cast<CosmicRayTaggingBaseTool*>(pAlgorithmTool));
1078  if (!pCosmicRayTaggingTool) return STATUS_CODE_INVALID_PARAMETER;
1079  m_cosmicRayTaggingToolVector.push_back(pCosmicRayTaggingTool);
1080  }
1081  }
1082 
1083  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1084  pExternalParameters->m_shouldRunSlicing, xmlHandle, "ShouldRunSlicing", m_shouldRunSlicing));
1085 
1086  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1087  pExternalParameters->m_shouldRunNeutrinoRecoOption, xmlHandle, "ShouldRunNeutrinoRecoOption", m_shouldRunNeutrinoRecoOption));
1088 
1089  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1090  pExternalParameters->m_shouldRunCosmicRecoOption, xmlHandle, "ShouldRunCosmicRecoOption", m_shouldRunCosmicRecoOption));
1091 
1092  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1093  pExternalParameters->m_shouldPerformSliceId, xmlHandle, "ShouldPerformSliceId", m_shouldPerformSliceId));
1094 
1096  {
1097  std::cout << "MasterAlgorithm::ReadSettings - ShouldPerformSliceId requires ShouldRunSlicing and both neutrino and cosmic reconstruction options" << std::endl;
1098  return STATUS_CODE_INVALID_PARAMETER;
1099  }
1100 
1102  {
1103  AlgorithmToolVector algorithmToolVector;
1104  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "SliceIdTools", algorithmToolVector));
1105 
1106  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
1107  {
1108  SliceIdBaseTool *const pSliceIdIdTool(dynamic_cast<SliceIdBaseTool*>(pAlgorithmTool));
1109  if (!pSliceIdIdTool) return STATUS_CODE_INVALID_PARAMETER;
1110  m_sliceIdToolVector.push_back(pSliceIdIdTool);
1111  }
1112  }
1113 
1114  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->ReadExternalSettings(pExternalParameters, !pExternalParameters ? InputBool() :
1115  pExternalParameters->m_printOverallRecoStatus, xmlHandle, "PrintOverallRecoStatus", m_printOverallRecoStatus));
1116 
1117  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1118  "VisualizeOverallRecoStatus", m_visualizeOverallRecoStatus));
1119 
1120  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1121  "FullWidthCRWorkerWireGaps", m_fullWidthCRWorkerWireGaps));
1122 
1123  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1124  "PassMCParticlesToWorkerInstances", m_passMCParticlesToWorkerInstances));
1125 
1126  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
1127  "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
1128 
1129  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CRSettingsFile", m_crSettingsFile));
1130  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NuSettingsFile", m_nuSettingsFile));
1131  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "SlicingSettingsFile", m_slicingSettingsFile));
1135 
1137  {
1138  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputMCParticleListName", m_inputMCParticleListName));
1139  }
1140 
1141  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputHitListName", m_inputHitListName));
1142  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedPfoListName", m_recreatedPfoListName));
1143  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedClusterListName", m_recreatedClusterListName));
1144  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RecreatedVertexListName", m_recreatedVertexListName));
1145  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InTimeMaxX0", m_inTimeMaxX0));
1146 
1147  return STATUS_CODE_SUCCESS;
1148 }
1149 
1150 //------------------------------------------------------------------------------------------------------------------------------------------
1151 
1152 StatusCode MasterAlgorithm::ReadExternalSettings(const ExternalSteeringParameters *const pExternalParameters, const InputBool inputBool,
1153  const TiXmlHandle xmlHandle, const std::string &xmlTag, bool &outputBool)
1154 {
1155  if (pExternalParameters && inputBool.IsInitialized())
1156  {
1157  outputBool = inputBool.Get();
1158  }
1159  else
1160  {
1161  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, xmlTag, outputBool));
1162  }
1163 
1164  return STATUS_CODE_SUCCESS;
1165 }
1166 
1167 } // 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.