28 m_iterateTrackHits(true),
29 m_iterateShowerHits(false),
30 m_slidingFitHalfWindow(10),
31 m_nHitRefinementIterations(10),
32 m_sigma3DFitMultiplier(0.2),
33 m_iterationMaxChi2Ratio(1.)
41 for (
const CaloHit *
const pCaloHit : inputCaloHitVector)
43 if (hitType == pCaloHit->GetHitType())
44 outputCaloHitVector.push_back(pCaloHit);
52 const PfoList *pPfoList(
nullptr);
56 if (!pPfoList || pPfoList->empty())
59 std::cout <<
"ThreeDHitCreationAlgorithm: unable to find pfo list " <<
m_inputPfoListName << std::endl;
61 return STATUS_CODE_SUCCESS;
66 PfoVector pfoVector(pPfoList->begin(), pPfoList->end());
78 if (remainingTwoDHits.empty())
81 pHitCreationTool->Run(
this, pPfo, remainingTwoDHits, protoHitVector);
87 if (protoHitVector.empty())
94 allNewThreeDHits.insert(allNewThreeDHits.end(), newThreeDHits.begin(), newThreeDHits.end());
97 if (!allNewThreeDHits.empty())
100 return STATUS_CODE_SUCCESS;
112 for (
const Cluster *
const pCluster : twoDClusterList)
117 pCluster->GetOrderedCaloHitList().FillCaloHitList(remainingHitList);
120 CaloHitSet remainingHitSet(remainingHitList.begin(), remainingHitList.end());
122 for (
const ProtoHit &protoHit : protoHitVector)
124 CaloHitSet::iterator eraseIter = remainingHitSet.find(protoHit.GetParentCaloHit2D());
126 if (remainingHitSet.end() == eraseIter)
129 remainingHitSet.erase(eraseIter);
132 remainingHitVector.insert(remainingHitVector.end(), remainingHitSet.begin(), remainingHitSet.end());
143 double originalChi2(0.);
145 this->
ExtractResults(protoHitVector, originalChi2, currentPoints3D);
150 const double originalChi2WrtFit(this->
GetChi2WrtFit(originalSlidingFitResult, protoHitVector));
151 double currentChi2(originalChi2 + originalChi2WrtFit);
153 unsigned int nIterations(0);
168 currentChi2 = newChi2;
169 currentPoints3D = newPoints3D;
170 protoHitVector = newProtoHitVector;
185 for (
const ProtoHit &protoHit : protoHitVector)
187 chi2 += protoHit.GetChi2();
188 pointVector.push_back(protoHit.GetPosition3D());
199 double chi2WrtFit(0.);
201 for (
const ProtoHit &protoHit : protoHitVector)
214 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ()));
216 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ()));
218 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ()));
220 const double deltaUFit(uFit - outputU), deltaVFit(vFit - outputV), deltaWFit(wFit - outputW);
221 chi2WrtFit += ((deltaUFit * deltaUFit) / (sigma3DFit * sigma3DFit)) + ((deltaVFit * deltaVFit) / (sigma3DFit * sigma3DFit)) +
222 ((deltaWFit * deltaWFit) / (sigma3DFit * sigma3DFit));
233 double hitMovementChi2(0.);
235 for (
const ProtoHit &protoHit : protoHitVector)
237 const CaloHit *
const pCaloHit2D(protoHit.GetParentCaloHit2D());
243 hitMovementChi2 += (delta * delta) / (sigmaUVW * sigmaUVW);
246 return hitMovementChi2;
254 const double sigmaFit(sigmaUVW);
255 const double sigmaHit(sigmaUVW);
258 for (
ProtoHit &protoHit : protoHitVector)
266 const CaloHit *
const pCaloHit2D(protoHit.GetParentCaloHit2D());
273 const double sigmaU((
TPC_VIEW_U == hitType) ? sigmaHit : sigmaFit);
274 const double sigmaV((
TPC_VIEW_V == hitType) ? sigmaHit : sigmaFit);
275 const double sigmaW((
TPC_VIEW_W == hitType) ? sigmaHit : sigmaFit);
278 double chi2(std::numeric_limits<double>::max());
279 double u(std::numeric_limits<double>::max()), v(std::numeric_limits<double>::max()), w(std::numeric_limits<double>::max());
281 if (protoHit.GetNTrajectorySamples() == 2)
284 : (
TPC_VIEW_U == protoHit.GetFirstTrajectorySample().GetHitType())
285 ? protoHit.GetFirstTrajectorySample().GetPosition().GetZ()
286 : protoHit.GetLastTrajectorySample().GetPosition().GetZ();
288 : (
TPC_VIEW_V == protoHit.GetFirstTrajectorySample().GetHitType())
289 ? protoHit.GetFirstTrajectorySample().GetPosition().GetZ()
290 : protoHit.GetLastTrajectorySample().GetPosition().GetZ();
292 : (
TPC_VIEW_W == protoHit.GetFirstTrajectorySample().GetHitType())
293 ? protoHit.GetFirstTrajectorySample().GetPosition().GetZ()
294 : protoHit.GetLastTrajectorySample().GetPosition().GetZ();
296 else if (protoHit.GetNTrajectorySamples() == 1)
299 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ());
301 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ());
303 protoHit.GetPosition3D().GetY(), protoHit.GetPosition3D().GetZ());
307 std::cout <<
"ThreeDHitCreationAlgorithm::IterativeTreatment - Unexpected number of trajectory samples" << std::endl;
311 double bestY(std::numeric_limits<double>::max()), bestZ(std::numeric_limits<double>::max());
313 u, v, w, sigmaU, sigmaV, sigmaW, uFit, vFit, wFit, sigma3DFit, bestY, bestZ, chi2);
314 position3D.SetValues(pCaloHit2D->
GetPositionVector().
GetX(),
static_cast<float>(bestY),
static_cast<float>(bestZ));
316 protoHit.SetPosition3D(position3D, chi2);
324 for (
const ProtoHit &protoHit : protoHitVector)
326 const CaloHit *pCaloHit3D(
nullptr);
332 newThreeDHits.push_back(pCaloHit3D);
343 PandoraContentApi::CaloHit::Parameters parameters;
345 parameters.m_hitType =
TPC_3D;
348 parameters.m_pParentAddress =
static_cast<const void *
>(pCaloHit2D);
359 parameters.m_time = pCaloHit2D->
GetTime();
364 parameters.m_isDigital = pCaloHit2D->
IsDigital();
366 parameters.m_layer = pCaloHit2D->
GetLayer();
368 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CaloHit::Create(*
this, parameters, pCaloHit3D));
393 if (caloHitList.empty())
399 if (!threeDClusterList.empty())
403 std::string clusterListName;
406 PandoraContentApi::Cluster::Parameters parameters;
407 parameters.m_caloHitList.insert(parameters.m_caloHitList.end(), caloHitList.begin(), caloHitList.end());
409 const Cluster *pCluster3D(
nullptr);
410 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, parameters, pCluster3D));
412 if (!pCluster3D || !pClusterList || pClusterList->empty())
434 if (!m_isPositionSet)
444 if (m_trajectorySampleVector.empty())
447 return m_trajectorySampleVector.front();
454 if (m_trajectorySampleVector.size() < 2)
457 return m_trajectorySampleVector.back();
468 for (AlgorithmToolVector::const_iterator iter = algorithmToolVector.begin(), iterEnd = algorithmToolVector.end(); iter != iterEnd; ++iter)
472 if (!pHitCreationTool)
473 return STATUS_CODE_INVALID_PARAMETER;
500 return STATUS_CODE_SUCCESS;
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the pfo helper class.
Header file for the lar three dimensional sliding fit result 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)
Header file for the three dimensional hit creation algorithm class.
static pandora::StatusCode SaveList(const pandora::Algorithm &algorithm, const T &t, const std::string &newListName)
Save a provided input object list under a new name.
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode AddToPfo(const pandora::Algorithm &algorithm, const pandora::ParticleFlowObject *const pPfo, const T *const pT)
Add a cluster to a particle flow object.
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static const pandora::PluginManager * GetPlugins(const pandora::Algorithm &algorithm)
Get the pandora plugin instance, providing access to user registered functions and calculators.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
HitCreationBaseTool class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
static float GetSigmaUVW(const pandora::Pandora &pandora, const float maxSigmaDiscrepancy=0.01)
Find the sigmaUVW value for the detector geometry.
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 void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Proto hits are temporary constructs to be used during iterative 3D hit procedure.
const TrajectorySample & GetFirstTrajectorySample() const
Get the first trajectory sample.
double GetChi2() const
Get the chi squared value.
const pandora::CaloHit * GetParentCaloHit2D() const
Get the address of the parent 2D calo hit.
pandora::CartesianVector m_position3D
The output 3D position.
const TrajectorySample & GetLastTrajectorySample() const
Get the last trajectory sample.
bool m_isPositionSet
Whether the output 3D position has been set.
const pandora::CartesianVector & GetPosition3D() const
Get the output 3D position.
Trajectory samples record the results of sampling a particles in a particular view.
bool m_iterateTrackHits
Whether to enable iterative improvement of 3D hits for track trajectories.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
bool CheckThreeDHit(const ProtoHit &protoHit) const
Check that a new three dimensional position is not unphysical.
void IterativeTreatment(ProtoHitVector &protoHitVector) const
Improve initial 3D hits by fitting proto hits and iteratively creating consisted 3D hit trajectory.
std::string m_inputPfoListName
The name of the input pfo list.
pandora::StatusCode Run()
Run the algorithm.
std::vector< ProtoHit > ProtoHitVector
double GetChi2WrtFit(const ThreeDSlidingFitResult &slidingFitResult, const ProtoHitVector &protoHitVector) const
Receive a chi2 value indicating consistency of a list of proto hits with a provided 3D sliding fit tr...
void SeparateTwoDHits(const pandora::ParticleFlowObject *const pPfo, const ProtoHitVector &protoHitVector, pandora::CaloHitVector &remainingHitVector) const
Get the list of 2D calo hits in a pfo for which 3D hits have and have not been created.
void RefineHitPositions(const ThreeDSlidingFitResult &slidingFitResult, ProtoHitVector &protoHitVector) const
Refine the 3D hit positions (and chi2) for a list of proto hits, in accordance with a provided 3D sli...
void CreateThreeDHits(const ProtoHitVector &protoHitVector, pandora::CaloHitList &newThreeDHits) const
Create new three dimensional hits from two dimensional hits.
ThreeDHitCreationAlgorithm()
Default constructor.
bool m_iterateShowerHits
Whether to enable iterative improvement of 3D hits for showers.
void FilterCaloHitsByType(const pandora::CaloHitVector &inputCaloHitVector, const pandora::HitType hitType, pandora::CaloHitVector &outputCaloHitVector) const
Get the subset of a provided calo hit vector corresponding to a specified hit type.
double GetHitMovementChi2(const ProtoHitVector &protoHitVector) const
Receive a chi2 value indicating consistency of a list of proto hits with the original,...
void ExtractResults(const ProtoHitVector &protoHitVector, double &chi2, pandora::CartesianPointVector &pointVector) const
Extract key results from a provided proto hit vector.
HitCreationToolVector m_algorithmToolVector
The algorithm tool vector.
unsigned int m_slidingFitHalfWindow
The sliding linear fit half window.
unsigned int m_nHitRefinementIterations
The maximum number of hit refinement iterations.
double m_sigma3DFitMultiplier
Multiplicative factor: sigmaUVW (same as sigmaHit and sigma2DFit) to sigma3DFit.
std::string m_outputCaloHitListName
The name of the output calo hit list.
void AddThreeDHitsToPfo(const pandora::ParticleFlowObject *const pPfo, const pandora::CaloHitList &caloHitList) const
Add a specified list of three dimensional hits to a cluster in a pfo, creating the new cluster if req...
void CreateThreeDHit(const ProtoHit &protoHit, const pandora::CaloHit *&pCaloHit3D) const
Create a new three dimensional hit from a two dimensional hit.
std::string m_outputClusterListName
The name of the output cluster list.
double m_iterationMaxChi2Ratio
Max ratio between current and previous chi2 values to cease iterations.
ThreeDSlidingFitResult class.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
float GetLongitudinalDisplacement(const pandora::CartesianVector &position) const
Get longitudinal projection onto primary axis.
float GetElectromagneticEnergy() const
Get the calibrated electromagnetic energy measure.
HitType GetHitType() const
Get the calorimeter hit type.
bool IsInOuterSamplingLayer() const
Whether cell is in one of the outermost detector sampling layers.
HitRegion GetHitRegion() const
Get the region of the detector in which the calo hit is located.
const CartesianVector & GetPositionVector() const
Get the position vector of center of calorimeter cell, units mm.
unsigned int GetLayer() const
Get the subdetector readout layer number.
float GetMipEquivalentEnergy() const
Get the calibrated mip equivalent energy.
float GetNCellRadiationLengths() const
Get the absorber material in front of cell, units radiation lengths.
float GetNCellInteractionLengths() const
Get the absorber material in front of cell, units interaction lengths.
float GetCellThickness() const
Get the thickness of cell, units mm.
float GetCellLengthScale() const
Get the typical length scale of cell, units mm.
bool IsDigital() const
Whether cell should be treated as digital.
const CartesianVector & GetCellNormalVector() const
Get the unit vector normal to the sampling layer, pointing outwards from the origin.
float GetHadronicEnergy() const
Get the calibrated hadronic energy measure.
float GetInputEnergy() const
Get the corrected energy of the calorimeter cell, units GeV, as supplied by the user.
float GetTime() const
Get the time of (earliest) energy deposition in this cell, units ns.
const CartesianVector & GetExpectedDirection() const
Get the unit vector in direction of expected hit propagation.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetY() const
Get the cartesian y coordinate.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
const LArTransformationPlugin * GetLArTransformationPlugin() const
Get the address of the lar transformation plugin.
const PseudoLayerPlugin * GetPseudoLayerPlugin() const
Get the address of the pseudo layer plugin.
const Pandora & GetPandora() const
Get the associated pandora instance.
virtual unsigned int GetPseudoLayer(const CartesianVector &positionVector) const =0
Get the appropriate pseudolayer for a specified position vector.
StatusCodeException class.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
static StatusCode ProcessAlgorithmToolList(const Algorithm &algorithm, const TiXmlHandle &xmlHandle, const std::string &listName, AlgorithmToolVector &algorithmToolVector)
Process a list of algorithms tools in an xml file.
HitType
Calorimeter hit type enum.
std::vector< const CaloHit * > CaloHitVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< const ParticleFlowObject * > PfoVector
std::vector< CartesianVector > CartesianPointVector
std::vector< AlgorithmTool * > AlgorithmToolVector
std::unordered_set< const CaloHit * > CaloHitSet
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList