/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 *    File: $Id: RooNonCPEigenDecay.cc,v 1.23 2005/06/21 16:46:33 wverkerke Exp $
 * Authors:                                                                  *
 *   AH, Andreas Hoecker,  Orsay,            hoecker@slac.stanford.edu       *
 *   SL, Sandrine Laplace, Orsay,            laplace@slac.stanford.edu       *
 *   JS, Jan Stark,        Paris,            stark@slac.stanford.edu         *
 *   WV, Wouter Verkerke,  UC Santa Barbara, verkerke@slac.stanford.edu      *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California,         *
 *                          IN2P3. All rights reserved.                      *
 *                                                                           *
 * History                                                                   *
 *   Nov-2001   WV Created initial version                                   *
 *   Dec-2001   SL mischarge correction, direct CPV                          *
 *   Jan-2002   AH built dedicated generator + code cleaning                 *
 *   Mar-2002   JS committed debugged version to CVS                         *
 *   Apr-2002   AH allow prompt (ie, non-Pdf) mischarge treatment            *
 *   May-2002   JS Changed the set of CP parameters (mathematically equiv.)  *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

// -- CLASS DESCRIPTION [PDF] --
// Time-dependent RooAbsAnaConvPdf for CP violating decays 
// to Non-CP eigenstates (eg, B0 -> rho+- pi-+).
// For a description of the physics model see the 
// BaBar Physics Book, section 6.5.2.3 .
// The set of CP parameters used in this class is equivalent to
// the one used in the Physics Book, but it is not exactly the
// same. Starting from the set in the BaBar Book, in order to 
// get the parameters used here you have to change the sign of both
// a_c^+ and a_c^-, and then substitute:
//    a_s^Q = S + Q* deltaS
//    a_c^Q = C + Q*deltaC
// where Q denotes the charge of the rho.

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include "RooRealVar.h"
#include "RooRandom.h"
#include "RooNonCPEigenDecay.h"
#include "TMath.h"

ClassImp(RooNonCPEigenDecay);

#define Debug_RooNonCPEigenDecay 1

RooNonCPEigenDecay::RooNonCPEigenDecay( const char *name, const char *title, 
					RooRealVar&     t,
					RooAbsCategory& tag,
					RooAbsReal&     tau,
					RooAbsReal&     dm,
					RooAbsReal&     avgW,
					RooAbsReal&     delW,
					RooAbsCategory& rhoQ,
					RooAbsReal&     correctQ,
					RooAbsReal&     wQ,
					RooAbsReal&     acp,
					RooAbsReal&     C,
					RooAbsReal&     delC,
					RooAbsReal&     S,
					RooAbsReal&     delS,
					const RooResolutionModel& model,
					DecayType       type )
  : RooAbsAnaConvPdf( name, title, model, t ),
  _acp      ( "acp",      "acp",                this, acp      ),
  _avgC        ( "C",        "C",                  this, C        ),
  _delC     ( "delC",     "delC",               this, delC     ),
  _avgS        ( "S",        "S",                  this, S        ),
  _delS     ( "delS",     "delS",               this, delS     ),
  _avgW     ( "avgW",     "Average mistag rate",this, avgW     ),
  _delW     ( "delW",     "Shift mistag rate",  this, delW     ),
  _t        ( "t",        "time",               this, t        ),
  _tau      ( "tau",      "decay time",         this, tau      ),
  _dm       ( "dm",       "mixing frequency",   this, dm       ),
  _tag      ( "tag",      "CP state",           this, tag      ),
  _rhoQ     ( "rhoQ",     "Charge of the rho",  this, rhoQ     ),
  _correctQ ( "correctQ", "correction of rhoQ", this, correctQ ),
  _wQ       ( "wQ",       "mischarge",          this, wQ       ),
  _genB0Frac     ( 0 ),
  _genRhoPlusFrac( 0 ),
  _type     ( type )
{

  // Constructor
  switch(type) {
  case SingleSided:
    _basisExp = declareBasis( "exp(-@0/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(-@0/@1)*sin(@0*@2)", RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(-@0/@1)*cos(@0*@2)", RooArgList( tau, dm ) );
    break;
  case Flipped:
    _basisExp = declareBasis( "exp(@0)/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(@0/@1)*sin(@0*@2)",  RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(@0/@1)*cos(@0*@2)",  RooArgList( tau, dm ) );
    break;
  case DoubleSided:
    _basisExp = declareBasis( "exp(-abs(@0)/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(-abs(@0)/@1)*sin(@0*@2)", RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(-abs(@0)/@1)*cos(@0*@2)", RooArgList( tau, dm ) );
    break;
  }
}

RooNonCPEigenDecay::RooNonCPEigenDecay( const char *name, const char *title, 
					RooRealVar&     t,
					RooAbsCategory& tag,
					RooAbsReal&     tau,
					RooAbsReal&     dm,
					RooAbsReal&     avgW,
					RooAbsReal&     delW,
					RooAbsCategory& rhoQ,
					RooAbsReal&     correctQ,
					RooAbsReal&     acp,
					RooAbsReal&     C,
					RooAbsReal&     delC,
					RooAbsReal&     S,
					RooAbsReal&     delS,
					const RooResolutionModel& model,
					DecayType       type )
  : RooAbsAnaConvPdf( name, title, model, t ),
  _acp      ( "acp",      "acp",                this, acp      ),
  _avgC        ( "C",        "C",                  this, C        ),
  _delC     ( "delC",     "delC",               this, delC     ),
  _avgS        ( "S",        "S",                  this, S        ),
  _delS     ( "delS",     "delS",               this, delS     ),
  _avgW     ( "avgW",     "Average mistag rate",this, avgW     ),
  _delW     ( "delW",     "Shift mistag rate",  this, delW     ),
  _t        ( "t",        "time",               this, t        ),
  _tau      ( "tau",      "decay time",         this, tau      ),
  _dm       ( "dm",       "mixing frequency",   this, dm       ),
  _tag      ( "tag",      "CP state",           this, tag      ),
  _rhoQ     ( "rhoQ",     "Charge of the rho",  this, rhoQ     ),
  _correctQ ( "correctQ", "correction of rhoQ", this, correctQ ),
  _genB0Frac     ( 0 ),
  _genRhoPlusFrac( 0 ),
  _type     ( type )
{

  // dummy mischarge (must be set to zero!)
  _wQ = RooRealProxy( "wQ", "mischarge", this, *(new RooRealVar( "wQ", "wQ", 0 )) );

  switch(type) {
  case SingleSided:
    _basisExp = declareBasis( "exp(-@0/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(-@0/@1)*sin(@0*@2)", RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(-@0/@1)*cos(@0*@2)", RooArgList( tau, dm ) );
    break;
  case Flipped:
    _basisExp = declareBasis( "exp(@0)/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(@0/@1)*sin(@0*@2)",  RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(@0/@1)*cos(@0*@2)",  RooArgList( tau, dm ) );
    break;
  case DoubleSided:
    _basisExp = declareBasis( "exp(-abs(@0)/@1)",            RooArgList( tau     ) );
    _basisSin = declareBasis( "exp(-abs(@0)/@1)*sin(@0*@2)", RooArgList( tau, dm ) );
    _basisCos = declareBasis( "exp(-abs(@0)/@1)*cos(@0*@2)", RooArgList( tau, dm ) );
    break;
  }
}

RooNonCPEigenDecay::RooNonCPEigenDecay( const RooNonCPEigenDecay& other, const char* name ) 
  : RooAbsAnaConvPdf( other, name ),
  _acp      ( "acp",      this, other._acp      ),
  _avgC        ( "C",        this, other._avgC        ),
  _delC     ( "delC",     this, other._delC     ),
  _avgS        ( "S",        this, other._avgS        ),
  _delS     ( "delS",     this, other._delS     ),
  _avgW     ( "avgW",     this, other._avgW     ),
  _delW     ( "delW",     this, other._delW     ),
  _t        ( "t",        this, other._t        ),
  _tau      ( "tau",      this, other._tau      ),
  _dm       ( "dm",       this, other._dm       ),
  _tag      ( "tag",      this, other._tag      ),
  _rhoQ     ( "rhoQ",     this, other._rhoQ     ),
  _correctQ ( "correctQ", this, other._correctQ ),
  _wQ       ( "wQ",       this, other._wQ       ),
  _genB0Frac     ( other._genB0Frac      ),
  _genRhoPlusFrac( other._genRhoPlusFrac ),
  _type          ( other._type           ),
  _basisExp      ( other._basisExp       ),
  _basisSin      ( other._basisSin       ),
  _basisCos      ( other._basisCos       )
{
  // Copy constructor
}

RooNonCPEigenDecay::~RooNonCPEigenDecay( void )
{
  // Destructor
}

Double_t RooNonCPEigenDecay::coefficient( Int_t basisIndex ) const 
{
  // B0    : _tag  == -1 
  // B0bar : _tag  == +1 
  // rho+  : _rhoQ == +1
  // rho-  : _rhoQ == -1
  // the charge corrrection factor "_correctQ" serves to implement mis-charges

  Int_t rhoQc = _rhoQ * int(_correctQ);
  assert( rhoQc == 1 || rhoQc == -1 );

  Double_t a_sin_p = _avgS + _delS;
  Double_t a_sin_m = _avgS - _delS;
  Double_t a_cos_p = _avgC + _delC;
  Double_t a_cos_m = _avgC - _delC;

  if (basisIndex == _basisExp) {
    if (rhoQc == -1 || rhoQc == +1)
      return (1 + rhoQc*_acp*(1 - 2*_wQ))*(1 + 0.5*_tag*(2*_delW));
    else
      return 1;
  }

  if (basisIndex == _basisSin) {

    if (rhoQc == -1)

      return - ((1 - _acp)*a_sin_m*(1 - _wQ) + (1 + _acp)*a_sin_p*_wQ)*(1 - 2*_avgW)*_tag;

    else if (rhoQc == +1)

      return - ((1 + _acp)*a_sin_p*(1 - _wQ) + (1 - _acp)*a_sin_m*_wQ)*(1 - 2*_avgW)*_tag;

    else
       return - _tag*((a_sin_p + a_sin_m)/2)*(1 - 2*_avgW);
  }

  if (basisIndex == _basisCos) {

    if ( rhoQc == -1)

      return + ((1 - _acp)*a_cos_m*(1 - _wQ) + (1 + _acp)*a_cos_p*_wQ)*(1 - 2*_avgW)*_tag;

    else if (rhoQc == +1)

      return + ((1 + _acp)*a_cos_p*(1 - _wQ) + (1 - _acp)*a_cos_m*_wQ)*(1 - 2*_avgW)*_tag;

    else
      return _tag*((a_cos_p + a_cos_m)/2)*(1 - 2*_avgW);
  }

  return 0;
}

// advertise analytical integration
Int_t RooNonCPEigenDecay::getCoefAnalyticalIntegral( RooArgSet& allVars, 
						     RooArgSet& analVars, const char* rangeName ) const
{
  if (rangeName) return 0 ;

  if (matchArgs( allVars, analVars, _tag, _rhoQ )) return 3;
  if (matchArgs( allVars, analVars, _rhoQ       )) return 2;
  if (matchArgs( allVars, analVars, _tag        )) return 1;

  return 0;
}

Double_t RooNonCPEigenDecay::coefAnalyticalIntegral( Int_t basisIndex, 
						     Int_t code, const char* /*rangeName*/ ) const
{
  // correct for the right/wrong charge...
  Int_t rhoQc = _rhoQ*int(_correctQ);

  Double_t a_sin_p = _avgS + _delS;
  Double_t a_sin_m = _avgS - _delS;
  Double_t a_cos_p = _avgC + _delC;
  Double_t a_cos_m = _avgC - _delC;

  switch(code) {

    // No integration
  case 0: return coefficient(basisIndex);

    // Integration over 'tag'
  case 1:
    if (basisIndex == _basisExp) return 2*(1 + rhoQc*_acp*(1 - 2*_wQ));
    if (basisIndex == _basisSin || basisIndex==_basisCos) return 0;
    assert( kFALSE );

    // Integration over 'rhoQ'
  case 2:
    if (basisIndex == _basisExp) return 2*(1 + 0.5*_tag*(2.*_delW));

    if (basisIndex == _basisSin)

      return - ( (1 - _acp)*a_sin_m + (1 + _acp)*a_sin_p )*(1 - 2*_avgW)*_tag;

    if (basisIndex == _basisCos)

      return + ( (1 - _acp)*a_cos_m + (1 + _acp)*a_cos_p )*(1 - 2*_avgW)*_tag;

    assert( kFALSE );

    // Integration over 'tag' and 'rhoQ'
  case 3:
    if (basisIndex == _basisExp) return 2*2; // for both: tag and charge
    if (basisIndex == _basisSin || basisIndex==_basisCos) return 0;
    assert( kFALSE );

  default:
    assert( kFALSE );
  }

  return 0;
}

Int_t RooNonCPEigenDecay::getGenerator( const RooArgSet& directVars, 
					RooArgSet&       generateVars, Bool_t staticInitOK ) const
{
  if (staticInitOK) {
    if (matchArgs( directVars, generateVars, _t, _tag, _rhoQ )) return 4;
    if (matchArgs( directVars, generateVars, _t, _rhoQ       )) return 3;
    if (matchArgs( directVars, generateVars, _t, _tag        )) return 2;
  }
  if (matchArgs( directVars, generateVars, _t              )) return 1;
  return 0;
}

void RooNonCPEigenDecay::initGenerator( Int_t code )
{

  if (code == 2 || code == 4) {
    // Calculate the fraction of mixed events to generate
    Double_t sumInt1 = RooRealIntegral( "sumInt1", "sum integral1", *this,
					RooArgSet( _t.arg(), _tag.arg(), _rhoQ.arg() )
				      ).getVal();
    _tag = -1;
    Double_t b0Int1 = RooRealIntegral( "mixInt1", "mix integral1", *this,
				       RooArgSet( _t.arg(), _rhoQ.arg() )
				     ).getVal();
    _genB0Frac = b0Int1/sumInt1;

    if (Debug_RooNonCPEigenDecay == 1)
      cout << "     o RooNonCPEigenDecay::initgenerator: genB0Frac     : "
	   << _genB0Frac
	   << ", tag dilution: " << (1 - 2*_avgW)
	   << endl;
  }

  if (code == 3 || code == 4) {
    // Calculate the fraction of positive rho's to generate
    Double_t sumInt2 = RooRealIntegral( "sumInt2", "sum integral2", *this,
					RooArgSet( _t.arg(), _tag.arg(), _rhoQ.arg() )
				      ).getVal();
    _rhoQ = 1;
    Double_t b0Int2 = RooRealIntegral( "mixInt2", "mix integral2", *this,
				       RooArgSet( _t.arg(), _tag.arg() )
				     ).getVal();
    _genRhoPlusFrac = b0Int2/sumInt2;

    if (Debug_RooNonCPEigenDecay == 1)
      cout << "     o RooNonCPEigenDecay::initgenerator: genRhoPlusFrac: "
	   << _genRhoPlusFrac << endl;
  }
}


void RooNonCPEigenDecay::generateEvent( Int_t code )
{

  // Generate delta-t dependent
  while (kTRUE) {

    // B flavor and rho charge (we do not use the integrated weights)
    if (code != 1) {
      if (code != 3) _tag  = (RooRandom::uniform()<=0.5) ? -1 : +1;
      if (code != 2) _rhoQ = (RooRandom::uniform()<=0.5) ?  1 : -1;
    }

    // opposite charge?
    // Int_t rhoQc = _rhoQ*int(_correctQ);

    Double_t a_sin_p = _avgS + _delS;
    Double_t a_sin_m = _avgS - _delS;
    Double_t a_cos_p = _avgC + _delC;
    Double_t a_cos_m = _avgC - _delC;

    // maximum probability density 
    double a1 = 1 + sqrt(TMath::Power(a_cos_m, 2) + TMath::Power(a_sin_m, 2));
    double a2 = 1 + sqrt(TMath::Power(a_cos_p, 2) + TMath::Power(a_sin_p, 2));

    Double_t maxAcceptProb = (1.10 + TMath::Abs(_acp)) * (a1 > a2 ? a1 : a2);
    // The 1.10 in the above line is a security feature to prevent crashes close to the limit at 1.00

    Double_t rand = RooRandom::uniform();
    Double_t tval(0);

    switch(_type) {

    case SingleSided:
      tval = -_tau*log(rand);
      break;

    case Flipped:
      tval = +_tau*log(rand);
      break;

    case DoubleSided:
      tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5));
      break;
    }

    // get coefficients
    Double_t expC = coefficient( _basisExp );
    Double_t sinC = coefficient( _basisSin );
    Double_t cosC = coefficient( _basisCos );

    // probability density
    Double_t acceptProb  = expC + sinC*sin(_dm*tval) + cosC*cos(_dm*tval);

    // sanity check...
    assert( acceptProb <= maxAcceptProb );

    // hit or miss...
    Bool_t accept = maxAcceptProb*RooRandom::uniform() < acceptProb ? kTRUE : kFALSE;

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



ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.