Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooLinearVar.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * @(#)root/roofitcore:$Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 //////////////////////////////////////////////////////////////////////////////
18 /// \class RooLinearVar
19 /// RooLinearVar is the most general form of a derived real-valued object that can
20 /// be used by RooRealIntegral to integrate over. The requirements for this are
21 /// * Can be modified directly (i.e. invertible formula)
22 /// * Jacobian term in integral is constant (but not necessarily 1)
23 ///
24 /// This class implements the most general form that satisfies these requirements
25 /// \f[
26 /// RLV = \mathrm{slope} \cdot x + \mathrm{offset}
27 /// \f]
28 /// \f$ x \f$ is required to be a RooRealVar to meet the invertibility criterium,
29 /// `slope` and `offset` are RooAbsReals, but cannot overlap with \f$ x \f$,
30 /// *i.e.*, \f$ x \f$ may not be a server of `slope` and `offset`.
31 ///
32 /// In the context of a dataset, `slope` may not contain any real-valued dependents
33 /// (to satisfyt the constant Jacobian requirement). This check cannot be enforced at
34 /// construction time, but can be performed at run time through the isJacobianOK(depList)
35 /// member function.
36 ///
37 ///
38 
39 #include "RooFit.h"
40 #include "Riostream.h"
41 
42 #include <math.h>
43 #include "TClass.h"
44 #include "TObjString.h"
45 #include "TTree.h"
46 #include "RooLinearVar.h"
47 #include "RooStreamParser.h"
48 #include "RooArgSet.h"
49 #include "RooRealVar.h"
50 #include "RooNumber.h"
51 #include "RooBinning.h"
52 #include "RooMsgService.h"
53 
54 
55 
56 using namespace std;
57 
58 ClassImp(RooLinearVar);
59 
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Constructor with RooAbsRealLValue variable and RooAbsReal slope and offset
63 
64 RooLinearVar::RooLinearVar(const char *name, const char *title, RooAbsRealLValue& variable,
65  const RooAbsReal& slope, const RooAbsReal& offs, const char *unit) :
66  RooAbsRealLValue(name, title, unit),
67  _binning(variable.getBinning(),slope.getVal(),offs.getVal()),
68  _var("var","variable",this,variable,kTRUE,kTRUE),
69  _slope("slope","slope",this,(RooAbsReal&)slope),
70  _offset("offset","offset",this,(RooAbsReal&)offs)
71 {
72  // Slope and offset may not depend on variable
73  if (slope.dependsOnValue(variable) || offs.dependsOnValue(variable)) {
74  coutE(InputArguments) << "RooLinearVar::RooLinearVar(" << GetName()
75  << "): ERROR, slope(" << slope.GetName() << ") and offset("
76  << offs.GetName() << ") may not depend on variable("
77  << variable.GetName() << ")" << endl ;
78  assert(0) ;
79  }
80 
81  // Initial plot range and number of bins from dependent variable
82 // setPlotRange(variable.getPlotMin()*_slope + _offset,
83 // variable.getPlotMax()*_slope + _offset) ;
84 // setPlotBins(variable.getPlotBins()) ;
85 
86 }
87 
88 
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Copy constructor
92 
93 RooLinearVar::RooLinearVar(const RooLinearVar& other, const char* name) :
94  RooAbsRealLValue(other,name),
95  _binning(other._binning),
96  _var("var",this,other._var),
97  _slope("slope",this,other._slope),
98  _offset("offset",this,other._offset)
99 {
100 }
101 
102 
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Destructor
106 
107 RooLinearVar::~RooLinearVar()
108 {
109  _altBinning.Delete() ;
110 }
111 
112 
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Calculate current value of this object
116 
117 Double_t RooLinearVar::evaluate() const
118 {
119  return _offset + _var * _slope ;
120 }
121 
122 
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// Assign given value to linear transformation: sets input variable to (value-offset)/slope
126 /// If slope is zerom an error message is printed and no assignment is made
127 
128 void RooLinearVar::setVal(Double_t value)
129 {
130  //cout << "RooLinearVar::setVal(" << GetName() << "): new value = " << value << endl ;
131 
132  // Prevent DIV0 problems
133  if (_slope == 0.) {
134  coutE(Eval) << "RooLinearVar::setVal(" << GetName() << "): ERROR: slope is zero, cannot invert relation" << endl ;
135  return ;
136  }
137 
138  // Invert formula 'value = offset + slope*var'
139  ((RooRealVar&)_var.arg()).setVal((value - _offset) / _slope) ;
140 
141 }
142 
143 
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// Returns true if Jacobian term associated with current
147 /// expression tree is indeed constant.
148 
149 Bool_t RooLinearVar::isJacobianOK(const RooArgSet& depList) const
150 {
151  if (!((RooAbsRealLValue&)_var.arg()).isJacobianOK(depList)) {
152  return kFALSE ;
153  }
154 
155  // Check if jacobian has no real-valued dependents
156  RooAbsArg* arg ;
157  TIterator* dIter = depList.createIterator() ;
158  while ((arg=(RooAbsArg*)dIter->Next())) {
159  if (arg->IsA()->InheritsFrom(RooAbsReal::Class())) {
160  if (_slope.arg().dependsOnValue(*arg)) {
161 // cout << "RooLinearVar::isJacobianOK(" << GetName() << ") return kFALSE because slope depends on value of " << arg->GetName() << endl ;
162  return kFALSE ;
163  }
164  }
165  }
166  delete dIter ;
167 // cout << "RooLinearVar::isJacobianOK(" << GetName() << ") return kTRUE" << endl ;
168  return kTRUE ;
169 }
170 
171 
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Return value of Jacobian associated with the transformation
175 
176 Double_t RooLinearVar::jacobian() const
177 {
178  return _slope*((RooAbsRealLValue&)_var.arg()).jacobian() ;
179 }
180 
181 
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Read object contents from stream
185 
186 Bool_t RooLinearVar::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/)
187 {
188  return kTRUE ;
189 }
190 
191 
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 /// Write object contents to stream
195 
196 void RooLinearVar::writeToStream(ostream& os, Bool_t compact) const
197 {
198  if (compact) {
199  os << getVal() ;
200  } else {
201  os << _slope.arg().GetName() << " * " << _var.arg().GetName() << " + " << _offset.arg().GetName() ;
202  }
203 }
204 
205 
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// Retrieve binning of this linear transformation. A RooLinearVar does not have its own
209 /// binnings but uses linearly transformed binnings of the input variable. If a given
210 /// binning exists on the input variable, it will also exist on this linear transformation,
211 /// and a binning adaptor object is created on the fly.
212 
213  RooAbsBinning& RooLinearVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly)
214 {
215  // Normalization binning
216  if (name==0) {
217  _binning.updateInput(((RooAbsRealLValue&)_var.arg()).getBinning(),_slope,_offset) ;
218  return _binning ;
219  }
220 
221  // Alternative named range binnings, look for existing translator binning first
222  RooLinTransBinning* altBinning = (RooLinTransBinning*) _altBinning.FindObject(name) ;
223  if (altBinning) {
224  altBinning->updateInput(((RooAbsRealLValue&)_var.arg()).getBinning(name,verbose),_slope,_offset) ;
225  return *altBinning ;
226  }
227 
228  // If binning is not found return default binning, if creation is not requested
229  if (!_var.arg().hasRange(name) && !createOnTheFly) {
230  return _binning ;
231  }
232 
233  // Create translator binning on the fly
234  RooAbsBinning& sourceBinning = ((RooAbsRealLValue&)_var.arg()).getBinning(name,verbose) ;
235  RooLinTransBinning* transBinning = new RooLinTransBinning(sourceBinning,_slope,_offset) ;
236  _altBinning.Add(transBinning) ;
237 
238  return *transBinning ;
239 }
240 
241 
242 ////////////////////////////////////////////////////////////////////////////////
243 /// Const version of getBinning()
244 
245 const RooAbsBinning& RooLinearVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly) const
246 {
247  return const_cast<RooLinearVar*>(this)->getBinning(name,verbose,createOnTheFly) ;
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////
251 /// Get a list of all binning names. An empty name implies the default binning.
252 /// A 0 pointer should be passed to getBinning in this case.
253 
254 std::list<std::string> RooLinearVar::getBinningNames() const
255 {
256  std::list<std::string> binningNames(1, "");
257 
258  RooFIter iter = _altBinning.fwdIterator();
259  const RooAbsArg* binning = 0;
260  while((binning = iter.next())) {
261  const char* name = binning->GetName();
262  binningNames.push_back(name);
263  }
264 
265  return binningNames;
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Returns true if binning with given name exists.If a given binning
270 /// exists on the input variable, it will also exists on this linear
271 /// transformation.
272 
273 Bool_t RooLinearVar::hasBinning(const char* name) const
274 {
275  return ((RooAbsRealLValue&)_var.arg()).hasBinning(name) ;
276 }