LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
NeutrinoDaughterVerticesAlgorithm.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 NeutrinoDaughterVerticesAlgorithm::NeutrinoDaughterVerticesAlgorithm() :
23  m_useParentShowerVertex(false),
24  m_halfWindowLayers(20)
25 {
26 }
27 
28 //------------------------------------------------------------------------------------------------------------------------------------------
29 
31 {
32  const PfoList *pPfoList = NULL;
33  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_neutrinoListName, pPfoList));
34 
35  if (!pPfoList || pPfoList->empty())
36  {
37  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
38  std::cout << "NeutrinoDaughterVerticesAlgorithm: unable to find pfo list " << m_neutrinoListName << std::endl;
39 
40  return STATUS_CODE_SUCCESS;
41  }
42 
43  PfoVector pfoVector;
44  LArPointingClusterMap pointingClusterMap;
45 
46  this->GetDaughterPfos(pPfoList, pfoVector);
47  this->BuildPointingClusterMap(pfoVector, pointingClusterMap);
48  this->BuildDaughterParticles(pointingClusterMap, pfoVector);
49 
50  return STATUS_CODE_SUCCESS;
51 }
52 
53 //------------------------------------------------------------------------------------------------------------------------------------------
54 
55 void NeutrinoDaughterVerticesAlgorithm::GetDaughterPfos(const PfoList *const pPfoList, PfoVector &pfoVector) const
56 {
57  PfoList outputList;
58 
59  for (PfoList::const_iterator pIter = pPfoList->begin(), pIterEnd = pPfoList->end(); pIter != pIterEnd; ++pIter)
60  {
61  if (!LArPfoHelper::IsNeutrino(*pIter) && (*pIter)->GetVertexList().size() != 1)
62  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
63 
64  LArPfoHelper::GetAllDownstreamPfos(*pIter, outputList);
65  }
66 
67  for (PfoList::const_iterator pIter = outputList.begin(), pIterEnd = outputList.end(); pIter != pIterEnd; ++pIter)
68  {
69  ClusterList clusterList;
70  LArPfoHelper::GetClusters(*pIter, TPC_3D, clusterList);
71 
72  if (clusterList.empty())
73  continue;
74 
75  pfoVector.push_back(*pIter);
76  }
77 }
78 
79 //------------------------------------------------------------------------------------------------------------------------------------------
80 
81 void NeutrinoDaughterVerticesAlgorithm::BuildPointingClusterMap(const PfoVector &pfoList, LArPointingClusterMap &pointingClusterMap) const
82 {
83  const float pitchU{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U)};
84  const float pitchV{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V)};
85  const float pitchW{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W)};
86  const float pitchMax{std::max({pitchU, pitchV, pitchW})};
87  const float slidingFitPitch(pitchMax);
88 
89  for (PfoVector::const_iterator pIter = pfoList.begin(), pIterEnd = pfoList.end(); pIter != pIterEnd; ++pIter)
90  {
91  const ParticleFlowObject *const pPfo = *pIter;
92 
93  if (!LArPfoHelper::IsTrack(pPfo))
94  continue;
95 
96  ClusterList clusterList;
97  LArPfoHelper::GetClusters(pPfo, TPC_3D, clusterList);
98 
99  for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
100  {
101  const Cluster *const pCluster = *cIter;
102 
103  try
104  {
105  const LArPointingCluster pointingCluster(pCluster, m_halfWindowLayers, slidingFitPitch);
106 
107  if (!pointingClusterMap.insert(LArPointingClusterMap::value_type(pCluster, pointingCluster)).second)
108  throw StatusCodeException(STATUS_CODE_FAILURE);
109  }
110  catch (StatusCodeException &statusCodeException)
111  {
112  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
113  throw statusCodeException;
114  }
115  }
116  }
117 }
118 
119 //------------------------------------------------------------------------------------------------------------------------------------------
120 
121 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterParticles(const LArPointingClusterMap &pointingClusterMap, const PfoVector &pfoVector) const
122 {
123  for (PfoVector::const_iterator iter = pfoVector.begin(), iterEnd = pfoVector.end(); iter != iterEnd; ++iter)
124  {
125  const ParticleFlowObject *const pPfo = *iter;
126 
127  if (LArPfoHelper::IsTrack(pPfo))
128  {
129  this->BuildDaughterTrack(pointingClusterMap, pPfo);
130  }
131  else
132  {
133  this->BuildDaughterShower(pPfo);
134  }
135  }
136 }
137 
138 //------------------------------------------------------------------------------------------------------------------------------------------
139 
140 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterTrack(const LArPointingClusterMap &pointingClusterMap, const ParticleFlowObject *const pDaughterPfo) const
141 {
142  if (pDaughterPfo->GetParentPfoList().size() != 1)
143  throw StatusCodeException(STATUS_CODE_FAILURE);
144 
145  const ParticleFlowObject *const pParentPfo = *(pDaughterPfo->GetParentPfoList().begin());
146 
147  ClusterList parentList, daughterList;
148  LArPfoHelper::GetClusters(pParentPfo, TPC_3D, parentList);
149  LArPfoHelper::GetClusters(pDaughterPfo, TPC_3D, daughterList);
150 
151  if (parentList.empty() && pParentPfo->GetVertexList().empty())
152  return;
153 
154  bool foundVtx(false);
155  float vtxDistance(0.f);
156  CartesianVector vtxPosition(0.f, 0.f, 0.f);
157  CartesianVector vtxDirection(0.f, 0.f, 0.f);
158 
159  for (ClusterList::const_iterator dIter = daughterList.begin(), dIterEnd = daughterList.end(); dIter != dIterEnd; ++dIter)
160  {
161  const Cluster *const pDaughterCluster = *dIter;
162 
163  CartesianVector minPosition(0.f, 0.f, 0.f), maxPosition(0.f, 0.f, 0.f);
164  CartesianVector minDirection(0.f, 0.f, 0.f), maxDirection(0.f, 0.f, 0.f);
165  bool foundDirection(false);
166 
167  LArPointingClusterMap::const_iterator cIter = pointingClusterMap.find(pDaughterCluster);
168 
169  if (pointingClusterMap.end() != cIter)
170  {
171  const LArPointingCluster &pointingCluster(cIter->second);
172 
173  minPosition = pointingCluster.GetInnerVertex().GetPosition();
174  maxPosition = pointingCluster.GetOuterVertex().GetPosition();
175  minDirection = pointingCluster.GetInnerVertex().GetDirection();
176  maxDirection = pointingCluster.GetOuterVertex().GetDirection();
177  foundDirection = true;
178  }
179  else
180  {
181  LArClusterHelper::GetExtremalCoordinates(pDaughterCluster, minPosition, maxPosition);
182  }
183 
184  if ((maxPosition - minPosition).GetMagnitudeSquared() < std::numeric_limits<float>::epsilon())
185  continue;
186 
187  if (!foundDirection)
188  {
189  minDirection = (maxPosition - minPosition).GetUnitVector();
190  maxDirection = (minPosition - maxPosition).GetUnitVector();
191  }
192 
193  float minDistance(std::numeric_limits<float>::max());
194  float maxDistance(std::numeric_limits<float>::max());
195 
196  for (ClusterList::const_iterator pIter = parentList.begin(), pIterEnd = parentList.end(); pIter != pIterEnd; ++pIter)
197  {
198  const Cluster *const pParentCluster = *pIter;
199  minDistance = std::min(minDistance, (LArClusterHelper::GetClosestDistance(minPosition, pParentCluster)));
200  maxDistance = std::min(maxDistance, (LArClusterHelper::GetClosestDistance(maxPosition, pParentCluster)));
201  }
202 
203  if (LArPfoHelper::IsNeutrino(pParentPfo) && !pParentPfo->GetVertexList().empty())
204  {
205  const Vertex *const pVertex = *(pParentPfo->GetVertexList().begin());
206  minDistance = std::min(minDistance, (pVertex->GetPosition() - minPosition).GetMagnitude());
207  maxDistance = std::min(maxDistance, (pVertex->GetPosition() - maxPosition).GetMagnitude());
208  }
209 
210  if (!foundVtx || (minDistance < vtxDistance))
211  {
212  foundVtx = true;
213  vtxDistance = minDistance;
214  vtxPosition = minPosition;
215  vtxDirection = minDirection;
216  }
217 
218  if (!foundVtx || (maxDistance < vtxDistance))
219  {
220  foundVtx = true;
221  vtxDistance = maxDistance;
222  vtxPosition = maxPosition;
223  vtxDirection = maxDirection;
224  }
225  }
226 
227  if (!foundVtx)
228  return;
229 
230  this->SetParticleParameters(vtxPosition, vtxDirection, pDaughterPfo);
231 }
232 
233 //------------------------------------------------------------------------------------------------------------------------------------------
234 
235 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterShower(const ParticleFlowObject *const pDaughterPfo) const
236 {
237  if (pDaughterPfo->GetParentPfoList().size() != 1)
238  throw StatusCodeException(STATUS_CODE_FAILURE);
239 
240  const ParticleFlowObject *const pParentPfo = *(pDaughterPfo->GetParentPfoList().begin());
241 
242  if (LArPfoHelper::IsNeutrino(pParentPfo) && pParentPfo->GetVertexList().size() != 1)
243  throw StatusCodeException(STATUS_CODE_FAILURE);
244 
245  ClusterList parentList, daughterList;
246  LArPfoHelper::GetClusters(pParentPfo, TPC_3D, parentList);
247  LArPfoHelper::GetClusters(pDaughterPfo, TPC_3D, daughterList);
248 
249  if (daughterList.empty())
250  return;
251 
252  if (LArPfoHelper::IsNeutrino(pParentPfo))
253  {
254  const Vertex *const pVertex = *(pParentPfo->GetVertexList().begin());
255  const CartesianVector vtxPosition(
256  m_useParentShowerVertex ? pVertex->GetPosition() : LArClusterHelper::GetClosestPosition(pVertex->GetPosition(), daughterList));
257 
258  return this->SetParticleParameters(vtxPosition, CartesianVector(0.f, 0.f, 0.f), pDaughterPfo);
259  }
260 
261  if (parentList.empty())
262  return;
263 
264  bool foundVtx(false);
265  float vtxDistanceSquared(0.f);
266  CartesianVector vtxPosition(0.f, 0.f, 0.f);
267 
268  for (ClusterList::const_iterator dIter = daughterList.begin(), dIterEnd = daughterList.end(); dIter != dIterEnd; ++dIter)
269  {
270  const Cluster *const pDaughterCluster = *dIter;
271 
272  for (ClusterList::const_iterator pIter = parentList.begin(), pIterEnd = parentList.end(); pIter != pIterEnd; ++pIter)
273  {
274  const Cluster *const pParentCluster = *pIter;
275 
276  CartesianVector closestDaughterPosition(0.f, 0.f, 0.f), closestParentPosition(0.f, 0.f, 0.f);
277  LArClusterHelper::GetClosestPositions(pDaughterCluster, pParentCluster, closestDaughterPosition, closestParentPosition);
278 
279  const float closestDistanceSquared((closestDaughterPosition - closestParentPosition).GetMagnitudeSquared());
280 
281  if (!foundVtx || closestDistanceSquared < vtxDistanceSquared)
282  {
283  foundVtx = true;
284  vtxDistanceSquared = closestDistanceSquared;
285  vtxPosition = (m_useParentShowerVertex ? closestParentPosition : closestDaughterPosition);
286  }
287  }
288  }
289 
290  if (!foundVtx)
291  return;
292 
293  this->SetParticleParameters(vtxPosition, CartesianVector(0.f, 0.f, 0.f), pDaughterPfo);
294 }
295 
296 //------------------------------------------------------------------------------------------------------------------------------------------
297 
299  const CartesianVector &vtxPosition, const CartesianVector &vtxDirection, const ParticleFlowObject *const pPfo) const
300 {
301  if (!pPfo->GetVertexList().empty())
302  throw StatusCodeException(STATUS_CODE_FAILURE);
303 
304  PandoraContentApi::ParticleFlowObject::Metadata metadata;
305  metadata.m_momentum = vtxDirection;
306  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
307 
308  const VertexList *pVertexList = NULL;
309  std::string vertexListName;
310  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
311 
312  PandoraContentApi::Vertex::Parameters parameters;
313  parameters.m_position = vtxPosition;
314  parameters.m_vertexLabel = VERTEX_INTERACTION;
315  parameters.m_vertexType = VERTEX_3D;
316 
317  const Vertex *pVertex(NULL);
318  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
319 
320  if (!pVertexList->empty())
321  {
322  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_vertexListName));
323  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo<Vertex>(*this, pPfo, pVertex));
324  }
325 }
326 
327 //------------------------------------------------------------------------------------------------------------------------------------------
328 
329 StatusCode NeutrinoDaughterVerticesAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
330 {
331  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NeutrinoPfoListName", m_neutrinoListName));
332 
333  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_vertexListName));
334 
335  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
336  XmlHelper::ReadValue(xmlHandle, "UseParentForShowerVertex", m_useParentShowerVertex));
337 
338  PANDORA_RETURN_RESULT_IF_AND_IF(
339  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
340 
341  return STATUS_CODE_SUCCESS;
342 }
343 
344 } // namespace lar_content
unsigned int m_halfWindowLayers
number of layers to use for half-window of sliding fit
std::unordered_map< const pandora::Cluster *, LArPointingCluster > LArPointingClusterMap
std::string m_vertexListName
The name of the output cosmic-ray vertex list.
Header file for the pfo helper class.
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.
intermediate_table::const_iterator const_iterator
Header file for the neutrino daughter vertices algorithm class.
LArPointingCluster class.
static void GetClosestPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianVector &position1, pandora::CartesianVector &position2)
Get pair of closest positions for a pair of clusters.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
void GetDaughterPfos(const pandora::PfoList *const pfoList, pandora::PfoVector &pfoVector) const
Get the vector of daughter pfos.
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
const Vertex & GetInnerVertex() const
Get the inner vertex.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static bool IsNeutrino(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a neutrino or (antineutrino)
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
bool m_useParentShowerVertex
use the parent pfo for the shower vertices
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) ...
void SetParticleParameters(const pandora::CartesianVector &vtxPosition, const pandora::CartesianVector &vtxDirection, const pandora::ParticleFlowObject *const pPfo) const
Set the vertex and direction of the Pfos.
void BuildDaughterShower(const pandora::ParticleFlowObject *const pDaughterPfo) const
Reconstruct the vertex and direction of a shower-like 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...
void BuildDaughterParticles(const LArPointingClusterMap &pointingClusterMap, const pandora::PfoVector &pfoVector) const
Reconstruct the vertex and direction of daughter Pfos.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
void BuildPointingClusterMap(const pandora::PfoVector &pfoVector, LArPointingClusterMap &pointingClusterMap) const
Build a map of 3D sliding fits from the input Pfos.
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.
std::string m_neutrinoListName
The input list of pfo list names.
std::list< Vertex > VertexList
Definition: DCEL.h:169
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
void BuildDaughterTrack(const LArPointingClusterMap &pointingClusterMap, const pandora::ParticleFlowObject *const pDaughterPfo) const
Reconstruct the vertex and direction of a track-like Pfos.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.