LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
LArTwoDSlidingFitResult.cc
Go to the documentation of this file.
1 
12 
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <limits>
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 template <>
25 TwoDSlidingFitResult::TwoDSlidingFitResult(const Cluster *const pCluster, const unsigned int layerFitHalfWindow, const float layerPitch) :
26  m_pCluster(pCluster),
27  m_layerFitHalfWindow(layerFitHalfWindow),
28  m_layerPitch(layerPitch),
29  m_axisIntercept(0.f, 0.f, 0.f),
30  m_axisDirection(0.f, 0.f, 0.f),
31  m_orthoDirection(0.f, 0.f, 0.f)
32 {
33  CartesianPointVector pointVector;
34  LArClusterHelper::GetCoordinateVector(pCluster, pointVector);
35  this->CalculateAxes(pointVector, layerPitch);
36  this->FillLayerFitContributionMap(pointVector);
38  this->FindSlidingFitSegments();
39 }
40 
41 template <>
42 TwoDSlidingFitResult::TwoDSlidingFitResult(const CartesianPointVector *const pPointVector, const unsigned int layerFitHalfWindow, const float layerPitch) :
43  m_pCluster(nullptr),
44  m_layerFitHalfWindow(layerFitHalfWindow),
45  m_layerPitch(layerPitch),
46  m_axisIntercept(0.f, 0.f, 0.f),
47  m_axisDirection(0.f, 0.f, 0.f),
48  m_orthoDirection(0.f, 0.f, 0.f)
49 {
50  this->CalculateAxes(*pPointVector, layerPitch);
51  this->FillLayerFitContributionMap(*pPointVector);
53  this->FindSlidingFitSegments();
54 }
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 
58 template <>
59 TwoDSlidingFitResult::TwoDSlidingFitResult(const Cluster *const pCluster, const unsigned int layerFitHalfWindow, const float layerPitch,
60  const CartesianVector &axisIntercept, const CartesianVector &axisDirection, const CartesianVector &orthoDirection) :
61  m_pCluster(pCluster),
62  m_layerFitHalfWindow(layerFitHalfWindow),
63  m_layerPitch(layerPitch),
64  m_axisIntercept(axisIntercept),
65  m_axisDirection(axisDirection),
66  m_orthoDirection(orthoDirection)
67 {
68  CartesianPointVector pointVector;
69  LArClusterHelper::GetCoordinateVector(pCluster, pointVector);
70  this->FillLayerFitContributionMap(pointVector);
72  this->FindSlidingFitSegments();
73 }
74 
75 template <>
76 TwoDSlidingFitResult::TwoDSlidingFitResult(const CartesianPointVector *const pPointVector, const unsigned int layerFitHalfWindow, const float layerPitch,
77  const CartesianVector &axisIntercept, const CartesianVector &axisDirection, const CartesianVector &orthoDirection) :
78  m_pCluster(nullptr),
79  m_layerFitHalfWindow(layerFitHalfWindow),
80  m_layerPitch(layerPitch),
81  m_axisIntercept(axisIntercept),
82  m_axisDirection(axisDirection),
83  m_orthoDirection(orthoDirection)
84 {
85  this->FillLayerFitContributionMap(*pPointVector);
87  this->FindSlidingFitSegments();
88 }
89 
90 //------------------------------------------------------------------------------------------------------------------------------------------
91 
92 TwoDSlidingFitResult::TwoDSlidingFitResult(const unsigned int layerFitHalfWindow, const float layerPitch,
93  const CartesianVector &axisIntercept, const CartesianVector &axisDirection, const CartesianVector &orthoDirection,
94  const LayerFitContributionMap &layerFitContributionMap) :
95  m_pCluster(nullptr),
96  m_layerFitHalfWindow(layerFitHalfWindow),
97  m_layerPitch(layerPitch),
98  m_axisIntercept(axisIntercept),
99  m_axisDirection(axisDirection),
100  m_orthoDirection(orthoDirection),
101  m_layerFitContributionMap(layerFitContributionMap)
102 {
103  this->PerformSlidingLinearFit();
104  this->FindSlidingFitSegments();
105 }
106 
107 //------------------------------------------------------------------------------------------------------------------------------------------
108 
109 const pandora::Cluster *TwoDSlidingFitResult::GetCluster() const
110 {
111  if (!m_pCluster)
112  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
113 
114  return m_pCluster;
115 }
116 
117 //------------------------------------------------------------------------------------------------------------------------------------------
118 
120 {
121  return (static_cast<float>(m_layerFitHalfWindow)) * m_layerPitch;
122 }
123 
124 //------------------------------------------------------------------------------------------------------------------------------------------
125 
127 {
128  if (m_layerFitResultMap.empty())
129  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
130 
131  return m_layerFitResultMap.begin()->first;
132 }
133 
134 //------------------------------------------------------------------------------------------------------------------------------------------
135 
137 {
138  if (m_layerFitResultMap.empty())
139  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
140 
141  return m_layerFitResultMap.rbegin()->first;
142 }
143 
144 //------------------------------------------------------------------------------------------------------------------------------------------
145 
146 int TwoDSlidingFitResult::GetLayer(const float rL) const
147 {
148  if (m_layerPitch < std::numeric_limits<float>::epsilon())
149  throw StatusCodeException(STATUS_CODE_FAILURE);
150 
151  return static_cast<int>(std::floor(rL / m_layerPitch));
152 }
153 
154 //------------------------------------------------------------------------------------------------------------------------------------------
155 
156 float TwoDSlidingFitResult::GetL(const int layer) const
157 {
158  return (static_cast<float>(layer) + 0.5f) * m_layerPitch;
159 }
160 
161 //------------------------------------------------------------------------------------------------------------------------------------------
162 
163 void TwoDSlidingFitResult::GetLocalPosition(const CartesianVector &position, float &rL, float &rT) const
164 {
165  const CartesianVector displacement(position - m_axisIntercept);
166 
167  rL = displacement.GetDotProduct(m_axisDirection);
168  rT = displacement.GetDotProduct(m_orthoDirection);
169 }
170 
171 //------------------------------------------------------------------------------------------------------------------------------------------
172 
173 void TwoDSlidingFitResult::GetLocalDirection(const CartesianVector &direction, float&dTdL) const
174 {
175  float pL(0.f), pT(0.f);
176  this->GetLocalPosition((direction + m_axisIntercept), pL, pT);
177 
178  if (std::fabs(pL) < std::numeric_limits<float>::epsilon())
179  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
180 
181  dTdL = pT / pL;
182 }
183 
184 //------------------------------------------------------------------------------------------------------------------------------------------
185 
186 void TwoDSlidingFitResult::GetGlobalPosition(const float rL, const float rT, CartesianVector &position) const
187 {
188  position = m_axisIntercept + (m_axisDirection * rL) + (m_orthoDirection * rT);
189 }
190 
191 //------------------------------------------------------------------------------------------------------------------------------------------
192 
193 void TwoDSlidingFitResult::GetGlobalDirection(const float dTdL, CartesianVector &direction) const
194 {
195  const float pL(1.f / std::sqrt(1.f + dTdL * dTdL));
196  const float pT(dTdL / std::sqrt(1.f + dTdL * dTdL));
197 
198  CartesianVector globalCoordinates(0.f, 0.f, 0.f);
199  this->GetGlobalPosition(pL, pT, globalCoordinates);
200  direction = (globalCoordinates - m_axisIntercept).GetUnitVector();
201 }
202 
203 //------------------------------------------------------------------------------------------------------------------------------------------
204 
206 {
207  if (m_layerFitResultMap.empty())
208  throw StatusCodeException(STATUS_CODE_FAILURE);
209 
211  CartesianVector position(0.f, 0.f, 0.f);
212  this->GetGlobalPosition(iter->second.GetL(), iter->second.GetFitT(), position);
213  return position;
214 }
215 
216 //------------------------------------------------------------------------------------------------------------------------------------------
217 
219 {
220  if (m_layerFitResultMap.empty())
221  throw StatusCodeException(STATUS_CODE_FAILURE);
222 
223  LayerFitResultMap::const_reverse_iterator iter = m_layerFitResultMap.rbegin();
224  CartesianVector position(0.f, 0.f, 0.f);
225  this->GetGlobalPosition(iter->second.GetL(), iter->second.GetFitT(), position);
226  return position;
227 }
228 
229 //------------------------------------------------------------------------------------------------------------------------------------------
230 
232 {
233  if (m_layerFitResultMap.empty())
234  throw StatusCodeException(STATUS_CODE_FAILURE);
235 
237  CartesianVector direction(0.f, 0.f, 0.f);
238  this->GetGlobalDirection(iter->second.GetGradient(), direction);
239  return direction;
240 }
241 
242 //------------------------------------------------------------------------------------------------------------------------------------------
243 
245 {
246  if (m_layerFitResultMap.empty())
247  throw StatusCodeException(STATUS_CODE_FAILURE);
248 
249  LayerFitResultMap::const_reverse_iterator iter = m_layerFitResultMap.rbegin();
250  CartesianVector direction(0.f, 0.f, 0.f);
251  this->GetGlobalDirection(iter->second.GetGradient(), direction);
252  return direction;
253 }
254 
255 //------------------------------------------------------------------------------------------------------------------------------------------
256 
258 {
259  if (m_layerFitResultMap.empty())
260  throw StatusCodeException(STATUS_CODE_FAILURE);
261 
263  return iter->second.GetRms();
264 }
265 
266 //------------------------------------------------------------------------------------------------------------------------------------------
267 
269 {
270  if (m_layerFitResultMap.empty())
271  throw StatusCodeException(STATUS_CODE_FAILURE);
272 
273  LayerFitResultMap::const_reverse_iterator iter = m_layerFitResultMap.rbegin();
274  return iter->second.GetRms();
275 }
276 
277 //------------------------------------------------------------------------------------------------------------------------------------------
278 
279 float TwoDSlidingFitResult::GetFitRms(const float rL) const
280 {
281  LayerInterpolation layerInterpolation;
282  const StatusCode statusCode(this->LongitudinalInterpolation(rL, layerInterpolation));
283 
284  if (STATUS_CODE_SUCCESS != statusCode)
285  throw StatusCodeException(statusCode);
286 
287  return this->GetFitRms(layerInterpolation);
288 }
289 
290 //------------------------------------------------------------------------------------------------------------------------------------------
291 
293 {
294  const float halfWindowLength(this->GetLayerFitHalfWindowLength());
295 
296  CartesianVector firstDirection(0.f,0.f,0.f);
297  CartesianVector secondDirection(0.f,0.f,0.f);
298 
299  const StatusCode firstStatusCode(this->GetGlobalFitDirection(rL - halfWindowLength, firstDirection));
300  const StatusCode secondStatusCode(this->GetGlobalFitDirection(rL + halfWindowLength, secondDirection));
301 
302  if (STATUS_CODE_SUCCESS != firstStatusCode)
303  throw StatusCodeException(firstStatusCode);
304 
305  if (STATUS_CODE_SUCCESS != secondStatusCode)
306  throw StatusCodeException(secondStatusCode);
307 
308  return firstDirection.GetDotProduct(secondDirection);
309 }
310 
311 //------------------------------------------------------------------------------------------------------------------------------------------
312 
313 StatusCode TwoDSlidingFitResult::GetGlobalFitPosition(const float rL, CartesianVector &position) const
314 {
315  LayerInterpolation layerInterpolation;
316  const StatusCode statusCode(this->LongitudinalInterpolation(rL, layerInterpolation));
317 
318  if (STATUS_CODE_SUCCESS != statusCode)
319  return statusCode;
320 
321  position = this->GetGlobalFitPosition(layerInterpolation);
322  return STATUS_CODE_SUCCESS;
323 }
324 
325 //------------------------------------------------------------------------------------------------------------------------------------------
326 
327 StatusCode TwoDSlidingFitResult::GetGlobalFitDirection(const float rL, CartesianVector &direction) const
328 {
329  LayerInterpolation layerInterpolation;
330  const StatusCode statusCode(this->LongitudinalInterpolation(rL, layerInterpolation));
331 
332  if (STATUS_CODE_SUCCESS != statusCode)
333  return statusCode;
334 
335  direction = this->GetGlobalFitDirection(layerInterpolation);
336  return STATUS_CODE_SUCCESS;
337 }
338 
339 //------------------------------------------------------------------------------------------------------------------------------------------
340 
341 StatusCode TwoDSlidingFitResult::GetGlobalFitPositionAtX(const float x, CartesianVector &position) const
342 {
343  LayerInterpolationList layerInterpolationList;
344  const StatusCode statusCode(this->TransverseInterpolation(x, layerInterpolationList));
345 
346  if (STATUS_CODE_SUCCESS != statusCode)
347  return statusCode;
348 
349  if (layerInterpolationList.size() != 1)
350  return STATUS_CODE_NOT_FOUND;
351 
352  position = this->GetGlobalFitPosition(layerInterpolationList.at(0));
353  return STATUS_CODE_SUCCESS;
354 }
355 
356 //------------------------------------------------------------------------------------------------------------------------------------------
357 
358 StatusCode TwoDSlidingFitResult::GetGlobalFitDirectionAtX(const float x, CartesianVector &direction) const
359 {
360  LayerInterpolationList layerInterpolationList;
361  const StatusCode statusCode(this->TransverseInterpolation(x, layerInterpolationList));
362 
363  if (STATUS_CODE_SUCCESS != statusCode)
364  return statusCode;
365 
366  if (layerInterpolationList.size() != 1)
367  return STATUS_CODE_NOT_FOUND;
368 
369  direction = this->GetGlobalFitDirection(layerInterpolationList.at(0));
370  return STATUS_CODE_SUCCESS;
371 }
372 
373 //------------------------------------------------------------------------------------------------------------------------------------------
374 
375 StatusCode TwoDSlidingFitResult::GetGlobalFitProjection(const CartesianVector &inputPosition, CartesianVector &projectedPosition) const
376 {
377  float rL(0.f), rT(0.f);
378  this->GetLocalPosition(inputPosition, rL, rT);
379  return this->GetGlobalFitPosition(rL, projectedPosition);
380 }
381 
382 //------------------------------------------------------------------------------------------------------------------------------------------
383 
384 StatusCode TwoDSlidingFitResult::GetGlobalFitPositionListAtX(const float x, CartesianPointVector &positionList) const
385 {
386  LayerInterpolationList layerInterpolationList;
387  const StatusCode statusCode(this->TransverseInterpolation(x, layerInterpolationList));
388 
389  if (STATUS_CODE_SUCCESS != statusCode)
390  return statusCode;
391 
392  for (LayerInterpolationList::const_iterator iter = layerInterpolationList.begin(), iterEnd = layerInterpolationList.end();
393  iter != iterEnd; ++iter)
394  {
395  positionList.push_back(this->GetGlobalFitPosition(*iter));
396  }
397 
398  return STATUS_CODE_SUCCESS;
399 }
400 
401 //------------------------------------------------------------------------------------------------------------------------------------------
402 
403 StatusCode TwoDSlidingFitResult::GetTransverseProjection(const float x, const FitSegment &fitSegment, CartesianVector &position) const
404 {
405  LayerInterpolation layerInterpolation;
406  const StatusCode statusCode(this->TransverseInterpolation(x, fitSegment, layerInterpolation));
407 
408  if (STATUS_CODE_SUCCESS != statusCode)
409  return statusCode;
410 
411  position = this->GetGlobalFitPosition(layerInterpolation);
412  return STATUS_CODE_SUCCESS;
413 }
414 
415 //------------------------------------------------------------------------------------------------------------------------------------------
416 
417 StatusCode TwoDSlidingFitResult::GetTransverseProjection(const float x, const FitSegment &fitSegment, CartesianVector &position,
418  CartesianVector &direction) const
419 {
420  LayerInterpolation layerInterpolation;
421  const StatusCode statusCode(this->TransverseInterpolation(x, fitSegment, layerInterpolation));
422 
423  if (STATUS_CODE_SUCCESS != statusCode)
424  return statusCode;
425 
426  position = this->GetGlobalFitPosition(layerInterpolation);
427  direction = this->GetGlobalFitDirection(layerInterpolation);
428  return STATUS_CODE_SUCCESS;
429 }
430 
431 //------------------------------------------------------------------------------------------------------------------------------------------
432 
433 StatusCode TwoDSlidingFitResult::GetExtrapolatedPosition(const float rL, CartesianVector &position) const
434 {
435  const StatusCode statusCode(this->GetGlobalFitPosition(rL, position));
436 
437  if (STATUS_CODE_NOT_FOUND != statusCode)
438  return statusCode;
439 
440  const int thisLayer(this->GetLayer(rL));
441  const int minLayer(this->GetMinLayer());
442  const int maxLayer(this->GetMaxLayer());
443 
444  if (thisLayer <= minLayer)
445  {
446  position = (this->GetGlobalMinLayerPosition() + this->GetGlobalMinLayerDirection() * (rL - this->GetL(minLayer)));
447  }
448  else if (thisLayer >= maxLayer)
449  {
450  position = (this->GetGlobalMaxLayerPosition() + this->GetGlobalMaxLayerDirection() * (rL - this->GetL(maxLayer)));
451  }
452  else
453  {
454  return STATUS_CODE_FAILURE;
455  }
456 
457  return STATUS_CODE_SUCCESS;
458 }
459 
460 //------------------------------------------------------------------------------------------------------------------------------------------
461 
462 StatusCode TwoDSlidingFitResult::GetExtrapolatedDirection(const float rL, CartesianVector &direction) const
463 {
464  const StatusCode statusCode(this->GetGlobalFitDirection(rL, direction));
465 
466  if (STATUS_CODE_NOT_FOUND != statusCode)
467  return statusCode;
468 
469  const int thisLayer(this->GetLayer(rL));
470  const int minLayer(this->GetMinLayer());
471  const int maxLayer(this->GetMaxLayer());
472 
473  if (thisLayer <= minLayer)
474  {
475  direction = this->GetGlobalMinLayerDirection();
476  }
477  else if (thisLayer >= maxLayer)
478  {
479  direction = this->GetGlobalMaxLayerDirection();
480  }
481  else
482  {
483  return STATUS_CODE_FAILURE;
484  }
485 
486  return STATUS_CODE_SUCCESS;
487 }
488 
489 //------------------------------------------------------------------------------------------------------------------------------------------
490 
491 StatusCode TwoDSlidingFitResult::GetExtrapolatedPositionAtX(const float x, CartesianVector &position) const
492 {
493  const StatusCode statusCode(this->GetGlobalFitPositionAtX(x, position));
494 
495  if (STATUS_CODE_NOT_FOUND != statusCode)
496  return statusCode;
497 
498  const float minLayerX(this->GetGlobalMinLayerPosition().GetX());
499  const float maxLayerX(this->GetGlobalMaxLayerPosition().GetX());
500 
501  const int minLayer(this->GetMinLayer());
502  const int maxLayer(this->GetMaxLayer());
503 
504  const int innerLayer((minLayerX < maxLayerX) ? minLayer : maxLayer);
505  const int outerLayer((minLayerX < maxLayerX) ? maxLayer : minLayer);
506 
507  const CartesianVector innerVertex((innerLayer == minLayer) ? this->GetGlobalMinLayerPosition() : this->GetGlobalMaxLayerPosition());
508  const CartesianVector innerDirection((innerLayer == minLayer) ? this->GetGlobalMinLayerDirection() * -1.f : this->GetGlobalMaxLayerDirection());
509 
510  const CartesianVector outerVertex((outerLayer == minLayer) ? this->GetGlobalMinLayerPosition() : this->GetGlobalMaxLayerPosition());
511  const CartesianVector outerDirection((outerLayer == minLayer) ? this->GetGlobalMinLayerDirection() * -1.f : this->GetGlobalMaxLayerDirection());
512 
513  if (innerDirection.GetX() > -std::numeric_limits<float>::epsilon() || outerDirection.GetX() < +std::numeric_limits<float>::epsilon() ||
514  outerVertex.GetX() - innerVertex.GetX() < +std::numeric_limits<float>::epsilon())
515  {
516  return STATUS_CODE_NOT_FOUND;
517  }
518  else if (x >= outerVertex.GetX())
519  {
520  position = outerVertex + outerDirection * ((x - outerVertex.GetX()) / outerDirection.GetX());
521  }
522  else if (x <= innerVertex.GetX())
523  {
524  position = innerVertex + innerDirection * ((x - innerVertex.GetX()) / innerDirection.GetX());
525  }
526  else
527  {
528  return STATUS_CODE_NOT_FOUND;
529  }
530 
531  // TODO How to assign an uncertainty on the extrapolated position?
532  return STATUS_CODE_SUCCESS;
533 }
534 
535 //------------------------------------------------------------------------------------------------------------------------------------------
536 
538 {
539  int layer(this->GetLayer(rL));
540 
541  for (FitSegmentList::const_iterator iter = m_fitSegmentList.begin(), iterEnd = m_fitSegmentList.end(); iter != iterEnd; ++iter)
542  {
543  const FitSegment &fitSegment = *iter;
544 
545  if (layer >= fitSegment.GetStartLayer() && layer <= fitSegment.GetEndLayer())
546  return fitSegment;
547  }
548 
549  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
550 }
551 
552 // Private member functions start here
553 //------------------------------------------------------------------------------------------------------------------------------------------
554 
555 void TwoDSlidingFitResult::CalculateAxes(const CartesianPointVector &coordinateVector, const float layerPitch)
556 {
557  if (coordinateVector.size() < 2)
558  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
559 
560  CartesianVector centroid(0.f, 0.f, 0.f);
561  LArPcaHelper::EigenVectors eigenVecs;
562  LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
563  LArPcaHelper::RunPca(coordinateVector, centroid, eigenValues, eigenVecs);
564 
565  float minProjection(std::numeric_limits<float>::max());
566  CartesianVector fitDirection(eigenVecs.at(0));
567 
568  // ATTN TwoDSlidingFitResult convention is to point in direction of increasing z
569  if (fitDirection.GetZ() < 0.f)
570  fitDirection *= -1.f;
571 
572  for (const CartesianVector &coordinate : coordinateVector)
573  minProjection = std::min(minProjection, fitDirection.GetDotProduct(coordinate - centroid));
574 
575  // Define layers based on centroid rather than individual extremal hits
576  const float fitProjection(layerPitch * std::floor(minProjection / layerPitch));
577 
578  m_axisIntercept = centroid + (fitDirection * fitProjection);
579  m_axisDirection = fitDirection;
580 
581  // Use y-axis to generate an orthogonal axis (assuming that cluster occupies X-Z plane)
582  CartesianVector yAxis(0.f, 1.f, 0.f);
583  m_orthoDirection = yAxis.GetCrossProduct(m_axisDirection).GetUnitVector();
584 }
585 
586 //------------------------------------------------------------------------------------------------------------------------------------------
587 
588 void TwoDSlidingFitResult::FillLayerFitContributionMap(const CartesianPointVector &coordinateVector)
589 {
590  if (m_layerPitch < std::numeric_limits<float>::epsilon())
591  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
592 
593  if ((m_axisDirection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()) ||
594  (m_orthoDirection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()))
595  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
596 
597  if (!m_layerFitContributionMap.empty())
598  throw StatusCodeException(STATUS_CODE_FAILURE);
599 
600  for (CartesianPointVector::const_iterator iter = coordinateVector.begin(), iterEnd = coordinateVector.end(); iter != iterEnd; ++iter)
601  {
602  float rL(0.f), rT(0.f);
603  this->GetLocalPosition(*iter, rL, rT);
604  m_layerFitContributionMap[this->GetLayer(rL)].AddPoint(rL, rT);
605  }
606 }
607 
608 //------------------------------------------------------------------------------------------------------------------------------------------
609 
611 {
612  if (!m_layerFitResultMap.empty())
613  throw StatusCodeException(STATUS_CODE_FAILURE);
614 
615  if ((m_layerPitch < std::numeric_limits<float>::epsilon()) || (m_layerFitContributionMap.empty()))
616  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
617 
618  unsigned int slidingNPoints(0);
619  double slidingSumT(0.), slidingSumL(0.), slidingSumTT(0.), slidingSumLT(0.), slidingSumLL(0.);
620 
621  const LayerFitContributionMap &layerFitContributionMap(this->GetLayerFitContributionMap());
622  const int innerLayer(layerFitContributionMap.begin()->first);
623  const int layerFitHalfWindow(static_cast<int>(this->GetLayerFitHalfWindow()));
624 
625  for (int iLayer = innerLayer; iLayer < innerLayer + layerFitHalfWindow; ++iLayer)
626  {
627  LayerFitContributionMap::const_iterator lyrIter = layerFitContributionMap.find(iLayer);
628 
629  if (layerFitContributionMap.end() != lyrIter)
630  {
631  slidingSumT += lyrIter->second.GetSumT();
632  slidingSumL += lyrIter->second.GetSumL();
633  slidingSumTT += lyrIter->second.GetSumTT();
634  slidingSumLT += lyrIter->second.GetSumLT();
635  slidingSumLL += lyrIter->second.GetSumLL();
636  slidingNPoints += lyrIter->second.GetNPoints();
637  }
638  }
639 
640  const int outerLayer(layerFitContributionMap.rbegin()->first);
641 
642  for (int iLayer = innerLayer; iLayer <= outerLayer; ++iLayer)
643  {
644  const int fwdLayer(iLayer + layerFitHalfWindow);
645  LayerFitContributionMap::const_iterator fwdIter = layerFitContributionMap.find(fwdLayer);
646 
647  if (layerFitContributionMap.end() != fwdIter)
648  {
649  slidingSumT += fwdIter->second.GetSumT();
650  slidingSumL += fwdIter->second.GetSumL();
651  slidingSumTT += fwdIter->second.GetSumTT();
652  slidingSumLT += fwdIter->second.GetSumLT();
653  slidingSumLL += fwdIter->second.GetSumLL();
654  slidingNPoints += fwdIter->second.GetNPoints();
655  }
656 
657  const int bwdLayer(iLayer - layerFitHalfWindow - 1);
658  LayerFitContributionMap::const_iterator bwdIter = layerFitContributionMap.find(bwdLayer);
659 
660  if (layerFitContributionMap.end() != bwdIter)
661  {
662  slidingSumT -= bwdIter->second.GetSumT();
663  slidingSumL -= bwdIter->second.GetSumL();
664  slidingSumTT -= bwdIter->second.GetSumTT();
665  slidingSumLT -= bwdIter->second.GetSumLT();
666  slidingSumLL -= bwdIter->second.GetSumLL();
667  slidingNPoints -= bwdIter->second.GetNPoints();
668  }
669 
670  // require three points for meaningful results
671  if (slidingNPoints <= 2)
672  continue;
673 
674  // only fill the result map if there is an entry in the contribution map
675  if (layerFitContributionMap.end() == layerFitContributionMap.find(iLayer))
676  continue;
677 
678  const double denominator(slidingSumLL - slidingSumL * slidingSumL / static_cast<double>(slidingNPoints));
679 
680  if (std::fabs(denominator) < std::numeric_limits<float>::epsilon())
681  continue;
682 
683  const double gradient((slidingSumLT - slidingSumL * slidingSumT / static_cast<double>(slidingNPoints)) / denominator);
684  const double intercept((slidingSumLL * slidingSumT / static_cast<double>(slidingNPoints) - slidingSumL * slidingSumLT / static_cast<double>(slidingNPoints)) / denominator);
685  double variance((slidingSumTT - 2. * intercept * slidingSumT - 2. * gradient * slidingSumLT + intercept * intercept * static_cast<double>(slidingNPoints) + 2. * gradient * intercept * slidingSumL + gradient * gradient * slidingSumLL) / (1. + gradient * gradient));
686 
687  if (variance < -std::numeric_limits<float>::epsilon())
688  continue;
689 
690  if (variance < std::numeric_limits<float>::epsilon())
691  variance = 0.;
692 
693  const double rms(std::sqrt(variance / static_cast<double>(slidingNPoints)));
694  const double l(this->GetL(iLayer));
695  const double fitT(intercept + gradient * l);
696 
697  const LayerFitResult layerFitResult(l, fitT, gradient, rms);
698  (void) m_layerFitResultMap.insert(LayerFitResultMap::value_type(iLayer, layerFitResult));
699  }
700 
701  if (m_layerFitResultMap.empty())
702  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
703 }
704 
705 //------------------------------------------------------------------------------------------------------------------------------------------
706 
708 {
709  if (!m_fitSegmentList.empty())
710  throw StatusCodeException(STATUS_CODE_FAILURE);
711 
712  unsigned int nSustainedSteps(0);
713  float sustainedDirectionStartX(0.f), sustainedDirectionEndX(0.f);
714 
715  CartesianVector previousPosition(0.f, 0.f, 0.f);
716  TransverseDirection previousDirection(UNKNOWN), sustainedDirection(UNKNOWN);
717 
718  LayerFitResultMap::const_iterator sustainedDirectionStartIter, sustainedDirectionEndIter;
719  const LayerFitResultMap &layerFitResultMap(this->GetLayerFitResultMap());
720 
721  for (LayerFitResultMap::const_iterator iter = layerFitResultMap.begin(), iterEnd = layerFitResultMap.end(); iter != iterEnd; ++iter)
722  {
723  CartesianVector position(0.f, 0.f, 0.f);
724  this->GetGlobalPosition(iter->second.GetL(), iter->second.GetFitT(), position);
725 
726  // TODO currentDirection could also be UNCHANGED_IN_X
727  const TransverseDirection currentDirection(((position - previousPosition).GetX() > 0.f) ? POSITIVE_IN_X : NEGATIVE_IN_X);
728 
729  if (previousDirection == currentDirection)
730  {
731  ++nSustainedSteps;
732 
733  if (nSustainedSteps > 2)
734  {
735  sustainedDirection = currentDirection;
736  sustainedDirectionEndIter = iter;
737  sustainedDirectionEndX = position.GetX();
738  }
739  }
740  else
741  {
742  if ((POSITIVE_IN_X == sustainedDirection) || (NEGATIVE_IN_X == sustainedDirection))
743  m_fitSegmentList.push_back(FitSegment(sustainedDirectionStartIter->first, sustainedDirectionEndIter->first, sustainedDirectionStartX, sustainedDirectionEndX));
744 
745  nSustainedSteps = 0;
746  sustainedDirection = UNKNOWN;
747  sustainedDirectionStartIter = iter;
748  sustainedDirectionStartX = position.GetX();
749  }
750 
751  previousPosition = position;
752  previousDirection = currentDirection;
753  }
754 
755  if ((POSITIVE_IN_X == sustainedDirection) || (NEGATIVE_IN_X == sustainedDirection))
756  m_fitSegmentList.push_back(FitSegment(sustainedDirectionStartIter->first, sustainedDirectionEndIter->first, sustainedDirectionStartX, sustainedDirectionEndX));
757 }
758 
759 //------------------------------------------------------------------------------------------------------------------------------------------
760 
761 void TwoDSlidingFitResult::GetMinAndMaxCoordinate(const bool isX, float &min, float &max) const
762 {
763  if (m_layerFitResultMap.empty())
764  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
765 
768 
769  for (LayerFitResultMap::const_iterator iter = m_layerFitResultMap.begin(), iterEnd = m_layerFitResultMap.end(); iter != iterEnd; ++iter)
770  {
771  CartesianVector globalPosition(0.f, 0.f, 0.f);
772  this->GetGlobalPosition(iter->second.GetL(), iter->second.GetFitT(), globalPosition);
773  const float coordinate(isX ? globalPosition.GetX() : globalPosition.GetZ());
774  min = std::min(min, coordinate);
775  max = std::max(max, coordinate);
776  }
777 }
778 
779 //------------------------------------------------------------------------------------------------------------------------------------------
780 
781 CartesianVector TwoDSlidingFitResult::GetGlobalFitPosition(const LayerInterpolation &layerInterpolation) const
782 {
783  const LayerFitResultMap::const_iterator firstLayerIter(layerInterpolation.GetStartLayerIter());
784  const LayerFitResultMap::const_iterator secondLayerIter(layerInterpolation.GetEndLayerIter());
785 
786  const float firstWeight(layerInterpolation.GetStartLayerWeight());
787  const float secondWeight(layerInterpolation.GetEndLayerWeight());
788 
789  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
790  throw StatusCodeException(STATUS_CODE_FAILURE);
791 
792  CartesianVector firstLayerPosition(0.f, 0.f, 0.f);
793  this->GetGlobalPosition(firstLayerIter->second.GetL(), firstLayerIter->second.GetFitT(), firstLayerPosition);
794 
795  if (firstLayerIter == secondLayerIter)
796  return firstLayerPosition;
797 
798  CartesianVector secondLayerPosition(0.f, 0.f, 0.f);
799  this->GetGlobalPosition(secondLayerIter->second.GetL(), secondLayerIter->second.GetFitT(), secondLayerPosition);
800 
801  if (firstWeight + secondWeight < std::numeric_limits<float>::epsilon())
802  throw StatusCodeException(STATUS_CODE_FAILURE);
803 
804  return ((firstLayerPosition * firstWeight + secondLayerPosition * secondWeight) * (1.f / (firstWeight + secondWeight)));
805 }
806 
807 //------------------------------------------------------------------------------------------------------------------------------------------
808 
809 CartesianVector TwoDSlidingFitResult::GetGlobalFitDirection(const LayerInterpolation &layerInterpolation) const
810 {
811  const LayerFitResultMap::const_iterator firstLayerIter(layerInterpolation.GetStartLayerIter());
812  const LayerFitResultMap::const_iterator secondLayerIter(layerInterpolation.GetEndLayerIter());
813 
814  const float firstWeight(layerInterpolation.GetStartLayerWeight());
815  const float secondWeight(layerInterpolation.GetEndLayerWeight());
816 
817  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
818  throw StatusCodeException(STATUS_CODE_FAILURE);
819 
820  CartesianVector firstLayerDirection(0.f,0.f,0.f);
821  this->GetGlobalDirection(firstLayerIter->second.GetGradient(),firstLayerDirection);
822 
823  if (firstLayerIter == secondLayerIter)
824  return firstLayerDirection;
825 
826  CartesianVector secondLayerDirection(0.f,0.f,0.f);
827  this->GetGlobalDirection(secondLayerIter->second.GetGradient(),secondLayerDirection);
828 
829  if (firstWeight + secondWeight < std::numeric_limits<float>::epsilon())
830  throw StatusCodeException(STATUS_CODE_FAILURE);
831 
832  return ((firstLayerDirection * firstWeight + secondLayerDirection * secondWeight).GetUnitVector());
833 }
834 
835 //------------------------------------------------------------------------------------------------------------------------------------------
836 
837 float TwoDSlidingFitResult::GetFitRms(const LayerInterpolation &layerInterpolation) const
838 {
839  const LayerFitResultMap::const_iterator firstLayerIter(layerInterpolation.GetStartLayerIter());
840  const LayerFitResultMap::const_iterator secondLayerIter(layerInterpolation.GetEndLayerIter());
841 
842  const float firstWeight(layerInterpolation.GetStartLayerWeight());
843  const float secondWeight(layerInterpolation.GetEndLayerWeight());
844 
845  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
846  throw StatusCodeException(STATUS_CODE_FAILURE);
847 
848  const float firstLayerRms(firstLayerIter->second.GetRms());
849 
850  if (firstLayerIter == secondLayerIter)
851  return firstLayerRms;
852 
853  const float secondLayerRms(secondLayerIter->second.GetRms());
854 
855  if (firstWeight + secondWeight < std::numeric_limits<float>::epsilon())
856  throw StatusCodeException(STATUS_CODE_FAILURE);
857 
858  return ((firstLayerRms * firstWeight + secondLayerRms * secondWeight) / (firstWeight + secondWeight));
859 }
860 
861 //------------------------------------------------------------------------------------------------------------------------------------------
862 
863 StatusCode TwoDSlidingFitResult::LongitudinalInterpolation(const float rL, LayerInterpolation &layerInterpolation) const
864 {
865  double firstWeight(0.), secondWeight(0.);
866  LayerFitResultMap::const_iterator firstLayerIter, secondLayerIter;
867 
868  const StatusCode statusCode(this->GetLongitudinalSurroundingLayers(rL, firstLayerIter, secondLayerIter));
869 
870  if (STATUS_CODE_SUCCESS != statusCode)
871  return statusCode;
872 
873  this->GetLongitudinalInterpolationWeights(rL, firstLayerIter, secondLayerIter, firstWeight, secondWeight);
874  layerInterpolation = LayerInterpolation(firstLayerIter, secondLayerIter, firstWeight, secondWeight);
875 
876  return STATUS_CODE_SUCCESS;
877 }
878 
879 //------------------------------------------------------------------------------------------------------------------------------------------
880 
881 StatusCode TwoDSlidingFitResult::TransverseInterpolation(const float x, const FitSegment &fitSegment, LayerInterpolation &layerInterpolation) const
882 {
883  double firstWeight(0.), secondWeight(0.);
884  LayerFitResultMap::const_iterator firstLayerIter, secondLayerIter;
885 
886  const StatusCode statusCode(this->GetTransverseSurroundingLayers(x, fitSegment.GetStartLayer(), fitSegment.GetEndLayer(), firstLayerIter, secondLayerIter));
887 
888  if (STATUS_CODE_SUCCESS != statusCode)
889  return statusCode;
890 
891  this->GetTransverseInterpolationWeights(x, firstLayerIter, secondLayerIter, firstWeight, secondWeight);
892  layerInterpolation = LayerInterpolation(firstLayerIter, secondLayerIter, firstWeight, secondWeight);
893 
894  return STATUS_CODE_SUCCESS;
895 }
896 
897 //------------------------------------------------------------------------------------------------------------------------------------------
898 
899 StatusCode TwoDSlidingFitResult::TransverseInterpolation(const float x, LayerInterpolationList &layerInterpolationList) const
900 {
901  for (FitSegmentList::const_iterator iter = m_fitSegmentList.begin(), iterEnd = m_fitSegmentList.end(); iter != iterEnd; ++iter)
902  {
903  LayerInterpolation layerInterpolation;
904  const StatusCode statusCode(this->TransverseInterpolation(x, *iter, layerInterpolation));
905 
906  if (STATUS_CODE_SUCCESS == statusCode)
907  {
908  layerInterpolationList.push_back(layerInterpolation);
909  }
910  else if (STATUS_CODE_NOT_FOUND != statusCode)
911  {
912  return statusCode;
913  }
914  }
915 
916  return STATUS_CODE_SUCCESS;
917 }
918 
919 //------------------------------------------------------------------------------------------------------------------------------------------
920 
922  LayerFitResultMap::const_iterator &secondLayerIter) const
923 {
924  if (m_layerFitResultMap.empty())
925  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
926 
927  // Get minimum, maximum and input layers
928  const int minLayer(m_layerFitResultMap.begin()->first), maxLayer(m_layerFitResultMap.rbegin()->first);
929  const int thisLayer(this->GetLayer(rL));
930 
931  // Allow special case of single-layer sliding fit result
932  if (minLayer == thisLayer && thisLayer == maxLayer)
933  {
934  firstLayerIter = m_layerFitResultMap.find(minLayer);
935  secondLayerIter = m_layerFitResultMap.find(maxLayer);
936  return STATUS_CODE_SUCCESS;
937  }
938 
939  // For multi-layer sliding fit result, set start layer and bail out if out of range
940  const int startLayer((thisLayer >= maxLayer) ? thisLayer - 1 : thisLayer);
941 
942  if ((startLayer < minLayer) || (startLayer >= maxLayer))
943  return STATUS_CODE_NOT_FOUND;
944 
945  // First layer iterator
946  firstLayerIter = m_layerFitResultMap.end();
947 
948  for (int iLayer = startLayer; iLayer >= minLayer; --iLayer)
949  {
950  firstLayerIter = m_layerFitResultMap.find(iLayer);
951 
952  if (m_layerFitResultMap.end() != firstLayerIter)
953  break;
954  }
955 
956  if (m_layerFitResultMap.end() == firstLayerIter)
957  return STATUS_CODE_NOT_FOUND;
958 
959  // Second layer iterator
960  secondLayerIter = m_layerFitResultMap.end();
961 
962  for (int iLayer = startLayer + 1; iLayer <= maxLayer; ++iLayer)
963  {
964  secondLayerIter = m_layerFitResultMap.find(iLayer);
965 
966  if (m_layerFitResultMap.end() != secondLayerIter)
967  break;
968  }
969 
970  if (m_layerFitResultMap.end() == secondLayerIter)
971  return STATUS_CODE_NOT_FOUND;
972 
973  return STATUS_CODE_SUCCESS;
974 }
975 
976 //------------------------------------------------------------------------------------------------------------------------------------------
977 
978 StatusCode TwoDSlidingFitResult::GetTransverseSurroundingLayers(const float x, const int minLayer, const int maxLayer,
979  LayerFitResultMap::const_iterator &firstLayerIter, LayerFitResultMap::const_iterator &secondLayerIter) const
980 {
981  if (m_layerFitResultMap.empty())
982  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
983 
984  LayerFitResultMap::const_iterator minLayerIter = m_layerFitResultMap.find(minLayer);
985  if (m_layerFitResultMap.end() == minLayerIter)
986  throw StatusCodeException(STATUS_CODE_FAILURE);
987 
988  LayerFitResultMap::const_iterator maxLayerIter = m_layerFitResultMap.find(maxLayer);
989  if (m_layerFitResultMap.end() == maxLayerIter)
990  throw StatusCodeException(STATUS_CODE_FAILURE);
991 
992  CartesianVector minPosition(0.f, 0.f, 0.f), maxPosition(0.f, 0.f, 0.f);
993  this->GetGlobalPosition(minLayerIter->second.GetL(), minLayerIter->second.GetFitT(), minPosition);
994  this->GetGlobalPosition(maxLayerIter->second.GetL(), maxLayerIter->second.GetFitT(), maxPosition);
995 
996  if ((std::fabs(maxPosition.GetX() - minPosition.GetX()) < std::numeric_limits<float>::epsilon()))
997  return STATUS_CODE_NOT_FOUND;
998 
999  // Find start layer
1000  const float minL(minLayerIter->second.GetL());
1001  const float maxL(maxLayerIter->second.GetL());
1002  const float startL(minL + (maxL - minL) * (x - minPosition.GetX()) / (maxPosition.GetX() - minPosition.GetX()));
1003  const int startLayer(std::max(minLayer, std::min(maxLayer, this->GetLayer(startL))));
1004 
1005  // Find nearest layer iterator to start layer
1007  CartesianVector startLayerPosition(0.f, 0.f, 0.f);
1008 
1009  for (int iLayer = startLayer; iLayer <= maxLayer; ++iLayer)
1010  {
1011  startLayerIter = m_layerFitResultMap.find(iLayer);
1012 
1013  if (m_layerFitResultMap.end() != startLayerIter)
1014  break;
1015  }
1016 
1017  if (m_layerFitResultMap.end() == startLayerIter)
1018  return STATUS_CODE_NOT_FOUND;
1019 
1020  this->GetGlobalPosition(startLayerIter->second.GetL(), startLayerIter->second.GetFitT(), startLayerPosition);
1021 
1022  const bool startIsAhead((startLayerPosition.GetX() - x) > std::numeric_limits<float>::epsilon());
1023  const bool increasesWithLayers(maxPosition.GetX() > minPosition.GetX());
1024  const int increment = ((startIsAhead == increasesWithLayers) ? -1 : +1);
1025 
1026  // Find surrounding layer iterators
1027  // (Second layer iterator comes immediately after the fit has crossed the target X coordinate
1028  // and first layer iterator comes immediately before the second layer iterator).
1029  firstLayerIter = m_layerFitResultMap.end();
1030  secondLayerIter = m_layerFitResultMap.end();
1031 
1032  CartesianVector firstLayerPosition(0.f, 0.f, 0.f);
1033  CartesianVector secondLayerPosition(0.f, 0.f, 0.f);
1034 
1035  for (int iLayer = startLayerIter->first; (iLayer >= minLayer) && (iLayer <= maxLayer); iLayer += increment)
1036  {
1038  if (m_layerFitResultMap.end() == tempIter)
1039  continue;
1040 
1041  firstLayerIter = secondLayerIter;
1042  firstLayerPosition = secondLayerPosition;
1043  secondLayerIter = tempIter;
1044 
1045  this->GetGlobalPosition(secondLayerIter->second.GetL(), secondLayerIter->second.GetFitT(), secondLayerPosition);
1046  const bool isAhead(secondLayerPosition.GetX() > x);
1047 
1048  if (startIsAhead != isAhead)
1049  break;
1050 
1051  firstLayerIter = m_layerFitResultMap.end();
1052  }
1053 
1054  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
1055  return STATUS_CODE_NOT_FOUND;
1056 
1057  return STATUS_CODE_SUCCESS;
1058 }
1059 
1060 //------------------------------------------------------------------------------------------------------------------------------------------
1061 
1063  const LayerFitResultMap::const_iterator &secondLayerIter, double &firstWeight, double &secondWeight) const
1064 {
1065  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
1066  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
1067 
1068  const double deltaL(rL - firstLayerIter->second.GetL());
1069  const double deltaLLayers(secondLayerIter->second.GetL() - firstLayerIter->second.GetL());
1070 
1071  if (std::fabs(deltaLLayers) > std::numeric_limits<float>::epsilon())
1072  {
1073  firstWeight = 1. - deltaL / deltaLLayers;
1074  secondWeight = deltaL / deltaLLayers;
1075  }
1076  else
1077  {
1078  firstWeight = 0.5;
1079  secondWeight = 0.5;
1080  }
1081 }
1082 
1083 //------------------------------------------------------------------------------------------------------------------------------------------
1084 
1086  const LayerFitResultMap::const_iterator &secondLayerIter, double &firstWeight, double &secondWeight) const
1087 {
1088  if (m_layerFitResultMap.end() == firstLayerIter || m_layerFitResultMap.end() == secondLayerIter)
1089  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
1090 
1091  CartesianVector firstLayerPosition(0.f, 0.f, 0.f);
1092  CartesianVector secondLayerPosition(0.f, 0.f, 0.f);
1093 
1094  this->GetGlobalPosition(firstLayerIter->second.GetL(), firstLayerIter->second.GetFitT(), firstLayerPosition);
1095  this->GetGlobalPosition(secondLayerIter->second.GetL(), secondLayerIter->second.GetFitT(), secondLayerPosition);
1096 
1097  const double deltaP(x - firstLayerPosition.GetX());
1098  const double deltaPLayers(secondLayerPosition.GetX() - firstLayerPosition.GetX());
1099 
1100  if (std::fabs(deltaPLayers) > std::numeric_limits<float>::epsilon())
1101  {
1102  firstWeight = 1. - deltaP / deltaPLayers;
1103  secondWeight = deltaP / deltaPLayers;
1104  }
1105  else
1106  {
1107  firstWeight = 0.5;
1108  secondWeight = 0.5;
1109  }
1110 }
1111 
1112 } // namespace lar_content
Float_t x
Definition: compare.C:6
void FillLayerFitContributionMap(const pandora::CartesianPointVector &coordinateVector)
Fill the layer fit contribution map.
unsigned int GetLayerFitHalfWindow() const
Get the layer fit half window.
void GetMinAndMaxCoordinate(const bool isX, float &min, float &max) const
Get the minimum and maximum x or z coordinates associated with the sliding fit.
pandora::CartesianVector m_axisIntercept
The axis intercept position.
int GetStartLayer() const
Get start layer.
void GetTransverseInterpolationWeights(const float x, const LayerFitResultMap::const_iterator &firstLayerIter, const LayerFitResultMap::const_iterator &secondLayerIter, double &firstWeight, double &secondWeight) const
Get interpolation weights for layers surrounding a specified transverse position. ...
pandora::StatusCode GetTransverseSurroundingLayers(const float x, const int minLayer, const int maxLayer, LayerFitResultMap::const_iterator &firstLayerIter, LayerFitResultMap::const_iterator &secondLayerIter) const
Get iterators for layers surrounding a specified transverse position.
const pandora::Cluster * m_pCluster
The address of the cluster.
double GetEndLayerWeight() const
Get the end layer weight.
TransverseDirection
TransverseDirection enum.
void FindSlidingFitSegments()
Find sliding fit segments; sections with tramsverse direction.
pandora::StatusCode GetExtrapolatedPositionAtX(const float x, pandora::CartesianVector &position) const
Get extrapolated position (beyond span) for a given input x coordinate.
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:21
void GetLocalDirection(const pandora::CartesianVector &direction, float &dTdL) const
Get local sliding fit gradient for a given global direction.
float GetMaxLayerRms() const
Get rms at maximum layer.
pandora::CartesianVector m_axisDirection
The axis direction vector.
void GetLongitudinalInterpolationWeights(const float rL, const LayerFitResultMap::const_iterator &firstLayerIter, const LayerFitResultMap::const_iterator &secondLayerIter, double &firstWeight, double &secondWeight) const
Get interpolation weights for layers surrounding a specified longitudinal position.
float GetLayerFitHalfWindowLength() const
Get the layer fit half window length.
Header file for the principal curve analysis helper class.
pandora::StatusCode LongitudinalInterpolation(const float rL, LayerInterpolation &layerInterpolation) const
Get the pair of layers surrounding a specified longitudinal position.
pandora::CartesianVector GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
pandora::StatusCode GetLongitudinalSurroundingLayers(const float rL, LayerFitResultMap::const_iterator &firstLayerIter, LayerFitResultMap::const_iterator &secondLayerIter) const
Get iterators for layers surrounding the specified longitudinal position.
std::map< int, LayerFitContribution > LayerFitContributionMap
float GetCosScatteringAngle(const float rL) const
Get scattering angle for a given longitudinal coordinate.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
unsigned int m_layerFitHalfWindow
The layer fit half window.
TwoDSlidingFitResult(const T *const pT, const unsigned int layerFitHalfWindow, const float layerPitch)
Constructor using internal definition of primary axis.
Int_t max
Definition: plot.C:27
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
LayerFitResultMap::const_iterator GetEndLayerIter() const
Get the end layer iterator.
intermediate_table::const_iterator const_iterator
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
Header file for the cluster helper class.
float GetFitRms(const float rL) const
Get fit rms for a given longitudinal coordinate.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
double GetStartLayerWeight() const
Get the start layer weight.
Header file for the lar two dimensional sliding fit result class.
pandora::StatusCode TransverseInterpolation(const float x, const FitSegment &fitSegment, LayerInterpolation &layerInterpolation) const
Get the surrounding pair of layers for a specified transverse position and fit segment.
pandora::StatusCode GetExtrapolatedPosition(const float rL, pandora::CartesianVector &position) const
Get extrapolated position (beyond span) for a given input coordinate.
std::map< int, LayerFitResult > LayerFitResultMap
void CalculateAxes(const pandora::CartesianPointVector &coordinateVector, const float layerPitch)
Calculate the longitudinal and transverse axes.
const FitSegment & GetFitSegment(const float rL) const
Get fit segment for a given longitudinal coordinate.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
pandora::StatusCode GetExtrapolatedDirection(const float rL, pandora::CartesianVector &direction) const
Get extrapolated direction (beyond span) for a given input coordinate.
std::vector< LayerInterpolation > LayerInterpolationList
void GetGlobalDirection(const float dTdL, pandora::CartesianVector &direction) const
Get global direction coordinates for given sliding linear fit gradient.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
float GetMinLayerRms() const
Get rms at minimum layer.
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...
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
pandora::StatusCode GetGlobalFitDirection(const float rL, pandora::CartesianVector &direction) const
Get global fit direction for a given longitudinal coordinate.
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:22
Int_t min
Definition: plot.C:26
pandora::StatusCode GetGlobalFitProjection(const pandora::CartesianVector &inputPosition, pandora::CartesianVector &projectedPosition) const
Get projected position on global fit for a given position vector.
void PerformSlidingLinearFit()
Perform the sliding linear fit.
void GetGlobalPosition(const float rL, const float rT, pandora::CartesianVector &position) const
Get global coordinates for given sliding linear fit coordinates.
FitSegmentList m_fitSegmentList
The fit segment list.
pandora::CartesianVector GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
LayerFitContributionMap m_layerFitContributionMap
The layer fit contribution map.
pandora::StatusCode GetGlobalFitDirectionAtX(const float x, pandora::CartesianVector &direction) const
Get global fit direction for a given input x coordinate.
pandora::StatusCode GetTransverseProjection(const float x, const FitSegment &fitSegment, pandora::CartesianVector &position) const
Get projected position for a given input x coordinate and fit segment.
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
LayerFitResultMap::const_iterator GetStartLayerIter() const
Get the start layer iterator.
float m_layerPitch
The layer pitch, units cm.
pandora::StatusCode GetGlobalFitPositionListAtX(const float x, pandora::CartesianPointVector &positionList) const
Get a list of projected positions for a given input x coordinate.
const LayerFitContributionMap & GetLayerFitContributionMap() const
Get the layer fit contribution map.
LayerFitResultMap m_layerFitResultMap
The layer fit result map.
int GetEndLayer() const
Get end layer.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
pandora::CartesianVector m_orthoDirection
The orthogonal direction vector.
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.