NeutrinoDaughterVerticesAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArEventBuilding/NeutrinoDaughterVerticesAlgorithm.cc
3  *
4  * @brief Implementation of the neutrino daughter vertices algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
14 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 NeutrinoDaughterVerticesAlgorithm::NeutrinoDaughterVerticesAlgorithm() : m_useParentShowerVertex(false), m_halfWindowLayers(20)
23 {
24 }
25 
26 //------------------------------------------------------------------------------------------------------------------------------------------
27 
29 {
30  const PfoList *pPfoList = NULL;
31  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_neutrinoListName, pPfoList));
32 
33  if (!pPfoList || pPfoList->empty())
34  {
35  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
36  std::cout << "NeutrinoDaughterVerticesAlgorithm: unable to find pfo list " << m_neutrinoListName << std::endl;
37 
38  return STATUS_CODE_SUCCESS;
39  }
40 
41  PfoVector pfoVector;
42  LArPointingClusterMap pointingClusterMap;
43 
44  this->GetDaughterPfos(pPfoList, pfoVector);
45  this->BuildPointingClusterMap(pfoVector, pointingClusterMap);
46  this->BuildDaughterParticles(pointingClusterMap, pfoVector);
47 
48  return STATUS_CODE_SUCCESS;
49 }
50 
51 //------------------------------------------------------------------------------------------------------------------------------------------
52 
53 void NeutrinoDaughterVerticesAlgorithm::GetDaughterPfos(const PfoList *const pPfoList, PfoVector &pfoVector) const
54 {
55  PfoList outputList;
56 
57  for (PfoList::const_iterator pIter = pPfoList->begin(), pIterEnd = pPfoList->end(); pIter != pIterEnd; ++pIter)
58  {
59  if (!LArPfoHelper::IsNeutrino(*pIter) && (*pIter)->GetVertexList().size() != 1)
60  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
61 
62  LArPfoHelper::GetAllDownstreamPfos(*pIter, outputList);
63  }
64 
65  for (PfoList::const_iterator pIter = outputList.begin(), pIterEnd = outputList.end(); pIter != pIterEnd; ++pIter)
66  {
67  ClusterList clusterList;
68  LArPfoHelper::GetClusters(*pIter, TPC_3D, clusterList);
69 
70  if (clusterList.empty())
71  continue;
72 
73  pfoVector.push_back(*pIter);
74  }
75 }
76 
77 //------------------------------------------------------------------------------------------------------------------------------------------
78 
79 void NeutrinoDaughterVerticesAlgorithm::BuildPointingClusterMap(const PfoVector &pfoList, LArPointingClusterMap &pointingClusterMap) const
80 {
81  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
82 
83  for (PfoVector::const_iterator pIter = pfoList.begin(), pIterEnd = pfoList.end(); pIter != pIterEnd; ++pIter)
84  {
85  const ParticleFlowObject *const pPfo = *pIter;
86 
87  if (!LArPfoHelper::IsTrack(pPfo))
88  continue;
89 
90  ClusterList clusterList;
91  LArPfoHelper::GetClusters(pPfo, TPC_3D, clusterList);
92 
93  for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
94  {
95  const Cluster *const pCluster = *cIter;
96 
97  try
98  {
99  const LArPointingCluster pointingCluster(pCluster, m_halfWindowLayers, slidingFitPitch);
100 
101  if (!pointingClusterMap.insert(LArPointingClusterMap::value_type(pCluster, pointingCluster)).second)
102  throw StatusCodeException(STATUS_CODE_FAILURE);
103  }
104  catch (StatusCodeException &statusCodeException)
105  {
106  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
107  throw statusCodeException;
108  }
109  }
110  }
111 }
112 
113 //------------------------------------------------------------------------------------------------------------------------------------------
114 
115 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterParticles(const LArPointingClusterMap &pointingClusterMap, const PfoVector &pfoVector) const
116 {
117  for (PfoVector::const_iterator iter = pfoVector.begin(), iterEnd = pfoVector.end(); iter != iterEnd; ++iter)
118  {
119  const ParticleFlowObject *const pPfo = *iter;
120 
121  if (LArPfoHelper::IsTrack(pPfo))
122  {
123  this->BuildDaughterTrack(pointingClusterMap, pPfo);
124  }
125  else
126  {
127  this->BuildDaughterShower(pPfo);
128  }
129  }
130 }
131 
132 //------------------------------------------------------------------------------------------------------------------------------------------
133 
134 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterTrack(const LArPointingClusterMap &pointingClusterMap, const ParticleFlowObject *const pDaughterPfo) const
135 {
136  if (pDaughterPfo->GetParentPfoList().size() != 1)
137  throw StatusCodeException(STATUS_CODE_FAILURE);
138 
139  const ParticleFlowObject *const pParentPfo = *(pDaughterPfo->GetParentPfoList().begin());
140 
141  ClusterList parentList, daughterList;
142  LArPfoHelper::GetClusters(pParentPfo, TPC_3D, parentList);
143  LArPfoHelper::GetClusters(pDaughterPfo, TPC_3D, daughterList);
144 
145  if (parentList.empty() && pParentPfo->GetVertexList().empty())
146  return;
147 
148  bool foundVtx(false);
149  float vtxDistance(0.f);
150  CartesianVector vtxPosition(0.f, 0.f, 0.f);
151  CartesianVector vtxDirection(0.f, 0.f, 0.f);
152 
153  for (ClusterList::const_iterator dIter = daughterList.begin(), dIterEnd = daughterList.end(); dIter != dIterEnd; ++dIter)
154  {
155  const Cluster *const pDaughterCluster = *dIter;
156 
157  CartesianVector minPosition(0.f, 0.f, 0.f), maxPosition(0.f, 0.f, 0.f);
158  CartesianVector minDirection(0.f, 0.f, 0.f), maxDirection(0.f, 0.f, 0.f);
159  bool foundDirection(false);
160 
161  LArPointingClusterMap::const_iterator cIter = pointingClusterMap.find(pDaughterCluster);
162 
163  if (pointingClusterMap.end() != cIter)
164  {
165  const LArPointingCluster &pointingCluster(cIter->second);
166 
167  minPosition = pointingCluster.GetInnerVertex().GetPosition();
168  maxPosition = pointingCluster.GetOuterVertex().GetPosition();
169  minDirection = pointingCluster.GetInnerVertex().GetDirection();
170  maxDirection = pointingCluster.GetOuterVertex().GetDirection();
171  foundDirection = true;
172  }
173  else
174  {
175  LArClusterHelper::GetExtremalCoordinates(pDaughterCluster, minPosition, maxPosition);
176  }
177 
178  if ((maxPosition - minPosition).GetMagnitudeSquared() < std::numeric_limits<float>::epsilon())
179  continue;
180 
181  if (!foundDirection)
182  {
183  minDirection = (maxPosition - minPosition).GetUnitVector();
184  maxDirection = (minPosition - maxPosition).GetUnitVector();
185  }
186 
187  float minDistance(std::numeric_limits<float>::max());
188  float maxDistance(std::numeric_limits<float>::max());
189 
190  for (ClusterList::const_iterator pIter = parentList.begin(), pIterEnd = parentList.end(); pIter != pIterEnd; ++pIter)
191  {
192  const Cluster *const pParentCluster = *pIter;
193  minDistance = std::min(minDistance, (LArClusterHelper::GetClosestDistance(minPosition, pParentCluster)));
194  maxDistance = std::min(maxDistance, (LArClusterHelper::GetClosestDistance(maxPosition, pParentCluster)));
195  }
196 
197  if (LArPfoHelper::IsNeutrino(pParentPfo) && !pParentPfo->GetVertexList().empty())
198  {
199  const Vertex *const pVertex = *(pParentPfo->GetVertexList().begin());
200  minDistance = std::min(minDistance, (pVertex->GetPosition() - minPosition).GetMagnitude());
201  maxDistance = std::min(maxDistance, (pVertex->GetPosition() - maxPosition).GetMagnitude());
202  }
203 
204  if (!foundVtx || (minDistance < vtxDistance))
205  {
206  foundVtx = true;
207  vtxDistance = minDistance;
208  vtxPosition = minPosition;
209  vtxDirection = minDirection;
210  }
211 
212  if (!foundVtx || (maxDistance < vtxDistance))
213  {
214  foundVtx = true;
215  vtxDistance = maxDistance;
216  vtxPosition = maxPosition;
217  vtxDirection = maxDirection;
218  }
219  }
220 
221  if (!foundVtx)
222  return;
223 
224  this->SetParticleParameters(vtxPosition, vtxDirection, pDaughterPfo);
225 }
226 
227 //------------------------------------------------------------------------------------------------------------------------------------------
228 
229 void NeutrinoDaughterVerticesAlgorithm::BuildDaughterShower(const ParticleFlowObject *const pDaughterPfo) const
230 {
231  if (pDaughterPfo->GetParentPfoList().size() != 1)
232  throw StatusCodeException(STATUS_CODE_FAILURE);
233 
234  const ParticleFlowObject *const pParentPfo = *(pDaughterPfo->GetParentPfoList().begin());
235 
236  if (LArPfoHelper::IsNeutrino(pParentPfo) && pParentPfo->GetVertexList().size() != 1)
237  throw StatusCodeException(STATUS_CODE_FAILURE);
238 
239  ClusterList parentList, daughterList;
240  LArPfoHelper::GetClusters(pParentPfo, TPC_3D, parentList);
241  LArPfoHelper::GetClusters(pDaughterPfo, TPC_3D, daughterList);
242 
243  if (daughterList.empty())
244  return;
245 
246  if (LArPfoHelper::IsNeutrino(pParentPfo))
247  {
248  const Vertex *const pVertex = *(pParentPfo->GetVertexList().begin());
249  const CartesianVector vtxPosition(
250  m_useParentShowerVertex ? pVertex->GetPosition() : LArClusterHelper::GetClosestPosition(pVertex->GetPosition(), daughterList));
251 
252  return this->SetParticleParameters(vtxPosition, CartesianVector(0.f, 0.f, 0.f), pDaughterPfo);
253  }
254 
255  if (parentList.empty())
256  return;
257 
258  bool foundVtx(false);
259  float vtxDistanceSquared(0.f);
260  CartesianVector vtxPosition(0.f, 0.f, 0.f);
261 
262  for (ClusterList::const_iterator dIter = daughterList.begin(), dIterEnd = daughterList.end(); dIter != dIterEnd; ++dIter)
263  {
264  const Cluster *const pDaughterCluster = *dIter;
265 
266  for (ClusterList::const_iterator pIter = parentList.begin(), pIterEnd = parentList.end(); pIter != pIterEnd; ++pIter)
267  {
268  const Cluster *const pParentCluster = *pIter;
269 
270  CartesianVector closestDaughterPosition(0.f, 0.f, 0.f), closestParentPosition(0.f, 0.f, 0.f);
271  LArClusterHelper::GetClosestPositions(pDaughterCluster, pParentCluster, closestDaughterPosition, closestParentPosition);
272 
273  const float closestDistanceSquared((closestDaughterPosition - closestParentPosition).GetMagnitudeSquared());
274 
275  if (!foundVtx || closestDistanceSquared < vtxDistanceSquared)
276  {
277  foundVtx = true;
278  vtxDistanceSquared = closestDistanceSquared;
279  vtxPosition = (m_useParentShowerVertex ? closestParentPosition : closestDaughterPosition);
280  }
281  }
282  }
283 
284  if (!foundVtx)
285  return;
286 
287  this->SetParticleParameters(vtxPosition, CartesianVector(0.f, 0.f, 0.f), pDaughterPfo);
288 }
289 
290 //------------------------------------------------------------------------------------------------------------------------------------------
291 
293  const CartesianVector &vtxPosition, const CartesianVector &vtxDirection, const ParticleFlowObject *const pPfo) const
294 {
295  if (!pPfo->GetVertexList().empty())
296  throw StatusCodeException(STATUS_CODE_FAILURE);
297 
298  PandoraContentApi::ParticleFlowObject::Metadata metadata;
299  metadata.m_momentum = vtxDirection;
300  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pPfo, metadata));
301 
302  const VertexList *pVertexList = NULL;
303  std::string vertexListName;
304  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, vertexListName));
305 
306  PandoraContentApi::Vertex::Parameters parameters;
307  parameters.m_position = vtxPosition;
308  parameters.m_vertexLabel = VERTEX_INTERACTION;
309  parameters.m_vertexType = VERTEX_3D;
310 
311  const Vertex *pVertex(NULL);
312  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
313 
314  if (!pVertexList->empty())
315  {
316  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_vertexListName));
317  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo<Vertex>(*this, pPfo, pVertex));
318  }
319 }
320 
321 //------------------------------------------------------------------------------------------------------------------------------------------
322 
323 StatusCode NeutrinoDaughterVerticesAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
324 {
325  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NeutrinoPfoListName", m_neutrinoListName));
326 
327  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_vertexListName));
328 
329  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
330  XmlHelper::ReadValue(xmlHandle, "UseParentForShowerVertex", m_useParentShowerVertex));
331 
332  PANDORA_RETURN_RESULT_IF_AND_IF(
333  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
334 
335  return STATUS_CODE_SUCCESS;
336 }
337 
338 } // 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.
std::string string
Definition: nybbler.cc:12
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.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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 int max(int a, int b)
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) ...
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
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:182
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
QTextStream & endl(QTextStream &s)
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.