Belle II Software  release-08-01-10
TOPTemplateFitter.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <top/utilities/TOPTemplateFitter.h>
10 #include <top/geometry/TOPGeometryPar.h>
11 #include <framework/logging/Logger.h>
12 
13 #include <algorithm>
14 
15 using namespace Belle2;
16 using namespace Belle2::TOP;
17 
18 using namespace std;
19 
24 std::vector<double> TOPTemplateFitter::s_templateSamples;
27 
29  const TOPSampleTimes& sampleTimes,
30  const double averageRMS)
31  : m_wf(wf), m_sampleTimes(sampleTimes), m_averageRMS(averageRMS)
32 {
33  m_chisq = -1.;
36  }
37 }
38 
40 {
41  s_templateParameters = params;
43 }
44 
46 {
47  s_totalTemplateSamples = nSamples;
49 
50 }
51 
53 {
54  s_templateResolution = resolution;
55  s_fineOffsetRange = resolution * 5;
57 }
58 
60 {
61  s_templateSamples.clear();
63  B2FATAL("rising edge of template function invalid!");
64  }
65 
66  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
67  const auto& signalShape = geo->getSignalShape();
68  const auto& tdc = geo->getNominalTDC();
69  const double dt = tdc.getSampleWidth();
70 
71  for (double x = 0; x < s_totalTemplateSamples; x += 1. / s_templateResolution) {
72  s_templateSamples.push_back(s_templateParameters.amplitude * signalShape.getValue((x - s_templateParameters.risingEdge)*dt));
73  }
74 
75  s_templateReInitialize = false;
76 }
77 
78 void TOPTemplateFitter::performTemplateFit(const double risingEdgeStart,
79  const double fitRange)
80 {
83  }//do this here to make sure nobody changed template settings? -> thread safety?
84 
85  //access time base correction and calculate correction to waveform sample number
86  vector<short> pedestals(m_wf.getSize(), m_averageRMS);//for now assume constant pedestals for TOP
87  vector<float> timingCorrection(m_wf.getSize(),
88  0.);//timing correction, should be relative to each sample in in units of samples -> pick correct template sample
89 
90  //perform template fit
91  m_chisq_vec.clear();
92  m_chisq = 1e6;
93  PerformTemplateFitMinimize(m_wf.getWaveform(), pedestals, timingCorrection, risingEdgeStart, fitRange);
94 
95  //use paraboic shape of chi^2 distribution to improve fit result
96  if (s_useParabola) {
97  auto it = std::min_element(std::begin(m_chisq_vec), std::end(m_chisq_vec));
98  int minidx = std::distance(std::begin(m_chisq_vec), it);
99  if (minidx > 0 && minidx < (int)m_chisq_vec.size() - 1) {
100  Point vertex;
101  CalculateParabolaVertex({ -1, m_chisq_vec[minidx - 1]}, {0, m_chisq_vec[minidx]}, {1, m_chisq_vec[minidx + 1]}, vertex);
102  m_chisq = vertex.second;
103  m_result.risingEdge += vertex.first / s_templateResolution;
104  }
105  }
106 }
107 
108 void TOPTemplateFitter::CalculateParabolaVertex(const Point& p1, const Point& p2, const Point& p3, Point& vertex)
109 {
110  double denom = (p1.first - p2.first) * (p1.first - p3.first) * (p2.first - p3.first);
111  double a = (p3.first * (p2.second - p1.second) + p2.first * (p1.second - p3.second) + p1.first *
112  (p3.second - p2.second)) / denom;
113  double b = (p3.first * p3.first * (p1.second - p2.second) + p2.first * p2.first * (p3.second - p1.second)
114  + p1.first * p1.first * (p2.second - p3.second)) / denom;
115  double c = (p2.first * p3.first * (p2.first - p3.first) * p1.second + p3.first * p1.first * (p3.first - p1.first) * p2.second
116  + p1.first * p2.first * (p1.first - p2.first) * p3.second) / denom;
117 
118  vertex.first = -b / (2 * a);
119  vertex.second = c - b * b / (4 * a);
120 }
121 
122 void TOPTemplateFitter::PerformTemplateFitMinimize(const std::vector<short>& samples, const std::vector<short>& pedestals,
123  const std::vector<float>& timingCorrection, const double risingEdgeCFD, const double fitRange)
124 {
125  if (samples.size() != pedestals.size() || samples.size() != timingCorrection.size()) {
126  B2FATAL("Size of sample, pedestal and timing correction vectors has to be equal!");
127  }
128 
129 
130  MinimizationSums sums;
131  FitResult result;
132  int initialOffset = risingEdgeCFD - s_templateParameters.risingEdge;
133  //offset search loop
134  for (int fineOffset = -s_fineOffsetRange; fineOffset < s_fineOffsetRange; ++fineOffset) {
135  sums.clear();
136  int totalTemplateOffset = initialOffset * s_templateResolution + fineOffset;
137  for (int signalSampleIndex = risingEdgeCFD - fitRange; signalSampleIndex < risingEdgeCFD + fitRange; ++signalSampleIndex) {
138  if (signalSampleIndex < 0 || signalSampleIndex > (int)samples.size() - 1) continue;
139  int templateIndex = signalSampleIndex * s_templateResolution - totalTemplateOffset + timingCorrection[signalSampleIndex];
140  if (templateIndex < 0 || templateIndex > (int) s_templateSamples.size() - 1) continue;
141  double weight = 1. / (pedestals[signalSampleIndex] * pedestals[signalSampleIndex]);
142  double Sx = weight * s_templateSamples[templateIndex];
143  double Sy = weight * samples[signalSampleIndex];
144  sums.S1 += weight;
145  sums.Sx += Sx;
146  sums.Sy += Sy;
147  sums.Sxx += Sx * s_templateSamples[templateIndex];
148  sums.Sxy += Sy * s_templateSamples[templateIndex];
149  sums.Syy += Sy * samples[signalSampleIndex];
150  }
151  double chisq = ComputeMinimizedParametersAndChisq(sums, result);
152  m_chisq_vec.push_back(chisq);
153  if (chisq < m_chisq) { //save minimal chisq result
154  m_chisq = chisq;
155  m_result = result;
156  m_result.risingEdge = totalTemplateOffset;
157  }
158  }
159  //template offset back to sample space and scale amplitude
163 }
164 
166 {
167  const double determinant = sums.S1 * sums.Sxx - sums.Sx * sums.Sx;
168  result.amplitude = (-sums.Sx * sums.Sy + sums.S1 * sums.Sxy) / determinant;
169  result.backgroundOffset = (sums.Sxx * sums.Sy - sums.Sx * sums.Sxy) / determinant;
170  result.amplitudeError = sums.S1 / determinant;
171  result.backgroundOffsetError = sums.Sxx / determinant;
172  return sums.Syy - result.backgroundOffset * sums.Sy - result.amplitude * sums.Sxy;
173 }
const TOPSignalShape & getSignalShape() const
Returns single photon signal shape.
Definition: TOPGeometry.h:224
Class to store raw data waveforms.
unsigned getSize() const
Returns waveform size.
const std::vector< short > & getWaveform() const
Returns waveform.
Calibration constants of a singe ASIC channel: time axis (sample times)
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
static int s_fineOffsetRange
range for offset between template and signal
static void InitializeTemplateFit()
Intializes the template fit using default values.
static TemplateParameters s_templateParameters
parameters used for the template calculation
std::vector< double > m_chisq_vec
all computed chi square values from template fit
const TOPRawWaveform m_wf
raw sampled waveforms
void PerformTemplateFitMinimize(const std::vector< short > &samples, const std::vector< short > &pedestals, const std::vector< float > &timingCorrection, const double risingEdgeCFD, const double fitRange)
performs the template fit
void performTemplateFit(const double risingEdgeStart, const double fitRange)
Prepares data and performs the template fit in sample space.
static bool s_templateReInitialize
flag showing that the template samples have to be recomputed
const double m_averageRMS
average RMS of waveform samples, no database for this
static int s_templateResolution
resolution of template with respect to normal sample spacing
void CalculateParabolaVertex(const Point &p1, const Point &p2, const Point &p3, Point &vertex)
Calculate vertex coordinates of parabola given three data points.
static void setTemplateParameters(const TemplateParameters &params)
Sets the template parameters.
double m_chisq
chi square value from template fit
static void setTemplateSamples(int nSamples)
Set the total number of template samples.
FitResult m_result
fit result from template fit
TOPTemplateFitter(const TOPRawWaveform &wf, const TOPSampleTimes &sampleTimes, const double averageRMS)
full constructor
double ComputeMinimizedParametersAndChisq(const MinimizationSums &sums, FitResult &result)
Compute the minimized parameters and chi square value.
static std::vector< double > s_templateSamples
precomputed template samples
static bool s_useParabola
try improving fit by making use of parabolic shape of chisq values
static void setTemplateResolution(int resolution)
Set the template resolution.
static int s_totalTemplateSamples
number of samples used for template
Abstract base class for different kinds of events.
structure holding values from template fit
double amplitudeError
fitted amplitude error
Variables used during template fit minimization.
double Sxy
sum of signal sample *template*weight
double Syy
sum of signal sample * signal sample * weight
double Sxx
sum of template*template*weight
void clear()
set sums used during template fit to initial values
double Sy
sum of signal sample * weight
Parameters of the template function.
double amplitude
amplitude of template function
double risingEdge
rising edge position of template in samples