Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooRealVar.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 \file RooRealVar.cxx
19 \class RooRealVar
20 \ingroup Roofitcore
21 
22 RooRealVar represents a fundamental (non-derived) real-valued object.
23 
24 This class also holds an (asymmetic) error, a default range and
25 optionally a series of alternate named ranges.
26 **/
27 
28 
29 #include "RooFit.h"
30 #include "Riostream.h"
31 #include "RooTrace.h"
32 
33 #include <math.h>
34 #include "TObjString.h"
35 #include "TTree.h"
36 #include "RooRealVar.h"
37 #include "RooStreamParser.h"
38 #include "RooErrorVar.h"
39 #include "RooRangeBinning.h"
40 #include "RooCmdConfig.h"
41 #include "RooMsgService.h"
42 #include "RooParamBinning.h"
43 #include "RooVectorDataStore.h"
44 
45 
46 using namespace std;
47 
48 ClassImp(RooRealVar);
49 ;
50 
51 Bool_t RooRealVar::_printScientific(kFALSE) ;
52 Int_t RooRealVar::_printSigDigits(5) ;
53 RooSharedPropertiesList RooRealVar::_sharedPropList ;
54 RooRealVarSharedProperties RooRealVar::_nullProp("00000000-0000-0000-0000-000000000000") ;
55 
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Default constructor
59 
60 RooRealVar::RooRealVar() : _error(0), _asymErrLo(0), _asymErrHi(0), _binning(0), _sharedProp(0)
61 {
62  _binning = new RooUniformBinning() ;
63  _fast = kTRUE ;
64  TRACE_CREATE
65 }
66 
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Constructor with value and unit
70 
71 RooRealVar::RooRealVar(const char *name, const char *title,
72  Double_t value, const char *unit) :
73  RooAbsRealLValue(name, title, unit), _error(-1), _asymErrLo(1), _asymErrHi(-1), _sharedProp(0)
74 {
75  // _instanceList.registerInstance(this) ;
76  _binning = new RooUniformBinning(-1,1,100) ;
77  _value = value ;
78  _fast = kTRUE ;
79  removeRange();
80  setConstant(kTRUE) ;
81  TRACE_CREATE
82 }
83 
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Constructor with range and unit. Initial value is center of range
87 
88 RooRealVar::RooRealVar(const char *name, const char *title,
89  Double_t minValue, Double_t maxValue,
90  const char *unit) :
91  RooAbsRealLValue(name, title, unit), _error(-1), _asymErrLo(1), _asymErrHi(-1), _sharedProp(0)
92 {
93  _binning = new RooUniformBinning(minValue,maxValue,100) ;
94  _fast = kTRUE ;
95 
96  if (RooNumber::isInfinite(minValue)) {
97  if (RooNumber::isInfinite(maxValue)) {
98  // [-inf,inf]
99  _value = 0 ;
100  } else {
101  // [-inf,X]
102  _value= maxValue ;
103  }
104  } else {
105  if (RooNumber::isInfinite(maxValue)) {
106  // [X,inf]
107  _value = minValue ;
108  } else {
109  // [X,X]
110  _value= 0.5*(minValue + maxValue);
111  }
112  }
113 
114  // setPlotRange(minValue,maxValue) ;
115  setRange(minValue,maxValue) ;
116  TRACE_CREATE
117 }
118 
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Constructor with value, range and unit
122 
123 RooRealVar::RooRealVar(const char *name, const char *title,
124  Double_t value, Double_t minValue, Double_t maxValue,
125  const char *unit) :
126  RooAbsRealLValue(name, title, unit), _error(-1), _asymErrLo(1), _asymErrHi(-1), _sharedProp(0)
127 {
128  _fast = kTRUE ;
129  _binning = new RooUniformBinning(minValue,maxValue,100) ;
130  setRange(minValue,maxValue) ;
131 
132  Double_t clipValue ;
133  inRange(value,0,&clipValue) ;
134  _value = clipValue ;
135 
136  TRACE_CREATE
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 /// Copy Constructor
142 
143 RooRealVar::RooRealVar(const RooRealVar& other, const char* name) :
144  RooAbsRealLValue(other,name),
145  _error(other._error),
146  _asymErrLo(other._asymErrLo),
147  _asymErrHi(other._asymErrHi)
148 {
149  _sharedProp = (RooRealVarSharedProperties*) _sharedPropList.registerProperties(other.sharedProp()) ;
150  if (other._binning) {
151  _binning = other._binning->clone() ;
152  _binning->insertHook(*this) ;
153  }
154  _fast = kTRUE ;
155 
156  //cout << "RooRealVar::cctor(this = " << this << " name = " << GetName() << ", other = " << &other << ")" << endl ;
157 
158  RooAbsBinning* ab ;
159  TIterator* iter = other._altNonSharedBinning.MakeIterator() ;
160  while((ab=(RooAbsBinning*)iter->Next())) {
161  RooAbsBinning* abc = ab->clone() ;
162  //cout << "cloning binning " << ab << " into " << abc << endl ;
163  _altNonSharedBinning.Add(abc) ;
164  abc->insertHook(*this) ;
165  }
166  delete iter ;
167 
168  TRACE_CREATE
169 
170 }
171 
172 /// Assign the values of another RooRealVar to this instance.
173 RooRealVar& RooRealVar::operator=(const RooRealVar& other) {
174  RooAbsRealLValue::operator=(other);
175 
176  _error = other._error;
177  _asymErrLo = other._asymErrLo;
178  _asymErrHi = other._asymErrHi;
179 
180  delete _binning;
181  _binning = nullptr;
182  if (other._binning) {
183  _binning = other._binning->clone() ;
184  _binning->insertHook(*this) ;
185  }
186 
187  _altNonSharedBinning.Clear();
188  RooAbsBinning* ab ;
189  std::unique_ptr<TIterator> iter(other._altNonSharedBinning.MakeIterator());
190  while((ab=(RooAbsBinning*)iter->Next())) {
191  RooAbsBinning* abc = ab->clone() ;
192  _altNonSharedBinning.Add(abc) ;
193  abc->insertHook(*this) ;
194  }
195 
196  _sharedProp = (RooRealVarSharedProperties*) _sharedPropList.registerProperties(other.sharedProp());
197 
198  return *this;
199 }
200 
201 
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 /// Destructor
205 
206 RooRealVar::~RooRealVar()
207 {
208  delete _binning ;
209  _altNonSharedBinning.Delete() ;
210 
211  if (_sharedProp) {
212  _sharedPropList.unregisterProperties(_sharedProp) ;
213  }
214 
215  TRACE_DESTROY
216 }
217 
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Return value of variable
221 
222 Double_t RooRealVar::getValV(const RooArgSet*) const
223 {
224  return _value ;
225 }
226 
227 
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Return batch of data between begin and end.
231 /// This requires that this instance is attached to a data store.
232 /// \param begin First event to return.
233 /// \param batchSize Size of the batch.
234 /// \return Span with event data. May be empty if not attached to a data storage.
235 RooSpan<const double> RooRealVar::getValBatch(std::size_t begin, std::size_t batchSize,
236  const RooArgSet*) const {
237  const auto batchStatus = _batchData.status(begin, batchSize);
238  if (batchStatus == BatchHelpers::BatchData::kNoBatch) {
239  return {};
240  }
241 
242  assert(batchStatus == BatchHelpers::BatchData::kReadyAndConstant);
243  return _batchData.getBatch(begin, batchSize);
244 }
245 
246 
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Set value of variable to 'value'. If 'value' is outside
250 /// range of object, clip value into range
251 
252 void RooRealVar::setVal(Double_t value)
253 {
254  Double_t clipValue ;
255  inRange(value,0,&clipValue) ;
256 
257  if (clipValue != _value) {
258  setValueDirty() ;
259  _value = clipValue;
260  }
261 }
262 
263 
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Set value of variable to 'value'. If 'value' is outside
267 /// range named 'rangeName' of object, clip value into that range
268 
269 void RooRealVar::setVal(Double_t value, const char* rangeName)
270 {
271  Double_t clipValue ;
272  inRange(value,rangeName,&clipValue) ;
273 
274  if (clipValue != _value) {
275  setValueDirty() ;
276  _value = clipValue;
277  }
278 }
279 
280 
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 /// Return a RooAbsRealLValue representing the error associated
284 /// with this variable. The callers takes ownership of the
285 /// return object
286 
287 RooErrorVar* RooRealVar::errorVar() const
288 {
289  TString name(GetName()), title(GetTitle()) ;
290  name.Append("err") ;
291  title.Append(" Error") ;
292 
293  return new RooErrorVar(name,title,*this) ;
294 }
295 
296 
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Returns true if variable has a binning with 'name'
300 
301 Bool_t RooRealVar::hasBinning(const char* name) const
302 {
303  return sharedProp()->_altBinning.FindObject(name) ? kTRUE : kFALSE ;
304 }
305 
306 
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Return binning definition with name. If binning with 'name' is not found it is created
310 /// on the fly as a clone of the default binning if createOnTheFly is true, otherwise
311 /// a reference to the default binning is returned. If verbose is true a message
312 /// is printed if a binning is created on the fly.
313 
314 const RooAbsBinning& RooRealVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly) const
315 {
316  return const_cast<RooRealVar*>(this)->getBinning(name, verbose, createOnTheFly) ;
317 }
318 
319 
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Return binning definition with name. If binning with 'name' is not found it is created
323 /// on the fly as a clone of the default binning if createOnTheFly is true, otherwise
324 /// a reference to the default binning is returned. If verbose is true a message
325 /// is printed if a binning is created on the fly.
326 
327 RooAbsBinning& RooRealVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly)
328 {
329  // Return default (normalization) binning and range if no name is specified
330  if (name==0) {
331  return *_binning ;
332  }
333 
334  // Check if non-shared binning with this name has been created already
335  RooAbsBinning* binning = (RooAbsBinning*) _altNonSharedBinning.FindObject(name) ;
336  if (binning) {
337  return *binning ;
338  }
339 
340  // Check if binning with this name has been created already
341  binning = (RooAbsBinning*) (sharedProp()->_altBinning).FindObject(name) ;
342  if (binning) {
343  return *binning ;
344  }
345 
346 
347  // Return default binning if requested binning doesn't exist
348  if (!createOnTheFly) {
349  return *_binning ;
350  }
351 
352  // Create a new RooRangeBinning with this name with default range
353  binning = new RooRangeBinning(getMin(),getMax(),name) ;
354  if (verbose) {
355  coutI(Eval) << "RooRealVar::getBinning(" << GetName() << ") new range named '"
356  << name << "' created with default bounds" << endl ;
357  }
358  sharedProp()->_altBinning.Add(binning) ;
359 
360  return *binning ;
361 }
362 
363 ////////////////////////////////////////////////////////////////////////////////
364 /// Get a list of all binning names. An empty name implies the default binning and
365 /// a NULL pointer should be passed to getBinning in this case.
366 
367 std::list<std::string> RooRealVar::getBinningNames() const
368 {
369  std::list<std::string> binningNames;
370  if (_binning) {
371  binningNames.push_back("");
372  }
373 
374  RooFIter iter = _altNonSharedBinning.fwdIterator();
375  const RooAbsArg* binning = 0;
376  while((binning = iter.next())) {
377  const char* name = binning->GetName();
378  binningNames.push_back(string(name));
379  }
380  iter = sharedProp()->_altBinning.fwdIterator();
381  binning = 0;
382  while((binning = iter.next())) {
383  const char* name = binning->GetName();
384  binningNames.push_back(string(name));
385  }
386  return binningNames;
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Add given binning under name 'name' with this variable. If name is null
391 /// the binning is installed as the default binning
392 
393 void RooRealVar::setBinning(const RooAbsBinning& binning, const char* name)
394 {
395  // Process insert hooks required for parameterized binnings
396  if (!name) {
397  RooAbsBinning* newBinning = binning.clone() ;
398  if (_binning) {
399  _binning->removeHook(*this) ;
400  delete _binning ;
401  }
402  newBinning->insertHook(*this) ;
403  _binning = newBinning ;
404  } else {
405 
406  RooLinkedList* altBinning = binning.isShareable() ? &(sharedProp()->_altBinning) : &_altNonSharedBinning ;
407 
408  RooAbsBinning* newBinning = binning.clone() ;
409 
410  // Remove any old binning with this name
411  RooAbsBinning* oldBinning = (RooAbsBinning*) altBinning->FindObject(name) ;
412  if (oldBinning) {
413  altBinning->Remove(oldBinning) ;
414  oldBinning->removeHook(*this) ;
415  delete oldBinning ;
416  }
417 
418  // Insert new binning in list of alternative binnings
419  newBinning->SetName(name) ;
420  newBinning->SetTitle(name) ;
421  newBinning->insertHook(*this) ;
422  altBinning->Add(newBinning) ;
423 
424  }
425 
426 
427 }
428 
429 
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Set minimum of name range to given value. If name is null
433 /// minimum of default range is set
434 
435 void RooRealVar::setMin(const char* name, Double_t value)
436 {
437  // Set new minimum of fit range
438  RooAbsBinning& binning = getBinning(name,kTRUE,kTRUE) ;
439 
440  // Check if new limit is consistent
441  if (value >= getMax()) {
442  coutW(InputArguments) << "RooRealVar::setMin(" << GetName()
443  << "): Proposed new fit min. larger than max., setting min. to max." << endl ;
444  binning.setMin(getMax()) ;
445  } else {
446  binning.setMin(value) ;
447  }
448 
449  // Clip current value in window if it fell out
450  if (!name) {
451  Double_t clipValue ;
452  if (!inRange(_value,0,&clipValue)) {
453  setVal(clipValue) ;
454  }
455  }
456 
457  setShapeDirty() ;
458 }
459 
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 /// Set maximum of name range to given value. If name is null
463 /// maximum of default range is set
464 
465 void RooRealVar::setMax(const char* name, Double_t value)
466 {
467  // Set new maximum of fit range
468  RooAbsBinning& binning = getBinning(name,kTRUE,kTRUE) ;
469 
470  // Check if new limit is consistent
471  if (value < getMin()) {
472  coutW(InputArguments) << "RooRealVar::setMax(" << GetName()
473  << "): Proposed new fit max. smaller than min., setting max. to min." << endl ;
474  binning.setMax(getMin()) ;
475  } else {
476  binning.setMax(value) ;
477  }
478 
479  // Clip current value in window if it fell out
480  if (!name) {
481  Double_t clipValue ;
482  if (!inRange(_value,0,&clipValue)) {
483  setVal(clipValue) ;
484  }
485  }
486 
487  setShapeDirty() ;
488 }
489 
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 /// Set range named 'name to [min,max]. If name is null
493 /// range of default range is adjusted. If no range with
494 /// 'name' exists it is created on the fly
495 
496 void RooRealVar::setRange(const char* name, Double_t min, Double_t max)
497 {
498  Bool_t exists = name ? (sharedProp()->_altBinning.FindObject(name)?kTRUE:kFALSE) : kTRUE ;
499 
500  // Set new fit range
501  RooAbsBinning& binning = getBinning(name,kFALSE,kTRUE) ;
502 
503  // Check if new limit is consistent
504  if (min>max) {
505  coutW(InputArguments) << "RooRealVar::setRange(" << GetName()
506  << "): Proposed new fit max. smaller than min., setting max. to min." << endl ;
507  binning.setRange(min,min) ;
508  } else {
509  binning.setRange(min,max) ;
510  }
511 
512  if (!exists) {
513  coutI(Eval) << "RooRealVar::setRange(" << GetName()
514  << ") new range named '" << name << "' created with bounds ["
515  << min << "," << max << "]" << endl ;
516  }
517 
518  setShapeDirty() ;
519 }
520 
521 
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Create or modify a parameterized range named 'name' that has external functions
525 /// min and max parameterizing its boundaries.
526 
527 void RooRealVar::setRange(const char* name, RooAbsReal& min, RooAbsReal& max)
528 {
529  RooParamBinning pb(min,max,100) ;
530  setBinning(pb,name) ;
531 }
532 
533 
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 /// Read object contents from given stream
537 
538 Bool_t RooRealVar::readFromStream(istream& is, Bool_t compact, Bool_t verbose)
539 {
540  TString token,errorPrefix("RooRealVar::readFromStream(") ;
541  errorPrefix.Append(GetName()) ;
542  errorPrefix.Append(")") ;
543  RooStreamParser parser(is,errorPrefix) ;
544  Double_t value(0) ;
545 
546  if (compact) {
547  // Compact mode: Read single token
548  if (parser.readDouble(value,verbose)) return kTRUE ;
549  if (isValidReal(value,verbose)) {
550  setVal(value) ;
551  return kFALSE ;
552  } else {
553  return kTRUE ;
554  }
555 
556  } else {
557  // Extended mode: Read multiple tokens on a single line
558  Bool_t haveValue(kFALSE) ;
559  Bool_t haveConstant(kFALSE) ;
560  removeError() ;
561  removeAsymError() ;
562 
563  Bool_t reprocessToken = kFALSE ;
564  while(1) {
565  if (parser.atEOL() || parser.atEOF()) break ;
566 
567  if (!reprocessToken) {
568  token=parser.readToken() ;
569  }
570  reprocessToken = kFALSE ;
571 
572  if (!token.CompareTo("+")) {
573 
574  // Expect +/- as 3-token sequence
575  if (parser.expectToken("/",kTRUE) ||
576  parser.expectToken("-",kTRUE)) {
577  break ;
578  }
579 
580  // Next token is error or asymmetric error, check if first char of token is a '('
581  TString tmp = parser.readToken() ;
582  if (tmp.CompareTo("(")) {
583  // Symmetric error, convert token do double
584 
585  Double_t error ;
586  parser.convertToDouble(tmp,error) ;
587  setError(error) ;
588 
589  } else {
590  // Have error
591  Double_t asymErrLo=0., asymErrHi=0.;
592  if (parser.readDouble(asymErrLo,kTRUE) ||
593  parser.expectToken(",",kTRUE) ||
594  parser.readDouble(asymErrHi,kTRUE) ||
595  parser.expectToken(")",kTRUE)) break ;
596  setAsymError(asymErrLo,asymErrHi) ;
597  }
598 
599  } else if (!token.CompareTo("C")) {
600 
601  // Set constant
602  setConstant(kTRUE) ;
603  haveConstant = kTRUE ;
604 
605  } else if (!token.CompareTo("P")) {
606 
607  // Next tokens are plot limits
608  Double_t plotMin(0), plotMax(0) ;
609  Int_t plotBins(0) ;
610  if (parser.expectToken("(",kTRUE) ||
611  parser.readDouble(plotMin,kTRUE) ||
612  parser.expectToken("-",kTRUE) ||
613  parser.readDouble(plotMax,kTRUE) ||
614  parser.expectToken(":",kTRUE) ||
615  parser.readInteger(plotBins,kTRUE) ||
616  parser.expectToken(")",kTRUE)) break ;
617 // setPlotRange(plotMin,plotMax) ;
618  coutW(Eval) << "RooRealVar::readFromStrem(" << GetName()
619  << ") WARNING: plot range deprecated, removed P(...) token" << endl ;
620 
621  } else if (!token.CompareTo("F")) {
622 
623  // Next tokens are fit limits
624  Double_t fitMin, fitMax ;
625  Int_t fitBins ;
626  if (parser.expectToken("(",kTRUE) ||
627  parser.readDouble(fitMin,kTRUE) ||
628  parser.expectToken("-",kTRUE) ||
629  parser.readDouble(fitMax,kTRUE) ||
630  parser.expectToken(":",kTRUE) ||
631  parser.readInteger(fitBins,kTRUE) ||
632  parser.expectToken(")",kTRUE)) break ;
633  //setBins(fitBins) ;
634  //setRange(fitMin,fitMax) ;
635  coutW(Eval) << "RooRealVar::readFromStream(" << GetName()
636  << ") WARNING: F(lo-hi:bins) token deprecated, use L(lo-hi) B(bins)" << endl ;
637  if (!haveConstant) setConstant(kFALSE) ;
638 
639  } else if (!token.CompareTo("L")) {
640 
641  // Next tokens are fit limits
642  Double_t fitMin = 0.0, fitMax = 0.0;
643 // Int_t fitBins ;
644  if (parser.expectToken("(",kTRUE) ||
645  parser.readDouble(fitMin,kTRUE) ||
646  parser.expectToken("-",kTRUE) ||
647  parser.readDouble(fitMax,kTRUE) ||
648  parser.expectToken(")",kTRUE)) break ;
649  setRange(fitMin,fitMax) ;
650  if (!haveConstant) setConstant(kFALSE) ;
651 
652  } else if (!token.CompareTo("B")) {
653 
654  // Next tokens are fit limits
655  Int_t fitBins = 0;
656  if (parser.expectToken("(",kTRUE) ||
657  parser.readInteger(fitBins,kTRUE) ||
658  parser.expectToken(")",kTRUE)) break ;
659  setBins(fitBins) ;
660 
661  } else {
662  // Token is value
663  if (parser.convertToDouble(token,value)) { parser.zapToEnd() ; break ; }
664  haveValue = kTRUE ;
665  // Defer value assignment to end
666  }
667  }
668  if (haveValue) setVal(value) ;
669  return kFALSE ;
670  }
671 }
672 
673 
674 ////////////////////////////////////////////////////////////////////////////////
675 /// Write object contents to given stream
676 
677 void RooRealVar::writeToStream(ostream& os, Bool_t compact) const
678 {
679  if (compact) {
680  // Write value only
681  os << getVal() ;
682  } else {
683 
684  // Write value with error (if not zero)
685  if (_printScientific) {
686  char fmtVal[16], fmtErr[16] ;
687  snprintf(fmtVal,16,"%%.%de",_printSigDigits) ;
688  snprintf(fmtErr,16,"%%.%de",(_printSigDigits+1)/2) ;
689  if (_value>=0) os << " " ;
690  os << Form(fmtVal,_value) ;
691 
692  if (hasAsymError()) {
693  os << " +/- (" << Form(fmtErr,getAsymErrorLo())
694  << ", " << Form(fmtErr,getAsymErrorHi()) << ")" ;
695  } else if (hasError()) {
696  os << " +/- " << Form(fmtErr,getError()) ;
697  }
698 
699  os << " " ;
700  } else {
701  TString* tmp = format(_printSigDigits,"EFA") ;
702  os << tmp->Data() << " " ;
703  delete tmp ;
704  }
705 
706  // Append limits if not constants
707  if (isConstant()) {
708  os << "C " ;
709  }
710 
711  // Append fit limits
712  os << "L(" ;
713  if(hasMin()) {
714  os << getMin();
715  }
716  else {
717  os << "-INF";
718  }
719  if(hasMax()) {
720  os << " - " << getMax() ;
721  }
722  else {
723  os << " - +INF";
724  }
725  os << ") " ;
726 
727  if (getBins()!=100) {
728  os << "B(" << getBins() << ") " ;
729  }
730 
731  // Add comment with unit, if unit exists
732  if (!_unit.IsNull())
733  os << "// [" << getUnit() << "]" ;
734  }
735 }
736 
737 
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 /// Print value of variable
741 
742 void RooRealVar::printValue(ostream& os) const
743 {
744  os << getVal() ;
745 
746  if(hasError() && !hasAsymError()) {
747  os << " +/- " << getError() ;
748  } else if (hasAsymError()) {
749  os << " +/- (" << getAsymErrorLo() << "," << getAsymErrorHi() << ")" ;
750  }
751 
752 }
753 
754 
755 ////////////////////////////////////////////////////////////////////////////////
756 /// Print extras of variable: (asymmetric) error, constant flag, limits and binning
757 
758 void RooRealVar::printExtras(ostream& os) const
759 {
760  // Append limits if not constants
761  if (isConstant()) {
762  os << "C " ;
763  }
764 
765  // Append fit limits
766  os << " L(" ;
767  if(hasMin()) {
768  os << getMin();
769  }
770  else {
771  os << "-INF";
772  }
773  if(hasMax()) {
774  os << " - " << getMax() ;
775  }
776  else {
777  os << " - +INF";
778  }
779  os << ") " ;
780 
781  if (getBins()!=100) {
782  os << "B(" << getBins() << ") " ;
783  }
784 
785  // Add comment with unit, if unit exists
786  if (!_unit.IsNull())
787  os << "// [" << getUnit() << "]" ;
788 
789 // cout << " _value = " << &_value << " _error = " << &_error ;
790 
791 
792 }
793 
794 
795 ////////////////////////////////////////////////////////////////////////////////
796 /// Mapping of Print() option string to RooPrintable contents specifications
797 
798 Int_t RooRealVar::defaultPrintContents(Option_t* opt) const
799 {
800  if (opt && TString(opt)=="I") {
801  return kName|kClassName|kValue ;
802  }
803  return kName|kClassName|kValue|kExtras ;
804 }
805 
806 
807 ////////////////////////////////////////////////////////////////////////////////
808 /// Detailed printing interface
809 
810 void RooRealVar::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
811 {
812  RooAbsRealLValue::printMultiline(os,contents,verbose,indent);
813  os << indent << "--- RooRealVar ---" << endl;
814  TString unit(_unit);
815  if(!unit.IsNull()) unit.Prepend(' ');
816  os << indent << " Error = " << getError() << unit << endl;
817 }
818 
819 
820 
821 ////////////////////////////////////////////////////////////////////////////////
822 /// Format contents of RooRealVar for pretty printing on RooPlot
823 /// parameter boxes. This function processes the named arguments
824 /// taken by paramOn() and translates them to an option string
825 /// parsed by RooRealVar::format(Int_t sigDigits, const char *options)
826 
827 TString* RooRealVar::format(const RooCmdArg& formatArg) const
828 {
829  RooCmdArg tmp(formatArg) ;
830  tmp.setProcessRecArgs(kTRUE) ;
831 
832  RooCmdConfig pc(Form("RooRealVar::format(%s)",GetName())) ;
833  pc.defineString("what","FormatArgs",0,"") ;
834  pc.defineInt("autop","FormatArgs::AutoPrecision",0,2) ;
835  pc.defineInt("fixedp","FormatArgs::FixedPrecision",0,2) ;
836  pc.defineInt("tlatex","FormatArgs::TLatexStyle",0,0) ;
837  pc.defineInt("latex","FormatArgs::LatexStyle",0,0) ;
838  pc.defineInt("latext","FormatArgs::LatexTableStyle",0,0) ;
839  pc.defineInt("verbn","FormatArgs::VerbatimName",0,0) ;
840  pc.defineMutex("FormatArgs::TLatexStyle","FormatArgs::LatexStyle","FormatArgs::LatexTableStyle") ;
841  pc.defineMutex("FormatArgs::AutoPrecision","FormatArgs::FixedPrecision") ;
842 
843  // Process & check varargs
844  pc.process(tmp) ;
845  if (!pc.ok(kTRUE)) {
846  return 0 ;
847  }
848 
849  // Extract values from named arguments
850  TString options ;
851  options = pc.getString("what") ;
852 
853  if (pc.getInt("tlatex")) {
854  options += "L" ;
855  } else if (pc.getInt("latex")) {
856  options += "X" ;
857  } else if (pc.getInt("latext")) {
858  options += "Y" ;
859  }
860 
861  if (pc.getInt("verbn")) options += "V" ;
862  Int_t sigDigits = 2 ;
863  if (pc.hasProcessed("FormatArgs::AutoPrecision")) {
864  options += "P" ;
865  sigDigits = pc.getInt("autop") ;
866  } else if (pc.hasProcessed("FormatArgs::FixedPrecision")) {
867  options += "F" ;
868  sigDigits = pc.getInt("fixedp") ;
869  }
870 
871  return format(sigDigits,options) ;
872 }
873 
874 
875 
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// Format numeric value of RooRealVar and its error in a variety of ways
879 ///
880 /// To control what is shown use the following options
881 /// N = show name
882 /// H = hide value
883 /// E = show error
884 /// A = show asymmetric error instead of parabolic error (if available)
885 /// U = show unit
886 ///
887 /// To control how it is shown use these options
888 /// L = TLatex mode
889 /// X = Latex mode
890 /// Y = Latex table mode ( '=' replaced by '&' )
891 /// V = Make name \\verbatim in Latex mode
892 /// P = use error to control shown precision
893 /// F = force fixed precision
894 ///
895 
896 TString *RooRealVar::format(Int_t sigDigits, const char *options) const
897 {
898  //cout << "format = " << options << endl ;
899 
900  // parse the options string
901  TString opts(options);
902  opts.ToLower();
903  Bool_t showName= opts.Contains("n");
904  Bool_t hideValue= opts.Contains("h");
905  Bool_t showError= opts.Contains("e");
906  Bool_t showUnit= opts.Contains("u");
907  Bool_t tlatexMode= opts.Contains("l");
908  Bool_t latexMode= opts.Contains("x");
909  Bool_t latexTableMode = opts.Contains("y") ;
910  Bool_t latexVerbatimName = opts.Contains("v") ;
911 
912  if (latexTableMode) latexMode = kTRUE ;
913  Bool_t asymError= opts.Contains("a") ;
914  Bool_t useErrorForPrecision= (((showError && hasError(kFALSE) && !isConstant()) || opts.Contains("p")) && !opts.Contains("f")) ;
915  // calculate the precision to use
916  if(sigDigits < 1) sigDigits= 1;
917  Int_t leadingDigitVal = 0;
918  if (useErrorForPrecision) {
919  leadingDigitVal = (Int_t)floor(log10(fabs(_error+1e-10)));
920  if (_value==0&&_error==0) leadingDigitVal=0 ;
921  } else {
922  leadingDigitVal = (Int_t)floor(log10(fabs(_value+1e-10)));
923  if (_value==0) leadingDigitVal=0 ;
924  }
925  Int_t leadingDigitErr= (Int_t)floor(log10(fabs(_error+1e-10)));
926  Int_t whereVal= leadingDigitVal - sigDigits + 1;
927  Int_t whereErr= leadingDigitErr - sigDigits + 1;
928  char fmtVal[16], fmtErr[16];
929 
930  if (_value<0) whereVal -= 1 ;
931  snprintf(fmtVal,16,"%%.%df", whereVal < 0 ? -whereVal : 0);
932  snprintf(fmtErr,16,"%%.%df", whereErr < 0 ? -whereErr : 0);
933  TString *text= new TString();
934  if(latexMode) text->Append("$");
935  // begin the string with "<name> = " if requested
936  if(showName) {
937  if (latexTableMode && latexVerbatimName) {
938  text->Append("\\verb+") ;
939  }
940  text->Append(getPlotLabel());
941  if (latexVerbatimName) text->Append("+") ;
942 
943  if (!latexTableMode) {
944  text->Append(" = ");
945  } else {
946  text->Append(" $ & $ ");
947  }
948  }
949 
950  // Add leading space if value is positive
951  if (_value>=0) text->Append(" ") ;
952 
953  // append our value if requested
954  char buffer[256];
955  if(!hideValue) {
956  chopAt(_value, whereVal);
957  snprintf(buffer, 256,fmtVal, _value);
958  text->Append(buffer);
959  }
960 
961  // append our error if requested and this variable is not constant
962  if(hasError(kFALSE) && showError && !(asymError && hasAsymError(kFALSE))) {
963  if(tlatexMode) {
964  text->Append(" #pm ");
965  }
966  else if(latexMode) {
967  text->Append("\\pm ");
968  }
969  else {
970  text->Append(" +/- ");
971  }
972  snprintf(buffer, 256,fmtErr, getError());
973  text->Append(buffer);
974  }
975 
976  if (asymError && hasAsymError() && showError) {
977  if(tlatexMode) {
978  text->Append(" #pm ");
979  text->Append("_{") ;
980  snprintf(buffer, 256,fmtErr, getAsymErrorLo());
981  text->Append(buffer);
982  text->Append("}^{+") ;
983  snprintf(buffer, 256,fmtErr, getAsymErrorHi());
984  text->Append(buffer);
985  text->Append("}") ;
986  }
987  else if(latexMode) {
988  text->Append("\\pm ");
989  text->Append("_{") ;
990  snprintf(buffer, 256,fmtErr, getAsymErrorLo());
991  text->Append(buffer);
992  text->Append("}^{+") ;
993  snprintf(buffer, 256,fmtErr, getAsymErrorHi());
994  text->Append(buffer);
995  text->Append("}") ;
996  }
997  else {
998  text->Append(" +/- ");
999  text->Append(" (") ;
1000  snprintf(buffer, 256, fmtErr, getAsymErrorLo());
1001  text->Append(buffer);
1002  text->Append(", ") ;
1003  snprintf(buffer, 256, fmtErr, getAsymErrorHi());
1004  text->Append(buffer);
1005  text->Append(")") ;
1006  }
1007 
1008  }
1009 
1010  // append our units if requested
1011  if(!_unit.IsNull() && showUnit) {
1012  text->Append(' ');
1013  text->Append(_unit);
1014  }
1015  if(latexMode) text->Append("$");
1016  return text;
1017 }
1018 
1019 
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Utility to calculate number of decimals to show
1023 /// based on magnitude of error
1024 
1025 Double_t RooRealVar::chopAt(Double_t what, Int_t where) const
1026 {
1027  Double_t scale= pow(10.0,where);
1028  Int_t trunc= (Int_t)floor(what/scale + 0.5);
1029  return (Double_t)trunc*scale;
1030 }
1031 
1032 
1033 
1034 ////////////////////////////////////////////////////////////////////////////////
1035 /// Overload RooAbsReal::attachToTree to also attach
1036 /// branches for errors and/or asymmetric errors
1037 /// attribute StoreError and/or StoreAsymError are set
1038 
1039 void RooRealVar::attachToVStore(RooVectorDataStore& vstore)
1040 {
1041  // Follow usual procedure for value
1042 
1043  if (getAttribute("StoreError") || getAttribute("StoreAsymError") || vstore.isFullReal(this) ) {
1044 
1045  RooVectorDataStore::RealFullVector* rfv = vstore.addRealFull(this) ;
1046  rfv->setBuffer(this,&_value);
1047 
1048  _batchData.attachForeignStorage(rfv->data());
1049 
1050  // Attach/create additional branch for error
1051  if (getAttribute("StoreError") || vstore.hasError(this) ) {
1052  rfv->setErrorBuffer(&_error) ;
1053  }
1054 
1055  // Attach/create additional branches for asymmetric error
1056  if (getAttribute("StoreAsymError") || vstore.hasAsymError(this)) {
1057  rfv->setAsymErrorBuffer(&_asymErrLo,&_asymErrHi) ;
1058  }
1059 
1060  } else {
1061 
1062  RooAbsReal::attachToVStore(vstore) ;
1063 
1064  }
1065 }
1066 
1067 
1068 
1069 ////////////////////////////////////////////////////////////////////////////////
1070 /// Overload RooAbsReal::attachToTree to also attach
1071 /// branches for errors and/or asymmetric errors
1072 /// attribute StoreError and/or StoreAsymError are set
1073 
1074 void RooRealVar::attachToTree(TTree& t, Int_t bufSize)
1075 {
1076  // Follow usual procedure for value
1077  RooAbsReal::attachToTree(t,bufSize) ;
1078 // cout << "RooRealVar::attachToTree(" << this << ") name = " << GetName()
1079 // << " StoreError = " << (getAttribute("StoreError")?"T":"F") << endl ;
1080 
1081  // Attach/create additional branch for error
1082  if (getAttribute("StoreError")) {
1083  TString errName(GetName()) ;
1084  errName.Append("_err") ;
1085  TBranch* branch = t.GetBranch(errName) ;
1086  if (branch) {
1087  t.SetBranchAddress(errName,&_error) ;
1088  } else {
1089  TString format2(errName);
1090  format2.Append("/D");
1091  t.Branch(errName, &_error, (const Text_t*)format2, bufSize);
1092  }
1093  }
1094 
1095  // Attach/create additional branches for asymmetric error
1096  if (getAttribute("StoreAsymError")) {
1097  TString loName(GetName()) ;
1098  loName.Append("_aerr_lo") ;
1099  TBranch* lobranch = t.GetBranch(loName) ;
1100  if (lobranch) {
1101  t.SetBranchAddress(loName,&_asymErrLo) ;
1102  } else {
1103  TString format2(loName);
1104  format2.Append("/D");
1105  t.Branch(loName, &_asymErrLo, (const Text_t*)format2, bufSize);
1106  }
1107 
1108  TString hiName(GetName()) ;
1109  hiName.Append("_aerr_hi") ;
1110  TBranch* hibranch = t.GetBranch(hiName) ;
1111  if (hibranch) {
1112  t.SetBranchAddress(hiName,&_asymErrHi) ;
1113  } else {
1114  TString format2(hiName);
1115  format2.Append("/D");
1116  t.Branch(hiName, &_asymErrHi, (const Text_t*)format2, bufSize);
1117  }
1118  }
1119 }
1120 
1121 
1122 ////////////////////////////////////////////////////////////////////////////////
1123 /// Overload RooAbsReal::fillTreeBranch to also
1124 /// fill tree branches with (asymmetric) errors
1125 /// if requested.
1126 
1127 void RooRealVar::fillTreeBranch(TTree& t)
1128 {
1129  // First determine if branch is taken
1130  TString cleanName(cleanBranchName()) ;
1131  TBranch* valBranch = t.GetBranch(cleanName) ;
1132  if (!valBranch) {
1133  coutE(Eval) << "RooAbsReal::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree" << endl ;
1134  assert(0) ;
1135  }
1136  valBranch->Fill() ;
1137 
1138  if (getAttribute("StoreError")) {
1139  TString errName(GetName()) ;
1140  errName.Append("_err") ;
1141  TBranch* errBranch = t.GetBranch(errName) ;
1142  if (errBranch) errBranch->Fill() ;
1143  }
1144 
1145  if (getAttribute("StoreAsymError")) {
1146  TString loName(GetName()) ;
1147  loName.Append("_aerr_lo") ;
1148  TBranch* loBranch = t.GetBranch(loName) ;
1149  if (loBranch) loBranch->Fill() ;
1150 
1151  TString hiName(GetName()) ;
1152  hiName.Append("_aerr_hi") ;
1153  TBranch* hiBranch = t.GetBranch(hiName) ;
1154  if (hiBranch) hiBranch->Fill() ;
1155  }
1156 }
1157 
1158 
1159 
1160 ////////////////////////////////////////////////////////////////////////////////
1161 /// Copy the cached value of another RooAbsArg to our cache
1162 /// Warning: This function copies the cached values of source,
1163 /// it is the callers responsibility to make sure the cache is clean
1164 
1165 void RooRealVar::copyCache(const RooAbsArg* source, Bool_t valueOnly, Bool_t setValDirty)
1166 {
1167  // Follow usual procedure for valueklog
1168  RooAbsReal::copyCache(source,valueOnly,setValDirty) ;
1169 
1170  if (valueOnly) return ;
1171 
1172  // Copy error too, if source has one
1173  RooRealVar* other = dynamic_cast<RooRealVar*>(const_cast<RooAbsArg*>(source)) ;
1174  if (other) {
1175  // Copy additional error value
1176  _error = other->_error ;
1177  _asymErrLo = other->_asymErrLo ;
1178  _asymErrHi = other->_asymErrHi ;
1179  }
1180 }
1181 
1182 
1183 
1184 ////////////////////////////////////////////////////////////////////////////////
1185 /// Stream an object of class RooRealVar.
1186 
1187 void RooRealVar::Streamer(TBuffer &R__b)
1188 {
1189  UInt_t R__s, R__c;
1190  if (R__b.IsReading()) {
1191 
1192  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1193  RooAbsRealLValue::Streamer(R__b);
1194  if (R__v==1) {
1195  coutI(Eval) << "RooRealVar::Streamer(" << GetName() << ") converting version 1 data format" << endl ;
1196  Double_t fitMin, fitMax ;
1197  Int_t fitBins ;
1198  R__b >> fitMin;
1199  R__b >> fitMax;
1200  R__b >> fitBins;
1201  _binning = new RooUniformBinning(fitMin,fitMax,fitBins) ;
1202  }
1203  R__b >> _error;
1204  R__b >> _asymErrLo;
1205  R__b >> _asymErrHi;
1206  if (R__v>=2) {
1207  R__b >> _binning;
1208  }
1209  if (R__v==3) {
1210  R__b >> _sharedProp ;
1211  _sharedProp = (RooRealVarSharedProperties*) _sharedPropList.registerProperties(_sharedProp,kFALSE) ;
1212  }
1213  if (R__v>=4) {
1214  RooRealVarSharedProperties* tmpSharedProp = new RooRealVarSharedProperties() ;
1215  tmpSharedProp->Streamer(R__b) ;
1216  if (!(_nullProp==*tmpSharedProp)) {
1217  _sharedProp = (RooRealVarSharedProperties*) _sharedPropList.registerProperties(tmpSharedProp,kFALSE) ;
1218  } else {
1219  delete tmpSharedProp ;
1220  _sharedProp = 0 ;
1221  }
1222  }
1223 
1224  R__b.CheckByteCount(R__s, R__c, RooRealVar::IsA());
1225 
1226  } else {
1227 
1228  R__c = R__b.WriteVersion(RooRealVar::IsA(), kTRUE);
1229  RooAbsRealLValue::Streamer(R__b);
1230  R__b << _error;
1231  R__b << _asymErrLo;
1232  R__b << _asymErrHi;
1233  R__b << _binning;
1234  if (_sharedProp) {
1235  _sharedProp->Streamer(R__b) ;
1236  } else {
1237  _nullProp.Streamer(R__b) ;
1238  }
1239  R__b.SetByteCount(R__c, kTRUE);
1240 
1241  }
1242 }
1243 
1244 
1245 
1246 ////////////////////////////////////////////////////////////////////////////////
1247 /// No longer used?
1248 
1249 void RooRealVar::deleteSharedProperties()
1250 {
1251  if (_sharedProp) {
1252  _sharedPropList.unregisterProperties(_sharedProp) ;
1253  _sharedProp = 0 ;
1254  }
1255 }
1256 
1257 
1258 ////////////////////////////////////////////////////////////////////////////////
1259 /// If true, contents of RooRealVars will be printed in scientific notation
1260 
1261 void RooRealVar::printScientific(Bool_t flag)
1262 {
1263  _printScientific = flag ;
1264 }
1265 
1266 
1267 ////////////////////////////////////////////////////////////////////////////////
1268 /// Set number of digits to show when printing RooRealVars
1269 
1270 void RooRealVar::printSigDigits(Int_t ndig)
1271 {
1272  _printSigDigits = ndig>1?ndig:1 ;
1273 }