Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
TrackShowerIdFeatureTool.cc
Go to the documentation of this file.
1
10#include "Pandora/StatusCodes.h"
11
16
18
21
22using namespace pandora;
23
24namespace lar_content
25{
26
27TwoDShowerFitFeatureTool::TwoDShowerFitFeatureTool() : m_slidingShowerFitWindow(3), m_slidingLinearFitWindow(10000)
28{
29}
30
31//------------------------------------------------------------------------------------------------------------------------------------------
32
33void TwoDShowerFitFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
34{
36 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
37
38 float ratio(-1.f);
39 try
40 {
42 const float straightLineLength =
43 (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
44 if (straightLineLength > std::numeric_limits<float>::epsilon())
45 ratio = (CutClusterCharacterisationAlgorithm::GetShowerFitWidth(pAlgorithm, pCluster, m_slidingShowerFitWindow)) / straightLineLength;
46 }
47 catch (const StatusCodeException &)
48 {
49 ratio = -1.f;
50 }
51 featureVector.push_back(ratio);
52}
53
54//------------------------------------------------------------------------------------------------------------------------------------------
55
56void TwoDShowerFitFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
57 const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
58{
59 LArMvaHelper::MvaFeatureVector toolFeatureVec;
60 this->Run(toolFeatureVec, pAlgorithm, pCluster);
61
62 if (featureMap.find(featureToolName + "_WidthLenRatio") != featureMap.end())
63 {
64 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
65 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
66 }
67
68 featureOrder.push_back(featureToolName + "_WidthLenRatio");
69 featureMap[featureToolName + "_WidthLenRatio"] = toolFeatureVec[0];
70}
71
72//------------------------------------------------------------------------------------------------------------------------------------------
73
75{
77 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingShowerFitWindow", m_slidingShowerFitWindow));
78
80 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindow", m_slidingLinearFitWindow));
81
82 return STATUS_CODE_SUCCESS;
83}
84
85//------------------------------------------------------------------------------------------------------------------------------------------
86//------------------------------------------------------------------------------------------------------------------------------------------
87
88TwoDLinearFitFeatureTool::TwoDLinearFitFeatureTool() : m_slidingLinearFitWindow(3), m_slidingLinearFitWindowLarge(10000)
89{
90}
91
92//------------------------------------------------------------------------------------------------------------------------------------------
93
94void TwoDLinearFitFeatureTool::Run(LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
95{
97 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
98
99 float dTdLWidth(-1.f), straightLineLengthLarge(-1.f), diffWithStraightLineMean(-1.f), diffWithStraightLineSigma(-1.f),
100 maxFitGapLength(-1.f), rmsSlidingLinearFit(-1.f);
101 this->CalculateVariablesSlidingLinearFit(pCluster, straightLineLengthLarge, diffWithStraightLineMean, diffWithStraightLineSigma,
102 dTdLWidth, maxFitGapLength, rmsSlidingLinearFit);
103
104 if (straightLineLengthLarge > std::numeric_limits<float>::epsilon())
105 {
106 diffWithStraightLineMean /= straightLineLengthLarge;
107 diffWithStraightLineSigma /= straightLineLengthLarge;
108 dTdLWidth /= straightLineLengthLarge;
109 maxFitGapLength /= straightLineLengthLarge;
110 rmsSlidingLinearFit /= straightLineLengthLarge;
111 }
112
113 featureVector.push_back(straightLineLengthLarge);
114 featureVector.push_back(diffWithStraightLineMean);
115 featureVector.push_back(diffWithStraightLineSigma);
116 featureVector.push_back(dTdLWidth);
117 featureVector.push_back(maxFitGapLength);
118 featureVector.push_back(rmsSlidingLinearFit);
119}
120
121//------------------------------------------------------------------------------------------------------------------------------------------
122
123void TwoDLinearFitFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
124 const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
125{
126 LArMvaHelper::MvaFeatureVector toolFeatureVec;
127 this->Run(toolFeatureVec, pAlgorithm, pCluster);
128
129 if (featureMap.find(featureToolName + "_StLineLenLarge") != featureMap.end() ||
130 featureMap.find(featureToolName + "_DiffStLineMean") != featureMap.end() ||
131 featureMap.find(featureToolName + "_DiffStLineSigma") != featureMap.end() ||
132 featureMap.find(featureToolName + "_dTdLWidth") != featureMap.end() ||
133 featureMap.find(featureToolName + "_MaxFitGapLen") != featureMap.end() ||
134 featureMap.find(featureToolName + "_rmsSlidingLinFit") != featureMap.end())
135 {
136 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
137 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
138 }
139
140 featureOrder.push_back(featureToolName + "_StLineLenLarge");
141 featureOrder.push_back(featureToolName + "_DiffStLineMean");
142 featureOrder.push_back(featureToolName + "_DiffStLineSigma");
143 featureOrder.push_back(featureToolName + "_dTdLWidth");
144 featureOrder.push_back(featureToolName + "_MaxFitGapLen");
145 featureOrder.push_back(featureToolName + "_rmsSlidingLinFit");
146
147 featureMap[featureToolName + "_StLineLenLarge"] = toolFeatureVec[0];
148 featureMap[featureToolName + "_DiffStLineMean"] = toolFeatureVec[1];
149 featureMap[featureToolName + "_DiffStLineSigma"] = toolFeatureVec[2];
150 featureMap[featureToolName + "_dTdLWidth"] = toolFeatureVec[3];
151 featureMap[featureToolName + "_MaxFitGapLen"] = toolFeatureVec[4];
152 featureMap[featureToolName + "_rmsSlidingLinFit"] = toolFeatureVec[5];
153}
154
155//------------------------------------------------------------------------------------------------------------------------------------------
156
157void TwoDLinearFitFeatureTool::CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge,
158 float &diffWithStraightLineMean, float &diffWithStraightLineSigma, float &dTdLWidth, float &maxFitGapLength, float &rmsSlidingLinearFit) const
159{
160 try
161 {
163 const TwoDSlidingFitResult slidingFitResultLarge(
165
166 if (slidingFitResult.GetLayerFitResultMap().empty())
167 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
168
169 straightLineLengthLarge =
170 (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
171 rmsSlidingLinearFit = 0.f;
172
173 FloatVector diffWithStraightLineVector;
174 const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
175 CartesianVector previousFitPosition(slidingFitResult.GetGlobalMinLayerPosition());
176 float dTdLMin(+std::numeric_limits<float>::max()), dTdLMax(-std::numeric_limits<float>::max());
177
178 for (const auto &mapEntry : slidingFitResult.GetLayerFitResultMap())
179 {
180 const LayerFitResult &layerFitResult(mapEntry.second);
181 rmsSlidingLinearFit += layerFitResult.GetRms();
182
183 CartesianVector thisFitPosition(0.f, 0.f, 0.f);
184 slidingFitResult.GetGlobalPosition(layerFitResult.GetL(), layerFitResult.GetFitT(), thisFitPosition);
185
186 LayerFitResultMap::const_iterator iterLarge =
187 slidingFitResultLarge.GetLayerFitResultMap().find(slidingFitResultLarge.GetLayer(layerFitResult.GetL()));
188
189 if (slidingFitResultLarge.GetLayerFitResultMap().end() == iterLarge)
190 throw StatusCodeException(STATUS_CODE_FAILURE);
191
192 diffWithStraightLineVector.push_back(static_cast<float>(std::fabs(layerFitResult.GetFitT() - iterLarge->second.GetFitT())));
193
194 const float thisGapLength((thisFitPosition - previousFitPosition).GetMagnitude());
195 const float minZ(std::min(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
196 const float maxZ(std::max(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
197
198 if ((maxZ - minZ) > std::numeric_limits<float>::epsilon())
199 {
200 const float gapZ(LArGeometryHelper::CalculateGapDeltaZ(this->GetPandora(), minZ, maxZ, hitType));
201 const float correctedGapLength(thisGapLength * (1.f - gapZ / (maxZ - minZ)));
202
203 if (correctedGapLength > maxFitGapLength)
204 maxFitGapLength = correctedGapLength;
205 }
206
207 dTdLMin = std::min(dTdLMin, static_cast<float>(layerFitResult.GetGradient()));
208 dTdLMax = std::max(dTdLMax, static_cast<float>(layerFitResult.GetGradient()));
209 previousFitPosition = thisFitPosition;
210 }
211
212 if (diffWithStraightLineVector.empty())
213 throw StatusCodeException(STATUS_CODE_FAILURE);
214
215 diffWithStraightLineMean = 0.f;
216 diffWithStraightLineSigma = 0.f;
217
218 for (const float diffWithStraightLine : diffWithStraightLineVector)
219 diffWithStraightLineMean += diffWithStraightLine;
220
221 diffWithStraightLineMean /= static_cast<float>(diffWithStraightLineVector.size());
222
223 for (const float diffWithStraightLine : diffWithStraightLineVector)
224 diffWithStraightLineSigma += (diffWithStraightLine - diffWithStraightLineMean) * (diffWithStraightLine - diffWithStraightLineMean);
225
226 if (diffWithStraightLineSigma < 0.f)
227 throw StatusCodeException(STATUS_CODE_FAILURE);
228
229 diffWithStraightLineSigma = std::sqrt(diffWithStraightLineSigma / static_cast<float>(diffWithStraightLineVector.size()));
230 dTdLWidth = dTdLMax - dTdLMin;
231 }
232 catch (const StatusCodeException &)
233 {
234 straightLineLengthLarge = -1.f;
235 diffWithStraightLineMean = -1.f;
236 diffWithStraightLineSigma = -1.f;
237 dTdLWidth = -1.f;
238 maxFitGapLength = -1.f;
239 rmsSlidingLinearFit = -1.f;
240 }
241}
242
243//------------------------------------------------------------------------------------------------------------------------------------------
244
246{
248 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindow", m_slidingLinearFitWindow));
249
250 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
251 XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindowLarge", m_slidingLinearFitWindowLarge));
252
253 return STATUS_CODE_SUCCESS;
254}
255
256//------------------------------------------------------------------------------------------------------------------------------------------
257//------------------------------------------------------------------------------------------------------------------------------------------
258
260{
261}
262
263//------------------------------------------------------------------------------------------------------------------------------------------
264
266 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
267{
269 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
270
271 float straightLineLength(-1.f), ratio(-1.f);
272 try
273 {
274 const TwoDSlidingFitResult slidingFitResultLarge(pCluster, m_slidingLinearFitWindow, LArGeometryHelper::GetWireZPitch(this->GetPandora()));
275 straightLineLength = (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
276 if (straightLineLength > std::numeric_limits<float>::epsilon())
277 ratio = (CutClusterCharacterisationAlgorithm::GetVertexDistance(pAlgorithm, pCluster)) / straightLineLength;
278 }
279 catch (const StatusCodeException &)
280 {
281 ratio = -1.f;
282 }
283 featureVector.push_back(ratio);
284}
285
286//------------------------------------------------------------------------------------------------------------------------------------------
287
289 const std::string &featureToolName, const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
290{
291 LArMvaHelper::MvaFeatureVector toolFeatureVec;
292 this->Run(toolFeatureVec, pAlgorithm, pCluster);
293
294 if (featureMap.find(featureToolName + "_DistLenRatio") != featureMap.end())
295 {
296 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
297 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
298 }
299
300 featureOrder.push_back(featureToolName + "_DistLenRatio");
301 featureMap[featureToolName + "_DistLenRatio"] = toolFeatureVec[0];
302}
303
304//------------------------------------------------------------------------------------------------------------------------------------------
305
307{
309 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindow", m_slidingLinearFitWindow));
310
311 return STATUS_CODE_SUCCESS;
312}
313
314//------------------------------------------------------------------------------------------------------------------------------------------
315//------------------------------------------------------------------------------------------------------------------------------------------
316
320
321//------------------------------------------------------------------------------------------------------------------------------------------
322
324 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
325{
327 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
328
329 CaloHitList parent3DHitList;
330 LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, parent3DHitList);
331 const unsigned int nParentHits3D(parent3DHitList.size());
332
333 PfoList allDaughtersPfoList;
334 LArPfoHelper::GetAllDownstreamPfos(pInputPfo, allDaughtersPfoList);
335 const unsigned int nDaughterPfos(allDaughtersPfoList.empty() ? 0 : allDaughtersPfoList.size() - 1);
336
337 unsigned int nDaughterHits3DTotal(0);
338
339 if (nDaughterPfos > 0)
340 {
341 // ATTN This relies on knowing that the first pfo in allDaughtersPfoList is the input pfo
342 allDaughtersPfoList.pop_front();
343
344 for (const ParticleFlowObject *const pDaughterPfo : allDaughtersPfoList)
345 {
346 CaloHitList daughter3DHitList;
347 LArPfoHelper::GetCaloHits(pDaughterPfo, TPC_3D, daughter3DHitList);
348 nDaughterHits3DTotal += daughter3DHitList.size();
349 }
350 }
351
352 const LArMvaHelper::MvaFeature nDaughters(static_cast<double>(nDaughterPfos));
353 const LArMvaHelper::MvaFeature nDaughterHits3D(static_cast<double>(nDaughterHits3DTotal));
354 const LArMvaHelper::MvaFeature daughterParentNHitsRatio(
355 (nParentHits3D > 0) ? static_cast<double>(nDaughterHits3DTotal) / static_cast<double>(nParentHits3D) : 0.);
356
357 featureVector.push_back(nDaughters);
358 featureVector.push_back(nDaughterHits3D);
359 featureVector.push_back(daughterParentNHitsRatio);
360}
361
362//------------------------------------------------------------------------------------------------------------------------------------------
363
364void PfoHierarchyFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
365 const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
366{
367 LArMvaHelper::MvaFeatureVector toolFeatureVec;
368 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
369
370 if (featureMap.find(featureToolName + "_NDaughters") != featureMap.end() ||
371 featureMap.find(featureToolName + "_NDaughterHits3D") != featureMap.end() ||
372 featureMap.find(featureToolName + "_DaughterParentHitRatio") != featureMap.end())
373 {
374 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
375 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
376 }
377
378 featureOrder.push_back(featureToolName + "_NDaughters");
379 featureOrder.push_back(featureToolName + "_NDaughterHits3D");
380 featureOrder.push_back(featureToolName + "_DaughterParentHitRatio");
381
382 featureMap[featureToolName + "_NDaughters"] = toolFeatureVec[0];
383 featureMap[featureToolName + "_NDaughterHits3D"] = toolFeatureVec[1];
384 featureMap[featureToolName + "_DaughterParentHitRatio"] = toolFeatureVec[2];
385}
386
387//------------------------------------------------------------------------------------------------------------------------------------------
388
390{
391 return STATUS_CODE_SUCCESS;
392}
393
394//------------------------------------------------------------------------------------------------------------------------------------------
395//------------------------------------------------------------------------------------------------------------------------------------------
396
398 m_conMinHits(3),
399 m_minCharge(0.1f),
400 m_conFracRange(0.2f),
401 m_MoliereRadius(10.1f),
402 m_MoliereRadiusFrac(0.2f)
403{
404}
405
406//------------------------------------------------------------------------------------------------------------------------------------------
407
409 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
410{
412 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
413
414 ClusterList clusterListW;
415 LArPfoHelper::GetClusters(pInputPfo, TPC_VIEW_W, clusterListW);
416
417 LArMvaHelper::MvaFeature haloTotalRatio, concentration, conicalness;
418
419 if (!clusterListW.empty())
420 {
421 CaloHitList clusterCaloHitList;
422 clusterListW.front()->GetOrderedCaloHitList().FillCaloHitList(clusterCaloHitList);
423
424 const CartesianVector &pfoStart(clusterCaloHitList.front()->GetPositionVector());
425 CartesianVector centroid(0.f, 0.f, 0.f);
427 LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
428 LArPcaHelper::RunPca(clusterCaloHitList, centroid, eigenValues, eigenVecs);
429
430 float chargeCore(0.f), chargeHalo(0.f), chargeCon(0.f);
431 this->CalculateChargeDistribution(clusterCaloHitList, pfoStart, eigenVecs[0], chargeCore, chargeHalo, chargeCon);
432 haloTotalRatio = (chargeCore + chargeHalo > std::numeric_limits<float>::epsilon()) ? chargeHalo / (chargeCore + chargeHalo) : -1.f;
433 concentration = (chargeCore + chargeHalo > std::numeric_limits<float>::epsilon()) ? chargeCon / (chargeCore + chargeHalo) : -1.f;
434 const float pfoLength(std::sqrt(LArPfoHelper::GetThreeDLengthSquared(pInputPfo)));
435 conicalness = (pfoLength > std::numeric_limits<float>::epsilon())
436 ? this->CalculateConicalness(clusterCaloHitList, pfoStart, eigenVecs[0], pfoLength)
437 : 1.f;
438 }
439
440 featureVector.push_back(haloTotalRatio);
441 featureVector.push_back(concentration);
442 featureVector.push_back(conicalness);
443}
444
445//------------------------------------------------------------------------------------------------------------------------------------------
446
447void ConeChargeFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
448 const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
449{
450 LArMvaHelper::MvaFeatureVector toolFeatureVec;
451 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
452
453 if (featureMap.find(featureToolName + "_HaloTotalRatio") != featureMap.end() ||
454 featureMap.find(featureToolName + "_Concentration") != featureMap.end() ||
455 featureMap.find(featureToolName + "_Conicalness") != featureMap.end())
456 {
457 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
458 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
459 }
460
461 featureOrder.push_back(featureToolName + "_HaloTotalRatio");
462 featureOrder.push_back(featureToolName + "_Concentration");
463 featureOrder.push_back(featureToolName + "_Conicalness");
464
465 featureMap[featureToolName + "_HaloTotalRatio"] = toolFeatureVec[0];
466 featureMap[featureToolName + "_Concentration"] = toolFeatureVec[1];
467 featureMap[featureToolName + "_Conicalness"] = toolFeatureVec[2];
468}
469
470//------------------------------------------------------------------------------------------------------------------------------------------
471
473 const CartesianVector &pfoDir, float &chargeCore, float &chargeHalo, float &chargeCon)
474{
475 for (const CaloHit *const pCaloHit : caloHitList)
476 {
477 const float distFromTrackFit(((pCaloHit->GetPositionVector() - pfoStart).GetCrossProduct(pfoDir)).GetMagnitude());
478
479 if (distFromTrackFit < m_MoliereRadiusFrac * m_MoliereRadius)
480 chargeCore += pCaloHit->GetInputEnergy();
481 else
482 chargeHalo += pCaloHit->GetInputEnergy();
483
484 chargeCon += pCaloHit->GetInputEnergy() / std::max(1.E-2f, distFromTrackFit); /* Set 1.E-2f to prevent division by 0 and to set max histogram bin as 100 */
485 }
486}
487
488//------------------------------------------------------------------------------------------------------------------------------------------
489
491 const CaloHitList &caloHitList, const CartesianVector &pfoStart, const CartesianVector &pfoDir, const float pfoLength)
492{
493 float totalChargeStart(0.f), totalChargeEnd(0.f);
494 float chargeConStart(0.f), chargeConEnd(0.f);
495 unsigned int nHitsConStart(0), nHitsConEnd(0);
496
497 for (const CaloHit *const pCaloHit : caloHitList)
498 {
499 const float distFromTrackFit(((pCaloHit->GetPositionVector() - pfoStart).GetCrossProduct(pfoDir)).GetMagnitude());
500 const float hitLength(std::fabs((pCaloHit->GetPositionVector() - pfoStart).GetDotProduct(pfoDir)));
501
502 if (hitLength / pfoLength < m_conFracRange)
503 {
504 chargeConStart += distFromTrackFit * distFromTrackFit * pCaloHit->GetInputEnergy();
505 ++nHitsConStart;
506 totalChargeStart += pCaloHit->GetInputEnergy();
507 }
508 else if (1.f - hitLength / pfoLength < m_conFracRange)
509 {
510 chargeConEnd += distFromTrackFit * distFromTrackFit * pCaloHit->GetInputEnergy();
511 ++nHitsConEnd;
512 totalChargeEnd += pCaloHit->GetInputEnergy();
513 }
514 }
515
516 float conicalness(1.f);
517
518 if (nHitsConStart >= m_conMinHits && nHitsConEnd >= m_conMinHits && totalChargeEnd > m_minCharge &&
519 std::sqrt(chargeConStart) > m_minCharge && totalChargeStart > m_minCharge)
520 conicalness = (std::sqrt(chargeConEnd / chargeConStart)) / (totalChargeEnd / totalChargeStart);
521
522 return conicalness;
523}
524
525//------------------------------------------------------------------------------------------------------------------------------------------
526
528{
529 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConMinHits", m_conMinHits));
530 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCharge", m_minCharge));
531 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConFracRange", m_conFracRange));
532 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MoliereRadius", m_MoliereRadius));
534 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MoliereRadiusFrac", m_MoliereRadiusFrac));
535
536 return STATUS_CODE_SUCCESS;
537}
538
539//------------------------------------------------------------------------------------------------------------------------------------------
540//------------------------------------------------------------------------------------------------------------------------------------------
541
542ThreeDLinearFitFeatureTool::ThreeDLinearFitFeatureTool() : m_slidingLinearFitWindow(3), m_slidingLinearFitWindowLarge(10000)
543{
544}
545
546//------------------------------------------------------------------------------------------------------------------------------------------
547
549 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
550{
552 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
553
554 ClusterList clusterList;
555 LArPfoHelper::GetTwoDClusterList(pInputPfo, clusterList);
556 float diffWithStraightLineMean(0.f), maxFitGapLength(0.f), rmsSlidingLinearFit(0.f);
557 LArMvaHelper::MvaFeature length, diff, gap, rms;
558 unsigned int nClustersUsed(0);
559
560 for (const Cluster *const pCluster : clusterList)
561 {
562 float straightLineLengthLargeCluster(-1.f), diffWithStraightLineMeanCluster(-1.f), maxFitGapLengthCluster(-1.f),
563 rmsSlidingLinearFitCluster(-1.f);
564
566 pCluster, straightLineLengthLargeCluster, diffWithStraightLineMeanCluster, maxFitGapLengthCluster, rmsSlidingLinearFitCluster);
567
568 if (straightLineLengthLargeCluster > std::numeric_limits<float>::epsilon())
569 {
570 diffWithStraightLineMeanCluster /= straightLineLengthLargeCluster;
571 maxFitGapLengthCluster /= straightLineLengthLargeCluster;
572 rmsSlidingLinearFitCluster /= straightLineLengthLargeCluster;
573
574 diffWithStraightLineMean += diffWithStraightLineMeanCluster;
575 maxFitGapLength += maxFitGapLengthCluster;
576 rmsSlidingLinearFit += rmsSlidingLinearFitCluster;
577
578 ++nClustersUsed;
579 }
580 }
581
582 if (nClustersUsed > 0)
583 {
584 const float nClusters(static_cast<float>(nClustersUsed));
585 length = std::sqrt(LArPfoHelper::GetThreeDLengthSquared(pInputPfo));
586 diff = diffWithStraightLineMean / nClusters;
587 gap = maxFitGapLength / nClusters;
588 rms = rmsSlidingLinearFit / nClusters;
589 }
590
591 featureVector.push_back(length);
592 featureVector.push_back(diff);
593 featureVector.push_back(gap);
594 featureVector.push_back(rms);
595}
596
597//------------------------------------------------------------------------------------------------------------------------------------------
598
600 const std::string &featureToolName, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
601{
602 LArMvaHelper::MvaFeatureVector toolFeatureVec;
603 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
604
605 if (featureMap.find(featureToolName + "_Length") != featureMap.end() ||
606 featureMap.find(featureToolName + "_DiffStraightLineMean") != featureMap.end() ||
607 featureMap.find(featureToolName + "_MaxFitGapLength") != featureMap.end() ||
608 featureMap.find(featureToolName + "_SlidingLinearFitRMS") != featureMap.end())
609 {
610 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
611 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
612 }
613
614 featureOrder.push_back(featureToolName + "_Length");
615 featureOrder.push_back(featureToolName + "_DiffStraightLineMean");
616 featureOrder.push_back(featureToolName + "_MaxFitGapLength");
617 featureOrder.push_back(featureToolName + "_SlidingLinearFitRMS");
618
619 featureMap[featureToolName + "_Length"] = toolFeatureVec[0];
620 featureMap[featureToolName + "_DiffStraightLineMean"] = toolFeatureVec[1];
621 featureMap[featureToolName + "_MaxFitGapLength"] = toolFeatureVec[2];
622 featureMap[featureToolName + "_SlidingLinearFitRMS"] = toolFeatureVec[3];
623}
624
625//------------------------------------------------------------------------------------------------------------------------------------------
626
627void ThreeDLinearFitFeatureTool::CalculateVariablesSlidingLinearFit(const pandora::Cluster *const pCluster, float &straightLineLengthLarge,
628 float &diffWithStraightLineMean, float &maxFitGapLength, float &rmsSlidingLinearFit) const
629{
630 try
631 {
633 const TwoDSlidingFitResult slidingFitResultLarge(
635
636 if (slidingFitResult.GetLayerFitResultMap().empty())
637 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
638
639 straightLineLengthLarge =
640 (slidingFitResultLarge.GetGlobalMaxLayerPosition() - slidingFitResultLarge.GetGlobalMinLayerPosition()).GetMagnitude();
641 rmsSlidingLinearFit = 0.f;
642
643 FloatVector diffWithStraightLineVector;
644 const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
645 CartesianVector previousFitPosition(slidingFitResult.GetGlobalMinLayerPosition());
646 float dTdLMin(+std::numeric_limits<float>::max()), dTdLMax(-std::numeric_limits<float>::max());
647
648 for (const auto &mapEntry : slidingFitResult.GetLayerFitResultMap())
649 {
650 const LayerFitResult &layerFitResult(mapEntry.second);
651 rmsSlidingLinearFit += layerFitResult.GetRms();
652
653 CartesianVector thisFitPosition(0.f, 0.f, 0.f);
654 slidingFitResult.GetGlobalPosition(layerFitResult.GetL(), layerFitResult.GetFitT(), thisFitPosition);
655
656 LayerFitResultMap::const_iterator iterLarge =
657 slidingFitResultLarge.GetLayerFitResultMap().find(slidingFitResultLarge.GetLayer(layerFitResult.GetL()));
658
659 if (slidingFitResultLarge.GetLayerFitResultMap().end() == iterLarge)
660 throw StatusCodeException(STATUS_CODE_FAILURE);
661
662 diffWithStraightLineVector.push_back(static_cast<float>(std::fabs(layerFitResult.GetFitT() - iterLarge->second.GetFitT())));
663
664 const float thisGapLength((thisFitPosition - previousFitPosition).GetMagnitude());
665 const float minZ(std::min(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
666 const float maxZ(std::max(thisFitPosition.GetZ(), previousFitPosition.GetZ()));
667
668 if ((maxZ - minZ) > std::numeric_limits<float>::epsilon())
669 {
670 const float gapZ(LArGeometryHelper::CalculateGapDeltaZ(this->GetPandora(), minZ, maxZ, hitType));
671 const float correctedGapLength(thisGapLength * (1.f - gapZ / (maxZ - minZ)));
672
673 if (correctedGapLength > maxFitGapLength)
674 maxFitGapLength = correctedGapLength;
675 }
676 else
677 {
678 maxFitGapLength = 0.f;
679 }
680
681 dTdLMin = std::min(dTdLMin, static_cast<float>(layerFitResult.GetGradient()));
682 dTdLMax = std::max(dTdLMax, static_cast<float>(layerFitResult.GetGradient()));
683 previousFitPosition = thisFitPosition;
684 }
685
686 if (diffWithStraightLineVector.empty())
687 throw StatusCodeException(STATUS_CODE_FAILURE);
688
689 diffWithStraightLineMean = 0.f;
690
691 for (const float diffWithStraightLine : diffWithStraightLineVector)
692 diffWithStraightLineMean += diffWithStraightLine;
693
694 diffWithStraightLineMean /= static_cast<float>(diffWithStraightLineVector.size());
695 }
696 catch (const StatusCodeException &)
697 {
698 straightLineLengthLarge = -1.f;
699 diffWithStraightLineMean = -1.f;
700 maxFitGapLength = -1.f;
701 rmsSlidingLinearFit = -1.f;
702 }
703}
704
705//------------------------------------------------------------------------------------------------------------------------------------------
706
708{
710 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindow", m_slidingLinearFitWindow));
711
712 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
713 XmlHelper::ReadValue(xmlHandle, "SlidingLinearFitWindowLarge", m_slidingLinearFitWindowLarge));
714
715 return STATUS_CODE_SUCCESS;
716}
717
718//------------------------------------------------------------------------------------------------------------------------------------------
719//------------------------------------------------------------------------------------------------------------------------------------------
720
724
725//------------------------------------------------------------------------------------------------------------------------------------------
726
728 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
729{
731 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
732
733 LArMvaHelper::MvaFeature vertexDistance;
734
735 const VertexList *pVertexList(nullptr);
736 (void)PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
737
738 if (!pVertexList || pVertexList->empty())
739 {
740 featureVector.push_back(vertexDistance);
741 return;
742 }
743
744 unsigned int nInteractionVertices(0);
745 const Vertex *pInteractionVertex(nullptr);
746
747 for (const Vertex *pVertex : *pVertexList)
748 {
749 if ((pVertex->GetVertexLabel() == VERTEX_INTERACTION) && (pVertex->GetVertexType() == VERTEX_3D))
750 {
751 ++nInteractionVertices;
752 pInteractionVertex = pVertex;
753 }
754 }
755
756 if (pInteractionVertex && (1 == nInteractionVertices))
757 {
758 try
759 {
760 vertexDistance = (pInteractionVertex->GetPosition() - LArPfoHelper::GetVertex(pInputPfo)->GetPosition()).GetMagnitude();
761 }
762 catch (const StatusCodeException &)
763 {
764 CaloHitList threeDCaloHitList;
765 LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, threeDCaloHitList);
766
767 if (!threeDCaloHitList.empty())
768 vertexDistance = (pInteractionVertex->GetPosition() - (threeDCaloHitList.front())->GetPositionVector()).GetMagnitude();
769 }
770 }
771
772 featureVector.push_back(vertexDistance);
773}
774
775//------------------------------------------------------------------------------------------------------------------------------------------
776
778 const std::string &featureToolName, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
779{
780 LArMvaHelper::MvaFeatureVector toolFeatureVec;
781 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
782
783 if (featureMap.find(featureToolName + "_VertexDistance") != featureMap.end())
784 {
785 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
786 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
787 }
788
789 featureOrder.push_back(featureToolName + "_VertexDistance");
790
791 featureMap[featureToolName + "_VertexDistance"] = toolFeatureVec[0];
792}
793
794//------------------------------------------------------------------------------------------------------------------------------------------
795
797{
798 return STATUS_CODE_SUCCESS;
799}
800
801//------------------------------------------------------------------------------------------------------------------------------------------
802//------------------------------------------------------------------------------------------------------------------------------------------
803
804ThreeDOpeningAngleFeatureTool::ThreeDOpeningAngleFeatureTool() : m_hitFraction(0.5f), m_defaultValue(0.1f)
805{
806}
807
808//------------------------------------------------------------------------------------------------------------------------------------------
809
811 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
812{
814 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
815
816 // Need the 3D hits to calculate PCA components
817 CaloHitList threeDCaloHitList;
818 LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, threeDCaloHitList);
819
820 LArMvaHelper::MvaFeature diffAngle;
821 if (!threeDCaloHitList.empty())
822 {
823 CartesianPointVector pointVectorStart, pointVectorEnd;
824 this->Divide3DCaloHitList(pAlgorithm, threeDCaloHitList, pointVectorStart, pointVectorEnd);
825
826 // Able to calculate angles only if > 1 point provided
827 if ((pointVectorStart.size() > 1) && (pointVectorEnd.size() > 1))
828 {
829 try
830 {
831 // Run the PCA analysis twice
832 CartesianVector centroidStart(0.f, 0.f, 0.f), centroidEnd(0.f, 0.f, 0.f);
833 LArPcaHelper::EigenVectors eigenVecsStart, eigenVecsEnd;
834 LArPcaHelper::EigenValues eigenValuesStart(0.f, 0.f, 0.f), eigenValuesEnd(0.f, 0.f, 0.f);
835
836 LArPcaHelper::RunPca(pointVectorStart, centroidStart, eigenValuesStart, eigenVecsStart);
837 LArPcaHelper::RunPca(pointVectorEnd, centroidEnd, eigenValuesEnd, eigenVecsEnd);
838
839 const float openingAngle(this->OpeningAngle(eigenVecsStart.at(0), eigenVecsStart.at(1), eigenValuesStart));
840 const float closingAngle(this->OpeningAngle(eigenVecsEnd.at(0), eigenVecsEnd.at(1), eigenValuesEnd));
841 diffAngle = std::fabs(openingAngle - closingAngle);
842 }
843 catch (const StatusCodeException &)
844 {
845 }
846 }
847 else
848 {
849 diffAngle = m_defaultValue;
850 }
851 }
852
853 featureVector.push_back(diffAngle);
854}
855
856//------------------------------------------------------------------------------------------------------------------------------------------
857
859 const std::string &featureToolName, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
860{
861 LArMvaHelper::MvaFeatureVector toolFeatureVec;
862 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
863
864 if (featureMap.find(featureToolName + "_AngleDiff") != featureMap.end())
865 {
866 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
867 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
868 }
869
870 featureOrder.push_back(featureToolName + "_AngleDiff");
871
872 featureMap[featureToolName + "_AngleDiff"] = toolFeatureVec[0];
873}
874
875//------------------------------------------------------------------------------------------------------------------------------------------
876
877void ThreeDOpeningAngleFeatureTool::Divide3DCaloHitList(const Algorithm *const pAlgorithm, const CaloHitList &threeDCaloHitList,
878 CartesianPointVector &pointVectorStart, CartesianPointVector &pointVectorEnd)
879{
880 const VertexList *pVertexList(nullptr);
881 (void)PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
882
883 if (threeDCaloHitList.empty() || !pVertexList || pVertexList->empty())
884 return;
885
886 unsigned int nInteractionVertices(0);
887 const Vertex *pInteractionVertex(nullptr);
888
889 for (const Vertex *pVertex : *pVertexList)
890 {
891 if ((pVertex->GetVertexLabel() == VERTEX_INTERACTION) && (pVertex->GetVertexType() == VERTEX_3D))
892 {
893 ++nInteractionVertices;
894 pInteractionVertex = pVertex;
895 }
896 }
897
898 if (pInteractionVertex && (1 == nInteractionVertices))
899 {
900 // Order by distance to vertex, so first ones are closer to nuvertex
901 CaloHitVector threeDCaloHitVector(threeDCaloHitList.begin(), threeDCaloHitList.end());
902 std::sort(threeDCaloHitVector.begin(), threeDCaloHitVector.end(),
904
905 unsigned int iHit(1);
906 const unsigned int nHits(threeDCaloHitVector.size());
907
908 for (const CaloHit *const pCaloHit : threeDCaloHitVector)
909 {
910 if (static_cast<float>(iHit) / static_cast<float>(nHits) <= m_hitFraction)
911 pointVectorStart.push_back(pCaloHit->GetPositionVector());
912
913 if (static_cast<float>(iHit) / static_cast<float>(nHits) >= 1.f - m_hitFraction)
914 pointVectorEnd.push_back(pCaloHit->GetPositionVector());
915
916 ++iHit;
917 }
918 }
919}
920
921//------------------------------------------------------------------------------------------------------------------------------------------
922
923float ThreeDOpeningAngleFeatureTool::OpeningAngle(const CartesianVector &principal, const CartesianVector &secondary, const CartesianVector &eigenValues) const
924{
925 const float principalMagnitude(principal.GetMagnitude());
926 const float secondaryMagnitude(secondary.GetMagnitude());
927
928 if (std::fabs(principalMagnitude) < std::numeric_limits<float>::epsilon())
929 {
930 std::cout << "ThreeDOpeningAngleFeatureTool::OpeningAngle - The principal eigenvector is 0." << std::endl;
931 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
932 }
933 else if (std::fabs(secondaryMagnitude) < std::numeric_limits<float>::epsilon())
934 {
935 return 0.f;
936 }
937
938 const float cosTheta(principal.GetDotProduct(secondary) / (principalMagnitude * secondaryMagnitude));
939
940 if (cosTheta > 1.f)
941 {
942 std::cout << "PcaShowerParticleBuildingAlgorithm::OpeningAngle - cos(theta) reportedly greater than 1." << std::endl;
943 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
944 }
945
946 const float sinTheta(std::sqrt(1.f - cosTheta * cosTheta));
947
948 if (eigenValues.GetX() < std::numeric_limits<float>::epsilon())
949 {
950 std::cout << "PcaShowerParticleBuildingAlgorithm::OpeningAngle - principal eigenvalue less than or equal to 0." << std::endl;
951 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
952 }
953 else if (eigenValues.GetY() < std::numeric_limits<float>::epsilon())
954 {
955 return 0.f;
956 }
957
958 return std::atan(std::sqrt(eigenValues.GetY()) * sinTheta / std::sqrt(eigenValues.GetX()));
959}
960
961//------------------------------------------------------------------------------------------------------------------------------------------
962
964{
965 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitFraction", m_hitFraction));
966
967 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DefaultValue", m_defaultValue));
968
969 return STATUS_CODE_SUCCESS;
970}
971
972//------------------------------------------------------------------------------------------------------------------------------------------
973//------------------------------------------------------------------------------------------------------------------------------------------
974
978
979//------------------------------------------------------------------------------------------------------------------------------------------
980
982 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
983{
985 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
986
987 LArMvaHelper::MvaFeature pca1, pca2;
988
989 // Need the 3D hits to calculate PCA components
990 CaloHitList threeDCaloHitList;
991 LArPfoHelper::GetCaloHits(pInputPfo, TPC_3D, threeDCaloHitList);
992
993 if (!threeDCaloHitList.empty())
994 {
995 try
996 {
997 CartesianVector centroid(0.f, 0.f, 0.f);
999 LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
1000
1001 LArPcaHelper::RunPca(threeDCaloHitList, centroid, eigenValues, eigenVecs);
1002 const float principalEigenvalue(eigenValues.GetX()), secondaryEigenvalue(eigenValues.GetY()), tertiaryEigenvalue(eigenValues.GetZ());
1003
1004 if (principalEigenvalue > std::numeric_limits<float>::epsilon())
1005 {
1006 pca1 = secondaryEigenvalue / principalEigenvalue;
1007 pca2 = tertiaryEigenvalue / principalEigenvalue;
1008 }
1009 else
1010 {
1011 // ATTN if n3dHits == 1 then principal, secondary, and tertiary eigenvalues are zero hence default to zero
1012 pca1 = 0.;
1013 pca2 = 0.;
1014 }
1015 }
1016 catch (const StatusCodeException &)
1017 {
1018 }
1019 }
1020
1021 featureVector.push_back(pca1);
1022 featureVector.push_back(pca2);
1023}
1024
1025//------------------------------------------------------------------------------------------------------------------------------------------
1026
1027void ThreeDPCAFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
1028 const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
1029{
1030 LArMvaHelper::MvaFeatureVector toolFeatureVec;
1031 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
1032
1033 if (featureMap.find(featureToolName + "_SecondaryPCARatio") != featureMap.end() ||
1034 featureMap.find(featureToolName + "_TertiaryPCARatio") != featureMap.end())
1035 {
1036 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
1037 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
1038 }
1039
1040 featureOrder.push_back(featureToolName + "_SecondaryPCARatio");
1041 featureOrder.push_back(featureToolName + "_TertiaryPCARatio");
1042
1043 featureMap[featureToolName + "_SecondaryPCARatio"] = toolFeatureVec[0];
1044 featureMap[featureToolName + "_TertiaryPCARatio"] = toolFeatureVec[1];
1045}
1046
1047//------------------------------------------------------------------------------------------------------------------------------------------
1048
1050{
1051 return STATUS_CODE_SUCCESS;
1052}
1053
1054//------------------------------------------------------------------------------------------------------------------------------------------
1055//------------------------------------------------------------------------------------------------------------------------------------------
1056
1058{
1059}
1060
1061//------------------------------------------------------------------------------------------------------------------------------------------
1062
1064 LArMvaHelper::MvaFeatureVector &featureVector, const Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
1065{
1067 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
1068
1069 float totalCharge(-1.f), chargeSigma(-1.f), chargeMean(-1.f), endCharge(-1.f);
1070 LArMvaHelper::MvaFeature charge1, charge2;
1071
1072 ClusterList clusterListW;
1073 LArPfoHelper::GetClusters(pInputPfo, TPC_VIEW_W, clusterListW);
1074
1075 if (!clusterListW.empty())
1076 this->CalculateChargeVariables(pAlgorithm, clusterListW.front(), totalCharge, chargeSigma, chargeMean, endCharge);
1077
1078 if (chargeMean > std::numeric_limits<float>::epsilon())
1079 charge1 = chargeSigma / chargeMean;
1080
1081 if (totalCharge > std::numeric_limits<float>::epsilon())
1082 charge2 = endCharge / totalCharge;
1083
1084 featureVector.push_back(charge1);
1085 featureVector.push_back(charge2);
1086}
1087
1088//------------------------------------------------------------------------------------------------------------------------------------------
1089
1090void ThreeDChargeFeatureTool::Run(LArMvaHelper::MvaFeatureMap &featureMap, StringVector &featureOrder, const std::string &featureToolName,
1091 const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
1092{
1093 LArMvaHelper::MvaFeatureVector toolFeatureVec;
1094 this->Run(toolFeatureVec, pAlgorithm, pInputPfo);
1095
1096 if (featureMap.find(featureToolName + "_FractionalSpread") != featureMap.end() ||
1097 featureMap.find(featureToolName + "_EndFraction") != featureMap.end())
1098 {
1099 std::cout << "Already wrote this feature into map! Not writing again." << std::endl;
1100 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
1101 }
1102
1103 featureOrder.push_back(featureToolName + "_FractionalSpread");
1104 featureOrder.push_back(featureToolName + "_EndFraction");
1105
1106 featureMap[featureToolName + "_FractionalSpread"] = toolFeatureVec[0];
1107 featureMap[featureToolName + "_EndFraction"] = toolFeatureVec[1];
1108}
1109
1110//------------------------------------------------------------------------------------------------------------------------------------------
1111
1112void ThreeDChargeFeatureTool::CalculateChargeVariables(const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster,
1113 float &totalCharge, float &chargeSigma, float &chargeMean, float &endCharge)
1114{
1115 totalCharge = 0.f;
1116 chargeSigma = 0.f;
1117 chargeMean = 0.f;
1118 endCharge = 0.f;
1119
1120 CaloHitList orderedCaloHitList;
1121 this->OrderCaloHitsByDistanceToVertex(pAlgorithm, pCluster, orderedCaloHitList);
1122
1123 FloatVector chargeVector;
1124 unsigned int hitCounter(0);
1125 const unsigned int nTotalHits(orderedCaloHitList.size());
1126
1127 for (const CaloHit *const pCaloHit : orderedCaloHitList)
1128 {
1129 ++hitCounter;
1130 const float pCaloHitCharge(pCaloHit->GetInputEnergy());
1131
1132 if (pCaloHitCharge >= 0.f)
1133 {
1134 totalCharge += pCaloHitCharge;
1135 chargeVector.push_back(pCaloHitCharge);
1136
1137 if (hitCounter >= std::floor(static_cast<float>(nTotalHits) * (1.f - m_endChargeFraction)))
1138 endCharge += pCaloHitCharge;
1139 }
1140 }
1141
1142 if (!chargeVector.empty())
1143 {
1144 chargeMean = totalCharge / static_cast<float>(chargeVector.size());
1145
1146 for (const float charge : chargeVector)
1147 chargeSigma += (charge - chargeMean) * (charge - chargeMean);
1148
1149 chargeSigma = std::sqrt(chargeSigma / static_cast<float>(chargeVector.size()));
1150 }
1151}
1152
1153//------------------------------------------------------------------------------------------------------------------------------------------
1154
1156 const Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster, CaloHitList &caloHitList)
1157{
1158 const VertexList *pVertexList(nullptr);
1159 (void)PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList);
1160
1161 if (!pVertexList || pVertexList->empty())
1162 return;
1163
1164 unsigned int nInteractionVertices(0);
1165 const Vertex *pInteractionVertex(nullptr);
1166
1167 for (const Vertex *pVertex : *pVertexList)
1168 {
1169 if ((pVertex->GetVertexLabel() == VERTEX_INTERACTION) && (pVertex->GetVertexType() == VERTEX_3D))
1170 {
1171 ++nInteractionVertices;
1172 pInteractionVertex = pVertex;
1173 }
1174 }
1175
1176 if (pInteractionVertex && (1 == nInteractionVertices))
1177 {
1178 const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
1179 const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(pAlgorithm->GetPandora(), pInteractionVertex->GetPosition(), hitType));
1180
1181 CaloHitList clusterCaloHitList;
1182 pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterCaloHitList);
1183
1184 clusterCaloHitList.sort(ThreeDChargeFeatureTool::VertexComparator(vertexPosition2D));
1185 caloHitList.insert(caloHitList.end(), clusterCaloHitList.begin(), clusterCaloHitList.end());
1186 }
1187}
1188
1189//------------------------------------------------------------------------------------------------------------------------------------------
1190
1192{
1194 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EndChargeFraction", m_endChargeFraction));
1195
1196 return STATUS_CODE_SUCCESS;
1197}
1198
1199//------------------------------------------------------------------------------------------------------------------------------------------
1200//------------------------------------------------------------------------------------------------------------------------------------------
1201
1202ThreeDChargeFeatureTool::VertexComparator::VertexComparator(const CartesianVector vertexPosition2D) : m_neutrinoVertex(vertexPosition2D)
1203{
1204}
1205
1206//------------------------------------------------------------------------------------------------------------------------------------------
1207
1208bool ThreeDChargeFeatureTool::VertexComparator::operator()(const CaloHit *const left, const CaloHit *const right) const
1209{
1210 const float distanceL((left->GetPositionVector() - m_neutrinoVertex).GetMagnitudeSquared());
1211 const float distanceR((right->GetPositionVector() - m_neutrinoVertex).GetMagnitudeSquared());
1212 return distanceL < distanceR;
1213}
1214
1215} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cut based cluster characterisation algorithm class.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the principal curve analysis helper class.
Header file for the pfo helper class.
Header file for the lar two dimensional sliding fit result class.
Header file defining status codes and relevant preprocessor macros.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
Header file for the track shower id feature tools.
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
unsigned int m_conMinHits
Configurable parameters to calculate cone charge variables.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
void CalculateChargeDistribution(const pandora::CaloHitList &caloHitList, const pandora::CartesianVector &pfoStart, const pandora::CartesianVector &pfoDir, float &chargeCore, float &chargeHalo, float &chargeCon)
Calculate charge distribution in relation to the Moeliere radius.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float CalculateConicalness(const pandora::CaloHitList &caloHitList, const pandora::CartesianVector &pfoStart, const pandora::CartesianVector &pfoDir, const float pfoLength)
Calculate conicalness as a ratio of charge distribution at the end and start of pfo.
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.
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::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
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.
MvaTypes::MvaFeatureVector MvaFeatureVector
MvaTypes::MvaFeatureMap MvaFeatureMap
std::vector< pandora::CartesianVector > EigenVectors
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...
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...
static float GetThreeDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 3D clusters.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
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 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.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
double GetFitT() const
Get the fitted t coordinate.
double GetGradient() const
Get the fitted gradient dt/dz.
double GetRms() const
Get the rms of the fit residuals.
double GetL() const
Get the l coordinate.
InitializedDouble class used to define mva features.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
VertexComparator class for comparison of two points wrt neutrino vertex position.
bool operator()(const pandora::CaloHit *const left, const pandora::CaloHit *const right) const
operator <
VertexComparator(const pandora::CartesianVector vertexPosition2D)
Constructor.
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.
float m_endChargeFraction
Fraction of hits that will be considered to calculate end charge (default 10%)
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.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
unsigned int m_slidingLinearFitWindowLarge
The sliding linear fit window - should be large, providing a simple linear fit.
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.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
float m_defaultValue
Default value to return, in case calculation not feasible.
void Divide3DCaloHitList(const pandora::Algorithm *const pAlgorithm, const pandora::CaloHitList &threeDCaloHitList, pandora::CartesianPointVector &pointVectorStart, pandora::CartesianPointVector &pointVectorEnd)
Obtain positions at the vertex and non-vertex end of a list of three dimensional calo hits.
float OpeningAngle(const pandora::CartesianVector &principal, const pandora::CartesianVector &secondary, const pandora::CartesianVector &eigenValues) const
Use the results of principal component analysis to calculate an opening angle.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
float m_hitFraction
Fraction of hits in start and end of pfo.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pInputPfo)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
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::Cluster *const pCluster)
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.
unsigned int m_slidingLinearFitWindowLarge
The sliding linear fit window - should be large, providing a simple linear fit.
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
unsigned int m_slidingShowerFitWindow
The sliding shower fit window.
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.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
void GetGlobalPosition(const float rL, const float rT, pandora::CartesianVector &position) const
Get global coordinates for given sliding linear fit coordinates.
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.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const pandora::Algorithm *const pAlgorithm, const pandora::Cluster *const pCluster)
unsigned int m_slidingLinearFitWindow
The sliding linear fit window.
Algorithm class. Algorithm addresses are held only by the algorithm manager. They have a fully define...
Definition Algorithm.h:21
CaloHit class.
Definition CaloHit.h:26
const CartesianVector & GetPositionVector() const
Get the position vector of center of calorimeter cell, units mm.
Definition CaloHit.h:350
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
float GetMagnitude() const
Get the magnitude.
float GetY() const
Get the cartesian y coordinate.
Cluster class.
Definition Cluster.h:31
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
void FillCaloHitList(CaloHitList &caloHitList) const
Fill a provided calo hit list with all the calo hits in the ordered calo hit list.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
const std::string & GetType() const
Get the type.
Definition Process.h:102
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
const std::string & GetInstanceName() const
Get the instance name.
Definition Process.h:109
StatusCodeException class.
Vertex class.
Definition Vertex.h:26
const CartesianVector & GetPosition() const
Get the vertex position.
Definition Vertex.h:103
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
HitType
Calorimeter hit type enum.
std::vector< const CaloHit * > CaloHitVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< std::string > StringVector
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
std::vector< float > FloatVector
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList