RPhiFeatureTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/RPhiFeatureTool.cc
3  *
4  * @brief Implementation of the r/phi feature tool class.
5  *
6  * $Log: $
7  */
8 
10 #include "Pandora/AlgorithmHeaders.h"
13 
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 RPhiFeatureTool::RPhiFeatureTool() :
22  m_fastScoreCheck(true),
23  m_fastScoreOnly(false),
24  m_fullScore(false),
25  m_kernelEstimateSigma(0.048f),
26  m_kappa(0.42f),
27  m_maxHitVertexDisplacement1D(100.f),
28  m_minFastScoreFraction(0.8f),
29  m_fastHistogramNPhiBins(200),
30  m_fastHistogramPhiMin(-1.1f * M_PI),
31  m_fastHistogramPhiMax(+1.1f * M_PI),
32  m_enableFolding(true)
33 {
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
39  const Vertex *const pVertex, const VertexSelectionBaseAlgorithm::SlidingFitDataListMap &,
41  const VertexSelectionBaseAlgorithm::ShowerClusterListMap &, const float beamDeweightingScore, float &bestFastScore)
42 {
43  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
44  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
45 
46  KernelEstimate kernelEstimateU(m_kernelEstimateSigma);
47  KernelEstimate kernelEstimateV(m_kernelEstimateSigma);
48  KernelEstimate kernelEstimateW(m_kernelEstimateSigma);
49 
50  this->FillKernelEstimate(pVertex, TPC_VIEW_U, kdTreeMap.at(TPC_VIEW_U), kernelEstimateU);
51  this->FillKernelEstimate(pVertex, TPC_VIEW_V, kdTreeMap.at(TPC_VIEW_V), kernelEstimateV);
52  this->FillKernelEstimate(pVertex, TPC_VIEW_W, kdTreeMap.at(TPC_VIEW_W), kernelEstimateW);
53 
54  const float expBeamDeweightingScore = std::exp(beamDeweightingScore);
55 
57  {
58  const float fastScore(this->GetFastScore(kernelEstimateU, kernelEstimateV, kernelEstimateW));
59 
60  if (m_fastScoreOnly)
61  {
62  featureVector.push_back(fastScore);
63  return;
64  }
65 
66  if (expBeamDeweightingScore * fastScore < m_minFastScoreFraction * bestFastScore)
67  {
68  featureVector.push_back(0.);
69  return;
70  }
71 
72  if (expBeamDeweightingScore * fastScore > bestFastScore)
73  bestFastScore = expBeamDeweightingScore * fastScore;
74  }
75 
76  featureVector.push_back(m_fullScore ? this->GetFullScore(kernelEstimateU, kernelEstimateV, kernelEstimateW)
77  : this->GetMidwayScore(kernelEstimateU, kernelEstimateV, kernelEstimateW));
78 }
79 
80 //------------------------------------------------------------------------------------------------------------------------------------------
81 
82 float RPhiFeatureTool::GetFastScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
83 {
87 
88  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateU.GetContributionList())
89  histogramU.Fill(contribution.first, contribution.second);
90 
91  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateV.GetContributionList())
92  histogramV.Fill(contribution.first, contribution.second);
93 
94  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateW.GetContributionList())
95  histogramW.Fill(contribution.first, contribution.second);
96 
97  // Is the below correct?
98  histogramU.Scale(1.f / histogramU.GetCumulativeSum());
99  histogramV.Scale(1.f / histogramV.GetCumulativeSum());
100  histogramW.Scale(1.f / histogramW.GetCumulativeSum());
101 
102  // ATTN Need to renormalise histograms if ever want to directly compare fast and full scores
103  float figureOfMerit(0.f);
104 
105  for (int xBin = 0; xBin < histogramU.GetNBinsX(); ++xBin)
106  {
107  const float binContentU(histogramU.GetBinContent(xBin));
108  const float binContentV(histogramV.GetBinContent(xBin));
109  const float binContentW(histogramW.GetBinContent(xBin));
110  figureOfMerit += binContentU * binContentU + binContentV * binContentV + binContentW * binContentW;
111  }
112 
113  return figureOfMerit;
114 }
115 
116 //------------------------------------------------------------------------------------------------------------------------------------------
117 
118 float RPhiFeatureTool::GetMidwayScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
119 {
123 
124  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateU.GetContributionList())
125  histogramU.Fill(contribution.first, contribution.second);
126 
127  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateV.GetContributionList())
128  histogramV.Fill(contribution.first, contribution.second);
129 
130  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateW.GetContributionList())
131  histogramW.Fill(contribution.first, contribution.second);
132 
133  float figureOfMerit(0.f);
134 
135  for (int xBin = 0; xBin < histogramU.GetNBinsX(); ++xBin)
136  {
137  const float binCenter(histogramU.GetXLow() + (static_cast<float>(xBin) + 0.5f) * histogramU.GetXBinWidth());
138  figureOfMerit += histogramU.GetBinContent(xBin) * kernelEstimateU.Sample(binCenter);
139  figureOfMerit += histogramV.GetBinContent(xBin) * kernelEstimateV.Sample(binCenter);
140  figureOfMerit += histogramW.GetBinContent(xBin) * kernelEstimateW.Sample(binCenter);
141  }
142 
143  return figureOfMerit;
144 }
145 
146 //------------------------------------------------------------------------------------------------------------------------------------------
147 
148 float RPhiFeatureTool::GetFullScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
149 {
150  float figureOfMerit(0.f);
151 
152  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateU.GetContributionList())
153  figureOfMerit += contribution.second * kernelEstimateU.Sample(contribution.first);
154 
155  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateV.GetContributionList())
156  figureOfMerit += contribution.second * kernelEstimateV.Sample(contribution.first);
157 
158  for (const KernelEstimate::ContributionList::value_type &contribution : kernelEstimateW.GetContributionList())
159  figureOfMerit += contribution.second * kernelEstimateW.Sample(contribution.first);
160 
161  return figureOfMerit;
162 }
163 
164 //------------------------------------------------------------------------------------------------------------------------------------------
165 
166 void RPhiFeatureTool::FillKernelEstimate(const Vertex *const pVertex, const HitType hitType,
167  VertexSelectionBaseAlgorithm::HitKDTree2D &kdTree, KernelEstimate &kernelEstimate) const
168 {
169  const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
171 
173  kdTree.search(searchRegionHits, found);
174 
175  for (const auto &hit : found)
176  {
177  const CartesianVector displacement(hit.data->GetPositionVector() - vertexPosition2D);
178  const float magnitude(displacement.GetMagnitude());
179 
180  if (magnitude < std::numeric_limits<float>::epsilon())
181  continue;
182 
183  float phi(this->atan2Fast(displacement.GetZ(), displacement.GetX()));
184  float weight(1.f / (std::sqrt(magnitude + std::fabs(m_kappa))));
185 
186  if (m_enableFolding && (phi < 0.f))
187  {
188  phi += M_PI;
189  weight *= -1.f;
190  }
191 
192  kernelEstimate.AddContribution(phi, weight);
193  }
194 }
195 
196 //------------------------------------------------------------------------------------------------------------------------------------------
197 
198 float RPhiFeatureTool::atan2Fast(const float y, const float x) const
199 {
200  const float ONE_QTR_PI(0.25f * M_PI);
201  const float THR_QTR_PI(0.75f * M_PI);
202 
203  const float abs_y(std::max(std::fabs(y), std::numeric_limits<float>::epsilon()));
204  const float abs_x(std::fabs(x));
205 
206  const float r((x < 0.f) ? (x + abs_y) / (abs_y + abs_x) : (abs_x - abs_y) / (abs_x + abs_y));
207  const float angle(((x < 0.f) ? THR_QTR_PI : ONE_QTR_PI) + (0.1963f * r * r - 0.9817f) * r);
208 
209  return ((y < 0.f) ? -angle : angle); // negate if in quad III or IV
210 }
211 
212 //------------------------------------------------------------------------------------------------------------------------------------------
213 //------------------------------------------------------------------------------------------------------------------------------------------
214 
216 {
217  const ContributionList &contributionList(this->GetContributionList());
218  ContributionList::const_iterator lowerIter(contributionList.lower_bound(x - 3.f * m_sigma));
219  ContributionList::const_iterator upperIter(contributionList.upper_bound(x + 3.f * m_sigma));
220 
221  float sample(0.f);
222  const float gaussConstant(1.f / std::sqrt(2.f * M_PI * m_sigma * m_sigma));
223 
224  for (ContributionList::const_iterator iter = lowerIter; iter != upperIter; ++iter)
225  {
226  const float deltaSigma((x - iter->first) / m_sigma);
227  const float gaussian(gaussConstant * std::exp(-0.5f * deltaSigma * deltaSigma));
228  sample += iter->second * gaussian;
229  }
230 
231  return sample;
232 }
233 
234 //------------------------------------------------------------------------------------------------------------------------------------------
235 
237 {
238  m_contributionList.insert(ContributionList::value_type(x, weight));
239 }
240 
241 //------------------------------------------------------------------------------------------------------------------------------------------
242 
243 StatusCode RPhiFeatureTool::ReadSettings(const TiXmlHandle xmlHandle)
244 {
245  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FastScoreCheck", m_fastScoreCheck));
246 
247  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FastScoreOnly", m_fastScoreOnly));
248 
249  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FullScore", m_fullScore));
250 
251  PANDORA_RETURN_RESULT_IF_AND_IF(
252  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "KernelEstimateSigma", m_kernelEstimateSigma));
253 
254  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Kappa", m_kappa));
255 
256  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
257  XmlHelper::ReadValue(xmlHandle, "MaxHitVertexDisplacement1D", m_maxHitVertexDisplacement1D));
258 
259  PANDORA_RETURN_RESULT_IF_AND_IF(
260  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinFastScoreFraction", m_minFastScoreFraction));
261 
262  PANDORA_RETURN_RESULT_IF_AND_IF(
263  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FastHistogramNPhiBins", m_fastHistogramNPhiBins));
264 
265  PANDORA_RETURN_RESULT_IF_AND_IF(
266  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FastHistogramPhiMin", m_fastHistogramPhiMin));
267 
268  PANDORA_RETURN_RESULT_IF_AND_IF(
269  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FastHistogramPhiMax", m_fastHistogramPhiMax));
270 
271  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EnableFolding", m_enableFolding));
272 
273  return STATUS_CODE_SUCCESS;
274 }
275 
276 } // namespace lar_content
bool m_fastScoreCheck
Whether to use the fast histogram based score to selectively avoid calling full or midway scores...
Header file for the kd tree linker algo template class.
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:58
void Run(LArMvaHelper::MvaFeatureVector &featureVector, const VertexSelectionBaseAlgorithm *const pAlgorithm, const pandora::Vertex *const pVertex, const VertexSelectionBaseAlgorithm::SlidingFitDataListMap &, const VertexSelectionBaseAlgorithm::ClusterListMap &, const VertexSelectionBaseAlgorithm::KDTreeMap &kdTreeMap, const VertexSelectionBaseAlgorithm::ShowerClusterListMap &, const float beamDeweightingScore, float &bestFastScore)
Run the tool.
enum cvn::HType HitType
unsigned int m_fastHistogramNPhiBins
Number of bins to use for fast score histograms.
Box structure used to define 2D field. It&#39;s used in KDTree building step to divide the detector space...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_fastHistogramPhiMin
Min value for fast score histograms.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
float m_kappa
Hit-deweighting offset, of form: weight = 1 / sqrt(distance + kappa), units cm.
intermediate_table::const_iterator const_iterator
bool m_fastScoreOnly
Whether to use the fast histogram based score only.
weight
Definition: test.py:257
const ContributionList & GetContributionList() const
Get the contribution list.
float m_minFastScoreFraction
Fast score must be at least this fraction of best fast score to calculate full score.
float atan2Fast(const float y, const float x) const
Fast estimate of std::atan2 function. Rather coarse (max |error| > 0.01) but should suffice for this ...
Header file for the geometry helper class.
std::map< pandora::HitType, const ShowerClusterList > ShowerClusterListMap
Map of shower cluster lists for passing to tools.
float GetFastScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
Get the score for a trio of kernel estimations, using fast histogram approach.
Header file for the cluster helper class.
float Sample(const float x) const
Sample the parameterised distribution at a specified x coordinate.
float m_maxHitVertexDisplacement1D
Max hit-vertex displacement in any one dimension for contribution to kernel estimation.
float GetFullScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
Get the score for a trio of kernel estimations, using kernel density estimation and full hit-by-hit s...
float m_fastHistogramPhiMax
Max value for fast score histograms.
bool m_fullScore
Whether to use the full kernel density estimation score, as opposed to the midway score...
std::map< pandora::HitType, const pandora::ClusterList & > ClusterListMap
Map array of cluster lists for passing to tools.
float m_kernelEstimateSigma
The Gaussian width to use for kernel estimation.
static int max(int a, int b)
bool m_enableFolding
Whether to enable folding of -pi -> +pi phi distribution into 0 -> +pi region only.
Detector simulation of raw signals on wires.
#define M_PI
Definition: includeROOT.h:54
std::map< pandora::HitType, const SlidingFitDataList > SlidingFitDataListMap
Map of sliding fit data lists for passing to tools.
float GetMidwayScore(const KernelEstimate &kernelEstimateU, const KernelEstimate &kernelEstimateV, const KernelEstimate &kernelEstimateW) const
Get the score for a trio of kernel estimations, using kernel density estimation but with reduced (bin...
void FillKernelEstimate(const pandora::Vertex *const pVertex, const pandora::HitType hitType, VertexSelectionBaseAlgorithm::HitKDTree2D &kdTree, KernelEstimate &kernelEstimate) const
Use hits in clusters (in the provided kd tree) to fill a provided kernel estimate with hit-vertex rel...
void AddContribution(const float x, const float weight)
Add a contribution to the distribution.
list x
Definition: train.py:276
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::multimap< float, float > ContributionList
Map from x coord to weight, ATTN avoid map.find, etc. with float key.
std::map< pandora::HitType, const std::reference_wrapper< HitKDTree2D > > KDTreeMap
Map array of hit kd trees for passing to tools.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM >> &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
QTextStream & endl(QTextStream &s)
Header file for the r/phi feature tool class.