61 throw cet::exception(
"HitLineFitAlg") <<
"Invalid fit parameters. Fix it!";
67 float horiz,vert,
dist,ssr,diff,fiterr;
68 TVector3 hitloc,lineloc1,lineloc2;
70 std::vector<float> distances;
73 std::vector<unsigned int> points;
74 std::vector<unsigned int> points_best;
75 std::vector<unsigned int> bestkeys;
76 std::vector<unsigned int> datakeys;
79 bestfit.fitsuccess =
false;
84 TGraphAsymmErrors * maybe =
new TGraphAsymmErrors();
85 TGraphAsymmErrors * maybebetter =
new TGraphAsymmErrors();
91 model->SetParNames(
"constant",
"linear",
"quadratic",
"cubic",
"quartic",
"quintic");
94 model->SetParLimits(ipar.first,ipar.second.min,ipar.second.max);
95 model->SetParameter(ipar.first,ipar.second.start);
104 if (n >= data.size())
return -1;
108 if (d < 2*n || n < 2)
return -2;
111 for (i = 0; i < data.size(); ++i) datakeys.push_back(i);
114 if (
fLogLevel > 1) std::cout <<
"Minimum number of data points required to fit the model, n=" << n <<
"\n" 115 <<
"Maximum number of iterations allowed, k=" << k <<
"\n" 116 <<
"Threshold value for model inclusion (cm), t=" << t <<
"\n" 117 <<
"Number of close data points required to assert a good fit, d=" << d <<
std::endl;
121 while (iterations < k)
127 maybebetter->Clear();
133 if (iterations % 1000 == 0) std::cout <<
"Iteration # " << iterations <<
std::endl;
140 for (i = 0; i <
n; ++i)
142 points.push_back(datakeys[i]);
143 HitLineFitData thisdata = data.at(datakeys[i]);
144 maybe->SetPoint(i,thisdata.hitHoriz,thisdata.hitVert);
145 maybe->SetPointError(i,thisdata.hitHorizErrLo,
146 thisdata.hitHorizErrHi,
147 thisdata.hitVertErrLo,
148 thisdata.hitVertErrHi);
152 TFitResultPtr
r = maybe->Fit(
"model",
"SQCBR0");
155 for (i = n; i < data.size(); ++i)
157 vert = data.at(datakeys[i]).hitVert;
158 horiz = data.at(datakeys[i]).hitHoriz;
159 hitloc.SetXYZ(horiz,vert,0.);
160 double xloc1[1] = { horiz-1 };
161 double xloc2[1] = { horiz+1 };
162 lineloc1.SetXYZ(horiz-1,model->EvalPar(xloc1,r->GetParams()),0.);
163 lineloc2.SetXYZ(horiz+1,model->EvalPar(xloc2,r->GetParams()),0.);
165 if (dist <= t) points.push_back(datakeys[i]);
169 if (points.size() - n >
d)
172 for (i = 0; i < points.size(); ++i)
174 HitLineFitData thisdata = data.at(points[i]);
175 maybebetter->SetPoint(i,thisdata.hitHoriz,thisdata.hitVert);
176 maybebetter->SetPointError(i,thisdata.hitHorizErrLo,thisdata.hitHorizErrHi,thisdata.hitVertErrLo,thisdata.hitVertErrHi);
180 TFitResultPtr rb = maybebetter->Fit(
"model",
"SQCBR0");
184 for (i = 0; i < points.size(); ++i)
186 vert = data.at(points[i]).hitVert;
187 horiz = data.at(points[i]).hitHoriz;
188 hitloc.SetXYZ(horiz,vert,0.);
189 double xloc1[1] = { horiz-1 };
190 double xloc2[1] = { horiz+1 };
191 lineloc1.SetXYZ(horiz-1,model->EvalPar(xloc1,rb->GetParams()),0.);
192 lineloc2.SetXYZ(horiz+1,model->EvalPar(xloc2,rb->GetParams()),0.);
194 distances.push_back(fabs(dist));
198 points_best.push_back(points[i]);
201 if (points_best.size() < 2)
continue;
204 float sigma = TMath::Median(distances.size(),distances.data());
206 float p_outlier_prob = 0;
208 std::vector<float> p_inlier_prob(distances.size());
209 for (
int j = 0; j < 3; ++j)
211 for (i = 0; i < distances.size(); ++i)
213 p_inlier_prob[i] = gamma*TMath::Exp(-(distances[i]*distances[i])/(2*sigma*sigma))/(TMath::Sqrt(2*TMath::Pi())*sigma);
215 p_outlier_prob = (1-
gamma)/v;
217 for (i = 0; i < distances.size(); ++i)
219 gamma += p_inlier_prob[i]/(p_inlier_prob[i]+p_outlier_prob);
221 if (distances.size() > 0) gamma /= distances.size();
223 float d_cur_penalty = 0;
224 for (i = 0; i < distances.size(); ++i)
226 d_cur_penalty += TMath::Log(p_inlier_prob[i]+p_outlier_prob);
228 d_cur_penalty = (-d_cur_penalty);
232 if (d_cur_penalty < fiterr && fabs(model->GetParameter(
"linear")) > 0.0015)
234 diff = d_cur_penalty-fiterr;
235 fiterr = d_cur_penalty;
236 for (
auto & ipar : fParIVal)
238 bestfit.bestVal[ipar.first] = model->GetParameter(ipar.first);
239 bestfit.bestValError[ipar.first] = model->GetParError(ipar.first);
241 bestfit.chi2 = model->GetChisquare();
242 bestfit.ndf = model->GetNDF();
243 bestfit.sum2resid = ssr;
244 bestfit.mle = fiterr;
245 bestfit.fitsuccess =
true;
248 for (i = 0; i < data.size(); i++)
250 if (std::find(points_best.begin(),points_best.end(),i) != points_best.end())
252 data.at(i).hitREAL =
true;
256 data.at(i).hitREAL =
false;
261 std::cout <<
"-------------Found new minimum!-------------" << std::endl
262 <<
"FitError=" << fiterr <<
" delta(fiterr)=" << diff << std::endl
263 <<
"Number of points included = " << points_best.size() <<
" out of " << data.size() << std::endl
264 <<
"--------------------------------------------" <<
std::endl;
269 if (bestfit.fitsuccess)
return 1;
float PointToLineDist(TVector3 ptloc, TVector3 linept1, TVector3 linept2)
std::map< int, ParVals > fParIVal
static int max(int a, int b)
float fIterationsMultiplier
double gamma(double KE, const simb::MCParticle *part)
bool CheckModelParameters()
void DeterministicShuffle(std::vector< unsigned int > &vec)
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
float fInclusionThreshold
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)