00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TLinearFitter.h"
00013 #include "TMath.h"
00014 #include "TDecompChol.h"
00015 #include "TGraph.h"
00016 #include "TGraph2D.h"
00017 #include "TMultiGraph.h"
00018 #include "TRandom2.h"
00019 #include "TObjString.h"
00020 #include "TF2.h"
00021 #include "TH1.h"
00022 #include "TList.h"
00023
00024
00025 ClassImp(TLinearFitter)
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 TLinearFitter::TLinearFitter() :
00190 TVirtualFitter(),
00191 fParams(),
00192 fParCovar(),
00193 fTValues(),
00194 fDesign(),
00195 fDesignTemp(),
00196 fDesignTemp2(),
00197 fDesignTemp3(),
00198 fAtb(),
00199 fAtbTemp(),
00200 fAtbTemp2(),
00201 fAtbTemp3(),
00202 fFunctions(),
00203 fY(),
00204 fX(),
00205 fE(),
00206 fVal()
00207 {
00208
00209
00210
00211
00212 fChisquare =0;
00213 fNpoints =0;
00214 fNdim =0;
00215 fY2 =0;
00216 fY2Temp =0;
00217 fNfixed =0;
00218 fIsSet =kFALSE;
00219 fFormula =0;
00220 fFixedParams=0;
00221 fSpecial =0;
00222 fInputFunction=0;
00223 fStoreData =kTRUE;
00224 fRobust =kFALSE;
00225 fNfunctions = 0;
00226 fFormulaSize = 0;
00227 fH = 0;
00228 }
00229
00230
00231 TLinearFitter::TLinearFitter(Int_t ndim) :
00232 fVal()
00233 {
00234
00235
00236
00237
00238 fNdim =ndim;
00239 fNpoints =0;
00240 fY2 =0;
00241 fY2Temp =0;
00242 fNfixed =0;
00243 fFixedParams=0;
00244 fFormula =0;
00245 fIsSet =kFALSE;
00246 fChisquare=0;
00247 fSpecial =0;
00248 fInputFunction=0;
00249 fStoreData=kTRUE;
00250 fRobust = kFALSE;
00251 fNfunctions = 0;
00252 fFormulaSize = 0;
00253 fH = 0;
00254 }
00255
00256
00257 TLinearFitter::TLinearFitter(Int_t ndim, const char *formula, Option_t *opt)
00258 {
00259
00260
00261
00262
00263
00264
00265
00266 fNdim=ndim;
00267 fNpoints=0;
00268 fChisquare=0;
00269 fY2=0;
00270 fNfixed=0;
00271 fFixedParams=0;
00272 fSpecial=0;
00273 fInputFunction=0;
00274 fFormula = 0;
00275 TString option=opt;
00276 option.ToUpper();
00277 if (option.Contains("D"))
00278 fStoreData=kTRUE;
00279 else
00280 fStoreData=kFALSE;
00281 fRobust=kFALSE;
00282 SetFormula(formula);
00283 }
00284
00285
00286 TLinearFitter::TLinearFitter(TFormula *function, Option_t *opt)
00287 {
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 fNdim=function->GetNdim();
00300 if (!function->IsLinear()){
00301 Int_t number=function->GetNumber();
00302 if (number<299 || number>310){
00303 Error("TLinearFitter", "Trying to fit with a nonlinear function");
00304 return;
00305 }
00306 }
00307 fNpoints=0;
00308 fChisquare=0;
00309 fY2=0;
00310 fNfixed=0;
00311 fFixedParams=0;
00312 fSpecial=0;
00313 fFormula = 0;
00314 TString option=opt;
00315 option.ToUpper();
00316 if (option.Contains("D"))
00317 fStoreData=kTRUE;
00318 else
00319 fStoreData=kFALSE;
00320 fIsSet=kTRUE;
00321 fRobust=kFALSE;
00322 fInputFunction=0;
00323
00324 SetFormula(function);
00325 }
00326
00327
00328 TLinearFitter::TLinearFitter(const TLinearFitter& tlf) :
00329 TVirtualFitter(tlf),
00330 fParams(tlf.fParams),
00331 fParCovar(tlf.fParCovar),
00332 fTValues(tlf.fTValues),
00333 fParSign(tlf.fParSign),
00334 fDesign(tlf.fDesign),
00335 fDesignTemp(tlf.fDesignTemp),
00336 fDesignTemp2(tlf.fDesignTemp2),
00337 fDesignTemp3(tlf.fDesignTemp3),
00338 fAtb(tlf.fAtb),
00339 fAtbTemp(tlf.fAtbTemp),
00340 fAtbTemp2(tlf.fAtbTemp2),
00341 fAtbTemp3(tlf.fAtbTemp3),
00342 fFunctions( * (TObjArray *)tlf.fFunctions.Clone()),
00343 fY(tlf.fY),
00344 fY2(tlf.fY2),
00345 fY2Temp(tlf.fY2Temp),
00346 fX(tlf.fX),
00347 fE(tlf.fE),
00348 fInputFunction(tlf.fInputFunction),
00349 fNpoints(tlf.fNpoints),
00350 fNfunctions(tlf.fNfunctions),
00351 fFormulaSize(tlf.fFormulaSize),
00352 fNdim(tlf.fNdim),
00353 fNfixed(tlf.fNfixed),
00354 fSpecial(tlf.fSpecial),
00355 fFormula(0),
00356 fIsSet(tlf.fIsSet),
00357 fStoreData(tlf.fStoreData),
00358 fChisquare(tlf.fChisquare),
00359 fH(tlf.fH),
00360 fRobust(tlf.fRobust),
00361 fFitsample(tlf.fFitsample),
00362 fFixedParams(0)
00363 {
00364
00365
00366
00367
00368
00369 if ( tlf.fFixedParams && fNfixed > 0 ) {
00370 fFixedParams=new Bool_t[fNfixed];
00371 for(Int_t i=0; i<fNfixed; ++i)
00372 fFixedParams[i]=tlf.fFixedParams[i];
00373 }
00374 if (tlf.fFormula) {
00375 fFormula = new char[fFormulaSize+1];
00376 strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
00377 }
00378
00379 }
00380
00381
00382
00383 TLinearFitter::~TLinearFitter()
00384 {
00385
00386
00387 if (fFormula) {
00388 delete [] fFormula;
00389 fFormula = 0;
00390 }
00391 if (fFixedParams) {
00392 delete [] fFixedParams;
00393 fFixedParams = 0;
00394 }
00395 fInputFunction = 0;
00396 fFunctions.Delete();
00397
00398 }
00399
00400
00401 TLinearFitter& TLinearFitter::operator=(const TLinearFitter& tlf)
00402 {
00403
00404
00405 if(this!=&tlf) {
00406 TVirtualFitter::operator=(tlf);
00407 fParams.ResizeTo(tlf.fParams); fParams=tlf.fParams;
00408 fParCovar.ResizeTo(tlf.fParCovar); fParCovar=tlf.fParCovar;
00409 fTValues.ResizeTo(tlf.fTValues); fTValues=tlf.fTValues;
00410 fParSign.ResizeTo(tlf.fParSign); fParSign=tlf.fParSign;
00411 fDesign.ResizeTo(tlf.fDesign); fDesign=tlf.fDesign;
00412 fDesignTemp.ResizeTo(tlf.fDesignTemp); fDesignTemp=tlf.fDesignTemp;
00413 fDesignTemp2.ResizeTo(tlf.fDesignTemp2); fDesignTemp2=tlf.fDesignTemp2;
00414 fDesignTemp3.ResizeTo(tlf.fDesignTemp3); fDesignTemp3=tlf.fDesignTemp3;
00415 fAtb.ResizeTo(tlf.fAtb); fAtb=tlf.fAtb;
00416 fAtbTemp.ResizeTo(tlf.fAtbTemp); fAtbTemp=tlf.fAtbTemp;
00417 fAtbTemp2.ResizeTo(tlf.fAtbTemp2); fAtbTemp2=tlf.fAtbTemp2;
00418 fAtbTemp3.ResizeTo(tlf.fAtbTemp3); fAtbTemp3=tlf.fAtbTemp3;
00419
00420 if (fFormula) delete [] fFormula;
00421 fFormula = 0;
00422 if (tlf.fFormula) {
00423 fFormula = new char[fFormulaSize+1];
00424 strlcpy(fFormula,tlf.fFormula,fFormulaSize+1);
00425 }
00426
00427 if (fFixedParams) delete [] fFixedParams;
00428 fFixedParams = 0;
00429 if ( tlf.fFixedParams && fNfixed > 0 ) {
00430 fFixedParams=new Bool_t[tlf.fNfixed];
00431 for(Int_t i=0; i<tlf.fNfixed; ++i)
00432 fFixedParams[i]=tlf.fFixedParams[i];
00433 }
00434
00435 fFunctions.Delete();
00436 fFunctions= *(TObjArray*) tlf.fFunctions.Clone();
00437 fY=tlf.fY;
00438 fY2=tlf.fY2;
00439 fY2Temp=tlf.fY2Temp;
00440 fX=tlf.fX;
00441 fE=tlf.fE;
00442 fInputFunction=(TFormula*)tlf.fInputFunction;
00443 fNpoints=tlf.fNpoints;
00444 fNfunctions=tlf.fNfunctions;
00445 fFormulaSize=tlf.fFormulaSize;
00446 fNdim=tlf.fNdim;
00447 fNfixed=tlf.fNfixed;
00448 fSpecial=tlf.fSpecial;
00449 fIsSet=tlf.fIsSet;
00450 fStoreData=tlf.fStoreData;
00451 fChisquare=tlf.fChisquare;
00452 fH=tlf.fH;
00453 fRobust=tlf.fRobust;
00454 fFitsample=tlf.fFitsample;
00455 }
00456 return *this;
00457 }
00458
00459
00460 void TLinearFitter::Add(TLinearFitter *tlf)
00461 {
00462
00463
00464
00465
00466 fParams.Zero();
00467 fParCovar.Zero();
00468 fTValues.Zero();
00469 fParSign.Zero();
00470
00471 fDesign += tlf->fDesign;
00472
00473 fDesignTemp += tlf->fDesignTemp;
00474 fDesignTemp2 += tlf->fDesignTemp2;
00475 fDesignTemp3 += tlf->fDesignTemp3;
00476 fAtb += tlf->fAtb;
00477 fAtbTemp += tlf->fAtbTemp;
00478 fAtbTemp2 += tlf->fAtbTemp2;
00479 fAtbTemp3 += tlf->fAtbTemp3;
00480
00481 if (fStoreData){
00482 Int_t size=fY.GetNoElements();
00483 Int_t newsize = fNpoints+tlf->fNpoints;
00484 if (size<newsize){
00485 fY.ResizeTo(newsize);
00486 fE.ResizeTo(newsize);
00487 fX.ResizeTo(newsize, fNdim);
00488 }
00489 for (Int_t i=fNpoints; i<newsize; i++){
00490 fY(i)=tlf->fY(i-fNpoints);
00491 fE(i)=tlf->fE(i-fNpoints);
00492 for (Int_t j=0; j<fNdim; j++){
00493 fX(i,j)=tlf->fX(i-fNpoints, j);
00494 }
00495 }
00496 }
00497 fY2 += tlf->fY2;
00498 fY2Temp += tlf->fY2Temp;
00499 fNpoints += tlf->fNpoints;
00500
00501
00502 fChisquare=0;
00503 fH=0;
00504 fRobust=0;
00505 }
00506
00507
00508 void TLinearFitter::AddPoint(Double_t *x, Double_t y, Double_t e)
00509 {
00510
00511
00512
00513
00514
00515 Int_t size;
00516 fNpoints++;
00517 if (fStoreData){
00518 size=fY.GetNoElements();
00519 if (size<fNpoints){
00520 fY.ResizeTo(fNpoints+fNpoints/2);
00521 fE.ResizeTo(fNpoints+fNpoints/2);
00522 fX.ResizeTo(fNpoints+fNpoints/2, fNdim);
00523 }
00524
00525 Int_t j=fNpoints-1;
00526 fY(j)=y;
00527 fE(j)=e;
00528 for (Int_t i=0; i<fNdim; i++)
00529 fX(j,i)=x[i];
00530 }
00531
00532
00533
00534
00535 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
00536 Error("AddPoint", "Point can't be added, because the formula hasn't been set");
00537 return;
00538 }
00539 if (!fRobust) AddToDesign(x, y, e);
00540 }
00541
00542
00543 void TLinearFitter::AssignData(Int_t npoints, Int_t xncols, Double_t *x, Double_t *y, Double_t *e)
00544 {
00545
00546
00547
00548
00549
00550
00551
00552
00553 if (npoints<fNpoints){
00554 Error("AddData", "Those points are already added");
00555 return;
00556 }
00557 Bool_t same=kFALSE;
00558 if (fX.GetMatrixArray()==x && fY.GetMatrixArray()==y){
00559 if (e){
00560 if (fE.GetMatrixArray()==e)
00561 same=kTRUE;
00562 }
00563 }
00564
00565 fX.Use(npoints, xncols, x);
00566 fY.Use(npoints, y);
00567 if (e)
00568 fE.Use(npoints, e);
00569 else {
00570 fE.ResizeTo(npoints);
00571 fE=1;
00572 }
00573 Int_t xfirst;
00574 if (!fFunctions.IsEmpty() || fInputFunction || fSpecial>200) {
00575 if (same)
00576 xfirst=fNpoints;
00577
00578 else
00579 xfirst=0;
00580 for (Int_t i=xfirst; i<npoints; i++)
00581 AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
00582 }
00583 fNpoints=npoints;
00584 }
00585
00586
00587 void TLinearFitter::AddToDesign(Double_t *x, Double_t y, Double_t e)
00588 {
00589
00590
00591
00592
00593 Int_t i, j, ii;
00594 y/=e;
00595
00596
00597
00598 if ((fSpecial>100)&&(fSpecial<200)){
00599
00600 Int_t npar=fSpecial-100;
00601 fVal[0]=1;
00602 for (i=1; i<npar; i++)
00603 fVal[i]=fVal[i-1]*x[0];
00604 for (i=0; i<npar; i++)
00605 fVal[i]/=e;
00606 } else if (fSpecial>200){
00607
00608 Int_t npar=fSpecial-201;
00609 fVal[0]=1./e;
00610 for (i=0; i<npar; i++)
00611 fVal[i+1]=x[i]/e;
00612 } else {
00613
00614 for (ii=0; ii<fNfunctions; ii++){
00615 if (!fFunctions.IsEmpty()){
00616 TFormula *f1 = (TFormula*)(fFunctions.UncheckedAt(ii));
00617 fVal[ii]=f1->EvalPar(x)/e;
00618 } else {
00619 TFormula *f=(TFormula*)fInputFunction->GetLinearPart(ii);
00620 fVal[ii]=f->EvalPar(x)/e;
00621 }
00622 }
00623 }
00624
00625 for (i=0; i<fNfunctions; i++){
00626 for (j=0; j<i; j++)
00627 fDesignTemp3(j, i)+=fVal[i]*fVal[j];
00628 fDesignTemp3(i, i)+=fVal[i]*fVal[i];
00629 fAtbTemp3(i)+=fVal[i]*y;
00630
00631 }
00632 fY2Temp+=y*y;
00633 fIsSet=kTRUE;
00634
00635 if (fNpoints % 100 == 0 && fNpoints>100){
00636 fDesignTemp2+=fDesignTemp3;
00637 fDesignTemp3.Zero();
00638 fAtbTemp2+=fAtbTemp3;
00639 fAtbTemp3.Zero();
00640 if (fNpoints % 10000 == 0 && fNpoints>10000){
00641 fDesignTemp+=fDesignTemp2;
00642 fDesignTemp2.Zero();
00643 fAtbTemp+=fAtbTemp2;
00644 fAtbTemp2.Zero();
00645 fY2+=fY2Temp;
00646 fY2Temp=0;
00647 if (fNpoints % 1000000 == 0 && fNpoints>1000000){
00648 fDesign+=fDesignTemp;
00649 fDesignTemp.Zero();
00650 fAtb+=fAtbTemp;
00651 fAtbTemp.Zero();
00652 }
00653 }
00654 }
00655 }
00656
00657
00658 void TLinearFitter::AddTempMatrices()
00659 {
00660 if (fDesignTemp3.GetNrows()>0){
00661 fDesignTemp2+=fDesignTemp3;
00662 fDesignTemp+=fDesignTemp2;
00663 fDesign+=fDesignTemp;
00664 fDesignTemp3.Zero();
00665 fDesignTemp2.Zero();
00666 fDesignTemp.Zero();
00667 fAtbTemp2+=fAtbTemp3;
00668 fAtbTemp+=fAtbTemp2;
00669 fAtb+=fAtbTemp;
00670 fAtbTemp3.Zero();
00671 fAtbTemp2.Zero();
00672 fAtbTemp.Zero();
00673
00674 fY2+=fY2Temp;
00675 fY2Temp=0;
00676 }
00677 }
00678
00679
00680 void TLinearFitter::Clear(Option_t * )
00681 {
00682
00683
00684 fParams.Clear();
00685 fParCovar.Clear();
00686 fTValues.Clear();
00687 fParSign.Clear();
00688 fDesign.Clear();
00689 fDesignTemp.Clear();
00690 fDesignTemp2.Clear();
00691 fDesignTemp3.Clear();
00692 fAtb.Clear();
00693 fAtbTemp.Clear();
00694 fAtbTemp2.Clear();
00695 fAtbTemp3.Clear();
00696 fFunctions.Clear();
00697 fInputFunction=0;
00698 fY.Clear();
00699 fX.Clear();
00700 fE.Clear();
00701
00702 fNpoints=0;
00703 fNfunctions=0;
00704 fFormulaSize=0;
00705 fNdim=0;
00706 if (fFormula) delete [] fFormula;
00707 fFormula=0;
00708 fIsSet=0;
00709 if (fFixedParams) delete [] fFixedParams;
00710 fFixedParams=0;
00711
00712 fChisquare=0;
00713 fY2=0;
00714 fSpecial=0;
00715 fRobust=kFALSE;
00716 fFitsample.Clear();
00717 }
00718
00719
00720 void TLinearFitter::ClearPoints()
00721 {
00722
00723
00724 fDesign.Zero();
00725 fAtb.Zero();
00726 fDesignTemp.Zero();
00727 fDesignTemp2.Zero();
00728 fDesignTemp3.Zero();
00729 fAtbTemp.Zero();
00730 fAtbTemp2.Zero();
00731 fAtbTemp3.Zero();
00732
00733 fParams.Zero();
00734 fParCovar.Zero();
00735 fTValues.Zero();
00736 fParSign.Zero();
00737
00738 for (Int_t i=0; i<fNfunctions; i++)
00739 fFixedParams[i]=0;
00740 fChisquare=0;
00741 fNpoints=0;
00742
00743 }
00744
00745
00746 void TLinearFitter::Chisquare()
00747 {
00748
00749
00750 Int_t i, j;
00751 Double_t sumtotal2;
00752 Double_t temp, temp2;
00753
00754 if (!fStoreData){
00755 sumtotal2 = 0;
00756 for (i=0; i<fNfunctions; i++){
00757 for (j=0; j<i; j++){
00758 sumtotal2 += 2*fParams(i)*fParams(j)*fDesign(j, i);
00759 }
00760 sumtotal2 += fParams(i)*fParams(i)*fDesign(i, i);
00761 sumtotal2 -= 2*fParams(i)*fAtb(i);
00762 }
00763 sumtotal2 += fY2;
00764 } else {
00765 sumtotal2 = 0;
00766 if (fInputFunction){
00767 for (i=0; i<fNpoints; i++){
00768 temp = fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
00769 temp2 = (fY(i)-temp)*(fY(i)-temp);
00770 temp2 /= fE(i)*fE(i);
00771 sumtotal2 += temp2;
00772 }
00773 } else {
00774 sumtotal2 = 0;
00775 Double_t val[100];
00776 for (Int_t point=0; point<fNpoints; point++){
00777 temp = 0;
00778 if ((fSpecial>100)&&(fSpecial<200)){
00779 Int_t npar = fSpecial-100;
00780 val[0] = 1;
00781 for (i=1; i<npar; i++)
00782 val[i] = val[i-1]*fX(point, 0);
00783 for (i=0; i<npar; i++)
00784 temp += fParams(i)*val[i];
00785 } else {
00786 if (fSpecial>200) {
00787
00788 Int_t npar = fSpecial-201;
00789 temp+=fParams(0);
00790 for (i=0; i<npar; i++)
00791 temp += fParams(i+1)*fX(point, i);
00792 } else {
00793 for (j=0; j<fNfunctions; j++) {
00794 TFormula *f1 = (TFormula*)(fFunctions.UncheckedAt(j));
00795 val[j] = f1->EvalPar(TMatrixDRow(fX, point).GetPtr());
00796 temp += fParams(j)*val[j];
00797 }
00798 }
00799 }
00800 temp2 = (fY(point)-temp)*(fY(point)-temp);
00801 temp2 /= fE(point)*fE(point);
00802 sumtotal2 += temp2;
00803 }
00804 }
00805 }
00806 fChisquare = sumtotal2;
00807
00808 }
00809
00810
00811 void TLinearFitter::ComputeTValues()
00812 {
00813
00814
00815 for (Int_t i=0; i<fNfunctions; i++){
00816 fTValues(i) = fParams(i)/(TMath::Sqrt(fParCovar(i, i)));
00817 fParSign(i) = 2*(1-TMath::StudentI(TMath::Abs(fTValues(i)),fNpoints-fNfunctions+fNfixed));
00818 }
00819 }
00820
00821
00822 Int_t TLinearFitter::Eval()
00823 {
00824
00825
00826
00827 Double_t e;
00828 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
00829 Error("TLinearFitter::Eval", "The formula hasn't been set");
00830 return 1;
00831 }
00832
00833 fParams.ResizeTo(fNfunctions);
00834 fTValues.ResizeTo(fNfunctions);
00835 fParSign.ResizeTo(fNfunctions);
00836 fParCovar.ResizeTo(fNfunctions,fNfunctions);
00837
00838 fChisquare=0;
00839
00840 if (!fIsSet){
00841 Bool_t update = UpdateMatrix();
00842 if (!update){
00843
00844 fParams.Zero();
00845 fParCovar.Zero();
00846 fTValues.Zero();
00847 fParSign.Zero();
00848 fChisquare=0;
00849 if (fInputFunction){
00850 fInputFunction->SetParameters(fParams.GetMatrixArray());
00851 for (Int_t i=0; i<fNfunctions; i++)
00852 ((TF1*)fInputFunction)->SetParError(i, 0);
00853 ((TF1*)fInputFunction)->SetChisquare(0);
00854 ((TF1*)fInputFunction)->SetNDF(0);
00855 ((TF1*)fInputFunction)->SetNumberFitPoints(0);
00856 }
00857 return 1;
00858 }
00859 }
00860
00861 AddTempMatrices();
00862
00863
00864 Int_t i, ii, j=0;
00865 if (fNfixed>0){
00866 for (ii=0; ii<fNfunctions; ii++)
00867 fDesignTemp(ii, fNfixed) = fAtb(ii);
00868 for (i=0; i<fNfunctions; i++){
00869 if (fFixedParams[i]){
00870 for (ii=0; ii<i; ii++)
00871 fDesignTemp(ii, j) = fDesign(ii, i);
00872 for (ii=i; ii<fNfunctions; ii++)
00873 fDesignTemp(ii, j) = fDesign(i, ii);
00874 j++;
00875 for (ii=0; ii<fNfunctions; ii++){
00876 fAtb(ii)-=fParams(i)*(fDesignTemp(ii, j-1));
00877 }
00878 }
00879 }
00880 for (i=0; i<fNfunctions; i++){
00881 if (fFixedParams[i]){
00882 for (ii=0; ii<fNfunctions; ii++){
00883 fDesign(ii, i) = 0;
00884 fDesign(i, ii) = 0;
00885 }
00886 fDesign (i, i) = 1;
00887 fAtb(i) = fParams(i);
00888 }
00889 }
00890 }
00891
00892 TDecompChol chol(fDesign);
00893 Bool_t ok;
00894 TVectorD coef(fNfunctions);
00895 coef=chol.Solve(fAtb, ok);
00896 if (!ok){
00897 Error("Eval","Matrix inversion failed");
00898 fParams.Zero();
00899 fParCovar.Zero();
00900 fTValues.Zero();
00901 fParSign.Zero();
00902 if (fInputFunction){
00903 fInputFunction->SetParameters(fParams.GetMatrixArray());
00904 if (fInputFunction->InheritsFrom(TF1::Class())){
00905 ((TF1*)fInputFunction)->SetChisquare(0);
00906 ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
00907 ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
00908 }
00909 }
00910 return 1;
00911 }
00912 fParams=coef;
00913 fParCovar=chol.Invert();
00914
00915 if (fInputFunction){
00916 fInputFunction->SetParameters(fParams.GetMatrixArray());
00917 if (fInputFunction->InheritsFrom(TF1::Class())){
00918 for (i=0; i<fNfunctions; i++){
00919 e = TMath::Sqrt(fParCovar(i, i));
00920 ((TF1*)fInputFunction)->SetParError(i, e);
00921 }
00922 if (!fObjectFit)
00923 ((TF1*)fInputFunction)->SetChisquare(GetChisquare());
00924 ((TF1*)fInputFunction)->SetNDF(fNpoints-fNfunctions+fNfixed);
00925 ((TF1*)fInputFunction)->SetNumberFitPoints(fNpoints);
00926 }
00927 }
00928
00929
00930 j = 0;
00931 if (fNfixed>0){
00932 for (i=0; i<fNfunctions; i++){
00933 if (fFixedParams[i]){
00934 for (ii=0; ii<i; ii++){
00935 fDesign(ii, i) = fDesignTemp(ii, j);
00936 fAtb(ii) = fDesignTemp(ii, fNfixed);
00937 }
00938 for (ii=i; ii<fNfunctions; ii++){
00939 fDesign(i, ii) = fDesignTemp(ii, j);
00940 fAtb(ii) = fDesignTemp(ii, fNfixed);
00941 }
00942 j++;
00943 }
00944 }
00945 }
00946 return 0;
00947 }
00948
00949
00950 void TLinearFitter::FixParameter(Int_t ipar)
00951 {
00952
00953
00954 if (fParams.NonZeros()<1){
00955 Error("FixParameter", "no value available to fix the parameter");
00956 return;
00957 }
00958 if (ipar>fNfunctions || ipar<0){
00959 Error("FixParameter", "illegal parameter value");
00960 return;
00961 }
00962 if (fNfixed==fNfunctions) {
00963 Error("FixParameter", "no free parameters left");
00964 return;
00965 }
00966 if (!fFixedParams)
00967 fFixedParams = new Bool_t[fNfunctions];
00968 fFixedParams[ipar] = 1;
00969 fNfixed++;
00970 }
00971
00972
00973 void TLinearFitter::FixParameter(Int_t ipar, Double_t parvalue)
00974 {
00975
00976
00977 if (ipar>fNfunctions || ipar<0){
00978 Error("FixParameter", "illegal parameter value");
00979 return;
00980 }
00981 if (fNfixed==fNfunctions) {
00982 Error("FixParameter", "no free parameters left");
00983 return;
00984 }
00985 if(!fFixedParams)
00986 fFixedParams = new Bool_t[fNfunctions];
00987 fFixedParams[ipar] = 1;
00988 if (fParams.GetNoElements()<fNfunctions)
00989 fParams.ResizeTo(fNfunctions);
00990 fParams(ipar) = parvalue;
00991 fNfixed++;
00992 }
00993
00994
00995 void TLinearFitter::ReleaseParameter(Int_t ipar)
00996 {
00997
00998
00999 if (ipar>fNfunctions || ipar<0){
01000 Error("ReleaseParameter", "illegal parameter value");
01001 return;
01002 }
01003 if (!fFixedParams[ipar]){
01004 Warning("ReleaseParameter","This parameter is not fixed\n");
01005 return;
01006 } else {
01007 fFixedParams[ipar] = 0;
01008 fNfixed--;
01009 }
01010 }
01011
01012
01013 void TLinearFitter::GetAtbVector(TVectorD &v)
01014 {
01015
01016
01017 if (v.GetNoElements()!=fAtb.GetNoElements())
01018 v.ResizeTo(fAtb.GetNoElements());
01019 v = fAtb;
01020 }
01021
01022
01023 Double_t TLinearFitter::GetChisquare()
01024 {
01025
01026
01027 if (fChisquare > 1e-16)
01028 return fChisquare;
01029 else {
01030 Chisquare();
01031 return fChisquare;
01032 }
01033 }
01034
01035
01036 void TLinearFitter::GetConfidenceIntervals(Int_t n, Int_t ndim, const Double_t *x, Double_t *ci, Double_t cl)
01037 {
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 if (fInputFunction){
01051 Double_t *grad = new Double_t[fNfunctions];
01052 Double_t *sum_vector = new Double_t[fNfunctions];
01053 Double_t c=0;
01054 Int_t df = fNpoints-fNfunctions+fNfixed;
01055 Double_t t = TMath::StudentQuantile(0.5 + cl/2, df);
01056 Double_t chidf = TMath::Sqrt(fChisquare/df);
01057
01058 for (Int_t ipoint=0; ipoint<n; ipoint++){
01059 c=0;
01060 ((TF1*)(fInputFunction))->GradientPar(x+ndim*ipoint, grad);
01061
01062 for (Int_t irow=0; irow<fNfunctions; irow++){
01063 sum_vector[irow]=0;
01064 for (Int_t icol=0; icol<fNfunctions; icol++){
01065 sum_vector[irow]+=fParCovar(irow,icol)*grad[icol];
01066 }
01067 }
01068 for (Int_t i=0; i<fNfunctions; i++)
01069 c+=grad[i]*sum_vector[i];
01070 c=TMath::Sqrt(c);
01071 ci[ipoint]=c*t*chidf;
01072 }
01073
01074 delete [] grad;
01075 delete [] sum_vector;
01076 }
01077 }
01078
01079
01080 void TLinearFitter::GetConfidenceIntervals(TObject *obj, Double_t cl)
01081 {
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 if (!fInputFunction) {
01102 Error("GetConfidenceIntervals", "The case of fitting not with a TFormula is not yet implemented");
01103 return;
01104 }
01105
01106
01107
01108 if (obj->InheritsFrom(TGraph::Class())) {
01109 TGraph *gr = (TGraph*)obj;
01110 if (!gr->GetEY()){
01111 Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a graph");
01112 return;
01113 }
01114 if (fObjectFit->InheritsFrom(TGraph2D::Class())){
01115 Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a graph");
01116 return;
01117 }
01118 if (fObjectFit->InheritsFrom(TH1::Class())){
01119 if (((TH1*)(fObjectFit))->GetDimension()>1){
01120 Error("GetConfidenceIntervals", "A TGraph2DErrors or a TH23 should be passed instead of a graph");
01121 return;
01122 }
01123 }
01124
01125 GetConfidenceIntervals(gr->GetN(),1,gr->GetX(), gr->GetEY(), cl);
01126 for (Int_t i=0; i<gr->GetN(); i++)
01127 gr->SetPoint(i, gr->GetX()[i], fInputFunction->Eval(gr->GetX()[i]));
01128 }
01129
01130
01131 else if (obj->InheritsFrom(TGraph2D::Class())) {
01132 TGraph2D *gr2 = (TGraph2D*)obj;
01133 if (!gr2->GetEZ()){
01134 Error("GetConfidenceIntervals", "A TGraph2DErrors should be passed instead of a TGraph2D");
01135 return;
01136 }
01137 if (fObjectFit->InheritsFrom(TGraph::Class())){
01138 Error("GetConfidenceIntervals", "A TGraphErrors should be passed instead of a TGraph2D");
01139 return;
01140 }
01141 if (fObjectFit->InheritsFrom(TH1::Class())){
01142 if (((TH1*)(fObjectFit))->GetDimension()==1){
01143 Error("GetConfidenceIntervals", "A TGraphErrors or a TH1 should be passed instead of a graph");
01144 return;
01145 }
01146 }
01147 Double_t xy[2];
01148 Int_t np = gr2->GetN();
01149 Double_t *grad = new Double_t[fNfunctions];
01150 Double_t *sum_vector = new Double_t[fNfunctions];
01151 Double_t *x = gr2->GetX();
01152 Double_t *y = gr2->GetY();
01153 Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
01154 Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
01155 Double_t c = 0;
01156 for (Int_t ipoint=0; ipoint<np; ipoint++){
01157 c=0;
01158 xy[0]=x[ipoint];
01159 xy[1]=y[ipoint];
01160 ((TF1*)(fInputFunction))->GradientPar(xy, grad);
01161 for (Int_t irow=0; irow<fNfunctions; irow++){
01162 sum_vector[irow]=0;
01163 for (Int_t icol=0; icol<fNfunctions; icol++)
01164 sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
01165 }
01166 for (Int_t i=0; i<fNfunctions; i++)
01167 c+=grad[i]*sum_vector[i];
01168 c=TMath::Sqrt(c);
01169 gr2->SetPoint(ipoint, xy[0], xy[1], fInputFunction->EvalPar(xy));
01170 gr2->GetEZ()[ipoint]=c*t*chidf;
01171 }
01172 delete [] grad;
01173 delete [] sum_vector;
01174 }
01175
01176
01177 else if (obj->InheritsFrom(TH1::Class())) {
01178 if (fObjectFit->InheritsFrom(TGraph::Class())){
01179 if (((TH1*)obj)->GetDimension()>1){
01180 Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
01181 return;
01182 }
01183 }
01184 if (fObjectFit->InheritsFrom(TGraph2D::Class())){
01185 if (((TH1*)obj)->GetDimension()!=2){
01186 Error("GetConfidenceIntervals", "Fitted graph and passed histogram have different number of dimensions");
01187 return;
01188 }
01189 }
01190 if (fObjectFit->InheritsFrom(TH1::Class())){
01191 if (((TH1*)(fObjectFit))->GetDimension()!=((TH1*)(obj))->GetDimension()){
01192 Error("GetConfidenceIntervals", "Fitted and passed histograms have different number of dimensions");
01193 return;
01194 }
01195 }
01196
01197
01198 TH1 *hfit = (TH1*)obj;
01199 Double_t *grad = new Double_t[fNfunctions];
01200 Double_t *sum_vector = new Double_t[fNfunctions];
01201 Double_t x[3];
01202 Int_t hxfirst = hfit->GetXaxis()->GetFirst();
01203 Int_t hxlast = hfit->GetXaxis()->GetLast();
01204 Int_t hyfirst = hfit->GetYaxis()->GetFirst();
01205 Int_t hylast = hfit->GetYaxis()->GetLast();
01206 Int_t hzfirst = hfit->GetZaxis()->GetFirst();
01207 Int_t hzlast = hfit->GetZaxis()->GetLast();
01208
01209 TAxis *xaxis = hfit->GetXaxis();
01210 TAxis *yaxis = hfit->GetYaxis();
01211 TAxis *zaxis = hfit->GetZaxis();
01212 Double_t t = TMath::StudentQuantile(0.5 + cl/2, ((TF1*)(fInputFunction))->GetNDF());
01213 Double_t chidf = TMath::Sqrt(fChisquare/((TF1*)(fInputFunction))->GetNDF());
01214 Double_t c=0;
01215 for (Int_t binz=hzfirst; binz<=hzlast; binz++){
01216 x[2]=zaxis->GetBinCenter(binz);
01217 for (Int_t biny=hyfirst; biny<=hylast; biny++) {
01218 x[1]=yaxis->GetBinCenter(biny);
01219 for (Int_t binx=hxfirst; binx<=hxlast; binx++) {
01220 x[0]=xaxis->GetBinCenter(binx);
01221 ((TF1*)(fInputFunction))->GradientPar(x, grad);
01222 c=0;
01223 for (Int_t irow=0; irow<fNfunctions; irow++){
01224 sum_vector[irow]=0;
01225 for (Int_t icol=0; icol<fNfunctions; icol++)
01226 sum_vector[irow]+=fParCovar(irow, icol)*grad[icol];
01227 }
01228 for (Int_t i=0; i<fNfunctions; i++)
01229 c+=grad[i]*sum_vector[i];
01230 c=TMath::Sqrt(c);
01231 hfit->SetBinContent(binx, biny, binz, fInputFunction->EvalPar(x));
01232 hfit->SetBinError(binx, biny, binz, c*t*chidf);
01233 }
01234 }
01235 }
01236 delete [] grad;
01237 delete [] sum_vector;
01238 }
01239 else {
01240 Error("GetConfidenceIntervals", "This object type is not supported");
01241 return;
01242 }
01243 }
01244
01245
01246 Double_t* TLinearFitter::GetCovarianceMatrix() const
01247 {
01248
01249
01250 Double_t *p = const_cast<Double_t*>(fParCovar.GetMatrixArray());
01251 return p;
01252 }
01253
01254
01255 void TLinearFitter::GetCovarianceMatrix(TMatrixD &matr)
01256 {
01257
01258
01259 if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
01260 matr.ResizeTo(fNfunctions, fNfunctions);
01261 }
01262 matr = fParCovar;
01263 }
01264
01265
01266 void TLinearFitter::GetDesignMatrix(TMatrixD &matr)
01267 {
01268
01269 if (matr.GetNrows()!=fNfunctions || matr.GetNcols()!=fNfunctions){
01270 matr.ResizeTo(fNfunctions, fNfunctions);
01271 }
01272 matr = fDesign;
01273 }
01274
01275
01276 void TLinearFitter::GetErrors(TVectorD &vpar)
01277 {
01278
01279
01280 if (vpar.GetNoElements()!=fNfunctions) {
01281 vpar.ResizeTo(fNfunctions);
01282 }
01283 for (Int_t i=0; i<fNfunctions; i++)
01284 vpar(i) = TMath::Sqrt(fParCovar(i, i));
01285
01286 }
01287
01288
01289 void TLinearFitter::GetParameters(TVectorD &vpar)
01290 {
01291
01292
01293 if (vpar.GetNoElements()!=fNfunctions) {
01294 vpar.ResizeTo(fNfunctions);
01295 }
01296 vpar=fParams;
01297 }
01298
01299
01300 Int_t TLinearFitter::GetParameter(Int_t ipar,char* name,Double_t& value,Double_t& ,Double_t& , Double_t& ) const
01301 {
01302
01303
01304
01305 if (ipar<0 || ipar>fNfunctions) {
01306 Error("GetParError", "illegal value of parameter");
01307 return 0;
01308 }
01309 value = fParams(ipar);
01310 if (fInputFunction)
01311 strcpy(name, fInputFunction->GetParName(ipar));
01312 else
01313 name = 0;
01314 return 1;
01315 }
01316
01317
01318
01319 Double_t TLinearFitter::GetParError(Int_t ipar) const
01320 {
01321
01322
01323 if (ipar<0 || ipar>fNfunctions) {
01324 Error("GetParError", "illegal value of parameter");
01325 return 0;
01326 }
01327
01328 return TMath::Sqrt(fParCovar(ipar, ipar));
01329 }
01330
01331
01332
01333 const char *TLinearFitter::GetParName(Int_t ipar) const
01334 {
01335
01336
01337 if (ipar<0 || ipar>fNfunctions) {
01338 Error("GetParError", "illegal value of parameter");
01339 return 0;
01340 }
01341 if (fInputFunction)
01342 return fInputFunction->GetParName(ipar);
01343 return "";
01344 }
01345
01346
01347 Double_t TLinearFitter::GetParTValue(Int_t ipar)
01348 {
01349
01350
01351 if (ipar<0 || ipar>fNfunctions) {
01352 Error("GetParTValue", "illegal value of parameter");
01353 return 0;
01354 }
01355 if (!fTValues.NonZeros())
01356 ComputeTValues();
01357 return fTValues(ipar);
01358 }
01359
01360
01361 Double_t TLinearFitter::GetParSignificance(Int_t ipar)
01362 {
01363
01364
01365 if (ipar<0 || ipar>fNfunctions) {
01366 Error("GetParSignificance", "illegal value of parameter");
01367 return 0;
01368 }
01369 if (!fParSign.NonZeros())
01370 ComputeTValues();
01371 return fParSign(ipar);
01372 }
01373
01374
01375 void TLinearFitter::GetFitSample(TBits &bits)
01376 {
01377
01378
01379 if (!fRobust){
01380 Error("GetFitSample", "there is no fit sample in ordinary least-squares fit");
01381 return;
01382 }
01383 for (Int_t i=0; i<fNpoints; i++)
01384 bits.SetBitNumber(i, fFitsample.TestBitNumber(i));
01385
01386 }
01387
01388
01389 Int_t TLinearFitter::Merge(TCollection *list)
01390 {
01391
01392 if (!list) return -1;
01393 TIter next(list);
01394 TLinearFitter *lfit = 0;
01395 while ((lfit = (TLinearFitter*)next())) {
01396 if (!lfit->InheritsFrom(TLinearFitter::Class())) {
01397 Error("Add","Attempt to add object of class: %s to a %s",lfit->ClassName(),this->ClassName());
01398 return -1;
01399 }
01400 Add(lfit);
01401 }
01402 return 0;
01403 }
01404
01405 void TLinearFitter::SetBasisFunctions(TObjArray * functions)
01406 {
01407
01408
01409
01410
01411 fFunctions = *(functions);
01412 int size = fFunctions.GetEntries();
01413
01414 fNfunctions=size;
01415
01416 fDesign.ResizeTo(size, size);
01417 fAtb.ResizeTo(size);
01418 fDesignTemp.ResizeTo(size, size);
01419 fDesignTemp2.ResizeTo(size, size);
01420 fDesignTemp3.ResizeTo(size, size);
01421 fAtbTemp.ResizeTo(size);
01422 fAtbTemp2.ResizeTo(size);
01423 fAtbTemp3.ResizeTo(size);
01424 if (fFixedParams)
01425 delete [] fFixedParams;
01426 fFixedParams=new Bool_t[size];
01427 fDesign.Zero();
01428 fAtb.Zero();
01429 fDesignTemp.Zero();
01430 fDesignTemp2.Zero();
01431 fDesignTemp3.Zero();
01432 fAtbTemp.Zero();
01433 fAtbTemp2.Zero();
01434 fAtbTemp3.Zero();
01435 fY2Temp=0;
01436 fY2=0;
01437 for (int i=0; i<size; i++)
01438 fFixedParams[i]=0;
01439 fIsSet=kFALSE;
01440 fChisquare=0;
01441
01442 }
01443
01444
01445
01446 void TLinearFitter::SetDim(Int_t ndim)
01447 {
01448
01449
01450 fNdim=ndim;
01451 fY.ResizeTo(ndim+1);
01452 fX.ResizeTo(ndim+1, ndim);
01453 fE.ResizeTo(ndim+1);
01454
01455 fNpoints=0;
01456 fIsSet=kFALSE;
01457 }
01458
01459
01460 void TLinearFitter::SetFormula(const char *formula)
01461 {
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 Int_t size, special = 0;
01472 Int_t i;
01473 Bool_t isHyper = kFALSE;
01474
01475 if (fInputFunction)
01476 fInputFunction = 0;
01477 fFormulaSize = strlen(formula);
01478 fFormula = new char[fFormulaSize+1];
01479 strlcpy(fFormula, formula,fFormulaSize+1);
01480 fSpecial = 0;
01481
01482 char *fstring;
01483 fstring = (char *)strstr(fFormula, "hyp");
01484 if (fstring!=0){
01485 isHyper = kTRUE;
01486 fstring+=3;
01487 sscanf(fstring, "%d", &size);
01488
01489 size++;
01490 fSpecial=200+size;
01491 }
01492
01493 if (fSpecial==0) {
01494
01495 TString sstring(fFormula);
01496 sstring = sstring.ReplaceAll("++", 2, "|", 1);
01497 TString replaceformula;
01498
01499
01500
01501 TObjArray *oa = sstring.Tokenize("|");
01502
01503
01504 if (!fFunctions.IsEmpty())
01505 fFunctions.Clear();
01506
01507 fNfunctions = oa->GetEntriesFast();
01508 fFunctions.Expand(fNfunctions);
01509
01510
01511 char pattern[5];
01512 char replacement[6];
01513 for (i=0; i<fNdim; i++){
01514 snprintf(pattern,5, "x%d", i);
01515 snprintf(replacement,6, "x[%d]", i);
01516 sstring = sstring.ReplaceAll(pattern, Int_t(i/10)+2, replacement, Int_t(i/10)+4);
01517 }
01518
01519
01520 oa = sstring.Tokenize("|");
01521 for (i=0; i<fNfunctions; i++) {
01522 replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
01523 TFormula *f = new TFormula("f", replaceformula.Data());
01524 if (!f) {
01525 Error("TLinearFitter", "f_linear not allocated");
01526 return;
01527 }
01528 special=f->GetNumber();
01529 fFunctions.Add(f);
01530 }
01531
01532 if ((fNfunctions==1)&&(special>299)&&(special<310)){
01533
01534 size=special-299;
01535 fSpecial=100+size;
01536 } else
01537 size=fNfunctions;
01538 oa->Delete();
01539 delete oa;
01540 }
01541 fNfunctions=size;
01542
01543 fDesign.ResizeTo(size, size);
01544 fAtb.ResizeTo(size);
01545 fDesignTemp.ResizeTo(size, size);
01546 fDesignTemp2.ResizeTo(size, size);
01547 fDesignTemp3.ResizeTo(size, size);
01548 fAtbTemp.ResizeTo(size);
01549 fAtbTemp2.ResizeTo(size);
01550 fAtbTemp3.ResizeTo(size);
01551 if (fFixedParams)
01552 delete [] fFixedParams;
01553 fFixedParams=new Bool_t[size];
01554 fDesign.Zero();
01555 fAtb.Zero();
01556 fDesignTemp.Zero();
01557 fDesignTemp2.Zero();
01558 fDesignTemp3.Zero();
01559 fAtbTemp.Zero();
01560 fAtbTemp2.Zero();
01561 fAtbTemp3.Zero();
01562 fY2Temp=0;
01563 fY2=0;
01564 for (i=0; i<size; i++)
01565 fFixedParams[i]=0;
01566 fIsSet=kFALSE;
01567 fChisquare=0;
01568
01569 }
01570
01571
01572 void TLinearFitter::SetFormula(TFormula *function)
01573 {
01574
01575
01576 Int_t special, size;
01577 fInputFunction=function;
01578 fNfunctions=fInputFunction->GetNpar();
01579 fSpecial = 0;
01580 special=fInputFunction->GetNumber();
01581 if (!fFunctions.IsEmpty())
01582 fFunctions.Delete();
01583
01584 if ((special>299)&&(special<310)){
01585
01586 size=special-299;
01587 fSpecial=100+size;
01588 } else
01589 size=fNfunctions;
01590
01591 fNfunctions=size;
01592
01593 fDesign.ResizeTo(size, size);
01594 fAtb.ResizeTo(size);
01595 fDesignTemp.ResizeTo(size, size);
01596 fAtbTemp.ResizeTo(size);
01597
01598 fDesignTemp2.ResizeTo(size, size);
01599 fDesignTemp3.ResizeTo(size, size);
01600
01601 fAtbTemp2.ResizeTo(size);
01602 fAtbTemp3.ResizeTo(size);
01603
01604 if (fFixedParams)
01605 delete [] fFixedParams;
01606 fFixedParams=new Bool_t[size];
01607 fDesign.Zero();
01608 fAtb.Zero();
01609 fDesignTemp.Zero();
01610 fAtbTemp.Zero();
01611
01612 fDesignTemp2.Zero();
01613 fDesignTemp3.Zero();
01614
01615 fAtbTemp2.Zero();
01616 fAtbTemp3.Zero();
01617 fY2Temp=0;
01618 fY2=0;
01619 for (Int_t i=0; i<size; i++)
01620 fFixedParams[i]=0;
01621
01622
01623 if (function->InheritsFrom(TF1::Class())){
01624 Double_t al,bl;
01625 for (Int_t i=0;i<fNfunctions;i++) {
01626 ((TF1*)function)->GetParLimits(i,al,bl);
01627 if (al*bl !=0 && al >= bl) {
01628 FixParameter(i, function->GetParameter(i));
01629 }
01630 }
01631 }
01632
01633 fIsSet=kFALSE;
01634 fChisquare=0;
01635
01636 }
01637
01638
01639 Bool_t TLinearFitter::UpdateMatrix()
01640 {
01641
01642
01643 if (fStoreData) {
01644 for (Int_t i=0; i<fNpoints; i++) {
01645 AddToDesign(TMatrixDRow(fX, i).GetPtr(), fY(i), fE(i));
01646 }
01647 return 1;
01648 } else
01649 return 0;
01650
01651 }
01652
01653
01654 Int_t TLinearFitter::ExecuteCommand(const char *command, Double_t *args, Int_t )
01655 {
01656
01657
01658 if (!strcmp(command, "FitGraph")){
01659 if (args) return GraphLinearFitter(args[0]);
01660 else return GraphLinearFitter(0);
01661 }
01662 if (!strcmp(command, "FitGraph2D")){
01663 if (args) return Graph2DLinearFitter(args[0]);
01664 else return Graph2DLinearFitter(0);
01665 }
01666 if (!strcmp(command, "FitMultiGraph")){
01667 if (args) return MultiGraphLinearFitter(args[0]);
01668 else return MultiGraphLinearFitter(0);
01669 }
01670 if (!strcmp(command, "FitHist")) return HistLinearFitter();
01671
01672
01673 return 0;
01674 }
01675
01676
01677 void TLinearFitter::PrintResults(Int_t level, Double_t ) const
01678 {
01679
01680
01681
01682 if (level==3){
01683 if (!fRobust){
01684 printf("Fitting results:\nParameters:\nNO.\t\tVALUE\t\tERROR\n");
01685 for (Int_t i=0; i<fNfunctions; i++){
01686 printf("%d\t%e\t%e\n", i, fParams(i), TMath::Sqrt(fParCovar(i, i)));
01687 }
01688 } else {
01689 printf("Fitting results:\nParameters:\nNO.\t\tVALUE\n");
01690 for (Int_t i=0; i<fNfunctions; i++){
01691 printf("%d\t%e\n", i, fParams(i));
01692 }
01693 }
01694 }
01695 }
01696
01697
01698 Int_t TLinearFitter::GraphLinearFitter(Double_t h)
01699 {
01700
01701
01702 StoreData(kFALSE);
01703 TGraph *grr=(TGraph*)GetObjectFit();
01704 TF1 *f1=(TF1*)GetUserFunc();
01705 Foption_t fitOption=GetFitOption();
01706
01707
01708 Double_t *x=grr->GetX();
01709 Double_t *y=grr->GetY();
01710 Double_t e;
01711
01712 Int_t fitResult = 0;
01713
01714 SetDim(1);
01715 SetFormula(f1);
01716
01717 if (fitOption.Robust){
01718 fRobust=kTRUE;
01719 StoreData(kTRUE);
01720 }
01721
01722 Int_t n=grr->GetN();
01723 for (Int_t i=0; i<n; i++){
01724 if (!f1->IsInside(&x[i])) continue;
01725 e=grr->GetErrorY(i);
01726 if (e<0 || fitOption.W1)
01727 e=1;
01728 AddPoint(&x[i], y[i], e);
01729 }
01730
01731 if (fitOption.Robust){
01732 return EvalRobust(h);
01733 }
01734
01735 fitResult = Eval();
01736
01737
01738 if (!fitResult){
01739 if (!fitOption.Nochisq){
01740 Double_t temp, temp2, sumtotal=0;
01741 for (Int_t i=0; i<n; i++){
01742 if (!f1->IsInside(&x[i])) continue;
01743 temp=f1->Eval(x[i]);
01744 temp2=(y[i]-temp)*(y[i]-temp);
01745 e=grr->GetErrorY(i);
01746 if (e<0 || fitOption.W1)
01747 e=1;
01748 temp2/=(e*e);
01749
01750 sumtotal+=temp2;
01751 }
01752 fChisquare=sumtotal;
01753 f1->SetChisquare(fChisquare);
01754 }
01755 }
01756 return fitResult;
01757 }
01758
01759
01760 Int_t TLinearFitter::Graph2DLinearFitter(Double_t h)
01761 {
01762
01763 StoreData(kFALSE);
01764
01765 TGraph2D *gr=(TGraph2D*)GetObjectFit();
01766 TF2 *f2=(TF2*)GetUserFunc();
01767
01768 Foption_t fitOption=GetFitOption();
01769 Int_t n = gr->GetN();
01770 Double_t *gx = gr->GetX();
01771 Double_t *gy = gr->GetY();
01772 Double_t *gz = gr->GetZ();
01773 Double_t x[2];
01774 Double_t z, e;
01775 Int_t fitResult=0;
01776 SetDim(2);
01777 SetFormula(f2);
01778
01779 if (fitOption.Robust){
01780 fRobust=kTRUE;
01781 StoreData(kTRUE);
01782 }
01783
01784 for (Int_t bin=0;bin<n;bin++) {
01785 x[0] = gx[bin];
01786 x[1] = gy[bin];
01787 if (!f2->IsInside(x)) {
01788 continue;
01789 }
01790 z = gz[bin];
01791 e=gr->GetErrorZ(bin);
01792 if (e<0 || fitOption.W1)
01793 e=1;
01794 AddPoint(x, z, e);
01795 }
01796
01797 if (fitOption.Robust){
01798 return EvalRobust(h);
01799 }
01800
01801 fitResult = Eval();
01802
01803 if (!fitResult){
01804 if (!fitOption.Nochisq){
01805
01806 Double_t temp, temp2, sumtotal=0;
01807 for (Int_t bin=0; bin<n; bin++){
01808 x[0] = gx[bin];
01809 x[1] = gy[bin];
01810 if (!f2->IsInside(x)) {
01811 continue;
01812 }
01813 z = gz[bin];
01814
01815 temp=f2->Eval(x[0], x[1]);
01816 temp2=(z-temp)*(z-temp);
01817 e=gr->GetErrorZ(bin);
01818 if (e<0 || fitOption.W1)
01819 e=1;
01820 temp2/=(e*e);
01821
01822 sumtotal+=temp2;
01823 }
01824 fChisquare=sumtotal;
01825 f2->SetChisquare(fChisquare);
01826 }
01827 }
01828 return fitResult;
01829 }
01830
01831
01832 Int_t TLinearFitter::MultiGraphLinearFitter(Double_t h)
01833 {
01834
01835 Int_t n, i;
01836 Double_t *gx, *gy;
01837 Double_t e;
01838 TVirtualFitter *grFitter = TVirtualFitter::GetFitter();
01839 TMultiGraph *mg = (TMultiGraph*)grFitter->GetObjectFit();
01840 TF1 *f1 = (TF1*)grFitter->GetUserFunc();
01841 Foption_t fitOption = grFitter->GetFitOption();
01842 Int_t fitResult=0;
01843 SetDim(1);
01844
01845 if (fitOption.Robust){
01846 fRobust=kTRUE;
01847 StoreData(kTRUE);
01848 }
01849 SetFormula(f1);
01850
01851 TGraph *gr;
01852 TIter next(mg->GetListOfGraphs());
01853 while ((gr = (TGraph*) next())) {
01854 n = gr->GetN();
01855 gx = gr->GetX();
01856 gy = gr->GetY();
01857 for (i=0; i<n; i++){
01858 if (!f1->IsInside(&gx[i])) continue;
01859 e=gr->GetErrorY(i);
01860 if (e<0 || fitOption.W1)
01861 e=1;
01862 AddPoint(&gx[i], gy[i], e);
01863 }
01864 }
01865
01866 if (fitOption.Robust){
01867 return EvalRobust(h);
01868 }
01869
01870 fitResult = Eval();
01871
01872
01873 if (!fitResult){
01874 if (!fitOption.Nochisq){
01875 Double_t temp, temp2, sumtotal=0;
01876 next.Reset();
01877 while((gr = (TGraph*)next())) {
01878 n = gr->GetN();
01879 gx = gr->GetX();
01880 gy = gr->GetY();
01881 for (i=0; i<n; i++){
01882 if (!f1->IsInside(&gx[i])) continue;
01883 temp=f1->Eval(gx[i]);
01884 temp2=(gy[i]-temp)*(gy[i]-temp);
01885 e=gr->GetErrorY(i);
01886 if (e<0 || fitOption.W1)
01887 e=1;
01888 temp2/=(e*e);
01889
01890 sumtotal+=temp2;
01891 }
01892
01893 }
01894 fChisquare=sumtotal;
01895 f1->SetChisquare(fChisquare);
01896 }
01897 }
01898 return fitResult;
01899 }
01900
01901
01902 Int_t TLinearFitter::HistLinearFitter()
01903 {
01904
01905
01906 StoreData(kFALSE);
01907 Double_t cu,eu;
01908
01909 Double_t x[3];
01910 Int_t bin,binx,biny,binz;
01911
01912
01913 TH1 *hfit = (TH1*)GetObjectFit();
01914 TF1 *f1 = (TF1*)GetUserFunc();
01915 Int_t fitResult;
01916 Foption_t fitOption = GetFitOption();
01917
01918 SetDim(f1->GetNdim());
01919 SetFormula(f1);
01920
01921 Int_t hxfirst = GetXfirst();
01922 Int_t hxlast = GetXlast();
01923 Int_t hyfirst = GetYfirst();
01924 Int_t hylast = GetYlast();
01925 Int_t hzfirst = GetZfirst();
01926 Int_t hzlast = GetZlast();
01927 TAxis *xaxis = hfit->GetXaxis();
01928 TAxis *yaxis = hfit->GetYaxis();
01929 TAxis *zaxis = hfit->GetZaxis();
01930
01931 for (binz=hzfirst;binz<=hzlast;binz++) {
01932 x[2] = zaxis->GetBinCenter(binz);
01933 for (biny=hyfirst;biny<=hylast;biny++) {
01934 x[1] = yaxis->GetBinCenter(biny);
01935 for (binx=hxfirst;binx<=hxlast;binx++) {
01936 x[0] = xaxis->GetBinCenter(binx);
01937 if (!f1->IsInside(x)) continue;
01938 bin = hfit->GetBin(binx,biny,binz);
01939 cu = hfit->GetBinContent(bin);
01940 if (f1->GetNdim() < hfit->GetDimension()) {
01941 if (hfit->GetDimension() > 2) cu = x[2];
01942 else cu = x[1];
01943 }
01944 if (fitOption.W1) {
01945 if (fitOption.W1==1 && cu == 0) continue;
01946 eu = 1;
01947 } else {
01948 eu = hfit->GetBinError(bin);
01949 if (eu <= 0) continue;
01950 }
01951 AddPoint(x, cu, eu);
01952 }
01953 }
01954 }
01955
01956 fitResult = Eval();
01957
01958 if (!fitResult){
01959 if (!fitOption.Nochisq){
01960 Double_t temp, temp2, sumtotal=0;
01961 for (binz=hzfirst;binz<=hzlast;binz++) {
01962 x[2] = zaxis->GetBinCenter(binz);
01963 for (biny=hyfirst;biny<=hylast;biny++) {
01964 x[1] = yaxis->GetBinCenter(biny);
01965 for (binx=hxfirst;binx<=hxlast;binx++) {
01966 x[0] = xaxis->GetBinCenter(binx);
01967 if (!f1->IsInside(x)) continue;
01968 bin = hfit->GetBin(binx,biny,binz);
01969 cu = hfit->GetBinContent(bin);
01970
01971 if (fitOption.W1) {
01972 if (fitOption.W1==1 && cu == 0) continue;
01973 eu = 1;
01974 } else {
01975 eu = hfit->GetBinError(bin);
01976 if (eu <= 0) continue;
01977 }
01978 temp=f1->EvalPar(x);
01979 temp2=(cu-temp)*(cu-temp);
01980 temp2/=(eu*eu);
01981 sumtotal+=temp2;
01982 }
01983 }
01984 }
01985
01986 fChisquare=sumtotal;
01987 f1->SetChisquare(fChisquare);
01988 }
01989 }
01990 return fitResult;
01991 }
01992
01993
01994 void TLinearFitter::Streamer(TBuffer &R__b)
01995 {
01996 if (R__b.IsReading()) {
01997 Int_t old_matr_size = fNfunctions;
01998 R__b.ReadClassBuffer(TLinearFitter::Class(),this);
01999 if (old_matr_size < fNfunctions) {
02000 fDesignTemp.ResizeTo(fNfunctions, fNfunctions);
02001 fAtbTemp.ResizeTo(fNfunctions);
02002
02003 fDesignTemp2.ResizeTo(fNfunctions, fNfunctions);
02004 fDesignTemp3.ResizeTo(fNfunctions, fNfunctions);
02005
02006 fAtbTemp2.ResizeTo(fNfunctions);
02007 fAtbTemp3.ResizeTo(fNfunctions);
02008 }
02009 } else {
02010 if (fAtb.NonZeros()==0) AddTempMatrices();
02011 R__b.WriteClassBuffer(TLinearFitter::Class(),this);
02012 }
02013 }
02014
02015
02016 Int_t TLinearFitter::EvalRobust(Double_t h)
02017 {
02018
02019
02020
02021
02022
02023
02024
02025
02026 fRobust = kTRUE;
02027 Double_t kEps = 1e-13;
02028 Int_t nmini = 300;
02029 Int_t i, j, maxind=0, k, k1 = 500;
02030 Int_t nbest = 10;
02031 Double_t chi2 = -1;
02032
02033 if (fFunctions.IsEmpty()&&(!fInputFunction)&&(fSpecial<=200)){
02034 Error("TLinearFitter::EvalRobust", "The formula hasn't been set");
02035 return 1;
02036 }
02037
02038
02039 Double_t *bestchi2 = new Double_t[nbest];
02040 for (i=0; i<nbest; i++)
02041 bestchi2[i]=1e30;
02042
02043 Int_t hdef=Int_t((fNpoints+fNfunctions+1)/2);
02044
02045 if (h<0.000001) fH = hdef;
02046 else if (h>0 && h<1 && fNpoints*h > hdef)
02047 fH = Int_t(fNpoints*h);
02048 else {
02049 Warning("Fitting:", "illegal value of H, default is taken");
02050 fH=hdef;
02051 }
02052
02053 fDesign.ResizeTo(fNfunctions, fNfunctions);
02054 fAtb.ResizeTo(fNfunctions);
02055 fParams.ResizeTo(fNfunctions);
02056
02057 Int_t *index = new Int_t[fNpoints];
02058 Double_t *residuals = new Double_t[fNpoints];
02059
02060 if (fNpoints < 2*nmini) {
02061
02062
02063
02064 TMatrixD cstock(fNfunctions, nbest);
02065 for (k = 0; k < k1; k++) {
02066 CreateSubset(fNpoints, fH, index);
02067 chi2 = CStep(1, fH, residuals,index, index, -1, -1);
02068 chi2 = CStep(2, fH, residuals,index, index, -1, -1);
02069 maxind = TMath::LocMax(nbest, bestchi2);
02070 if (chi2 < bestchi2[maxind]) {
02071 bestchi2[maxind] = chi2;
02072 for (i=0; i<fNfunctions; i++)
02073 cstock(i, maxind) = fParams(i);
02074 }
02075 }
02076
02077
02078 Int_t *bestindex = new Int_t[fH];
02079 Double_t currentbest;
02080 for (i=0; i<nbest; i++) {
02081 for (j=0; j<fNfunctions; j++)
02082 fParams(j) = cstock(j, i);
02083 chi2 = 1;
02084 while (chi2 > kEps) {
02085 chi2 = CStep(2, fH, residuals,index, index, -1, -1);
02086 if (TMath::Abs(chi2 - bestchi2[i]) < kEps)
02087 break;
02088 else
02089 bestchi2[i] = chi2;
02090 }
02091 currentbest = TMath::MinElement(nbest, bestchi2);
02092 if (chi2 <= currentbest + kEps) {
02093 for (j=0; j<fH; j++){
02094 bestindex[j]=index[j];
02095 }
02096 maxind = i;
02097 }
02098 for (j=0; j<fNfunctions; j++)
02099 cstock(j, i) = fParams(j);
02100 }
02101
02102 for (j=0; j<fNfunctions; j++)
02103 fParams(j) = cstock(j, maxind);
02104 fFitsample.SetBitNumber(fNpoints, kFALSE);
02105 for (j=0; j<fH; j++){
02106
02107 fFitsample.SetBitNumber(bestindex[j]);
02108 }
02109 if (fInputFunction && fInputFunction->InheritsFrom(TF1::Class())) {
02110 ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
02111 ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
02112 ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
02113 }
02114 delete [] index;
02115 delete [] bestindex;
02116 delete [] residuals;
02117 delete [] bestchi2;
02118 return 0;
02119 }
02120
02121 Int_t indsubdat[5];
02122 for (i=0; i<5; i++)
02123 indsubdat[i] = 0;
02124
02125 Int_t nsub = Partition(nmini, indsubdat);
02126 Int_t hsub;
02127
02128 Int_t sum = TMath::Min(nmini*5, fNpoints);
02129
02130 Int_t *subdat = new Int_t[sum];
02131 RDraw(subdat, indsubdat);
02132
02133 TMatrixD cstockbig(fNfunctions, nbest*5);
02134 Int_t *beststock = new Int_t[nbest];
02135 Int_t i_start = 0;
02136 Int_t i_end = indsubdat[0];
02137 Int_t k2 = Int_t(k1/nsub);
02138 for (Int_t kgroup = 0; kgroup < nsub; kgroup++) {
02139
02140 hsub = Int_t(fH * indsubdat[kgroup]/fNpoints);
02141 for (i=0; i<nbest; i++)
02142 bestchi2[i] = 1e16;
02143 for (k=0; k<k2; k++) {
02144 CreateSubset(indsubdat[kgroup], hsub, index);
02145 chi2 = CStep(1, hsub, residuals, index, subdat, i_start, i_end);
02146 chi2 = CStep(2, hsub, residuals, index, subdat, i_start, i_end);
02147 maxind = TMath::LocMax(nbest, bestchi2);
02148 if (chi2 < bestchi2[maxind]){
02149 for (i=0; i<fNfunctions; i++)
02150 cstockbig(i, nbest*kgroup + maxind) = fParams(i);
02151 bestchi2[maxind] = chi2;
02152 }
02153 }
02154 if (kgroup != nsub - 1){
02155 i_start += indsubdat[kgroup];
02156 i_end += indsubdat[kgroup+1];
02157 }
02158 }
02159
02160 for (i=0; i<nbest; i++)
02161 bestchi2[i] = 1e30;
02162
02163 Int_t hsub2 = Int_t(fH*sum/fNpoints);
02164 for (k=0; k<nbest*5; k++) {
02165 for (i=0; i<fNfunctions; i++)
02166 fParams(i)=cstockbig(i, k);
02167 chi2 = CStep(1, hsub2, residuals, index, subdat, 0, sum);
02168 chi2 = CStep(2, hsub2, residuals, index, subdat, 0, sum);
02169 maxind = TMath::LocMax(nbest, bestchi2);
02170 if (chi2 < bestchi2[maxind]){
02171 beststock[maxind] = k;
02172 bestchi2[maxind] = chi2;
02173 }
02174 }
02175
02176
02177 for (k=0; k<nbest; k++) {
02178 for (i=0; i<fNfunctions; i++)
02179 fParams(i) = cstockbig(i, beststock[k]);
02180 chi2 = CStep(1, fH, residuals, index, index, -1, -1);
02181 chi2 = CStep(2, fH, residuals, index, index, -1, -1);
02182 bestchi2[k] = chi2;
02183 }
02184
02185 maxind = TMath::LocMin(nbest, bestchi2);
02186 for (i=0; i<fNfunctions; i++)
02187 fParams(i)=cstockbig(i, beststock[maxind]);
02188
02189 chi2 = 1;
02190 while (chi2 > kEps) {
02191 chi2 = CStep(2, fH, residuals, index, index, -1, -1);
02192 if (TMath::Abs(chi2 - bestchi2[maxind]) < kEps)
02193 break;
02194 else
02195 bestchi2[maxind] = chi2;
02196 }
02197
02198 fFitsample.SetBitNumber(fNpoints, kFALSE);
02199 for (j=0; j<fH; j++)
02200 fFitsample.SetBitNumber(index[j]);
02201 if (fInputFunction){
02202 ((TF1*)fInputFunction)->SetChisquare(bestchi2[maxind]);
02203 ((TF1*)fInputFunction)->SetNumberFitPoints(fH);
02204 ((TF1*)fInputFunction)->SetNDF(fH-fNfunctions);
02205 }
02206
02207 delete [] subdat;
02208 delete [] beststock;
02209 delete [] bestchi2;
02210 delete [] residuals;
02211 delete [] index;
02212
02213 return 0;
02214 }
02215
02216
02217 void TLinearFitter::CreateSubset(Int_t ntotal, Int_t h, Int_t *index)
02218 {
02219
02220
02221
02222 Int_t i, j;
02223 Bool_t repeat=kFALSE;
02224 Int_t nindex=0;
02225 Int_t num;
02226 for(i=0; i<ntotal; i++)
02227 index[i] = ntotal+1;
02228
02229 TRandom2 r;
02230
02231 for (i=0; i<fNfunctions; i++) {
02232 num=Int_t(r.Uniform(0, 1)*(ntotal-1));
02233 if (i>0){
02234 for(j=0; j<=i-1; j++) {
02235 if(index[j]==num)
02236 repeat = kTRUE;
02237 }
02238 }
02239 if(repeat==kTRUE) {
02240 i--;
02241 repeat = kFALSE;
02242 } else {
02243 index[i] = num;
02244 nindex++;
02245 }
02246 }
02247
02248
02249 fDesign.Zero();
02250 fAtb.Zero();
02251 for (i=0; i<fNfunctions; i++){
02252 AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
02253 }
02254 Bool_t ok;
02255
02256 ok = Linf();
02257
02258
02259 while (!ok && (nindex < h)) {
02260 repeat=kFALSE;
02261 do{
02262 num=Int_t(r.Uniform(0,1)*(ntotal-1));
02263 repeat=kFALSE;
02264 for(i=0; i<nindex; i++) {
02265 if(index[i]==num) {
02266 repeat=kTRUE;
02267 break;
02268 }
02269 }
02270 } while(repeat==kTRUE);
02271
02272 index[nindex] = num;
02273 nindex++;
02274
02275 AddToDesign(TMatrixDRow(fX, index[nindex-1]).GetPtr(), fY(index[nindex-1]), fE(index[nindex-1]));
02276 ok = Linf();
02277 }
02278 }
02279
02280
02281 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)
02282 {
02283
02284
02285 R__ASSERT( !fFunctions.IsEmpty() || fInputFunction || fSpecial>200);
02286
02287 Int_t i, j, itemp, n;
02288 Double_t func;
02289 Double_t val[100];
02290 Int_t npar;
02291 if (start > -1) {
02292 n = end - start;
02293 for (i=0; i<n; i++) {
02294 func = 0;
02295 itemp = subdat[start+i];
02296 if (fInputFunction){
02297 fInputFunction->SetParameters(fParams.GetMatrixArray());
02298 func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02299 } else {
02300 func=0;
02301 if ((fSpecial>100)&&(fSpecial<200)){
02302 npar = fSpecial-100;
02303 val[0] = 1;
02304 for (j=1; j<npar; j++)
02305 val[j] = val[j-1]*fX(itemp, 0);
02306 for (j=0; j<npar; j++)
02307 func += fParams(j)*val[j];
02308 } else if (fSpecial>200) {
02309
02310 npar = fSpecial-201;
02311 func+=fParams(0);
02312 for (j=0; j<npar; j++)
02313 func += fParams(j+1)*fX(itemp, j);
02314 } else {
02315
02316 for (j=0; j<fNfunctions; j++) {
02317 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02318 val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02319 func += fParams(j)*val[j];
02320 }
02321 }
02322 }
02323 residuals[i] = (fY(itemp) - func)*(fY(itemp) - func)/(fE(i)*fE(i));
02324 }
02325 } else {
02326 n=fNpoints;
02327 for (i=0; i<fNpoints; i++) {
02328 func = 0;
02329 if (fInputFunction){
02330 fInputFunction->SetParameters(fParams.GetMatrixArray());
02331 func=fInputFunction->EvalPar(TMatrixDRow(fX, i).GetPtr());
02332 } else {
02333 func=0;
02334 if ((fSpecial>100)&&(fSpecial<200)){
02335 npar = fSpecial-100;
02336 val[0] = 1;
02337 for (j=1; j<npar; j++)
02338 val[j] = val[j-1]*fX(i, 0);
02339 for (j=0; j<npar; j++)
02340 func += fParams(j)*val[j];
02341 } else if (fSpecial>200) {
02342
02343 npar = fSpecial-201;
02344 func+=fParams(0);
02345 for (j=0; j<npar; j++)
02346 func += fParams(j+1)*fX(i, j);
02347 } else {
02348 for (j=0; j<fNfunctions; j++) {
02349 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02350 val[j] = f1->EvalPar(TMatrixDRow(fX, i).GetPtr());
02351 func += fParams(j)*val[j];
02352 }
02353 }
02354 }
02355 residuals[i] = (fY(i) - func)*(fY(i) - func)/(fE(i)*fE(i));
02356 }
02357 }
02358
02359 TMath::KOrdStat(n, residuals, h-1, index);
02360
02361 fDesign.Zero();
02362 fAtb.Zero();
02363 for (i=0; i<h; i++)
02364 AddToDesign(TMatrixDRow(fX, index[i]).GetPtr(), fY(index[i]), fE(index[i]));
02365
02366 Linf();
02367
02368
02369 if (step==1) return 0;
02370 Double_t sum=0;
02371
02372
02373 if (start > -1) {
02374 for (i=0; i<h; i++) {
02375 itemp = subdat[start+index[i]];
02376 if (fInputFunction){
02377 fInputFunction->SetParameters(fParams.GetMatrixArray());
02378 func=fInputFunction->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02379 } else {
02380 func=0;
02381 if ((fSpecial>100)&&(fSpecial<200)){
02382 npar = fSpecial-100;
02383 val[0] = 1;
02384 for (j=1; j<npar; j++)
02385 val[j] = val[j-1]*fX(itemp, 0);
02386 for (j=0; j<npar; j++)
02387 func += fParams(j)*val[j];
02388 } else if (fSpecial>200) {
02389
02390 npar = fSpecial-201;
02391 func+=fParams(0);
02392 for (j=0; j<npar; j++)
02393 func += fParams(j+1)*fX(itemp, j);
02394 } else {
02395 for (j=0; j<fNfunctions; j++) {
02396 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02397 val[j] = f1->EvalPar(TMatrixDRow(fX, itemp).GetPtr());
02398 func += fParams(j)*val[j];
02399 }
02400 }
02401 }
02402 sum+=(fY(itemp)-func)*(fY(itemp)-func)/(fE(itemp)*fE(itemp));
02403 }
02404 } else {
02405 for (i=0; i<h; i++) {
02406 if (fInputFunction){
02407 fInputFunction->SetParameters(fParams.GetMatrixArray());
02408 func=fInputFunction->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
02409 } else {
02410 func=0;
02411 if ((fSpecial>100)&&(fSpecial<200)){
02412 npar = fSpecial-100;
02413 val[0] = 1;
02414 for (j=1; j<npar; j++)
02415 val[j] = val[j-1]*fX(index[i], 0);
02416 for (j=0; j<npar; j++)
02417 func += fParams(j)*val[j];
02418 } else {
02419 if (fSpecial>200) {
02420
02421 npar = fSpecial-201;
02422 func+=fParams(0);
02423 for (j=0; j<npar; j++)
02424 func += fParams(j+1)*fX(index[i], j);
02425 } else {
02426 for (j=0; j<fNfunctions; j++) {
02427 TF1 *f1 = (TF1*)(fFunctions.UncheckedAt(j));
02428 val[j] = f1->EvalPar(TMatrixDRow(fX, index[i]).GetPtr());
02429 func += fParams(j)*val[j];
02430 }
02431 }
02432 }
02433 }
02434
02435 sum+=(fY(index[i])-func)*(fY(index[i])-func)/(fE(index[i])*fE(index[i]));
02436 }
02437 }
02438
02439 return sum;
02440 }
02441
02442
02443 Bool_t TLinearFitter::Linf()
02444 {
02445
02446
02447 fDesignTemp2+=fDesignTemp3;
02448 fDesignTemp+=fDesignTemp2;
02449 fDesign+=fDesignTemp;
02450 fDesignTemp3.Zero();
02451 fDesignTemp2.Zero();
02452 fDesignTemp.Zero();
02453 fAtbTemp2+=fAtbTemp3;
02454 fAtbTemp+=fAtbTemp2;
02455 fAtb+=fAtbTemp;
02456 fAtbTemp3.Zero();
02457 fAtbTemp2.Zero();
02458 fAtbTemp.Zero();
02459
02460 fY2+=fY2Temp;
02461 fY2Temp=0;
02462
02463
02464 TDecompChol chol(fDesign);
02465 TVectorD temp(fNfunctions);
02466 Bool_t ok;
02467 temp = chol.Solve(fAtb, ok);
02468 if (!ok){
02469 Error("Linf","Matrix inversion failed");
02470
02471 fParams.Zero();
02472 return kFALSE;
02473 }
02474 fParams = temp;
02475 return ok;
02476 }
02477
02478
02479 Int_t TLinearFitter::Partition(Int_t nmini, Int_t *indsubdat)
02480 {
02481
02482
02483
02484
02485 Int_t nsub;
02486
02487 if ((fNpoints>=2*nmini) && (fNpoints<=(3*nmini-1))) {
02488 if (fNpoints%2==1){
02489 indsubdat[0]=Int_t(fNpoints*0.5);
02490 indsubdat[1]=Int_t(fNpoints*0.5)+1;
02491 } else
02492 indsubdat[0]=indsubdat[1]=Int_t(fNpoints/2);
02493 nsub=2;
02494 }
02495 else{
02496 if((fNpoints>=3*nmini) && (fNpoints<(4*nmini -1))) {
02497 if(fNpoints%3==0){
02498 indsubdat[0]=indsubdat[1]=indsubdat[2]=Int_t(fNpoints/3);
02499 } else {
02500 indsubdat[0]=Int_t(fNpoints/3);
02501 indsubdat[1]=Int_t(fNpoints/3)+1;
02502 if (fNpoints%3==1) indsubdat[2]=Int_t(fNpoints/3);
02503 else indsubdat[2]=Int_t(fNpoints/3)+1;
02504 }
02505 nsub=3;
02506 }
02507 else{
02508 if((fNpoints>=4*nmini)&&(fNpoints<=(5*nmini-1))){
02509 if (fNpoints%4==0) indsubdat[0]=indsubdat[1]=indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
02510 else {
02511 indsubdat[0]=Int_t(fNpoints/4);
02512 indsubdat[1]=Int_t(fNpoints/4)+1;
02513 if(fNpoints%4==1) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4);
02514 if(fNpoints%4==2) {
02515 indsubdat[2]=Int_t(fNpoints/4)+1;
02516 indsubdat[3]=Int_t(fNpoints/4);
02517 }
02518 if(fNpoints%4==3) indsubdat[2]=indsubdat[3]=Int_t(fNpoints/4)+1;
02519 }
02520 nsub=4;
02521 } else {
02522 for(Int_t i=0; i<5; i++)
02523 indsubdat[i]=nmini;
02524 nsub=5;
02525 }
02526 }
02527 }
02528 return nsub;
02529 }
02530
02531
02532 void TLinearFitter::RDraw(Int_t *subdat, Int_t *indsubdat)
02533 {
02534
02535
02536
02537 Int_t jndex = 0;
02538 Int_t nrand;
02539 Int_t i, k, m, j;
02540 Int_t ngroup=0;
02541 for (i=0; i<5; i++) {
02542 if (indsubdat[i]!=0)
02543 ngroup++;
02544 }
02545 TRandom r;
02546 for (k=1; k<=ngroup; k++) {
02547 for (m=1; m<=indsubdat[k-1]; m++) {
02548 nrand = Int_t(r.Uniform(0, 1) * (fNpoints-jndex)) + 1;
02549 jndex++;
02550 if (jndex==1) {
02551 subdat[0] = nrand;
02552 } else {
02553 subdat[jndex-1] = nrand + jndex - 2;
02554 for (i=1; i<=jndex-1; i++) {
02555 if(subdat[i-1] > nrand+i-2) {
02556 for(j=jndex; j>=i+1; j--) {
02557 subdat[j-1] = subdat[j-2];
02558 }
02559 subdat[i-1] = nrand+i-2;
02560 break;
02561 }
02562 }
02563 }
02564 }
02565 }
02566 }
02567
02568