Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 43 additions & 37 deletions roofit/roofitcore/inc/RooAbsArg.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ class RooAbsArg : public TNamed, public RooPrintable {
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
/// \name Client-Server Interface.
/// \anchor clientServerInterface
/// \name Client-Server Interface
/// These functions allow RooFit to figure out who is serving values to whom.
/// @{

Expand Down Expand Up @@ -369,12 +370,6 @@ class RooAbsArg : public TNamed, public RooPrintable {
return kTRUE ;
}

//Debug hooks
static void verboseDirty(Bool_t flag) ;
void printDirty(Bool_t depth=kTRUE) const ;

static void setDirtyInhibit(Bool_t flag) ;

virtual bool operator==(const RooAbsArg& other) const = 0 ;
virtual bool isIdentical(const RooAbsArg& other, Bool_t assumeSameType=kFALSE) const = 0 ;

Expand All @@ -390,9 +385,15 @@ class RooAbsArg : public TNamed, public RooPrintable {


enum ConstOpCode { Activate=0, DeActivate=1, ConfigChange=2, ValueChange=3 } ;
enum CacheMode { Always=0, NotAdvised=1, Never=2 } ;
enum OperMode { Auto=0, AClean=1, ADirty=2 } ;


friend class RooMinuit ;
////////////////////////////////////////////////////////////////////////////
/// \anchor optimisationInterface
/// \name Optimisation interface
/// These functions allow RooFit to optimise a computation graph, to keep track
/// of cached values, and to invalidate caches.
/// @{

// Cache mode optimization (tracks changes & do lazy evaluation vs evaluate always)
virtual void optimizeCacheMode(const RooArgSet& observables) ;
Expand All @@ -406,20 +407,10 @@ class RooAbsArg : public TNamed, public RooPrintable {

// constant term optimization
virtual void constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt=kTRUE) ;
enum CacheMode { Always=0, NotAdvised=1, Never=2 } ;

virtual CacheMode canNodeBeCached() const { return Always ; }
virtual void setCacheAndTrackHints(RooArgSet& /*trackNodes*/ ) {} ;

void graphVizTree(const char* fileName, const char* delimiter="\n", bool useTitle=false, bool useLatex=false) ;
void graphVizTree(std::ostream& os, const char* delimiter="\n", bool useTitle=false, bool useLatex=false) ;

/* TGraphStruct* graph(Bool_t useFactoryTag=kFALSE, Double_t textSize=0.03) ; */

void printComponentTree(const char* indent="",const char* namePat=0, Int_t nLevel=999) ;
void printCompactTree(const char* indent="",const char* fileName=0, const char* namePat=0, RooAbsArg* client=0) ;
void printCompactTree(std::ostream& os, const char* indent="", const char* namePat=0, RooAbsArg* client=0) ;
virtual void printCompactTreeHook(std::ostream& os, const char *ind="") ;

// Dirty state accessor
inline Bool_t isShapeDirty() const {
// Return true is shape has been invalidated by server value change
Expand Down Expand Up @@ -488,20 +479,11 @@ class RooAbsArg : public TNamed, public RooPrintable {
Int_t numCaches() const ;
RooAbsCache* getCache(Int_t index) const ;

enum OperMode { Auto=0, AClean=1, ADirty=2 } ;
/// Query the operation mode of this node.
inline OperMode operMode() const { return _operMode ; }
/// Set the operation mode of this node.
void setOperMode(OperMode mode, Bool_t recurseADirty=kTRUE) ;

Bool_t addOwnedComponents(const RooArgSet& comps) ;
const RooArgSet* ownedComponents() const { return _ownedComponents ; }

void setProhibitServerRedirect(Bool_t flag) { _prohibitServerRedirect = flag ; }

void setWorkspace(RooWorkspace &ws) { _myws = &ws; }

RooAbsProxy* getProxy(Int_t index) const ;
Int_t numProxies() const ;

// Dirty state modifiers
/// Mark the element dirty. This forces a re-evaluation when a value is requested.
void setValueDirty() {
Expand All @@ -516,19 +498,43 @@ class RooAbsArg : public TNamed, public RooPrintable {

void wireAllCaches() ;

RooExpensiveObjectCache& expensiveObjectCache() const ;
virtual void setExpensiveObjectCache(RooExpensiveObjectCache &cache) { _eocache = &cache; }

/// @}
////////////////////////////////////////////////////////////////////////////

//Debug hooks
static void verboseDirty(Bool_t flag) ;
void printDirty(Bool_t depth=kTRUE) const ;
static void setDirtyInhibit(Bool_t flag) ;

void graphVizTree(const char* fileName, const char* delimiter="\n", bool useTitle=false, bool useLatex=false) ;
void graphVizTree(std::ostream& os, const char* delimiter="\n", bool useTitle=false, bool useLatex=false) ;

void printComponentTree(const char* indent="",const char* namePat=0, Int_t nLevel=999) ;
void printCompactTree(const char* indent="",const char* fileName=0, const char* namePat=0, RooAbsArg* client=0) ;
void printCompactTree(std::ostream& os, const char* indent="", const char* namePat=0, RooAbsArg* client=0) ;
virtual void printCompactTreeHook(std::ostream& os, const char *ind="") ;

Bool_t addOwnedComponents(const RooArgSet& comps) ;
const RooArgSet* ownedComponents() const { return _ownedComponents ; }

void setProhibitServerRedirect(Bool_t flag) { _prohibitServerRedirect = flag ; }

void setWorkspace(RooWorkspace &ws) { _myws = &ws; }

RooAbsProxy* getProxy(Int_t index) const ;
Int_t numProxies() const ;


inline const TNamed* namePtr() const {
return _namePtr ;
}

void SetName(const char* name) ;
void SetNameTitle(const char *name, const char *title) ;




RooExpensiveObjectCache& expensiveObjectCache() const ;
virtual void setExpensiveObjectCache(RooExpensiveObjectCache &cache) { _eocache = &cache; }

virtual Bool_t importWorkspaceHook(RooWorkspace &ws)
{
_myws = &ws;
Expand Down
5 changes: 2 additions & 3 deletions roofit/roofitcore/inc/RooMCStudy.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ class RooMCStudy : public TNamed {
const RooFitResult* fitResult(Int_t sampleNum) const ;
RooAbsData* genData(Int_t sampleNum) const ;
const RooDataSet& fitParDataSet() ;
/// Return a RooDataSet containing the pre-fit parameters of each toy cycle.
/// Return dataset with generator parameters for each toy. When constraints are used these
/// may generally not be the same as the fitted parameters.
const RooDataSet* genParDataSet() const {
// Return dataset with generator parameters for each toy. When constraints are used these
// may generally not be the same
return _genParData ;
}

Expand Down
57 changes: 45 additions & 12 deletions roofit/roofitcore/src/RooAbsArg.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,50 @@
\ingroup Roofitcore

RooAbsArg is the common abstract base class for objects that
represent a value (of arbitrary type) and "shape" that in general
depends on (is a client of) other RooAbsArg subclasses. The only
state information about a value that is maintained in this base
class consists of named attributes and flags that track when either
the value or the shape of this object changes. The meaning of shape
depends on the client implementation but could be, for example, the
allowed range of a value. The base class is also responsible for
managing client/server links and propagating value/shape changes
through an expression tree. RooAbsArg implements public interfaces
for inspecting client/server relationships and
setting/clearing/testing named attributes.
represent a value and a "shape" in RooFit. Values or shapes usually depend on values
or shapes of other RooAbsArg instances. Connecting several RooAbsArg in
a computation graph models an expression tree that can be evaluated.

### Building a computation graph of RooFit objects
Therefore, RooAbsArg provides functionality to connect objects of type RooAbsArg into
a computation graph to pass values between those objects.
A value can e.g. be a real-valued number, (instances of RooAbsReal), or an integer, that is,
catgory index (instances of RooAbsCategory). The third subclass of RooAbsArg is RooStringVar,
but it is rarely used.

The "shapes" that a RooAbsArg can possess can e.g. be the definition
range of an observable, or how many states a category object has. In computations,
values are expected to change often, while shapes remain mostly constant
(unless e.g. a new range is set for an observable).

Nodes of a computation graph are connected using instances of RooAbsProxy.
If Node B declares a member `RooTemplateProxy<TypeOfNodeA>`, Node A will be
registered as a server of values to Node B, and Node B will know that it is
a client of node A. Using functions like dependsOn(), or getObservables()
/ getParameters(), the relation of `A --> B` can be queried. Using graphVizTree(),
one can create a visualisation of the expression tree.


An instance of RooAbsArg can have named attributes. It also has flags
to indicate that either its value or its shape were changed (= it is dirty).
RooAbsArg provides functionality to manage client/server relations in
a computation graph (\ref clientServerInterface), and helps propagating
value/shape changes through the graph. RooAbsArg implements interfaces
for inspecting client/server relationships (\ref clientServerInterface) and
setting/clearing/querying named attributes.

### Caching of values
The values of nodes in the computation graph are cached in RooFit. If
a value is used in two nodes of a graph, it doesn't need to be recomputed. If
a node acquires a new value, it notifies its consumers ("clients") that
their cached values are dirty. See the functions in \ref optimisationInterface
for details.
A node uses its isValueDirty() and isShapeDirty() functions to decide if a
computation is necessary. Caching can be vetoed globally by setting a
bit using setDirtyInhibit(). This will make computations slower, but all the
nodes of the computation graph will be evaluated irrespective of whether their
state is clean or dirty. Using setOperMode(), caching can also be enabled/disabled
for single nodes.

*/

Expand Down Expand Up @@ -821,7 +854,7 @@ Bool_t RooAbsArg::observableOverlaps(const RooArgSet* nset, const RooAbsArg& tes
////////////////////////////////////////////////////////////////////////////////
/// Mark this object as having changed its value, and propagate this status
/// change to all of our clients. If the object is not in automatic dirty
/// state propagation mode, this call has no effect
/// state propagation mode, this call has no effect.

void RooAbsArg::setValueDirty(const RooAbsArg* source)
{
Expand Down
2 changes: 1 addition & 1 deletion roofit/roofitcore/src/RooAbsMCStudyModule.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ between the generation and fitting step and after the fitting step.
Any summary output variables declared in the RooDataSet exported through
summaryData() is merged with the 'master' summary dataset in RooMCStudy.

Look at RooDLLSignificanceMCStudyModule for an example of an implementation.
Look at RooDLLSignificanceMCSModule for an example of an implementation.
**/

#include "RooFit.h"
Expand Down
18 changes: 13 additions & 5 deletions roofit/roofitcore/src/RooAbsPdf.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,7 @@ RooAbsReal* RooAbsPdf::createNLL(RooAbsData& data, const RooLinkedList& cmdList)
/// commands MIGRAD, HESSE in succession.
/// \param[in] data Data to fit the PDF to
/// \param[in] arg1 One or more arguments to control the behaviour of the fit
/// \return RooFitResult * with the fit status if option Save() is used, 0 otherwise.
/// \return RooFitResult with fit status and parameters if option Save() is used, `nullptr` otherwise. The user takes ownership of the fit result.
///
/// The following named arguments are supported
///
Expand Down Expand Up @@ -2767,11 +2767,19 @@ void removeRangeOverlap(std::vector<std::pair<double, double>>& ranges) {
/// <tr><td> `Components(const RooArgSet& compSet)` <td> As above, but pass a RooArgSet of the components themselves.
///
/// <tr><th> Type of argument <th> Projection control
/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omitting
/// observables listed in set from the projection, resulting in a 'slice' plot. Slicing is mostly
/// needed in discrete observables such as categories.
/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omitting observables listed
/// in set from the projection, i.e. by not integrating over these.
/// Slicing is usually only sensible in discrete observables, by e.g. creating a slice
/// of the PDF at the current value of the category observable.
/// <tr><td> `Slice(RooCategory& cat, const char* label)` <td> Override default projection behaviour by omitting the specified category
/// observable from the projection, i.e., by not integrating over all states of this category.
/// The slice is positioned at the given label value. Multiple Slice() commands can be given to specify slices
/// in multiple observables, e.g.
/// ```{.cpp}
/// pdf.plotOn(frame, Slice(tagCategory, "2tag"), Slice(jetCategory, "3jet"));
/// ```
/// <tr><td> `Project(const RooArgSet& set)` <td> Override default projection behaviour by projecting
/// over observables given in set and complete ignoring the default projection behavior. Advanced use only.
/// over observables given in set, completely ignoring the default projection behavior. Advanced use only.
/// <tr><td> `ProjWData(const RooAbsData& d)` <td> Override default projection _technique_ (integration). For observables
/// present in given dataset projection of PDF is achieved by constructing an average over all observable
/// values in given set. Consult RooFit plotting tutorial for further explanation of meaning & use of this technique
Expand Down
33 changes: 19 additions & 14 deletions roofit/roofitcore/src/RooAbsReal.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1617,15 +1617,18 @@ void RooAbsReal::plotOnCompSelect(RooArgSet* selNodes) const
/// This function takes the following named arguments
/// <table>
/// <tr><th><th> Projection control
/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omittting observables listed
/// in set from the projection, resulting a 'slice' plot. Slicing is usually
/// only sensible in discrete observables. The slice is position at the 'current'
/// value of the observable objects
/// <tr><td> `Slice(const RooArgSet& set)` <td> Override default projection behaviour by omitting observables listed
/// in set from the projection, i.e. by not integrating over these.
/// Slicing is usually only sensible in discrete observables, by e.g. creating a slice
/// of the PDF at the current value of the category observable.
///
/// <tr><td> `Slice(RooCategory& cat, const char* label)` <td> Override default projection behaviour by omittting specified category
/// observable from the projection, resulting in a 'slice' plot. The slice is positioned
/// at the given label value. Multiple Slice() commands can be given to specify slices
/// in multiple observables
/// <tr><td> `Slice(RooCategory& cat, const char* label)` <td> Override default projection behaviour by omitting the specified category
/// observable from the projection, i.e., by not integrating over all states of this category.
/// The slice is positioned at the given label value. Multiple Slice() commands can be given to specify slices
/// in multiple observables, e.g.
/// ```{.cpp}
/// pdf.plotOn(frame, Slice(tagCategory, "2tag"), Slice(jetCategory, "3jet"));
/// ```
///
/// <tr><td> `Project(const RooArgSet& set)` <td> Override default projection behaviour by projecting over observables
/// given in the set, ignoring the default projection behavior. Advanced use only.
Expand Down Expand Up @@ -2690,14 +2693,16 @@ RooPlot* RooAbsReal::plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue& asym


////////////////////////////////////////////////////////////////////////////////
/// Calculate error on self by propagated errors on parameters with correlations as given by fit result
/// The linearly propagated error is calculated as follows
/// Calculate error on self by *linearly* propagating errors on parameters using the covariance matrix
/// from a fit result.
/// The error is calculated as follows
/// \f[
/// \mathrm{error}(x) = F_a(x) * \mathrm{Corr}(a,a') * F_{a'}^{\mathrm{T}}(x)
/// \mathrm{error}^2(x) = F_\mathbf{a}(x) \cdot \mathrm{Cov}(\mathbf{a},\mathbf{a}') \cdot F_{\mathbf{a}'}^{\mathrm{T}}(x)
/// \f]
/// where \f$ F_a(x) = \frac{ f(x, a + \mathrm{d}a) - f(x, a - \mathrm{d}a) }{2} \f$,
/// with \f$ f(x) \f$ this function and \f$ \mathrm{d}a \f$ taken from the fit result and
/// \f$ \mathrm{Corr}(a,a') \f$ = the correlation matrix from the fit result
/// where \f$ F_mathbf{a}(x) = \frac{ f(x, mathbf{a} + \mathrm{d}mathbf{a}) - f(x, mathbf{a} - \mathrm{d}mathbf{a}) }{2} \f$,
/// with \f$ f(x) = \f$ `this` and \f$ \mathrm{d}mathbf{a} \f$ the vector of one-sigma uncertainties of all
/// fit parameters taken from the fit result and
/// \f$ \mathrm{Cov}(mathbf{a},mathbf{a}') \f$ = the covariance matrix from the fit result.
///

Double_t RooAbsReal::getPropagatedError(const RooFitResult &fr, const RooArgSet &nset_in) const
Expand Down
37 changes: 29 additions & 8 deletions roofit/roofitcore/src/RooChi2Var.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,36 @@
//////////////////////////////////////////////////////////////////////////////
/**
// \class RooChi2Var
// Class RooChi2Var implements a simple chi^2 calculation from a binned dataset
// RooChi2Var implements a simple \f$ \chi^2 \f$ calculation from a binned dataset
// and a PDF. It calculates
\f[
\chi^2 = \sum_{[\mathrm{bins}]} \left( \frac{(f_\mathrm{PDF} \cdot N_\mathrm{tot} / V_\mathrm{bin}) - N_\mathrm{bin}}{\mathrm{err}_\mathrm{bin}} \right)^2
\f]
// If no user-defined errors are defined for the dataset, poisson errors
// are used. In extended PDF mode, N_tot is substituted with N_expected.
//
*/
\f{align*}{
\chi^2 &= \sum_{\mathrm{bins}} \left( \frac{N_\mathrm{PDF,bin} - N_\mathrm{Data,bin}}{\Delta_\mathrm{bin}} \right)^2 \\
N_\mathrm{PDF,bin} &=
\begin{cases}
\mathrm{pdf}(\text{bin centre}) \cdot V_\mathrm{bin} \cdot N_\mathrm{Data,tot} &\text{normal PDF}\\
\mathrm{pdf}(\text{bin centre}) \cdot V_\mathrm{bin} \cdot N_\mathrm{Data,expected} &\text{extended PDF}
\end{cases} \\
\Delta_\mathrm{bin} &=
\begin{cases}
\sqrt{N_\mathrm{PDF,bin}} &\text{if } \mathtt{DataError == RooAbsData::Expected}\\
\mathtt{data{\rightarrow}weightError()} &\text{otherwise} \\
\end{cases}
\f}
* If the dataset doesn't have user-defined errors, errors are assumed to be \f$ \sqrt{N} \f$.
* In extended PDF mode, N_tot (total number of data events) is substituted with N_expected, the
* expected number of events that the PDF predicts.
*
* \note If data errors are used, empty bins will prevent the calculation of \f$ \chi^2 \f$, because those have
* zero error. This leads to messages like:
* ```
* [#0] ERROR:Eval -- RooChi2Var::RooChi2Var(chi2_GenPdf_data_hist) INFINITY ERROR: bin 2 has zero error
* ```
*
* \note In this case, one can use the expected errors of the PDF instead of the data errors:
* ```{.cpp}
* RooChi2Var chi2(..., ..., RooFit::DataError(RooAbsData::Expected), ...);
* ```
*/

#include "RooFit.h"

Expand Down
Loading