00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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 #include "Riostream.h"
00081
00082 #include "RooIntegralMorph.h"
00083 #include "RooAbsReal.h"
00084 #include "RooAbsCategory.h"
00085 #include "RooBrentRootFinder.h"
00086 #include "RooAbsFunc.h"
00087 #include "RooRealVar.h"
00088 #include "RooDataHist.h"
00089 #include "TH1.h"
00090
00091 ClassImp(RooIntegralMorph)
00092
00093
00094
00095 RooIntegralMorph::RooIntegralMorph(const char *name, const char *title,
00096 RooAbsReal& _pdf1,
00097 RooAbsReal& _pdf2,
00098 RooAbsReal& _x,
00099 RooAbsReal& _alpha,
00100 Bool_t doCacheAlpha) :
00101 RooAbsCachedPdf(name,title,2),
00102 pdf1("pdf1","pdf1",this,_pdf1),
00103 pdf2("pdf2","pdf2",this,_pdf2),
00104 x("x","x",this,_x),
00105 alpha("alpha","alpha",this,_alpha),
00106 _cacheAlpha(doCacheAlpha),
00107 _cache(0)
00108 {
00109
00110
00111
00112
00113 }
00114
00115
00116
00117
00118 RooIntegralMorph::RooIntegralMorph(const RooIntegralMorph& other, const char* name) :
00119 RooAbsCachedPdf(other,name),
00120 pdf1("pdf1",this,other.pdf1),
00121 pdf2("pdf2",this,other.pdf2),
00122 x("x",this,other.x),
00123 alpha("alpha",this,other.alpha),
00124 _cacheAlpha(other._cacheAlpha),
00125 _cache(0)
00126 {
00127
00128 }
00129
00130
00131
00132
00133 RooArgSet* RooIntegralMorph::actualObservables(const RooArgSet& ) const
00134 {
00135
00136
00137
00138
00139 RooArgSet* obs = new RooArgSet ;
00140 if (_cacheAlpha) {
00141 obs->add(alpha.arg()) ;
00142 }
00143 obs->add(x.arg()) ;
00144 return obs ;
00145 }
00146
00147
00148
00149
00150 RooArgSet* RooIntegralMorph::actualParameters(const RooArgSet& ) const
00151 {
00152
00153
00154
00155 RooArgSet* par1 = pdf1.arg().getParameters(RooArgSet()) ;
00156 RooArgSet* par2 = pdf2.arg().getParameters(RooArgSet()) ;
00157 par1->add(*par2,kTRUE) ;
00158 par1->remove(x.arg(),kTRUE,kTRUE) ;
00159 if (!_cacheAlpha) {
00160 par1->add(alpha.arg()) ;
00161 }
00162 delete par2 ;
00163 return par1 ;
00164 }
00165
00166
00167
00168
00169 const char* RooIntegralMorph::inputBaseName() const
00170 {
00171
00172
00173
00174 static TString name ;
00175
00176 name = pdf1.arg().GetName() ;
00177 name.Append("_MORPH_") ;
00178 name.Append(pdf2.arg().GetName()) ;
00179 return name.Data() ;
00180 }
00181
00182
00183
00184
00185 void RooIntegralMorph::fillCacheObject(PdfCacheElem& cache) const
00186 {
00187
00188
00189 MorphCacheElem& mcache = static_cast<MorphCacheElem&>(cache) ;
00190
00191
00192
00193 if (!_cacheAlpha) {
00194
00195 TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet()) ;
00196 mcache.calculate(dIter) ;
00197 delete dIter ;
00198
00199 } else {
00200 TIterator* slIter = cache.hist()->sliceIterator((RooAbsArg&)alpha.arg(),RooArgSet()) ;
00201
00202 Double_t alphaSave = alpha ;
00203 RooArgSet alphaSet(alpha.arg()) ;
00204 coutP(Eval) << "RooIntegralMorph::fillCacheObject(" << GetName() << ") filling multi-dimensional cache" ;
00205 while(slIter->Next()) {
00206 alphaSet = (*cache.hist()->get()) ;
00207 TIterator* dIter = cache.hist()->sliceIterator((RooAbsArg&)x.arg(),RooArgSet(alpha.arg())) ;
00208 mcache.calculate(dIter) ;
00209 ccoutP(Eval) << "." << flush;
00210 delete dIter ;
00211 }
00212 ccoutP(Eval) << endl ;
00213
00214 delete slIter ;
00215 const_cast<RooIntegralMorph*>(this)->alpha = alphaSave ;
00216 }
00217 }
00218
00219
00220
00221
00222 RooAbsCachedPdf::PdfCacheElem* RooIntegralMorph::createCache(const RooArgSet* nset) const
00223 {
00224
00225
00226 return new MorphCacheElem(const_cast<RooIntegralMorph&>(*this),nset) ;
00227 }
00228
00229
00230
00231
00232 RooArgList RooIntegralMorph::MorphCacheElem::containedArgs(Action action)
00233 {
00234
00235
00236 RooArgList ret ;
00237 ret.add(PdfCacheElem::containedArgs(action)) ;
00238 ret.add(*_self) ;
00239 ret.add(*_pdf1) ;
00240 ret.add(*_pdf2) ;
00241 ret.add(*_x ) ;
00242 ret.add(*_alpha) ;
00243 ret.add(*_c1) ;
00244 ret.add(*_c2) ;
00245
00246 return ret ;
00247 }
00248
00249
00250
00251
00252 RooIntegralMorph::MorphCacheElem::MorphCacheElem(RooIntegralMorph& self, const RooArgSet* nsetIn) : PdfCacheElem(self,nsetIn)
00253 {
00254
00255
00256
00257
00258
00259 _x = (RooRealVar*)self.x.absArg() ;
00260 _nset = new RooArgSet(*_x) ;
00261
00262 _alpha = (RooAbsReal*)self.alpha.absArg() ;
00263 _pdf1 = (RooAbsPdf*)(self.pdf1.absArg()) ;
00264 _pdf2 = (RooAbsPdf*)(self.pdf2.absArg()) ;
00265 _c1 = _pdf1->createCdf(*_x);
00266 _c2 = _pdf2->createCdf(*_x) ;
00267 _cb1 = _c1->bindVars(*_x,_nset) ;
00268 _cb2 = _c2->bindVars(*_x,_nset) ;
00269 _self = &self ;
00270
00271 _rf1 = new RooBrentRootFinder(*_cb1) ;
00272 _rf2 = new RooBrentRootFinder(*_cb2) ;
00273 _ccounter = 0 ;
00274
00275 _rf1->setTol(1e-12) ;
00276 _rf2->setTol(1e-12) ;
00277 _ycutoff = 1e-7 ;
00278
00279 _yatX = 0 ;
00280 _calcX = 0 ;
00281
00282
00283 pdf()->setUnitNorm(kTRUE) ;
00284
00285 _yatXmax = 0 ;
00286 _yatXmin = 0 ;
00287 }
00288
00289
00290
00291 RooIntegralMorph::MorphCacheElem::~MorphCacheElem()
00292 {
00293
00294
00295 delete _rf1 ;
00296 delete _rf2 ;
00297 delete[] _yatX ;
00298 delete[] _calcX ;
00299 }
00300
00301
00302
00303
00304 Double_t RooIntegralMorph::MorphCacheElem::calcX(Double_t y, Bool_t& ok)
00305 {
00306
00307
00308
00309 if (y<0 || y>1) {
00310 oocoutW(_self,Eval) << "RooIntegralMorph::MorphCacheElem::calcX() WARNING: requested root finding for unphysical CDF value " << y << endl ;
00311 }
00312 Double_t x1,x2 ;
00313
00314 Double_t xmax = _x->getMax("cache") ;
00315 Double_t xmin = _x->getMin("cache") ;
00316
00317 ok=kTRUE ;
00318 ok &= _rf1->findRoot(x1,xmin,xmax,y) ;
00319 ok &= _rf2->findRoot(x2,xmin,xmax,y) ;
00320 if (!ok) return 0 ;
00321 _ccounter++ ;
00322
00323 return _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
00324 }
00325
00326
00327
00328 Int_t RooIntegralMorph::MorphCacheElem::binX(Double_t X)
00329 {
00330
00331
00332 Double_t xmax = _x->getMax("cache") ;
00333 Double_t xmin = _x->getMin("cache") ;
00334 return (Int_t)(_x->numBins("cache")*(X-xmin)/(xmax-xmin)) ;
00335 }
00336
00337
00338
00339
00340 void RooIntegralMorph::MorphCacheElem::calculate(TIterator* dIter)
00341 {
00342
00343
00344
00345 Double_t xsave = _self->x ;
00346
00347 if (!_yatX) {
00348 _yatX = new Double_t[_x->numBins("cache")+1] ;
00349 _calcX = new Double_t[_x->numBins("cache")+1] ;
00350 }
00351
00352 RooArgSet nsetTmp(*_x) ;
00353 _ccounter = 0 ;
00354
00355
00356 Int_t nbins = _x->numBins("cache") ;
00357
00358
00359 for (int i=0 ; i<nbins ; i++) {
00360 _yatX[i] = -1 ;
00361 _calcX[i] = 0 ;
00362 }
00363
00364
00365 findRange() ;
00366
00367
00368 for (int i=0 ; i<10 ; i++) {
00369
00370
00371 Double_t offset = _yatX[_yatXmin] ;
00372 Double_t delta = (_yatX[_yatXmax] - _yatX[_yatXmin])/10 ;
00373 Double_t y = offset + i*delta ;
00374
00375
00376 Bool_t ok ;
00377 Double_t X = calcX(y,ok) ;
00378 if (ok) {
00379 Int_t iX = binX(X) ;
00380 _yatX[iX] = y ;
00381 _calcX[iX] = X ;
00382 }
00383 }
00384
00385
00386 Int_t igapLow = _yatXmin+1 ;
00387 while(true) {
00388
00389 Int_t igapHigh = igapLow+1 ;
00390 while(_yatX[igapHigh]<0 && igapHigh<(_yatXmax)) igapHigh++ ;
00391
00392
00393 fillGap(igapLow-1,igapHigh) ;
00394
00395
00396 if (igapHigh>=_yatXmax-1) break ;
00397 igapLow = igapHigh+1 ;
00398 }
00399
00400
00401 Double_t xmax = _x->getMax("cache") ;
00402 Double_t xmin = _x->getMin("cache") ;
00403 Double_t binw = (xmax-xmin)/_x->numBins("cache") ;
00404 for (int i=_yatXmin+1 ; i<_yatXmax-1 ; i++) {
00405
00406
00407 Double_t xBinC = xmin + (i+0.5)*binw ;
00408 Double_t xOffset = xBinC-_calcX[i] ;
00409 if (fabs(xOffset/binw)>1e-3) {
00410 Double_t slope = (_yatX[i+1]-_yatX[i-1])/(_calcX[i+1]-_calcX[i-1]) ;
00411 Double_t newY = _yatX[i] + slope*xOffset ;
00412
00413 _yatX[i] = newY ;
00414 }
00415 }
00416
00417
00418 for (int i=0; i<_yatXmin ; i++) {
00419 dIter->Next() ;
00420
00421 hist()->set(0) ;
00422 }
00423
00424 for (int i=_yatXmin ; i<_yatXmax ; i++) {
00425
00426 Double_t y = _yatX[i] ;
00427
00428 Double_t x1,x2 ;
00429
00430 Double_t xMin = _x->getMin("cache") ;
00431 Double_t xMax = _x->getMax("cache") ;
00432 _rf1->findRoot(x1,xMin,xMax,y) ;
00433 _rf2->findRoot(x2,xMin,xMax,y) ;
00434
00435 _x->setVal(x1) ; Double_t f1x1 = _pdf1->getVal(&nsetTmp) ;
00436 _x->setVal(x2) ; Double_t f2x2 = _pdf2->getVal(&nsetTmp) ;
00437 Double_t fbarX = f1x1*f2x2 / ( _alpha->getVal()*f2x2 + (1-_alpha->getVal())*f1x1 ) ;
00438
00439 dIter->Next() ;
00440
00441 hist()->set(fbarX) ;
00442 }
00443
00444 for (int i=_yatXmax+1 ; i<nbins ; i++) {
00445 dIter->Next() ;
00446
00447 hist()->set(0) ;
00448 }
00449
00450 pdf()->setUnitNorm(kTRUE) ;
00451 _self->x = xsave ;
00452
00453 oocxcoutD(_self,Eval) << "RooIntegralMorph::MorphCacheElem::calculate(" << _self->GetName() << ") calculation required " << _ccounter << " samplings of cdfs" << endl ;
00454 }
00455
00456
00457
00458 void RooIntegralMorph::MorphCacheElem::fillGap(Int_t ixlo, Int_t ixhi, Double_t splitPoint)
00459 {
00460
00461
00462
00463
00464
00465
00466
00467
00468 if (_yatX[ixlo]<0) {
00469 oocoutE(_self,Eval) << "RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() << "): ERROR in fillgap " << ixlo << " = " << ixhi
00470 << " splitPoint= " << splitPoint << " _yatX[ixlo] = " << _yatX[ixlo] << endl ;
00471 }
00472 if (_yatX[ixhi]<0) {
00473 oocoutE(_self,Eval) << "RooIntegralMorph::MorphCacheElme::fillGap(" << _self->GetName() << "): ERROR in fillgap " << ixlo << " = " << ixhi
00474 << " splitPoint " << splitPoint << " _yatX[ixhi] = " << _yatX[ixhi] << endl ;
00475 }
00476
00477
00478 Double_t ymid = _yatX[ixlo]*splitPoint + _yatX[ixhi]*(1-splitPoint) ;
00479 Bool_t ok ;
00480 Double_t Xmid = calcX(ymid,ok) ;
00481 if (!ok) {
00482 oocoutW(_self,Eval) << "RooIntegralMorph::MorphCacheElem::fillGap(" << _self->GetName() << ") unable to calculate midpoint in gap ["
00483 << ixlo << "," << ixhi << "], resorting to interpolation" << endl ;
00484 interpolateGap(ixlo,ixhi) ;
00485 }
00486
00487 Int_t iX = binX(Xmid) ;
00488 Double_t cq = (Xmid-_calcX[ixlo])/(_calcX[ixhi]-_calcX[ixlo])-0.5 ;
00489
00490
00491 _yatX[iX] = ymid ;
00492 _calcX[iX] = Xmid ;
00493
00494
00495
00496 if (fabs(cq)<0.01 || fabs(cq*(ixhi-ixlo))<0.1 || ymid<_ycutoff ) {
00497
00498
00499 if (iX-ixlo>1) {
00500 interpolateGap(ixlo,iX) ;
00501 }
00502 if (ixhi-iX>1) {
00503 interpolateGap(iX,ixhi) ;
00504 }
00505
00506 } else {
00507
00508 if (iX==ixlo) {
00509
00510 if (splitPoint<0.95) {
00511
00512 Double_t newSplit = splitPoint + 0.5*(1-splitPoint) ;
00513 fillGap(ixlo,ixhi,newSplit) ;
00514 } else {
00515
00516 interpolateGap(ixlo,ixhi) ;
00517 }
00518
00519 } else if (iX==ixhi) {
00520
00521
00522 if (splitPoint>0.05) {
00523 Double_t newSplit = splitPoint/2 ;
00524 fillGap(ixlo,ixhi,newSplit) ;
00525 } else {
00526
00527 interpolateGap(ixlo,ixhi) ;
00528 }
00529
00530 } else {
00531
00532
00533 if (iX-ixlo>1) {
00534 fillGap(ixlo,iX) ;
00535 }
00536 if (ixhi-iX>1) {
00537 fillGap(iX,ixhi) ;
00538 }
00539 }
00540 }
00541 }
00542
00543
00544
00545 void RooIntegralMorph::MorphCacheElem::interpolateGap(Int_t ixlo, Int_t ixhi)
00546 {
00547
00548
00549
00550
00551
00552 Double_t xmax = _x->getMax("cache") ;
00553 Double_t xmin = _x->getMin("cache") ;
00554 Double_t binw = (xmax-xmin)/_x->numBins("cache") ;
00555
00556
00557 Double_t deltaY = (_yatX[ixhi]-_yatX[ixlo])/((_calcX[ixhi]-_calcX[ixlo])/binw) ;
00558
00559
00560 Double_t xBinC = xmin + (ixlo+0.5)*binw ;
00561 Double_t xOffset = xBinC-_calcX[ixlo] ;
00562
00563 for (int j=ixlo+1 ; j<ixhi ; j++) {
00564 _yatX[j] = _yatX[ixlo]+(xOffset+(j-ixlo))*deltaY ;
00565 _calcX[j] = xmin + (j+0.5)*binw ;
00566 }
00567
00568 }
00569
00570
00571
00572
00573 void RooIntegralMorph::MorphCacheElem::findRange()
00574 {
00575
00576
00577
00578
00579
00580
00581 Double_t xmin = _x->getMin("cache") ;
00582 Double_t xmax = _x->getMax("cache") ;
00583 Int_t nbins = _x->numBins("cache") ;
00584
00585 Double_t x1,x2 ;
00586 Bool_t ok = kTRUE ;
00587 Double_t ymin=0.1,yminSave(-1) ;
00588 Double_t Xsave(-1),Xlast=xmax ;
00589
00590
00591
00592 while(true) {
00593 ok &= _rf1->findRoot(x1,xmin,xmax,ymin) ;
00594 ok &= _rf2->findRoot(x2,xmin,xmax,ymin) ;
00595 oocxcoutD(_self,Eval) << "RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() << ") findMin: x1 = " << x1 << " x2 = " << x2 << " ok = " << (ok?"T":"F") << endl ;
00596
00597
00598 if (!ok) break ;
00599
00600
00601 Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
00602 if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
00603 break ;
00604 }
00605 Xlast=X ;
00606
00607
00608 _yatXmin = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
00609 _yatX[_yatXmin] = ymin ;
00610 _calcX[_yatXmin] = X ;
00611 yminSave = ymin ;
00612 Xsave=X ;
00613
00614
00615 ymin /=sqrt(10.) ;
00616
00617
00618 if (ymin<_ycutoff) break ;
00619 }
00620 _yatX[_yatXmin] = yminSave ;
00621 _calcX[_yatXmin] = Xsave ;
00622
00623
00624
00625 ok = kTRUE ;
00626 Double_t deltaymax=0.1, deltaymaxSave(-1) ;
00627 Xlast=xmin ;
00628 while(true) {
00629 ok &= _rf1->findRoot(x1,xmin,xmax,1-deltaymax) ;
00630 ok &= _rf2->findRoot(x2,xmin,xmax,1-deltaymax) ;
00631
00632 oocxcoutD(_self,Eval) << "RooIntegralMorph::MorphCacheElem::findRange(" << _self->GetName() << ") findMax: x1 = " << x1 << " x2 = " << x2 << " ok = " << (ok?"T":"F") << endl ;
00633
00634
00635 if (!ok) break ;
00636
00637
00638 Double_t X = _alpha->getVal()*x1 + (1-_alpha->getVal())*x2 ;
00639 if (fabs(X-Xlast)/(xmax-xmin)<0.0001) {
00640 break ;
00641 }
00642 Xlast=X ;
00643
00644
00645 _yatXmax = (Int_t)(nbins*(X-xmin)/(xmax-xmin)) ;
00646 _yatX[_yatXmax] = 1-deltaymax ;
00647 _calcX[_yatXmax] = X ;
00648 deltaymaxSave = deltaymax ;
00649 Xsave=X ;
00650
00651
00652 deltaymax /=sqrt(10.) ;
00653
00654
00655 if (deltaymax<_ycutoff) break ;
00656 }
00657
00658 _yatX[_yatXmax] = 1-deltaymaxSave ;
00659 _calcX[_yatXmax] = Xsave ;
00660
00661
00662
00663 for (int i=0 ; i<_yatXmin ; i++) _yatX[i] = -2 ;
00664 for (int i=_yatXmax+1 ; i<nbins; i++) _yatX[i] = -2 ;
00665 oocxcoutD(_self,Eval) << "RooIntegralMorph::findRange(" << _self->GetName() << "): ymin = " << _yatX[_yatXmin] << " ymax = " << _yatX[_yatXmax] << endl;
00666 oocxcoutD(_self,Eval) << "RooIntegralMorph::findRange(" << _self->GetName() << "): xmin = " << _calcX[_yatXmin] << " xmax = " << _calcX[_yatXmax] << endl;
00667 }
00668
00669
00670
00671
00672 Double_t RooIntegralMorph::evaluate() const
00673 {
00674
00675 return 0 ;
00676 }
00677
00678
00679
00680
00681 void RooIntegralMorph::preferredObservableScanOrder(const RooArgSet& obs, RooArgSet& orderedObs) const
00682 {
00683
00684
00685
00686
00687
00688 orderedObs.removeAll() ;
00689
00690 orderedObs.add(obs) ;
00691 RooAbsArg* obsX = obs.find(x.arg().GetName()) ;
00692 if (obsX) {
00693 orderedObs.remove(*obsX) ;
00694 orderedObs.add(*obsX) ;
00695 }
00696 }
00697
00698
00699