3 #ifdef STANDALONE_FITTER
14 #include "TRobustEstimator.h"
34 static const double cgaus = 0.5 *
log( 2.*
M_PI );
35 return (-
pow(residual - center, 2) *0.5 / sigma / sigma) - cgaus -
log(sigma);
48 sx = fabs(sx); sy = fabs(sy);
49 static const double c2gaus =
log( 2.*
M_PI );
50 double one_r2 = 1. - r*
r;
53 return -0.5/one_r2 * (
pow(dx/sx, 2) +
pow(dy/sy, 2) - 2.*r*dx/sx*dy/sy ) - c2gaus -
log(sx*sy*
sqrt(one_r2));
59 if (gammaoversigma == 0.)
return (-toversigma*toversigma/2.) -
log(
sqrt(2*
M_PI));
63 double integrandplus_last = 0.;
64 double integrandminus_last = 0.;
65 for (
double inc = 0.; uplus <
max; inc +=
step)
67 double uplus_last = uplus;
68 uplus =
pow(inc, power);
70 double integrandplus =
exp(-
pow(uplus - toversigma, 2)/2.) / (uplus*uplus/gammaoversigma + gammaoversigma) /
M_PI /
sqrt(2.*
M_PI);
71 double integrandminus =
exp(-
pow(-uplus - toversigma, 2)/2.) / (uplus*uplus/gammaoversigma + gammaoversigma) /
M_PI /
sqrt(2.*
M_PI);
73 sum += integrandplus * (uplus - uplus_last);
74 sum += 0.5 * fabs(integrandplus_last - integrandplus) * (uplus - uplus_last);
76 sum += integrandminus * (uplus - uplus_last);
77 sum += 0.5 * fabs(integrandminus_last - integrandminus) * (uplus - uplus_last);
79 integrandplus_last = integrandplus;
80 integrandminus_last = integrandminus;
89 double gammaoversigma = fabs(gamma / sigma);
90 double toversigma = fabs((residual - center) / sigma);
100 if (gsisbad || tsisbad)
102 return log(gammaoversigma/
M_PI) -
log(toversigma*toversigma + gammaoversigma*gammaoversigma) -
log(sigma);
116 return val -
log(sigma);
130 return log(TMath::Voigt(residual - center, fabs(sigma), fabs(gamma)*2.));
136 return par[0] * TMath::Voigt(xvec[0] - par[1], fabs(par[2]), fabs(par[3])*2.);
141 double x = residual-center;
142 double s = fabs(sigma);
146 double n = sqerf*s + 2.*a*
pow(m,-3)/3.;
148 if (fabs(x)<m)
return -x*x/(2.*s*
s) -
log(n);
149 else return log(a) -4.*
log(fabs(x)) -
log(n);
161 static const double isqr2 = 1./
sqrt(2.);
162 return (erf((high + center) * isqr2 / sigma) - erf((low + center) * isqr2 / sigma)) *
exp(0.5/sigma/sigma) * 0.5;
171 std::ifstream convolution_table(
"convolution_table.txt");
172 if (convolution_table.is_open())
176 double tsbinsize = 0.;
177 double gsbinsize = 0.;
179 convolution_table >> numgsbins >> numtsbins >> tsbinsize >> gsbinsize;
183 throw cms::Exception(
"MuonResidualsFitter") <<
"convolution_table.txt has the wrong bin width/bin size. Throw it away and let the fitter re-create the file.\n";
194 convolution_table >> read_gsbin >> read_tsbin >> val;
195 if (read_gsbin != gsbin || read_tsbin != tsbin)
197 throw cms::Exception(
"MuonResidualsFitter") <<
"convolution_table.txt is out of order. Throw it away and let the fitter re-create the file.\n";
202 convolution_table.close();
206 std::ofstream convolution_table2(
"convolution_table.txt");
208 if (!convolution_table2.is_open())
throw cms::Exception(
"MuonResidualsFitter") <<
"Couldn't write to file convolution_table.txt\n";
212 std::cout <<
"Initializing convolution look-up table (takes a few minutes)..." << std::endl;
217 std::cout <<
" gsbin " << gsbin <<
"/" << MuonResidualsFitter_numgsbins << std::endl;
231 convolution_table2.close();
232 std::cout <<
"Initialization done!" << std::endl;
238 std::vector<double> &
start, std::vector<double> &
step, std::vector<double> &low, std::vector<double> &high)
248 std::vector<int>::const_iterator iNum = parNum.begin();
249 std::vector<std::string>::const_iterator iName = parName.begin();
250 std::vector<double>::const_iterator istart = start.begin();
251 std::vector<double>::const_iterator istep = step.begin();
252 std::vector<double>::const_iterator ilow = low.begin();
253 std::vector<double>::const_iterator ihigh = high.begin();
257 for (; iNum != parNum.end(); ++iNum, ++iName, ++istart, ++istep, ++ilow, ++ihigh)
268 for (
int i = 0;
i < 10;
i++) arglist[
i] = 0.;
276 for (
int i = 0;
i < 10;
i++) arglist[
i] = 0.;
282 bool try_again =
false;
285 for (
int i = 0;
i < 10;
i++) arglist[
i] = 0.;
289 if (ierflg != 0) try_again =
true;
294 for (
int i = 0;
i < 10;
i++) arglist[
i] = 0.;
299 Double_t fmin, fedm, errdef;
300 Int_t npari, nparx, istat;
305 for (
int i = 0;
i < 10;
i++) arglist[
i] = 0.;
315 for (
int i = 0;
i <
npar();
i++)
327 if (smierflg != 0)
return false;
336 int whichcopy = which;
338 fwrite(&rows,
sizeof(
long), 1, file);
339 fwrite(&cols,
sizeof(
int), 1, file);
340 fwrite(&whichcopy,
sizeof(
int), 1, file);
342 double *likeAChecksum =
new double[cols];
343 double *likeAChecksum2 =
new double[cols];
344 for (
int i = 0;
i < cols;
i++)
346 likeAChecksum[
i] = 0.;
347 likeAChecksum2[
i] = 0.;
352 fwrite((*residual),
sizeof(
double), cols, file);
353 for (
int i = 0;
i < cols;
i++)
355 if (fabs((*residual)[
i]) > likeAChecksum[i]) likeAChecksum[
i] = fabs((*residual)[i]);
356 if (fabs((*residual)[i]) < likeAChecksum2[i]) likeAChecksum2[
i] = fabs((*residual)[i]);
362 fwrite(likeAChecksum,
sizeof(
double), cols, file);
363 fwrite(likeAChecksum2,
sizeof(
double), cols, file);
365 delete [] likeAChecksum;
366 delete [] likeAChecksum2;
373 int readwhich = -100;
375 fread(&rows,
sizeof(
long), 1, file);
376 fread(&cols,
sizeof(
int), 1, file);
377 fread(&readwhich,
sizeof(
int), 1, file);
379 if (cols !=
ndata() || rows < 0 || readwhich != which)
381 throw cms::Exception(
"MuonResidualsFitter") <<
"temporary file is corrupted (which = " << which <<
" readwhich = " << readwhich <<
" rows = " << rows <<
" cols = " << cols <<
")\n";
384 double *likeAChecksum =
new double[cols];
385 double *likeAChecksum2 =
new double[cols];
386 for (
int i = 0;
i < cols;
i++)
388 likeAChecksum[
i] = 0.;
389 likeAChecksum2[
i] = 0.;
393 for (
long row = 0; row <
rows; row++)
395 double *residual =
new double[cols];
396 fread(residual,
sizeof(
double), cols, file);
398 for (
int i = 0;
i < cols;
i++)
400 if (fabs(residual[
i]) > likeAChecksum[i]) likeAChecksum[
i] = fabs(residual[i]);
401 if (fabs(residual[i]) < likeAChecksum2[i]) likeAChecksum2[
i] = fabs(residual[i]);
405 double *readChecksum =
new double[cols];
406 double *readChecksum2 =
new double[cols];
407 fread(readChecksum,
sizeof(
double), cols, file);
408 fread(readChecksum2,
sizeof(
double), cols, file);
410 for (
int i = 0;
i < cols;
i++)
412 if (fabs(likeAChecksum[
i] - readChecksum[
i]) > 1
e-10 || fabs(1./likeAChecksum2[i] - 1./readChecksum2[i]) > 1e10)
414 throw cms::Exception(
"MuonResidualsFitter") <<
"temporary file is corrupted (which = " << which <<
" rows = " << rows <<
" likeAChecksum " << likeAChecksum[
i] <<
" != readChecksum " << readChecksum[
i] <<
" " <<
" likeAChecksum2 " << likeAChecksum2[
i] <<
" != readChecksum2 " << readChecksum2[
i] <<
")\n";
420 delete [] likeAChecksum;
421 delete [] likeAChecksum2;
428 if (which == 0) window = 2.*30.;
429 else if (which == 1) window = 2.*30.;
430 else if (which == 2) window = 2.*20.;
431 else if (which == 3) window = 2.*50.;
441 if (which == 0) window = 2.*30.;
442 else if (which == 1) window = 2.*30.;
443 else if (which == 2) window = 2.*20.;
444 else if (which == 3) window = 2.*50.;
449 double weight = 1./(*r)[whichredchi2];
450 if (TMath::Prob(1./weight*12, 12) < 0.99) hist->Fill(multiplier * (*
r)[which], weight);
461 if (fabs((*
r)[which])<50.)
463 data[
n] = (*r)[which];
468 const int n_quantiles = 7;
469 double probabilities[n_quantiles] = {0.00135, 0.02275, 0.25, 0.5, 0.75, 0.97725, 0.99865};
471 double quantiles[n_quantiles];
473 TMath::Quantiles(n, n_quantiles, data, quantiles, probabilities,
true,
NULL, 7);
475 double iqr = quantiles[4] - quantiles[2];
478 double hbin = 2 * iqr /
pow( n, 1./3);
482 nbins = (int) ( (b - a) / hbin + 3. );
487 std::cout<<
" optimal h="<<hbin<<
" nbins="<<nbins<<std::endl;
496 if (a==b || a > b) { fit_mean =
a; fit_sigma = 0;
return; }
498 TH1D *
hist =
new TH1D(
"htmp",
"", nbins, a, b);
502 TF1 *
f1=
new TF1(
"f1",
"gaus", a, b);
503 f1->SetParameter(0, hist->GetEntries());
504 f1->SetParameter(1, 0);
505 f1->SetParameter(2, hist->GetRMS());
506 hist->Fit(
"f1",
"RQ");
508 fit_mean = f1->GetParameter(1);
509 fit_sigma = f1->GetParameter(2);
510 std::cout<<
" h("<<nbins<<
","<<a<<
","<<b<<
") mu="<<fit_mean<<
" sig="<<fit_sigma<<std::endl;
529 for (
int v = 0;
v<nvar;
v++)
540 double ellipsoid_sum = 0;
541 for (
int v = 0;
v<nvar;
v++)
544 if (
m_radii[which] == 0.)
continue;
547 if (ellipsoid_sum <= 1.) ++
r;
571 assert(nvar<=10 && nvar>0);
579 double *
data =
new double[nbefore];
583 re.EvaluateUni(nbefore, data, peak, sigma);
588 double distance = fabs( ((*r)[ vars[0] ] - peak)/sigma );
589 if (distance <= nsigma) ++
r;
603 TRobustEstimator re(nbefore, nvar);
607 double *row =
new double[nvar];
608 for (
int v = 0;
v<nvar;
v++) row[
v] = (*r)[ vars[
v] ];
618 TMatrixDSym Cov(nvar);
619 re.GetCovariance(Cov);
623 double conf_1d = TMath::Erf(nsigma/
sqrt(2));
624 double surf_radius =
sqrt(TMath::ChisquareQuantile(conf_1d, nvar));
631 for (
int v = 0;
v<nvar;
v++) res[
v] = (*r)[ vars[
v] ];
632 double distance =
sqrt( Cov.Similarity(res - M) );
633 if (distance <= surf_radius) ++
r;
650 double min_pt = 9999.;
653 double pt = fabs((*
r)[idx_momentum]);
654 if (pt < min_pt) min_pt =
pt;
657 const double bin_width = 1./min_pt/Nbin;
660 std::vector<size_t> pos[Nbin], neg[Nbin], to_erase;
664 int bin = (int)floor(1./fabs(
m_residuals[i][idx_momentum])/bin_width);
666 else neg[
bin].push_back(i);
670 for (
int j = 0;
j < Nbin;
j++)
672 size_t psize = pos[
j].size();
673 size_t nsize = neg[
j].size();
674 if (psize == nsize)
continue;
676 std::set<int> idx_set;
679 while (idx_set.size() < psize - nsize) idx_set.insert( gRandom->Integer(psize) );
680 for (std::set<int>::iterator it = idx_set.begin() ; it != idx_set.end(); it++ ) to_erase.push_back(pos[
j][*it]);
684 while (idx_set.size() < nsize - psize) idx_set.insert( gRandom->Integer(nsize) );
685 for (std::set<int>::iterator it = idx_set.begin() ; it != idx_set.end(); it++ ) to_erase.push_back(neg[
j][*it]);
689 std::sort(to_erase.begin(), to_erase.end(), std::greater<int>() );
690 for (std::vector<size_t>::const_iterator
e = to_erase.begin();
e != to_erase.end(); ++
e)
697 std::vector<size_t> apos[Nbin], aneg[Nbin];
701 int bin = (int)floor(1./fabs(
m_residuals[i][idx_momentum])/bin_width);
703 else aneg[
bin].push_back(i);
705 for (
int j = 0;
j < Nbin;
j++)
std::cout <<
"bin " <<
j <<
": [pos,neg] sizes before & after: ["
706 << pos[
j].
size() <<
","<< neg[
j].size()<<
"] -> [" << apos[
j].size() <<
","<< aneg[
j].size() <<
"]" << std::endl;
715 std::vector<double*>
tmp(n_ok, 0);
725 std::vector<bool> tmp_ok(n_ok,
true);
void histogramChi2GaussianFit(int which, double &fit_mean, double &fit_sigma)
double MuonResidualsFitter_logGaussPowerTails(double residual, double center, double sigma)
double MuonResidualsFitter_integrate_pureGaussian(double low, double high, double center, double sigma)
tuple start
Check for commandline option errors.
Double_t MuonResidualsFitter_powerLawTails_TF1(Double_t *xvec, Double_t *par)
virtual void inform(TMinuit *tMinuit)=0
void computeHistogramRangeAndBinning(int which, int &nbins, double &a, double &b)
void selectPeakResiduals(double nsigma, int nvar, int *vars)
const int MuonResidualsFitter_numgsbins
double MuonResidualsFitter_logPureGaussian2D(double x, double y, double x0, double y0, double sx, double sy, double r)
void write(FILE *file, int which=0)
long numResiduals() const
void eraseNotSelectedResiduals()
std::vector< double > m_error
void read(FILE *file, int which=0)
void fill(double *residual)
int residualsModel() const
bool dofit(void(*fcn)(int &, double *, double &, double *, int), std::vector< int > &parNum, std::vector< std::string > &parName, std::vector< double > &start, std::vector< double > &step, std::vector< double > &low, std::vector< double > &high)
double MuonResidualsFitter_logROOTVoigt(double residual, double center, double sigma, double gamma)
double MuonResidualsFitter_compute_log_convolution(double toversigma, double gammaoversigma, double max=1000., double step=0.001, double power=4.)
std::vector< double > m_value
std::vector< double * > m_residuals
const T & max(const T &a, const T &b)
const int MuonResidualsFitter_numtsbins
double MuonResidualsFitter_logPowerLawTails(double residual, double center, double sigma, double gamma)
const double MuonResidualsFitter_gsbinsize
std::vector< bool > m_residuals_ok
Double_t MuonResidualsFitter_GaussPowerTails_TF1(Double_t *xvec, Double_t *par)
T * make(const Args &...args) const
make new ROOT object
virtual void correctBField()=0
const double MuonResidualsFitter_tsbinsize
static TMinuit * MuonResidualsFitter_TMinuit
Double_t MuonResidualsFitter_pureGaussian_TF1(Double_t *xvec, Double_t *par)
void plotsimple(std::string name, TFileDirectory *dir, int which, double multiplier)
void fcn(int &, double *, double &, double *, int)
std::vector< double * >::const_iterator residuals_end() const
std::vector< std::vector< double > > tmp
char data[epos_bytes_allocation]
void plotweighted(std::string name, TFileDirectory *dir, int which, int whichredchi2, double multiplier)
bool MuonResidualsFitter_table_initialized
double MuonResidualsFitter_lookup_table[MuonResidualsFitter_numgsbins][MuonResidualsFitter_numtsbins]
void selectPeakResiduals_simple(double nsigma, int nvar, int *vars)
Double_t MuonResidualsFitter_ROOTVoigt_TF1(Double_t *xvec, Double_t *par)
std::vector< double * >::const_iterator residuals_begin() const
double MuonResidualsFitter_logPureGaussian(double residual, double center, double sigma)
tuple size
Write out results.
Power< A, B >::type pow(const A &a, const B &b)