LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
TrackShowerIdFeatureTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
11 
18 
21 
24 
25 using namespace pandora;
26 
27 namespace lar_content
28 {
29 
30 TwoDShowerFitFeatureTool::TwoDShowerFitFeatureTool() :
31  m_slidingShowerFitWindow(3),
32  m_slidingLinearFitWindow(10000)
33 {
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
38 void TwoDShowerFitFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
39  const pandora::Cluster *const pCluster)
40 {
41  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
42  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
43 
44  float ratio(-1.f);
45  try
46  {
47  const TwoDSlidingFitResult slidingFitResultLarge(pCluster, m_slidingLinearFitWindow, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
48  const float straightLineLength = (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
49  if (straightLineLength > std::numeric_limits<float>::epsilon())
50  ratio = (CutClusterCharacterisationAlgorithm::GetShowerFitWidth(pAlgorithm, pCluster, m_slidingShowerFitWindow))/straightLineLength;
51  }
52  catch (const StatusCodeException &)
53  {
54  ratio = -1.f;
55  }
56  featureVector.push_back(ratio);
57 
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 
62 StatusCode TwoDShowerFitFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
63 {
64  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
65  "SlidingShowerFitWindow", m_slidingShowerFitWindow));
66 
67  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
68  "SlidingLinearFitWindow", m_slidingLinearFitWindow));
69 
70  return STATUS_CODE_SUCCESS;
71 }
72 
73 //------------------------------------------------------------------------------------------------------------------------------------------
74 //------------------------------------------------------------------------------------------------------------------------------------------
75 
78  m_slidingLinearFitWindowLarge(10000)
79 {
80 }
81 
82 //------------------------------------------------------------------------------------------------------------------------------------------
83 
84 void TwoDLinearFitFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
85 const pandora::Cluster * const pCluster)
86 {
87  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
88  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
89 
90  float dTdLWidth(-1.f), straightLineLengthLarge(-1.f), diffWithStraightLineMean(-1.f), diffWithStraightLineSigma(-1.f), maxFitGapLength(-1.f), rmsSlidingLinearFit(-1.f);
91  this->CalculateVariablesSlidingLinearFit(pCluster, straightLineLengthLarge, diffWithStraightLineMean, diffWithStraightLineSigma, dTdLWidth, maxFitGapLength, rmsSlidingLinearFit);
92 
93  if (straightLineLengthLarge > std::numeric_limits<float>::epsilon())
94  {
95  diffWithStraightLineMean /= straightLineLengthLarge;
96  diffWithStraightLineSigma /= straightLineLengthLarge;
97  dTdLWidth /= straightLineLengthLarge;
98  maxFitGapLength /= straightLineLengthLarge;
99  rmsSlidingLinearFit /= straightLineLengthLarge;
100  }
101 
102  featureVector.push_back(straightLineLengthLarge);
103  featureVector.push_back(diffWithStraightLineMean);
104  featureVector.push_back(diffWithStraightLineSigma);
105  featureVector.push_back(dTdLWidth);
106  featureVector.push_back(maxFitGapLength);
107  featureVector.push_back(rmsSlidingLinearFit);
108 }
109 
110 //------------------------------------------------------------------------------------------------------------------------------------------
111 
112 void TwoDLinearFitFeatureTool::CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge,
113  float &diffWithStraightLineMean, float &diffWithStraightLineSigma, float &dTdLWidth, float &maxFitGapLength, float &rmsSlidingLinearFit) const
114 {
115  try
116  {
117  const TwoDSlidingFitResult slidingFitResult(pCluster, m_slidingLinearFitWindow, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
118  const TwoDSlidingFitResult slidingFitResultLarge(pCluster, m_slidingLinearFitWindowLarge, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
119 
120  if (slidingFitResult.GetLayerFitResultMap().empty())
121  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
122 
123  straightLineLengthLarge = (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
124  rmsSlidingLinearFit = 0.f;
125 
126  FloatVector diffWithStraightLineVector;
127  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
128  CartesianVector previousFitPosition(slidingFitResult.GetGlobalMinLayerPosition());
130 
131  for (const auto &mapEntry : slidingFitResult.GetLayerFitResultMap())
132  {
133  const LayerFitResult &layerFitResult(mapEntry.second);
134  rmsSlidingLinearFit += layerFitResult.GetRms();
135 
136  CartesianVector thisFitPosition(0.f, 0.f, 0.f);
137  slidingFitResult.GetGlobalPosition(layerFitResult.GetL(), layerFitResult.GetFitT(), thisFitPosition);
138 
139  LayerFitResultMap::const_iterator iterLarge = slidingFitResultLarge.GetLayerFitResultMap().find(slidingFitResultLarge.GetLayer(layerFitResult.GetL()));
140 
141  if (slidingFitResultLarge.GetLayerFitResultMap().end() == iterLarge)
142  throw StatusCodeException(STATUS_CODE_FAILURE);
143 
144  diffWithStraightLineVector.push_back(static_cast<float>(std::fabs(layerFitResult.GetFitT() - iterLarge->second.GetFitT())));
145 
146  const float thisGapLength((thisFitPosition - previousFitPosition).GetMagnitude());
147  const float minZ(std::min(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
148  const float maxZ(std::max(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
149 
150  if ((maxZ - minZ) > std::numeric_limits<float>::epsilon())
151  {
152  const float gapZ(LArGeometryHelper::CalculateGapDeltaZ(this->GetPandora(), minZ, maxZ, hitType));
153  const float correctedGapLength(thisGapLength * (1.f - gapZ / (maxZ - minZ)));
154 
155  if (correctedGapLength > maxFitGapLength)
156  maxFitGapLength = correctedGapLength;
157  }
158 
159  dTdLMin = std::min(dTdLMin, static_cast<float>(layerFitResult.GetGradient()));
160  dTdLMax = std::max(dTdLMax, static_cast<float>(layerFitResult.GetGradient()));
161  previousFitPosition = thisFitPosition;
162  }
163 
164  if (diffWithStraightLineVector.empty())
165  throw StatusCodeException(STATUS_CODE_FAILURE);
166 
167  diffWithStraightLineMean = 0.f;
168  diffWithStraightLineSigma = 0.f;
169 
170  for (const float diffWithStraightLine : diffWithStraightLineVector)
171  diffWithStraightLineMean += diffWithStraightLine;
172 
173  diffWithStraightLineMean /= static_cast<float>(diffWithStraightLineVector.size());
174 
175  for (const float diffWithStraightLine : diffWithStraightLineVector)
176  diffWithStraightLineSigma += (diffWithStraightLine - diffWithStraightLineMean) * (diffWithStraightLine - diffWithStraightLineMean);
177 
178  if (diffWithStraightLineSigma < 0.f)
179  throw StatusCodeException(STATUS_CODE_FAILURE);
180 
181  diffWithStraightLineSigma = std::sqrt(diffWithStraightLineSigma / static_cast<float>(diffWithStraightLineVector.size()));
182  dTdLWidth = dTdLMax - dTdLMin;
183  }
184  catch (const StatusCodeException &)
185  {
186  straightLineLengthLarge = -1.f;
187  diffWithStraightLineMean = -1.f;
188  diffWithStraightLineSigma = -1.f;
189  dTdLWidth = -1.f;
190  maxFitGapLength = -1.f;
191  rmsSlidingLinearFit = -1.f;
192  }
193 }
194 
195 //------------------------------------------------------------------------------------------------------------------------------------------
196 
197 StatusCode TwoDLinearFitFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
198 {
199  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
200  "SlidingLinearFitWindow", m_slidingLinearFitWindow));
201 
202  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
203  "SlidingLinearFitWindowLarge", m_slidingLinearFitWindowLarge));
204 
205  return STATUS_CODE_SUCCESS;
206 }
207 
208 //------------------------------------------------------------------------------------------------------------------------------------------
209 //------------------------------------------------------------------------------------------------------------------------------------------
210 
213 {
214 }
215 
216 //------------------------------------------------------------------------------------------------------------------------------------------
217 
218 void TwoDVertexDistanceFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
219  const pandora::Cluster *const pCluster)
220 {
221  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
222  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
223 
224  float straightLineLength(-1.f), ratio(-1.f);
225  try
226  {
227  const TwoDSlidingFitResult slidingFitResultLarge(pCluster, m_slidingLinearFitWindow, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
228  straightLineLength = (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
229  if (straightLineLength > std::numeric_limits<float>::epsilon())
230  ratio = (CutClusterCharacterisationAlgorithm::GetVertexDistance(pAlgorithm, pCluster))/straightLineLength;
231  }
232  catch (const StatusCodeException &)
233  {
234  ratio = -1.f;
235  }
236  featureVector.push_back(ratio);
237 }
238 
239 //------------------------------------------------------------------------------------------------------------------------------------------
240 
241 StatusCode TwoDVertexDistanceFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
242 {
243 
244  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
245  "SlidingLinearFitWindow", m_slidingLinearFitWindow));
246 
247  return STATUS_CODE_SUCCESS;
248 }
249 
250 //------------------------------------------------------------------------------------------------------------------------------------------
251 //------------------------------------------------------------------------------------------------------------------------------------------
252 
255  m_slidingLinearFitWindowLarge(10000)
256 {
257 }
258 
259 //------------------------------------------------------------------------------------------------------------------------------------------
260 
261 void ThreeDLinearFitFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
262 const pandora::ParticleFlowObject *const pInputPfo)
263 {
264  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
265  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
266 
267  ClusterList clusterList;
268  LArPfoHelper::GetTwoDClusterList(pInputPfo, clusterList);
269  float diffWithStraightLineMean(0.f), maxFitGapLength(0.f), rmsSlidingLinearFit(0.f);
270  LArMvaHelper::MvaFeature length, diff, gap, rms;
271  unsigned int nClustersUsed(0);
272 
273  for (const Cluster *const pCluster : clusterList)
274  {
275  float straightLineLengthLargeCluster(-1.f), diffWithStraightLineMeanCluster(-1.f), maxFitGapLengthCluster(-1.f), rmsSlidingLinearFitCluster(-1.f);
276 
277  this->CalculateVariablesSlidingLinearFit(pCluster, straightLineLengthLargeCluster, diffWithStraightLineMeanCluster, maxFitGapLengthCluster, rmsSlidingLinearFitCluster);
278 
279  if (straightLineLengthLargeCluster > std::numeric_limits<float>::epsilon())
280  {
281  diffWithStraightLineMeanCluster /= straightLineLengthLargeCluster;
282  maxFitGapLengthCluster /= straightLineLengthLargeCluster;
283  rmsSlidingLinearFitCluster /= straightLineLengthLargeCluster;
284 
285  diffWithStraightLineMean += diffWithStraightLineMeanCluster;
286  maxFitGapLength += maxFitGapLengthCluster;
287  rmsSlidingLinearFit += rmsSlidingLinearFitCluster;
288 
289  ++nClustersUsed;
290  }
291  }
292 
293  if (nClustersUsed > 0)
294  {
295  const float nClusters(static_cast<float>(nClustersUsed));
296  length = std::sqrt(LArPfoHelper::GetThreeDLengthSquared(pInputPfo));
297  diff = diffWithStraightLineMean / nClusters;
298  gap = maxFitGapLength / nClusters;
299  rms = rmsSlidingLinearFit / nClusters;
300  }
301 
302  featureVector.push_back(length);
303  featureVector.push_back(diff);
304  featureVector.push_back(gap);
305  featureVector.push_back(rms);
306 }
307 
308 //------------------------------------------------------------------------------------------------------------------------------------------
309 
310 void ThreeDLinearFitFeatureTool::CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge,
311  float &diffWithStraightLineMean, float &maxFitGapLength, float &rmsSlidingLinearFit) const
312 {
313  try
314  {
315  const TwoDSlidingFitResult slidingFitResult(pCluster, m_slidingLinearFitWindow, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
316  const TwoDSlidingFitResult slidingFitResultLarge(pCluster, m_slidingLinearFitWindowLarge, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
317 
318  if (slidingFitResult.GetLayerFitResultMap().empty())
319  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
320 
321  straightLineLengthLarge = (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
322  rmsSlidingLinearFit = 0.f;
323 
324  FloatVector diffWithStraightLineVector;
325  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
326  CartesianVector previousFitPosition(slidingFitResult.GetGlobalMinLayerPosition());
328 
329  for (const auto &mapEntry : slidingFitResult.GetLayerFitResultMap())
330  {
331  const LayerFitResult &layerFitResult(mapEntry.second);
332  rmsSlidingLinearFit += layerFitResult.GetRms();
333 
334  CartesianVector thisFitPosition(0.f, 0.f, 0.f);
335  slidingFitResult.GetGlobalPosition(layerFitResult.GetL(), layerFitResult.GetFitT(), thisFitPosition);
336 
337  LayerFitResultMap::const_iterator iterLarge = slidingFitResultLarge.GetLayerFitResultMap().find(slidingFitResultLarge.GetLayer(layerFitResult.GetL()));
338 
339  if (slidingFitResultLarge.GetLayerFitResultMap().end() == iterLarge)
340  throw StatusCodeException(STATUS_CODE_FAILURE);
341 
342  diffWithStraightLineVector.push_back(static_cast<float>(std::fabs(layerFitResult.GetFitT() - iterLarge->second.GetFitT())));
343 
344  const float thisGapLength((thisFitPosition - previousFitPosition).GetMagnitude());
345  const float minZ(std::min(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
346  const float maxZ(std::max(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
347 
348  if ((maxZ - minZ) > std::numeric_limits<float>::epsilon())
349  {
350  const float gapZ(LArGeometryHelper::CalculateGapDeltaZ(this->GetPandora(), minZ, maxZ, hitType));
351  const float correctedGapLength(thisGapLength * (1.f - gapZ / (maxZ - minZ)));
352 
353  if (correctedGapLength > maxFitGapLength)
354  maxFitGapLength = correctedGapLength;
355  }
356  else
357  {
358  maxFitGapLength = 0.f;
359  }
360 
361  dTdLMin = std::min(dTdLMin, static_cast<float>(layerFitResult.GetGradient()));
362  dTdLMax = std::max(dTdLMax, static_cast<float>(layerFitResult.GetGradient()));
363  previousFitPosition = thisFitPosition;
364  }
365 
366  if (diffWithStraightLineVector.empty())
367  throw StatusCodeException(STATUS_CODE_FAILURE);
368 
369  diffWithStraightLineMean = 0.f;
370 
371  for (const float diffWithStraightLine : diffWithStraightLineVector)
372  diffWithStraightLineMean += diffWithStraightLine;
373 
374  diffWithStraightLineMean /= static_cast<float>(diffWithStraightLineVector.size());
375 
376  }
377  catch (const StatusCodeException &)
378  {
379  straightLineLengthLarge = -1.f;
380  diffWithStraightLineMean = -1.f;
381  maxFitGapLength = -1.f;
382  rmsSlidingLinearFit = -1.f;
383  }
384 }
385 
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
388 StatusCode ThreeDLinearFitFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
389 {
390  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
391  "SlidingLinearFitWindow", m_slidingLinearFitWindow));
392 
393  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
394  "SlidingLinearFitWindowLarge", m_slidingLinearFitWindowLarge));
395 
396  return STATUS_CODE_SUCCESS;
397 }
398 
399 //------------------------------------------------------------------------------------------------------------------------------------------
400 //------------------------------------------------------------------------------------------------------------------------------------------
401 
403 {
404 }
405 
406 //------------------------------------------------------------------------------------------------------------------------------------------
407 
408 void ThreeDVertexDistanceFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
409  const pandora::ParticleFlowObject *const pInputPfo)
410 {
411  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
412  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
413 
414  LArMvaHelper::MvaFeature vertexDistance;
415  const VertexList *pVertexList(nullptr);
416  (void) PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
417 
418  if ((!pVertexList->empty()) && (pVertexList->size() == 1) && (VERTEX_3D == pVertexList->front()->GetVertexType()))
419  {
420  try
421  {
422  vertexDistance = (pVertexList->front()->GetPosition() - LArPfoHelper::GetVertex(pInputPfo)->GetPosition()).GetMagnitude();
423  }
424  catch (const StatusCodeException &) {}
425  }
426 
427  featureVector.push_back(vertexDistance);
428 }
429 
430 //------------------------------------------------------------------------------------------------------------------------------------------
431 
432 StatusCode ThreeDVertexDistanceFeatureTool::ReadSettings(const TiXmlHandle /*xmlHandle*/)
433 {
434 
435  return STATUS_CODE_SUCCESS;
436 }
437 
438 //------------------------------------------------------------------------------------------------------------------------------------------
439 //------------------------------------------------------------------------------------------------------------------------------------------
440 
442 {
443 }
444 
445 //------------------------------------------------------------------------------------------------------------------------------------------
446 
447 void ThreeDOpeningAngleFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
448  const pandora::ParticleFlowObject *const pInputPfo)
449 {
450  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
451  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
452 
453  // Need the 3D clusters and hits to calculate PCA components
454  ClusterList threeDClusterList;
455  LArPfoHelper::GetThreeDClusterList(pInputPfo, threeDClusterList);
456 
457  CaloHitList threeDCaloHitList;
458  LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, threeDCaloHitList);
459 
460  LArMvaHelper::MvaFeature diffAngle;
461  if (!threeDCaloHitList.empty())
462  {
463  CartesianPointVector pointVectorStart, pointVectorEnd;
464  this->Divide3DCaloHitList(pAlgorithm, threeDCaloHitList, pointVectorStart, pointVectorEnd);
465 
466  //able to calculate angles only if > 1 point provided
467  if ((pointVectorStart.size() > 1) && (pointVectorEnd.size() > 1))
468  {
469  try
470  {
471  // Run the PCA analysis twice
472  CartesianVector centroidStart(0.f, 0.f, 0.f), centroidEnd(0.f, 0.f, 0.f);
473  LArPcaHelper::EigenVectors eigenVecsStart, eigenVecsEnd;
474  LArPcaHelper::EigenValues eigenValuesStart(0.f, 0.f, 0.f), eigenValuesEnd(0.f, 0.f, 0.f);
475 
476  LArPcaHelper::RunPca(pointVectorStart, centroidStart, eigenValuesStart, eigenVecsStart);
477  LArPcaHelper::RunPca(pointVectorEnd, centroidEnd, eigenValuesEnd, eigenVecsEnd);
478 
479  const float openingAngle(this->OpeningAngle(eigenVecsStart.at(0), eigenVecsStart.at(1), eigenValuesStart));
480  const float closingAngle(this->OpeningAngle(eigenVecsEnd.at(0), eigenVecsEnd.at(1), eigenValuesEnd));
481  diffAngle = std::fabs(openingAngle-closingAngle);
482  }
483  catch (const StatusCodeException &){}
484  }
485  }
486 
487  featureVector.push_back(diffAngle);
488 }
489 
490 //------------------------------------------------------------------------------------------------------------------------------------------
491 
492 void ThreeDOpeningAngleFeatureTool::Divide3DCaloHitList(const Algorithm *const pAlgorithm, CaloHitList &threeDCaloHitList, CartesianPointVector &pointVectorStart, CartesianPointVector &pointVectorEnd)
493 {
494  const VertexList *pVertexList = nullptr;
495  (void) PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
496 
497  if ((!pVertexList->empty()) && (pVertexList->size() == 1) && (VERTEX_3D == pVertexList->front()->GetVertexType()))
498  {
499  const CartesianVector nuVertex(pVertexList->front()->GetPosition());
500  CaloHitVector threeDCaloHitVector(threeDCaloHitList.begin(), threeDCaloHitList.end());
501 
502  //order by distance to vertex, so first ones are closer to nuvertex
503  std::sort(threeDCaloHitVector.begin(), threeDCaloHitVector.end(), ThreeDChargeFeatureTool::VertexComparator(nuVertex));
504  CaloHitList orderedCaloHitList(threeDCaloHitVector.begin(),threeDCaloHitVector.end());
505  const unsigned int nhits(orderedCaloHitList.size());
506 
507  for (const CaloHit *const pCaloHit : orderedCaloHitList)
508  {
509  CartesianPointVector &targetVector((pointVectorStart.size() < (nhits / 2)) ? pointVectorStart : pointVectorEnd);
510  targetVector.push_back(pCaloHit->GetPositionVector());
511  }
512  }
513 }
514 
515 //------------------------------------------------------------------------------------------------------------------------------------------
516 
517 float ThreeDOpeningAngleFeatureTool::OpeningAngle(const CartesianVector &principal, const CartesianVector &secondary,
518  const CartesianVector &eigenValues) const
519 {
520  const float principalMagnitude(principal.GetMagnitude());
521  const float secondaryMagnitude(secondary.GetMagnitude());
522 
523  if (std::fabs(principalMagnitude) < std::numeric_limits<float>::epsilon())
524  {
525  std::cout << "PcaShowerParticleBuildingAlgorithm::OpeningAngle - The principal eigenvector is 0." << std::endl;
526  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
527  }
528  else if (std::fabs(secondaryMagnitude) < std::numeric_limits<float>::epsilon())
529  {
530  return 0.f;
531  }
532 
533  const float cosTheta(principal.GetDotProduct(secondary) / (principalMagnitude * secondaryMagnitude));
534 
535  if (cosTheta > 1.f)
536  {
537  std::cout << "PcaShowerParticleBuildingAlgorithm::OpeningAngle - cos(theta) reportedly greater than 1." << std::endl;
538  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
539  }
540 
541  const float sinTheta(std::sqrt(1.f - cosTheta * cosTheta));
542 
543  if (std::fabs(eigenValues.GetX()) < std::numeric_limits<float>::epsilon())
544  {
545  std::cout << "PcaShowerParticleBuildingAlgorithm::OpeningAngle - principal eigenvalue less than or equal to 0." << std::endl;
546  throw StatusCodeException( STATUS_CODE_INVALID_PARAMETER );
547  }
548  else if (std::fabs(eigenValues.GetY()) < std::numeric_limits<float>::epsilon())
549  {
550  return 0.f;
551  }
552 
553  return std::atan(std::sqrt(eigenValues.GetY()) * sinTheta / std::sqrt(eigenValues.GetX()));
554 }
555 //------------------------------------------------------------------------------------------------------------------------------------------
556 
557 StatusCode ThreeDOpeningAngleFeatureTool::ReadSettings(const TiXmlHandle /*xmlHandle*/)
558 {
559  return STATUS_CODE_SUCCESS;
560 }
561 
562 //------------------------------------------------------------------------------------------------------------------------------------------
563 //------------------------------------------------------------------------------------------------------------------------------------------
564 
566 {
567 }
568 
569 //------------------------------------------------------------------------------------------------------------------------------------------
570 
571 void ThreeDPCAFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
572  const pandora::ParticleFlowObject *const pInputPfo)
573 {
574  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
575  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
576 
577  LArMvaHelper::MvaFeature pca1, pca2;
578  // Need the 3D cluster and hits to calculate PCA components
579  ClusterList threeDClusterList;
580  LArPfoHelper::GetThreeDClusterList(pInputPfo, threeDClusterList);
581 
582  CaloHitList threeDCaloHitList;
583  LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, threeDCaloHitList);
584 
585 
586  if ((!threeDClusterList.empty()) && (!threeDCaloHitList.empty()))
587  {
588  // Run the PCA analysis
589  CartesianVector centroid(0.f, 0.f, 0.f);
590  LArPcaHelper::EigenVectors eigenVecs;
591  LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
592  try
593  {
594  LArPcaHelper::RunPca(threeDCaloHitList, centroid, eigenValues, eigenVecs);
595  const float principalEigenvalue(eigenValues.GetX()), secondaryEigenvalue(eigenValues.GetY()), tertiaryEigenvalue(eigenValues.GetZ());
596  if (principalEigenvalue > std::numeric_limits<float>::epsilon())
597  {
598  pca1 = secondaryEigenvalue/principalEigenvalue;
599  pca2 = tertiaryEigenvalue/principalEigenvalue;
600  }
601  }
602  catch (const StatusCodeException &){}
603  }
604 
605  featureVector.push_back(pca1);
606  featureVector.push_back(pca2);
607 }
608 
609 //------------------------------------------------------------------------------------------------------------------------------------------
610 
611 StatusCode ThreeDPCAFeatureTool::ReadSettings(const TiXmlHandle /*xmlHandle*/)
612 {
613  return STATUS_CODE_SUCCESS;
614 }
615 
616 //------------------------------------------------------------------------------------------------------------------------------------------
617 //------------------------------------------------------------------------------------------------------------------------------------------
618 
620  m_endChargeFraction(0.1f)
621 {
622 }
623 
624 //------------------------------------------------------------------------------------------------------------------------------------------
625 
626 void ThreeDChargeFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm,
627  const pandora::ParticleFlowObject *const pInputPfo)
628 {
629  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
630  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
631 
632  float totalCharge(-1.f), chargeSigma(-1.f), chargeMean(-1.f), endCharge(-1.f);
633  LArMvaHelper::MvaFeature charge1, charge2;
634 
635  ClusterList pClusterList;
636  LArPfoHelper::GetClusters(pInputPfo, TPC_VIEW_W, pClusterList);
637  if ((!pClusterList.empty()) && (pClusterList.size() == 1))
638  {
639  const Cluster *const pCluster(pClusterList.front());
640  this->CalculateChargeVariables(pAlgorithm, pCluster, totalCharge, chargeSigma, chargeMean, endCharge);
641  }
642 
643  if (chargeMean > std::numeric_limits<float>::epsilon())
644  charge1 = chargeSigma / chargeMean;
645 
646  if (totalCharge > std::numeric_limits<float>::epsilon())
647  charge2 = endCharge / totalCharge;
648 
649  featureVector.push_back(charge1);
650  featureVector.push_back(charge2);
651 }
652 
653 //------------------------------------------------------------------------------------------------------------------------------------------
654 
655 void ThreeDChargeFeatureTool::CalculateChargeVariables(const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, float &totalCharge,
656  float &chargeSigma, float &chargeMean, float &endCharge)
657 {
658 
659  CaloHitList orderedCaloHitList;
660  this->OrderCaloHitsByDistanceToVertex(pAlgorithm, pCluster, orderedCaloHitList);
661 
662  const int totalHits(pCluster->GetNCaloHits());
663  FloatVector chargeVector;
664  int hitCounter(0);
665  totalCharge = 0.f;
666  endCharge = 0.f;
667 
668  for (const CaloHit *const pCaloHit : orderedCaloHitList)
669  {
670  hitCounter++;
671  const float pCaloHitCharge(pCaloHit->GetInputEnergy());
672 
673  if (pCaloHitCharge < 0)
674  {
675  std::cout << "Found a hit with negative charge! " << std::endl;
676  }
677  else
678  {
679  totalCharge += pCaloHitCharge;
680  chargeVector.push_back(pCaloHitCharge);
681 
682  if (hitCounter >= std::floor(totalHits*(1.f-m_endChargeFraction)))
683  {
684  endCharge += pCaloHitCharge;
685  }
686  }
687  }
688 
689  if (!chargeVector.empty())
690  {
691  chargeMean = 0.f;
692  chargeSigma = 0.f;
693 
694  for (const float charge : chargeVector)
695  chargeMean += charge;
696 
697  chargeMean /= static_cast<float>(chargeVector.size());
698 
699  for (const float charge : chargeVector)
700  chargeSigma += (charge - chargeMean) * (charge - chargeMean);
701 
702  chargeSigma = std::sqrt(chargeSigma / static_cast<float>(chargeVector.size()));
703  }
704 }
705 
706 //------------------------------------------------------------------------------------------------------------------------------------------
707 
708 void ThreeDChargeFeatureTool::OrderCaloHitsByDistanceToVertex(const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, CaloHitList &caloHitList)
709 {
710  //find the neutrino vertex and sort hits by distance to vertex
711  const VertexList *pVertexList = nullptr;
712  (void) PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
713 
714  if ((!pVertexList->empty()) && (pVertexList->size() == 1) && (VERTEX_3D == pVertexList->front()->GetVertexType()))
715  {
716  const Vertex *const pVertex(pVertexList->front());
717  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
718 
719  const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(pAlgorithm->GetPandora(), pVertex->GetPosition(), hitType));
720 
721  CaloHitList clusterCaloHitList;
722  pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterCaloHitList);
723  CaloHitVector clusterCaloHitVector(clusterCaloHitList.begin(), clusterCaloHitList.end());
724 
725  //TODO: might give problems if vertex in the middle of the cluster ?
726  std::sort(clusterCaloHitVector.begin(), clusterCaloHitVector.end(), VertexComparator(vertexPosition2D));
727  caloHitList.insert(caloHitList.end(), clusterCaloHitVector.begin(), clusterCaloHitVector.end());
728  }
729 }
730 
731 //------------------------------------------------------------------------------------------------------------------------------------------
732 
733 StatusCode ThreeDChargeFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
734 {
735 
736  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
737  "EndChargeFraction", m_endChargeFraction));
738 
739  return STATUS_CODE_SUCCESS;
740 }
741 
742 //------------------------------------------------------------------------------------------------------------------------------------------
743 //------------------------------------------------------------------------------------------------------------------------------------------
744 
745 ThreeDChargeFeatureTool::VertexComparator::VertexComparator(const CartesianVector vertexPosition2D) :
746  m_neutrinoVertex(vertexPosition2D)
747 {
748 }
749 
750 //------------------------------------------------------------------------------------------------------------------------------------------
751 
752 bool ThreeDChargeFeatureTool::VertexComparator::operator()(const CaloHit *const left, const CaloHit *const right) const
753 {
754  float distanceL((left->GetPositionVector()-m_neutrinoVertex).GetMagnitudeSquared());
755  float distanceR((right->GetPositionVector()-m_neutrinoVertex).GetMagnitudeSquared());
756  return distanceL < distanceR;
757 }
758 
759 } // namespace lar_content
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void OrderCaloHitsByDistanceToVertex(const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, pandora::CaloHitList &caloHitList)
Function to order the calo hit list by distance to neutrino vertex.
Header file for the lar two dimensional sliding shower fit result class.
Header file for the pfo helper class.
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
Header file for the cut based cluster characterisation algorithm class.
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:58
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
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.
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
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:21
static float GetThreeDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 3D clusters.
static float CalculateGapDeltaZ(const pandora::Pandora &pandora, const float minZ, const float maxZ, const pandora::HitType hitType)
Calculate the total distance within a given 2D region that is composed of detector gaps...
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetVertexDistance(const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
Get the distance between the interaction vertex (if present in the current vertex list) and a provide...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
unsigned int m_slidingShowerFitWindow
The sliding shower fit window.
Header file for the principal curve analysis helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge, float &diffWithStraigthLineMean, float &maxFitGapLength, float &rmsSlidingLinearFit) const
Calculation of several variables related to sliding linear fit.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
Header file for the track shower id feature tools.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
Int_t max
Definition: plot.C:27
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
bool operator()(const pandora::CaloHit *const left, const pandora::CaloHit *const right) const
operator <
double GetFitT() const
Get the fitted t coordinate.
intermediate_table::const_iterator const_iterator
InitializedDouble class used to define mva features.
Header file for the lar monte carlo particle helper helper class.
unsigned int m_slidingLinearFitWindowLarge
The sliding linear fit window - should be large, providing a simple linear fit.
Header file for the cluster helper class.
float OpeningAngle(const pandora::CartesianVector &principal, const pandora::CartesianVector &secondary, const pandora::CartesianVector &eigenValues) const
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
Header file for the lar two dimensional sliding fit result class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
double GetGradient() const
Get the fitted gradient dt/dz.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
Header file for the vertex helper class.
VertexComparator class for comparison of two points wrt neutrino vertex position. ...
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
double GetRms() const
Get the rms of the fit residuals.
static void RunPca(const T &t, pandora::CartesianVector &centroid, EigenValues &outputEigenValues, EigenVectors &outputEigenVectors)
Run principal component analysis using input calo hits (TPC_VIEW_U,V,W or TPC_3D; all treated as 3D p...
VertexComparator(const pandora::CartesianVector vertexPosition2D)
Constructor.
Header file for the shower growing algorithm class.
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:22
Int_t min
Definition: plot.C:26
void GetGlobalPosition(const float rL, const float rT, pandora::CartesianVector &position) const
Get global coordinates for given sliding linear fit coordinates.
unsigned int m_slidingLinearFitWindowLarge
The sliding linear fit window - should be large, providing a simple linear fit.
void CalculateChargeVariables(const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, float &totalCharge, float &chargeSigma, float &chargeMean, float &endCharge)
Calculation of the charge variables.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_endChargeFraction
Fraction of hits that will be considered to calculate end charge (default 10%)
double GetL() const
Get the l coordinate.
static float GetShowerFitWidth(const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, const unsigned int showerFitWindow)
Get a measure of the width of a cluster, using a sliding shower fit result.
void Divide3DCaloHitList(const pandora::Algorithm *const pAlgorithm, pandora::CaloHitList &threeDCaloHitList, pandora::CartesianPointVector &pointVectorStart, pandora::CartesianPointVector &pointVectorEnd)
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
void CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge, float &diffWithStraigthLineMean, float &diffWithStraightLineSigma, float &dTdLWidth, float &maxFitGapLength, float &rmsSlidingLinearFit) const
Calculation of several variables related to sliding linear fit.
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.
std::list< Vertex > VertexList
Definition: DCEL.h:178
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)