LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
CosmicRayVertexBuildingAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
14 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 CosmicRayVertexBuildingAlgorithm::CosmicRayVertexBuildingAlgorithm() :
23  m_useParentShowerVertex(false),
24  m_isDualPhase(false),
25  m_halfWindowLayers(30),
26  m_maxVertexDisplacementFromTrack(1.f)
27 {
28 }
29 
30 //------------------------------------------------------------------------------------------------------------------------------------------
31 
33 {
34  const PfoList *pPfoList = NULL;
35  PANDORA_THROW_RESULT_IF_AND_IF(
36  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_parentPfoListName, pPfoList));
37 
38  if (NULL == pPfoList)
39  {
40  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
41  std::cout << "CosmicRayVertexBuildingAlgorithm: pfo list unavailable." << std::endl;
42 
43  return STATUS_CODE_SUCCESS;
44  }
45 
46  PfoVector pfoVector;
47  LArPointingClusterMap pointingClusterMap;
48 
49  this->GetCosmicPfos(pPfoList, pfoVector);
50  this->BuildPointingClusterMap(pfoVector, pointingClusterMap);
51  this->BuildCosmicRayParticles(pointingClusterMap, pfoVector);
52 
53  return STATUS_CODE_SUCCESS;
54 }
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 
58 void CosmicRayVertexBuildingAlgorithm::GetCosmicPfos(const PfoList *const pPfoList, PfoVector &pfoVector) const
59 {
60  PfoList outputList;
61 
62  for (PfoList::const_iterator pIter = pPfoList->begin(), pIterEnd = pPfoList->end(); pIter != pIterEnd; ++pIter)
63  {
64  if (!LArPfoHelper::IsFinalState(*pIter))
65  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
66 
67  LArPfoHelper::GetAllDownstreamPfos(*pIter, outputList);
68  }
69 
70  for (PfoList::const_iterator pIter = outputList.begin(), pIterEnd = outputList.end(); pIter != pIterEnd; ++pIter)
71  {
72  ClusterList clusterList;
73  LArPfoHelper::GetClusters(*pIter, TPC_3D, clusterList);
74 
75  if (clusterList.empty())
76  continue;
77 
78  pfoVector.push_back(*pIter);
79  }
80 }
81 
82 //------------------------------------------------------------------------------------------------------------------------------------------
83 
84 void CosmicRayVertexBuildingAlgorithm::BuildPointingClusterMap(const PfoVector &pfoVector, LArPointingClusterMap &pointingClusterMap) const
85 {
86  const float pitchU{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U)};
87  const float pitchV{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V)};
88  const float pitchW{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W)};
89  const float slidingFitPitch(std::max({pitchU, pitchV, pitchW}));
90 
91  for (PfoVector::const_iterator pIter = pfoVector.begin(), pIterEnd = pfoVector.end(); pIter != pIterEnd; ++pIter)
92  {
93  const ParticleFlowObject *const pPfo = *pIter;
94 
95  if (!LArPfoHelper::IsTrack(pPfo))
96  continue;
97 
98  ClusterList clusterList;
99  LArPfoHelper::GetClusters(pPfo, TPC_3D, clusterList);
100 
101  for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
102  {
103  const Cluster *const pCluster = *cIter;
104 
105  try
106  {
107  const LArPointingCluster pointingCluster(pCluster, m_halfWindowLayers, slidingFitPitch);
108 
109  if (!pointingClusterMap.insert(LArPointingClusterMap::value_type(pCluster, pointingCluster)).second)
110  throw StatusCodeException(STATUS_CODE_FAILURE);
111  }
112  catch (StatusCodeException &statusCodeException)
113  {
114  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
115  throw statusCodeException;
116  }
117  }
118  }
119 }
120 
121 //------------------------------------------------------------------------------------------------------------------------------------------
122 
123 void CosmicRayVertexBuildingAlgorithm::BuildCosmicRayParticles(const LArPointingClusterMap &pointingClusterMap, const PfoVector &pfoVector) const
124 {
125  for (PfoVector::const_iterator iter = pfoVector.begin(), iterEnd = pfoVector.end(); iter != iterEnd; ++iter)
126  {
127  const ParticleFlowObject *const pPfo = *iter;
128 
129  if (LArPfoHelper::IsFinalState(pPfo))
130  {
131  this->BuildCosmicRayParent(pointingClusterMap, pPfo);
132  }
133  else
134  {
135  this->BuildCosmicRayDaughter(pPfo);
136  }
137  }
138 }
139 
140 //------------------------------------------------------------------------------------------------------------------------------------------
141 
142 void CosmicRayVertexBuildingAlgorithm::BuildCosmicRayParent(const LArPointingClusterMap &pointingClusterMap, const ParticleFlowObject *const pPfo) const
143 {
144  ClusterList clusterList;
145  LArPfoHelper::GetClusters(pPfo, TPC_3D, clusterList);
146 
147  if (clusterList.empty())
148  return;
149 
150  // Take highest point as vertex of parent Pfos (TODO: do something more sophisticated for horizontal events)
151  bool foundVtx(false);
152  CartesianVector vtxPosition(0.f, 0.f, 0.f);
153  CartesianVector vtxDirection(0.f, 0.f, 0.f);
154 
155  bool foundEnd(false);
156  CartesianVector endPosition(0.f, 0.f, 0.f);
157  CartesianVector endDirection(0.f, 0.f, 0.f);
158 
159  for (ClusterList::const_iterator cIter1 = clusterList.begin(), cIterEnd1 = clusterList.end(); cIter1 != cIterEnd1; ++cIter1)
160  {
161  const Cluster *const pCluster = *cIter1;
162 
163  try
164  {
165  CartesianVector minPosition(0.f, 0.f, 0.f), maxPosition(0.f, 0.f, 0.f);
166  CartesianVector minDirection(0.f, 0.f, 0.f), maxDirection(0.f, 0.f, 0.f);
167 
168  LArPointingClusterMap::const_iterator cIter2 = pointingClusterMap.find(pCluster);
169 
170  if (pointingClusterMap.end() != cIter2)
171  {
172  const LArPointingCluster &pointingCluster(cIter2->second);
173 
174  minPosition = pointingCluster.GetInnerVertex().GetPosition();
175  maxPosition = pointingCluster.GetOuterVertex().GetPosition();
176  minDirection = pointingCluster.GetInnerVertex().GetDirection();
177  maxDirection = pointingCluster.GetOuterVertex().GetDirection();
178  }
179  else
180  {
181  LArClusterHelper::GetExtremalCoordinates(pCluster, minPosition, maxPosition);
182  minDirection = (maxPosition - minPosition).GetUnitVector();
183  maxDirection = (minPosition - maxPosition).GetUnitVector();
184  }
185 
186  if ((maxPosition - minPosition).GetMagnitudeSquared() < std::numeric_limits<float>::epsilon())
187  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
188 
189  // ATTN X is the vertical coordinate in Dual-Phase geometry
190  const float minVerticalCoordinate(m_isDualPhase ? minPosition.GetX() : minPosition.GetY());
191  const float maxVerticalCoordinate(m_isDualPhase ? maxPosition.GetX() : maxPosition.GetY());
192 
193  if (!foundVtx || (minVerticalCoordinate > std::max(maxVerticalCoordinate, m_isDualPhase ? vtxPosition.GetX() : vtxPosition.GetY())))
194  {
195  foundVtx = true;
196  vtxPosition = minPosition;
197  vtxDirection = minDirection;
198  }
199 
200  if (!foundVtx || (maxVerticalCoordinate > std::max(minVerticalCoordinate, m_isDualPhase ? vtxPosition.GetX() : vtxPosition.GetY())))
201  {
202  foundVtx = true;
203  vtxPosition = maxPosition;
204  vtxDirection = maxDirection;
205  }
206 
207  if (!foundEnd || (minVerticalCoordinate < std::min(maxVerticalCoordinate, m_isDualPhase ? endPosition.GetX() : endPosition.GetY())))
208  {
209  foundEnd = true;
210  endPosition = minPosition;
211  endDirection = minDirection;
212  }
213 
214  if (!foundEnd || (maxVerticalCoordinate < std::min(minVerticalCoordinate, m_isDualPhase ? endPosition.GetX() : endPosition.GetY())))
215  {
216  foundEnd = true;
217  endPosition = maxPosition;
218  endDirection = maxDirection;
219  }
220  }
221  catch (StatusCodeException &statusCodeException)
222  {
223  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
224  throw statusCodeException;
225 
226  continue;
227  }
228  }
229 
230  if (!(foundVtx && foundEnd))
231  return;
232 
233  this->SetParticleParameters(vtxPosition, vtxDirection, pPfo);
234 }
235 
236 //------------------------------------------------------------------------------------------------------------------------------------------
237 
238 void CosmicRayVertexBuildingAlgorithm::BuildCosmicRayDaughter(const ParticleFlowObject *const pDaughterPfo) const
239 {
240  if (pDaughterPfo->GetParentPfoList().size() != 1)
241  throw StatusCodeException(STATUS_CODE_FAILURE);
242 
243  const ParticleFlowObject *const pParentPfo = *(pDaughterPfo->GetParentPfoList().begin());
244 
245  ClusterList parentList, daughterList;
246  LArPfoHelper::GetClusters(pParentPfo, TPC_3D, parentList);
247  LArPfoHelper::GetClusters(pDaughterPfo, TPC_3D, daughterList);
248 
249  if (daughterList.empty() || parentList.empty())
250  return;
251 
252  bool found(false);
253  float closestMaxVerticalCoordinate(-std::numeric_limits<float>::max()), maxVerticalCoordinate(-std::numeric_limits<float>::max());
254  CartesianVector closestMaxVerticalVertex(0.f, 0.f, 0.f), maxVerticalVertex(0.f, 0.f, 0.f);
255 
256  for (const Cluster *const pDaughterCluster : daughterList)
257  {
258  CaloHitList daughterCaloHitList;
259  pDaughterCluster->GetOrderedCaloHitList().FillCaloHitList(daughterCaloHitList);
260 
261  for (const Cluster *const pParentCluster : parentList)
262  {
263  CaloHitList parentCaloHitList;
264  pParentCluster->GetOrderedCaloHitList().FillCaloHitList(parentCaloHitList);
265 
266  for (const CaloHit *const pDaughterCaloHit : daughterCaloHitList)
267  {
268  const CartesianVector &daughterPosition(pDaughterCaloHit->GetPositionVector());
269 
270  for (const CaloHit *const pParentCaloHit : parentCaloHitList)
271  {
272  const CartesianVector &parentPosition(pParentCaloHit->GetPositionVector());
273  const float separationSquared((daughterPosition - parentPosition).GetMagnitudeSquared());
274  const float verticalCoordinate(m_isDualPhase ? daughterPosition.GetX() : daughterPosition.GetY());
275 
276  if (verticalCoordinate > maxVerticalCoordinate)
277  {
278  maxVerticalCoordinate = verticalCoordinate;
279  maxVerticalVertex = daughterPosition;
280  }
281 
283  {
284  if (verticalCoordinate > closestMaxVerticalCoordinate)
285  {
286  found = true;
287  closestMaxVerticalCoordinate = verticalCoordinate;
288  closestMaxVerticalVertex = daughterPosition;
289  }
290  }
291  }
292  }
293  }
294  }
295 
296  const CartesianVector &daughterVertex(found ? closestMaxVerticalVertex : maxVerticalVertex);
297  const CartesianVector &vertexPosition(m_useParentShowerVertex ? LArClusterHelper::GetClosestPosition(daughterVertex, parentList) : daughterVertex);
298 
299  this->SetParticleParameters(vertexPosition, CartesianVector(0.f, 0.f, 0.f), pDaughterPfo);
300 }
301 
302 //------------------------------------------------------------------------------------------------------------------------------------------
303 
305  const CartesianVector &vtxPosition, const CartesianVector &vtxDirection, const ParticleFlowObject *const pPfo) const
306 {
307  if (!pPfo->GetVertexList().empty())
308  throw StatusCodeException(STATUS_CODE_FAILURE);
309 
310  PandoraContentApi::ParticleFlowObject::Metadata metadata;
311  metadata.m_momentum = vtxDirection;
312  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
313 
314  const VertexList *pVertexList = NULL;
315  std::string vertexListName;
316  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
317 
318  PandoraContentApi::Vertex::Parameters parameters;
319  parameters.m_position = vtxPosition;
320  parameters.m_vertexLabel = VERTEX_START;
321  parameters.m_vertexType = VERTEX_3D;
322 
323  const Vertex *pVertex(NULL);
324  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
325 
326  if (!pVertexList->empty())
327  {
328  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_vertexListName));
329  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo<Vertex>(*this, pPfo, pVertex));
330  }
331 }
332 
333 //------------------------------------------------------------------------------------------------------------------------------------------
334 
335 StatusCode CosmicRayVertexBuildingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
336 {
337  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputPfoListName", m_parentPfoListName));
338 
339  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_vertexListName));
340 
341  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
342  XmlHelper::ReadValue(xmlHandle, "UseParentForShowerVertex", m_useParentShowerVertex));
343 
344  PANDORA_RETURN_RESULT_IF_AND_IF(
345  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
346 
347  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "IsDualPhase", m_isDualPhase));
348 
349  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
350  XmlHelper::ReadValue(xmlHandle, "MaxVertexDisplacementFromTrack", m_maxVertexDisplacementFromTrack));
351 
352  return STATUS_CODE_SUCCESS;
353 }
354 
355 } // namespace lar_content
std::unordered_map< const pandora::Cluster *, LArPointingCluster > LArPointingClusterMap
Header file for the pfo helper class.
bool m_useParentShowerVertex
use the parent pfo for the shower vertices
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
void SetParticleParameters(const pandora::CartesianVector &vtxPosition, const pandora::CartesianVector &vtxDirection, const pandora::ParticleFlowObject *const pPfo) const
Set the vertex and direction of the Pfos.
intermediate_table::const_iterator const_iterator
LArPointingCluster class.
std::string m_vertexListName
The name of the output vertex list.
Header file for the cosmic-ray vertex building algorithm class.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
void BuildCosmicRayParent(const LArPointingClusterMap &pointingClusterMap, const pandora::ParticleFlowObject *const pPfo) const
Reconstruct the vertex and direction of a parent cosmic-ray Pfo.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void BuildCosmicRayParticles(const LArPointingClusterMap &pointingClusterMap, const pandora::PfoVector &pfoVector) const
Reconstruct the vertex and direction of a list of cosmic-ray Pfos.
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
const Vertex & GetInnerVertex() const
Get the inner vertex.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
std::string m_parentPfoListName
The name of the input pfo list.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
unsigned int m_halfWindowLayers
number of layers to use for half-window of sliding fit
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
float m_maxVertexDisplacementFromTrack
The maximum separation of a close vertex from the cosmic ray track.
static bool IsFinalState(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a primary parent particle.
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...
void GetCosmicPfos(const pandora::PfoList *const pPfoList, pandora::PfoVector &pfoVector) const
Get the list of input pfos to this algorithm.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
void BuildCosmicRayDaughter(const pandora::ParticleFlowObject *const pPfo) const
Reconstruct the vertex and direction of a daughter cosmic-ray Pfo.
void BuildPointingClusterMap(const pandora::PfoVector &pfoVector, LArPointingClusterMap &pointingClusterMap) const
Build a map of 3D sliding fits from the input Pfos.
std::list< Vertex > VertexList
Definition: DCEL.h:169
const pandora::CartesianVector & GetPosition() const
Get the vertex position.