ROOT logo
//////////////////////////////////////////////////////////////////////////
//
// 'NUMERIC ALGORITHM TUNING' RooFit tutorial macro #903 
// 
//  Caching of slow numeric integrals and parameterizations of slow
//  numeric integrals
//
// 07/2008 - Wouter Verkerke 
// 
/////////////////////////////////////////////////////////////////////////

#ifndef __CINT__
#include "RooGlobalFunc.h"
#endif
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooDataHist.h"
#include "RooGaussian.h"
#include "RooConstVar.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "RooPlot.h"
#include "RooWorkspace.h"
#include "RooExpensiveObjectCache.h"
#include "TFile.h"
#include "TH1.h"

using namespace RooFit ;

RooWorkspace* getWorkspace(Int_t mode) ;

void rf903_numintcache(Int_t mode=0)
{
  // Mode = 0 : Run plain fit (slow)
  // Mode = 1 : Generate workspace with precalculated integral and store it on file (prepare for accelerated running)
  // Mode = 2 : Run fit from previously stored workspace including cached integrals (fast, requires run in mode=1 first)

  // C r e a t e ,   s a v e   o r   l o a d   w o r k s p a c e   w i t h   p . d . f . 
  // -----------------------------------------------------------------------------------

  // Make/load workspace, exit here in mode 1
  RooWorkspace* w = getWorkspace(mode) ;
  if (mode==1) {

    // Show workspace that was created
    w->Print() ;

    // Show plot of cached integral values
    RooDataHist* hhcache = (RooDataHist*) w->expensiveObjectCache().getObj(1) ;

    new TCanvas("rf903_numintcache","rf903_numintcache",600,600) ;
    hhcache->createHistogram("a")->Draw() ;
    
    return ;
  }


  // U s e   p . d . f .   f r o m   w o r k s p a c e   f o r   g e n e r a t i o n   a n d   f i t t i n g 
  // -----------------------------------------------------------------------------------

  // This is always slow (need to find maximum function value empirically in 3D space)
  RooDataSet* d = w->pdf("model")->generate(RooArgSet(*w->var("x"),*w->var("y"),*w->var("z")),1000) ;

  // This is slow in mode 0, but fast in mode 1
  w->pdf("model")->fitTo(*d,Verbose(kTRUE),Timer(kTRUE)) ; 

  // Projection on x (always slow as 2D integral over Y,Z at fitted value of a is not cached)
  RooPlot* framex = w->var("x")->frame(Title("Projection of 3D model on X")) ;
  d->plotOn(framex) ;
  w->pdf("model")->plotOn(framex) ;

  // Draw x projection on canvas
  new TCanvas("rf903_numintcache","rf903_numintcache",600,600) ;
  framex->Draw() ;

  // Make workspace available on command line after macro finishes
  gDirectory->Add(w) ;

  return ;

 
}



RooWorkspace* getWorkspace(Int_t mode) 
{
  // C r e a t e ,   s a v e   o r   l o a d   w o r k s p a c e   w i t h   p . d . f . 
  // -----------------------------------------------------------------------------------
  //
  // Mode = 0 : Create workspace for plain running (no integral caching)
  // Mode = 1 : Generate workspace with precalculated integral and store it on file
  // Mode = 2 : Load previously stored workspace from file

  RooWorkspace* w(0) ;

  if (mode!=2) {

    // Create empty workspace workspace 
    w = new RooWorkspace("w",1) ;

    // Make a difficult to normalize  p.d.f. in 3 dimensions that is integrated numerically.
    w->factory("EXPR::model('1/((x-a)*(x-a)+0.01)+1/((y-a)*(y-a)+0.01)+1/((z-a)*(z-a)+0.01)',x[-1,1],y[-1,1],z[-1,1],a[-5,5])") ;
  }

  if (mode==1) {
    
    // Instruct model to precalculate normalization integral that integrate at least
    // two dimensions numerically. In this specific case the integral value for
    // all values of parameter 'a' are stored in a histogram and available for use 
    // in subsequent fitting and plotting operations (interpolation is applied)
    w->pdf("model")->setNormValueCaching(3) ;
    
    // Evaluate p.d.f. once to trigger filling of cache
    RooArgSet normSet(*w->var("x"),*w->var("y"),*w->var("z")) ;
    w->pdf("model")->getVal(&normSet) ;
    w->writeToFile("rf903_numintcache.root") ;

  } 

  if (mode==2) {    
    // Load preexisting workspace from file in mode==2
    TFile* f = new TFile("rf903_numintcache.root") ;
    w = (RooWorkspace*) f->Get("w") ;
  }

  // Return created or loaded workspace
  return w ;
}
 rf903_numintcache.C:1
 rf903_numintcache.C:2
 rf903_numintcache.C:3
 rf903_numintcache.C:4
 rf903_numintcache.C:5
 rf903_numintcache.C:6
 rf903_numintcache.C:7
 rf903_numintcache.C:8
 rf903_numintcache.C:9
 rf903_numintcache.C:10
 rf903_numintcache.C:11
 rf903_numintcache.C:12
 rf903_numintcache.C:13
 rf903_numintcache.C:14
 rf903_numintcache.C:15
 rf903_numintcache.C:16
 rf903_numintcache.C:17
 rf903_numintcache.C:18
 rf903_numintcache.C:19
 rf903_numintcache.C:20
 rf903_numintcache.C:21
 rf903_numintcache.C:22
 rf903_numintcache.C:23
 rf903_numintcache.C:24
 rf903_numintcache.C:25
 rf903_numintcache.C:26
 rf903_numintcache.C:27
 rf903_numintcache.C:28
 rf903_numintcache.C:29
 rf903_numintcache.C:30
 rf903_numintcache.C:31
 rf903_numintcache.C:32
 rf903_numintcache.C:33
 rf903_numintcache.C:34
 rf903_numintcache.C:35
 rf903_numintcache.C:36
 rf903_numintcache.C:37
 rf903_numintcache.C:38
 rf903_numintcache.C:39
 rf903_numintcache.C:40
 rf903_numintcache.C:41
 rf903_numintcache.C:42
 rf903_numintcache.C:43
 rf903_numintcache.C:44
 rf903_numintcache.C:45
 rf903_numintcache.C:46
 rf903_numintcache.C:47
 rf903_numintcache.C:48
 rf903_numintcache.C:49
 rf903_numintcache.C:50
 rf903_numintcache.C:51
 rf903_numintcache.C:52
 rf903_numintcache.C:53
 rf903_numintcache.C:54
 rf903_numintcache.C:55
 rf903_numintcache.C:56
 rf903_numintcache.C:57
 rf903_numintcache.C:58
 rf903_numintcache.C:59
 rf903_numintcache.C:60
 rf903_numintcache.C:61
 rf903_numintcache.C:62
 rf903_numintcache.C:63
 rf903_numintcache.C:64
 rf903_numintcache.C:65
 rf903_numintcache.C:66
 rf903_numintcache.C:67
 rf903_numintcache.C:68
 rf903_numintcache.C:69
 rf903_numintcache.C:70
 rf903_numintcache.C:71
 rf903_numintcache.C:72
 rf903_numintcache.C:73
 rf903_numintcache.C:74
 rf903_numintcache.C:75
 rf903_numintcache.C:76
 rf903_numintcache.C:77
 rf903_numintcache.C:78
 rf903_numintcache.C:79
 rf903_numintcache.C:80
 rf903_numintcache.C:81
 rf903_numintcache.C:82
 rf903_numintcache.C:83
 rf903_numintcache.C:84
 rf903_numintcache.C:85
 rf903_numintcache.C:86
 rf903_numintcache.C:87
 rf903_numintcache.C:88
 rf903_numintcache.C:89
 rf903_numintcache.C:90
 rf903_numintcache.C:91
 rf903_numintcache.C:92
 rf903_numintcache.C:93
 rf903_numintcache.C:94
 rf903_numintcache.C:95
 rf903_numintcache.C:96
 rf903_numintcache.C:97
 rf903_numintcache.C:98
 rf903_numintcache.C:99
 rf903_numintcache.C:100
 rf903_numintcache.C:101
 rf903_numintcache.C:102
 rf903_numintcache.C:103
 rf903_numintcache.C:104
 rf903_numintcache.C:105
 rf903_numintcache.C:106
 rf903_numintcache.C:107
 rf903_numintcache.C:108
 rf903_numintcache.C:109
 rf903_numintcache.C:110
 rf903_numintcache.C:111
 rf903_numintcache.C:112
 rf903_numintcache.C:113
 rf903_numintcache.C:114
 rf903_numintcache.C:115
 rf903_numintcache.C:116
 rf903_numintcache.C:117
 rf903_numintcache.C:118
 rf903_numintcache.C:119
 rf903_numintcache.C:120
 rf903_numintcache.C:121
 rf903_numintcache.C:122
 rf903_numintcache.C:123
 rf903_numintcache.C:124
 rf903_numintcache.C:125
 rf903_numintcache.C:126
 rf903_numintcache.C:127
 rf903_numintcache.C:128
 rf903_numintcache.C:129
 rf903_numintcache.C:130