30 m_useTrainingMode(false),
31 m_selectNuanceCode(false),
32 m_nuance(-std::numeric_limits<int>::max()),
34 m_minCompleteness(0.9f),
35 m_minProbability(0.0f),
36 m_defaultProbability(0.0f),
38 m_persistFeatures(false),
39 m_filePathEnvironmentVariable(
"FW_SEARCH_PATH")
49 if (nuSliceHypotheses.size() != crSliceHypotheses.size())
52 const unsigned int nSlices(nuSliceHypotheses.size());
57 this->GetSliceFeatures(
this, nuSliceHypotheses, crSliceHypotheses, sliceFeaturesVector);
59 if (m_useTrainingMode)
62 this->SelectAllPfos(pAlgorithm, crSliceHypotheses, selectedPfos);
64 unsigned int bestSliceIndex(std::numeric_limits<unsigned int>::max());
65 if (!this->GetBestMCSliceIndex(pAlgorithm, nuSliceHypotheses, crSliceHypotheses, bestSliceIndex))
68 for (
unsigned int sliceIndex = 0; sliceIndex < nSlices; ++sliceIndex)
70 const SliceFeatures &features(sliceFeaturesVector.at(sliceIndex));
82 this->SelectPfosByProbability(pAlgorithm, nuSliceHypotheses, crSliceHypotheses, sliceFeaturesVector, selectedPfos);
91 for (
unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
92 sliceFeaturesVector.push_back(
SliceFeatures(nuSliceHypotheses.at(sliceIndex), crSliceHypotheses.at(sliceIndex), pTool));
99 const SliceHypotheses &crSliceHypotheses,
unsigned int &bestSliceIndex)
const
101 unsigned int nHitsInBestSlice(0), nNuHitsInBestSlice(0);
104 const CaloHitList *pAllReconstructedCaloHitList(
nullptr);
120 const int nuNHitsTotal(this->CountNeutrinoInducedHits(reconstructableCaloHitList));
121 const CaloHitSet reconstructableCaloHitSet(reconstructableCaloHitList.begin(), reconstructableCaloHitList.end());
123 for (
unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
126 this->Collect2DHits(crSliceHypotheses.at(sliceIndex), reconstructedCaloHitList, reconstructableCaloHitSet);
130 const PfoList &nuFinalStates(pNeutrino->GetDaughterPfoList());
131 this->Collect2DHits(nuFinalStates, reconstructedCaloHitList, reconstructableCaloHitSet);
134 const unsigned int nNuHits(this->CountNeutrinoInducedHits(reconstructedCaloHitList));
136 if (nNuHits > nNuHitsInBestSlice)
138 nNuHitsInBestSlice = nNuHits;
139 nHitsInBestSlice = reconstructedCaloHitList.size();
140 bestSliceIndex = sliceIndex;
145 const float purity(nHitsInBestSlice > 0 ?
static_cast<float>(nNuHitsInBestSlice) /
static_cast<float>(nHitsInBestSlice) : 0.f);
146 const float completeness(nuNHitsTotal > 0 ?
static_cast<float>(nNuHitsInBestSlice) /
static_cast<float>(nuNHitsTotal) : 0.f);
147 return this->PassesQualityCuts(pAlgorithm, purity, completeness);
155 if (purity < m_minPurity || completeness < m_minCompleteness)
157 if (m_selectNuanceCode && (this->GetNuanceCode(pAlgorithm) != m_nuance))
173 for (
const CaloHit *
const pCaloHit : collectedHits)
175 const CaloHit *
const pParentHit =
static_cast<const CaloHit *
>(pCaloHit->GetParentAddress());
176 if (!reconstructableCaloHitSet.count(pParentHit))
180 if (std::find(reconstructedCaloHitList.begin(), reconstructedCaloHitList.end(), pParentHit) == reconstructedCaloHitList.end())
181 reconstructedCaloHitList.push_back(pParentHit);
190 unsigned int nNuHits(0);
191 for (
const CaloHit *
const pCaloHit : caloHitList)
217 if (trueNeutrinos.size() != 1)
219 std::cout <<
"NeutrinoIdTool::GetNuanceCode - Error: number of true neutrinos in event must be exactly one" << std::endl;
231 for (
const PfoList &pfos : hypotheses)
236 metadata.m_propertiesToAdd[
"NuScore"] = -1.f;
240 this->SelectPfos(pfos, selectedPfos);
251 std::vector<UintFloatPair> sliceIndexProbabilityPairs;
252 for (
unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
254 const float nuProbability(sliceFeaturesVector.at(sliceIndex).GetNeutrinoProbability(m_mva, m_defaultProbability));
259 metadata.m_propertiesToAdd[
"NuScore"] = nuProbability;
261 if (m_persistFeatures && sliceFeaturesVector.at(sliceIndex).IsFeatureVectorAvailable())
264 sliceFeaturesVector.at(sliceIndex).GetFeatureMap(featureMap);
266 for (
auto const &[name, value] : featureMap)
267 metadata.m_propertiesToAdd[name] = value;
276 metadata.m_propertiesToAdd[
"NuScore"] = nuProbability;
278 if (m_persistFeatures && sliceFeaturesVector.at(sliceIndex).IsFeatureVectorAvailable())
281 sliceFeaturesVector.at(sliceIndex).GetFeatureMap(featureMap);
283 for (
auto const &[name, value] : featureMap)
284 metadata.m_propertiesToAdd[name] = value;
290 if (nuProbability < m_minProbability)
292 this->SelectPfos(crSliceHypotheses.at(sliceIndex), selectedPfos);
296 sliceIndexProbabilityPairs.push_back(
UintFloatPair(sliceIndex, nuProbability));
300 std::sort(sliceIndexProbabilityPairs.begin(), sliceIndexProbabilityPairs.end(),
304 unsigned int nNuSlices(0);
305 for (
const UintFloatPair &slice : sliceIndexProbabilityPairs)
307 if (nNuSlices < m_maxNeutrinos)
309 this->SelectPfos(nuSliceHypotheses.at(slice.first), selectedPfos);
314 this->SelectPfos(crSliceHypotheses.at(slice.first), selectedPfos);
323 selectedPfos.insert(selectedPfos.end(), pfos.begin(), pfos.end());
332 m_isAvailable(false),
343 unsigned int nuNHitsUsedTotal(0);
344 unsigned int nuNHitsTotal(0);
351 nuAllSpacePoints.insert(nuAllSpacePoints.end(), spacePoints.begin(), spacePoints.end());
352 nuNHitsTotal += spacePoints.size();
354 if (spacePoints.size() < 5)
358 nuWeightedDirTotal += dir *
static_cast<float>(spacePoints.size());
359 nuNHitsUsedTotal += spacePoints.size();
362 if (nuNHitsUsedTotal == 0)
364 const CartesianVector nuWeightedDir(nuWeightedDirTotal * (1.f /
static_cast<float>(nuNHitsUsedTotal)));
369 CartesianVector centroid(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
370 LArPcaHelper::EigenValues eigenValues(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
374 const float nuNFinalStatePfos(
static_cast<float>(nuFinalStates.size()));
375 const float nuVertexY(nuVertex.
GetY());
376 const float nuWeightedDirZ(nuWeightedDir.
GetZ());
377 const float nuNSpacePointsInSphere(
static_cast<float>(pointsInSphere.size()));
379 if (eigenValues.
GetX() <= std::numeric_limits<float>::epsilon())
381 const float nuEigenRatioInSphere(eigenValues.
GetY() / eigenValues.
GetX());
384 unsigned int nCRHitsMax(0);
385 unsigned int nCRHitsTotal(0);
386 float crLongestTrackDirY(std::numeric_limits<float>::max());
387 float crLongestTrackDeflection(-std::numeric_limits<float>::max());
394 nCRHitsTotal += spacePoints.size();
396 if (spacePoints.size() < 5)
399 if (spacePoints.size() > nCRHitsMax)
401 nCRHitsMax = spacePoints.size();
405 crLongestTrackDirY = upperDir.
GetY();
406 crLongestTrackDeflection = 1.f - upperDir.
GetDotProduct(lowerDir * (-1.f));
412 if (nCRHitsTotal == 0)
415 const float crFracHitsInLongestTrack =
static_cast<float>(nCRHitsMax) /
static_cast<float>(nCRHitsTotal);
433 m_featureMap[
"NuNSpacePointsInSphere"] = nuNSpacePointsInSphere;
434 m_featureMap[
"NuEigenRatioInSphere"] = nuEigenRatioInSphere;
435 m_featureMap[
"CRLongestTrackDirY"] = crLongestTrackDirY;
436 m_featureMap[
"CRLongestTrackDeflection"] = crLongestTrackDeflection;
437 m_featureMap[
"CRFracHitsInLongestTrack"] = crFracHitsInLongestTrack;
453 return m_isAvailable;
464 featureVector.insert(featureVector.end(), m_featureVector.begin(), m_featureVector.end());
475 featureMap.insert(m_featureMap.begin(), m_featureMap.end());
484 if (!this->IsFeatureVectorAvailable())
485 return defaultProbability;
488 this->GetFeatureVector(featureVector);
498 if (nuPfos.size() != 1)
501 return nuPfos.front();
512 if (clusters3D.size() > 1)
515 if (clusters3D.empty())
519 clusters3D.front()->GetOrderedCaloHitList().FillCaloHitList(caloHits);
521 for (
const CaloHit *
const pCaloHit : caloHits)
522 spacePoints.push_back(pCaloHit->GetPositionVector());
531 return ((pointA - vertex).GetMagnitude() < (pointB - vertex).GetMagnitude());
540 return this->GetDirection(
549 return this->GetDirection(
560 const LArTPC *
const pFirstLArTPC(m_pTool->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
569 const bool isMinStart(fShouldChooseA(endMin, endMax));
574 const bool shouldFlip((endPoint - startPoint).GetUnitVector().GetDotProduct(startDir) < 0.f);
575 return (shouldFlip ? startDir * (-1.f) : startDir);
586 if ((point - vertex).GetMagnitudeSquared() <= radius * radius)
587 spacePointsInSphere.push_back(point);
634 std::string mvaFileName;
638 m_mva.Initialize(fullMvaFileName, mvaName);
641 return STATUS_CODE_SUCCESS;
Header file for the file helper class.
Header file for the lar monte carlo particle helper helper class.
Header file for the principal curve analysis helper class.
Header file for the pfo helper class.
Header file for the lar three dimensional sliding fit result class.
Header file for the mc particle helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static std::string FindFileInPath(const std::string &unqualifiedFileName, const std::string &environmentVariable, const std::string &delimiter=":")
Find the fully-qualified file name by searching through a list of delimiter-separated paths in a name...
bool m_selectInputHits
whether to select input hits
float m_maxPhotonPropagation
the maximum photon propagation length
static bool IsNeutrino(const pandora::MCParticle *const pMCParticle)
Whether a mc particle is a neutrino or antineutrino.
static unsigned int GetNuanceCode(const pandora::MCParticle *const pMCParticle)
Get the nuance code of an MCParticle.
static const pandora::MCParticle * GetParentMCParticle(const pandora::MCParticle *const pMCParticle)
Get the parent mc particle.
static void SelectCaloHits(const pandora::CaloHitList *const pCaloHitList, const MCRelationMap &mcToTargetMCMap, pandora::CaloHitList &selectedCaloHitList, const bool selectInputHits, const float maxPhotonPropagation)
Select a subset of calo hits representing those that represent "reconstructable" regions of the event...
std::unordered_map< const pandora::MCParticle *, const pandora::MCParticle * > MCRelationMap
static void GetMCPrimaryMap(const pandora::MCParticleList *const pMCParticleList, MCRelationMap &mcPrimaryMap)
Get mapping from individual mc particles (in a provided list) and their primary parent mc particles.
static void GetTrueNeutrinos(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueNeutrinos)
Get neutrino MC particles from an input MC particle list.
MvaTypes::MvaFeatureVector MvaFeatureVector
static double CalculateProbability(const MvaInterface &classifier, TCONTAINER &&featureContainer)
Use the trained mva to calculate a classification probability for an example.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
std::map< std::string, double > DoubleMap
std::vector< pandora::CartesianVector > EigenVectors
static void RunPca(const T &t, pandora::CartesianVector ¢roid, 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 GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
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.
LArMvaHelper::DoubleMap m_featureMap
A map between MVA features and their names.
void GetSpacePoints(const pandora::ParticleFlowObject *const pPfo, pandora::CartesianPointVector &spacePoints) const
Get the 3D space points in a given pfo.
bool IsFeatureVectorAvailable() const
Check if all features were calculable.
pandora::CartesianVector GetDirectionFromVertex(const pandora::CartesianPointVector &spacePoints, const pandora::CartesianVector &vertex) const
Use a sliding fit to get the direction of a collection of spacepoint near a vertex position.
float GetNeutrinoProbability(const T &t, const float defaultProbability) const
Get the probability that this slice contains a neutrino interaction.
void GetFeatureMap(LArMvaHelper::DoubleMap &featureMap) const
Get the feature map for the MVA.
const pandora::ParticleFlowObject * GetNeutrino(const pandora::PfoList &nuPfos) const
Get the recontructed neutrino the input list of neutrino Pfos.
pandora::CartesianVector GetUpperDirection(const pandora::CartesianPointVector &spacePoints) const
Use a sliding fit to get the upper direction of a collection of spacepoints.
LArMvaHelper::MvaFeatureVector m_featureVector
The MVA feature vector.
void GetPointsInSphere(const pandora::CartesianPointVector &spacePoints, const pandora::CartesianVector &vertex, const float radius, pandora::CartesianPointVector &spacePointsInSphere) const
Get a vector of spacepoints within a given radius of a vertex point.
void GetFeatureVector(LArMvaHelper::MvaFeatureVector &featureVector) const
Get the feature vector for the MVA.
SliceFeatures(const pandora::PfoList &nuPfos, const pandora::PfoList &crPfos, const NeutrinoIdTool *const pTool)
Constructor.
pandora::CartesianVector GetDirection(const pandora::CartesianPointVector &spacePoints, std::function< bool(const pandora::CartesianVector &pointA, const pandora::CartesianVector &pointB)> fShouldChooseA) const
Use a sliding fit to get the direction of a collection of spacepoints.
bool m_isAvailable
Is the feature vector available.
pandora::CartesianVector GetLowerDirection(const pandora::CartesianPointVector &spacePoints) const
Use a sliding fit to get the lower direction of a collection of spacepoints.
void SelectAllPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &hypotheses, pandora::PfoList &selectedPfos) const
Select all pfos under the same hypothesis.
bool GetBestMCSliceIndex(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, unsigned int &bestSliceIndex) const
Get the slice with the most neutrino induced hits using Monte-Carlo information.
std::pair< unsigned int, float > UintFloatPair
bool m_useTrainingMode
Should use training mode. If true, training examples will be written to the output file.
void SelectPfosByProbability(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, const SliceFeaturesVector &sliceFeaturesVector, pandora::PfoList &selectedPfos) const
Select pfos based on the probability that their slice contains a neutrino interaction.
bool m_selectNuanceCode
Should select training events by nuance code.
float m_minPurity
Minimum purity of the best slice to use event for training.
NeutrinoIdTool()
Default constructor.
void Collect2DHits(const pandora::PfoList &pfos, pandora::CaloHitList &reconstructedCaloHitList, const pandora::CaloHitSet &reconstructableCaloHitSet) const
Collect all 2D hits in a supplied list of Pfos and push them on to an existing hit list,...
void GetSliceFeatures(const NeutrinoIdTool *const pTool, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, SliceFeaturesVector &sliceFeaturesVector) const
Get the features of each slice.
std::string m_filePathEnvironmentVariable
The environment variable providing a list of paths to mva files.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float m_minProbability
Minimum probability required to classify a slice as the neutrino.
bool PassesQualityCuts(const pandora::Algorithm *const pAlgorithm, const float purity, const float completeness) const
Determine if the event passes the selection cuts for training and has the required NUANCE code.
bool m_persistFeatures
If true, the mva features will be persisted in the metadata.
void SelectPfos(const pandora::PfoList &pfos, pandora::PfoList &selectedPfos) const
Add the given pfos to the selected Pfo list.
int m_nuance
Nuance code to select for training.
void SelectOutputPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, pandora::PfoList &selectedPfos)
Select which reconstruction hypotheses to use; neutrino outcomes or cosmic-ray muon outcomes for each...
unsigned int m_maxNeutrinos
The maximum number of neutrinos to select in any one event.
float m_minCompleteness
Minimum completeness of the best slice to use event for training.
std::vector< SliceFeatures > SliceFeaturesVector
float m_defaultProbability
Default probability set if score could not be calculated.
unsigned int CountNeutrinoInducedHits(const pandora::CaloHitList &caloHitList) const
Count the number of neutrino induced hits in a given list using MC information.
int GetNuanceCode(const pandora::Algorithm *const pAlgorithm) const
Use the current MCParticle list to get the nuance code of the neutrino in the event.
std::string m_trainingOutputFile
Output file name for training examples.
ThreeDSlidingFitResult class.
const pandora::CartesianVector & GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
const pandora::CartesianVector & GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
Algorithm class. Algorithm addresses are held only by the algorithm manager. They have a fully define...
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 GetY() const
Get the cartesian y coordinate.
float GetWirePitchW() const
Get the w wire pitch, units mm.
static const MCParticle * GetMainMCParticle(const T *const pT)
Find the mc particle making the largest contribution to a specified calo hit, track or cluster.
ParticleFlowObject class.
const PfoList & GetDaughterPfoList() const
Get the daughter pfo list.
StatusCode AlterMetadata(const object_creation::ParticleFlowObject::Metadata &metadata)
Alter particle flow object metadata parameters.
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
std::vector< pandora::PfoList > SliceHypotheses
MANAGED_CONTAINER< const MCParticle * > MCParticleList
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< CartesianVector > CartesianPointVector
std::unordered_set< const CaloHit * > CaloHitSet
MANAGED_CONTAINER< const CaloHit * > CaloHitList
std::vector< const MCParticle * > MCParticleVector
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList