26 ClassImp(TLinearFitter);
29 std::map<TString,TFormula*> TLinearFitter::fgFormulaMap;
223 TLinearFitter::TLinearFitter() :
265 TLinearFitter::TLinearFitter(Int_t ndim) :
294 TLinearFitter::TLinearFitter(Int_t ndim,
const char *formula, Option_t *opt)
307 if (option.Contains(
"D"))
327 TLinearFitter::TLinearFitter(TFormula *
function, Option_t *opt)
329 fNdim=
function->GetNdim();
330 if (!function->IsLinear()){
331 Int_t number=
function->GetNumber();
332 if (number<299 || number>310){
333 Error(
"TLinearFitter",
"Trying to fit with a nonlinear function");
346 if (option.Contains(
"D"))
354 SetFormula(
function);
360 TLinearFitter::TLinearFitter(
const TLinearFitter& tlf) :
362 fParams(tlf.fParams),
363 fParCovar(tlf.fParCovar),
364 fTValues(tlf.fTValues),
365 fParSign(tlf.fParSign),
366 fDesign(tlf.fDesign),
367 fDesignTemp(tlf.fDesignTemp),
368 fDesignTemp2(tlf.fDesignTemp2),
369 fDesignTemp3(tlf.fDesignTemp3),
371 fAtbTemp(tlf.fAtbTemp),
372 fAtbTemp2(tlf.fAtbTemp2),
373 fAtbTemp3(tlf.fAtbTemp3),
374 fFunctions( * (TObjArray *)tlf.fFunctions.Clone()),
377 fY2Temp(tlf.fY2Temp),
380 fInputFunction(tlf.fInputFunction),
382 fNpoints(tlf.fNpoints),
383 fNfunctions(tlf.fNfunctions),
384 fFormulaSize(tlf.fFormulaSize),
386 fNfixed(tlf.fNfixed),
387 fSpecial(tlf.fSpecial),
390 fStoreData(tlf.fStoreData),
391 fChisquare(tlf.fChisquare),
393 fRobust(tlf.fRobust),
394 fFitsample(tlf.fFitsample),
400 if ( tlf.fFixedParams && fNfixed > 0 ) {
401 fFixedParams=
new Bool_t[fNfixed];
402 for(Int_t i=0; i<fNfixed; ++i)
403 fFixedParams[i]=tlf.fFixedParams[i];
406 fFormula =
new char[fFormulaSize+1];
407 strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
416 TLinearFitter::~TLinearFitter()
423 delete [] fFixedParams;
436 TLinearFitter& TLinearFitter::operator=(
const TLinearFitter& tlf)
440 TVirtualFitter::operator=(tlf);
441 fParams.ResizeTo(tlf.fParams); fParams=tlf.fParams;
442 fParCovar.ResizeTo(tlf.fParCovar); fParCovar=tlf.fParCovar;
443 fTValues.ResizeTo(tlf.fTValues); fTValues=tlf.fTValues;
444 fParSign.ResizeTo(tlf.fParSign); fParSign=tlf.fParSign;
445 fDesign.ResizeTo(tlf.fDesign); fDesign=tlf.fDesign;
446 fDesignTemp.ResizeTo(tlf.fDesignTemp); fDesignTemp=tlf.fDesignTemp;
447 fDesignTemp2.ResizeTo(tlf.fDesignTemp2); fDesignTemp2=tlf.fDesignTemp2;
448 fDesignTemp3.ResizeTo(tlf.fDesignTemp3); fDesignTemp3=tlf.fDesignTemp3;
450 fAtb.ResizeTo(tlf.fAtb); fAtb=tlf.fAtb;
451 fAtbTemp.ResizeTo(tlf.fAtbTemp); fAtbTemp=tlf.fAtbTemp;
452 fAtbTemp2.ResizeTo(tlf.fAtbTemp2); fAtbTemp2=tlf.fAtbTemp2;
453 fAtbTemp3.ResizeTo(tlf.fAtbTemp3); fAtbTemp3=tlf.fAtbTemp3;
457 fFunctions= *(TObjArray*) tlf.fFunctions.Clone();
459 fY.ResizeTo(tlf.fY); fY = tlf.fY;
460 fX.ResizeTo(tlf.fX); fX = tlf.fX;
461 fE.ResizeTo(tlf.fE); fE = tlf.fE;
464 fY2Temp = tlf.fY2Temp;
465 for(Int_t i = 0; i < 1000; i++) fVal[i] = tlf.fVal[i];
467 if(fInputFunction) {
delete fInputFunction; fInputFunction = 0; }
468 if(tlf.fInputFunction) fInputFunction =
new TFormula(*tlf.fInputFunction);
470 fNpoints=tlf.fNpoints;
471 fNfunctions=tlf.fNfunctions;
472 fFormulaSize=tlf.fFormulaSize;
475 fSpecial=tlf.fSpecial;
477 if(fFormula) {
delete [] fFormula; fFormula = 0; }
479 fFormula =
new char[fFormulaSize+1];
480 strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
484 fStoreData=tlf.fStoreData;
485 fChisquare=tlf.fChisquare;
489 fFitsample=tlf.fFitsample;
491 if(fFixedParams) {
delete [] fFixedParams; fFixedParams = 0; }
492 if ( tlf.fFixedParams && fNfixed > 0 ) {
493 fFixedParams=
new Bool_t[fNfixed];
494 for(Int_t i=0; i< fNfixed; ++i)
495 fFixedParams[i]=tlf.fFixedParams[i];
507 void TLinearFitter::Add(TLinearFitter *tlf)
514 fDesign += tlf->fDesign;
516 fDesignTemp += tlf->fDesignTemp;
517 fDesignTemp2 += tlf->fDesignTemp2;
518 fDesignTemp3 += tlf->fDesignTemp3;
520 fAtbTemp += tlf->fAtbTemp;
521 fAtbTemp2 += tlf->fAtbTemp2;
522 fAtbTemp3 += tlf->fAtbTemp3;
525 Int_t size=fY.GetNoElements();
526 Int_t newsize = fNpoints+tlf->fNpoints;
528 fY.ResizeTo(newsize);
529 fE.ResizeTo(newsize);
530 fX.ResizeTo(newsize, fNdim);
532 for (Int_t i=fNpoints; i<newsize; i++){
533 fY(i)=tlf->fY(i-fNpoints);
534 fE(i)=tlf->fE(i-fNpoints);
535 for (Int_t j=0; j<fNdim; j++){
536 fX(i,j)=tlf->fX(i-fNpoints, j);
541 fY2Temp += tlf->fY2Temp;
542 fNpoints += tlf->fNpoints;
556 void TLinearFitter::AddPoint(Double_t *x, Double_t y, Double_t e)
561 size=fY.GetNoElements();
563 fY.ResizeTo(fNpoints+fNpoints/2);
564 fE.ResizeTo(fNpoints+fNpoints/2);
565 fX.ResizeTo(fNpoints+fNpoints/2, fNdim);
571 for (Int_t i=0; i<fNdim; i++)
578 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
579 Error(
"AddPoint",
"Point can't be added, because the formula hasn't been set");
582 if (!fRobust) AddToDesign(x, y, e);
594 void TLinearFitter::AssignData(Int_t npoints, Int_t xncols, Double_t *x, Double_t *y, Double_t *e)
596 if (npoints<fNpoints){
597 Error(
"AddData",
"Those points are already added");
601 if (fX.GetMatrixArray()==x && fY.GetMatrixArray()==y){
603 if (fE.GetMatrixArray()==e)
608 fX.Use(npoints, xncols, x);
613 fE.ResizeTo(npoints);
617 if (!fFunctions.IsEmpty() || fInputFunction || fSpecial>200) {
623 for (Int_t i=xfirst; i<npoints; i++)
624 AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
632 void TLinearFitter::AddToDesign(Double_t *x, Double_t y, Double_t e)
641 if ((fSpecial>100)&&(fSpecial<200)){
643 Int_t npar=fSpecial-100;
645 for (i=1; i<npar; i++)
646 fVal[i]=fVal[i-1]*x[0];
647 for (i=0; i<npar; i++)
649 }
else if (fSpecial>200){
651 Int_t npar=fSpecial-201;
653 for (i=0; i<npar; i++)
657 for (ii=0; ii<fNfunctions; ii++){
658 if (!fFunctions.IsEmpty()){
660 TObject * obj = fFunctions.UncheckedAt(ii);
661 if (obj->IsA() == TFormula::Class() ) {
662 TFormula *f1 = (TFormula*)(obj);
663 fVal[ii]=f1->EvalPar(x)/e;
665 else if (obj->IsA() == TF1::Class() ) {
666 TF1 *f1 = (TF1*)(obj);
667 fVal[ii]=f1->EvalPar(x)/e;
670 Error(
"AddToDesign",
"Basis Function %s is of an invalid type %s",obj->GetName(),obj->IsA()->GetName());
674 TFormula *f=(TFormula*)fInputFunction->GetLinearPart(ii);
676 Error(
"AddToDesign",
"Function %s has no linear parts - maybe missing a ++ in the formula expression",fInputFunction->GetName());
679 fVal[ii]=f->EvalPar(x)/e;
684 for (i=0; i<fNfunctions; i++){
686 fDesignTemp3(j, i)+=fVal[i]*fVal[j];
687 fDesignTemp3(i, i)+=fVal[i]*fVal[i];
688 fAtbTemp3(i)+=fVal[i]*y;
694 if (fNpoints % 100 == 0 && fNpoints>100){
695 fDesignTemp2+=fDesignTemp3;
697 fAtbTemp2+=fAtbTemp3;
699 if (fNpoints % 10000 == 0 && fNpoints>10000){
700 fDesignTemp+=fDesignTemp2;
706 if (fNpoints % 1000000 == 0 && fNpoints>1000000){
707 fDesign+=fDesignTemp;
718 void TLinearFitter::AddTempMatrices()
720 if (fDesignTemp3.GetNrows()>0){
721 fDesignTemp2+=fDesignTemp3;
722 fDesignTemp+=fDesignTemp2;
723 fDesign+=fDesignTemp;
727 fAtbTemp2+=fAtbTemp3;
742 void TLinearFitter::Clear(Option_t * )
750 fDesignTemp2.Clear();
751 fDesignTemp3.Clear();
766 if (fFormula)
delete [] fFormula;
769 if (fFixedParams)
delete [] fFixedParams;
782 void TLinearFitter::ClearPoints()
798 for (Int_t i=0; i<fNfunctions; i++)
808 void TLinearFitter::Chisquare()
812 Double_t temp, temp2;
816 for (i=0; i<fNfunctions; i++){
818 sumtotal2 += 2*fParams(i)*fParams(j)*fDesign(j, i);
820 sumtotal2 += fParams(i)*fParams(i)*fDesign(i, i);
821 sumtotal2 -= 2*fParams(i)*fAtb(i);
827 for (i=0; i<fNpoints; i++){
828 temp = fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
829 temp2 = (fY(i)-temp)*(fY(i)-temp);
830 temp2 /= fE(i)*fE(i);
836 for (Int_t point=0; point<fNpoints; point++){
838 if ((fSpecial>100)&&(fSpecial<200)){
839 Int_t npar = fSpecial-100;
841 for (i=1; i<npar; i++)
842 val[i] = val[i-1]*fX(point, 0);
843 for (i=0; i<npar; i++)
844 temp += fParams(i)*val[i];
848 Int_t npar = fSpecial-201;
850 for (i=0; i<npar; i++)
851 temp += fParams(i+1)*fX(point, i);
853 for (j=0; j<fNfunctions; j++) {
854 TFormula *f1 = (TFormula*)(fFunctions.UncheckedAt(j));
855 val[j] = f1->EvalPar(TMatrixDRow(fX, point).GetPtr());
856 temp += fParams(j)*val[j];
860 temp2 = (fY(point)-temp)*(fY(point)-temp);
861 temp2 /= fE(point)*fE(point);
866 fChisquare = sumtotal2;
873 void TLinearFitter::ComputeTValues()
875 for (Int_t i=0; i<fNfunctions; i++){
876 fTValues(i) = fParams(i)/(TMath::Sqrt(fParCovar(i, i)));
877 fParSign(i) = 2*(1-TMath::StudentI(TMath::Abs(fTValues(i)),fNpoints-fNfunctions+fNfixed));
885 Int_t TLinearFitter::Eval()
888 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
889 Error(
"TLinearFitter::Eval",
"The formula hasn't been set");
893 fParams.ResizeTo(fNfunctions);
894 fTValues.ResizeTo(fNfunctions);
895 fParSign.ResizeTo(fNfunctions);
896 fParCovar.ResizeTo(fNfunctions,fNfunctions);
901 Bool_t update = UpdateMatrix();
910 fInputFunction->SetParameters(fParams.GetMatrixArray());
911 for (Int_t i=0; i<fNfunctions; i++)
912 ((TF1*)fInputFunction)->SetParError(i, 0);
913 ((TF1*)fInputFunction)->SetChisquare(0);
914 ((TF1*)fInputFunction)->SetNDF(0);
915 ((TF1*)fInputFunction)->SetNumberFitPoints(0);
926 for (ii=0; ii<fNfunctions; ii++)
927 fDesignTemp(ii, fNfixed) = fAtb(ii);
928 for (i=0; i<fNfunctions; i++){
929 if (fFixedParams[i]){
930 for (ii=0; ii<i; ii++)
931 fDesignTemp(ii, j) = fDesign(ii, i);
932 for (ii=i; ii<fNfunctions; ii++)
933 fDesignTemp(ii, j) = fDesign(i, ii);
935 for (ii=0; ii<fNfunctions; ii++){
936 fAtb(ii)-=fParams(i)*(fDesignTemp(ii, j-1));
940 for (i=0; i<fNfunctions; i++){
941 if (fFixedParams[i]){
942 for (ii=0; ii<fNfunctions; ii++){
947 fAtb(i) = fParams(i);
952 TDecompChol chol(fDesign);
954 TVectorD coef(fNfunctions);
955 coef=chol.Solve(fAtb, ok);
957 Error(
"Eval",
"Matrix inversion failed");
963 fInputFunction->SetParameters(fParams.GetMatrixArray());
964 if (fInputFunction->InheritsFrom(TF1::Class())){
965 ((TF1*)fInputFunction)->SetChisquare(0);
966 ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
967 ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
973 fParCovar=chol.Invert();
976 fInputFunction->SetParameters(fParams.GetMatrixArray());
977 if (fInputFunction->InheritsFrom(TF1::Class())){
978 for (i=0; i<fNfunctions; i++){
979 e = TMath::Sqrt(fParCovar(i, i));
980 ((TF1*)fInputFunction)->SetParError(i, e);
983 ((TF1*)fInputFunction)->SetChisquare(GetChisquare());
984 ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
985 ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
992 for (i=0; i<fNfunctions; i++){
993 if (fFixedParams[i]){
994 for (ii=0; ii<i; ii++){
995 fDesign(ii, i) = fDesignTemp(ii, j);
996 fAtb(ii) = fDesignTemp(ii, fNfixed);
998 for (ii=i; ii<fNfunctions; ii++){
999 fDesign(i, ii) = fDesignTemp(ii, j);
1000 fAtb(ii) = fDesignTemp(ii, fNfixed);
1012 void TLinearFitter::FixParameter(Int_t ipar)
1014 if (fParams.NonZeros()<1){
1015 Error(
"FixParameter",
"no value available to fix the parameter");
1018 if (ipar>fNfunctions || ipar<0){
1019 Error(
"FixParameter",
"illegal parameter value");
1022 if (fNfixed==fNfunctions) {
1023 Error(
"FixParameter",
"no free parameters left");
1027 fFixedParams =
new Bool_t[fNfunctions];
1028 fFixedParams[ipar] = 1;
1035 void TLinearFitter::FixParameter(Int_t ipar, Double_t parvalue)
1037 if (ipar>fNfunctions || ipar<0){
1038 Error(
"FixParameter",
"illegal parameter value");
1041 if (fNfixed==fNfunctions) {
1042 Error(
"FixParameter",
"no free parameters left");
1046 fFixedParams =
new Bool_t[fNfunctions];
1047 fFixedParams[ipar] = 1;
1048 if (fParams.GetNoElements()<fNfunctions)
1049 fParams.ResizeTo(fNfunctions);
1050 fParams(ipar) = parvalue;
1057 void TLinearFitter::ReleaseParameter(Int_t ipar)
1059 if (ipar>fNfunctions || ipar<0){
1060 Error(
"ReleaseParameter",
"illegal parameter value");
1063 if (!fFixedParams[ipar]){
1064 Warning(
"ReleaseParameter",
"This parameter is not fixed\n");
1067 fFixedParams[ipar] = 0;
1075 void TLinearFitter::GetAtbVector(TVectorD &v)
1077 if (v.GetNoElements()!=fAtb.GetNoElements())
1078 v.ResizeTo(fAtb.GetNoElements());
1085 Double_t TLinearFitter::GetChisquare()
1087 if (fChisquare > 1e-16)
1108 void TLinearFitter::GetConfidenceIntervals(Int_t n, Int_t ndim,
const Double_t *x, Double_t *ci, Double_t cl)
1110 if (fInputFunction){
1111 Double_t *grad =
new Double_t[fNfunctions];
1112 Double_t *sum_vector =
new Double_t[fNfunctions];
1114 Int_t df = fNpoints-fNfunctions+fNfixed;
1115 Double_t t = TMath::StudentQuantile(0.5 + cl/2, df);
1116 Double_t chidf = TMath::Sqrt(fChisquare/df);
1118 for (Int_t ipoint=0; ipoint<n; ipoint++){
1120 ((TF1*)(fInputFunction))->GradientPar(x+ndim*ipoint, grad);
1122 for (Int_t irow=0; irow<fNfunctions; irow++){
1124 for (Int_t icol=0; icol<fNfunctions; icol++){
1125 sum_vector[irow]+=fParCovar(irow,icol)*grad[icol];
1128 for (Int_t i=0; i<fNfunctions; i++)
1129 c+=grad[i]*sum_vector[i];
1131 ci[ipoint]=c*t*chidf;
1135 delete [] sum_vector;
1159 void TLinearFitter::GetConfidenceIntervals(TObject *obj, Double_t cl)
1161 if (!fInputFunction) {
1162 Error(
"GetConfidenceIntervals",
"The case of fitting not with a TFormula is not yet implemented");
1168 if (obj->InheritsFrom(TGraph::Class())) {
1169 TGraph *gr = (TGraph*)obj;
1171 Error(
"GetConfidenceIntervals",
"A TGraphErrors should be passed instead of a graph");
1174 if (fObjectFit->InheritsFrom(TGraph2D::Class())){
1175 Error(
"GetConfidenceIntervals",
"A TGraph2DErrors should be passed instead of a graph");
1178 if (fObjectFit->InheritsFrom(TH1::Class())){
1179 if (((TH1*)(fObjectFit))->GetDimension()>1){
1180 Error(
"GetConfidenceIntervals",
"A TGraph2DErrors or a TH23 should be passed instead of a graph");
1185 GetConfidenceIntervals(gr->GetN(),1,gr->GetX(), gr->GetEY(), cl);
1186 for (Int_t i=0; i<gr->GetN(); i++)
1187 gr->SetPoint(i, gr->GetX()[i], fInputFunction->Eval(gr->GetX()[i]));
1191 else if (obj->InheritsFrom(TGraph2D::Class())) {
1192 TGraph2D *gr2 = (TGraph2D*)obj;
1194 Error(
"GetConfidenceIntervals",
"A TGraph2DErrors should be passed instead of a TGraph2D");
1197 if (fObjectFit->InheritsFrom(TGraph::Class())){
1198 Error(
"GetConfidenceIntervals",
"A TGraphErrors should be passed instead of a TGraph2D");
1201 if (fObjectFit->InheritsFrom(TH1::Class())){
1202 if (((TH1*)(fObjectFit))->GetDimension()==1){
1203 Error(
"GetConfidenceIntervals",
"A TGraphErrors or a TH1 should be passed instead of a graph");
1208 Int_t np = gr2->GetN();
1209 Double_t *grad =
new Double_t[fNfunctions];
1210 Double_t *sum_vector =
new Double_t[fNfunctions];
1211 Double_t *x = gr2->GetX();
1212 Double_t *y = gr2->GetY();
1213 Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
1214 Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
1216 for (Int_t ipoint=0; ipoint<np; ipoint++){
1220 ((TF1*)(fInputFunction))->GradientPar(xy, grad);
1221 for (Int_t irow=0; irow<fNfunctions; irow++){
1223 for (Int_t icol=0; icol<fNfunctions; icol++)
1224 sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
1226 for (Int_t i=0; i<fNfunctions; i++)
1227 c+=grad[i]*sum_vector[i];
1229 gr2->SetPoint(ipoint, xy[0], xy[1], fInputFunction->EvalPar(xy));
1230 gr2->GetEZ()[ipoint]=c*t*chidf;
1233 delete [] sum_vector;
1237 else if (obj->InheritsFrom(TH1::Class())) {
1238 if (fObjectFit->InheritsFrom(TGraph::Class())){
1239 if (((TH1*)obj)->GetDimension()>1){
1240 Error(
"GetConfidenceIntervals",
"Fitted graph and passed histogram have different number of dimensions");
1244 if (fObjectFit->InheritsFrom(TGraph2D::Class())){
1245 if (((TH1*)obj)->GetDimension()!=2){
1246 Error(
"GetConfidenceIntervals",
"Fitted graph and passed histogram have different number of dimensions");
1250 if (fObjectFit->InheritsFrom(TH1::Class())){
1251 if (((TH1*)(fObjectFit))->GetDimension()!=((TH1*)(obj))->GetDimension()){
1252 Error(
"GetConfidenceIntervals",
"Fitted and passed histograms have different number of dimensions");
1258 TH1 *hfit = (TH1*)obj;
1259 Double_t *grad =
new Double_t[fNfunctions];
1260 Double_t *sum_vector =
new Double_t[fNfunctions];
1262 Int_t hxfirst = hfit->GetXaxis()->GetFirst();
1263 Int_t hxlast = hfit->GetXaxis()->GetLast();
1264 Int_t hyfirst = hfit->GetYaxis()->GetFirst();
1265 Int_t hylast = hfit->GetYaxis()->GetLast();
1266 Int_t hzfirst = hfit->GetZaxis()->GetFirst();
1267 Int_t hzlast = hfit->GetZaxis()->GetLast();
1269 TAxis *xaxis = hfit->GetXaxis();
1270 TAxis *yaxis = hfit->GetYaxis();
1271 TAxis *zaxis = hfit->GetZaxis();
1272 Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
1273 Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
1275 for (Int_t binz=hzfirst; binz<=hzlast; binz++){
1276 x[2]=zaxis->GetBinCenter(binz);
1277 for (Int_t biny=hyfirst; biny<=hylast; biny++) {
1278 x[1]=yaxis->GetBinCenter(biny);
1279 for (Int_t binx=hxfirst; binx<=hxlast; binx++) {
1280 x[0]=xaxis->GetBinCenter(binx);
1281 ((TF1*)(fInputFunction))->GradientPar(x, grad);
1283 for (Int_t irow=0; irow<fNfunctions; irow++){
1285 for (Int_t icol=0; icol<fNfunctions; icol++)
1286 sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
1288 for (Int_t i=0; i<fNfunctions; i++)
1289 c+=grad[i]*sum_vector[i];
1291 hfit->SetBinContent(binx, biny, binz, fInputFunction->EvalPar(x));
1292 hfit->SetBinError(binx, biny, binz, c*t*chidf);
1297 delete [] sum_vector;
1300 Error(
"GetConfidenceIntervals",
"This object type is not supported");
1308 Double_t* TLinearFitter::GetCovarianceMatrix()
const
1310 Double_t *p =
const_cast<Double_t*
>(fParCovar.GetMatrixArray());
1317 void TLinearFitter::GetCovarianceMatrix(TMatrixD &matr)
1319 if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
1320 matr.ResizeTo(fNfunctions, fNfunctions);
1328 void TLinearFitter::GetDesignMatrix(TMatrixD &matr)
1330 if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
1331 matr.ResizeTo(fNfunctions, fNfunctions);
1339 void TLinearFitter::GetErrors(TVectorD &vpar)
1341 if (vpar.GetNoElements()!=fNfunctions) {
1342 vpar.ResizeTo(fNfunctions);
1344 for (Int_t i=0; i<fNfunctions; i++)
1345 vpar(i) = TMath::Sqrt(fParCovar(i, i));
1352 void TLinearFitter::GetParameters(TVectorD &vpar)
1354 if (vpar.GetNoElements()!=fNfunctions) {
1355 vpar.ResizeTo(fNfunctions);
1364 Int_t TLinearFitter::GetParameter(Int_t ipar,
char* name,Double_t& value,Double_t& ,Double_t& , Double_t& )
const
1366 if (ipar<0 || ipar>fNfunctions) {
1367 Error(
"GetParError",
"illegal value of parameter");
1370 value = fParams(ipar);
1372 strcpy(name, fInputFunction->GetParName(ipar));
1382 Double_t TLinearFitter::GetParError(Int_t ipar)
const
1384 if (ipar<0 || ipar>fNfunctions) {
1385 Error(
"GetParError",
"illegal value of parameter");
1389 return TMath::Sqrt(fParCovar(ipar, ipar));
1396 const char *TLinearFitter::GetParName(Int_t ipar)
const
1398 if (ipar<0 || ipar>fNfunctions) {
1399 Error(
"GetParError",
"illegal value of parameter");
1403 return fInputFunction->GetParName(ipar);
1410 Double_t TLinearFitter::GetParTValue(Int_t ipar)
1412 if (ipar<0 || ipar>fNfunctions) {
1413 Error(
"GetParTValue",
"illegal value of parameter");
1416 if (!fTValues.NonZeros())
1418 return fTValues(ipar);
1424 Double_t TLinearFitter::GetParSignificance(Int_t ipar)
1426 if (ipar<0 || ipar>fNfunctions) {
1427 Error(
"GetParSignificance",
"illegal value of parameter");
1430 if (!fParSign.NonZeros())
1432 return fParSign(ipar);
1438 void TLinearFitter::GetFitSample(TBits &bits)
1441 Error(
"GetFitSample",
"there is no fit sample in ordinary least-squares fit");
1444 for (Int_t i=0; i<fNpoints; i++)
1445 bits.SetBitNumber(i, fFitsample.TestBitNumber(i));
1452 Int_t TLinearFitter::Merge(TCollection *list)
1454 if (!list)
return -1;
1456 TLinearFitter *lfit = 0;
1457 while ((lfit = (TLinearFitter*)next())) {
1458 if (!lfit->InheritsFrom(TLinearFitter::Class())) {
1459 Error(
"Add",
"Attempt to add object of class: %s to a %s",lfit->ClassName(),this->ClassName());
1471 void TLinearFitter::SetBasisFunctions(TObjArray * functions)
1473 fFunctions = *(functions);
1474 fFunctions.SetOwner(kTRUE);
1475 int size = fFunctions.GetEntries();
1479 fDesign.ResizeTo(size, size);
1480 fAtb.ResizeTo(size);
1481 fDesignTemp.ResizeTo(size, size);
1482 fDesignTemp2.ResizeTo(size, size);
1483 fDesignTemp3.ResizeTo(size, size);
1484 fAtbTemp.ResizeTo(size);
1485 fAtbTemp2.ResizeTo(size);
1486 fAtbTemp3.ResizeTo(size);
1488 delete [] fFixedParams;
1489 fFixedParams=
new Bool_t[size];
1493 fDesignTemp2.Zero();
1494 fDesignTemp3.Zero();
1500 for (
int i=0; i<size; i++)
1511 void TLinearFitter::SetDim(Int_t ndim)
1514 fY.ResizeTo(ndim+1);
1515 fX.ResizeTo(ndim+1, ndim);
1516 fE.ResizeTo(ndim+1);
1532 void TLinearFitter::SetFormula(
const char *formula)
1534 Int_t size = 0, special = 0;
1539 fFormulaSize = strlen(formula);
1540 fFormula =
new char[fFormulaSize+1];
1541 strlcpy(fFormula, formula,fFormulaSize+1);
1545 fstring = (
char *)strstr(fFormula,
"hyp");
1549 sscanf(fstring,
"%d", &size);
1557 TString sstring(fFormula);
1558 sstring = sstring.ReplaceAll(
"++", 2,
"|", 1);
1559 TString replaceformula;
1563 TObjArray *oa = sstring.Tokenize(
"|");
1566 if (!fFunctions.IsEmpty())
1570 fFunctions.SetOwner(kFALSE);
1572 fNfunctions = oa->GetEntriesFast();
1573 fFunctions.Expand(fNfunctions);
1577 char replacement[14];
1578 for (i=0; i<fNdim; i++){
1579 snprintf(pattern,
sizeof(pattern),
"x%d", i);
1580 snprintf(replacement,
sizeof(replacement),
"x[%d]", i);
1581 sstring = sstring.ReplaceAll(pattern, Int_t(i/10)+2, replacement, Int_t(i/10)+4);
1585 oa = sstring.Tokenize(
"|");
1586 for (i=0; i<fNfunctions; i++) {
1587 replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
1589 TFormula * f =
nullptr;
1590 auto elem = fgFormulaMap.find(replaceformula );
1591 if (elem != fgFormulaMap.end() )
1595 f =
new TFormula(
"f", replaceformula.Data());
1597 R__LOCKGUARD(gROOTMutex);
1598 fgFormulaMap[replaceformula]=f;
1602 Error(
"TLinearFitter",
"f_linear not allocated");
1605 special=f->GetNumber();
1609 if ((fNfunctions==1)&&(special>299)&&(special<310)){
1620 fDesign.ResizeTo(size, size);
1621 fAtb.ResizeTo(size);
1622 fDesignTemp.ResizeTo(size, size);
1623 fDesignTemp2.ResizeTo(size, size);
1624 fDesignTemp3.ResizeTo(size, size);
1625 fAtbTemp.ResizeTo(size);
1626 fAtbTemp2.ResizeTo(size);
1627 fAtbTemp3.ResizeTo(size);
1629 delete [] fFixedParams;
1630 fFixedParams=
new Bool_t[size];
1634 fDesignTemp2.Zero();
1635 fDesignTemp3.Zero();
1641 for (i=0; i<size; i++)
1651 void TLinearFitter::SetFormula(TFormula *
function)
1653 Int_t special, size;
1654 fInputFunction=
function;
1655 fNfunctions=fInputFunction->GetNpar();
1657 special=fInputFunction->GetNumber();
1658 if (!fFunctions.IsEmpty())
1659 fFunctions.Delete();
1661 if ((special>299)&&(special<310)){
1670 fDesign.ResizeTo(size, size);
1671 fAtb.ResizeTo(size);
1672 fDesignTemp.ResizeTo(size, size);
1673 fAtbTemp.ResizeTo(size);
1675 fDesignTemp2.ResizeTo(size, size);
1676 fDesignTemp3.ResizeTo(size, size);
1678 fAtbTemp2.ResizeTo(size);
1679 fAtbTemp3.ResizeTo(size);
1682 delete [] fFixedParams;
1683 fFixedParams=
new Bool_t[size];
1689 fDesignTemp2.Zero();
1690 fDesignTemp3.Zero();
1696 for (Int_t i=0; i<size; i++)
1700 if (function->InheritsFrom(TF1::Class())){
1702 for (Int_t i=0;i<fNfunctions;i++) {
1703 ((TF1*)
function)->GetParLimits(i,al,bl);
1704 if (al*bl !=0 && al >= bl) {
1705 FixParameter(i, function->GetParameter(i));
1718 Bool_t TLinearFitter::UpdateMatrix()
1721 for (Int_t i=0; i<fNpoints; i++) {
1722 AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
1733 Int_t TLinearFitter::ExecuteCommand(
const char *command, Double_t *args, Int_t )
1735 if (!strcmp(command,
"FitGraph")){
1736 if (args)
return GraphLinearFitter(args[0]);
1737 else return GraphLinearFitter(0);
1739 if (!strcmp(command,
"FitGraph2D")){
1740 if (args)
return Graph2DLinearFitter(args[0]);
1741 else return Graph2DLinearFitter(0);
1743 if (!strcmp(command,
"FitMultiGraph")){
1744 if (args)
return MultiGraphLinearFitter(args[0]);
1745 else return MultiGraphLinearFitter(0);
1747 if (!strcmp(command,
"FitHist"))
return HistLinearFitter();
1757 void TLinearFitter::PrintResults(Int_t level, Double_t )
const
1761 printf(
"Fitting results:\nParameters:\nNO.\t\tVALUE\t\tERROR\n");
1762 for (Int_t i=0; i<fNfunctions; i++){
1763 printf(
"%d\t%e\t%e\n", i, fParams(i), TMath::Sqrt(fParCovar(i, i)));
1766 printf(
"Fitting results:\nParameters:\nNO.\t\tVALUE\n");
1767 for (Int_t i=0; i<fNfunctions; i++){
1768 printf(
"%d\t%e\n", i, fParams(i));
1777 Int_t TLinearFitter::GraphLinearFitter(Double_t h)
1780 TGraph *grr=(TGraph*)GetObjectFit();
1781 TF1 *f1=(TF1*)GetUserFunc();
1782 Foption_t fitOption=GetFitOption();
1785 Double_t *x=grr->GetX();
1786 Double_t *y=grr->GetY();
1789 Int_t fitResult = 0;
1792 SetFormula(f1->GetFormula());
1794 if (fitOption.Robust){
1799 Int_t n=grr->GetN();
1800 for (Int_t i=0; i<n; i++){
1801 if (!f1->IsInside(&x[i]))
continue;
1802 e=grr->GetErrorY(i);
1803 if (e<0 || fitOption.W1)
1805 AddPoint(&x[i], y[i], e);
1808 if (fitOption.Robust){
1809 return EvalRobust(h);
1816 if (!fitOption.Nochisq){
1817 Double_t temp, temp2, sumtotal=0;
1818 for (Int_t i=0; i<n; i++){
1819 if (!f1->IsInside(&x[i]))
continue;
1820 temp=f1->Eval(x[i]);
1821 temp2=(y[i]-temp)*(y[i]-temp);
1822 e=grr->GetErrorY(i);
1823 if (e<0 || fitOption.W1)
1829 fChisquare=sumtotal;
1830 f1->SetChisquare(fChisquare);
1839 Int_t TLinearFitter::Graph2DLinearFitter(Double_t h)
1843 TGraph2D *gr=(TGraph2D*)GetObjectFit();
1844 TF2 *f2=(TF2*)GetUserFunc();
1846 Foption_t fitOption=GetFitOption();
1847 Int_t n = gr->GetN();
1848 Double_t *gx = gr->GetX();
1849 Double_t *gy = gr->GetY();
1850 Double_t *gz = gr->GetZ();
1855 SetFormula(f2->GetFormula());
1857 if (fitOption.Robust){
1862 for (Int_t bin=0;bin<n;bin++) {
1865 if (!f2->IsInside(x)) {
1869 e=gr->GetErrorZ(bin);
1870 if (e<0 || fitOption.W1)
1875 if (fitOption.Robust){
1876 return EvalRobust(h);
1882 if (!fitOption.Nochisq){
1884 Double_t temp, temp2, sumtotal=0;
1885 for (Int_t bin=0; bin<n; bin++){
1888 if (!f2->IsInside(x)) {
1893 temp=f2->Eval(x[0], x[1]);
1894 temp2=(z-temp)*(z-temp);
1895 e=gr->GetErrorZ(bin);
1896 if (e<0 || fitOption.W1)
1902 fChisquare=sumtotal;
1903 f2->SetChisquare(fChisquare);
1912 Int_t TLinearFitter::MultiGraphLinearFitter(Double_t h)
1917 TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
1918 TMultiGraph *mg = (TMultiGraph*)grFitter->GetObjectFit();
1919 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
1920 Foption_t fitOption = grFitter->GetFitOption();
1924 if (fitOption.Robust){
1928 SetFormula(f1->GetFormula());
1931 TIter next(mg->GetListOfGraphs());
1932 while ((gr = (TGraph*) next())) {
1936 for (i=0; i<n; i++){
1937 if (!f1->IsInside(&gx[i]))
continue;
1939 if (e<0 || fitOption.W1)
1941 AddPoint(&gx[i], gy[i], e);
1945 if (fitOption.Robust){
1946 return EvalRobust(h);
1953 if (!fitOption.Nochisq){
1954 Double_t temp, temp2, sumtotal=0;
1956 while((gr = (TGraph*)next())) {
1960 for (i=0; i<n; i++){
1961 if (!f1->IsInside(&gx[i]))
continue;
1962 temp=f1->Eval(gx[i]);
1963 temp2=(gy[i]-temp)*(gy[i]-temp);
1965 if (e<0 || fitOption.W1)
1973 fChisquare=sumtotal;
1974 f1->SetChisquare(fChisquare);
1983 Int_t TLinearFitter::HistLinearFitter()
1989 Int_t bin,binx,biny,binz;
1992 TH1 *hfit = (TH1*)GetObjectFit();
1993 TF1 *f1 = (TF1*)GetUserFunc();
1995 Foption_t fitOption = GetFitOption();
1997 SetDim(f1->GetNdim());
1998 SetFormula(f1->GetFormula());
2000 Int_t hxfirst = GetXfirst();
2001 Int_t hxlast = GetXlast();
2002 Int_t hyfirst = GetYfirst();
2003 Int_t hylast = GetYlast();
2004 Int_t hzfirst = GetZfirst();
2005 Int_t hzlast = GetZlast();
2006 TAxis *xaxis = hfit->GetXaxis();
2007 TAxis *yaxis = hfit->GetYaxis();
2008 TAxis *zaxis = hfit->GetZaxis();
2010 for (binz=hzfirst;binz<=hzlast;binz++) {
2011 x[2] = zaxis->GetBinCenter(binz);
2012 for (biny=hyfirst;biny<=hylast;biny++) {
2013 x[1] = yaxis->GetBinCenter(biny);
2014 for (binx=hxfirst;binx<=hxlast;binx++) {
2015 x[0] = xaxis->GetBinCenter(binx);
2016 if (!f1->IsInside(x))
continue;
2017 bin = hfit->GetBin(binx,biny,binz);
2018 cu = hfit->GetBinContent(bin);
2019 if (f1->GetNdim() < hfit->GetDimension()) {
2020 if (hfit->GetDimension() > 2) cu = x[2];
2024 if (fitOption.W1==1 && cu == 0)
continue;
2027 eu = hfit->GetBinError(bin);
2028 if (eu <= 0)
continue;
2030 AddPoint(x, cu, eu);
2038 if (!fitOption.Nochisq){
2039 Double_t temp, temp2, sumtotal=0;
2040 for (binz=hzfirst;binz<=hzlast;binz++) {
2041 x[2] = zaxis->GetBinCenter(binz);
2042 for (biny=hyfirst;biny<=hylast;biny++) {
2043 x[1] = yaxis->GetBinCenter(biny);
2044 for (binx=hxfirst;binx<=hxlast;binx++) {
2045 x[0] = xaxis->GetBinCenter(binx);
2046 if (!f1->IsInside(x))
continue;
2047 bin = hfit->GetBin(binx,biny,binz);
2048 cu = hfit->GetBinContent(bin);
2051 if (fitOption.W1==1 && cu == 0)
continue;
2054 eu = hfit->GetBinError(bin);
2055 if (eu <= 0)
continue;
2057 temp=f1->EvalPar(x);
2058 temp2=(cu-temp)*(cu-temp);
2065 fChisquare=sumtotal;
2066 f1->SetChisquare(fChisquare);
2074 void TLinearFitter::Streamer(TBuffer &R__b)
2076 if (R__b.IsReading()) {
2077 Int_t old_matr_size = fNfunctions;
2078 R__b.ReadClassBuffer(TLinearFitter::Class(),
this);
2079 if (old_matr_size < fNfunctions) {
2080 fDesignTemp.ResizeTo(fNfunctions, fNfunctions);
2081 fAtbTemp.ResizeTo(fNfunctions);
2083 fDesignTemp2.ResizeTo(fNfunctions, fNfunctions);
2084 fDesignTemp3.ResizeTo(fNfunctions, fNfunctions);
2086 fAtbTemp2.ResizeTo(fNfunctions);
2087 fAtbTemp3.ResizeTo(fNfunctions);
2090 if (fAtb.NonZeros()==0) AddTempMatrices();
2091 R__b.WriteClassBuffer(TLinearFitter::Class(),
this);
2104 Int_t TLinearFitter::EvalRobust(Double_t h)
2107 Double_t kEps = 1e-13;
2109 Int_t i, j, maxind=0, k, k1 = 500;
2113 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
2114 Error(
"TLinearFitter::EvalRobust",
"The formula hasn't been set");
2119 Double_t *bestchi2 =
new Double_t[nbest];
2120 for (i=0; i<nbest; i++)
2123 Int_t hdef=Int_t((fNpoints+fNfunctions+1)/2);
2125 if (h>0.000001 && h<1 && fNpoints*h > hdef)
2126 fH = Int_t(fNpoints*h);
2129 if (h>0) Warning(
"Fitting:",
"illegal value of H, default is taken, h = %3.2f",
double(hdef)/fNpoints);
2133 fDesign.ResizeTo(fNfunctions, fNfunctions);
2134 fAtb.ResizeTo(fNfunctions);
2135 fParams.ResizeTo(fNfunctions);
2137 Int_t *index =
new Int_t[fNpoints];
2138 Double_t *residuals =
new Double_t[fNpoints];
2140 if (fNpoints < 2*nmini) {
2144 TMatrixD cstock(fNfunctions, nbest);
2145 for (k = 0; k < k1; k++) {
2146 CreateSubset(fNpoints, fH, index);
2147 chi2 = CStep(1, fH, residuals,index, index, -1, -1);
2148 chi2 = CStep(2, fH, residuals,index, index, -1, -1);
2149 maxind = TMath::LocMax(nbest, bestchi2);
2150 if (chi2 < bestchi2[maxind]) {
2151 bestchi2[maxind] = chi2;
2152 for (i=0; i<fNfunctions; i++)
2153 cstock(i, maxind) = fParams(i);
2158 Int_t *bestindex =
new Int_t[fH];
2159 Double_t currentbest;
2160 for (i=0; i<nbest; i++) {
2161 for (j=0; j<fNfunctions; j++)
2162 fParams(j) = cstock(j, i);
2164 while (chi2 > kEps) {
2165 chi2 = CStep(2, fH, residuals,index, index, -1, -1);
2166 if (TMath::Abs(chi2 - bestchi2[i]) < kEps)
2171 currentbest = TMath::MinElement(nbest, bestchi2);
2172 if (chi2 <= currentbest + kEps) {
2173 for (j=0; j<fH; j++){
2174 bestindex[j]=index[j];
2178 for (j=0; j<fNfunctions; j++)
2179 cstock(j, i) = fParams(j);
2182 for (j=0; j<fNfunctions; j++)
2183 fParams(j) = cstock(j, maxind);
2184 fFitsample.SetBitNumber(fNpoints, kFALSE);
2185 for (j=0; j<fH; j++){
2187 fFitsample.SetBitNumber(bestindex[j]);
2189 if (fInputFunction && fInputFunction->InheritsFrom(TF1::Class())) {
2190 ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
2191 ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
2192 ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
2195 delete [] bestindex;
2196 delete [] residuals;
2205 Int_t nsub = Partition(nmini, indsubdat);
2208 Int_t sum = TMath::Min(nmini*5, fNpoints);
2210 Int_t *subdat =
new Int_t[sum];
2211 RDraw(subdat, indsubdat);
2213 TMatrixD cstockbig(fNfunctions, nbest*5);
2214 Int_t *beststock =
new Int_t[nbest];
2216 Int_t i_end = indsubdat[0];
2217 Int_t k2 = Int_t(k1/nsub);
2218 for (Int_t kgroup = 0; kgroup < nsub; kgroup++) {
2220 hsub = Int_t(fH * indsubdat[kgroup]/fNpoints);
2221 for (i=0; i<nbest; i++)
2223 for (k=0; k<k2; k++) {
2224 CreateSubset(indsubdat[kgroup], hsub, index);
2225 chi2 = CStep(1, hsub, residuals, index, subdat, i_start, i_end);
2226 chi2 = CStep(2, hsub, residuals, index, subdat, i_start, i_end);
2227 maxind = TMath::LocMax(nbest, bestchi2);
2228 if (chi2 < bestchi2[maxind]){
2229 for (i=0; i<fNfunctions; i++)
2230 cstockbig(i, nbest*kgroup + maxind) = fParams(i);
2231 bestchi2[maxind] = chi2;
2234 if (kgroup != nsub - 1){
2235 i_start += indsubdat[kgroup];
2236 i_end += indsubdat[kgroup+1];
2240 for (i=0; i<nbest; i++)
2243 Int_t hsub2 = Int_t(fH*sum/fNpoints);
2244 for (k=0; k<nbest*5; k++) {
2245 for (i=0; i<fNfunctions; i++)
2246 fParams(i)=cstockbig(i, k);
2247 chi2 = CStep(1, hsub2, residuals, index, subdat, 0, sum);
2248 chi2 = CStep(2, hsub2, residuals, index, subdat, 0, sum);
2249 maxind = TMath::LocMax(nbest, bestchi2);
2250 if (chi2 < bestchi2[maxind]){
2251 beststock[maxind] = k;
2252 bestchi2[maxind] = chi2;
2257 for (k=0; k<nbest; k++) {
2258 for (i=0; i<fNfunctions; i++)
2259 fParams(i) = cstockbig(i, beststock[k]);
2260 chi2 = CStep(1, fH, residuals, index, index, -1, -1);
2261 chi2 = CStep(2, fH, residuals, index, index, -1, -1);
2265 maxind = TMath::LocMin(nbest, bestchi2);
2266 for (i=0; i<fNfunctions; i++)
2267 fParams(i)=cstockbig(i, beststock[maxind]);
2270 while (chi2 > kEps) {
2271 chi2 = CStep(2, fH, residuals, index, index, -1, -1);
2272 if (TMath::Abs(chi2 - bestchi2[maxind]) < kEps)
2275 bestchi2[maxind] = chi2;
2278 fFitsample.SetBitNumber(fNpoints, kFALSE);
2279 for (j=0; j<fH; j++)
2280 fFitsample.SetBitNumber(index[j]);
2281 if (fInputFunction){
2282 ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
2283 ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
2284 ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
2288 delete [] beststock;
2290 delete [] residuals;
2300 void TLinearFitter::CreateSubset(Int_t ntotal, Int_t h, Int_t *index)
2303 Bool_t repeat=kFALSE;
2306 for(i=0; i<ntotal; i++)
2307 index[i] = ntotal+1;
2311 for (i=0; i<fNfunctions; i++) {
2312 num=Int_t(r.Uniform(0, 1)*(ntotal-1));
2314 for(j=0; j<=i-1; j++) {
2331 for (i=0; i<fNfunctions; i++){
2332 AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
2339 while (!ok && (nindex < h)) {
2342 num=Int_t(r.Uniform(0,1)*(ntotal-1));
2344 for(i=0; i<nindex; i++) {
2350 }
while(repeat==kTRUE);
2352 index[nindex] = num;
2355 AddToDesign(TMatrixDRow(fX, index[nindex-1]).GetPtr(), fY(index[nindex-1]), fE(index[nindex-1]));
2363 Double_t TLinearFitter::CStep(Int_t step, Int_t h, Double_t *residuals, Int_t *index, Int_t *subdat, Int_t start, Int_t end)
2365 R__ASSERT( !fFunctions.IsEmpty() || fInputFunction || fSpecial>200);
2367 Int_t i, j, itemp, n;
2373 for (i=0; i<n; i++) {
2375 itemp = subdat[start+i];
2376 if (fInputFunction){
2377 fInputFunction->SetParameters(fParams.GetMatrixArray());
2378 func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2381 if ((fSpecial>100)&&(fSpecial<200)){
2382 npar = fSpecial-100;
2384 for (j=1; j<npar; j++)
2385 val[j] = val[j-1]*fX(itemp, 0);
2386 for (j=0; j<npar; j++)
2387 func += fParams(j)*val[j];
2388 }
else if (fSpecial>200) {
2390 npar = fSpecial-201;
2392 for (j=0; j<npar; j++)
2393 func += fParams(j+1)*fX(itemp, j);
2396 for (j=0; j<fNfunctions; j++) {
2397 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2398 val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2399 func += fParams(j)*val[j];
2403 residuals[i] = (fY(itemp) - func)*(fY(itemp) - func)/(fE(i)*fE(i));
2407 for (i=0; i<fNpoints; i++) {
2409 if (fInputFunction){
2410 fInputFunction->SetParameters(fParams.GetMatrixArray());
2411 func=fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
2414 if ((fSpecial>100)&&(fSpecial<200)){
2415 npar = fSpecial-100;
2417 for (j=1; j<npar; j++)
2418 val[j] = val[j-1]*fX(i, 0);
2419 for (j=0; j<npar; j++)
2420 func += fParams(j)*val[j];
2421 }
else if (fSpecial>200) {
2423 npar = fSpecial-201;
2425 for (j=0; j<npar; j++)
2426 func += fParams(j+1)*fX(i, j);
2428 for (j=0; j<fNfunctions; j++) {
2429 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2430 val[j] = f1->EvalPar(TMatrixDRow(fX, i).GetPtr());
2431 func += fParams(j)*val[j];
2435 residuals[i] = (fY(i) - func)*(fY(i) - func)/(fE(i)*fE(i));
2439 TMath::KOrdStat(n, residuals, h-1, index);
2444 AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
2449 if (step==1)
return 0;
2454 for (i=0; i<h; i++) {
2455 itemp = subdat[start+index[i]];
2456 if (fInputFunction){
2457 fInputFunction->SetParameters(fParams.GetMatrixArray());
2458 func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2461 if ((fSpecial>100)&&(fSpecial<200)){
2462 npar = fSpecial-100;
2464 for (j=1; j<npar; j++)
2465 val[j] = val[j-1]*fX(itemp, 0);
2466 for (j=0; j<npar; j++)
2467 func += fParams(j)*val[j];
2468 }
else if (fSpecial>200) {
2470 npar = fSpecial-201;
2472 for (j=0; j<npar; j++)
2473 func += fParams(j+1)*fX(itemp, j);
2475 for (j=0; j<fNfunctions; j++) {
2476 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2477 val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
2478 func += fParams(j)*val[j];
2482 sum+=(fY(itemp)-func)*(fY(itemp)-func)/(fE(itemp)*fE(itemp));
2485 for (i=0; i<h; i++) {
2486 if (fInputFunction){
2487 fInputFunction->SetParameters(fParams.GetMatrixArray());
2488 func=fInputFunction->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
2491 if ((fSpecial>100)&&(fSpecial<200)){
2492 npar = fSpecial-100;
2494 for (j=1; j<npar; j++)
2495 val[j] = val[j-1]*fX(index[i], 0);
2496 for (j=0; j<npar; j++)
2497 func += fParams(j)*val[j];
2501 npar = fSpecial-201;
2503 for (j=0; j<npar; j++)
2504 func += fParams(j+1)*fX(index[i], j);
2506 for (j=0; j<fNfunctions; j++) {
2507 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
2508 val[j] = f1->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
2509 func += fParams(j)*val[j];
2515 sum+=(fY(index[i])-func)*(fY(index[i])-func)/(fE(index[i])*fE(index[i]));
2524 Bool_t TLinearFitter::Linf()
2527 fDesignTemp2+=fDesignTemp3;
2528 fDesignTemp+=fDesignTemp2;
2529 fDesign+=fDesignTemp;
2530 fDesignTemp3.Zero();
2531 fDesignTemp2.Zero();
2533 fAtbTemp2+=fAtbTemp3;
2534 fAtbTemp+=fAtbTemp2;
2544 TDecompChol chol(fDesign);
2545 TVectorD temp(fNfunctions);
2547 temp = chol.Solve(fAtb, ok);
2549 Error(
"Linf",
"Matrix inversion failed");
2563 Int_t TLinearFitter::Partition(Int_t nmini, Int_t *indsubdat)
2567 if ((fNpoints>=2*nmini) && (fNpoints<=(3*nmini-1))) {
2569 indsubdat[0]=Int_t(fNpoints*0.5);
2570 indsubdat[1]=Int_t(fNpoints*0.5)+1;
2572 indsubdat[0]=indsubdat[1]=Int_t(fNpoints/2);
2576 if((fNpoints>=3*nmini) && (fNpoints<(4*nmini -1))) {
2578 indsubdat[0]=indsubdat[1]=indsubdat[2]=Int_t(fNpoints/3);
2580 indsubdat[0]=Int_t(fNpoints/3);
2581 indsubdat[1]=Int_t(fNpoints/3)+1;
2582 if (fNpoints%3==1) indsubdat[2]=Int_t(fNpoints/3);
2583 else indsubdat[2]=Int_t(fNpoints/3)+1;
2588 if((fNpoints>=4*nmini)&&(fNpoints<=(5*nmini-1))){
2589 if (fNpoints%4==0) indsubdat[0]=indsubdat[1]=indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
2591 indsubdat[0]=Int_t(fNpoints/4);
2592 indsubdat[1]=Int_t(fNpoints/4)+1;
2593 if(fNpoints%4==1) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
2595 indsubdat[2]=Int_t(fNpoints/4)+1;
2596 indsubdat[3]=Int_t(fNpoints/4);
2598 if(fNpoints%4==3) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4)+1;
2602 for(Int_t i=0; i<5; i++)
2615 void TLinearFitter::RDraw(Int_t *subdat, Int_t *indsubdat)
2621 for (i=0; i<5; i++) {
2622 if (indsubdat[i]!=0)
2626 for (k=1; k<=ngroup; k++) {
2627 for (m=1; m<=indsubdat[k-1]; m++) {
2628 nrand = Int_t(r.Uniform(0, 1) * (fNpoints-jndex)) + 1;
2633 subdat[jndex-1] = nrand + jndex - 2;
2634 for (i=1; i<=jndex-1; i++) {
2635 if(subdat[i-1] > nrand+i-2) {
2636 for(j=jndex; j>=i+1; j--) {
2637 subdat[j-1] = subdat[j-2];
2639 subdat[i-1] = nrand+i-2;