Modifying roofit RooDecay pdf by adding time offset?

OK - I use the RooDecay::SingleSided PDF to describe pi+ decay time data. A nice feature is
a possibility of analytic convolution with different resolution functions on-a-fly, avoiding
numerical FFT.

Now, I would like to modify the RooDecay PDF by introducing an additional parameter -
offset of the zero time, replacing “exp(-t/tau)” with “exp(-(t-toff_mich)/tau)” (objective is to
study the effect of the incorrect t=0 point on the fitted parameters). So my macro reads:


RooRealVar toff_mich(“toff_mich”,“toff_mich”,0,-10,10) ; // time offset: -3+3 ns
toff_mich.setConstant(kTRUE) ;

RooRealVar s_pt(“s_pt”,“per-event error scale factor”,1,0.1,10) ; // sigma (SD)
RooGaussModel g_pt(“g_pt”,“gauss model scaled by per-event error”,t,bias_pt,s_pt,dt) ;
#ifdef CINT
gROOT->ProcessLineSync(".x ts_p2e.cxx+") ;
#endif
// load the t_p2e Pdf class
gROOT->ProcessLineSync(".L ts_p2e.cxx+") ; // compile and load
ts_p2e t_p2e(“t_p2e”,“pi+ decay”,t,tau_pi,toff_mich,g_pt,ts_p2e::SingleSided) ;

and I have to modify the default RooDecay. I copy RooDecay.cxx and Roodecay.h into
ts_p2e.cxx and ts_p2e.h, replace in *.cxx and *h files all instances of “RooDecay” with “ts_p2e” and
add obvious declarations of “toff_mich” variable in *.cxx and *.f files.

It is obvious how to modify “void ts_p2e::generateEvent(Int_t code)” and I can generate
time-offseted Gaussian-smeared exponential decay data OK. But my knowledge of C++ is
limited, and though I tried to work by analogies with other RooB*Decay roofit codes, I could
not properly modify PDF.

Below is my (non-working) modification of RooDecay (also in attachment):

/*****************************************************************************

  • Project: RooFit *
  • Package: RooFitModels *
  • @(#)root/roofit:Id: ts_p2e.cxx 24286 2008-06-16 15:47:04Z wouter
  • Authors: *
  • WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
  • DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
  •                                                                       *
    
  • Copyright © 2000-2005, Regents of the University of California *
  •                      and Stanford University. All rights reserved.    *
    
  •                                                                       *
    
  • Redistribution and use in source and binary forms, *
  • with or without modification, are permitted according to the terms *
  • listed in LICENSE (roofit.sourceforge.net/license.txt) *
    *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Single or double sided decay function that can be analytically convolved
// with any RooResolutionModel implementation
// END_HTML
//

#include “RooFit.h”

#include “Riostream.h”
#include “Riostream.h”
#include “ts_p2e.h”
#include “RooRealVar.h”
#include “RooRandom.h”

ClassImp(ts_p2e)
;

//_____________________________________________________________________________
ts_p2e::ts_p2e(const char *name, const char *title,
RooRealVar& t, RooAbsReal& tau, RooRealVar& toff_mich,
const RooResolutionModel& model, DecayType type) :
RooAbsAnaConvPdf(name,title,model,t),
_t(“t”,“time”,this,t),
_tau(“tau”,“decay time”,this,tau),
_toff_mich(“toff_mich”,“decay time offset”,this,toff_mich),
_type(type)
{
// Constructor
switch(type) {
case SingleSided:
// _t=_t - _toff_mich ;
_basisExp = declareBasis(“exp(-@0/@1)”,tau) ;
break ;
case Flipped:
_basisExp = declareBasis(“exp((@0/@1)”,tau) ;
break ;
case DoubleSided:
_basisExp = declareBasis(“exp(-abs(@0)/@1)”,tau) ;
break ;
}
}

//_____________________________________________________________________________
ts_p2e::ts_p2e(const ts_p2e& other, const char* name) :
RooAbsAnaConvPdf(other,name),
_t(“t”,this,other._t),
_tau(“tau”,this,other._tau),
_toff_mich(“toff_mich”,this,other._toff_mich),
_type(other._type),
_basisExp(other._basisExp)
{
// Copy constructor
}

//_____________________________________________________________________________
ts_p2e::~ts_p2e()
{
// Destructor
}

//_____________________________________________________________________________
Double_t ts_p2e::coefficient(Int_t basisIndex) const
{
if (basisIndex == _basisExp)
{
return -_toff_mich/_tau ;
}

return 0 ;
//  return 1 ;

}

//_____________________________________________________________________________
Int_t ts_p2e::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /staticInitOK/) const
{
if (matchArgs(directVars,generateVars,_t)) return 1 ;
return 0 ;
}

//_____________________________________________________________________________
void ts_p2e::generateEvent(Int_t code)
{
assert(code==1) ;

// Generate delta-t dependent
while(1) {
Double_t rand = RooRandom::uniform() ;
Double_t tval(0) ;

switch(_type) {
case SingleSided:
  tval = -_tau*log(rand)-_toff_mich;
  break ;
case Flipped:
  tval = +_tau*log(rand)-_toff_mich;
  break ;
case DoubleSided:
  tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5)) ;
  break ;
}

if (tval<_t.max() && tval>_t.min()) {
  _t = tval ;
  break ;
}

}
}
ts_p2e.cxx (3.85 KB)

OK - now I see a typo in Double_t ts_p2e::coefficient(Int_t basisIndex) const

   return -_toff_mich/_tau ; 

should be replaced (I think ;8) by

  return exp(-_toff_mich/_tau) ;

The code runs and generates the proper event distribution, but the PDF is still f.pdf (24.4 KB)wrong.
In att. 1 I set toff_mich=-10.

OK - now I realize that the time offset has already been built in RooDecay PDF
through the resolution function

RooGaussModel g_pt(“g_pt”,“gauss model scaled by per-event error”,t,bias_pt,s_pt,dt) ;

where “bias_pt” represents the time offset and s_pt represent the resolution ;8-(