00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "HFitInterface.h"
00014
00015 #include "Fit/BinData.h"
00016 #include "Fit/SparseData.h"
00017 #include "Fit/FitResult.h"
00018 #include "Math/IParamFunction.h"
00019
00020 #include <vector>
00021
00022 #include <cassert>
00023 #include <cmath>
00024
00025 #include "TH1.h"
00026 #include "THnSparse.h"
00027 #include "TF1.h"
00028 #include "TGraph2D.h"
00029 #include "TGraph.h"
00030 #include "TGraphErrors.h"
00031
00032
00033
00034 #include "TMultiGraph.h"
00035 #include "TList.h"
00036 #include "TError.h"
00037
00038
00039
00040 #ifdef DEBUG
00041 #include "TClass.h"
00042 #include <iostream>
00043 #endif
00044
00045
00046 namespace ROOT {
00047
00048 namespace Fit {
00049
00050
00051 namespace HFitInterface {
00052
00053
00054 bool IsPointOutOfRange(const TF1 * func, const double * x) {
00055
00056 if (func ==0) return false;
00057 return !func->IsInside(x);
00058 }
00059
00060 bool AdjustError(const DataOptions & option, double & error, double value = 1) {
00061
00062
00063
00064
00065
00066
00067
00068
00069 if (error <= 0) {
00070 if (option.fUseEmpty || (option.fErrors1 && std::abs(value) > 0 ) )
00071 error = 1.;
00072 else
00073 return false;
00074 } else if (option.fErrors1)
00075 error = 1;
00076 return true;
00077 }
00078
00079 void ExamineRange(TAxis * axis, std::pair<double,double> range,int &hxfirst,int &hxlast) {
00080
00081
00082 double xlow = range.first;
00083 double xhigh = range.second;
00084 #ifdef DEBUG
00085 std::cout << "xlow " << xlow << " xhigh = " << xhigh << std::endl;
00086 #endif
00087
00088 int ilow = axis->FindBin(xlow);
00089 int ihigh = axis->FindBin(xhigh);
00090 if (ilow > hxlast || ihigh < hxfirst) {
00091 Warning("ROOT::Fit::FillData","fit range is outside histogram range, no fit data for %s",axis->GetName());
00092 }
00093
00094 hxfirst = std::min( std::max( ilow, hxfirst), hxlast+1) ;
00095 hxlast = std::max( std::min( ihigh, hxlast), hxfirst-1) ;
00096
00097 if (hxfirst < hxlast) {
00098 if ( axis->GetBinCenter(hxfirst) < xlow) hxfirst++;
00099 if ( axis->GetBinCenter(hxlast) > xhigh) hxlast--;
00100 }
00101 }
00102
00103
00104 }
00105
00106 void FillData(BinData & dv, const TH1 * hfit, TF1 * func)
00107 {
00108
00109
00110
00111
00112
00113
00114
00115
00116 const DataOptions & fitOpt = dv.Opt();
00117
00118
00119
00120 bool useBinEdges = fitOpt.fIntegral || fitOpt.fBinVolume;
00121
00122 assert(hfit != 0);
00123
00124
00125
00126 int hxfirst = hfit->GetXaxis()->GetFirst();
00127 int hxlast = hfit->GetXaxis()->GetLast();
00128
00129 int hyfirst = hfit->GetYaxis()->GetFirst();
00130 int hylast = hfit->GetYaxis()->GetLast();
00131
00132 int hzfirst = hfit->GetZaxis()->GetFirst();
00133 int hzlast = hfit->GetZaxis()->GetLast();
00134
00135
00136
00137
00138
00139
00140 const DataRange & range = dv.Range();
00141 if (range.Size(0) != 0) {
00142 HFitInterface::ExamineRange( hfit->GetXaxis(), range(0), hxfirst, hxlast);
00143 if (range.Size(0) > 1 ) {
00144 Warning("ROOT::Fit::FillData","support only one range interval for X coordinate");
00145 }
00146 }
00147
00148 if (hfit->GetDimension() > 1 && range.Size(1) != 0) {
00149 HFitInterface::ExamineRange( hfit->GetYaxis(), range(1), hyfirst, hylast);
00150 if (range.Size(1) > 1 )
00151 Warning("ROOT::Fit::FillData","support only one range interval for Y coordinate");
00152 }
00153
00154 if (hfit->GetDimension() > 2 && range.Size(2) != 0) {
00155 HFitInterface::ExamineRange( hfit->GetZaxis(), range(2), hzfirst, hzlast);
00156 if (range.Size(2) > 1 )
00157 Warning("ROOT::Fit::FillData","support only one range interval for Z coordinate");
00158 }
00159
00160
00161 int n = (hxlast-hxfirst+1)*(hylast-hyfirst+1)*(hzlast-hzfirst+1);
00162
00163 #ifdef DEBUG
00164 std::cout << "THFitInterface: ifirst = " << hxfirst << " ilast = " << hxlast
00165 << " total bins " << n
00166 << std::endl;
00167 #endif
00168
00169
00170
00171
00172 int hdim = hfit->GetDimension();
00173 int ndim = hdim;
00174
00175 if (func !=0 && func->GetNdim() == hdim-1) ndim = hdim-1;
00176 assert( ndim > 0 );
00177
00178
00179 dv.Initialize(n,ndim);
00180
00181 double x[3];
00182 double s[3];
00183
00184 int binx = 0;
00185 int biny = 0;
00186 int binz = 0;
00187
00188 TAxis *xaxis = hfit->GetXaxis();
00189 TAxis *yaxis = hfit->GetYaxis();
00190 TAxis *zaxis = hfit->GetZaxis();
00191
00192 for ( binx = hxfirst; binx <= hxlast; ++binx) {
00193 if (useBinEdges) {
00194 x[0] = xaxis->GetBinLowEdge(binx);
00195 s[0] = xaxis->GetBinUpEdge(binx);
00196 }
00197 else
00198 x[0] = xaxis->GetBinCenter(binx);
00199
00200
00201 for ( biny = hyfirst; biny <= hylast; ++biny) {
00202 if (useBinEdges) {
00203 x[1] = yaxis->GetBinLowEdge(biny);
00204 s[1] = yaxis->GetBinUpEdge(biny);
00205 }
00206 else
00207 x[1] = yaxis->GetBinCenter(biny);
00208
00209 for ( binz = hzfirst; binz <= hzlast; ++binz) {
00210 if (useBinEdges) {
00211 x[2] = zaxis->GetBinLowEdge(binz);
00212 s[2] = zaxis->GetBinUpEdge(binz);
00213 }
00214 else
00215 x[2] = zaxis->GetBinCenter(binz);
00216
00217
00218
00219 if (func != 0) {
00220 func->RejectPoint(false);
00221 (*func)( &x[0] );
00222 if (func->RejectedPoint() ) continue;
00223 }
00224
00225
00226 double value = hfit->GetBinContent(binx, biny, binz);
00227 double error = hfit->GetBinError(binx, biny, binz);
00228 if (!HFitInterface::AdjustError(fitOpt,error,value) ) continue;
00229
00230 if (ndim == hdim -1) {
00231
00232
00233
00234 if (hdim == 2) dv.Add( x, x[1], yaxis->GetBinWidth(biny) / error );
00235 if (hdim == 3) dv.Add( x, x[2], zaxis->GetBinWidth(binz) / error );
00236 } else {
00237 dv.Add( x, value, error );
00238 if (useBinEdges) {
00239 dv.AddBinUpEdge( s );
00240 }
00241 }
00242
00243
00244 #ifdef DEBUG
00245 std::cout << "bin " << binx << " add point " << x[0] << " " << hfit->GetBinContent(binx) << std::endl;
00246 #endif
00247
00248 }
00249 }
00250 }
00251
00252
00253 #ifdef DEBUG
00254 std::cout << "THFitInterface::FillData: Hist FitData size is " << dv.Size() << std::endl;
00255 #endif
00256
00257 }
00258
00259
00260 void InitExpo(const ROOT::Fit::BinData & data, TF1 * f1)
00261 {
00262
00263
00264
00265 unsigned int n = data.Size();
00266 if (n == 0) return;
00267
00268
00269 double valxmin;
00270 double xmin = *(data.GetPoint(0,valxmin));
00271 double xmax = xmin;
00272 double valxmax = valxmin;
00273
00274 for (unsigned int i = 1; i < n; ++ i) {
00275 double val;
00276 double x = *(data.GetPoint(i,val) );
00277 if (x < xmin) {
00278 xmin = x;
00279 valxmin = val;
00280 }
00281 else if (x > xmax) {
00282 xmax = x;
00283 valxmax = val;
00284 }
00285 }
00286
00287
00288 if (valxmin <= 0 && valxmax > 0 ) valxmin = valxmax;
00289 else if (valxmax <=0 && valxmin > 0) valxmax = valxmin;
00290 else if (valxmin <=0 && valxmax <= 0) { valxmin = 1; valxmax = 1; }
00291
00292 double slope = std::log( valxmax/valxmin) / (xmax - xmin);
00293 double constant = std::log(valxmin) - slope * xmin;
00294 f1->SetParameters(constant, slope);
00295 }
00296
00297
00298
00299 void InitGaus(const ROOT::Fit::BinData & data, TF1 * f1)
00300 {
00301
00302
00303
00304
00305
00306 static const double sqrtpi = 2.506628;
00307
00308
00309 unsigned int n = data.Size();
00310 if (n == 0) return;
00311 double sumx = 0;
00312 double sumx2 = 0;
00313 double allcha = 0;
00314 double valmax = 0;
00315 double rangex = data.Coords(n-1)[0] - data.Coords(0)[0];
00316
00317 double binwidth = 1;
00318 if ( rangex > 0) binwidth = rangex;
00319 double x0 = 0;
00320 for (unsigned int i = 0; i < n; ++ i) {
00321 double val;
00322 double x = *(data.GetPoint(i,val) );
00323 sumx += val*x;
00324 sumx2 += val*x*x;
00325 allcha += val;
00326 if (val > valmax) valmax = val;
00327 if (i > 0) {
00328 double dx = x - x0;
00329 if (dx < binwidth) binwidth = dx;
00330 }
00331 x0 = x;
00332 }
00333
00334 if (allcha <= 0) return;
00335 double mean = sumx/allcha;
00336 double rms = sumx2/allcha - mean*mean;
00337
00338
00339 if (rms > 0)
00340 rms = std::sqrt(rms);
00341 else
00342 rms = binwidth*n/4;
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 double constant = 0.5*(valmax+ binwidth*allcha/(sqrtpi*rms));
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 f1->SetParameter(0,constant);
00370 f1->SetParameter(1,mean);
00371 f1->SetParameter(2,rms);
00372 f1->SetParLimits(2,0,10*rms);
00373
00374
00375 #ifdef DEBUG
00376 std::cout << "Gaussian initial par values" << constant << " " << mean << " " << rms << std::endl;
00377 #endif
00378
00379 }
00380
00381
00382 void Init2DGaus(const ROOT::Fit::BinData & data, TF1 * f1)
00383 {
00384
00385
00386
00387
00388
00389 static const double sqrtpi = 2.506628;
00390
00391
00392 unsigned int n = data.Size();
00393 if (n == 0) return;
00394 double sumx = 0, sumy = 0;
00395 double sumx2 = 0, sumy2 = 0;
00396 double allcha = 0;
00397 double valmax = 0;
00398 double rangex = data.Coords(n-1)[0] - data.Coords(0)[0];
00399 double rangey = data.Coords(n-1)[1] - data.Coords(0)[1];
00400
00401 double binwidthx = 1, binwidthy = 1;
00402 if ( rangex > 0) binwidthx = rangex;
00403 if ( rangey > 0) binwidthy = rangey;
00404 double x0 = 0, y0 = 0;
00405 for (unsigned int i = 0; i < n; ++i) {
00406 double val;
00407 const double *coords = data.GetPoint(i,val);
00408 double x = coords[0], y = coords[1];
00409 sumx += val*x;
00410 sumy += val*y;
00411 sumx2 += val*x*x;
00412 sumy2 += val*y*y;
00413 allcha += val;
00414 if (val > valmax) valmax = val;
00415 if (i > 0) {
00416 double dx = x - x0;
00417 if (dx < binwidthx) binwidthx = dx;
00418 double dy = y - y0;
00419 if (dy < binwidthy) binwidthy = dy;
00420 }
00421 x0 = x;
00422 y0 = y;
00423 }
00424
00425 if (allcha <= 0) return;
00426 double meanx = sumx/allcha, meany = sumy/allcha;
00427 double rmsx = sumx2/allcha - meanx*meanx;
00428 double rmsy = sumy2/allcha - meany*meany;
00429
00430
00431 if (rmsx > 0)
00432 rmsx = std::sqrt(rmsx);
00433 else
00434 rmsx = binwidthx*n/4;
00435
00436 if (rmsy > 0)
00437 rmsy = std::sqrt(rmsy);
00438 else
00439 rmsy = binwidthy*n/4;
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 double constant = 0.5 * (valmax+ binwidthx*allcha/(sqrtpi*rmsx))*
00450 (valmax+ binwidthy*allcha/(sqrtpi*rmsy));
00451
00452 f1->SetParameter(0,constant);
00453 f1->SetParameter(1,meanx);
00454 f1->SetParameter(2,rmsx);
00455 f1->SetParLimits(2,0,10*rmsx);
00456 f1->SetParameter(3,meany);
00457 f1->SetParameter(4,rmsy);
00458 f1->SetParLimits(4,0,10*rmsy);
00459
00460 #ifdef DEBUG
00461 std::cout << "2D Gaussian initial par values"
00462 << constant << " "
00463 << meanx << " "
00464 << rmsx
00465 << meany << " "
00466 << rmsy
00467 << std::endl;
00468 #endif
00469
00470 }
00471
00472
00473
00474 BinData::ErrorType GetDataType(const TGraph * gr, const DataOptions & fitOpt) {
00475
00476 double *ex = gr->GetEX();
00477 double *ey = gr->GetEY();
00478 double * eyl = gr->GetEYlow();
00479 double * eyh = gr->GetEYhigh();
00480
00481
00482
00483 BinData::ErrorType type = BinData::kValueError;
00484
00485 if (fitOpt.fErrors1 || ( ey == 0 && ( eyl == 0 || eyh == 0 ) ) ) {
00486 type = BinData::kNoError;
00487 }
00488
00489 else if ( ex != 0 && fitOpt.fCoordErrors) {
00490
00491 int i = 0;
00492 while (i < gr->GetN() && type != BinData::kCoordError) {
00493 if (ex[i] > 0) type = BinData::kCoordError;
00494 ++i;
00495 }
00496 }
00497 else if ( ( eyl != 0 && eyh != 0) && fitOpt.fAsymErrors) {
00498
00499 int i = 0;
00500 bool zeroError = true;
00501 while (i < gr->GetN() && zeroError) {
00502 double e2X = ( gr->GetErrorXlow(i) + gr->GetErrorXhigh(i) );
00503 double e2Y = eyl[i] + eyh[i];
00504 if ( e2X > 0 || e2Y > 0) zeroError = false;
00505 ++i;
00506 }
00507 if (zeroError)
00508 type = BinData::kNoError;
00509 else
00510 type = BinData::kAsymError;
00511 }
00512
00513
00514 if ( ey != 0 && type != BinData::kCoordError ) {
00515 int i = 0;
00516 bool zeroError = true;
00517 while (i < gr->GetN() && zeroError) {
00518 if (ey[i] > 0) zeroError = false;;
00519 ++i;
00520 }
00521 if (zeroError) type = BinData::kNoError;
00522 }
00523
00524
00525 #ifdef DEBUG
00526 std::cout << "type is " << type << " graph type is " << gr->IsA()->GetName() << std::endl;
00527 #endif
00528
00529 return type;
00530 }
00531
00532 BinData::ErrorType GetDataType(const TGraph2D * gr, const DataOptions & fitOpt) {
00533
00534 double *ex = gr->GetEX();
00535 double *ey = gr->GetEY();
00536 double *ez = gr->GetEZ();
00537
00538
00539 BinData::ErrorType type = BinData::kValueError;
00540
00541 if (ez == 0 ) {
00542 type = BinData::kNoError;
00543 }
00544 else if ( ex != 0 && ey!=0 && fitOpt.fCoordErrors) {
00545
00546 int i = 0;
00547 while (i < gr->GetN() && type != BinData::kCoordError) {
00548 if (ex[i] > 0 || ey[i] > 0) type = BinData::kCoordError;
00549 ++i;
00550 }
00551 }
00552
00553
00554 #ifdef DEBUG
00555 std::cout << "type is " << type << " graph2D type is " << gr->IsA()->GetName() << std::endl;
00556 #endif
00557
00558 return type;
00559 }
00560
00561
00562
00563 void DoFillData ( BinData & dv, const TGraph * gr, BinData::ErrorType type, TF1 * func ) {
00564
00565
00566
00567
00568 DataOptions & fitOpt = dv.Opt();
00569
00570 int nPoints = gr->GetN();
00571 double *gx = gr->GetX();
00572 double *gy = gr->GetY();
00573
00574 const DataRange & range = dv.Range();
00575 bool useRange = ( range.Size(0) > 0);
00576 double xmin = 0;
00577 double xmax = 0;
00578 range.GetRange(xmin,xmax);
00579
00580 dv.Initialize(nPoints,1, type);
00581
00582 #ifdef DEBUG
00583 std::cout << "DoFillData: graph npoints = " << nPoints << " type " << type << std::endl;
00584 if (func) {
00585 double a1,a2; func->GetRange(a1,a2); std::cout << "func range " << a1 << " " << a2 << std::endl;
00586 }
00587 #endif
00588
00589 double x[1];
00590 for ( int i = 0; i < nPoints; ++i) {
00591
00592 x[0] = gx[i];
00593
00594
00595 if (useRange && ( x[0] < xmin || x[0] > xmax) ) continue;
00596
00597
00598
00599 if (func) {
00600 func->RejectPoint(false);
00601 (*func)( x );
00602 if (func->RejectedPoint() ) continue;
00603 }
00604
00605
00606 if (fitOpt.fErrors1)
00607 dv.Add( gx[i], gy[i] );
00608
00609
00610
00611 else if (type == BinData::kValueError) {
00612 double errorY = gr->GetErrorY(i);
00613
00614
00615 if (!HFitInterface::AdjustError(fitOpt,errorY) ) continue;
00616 dv.Add( gx[i], gy[i], errorY );
00617
00618 #ifdef DEBUG
00619 std::cout << "Point " << i << " " << gx[i] << " " << gy[i] << " " << errorY << std::endl;
00620 #endif
00621
00622
00623 }
00624 else {
00625 double errorX = 0;
00626 if (fitOpt.fCoordErrors)
00627
00628
00629
00630 errorX = std::max( 0.5 * ( gr->GetErrorXlow(i) + gr->GetErrorXhigh(i) ) , 0. ) ;
00631
00632
00633
00634 double errorY = std::max(gr->GetErrorY(i), 0.);
00635 HFitInterface::AdjustError(fitOpt, errorY);
00636
00637
00638 if ( errorX <=0 && errorY <= 0 ) continue;
00639
00640 if (type == BinData::kAsymError) {
00641
00642 dv.Add( gx[i], gy[i], errorX, gr->GetErrorYlow(i), gr->GetErrorYhigh(i) );
00643 }
00644 else {
00645
00646 dv.Add( gx[i], gy[i], errorX, errorY );
00647 }
00648 }
00649
00650 }
00651
00652 #ifdef DEBUG
00653 std::cout << "TGraphFitInterface::FillData Graph FitData size is " << dv.Size() << std::endl;
00654 #endif
00655
00656 }
00657
00658 void FillData(SparseData & dv, const TH1 * h1, TF1 * )
00659 {
00660 const int dim = h1->GetDimension();
00661 std::vector<double> min(dim);
00662 std::vector<double> max(dim);
00663
00664 const TArray *array(dynamic_cast<const TArray*>(h1));
00665 assert(array && "THIS SHOULD NOT HAPPEN!");
00666 for ( int i = 0; i < array->GetSize(); ++i ) {
00667
00668
00669
00670
00671 if ( !( h1->IsBinOverflow(i) || h1->IsBinUnderflow(i) )
00672 && h1->GetBinContent(i))
00673 {
00674 int x,y,z;
00675 h1->GetBinXYZ(i, x, y, z);
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 min[0] = h1->GetXaxis()->GetBinLowEdge(x);
00687 max[0] = h1->GetXaxis()->GetBinUpEdge(x);
00688 if ( dim >= 2 )
00689 {
00690 min[1] = h1->GetYaxis()->GetBinLowEdge(y);
00691 max[1] = h1->GetYaxis()->GetBinUpEdge(y);
00692 }
00693 if ( dim >= 3 ) {
00694 min[2] = h1->GetZaxis()->GetBinLowEdge(z);
00695 max[2] = h1->GetZaxis()->GetBinUpEdge(z);
00696 }
00697
00698 dv.Add(min, max, h1->GetBinContent(i), h1->GetBinError(i));
00699 }
00700 }
00701 }
00702
00703 void FillData(SparseData & dv, const THnSparse * h1, TF1 * )
00704 {
00705 const int dim = h1->GetNdimensions();
00706 std::vector<double> min(dim);
00707 std::vector<double> max(dim);
00708 std::vector<Int_t> coord(dim);
00709
00710 ULong64_t nEntries = h1->GetNbins();
00711 for ( ULong64_t i = 0; i < nEntries; i++ )
00712 {
00713 double value = h1->GetBinContent( i, &coord[0] );
00714 if ( !value ) continue;
00715
00716
00717
00718
00719 bool insertBox = true;
00720 for ( int j = 0; j < dim && insertBox; ++j )
00721 {
00722 TAxis* axis = h1->GetAxis(j);
00723 if ( ( axis->GetBinLowEdge(coord[j]) < axis->GetXmin() ) ||
00724 ( axis->GetBinUpEdge(coord[j]) > axis->GetXmax() ) ) {
00725 insertBox = false;
00726 }
00727 min[j] = h1->GetAxis(j)->GetBinLowEdge(coord[j]);
00728 max[j] = h1->GetAxis(j)->GetBinUpEdge(coord[j]);
00729 }
00730 if ( !insertBox ) {
00731
00732 continue;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742 dv.Add(min, max, value, h1->GetBinError(i));
00743 }
00744 }
00745
00746 void FillData(BinData & dv, const THnSparse * s1, TF1 * func)
00747 {
00748
00749 unsigned int const ndim = s1->GetNdimensions();
00750 std::vector<double> xmin(ndim);
00751 std::vector<double> xmax(ndim);
00752 for ( unsigned int i = 0; i < ndim; ++i ) {
00753 TAxis* axis = s1->GetAxis(i);
00754 xmin[i] = axis->GetXmin();
00755 xmax[i] = axis->GetXmax();
00756 }
00757
00758
00759
00760 ROOT::Fit::DataOptions& dopt = dv.Opt();
00761 dopt.fUseEmpty = true;
00762
00763
00764 dopt.fBinVolume = true;
00765
00766
00767 ROOT::Fit::SparseData d(ndim, &xmin[0], &xmax[0]);
00768 ROOT::Fit::FillData(d, s1, func);
00769
00770
00771
00772
00773 d.GetBinDataIntegral(dv);
00774
00775 }
00776
00777 void FillData ( BinData & dv, const TGraph * gr, TF1 * func ) {
00778
00779
00780 assert(gr != 0);
00781
00782
00783 DataOptions & fitOpt = dv.Opt();
00784
00785 BinData::ErrorType type = GetDataType(gr,fitOpt);
00786
00787 fitOpt.fErrors1 = (type == BinData::kNoError);
00788
00789
00790 fitOpt.fCoordErrors = (type == BinData::kCoordError);
00791 fitOpt.fAsymErrors = (type == BinData::kAsymError);
00792
00793
00794
00795 if (dv.Size() > 0 && dv.NDim() == 1 ) {
00796
00797 if (dv.PointSize() == 2 && type != BinData::kNoError ) {
00798 Error("FillData","Inconsistent TGraph with previous data set- skip all graph data");
00799 return;
00800 }
00801 if (dv.PointSize() == 3 && type != BinData::kValueError ) {
00802 Error("FillData","Inconsistent TGraph with previous data set- skip all graph data");
00803 return;
00804 }
00805 if (dv.PointSize() == 4 && type != BinData::kCoordError ) {
00806 Error("FillData","Inconsistent TGraph with previous data set- skip all graph data");
00807 return;
00808 }
00809 }
00810
00811 DoFillData(dv, gr, type, func);
00812
00813 }
00814
00815 void FillData ( BinData & dv, const TMultiGraph * mg, TF1 * func ) {
00816
00817
00818 assert(mg != 0);
00819
00820 TList * grList = mg->GetListOfGraphs();
00821 assert(grList != 0);
00822
00823 #ifdef DEBUG
00824
00825 TIter itr(grList, kIterBackward);
00826 TObject *obj;
00827 std::cout << "multi-graph list of graps: " << std::endl;
00828 while ((obj = itr())) {
00829 std::cout << obj->IsA()->GetName() << std::endl;
00830 }
00831
00832 #endif
00833
00834
00835 DataOptions & fitOpt = dv.Opt();
00836
00837
00838 TIter next(grList);
00839
00840 BinData::ErrorType type = BinData::kNoError;
00841 TGraph *gr = 0;
00842 while ((gr = (TGraph*) next())) {
00843 BinData::ErrorType t = GetDataType(gr,fitOpt);
00844 if (t > type ) type = t;
00845 }
00846
00847 fitOpt.fErrors1 = (type == BinData::kNoError);
00848 fitOpt.fCoordErrors = (type == BinData::kCoordError);
00849 fitOpt.fAsymErrors = (type == BinData::kAsymError);
00850
00851
00852 #ifdef DEBUG
00853 std::cout << "Fitting MultiGraph of type " << type << std::endl;
00854 #endif
00855
00856
00857 next = grList;
00858 while ((gr = (TGraph*) next())) {
00859 DoFillData( dv, gr, type, func);
00860 }
00861
00862 #ifdef DEBUG
00863 std::cout << "TGraphFitInterface::FillData MultiGraph FitData size is " << dv.Size() << std::endl;
00864 #endif
00865
00866 }
00867
00868 void FillData ( BinData & dv, const TGraph2D * gr, TF1 * func ) {
00869
00870
00871
00872 assert(gr != 0);
00873
00874
00875 DataOptions & fitOpt = dv.Opt();
00876 BinData::ErrorType type = GetDataType(gr,fitOpt);
00877
00878 fitOpt.fErrors1 = (type == BinData::kNoError);
00879 fitOpt.fCoordErrors = (type == BinData::kCoordError);
00880 fitOpt.fAsymErrors = false;
00881
00882 int nPoints = gr->GetN();
00883 double *gx = gr->GetX();
00884 double *gy = gr->GetY();
00885 double *gz = gr->GetZ();
00886
00887
00888 if ( gr->GetEZ() == 0) fitOpt.fErrors1 = true;
00889
00890 double x[2];
00891 double ex[2];
00892
00893
00894 const DataRange & range = dv.Range();
00895 bool useRangeX = ( range.Size(0) > 0);
00896 bool useRangeY = ( range.Size(1) > 0);
00897 double xmin = 0;
00898 double xmax = 0;
00899 double ymin = 0;
00900 double ymax = 0;
00901 range.GetRange(xmin,xmax,ymin,ymax);
00902
00903 dv.Initialize(nPoints,2, type);
00904
00905 for ( int i = 0; i < nPoints; ++i) {
00906
00907 x[0] = gx[i];
00908 x[1] = gy[i];
00909
00910
00911 if (useRangeX && ( x[0] < xmin || x[0] > xmax) ) continue;
00912 if (useRangeY && ( x[1] < ymin || x[1] > ymax) ) continue;
00913
00914
00915
00916 if (func) {
00917 func->RejectPoint(false);
00918 (*func)( x );
00919 if (func->RejectedPoint() ) continue;
00920 }
00921
00922
00923 if (type == BinData::kNoError) {
00924 dv.Add( x, gz[i] );
00925 continue;
00926 }
00927
00928 double errorZ = gr->GetErrorZ(i);
00929 if (!HFitInterface::AdjustError(fitOpt,errorZ) ) continue;
00930
00931 if (type == BinData::kValueError) {
00932 dv.Add( x, gz[i], errorZ );
00933 }
00934 else if (type == BinData::kCoordError) {
00935 ex[0] = std::max(gr->GetErrorX(i), 0.);
00936 ex[1] = std::max(gr->GetErrorY(i), 0.);
00937 dv.Add( x, gz[i], ex, errorZ );
00938 }
00939 else
00940 assert(0);
00941
00942 #ifdef DEBUG
00943 std::cout << "Point " << i << " " << gx[i] << " " << gy[i] << " " << errorZ << std::endl;
00944 #endif
00945
00946 }
00947
00948 #ifdef DEBUG
00949 std::cout << "THFitInterface::FillData Graph2D FitData size is " << dv.Size() << std::endl;
00950 #endif
00951
00952 }
00953
00954
00955
00956 bool GetConfidenceIntervals(const TH1 * h1, const ROOT::Fit::FitResult & result, TGraphErrors * gr, double cl ) {
00957 if (h1->GetDimension() != 1) {
00958 Error("GetConfidenceIntervals","Invalid object used for storing confidence intervals");
00959 return false;
00960 }
00961
00962 BinData d;
00963 FillData(d,h1,0);
00964 gr->Set(d.NPoints() );
00965 double * ci = gr->GetEY();
00966 result.GetConfidenceIntervals(d,ci,cl);
00967
00968 for (unsigned int ipoint = 0; ipoint < d.NPoints(); ++ipoint) {
00969 const double * x = d.Coords(ipoint);
00970 const ROOT::Math::IParamMultiFunction * func = result.FittedFunction();
00971 gr->SetPoint(ipoint, x[0], (*func)(x) );
00972 }
00973 return true;
00974 }
00975
00976
00977 }
00978
00979 }
00980