/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 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 (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// RooLinearVar is the most general form of a derived real-valued object that can
// be used by RooRealIntegral to integrate over. The requirements for this are
//
//          - Can be modified directly (i.e. invertible formula)
//          - Jacobian term in integral is constant (but not necessarily 1)
//
// This class implements the most general form that satisfy these requirement
// 
//    RLV = (slope)*x + (offset)
//
// X is required to be a RooRealVar to meet the invertibility criterium
// (slope) and (offset) is are RooAbsReals, but may not overlap with x,
// i.e. x may not be a server of (slope) and (offset)
//
// In the context of a dataset, (slope) may not contain any real-valued dependents
// (satisfied constant Jacobian requirement). This check cannot be enforced at
// construction time, but can be performed at run time through the isJacobianOK(depList)
// member function.
//
//

#include "RooFit.h"
#include "Riostream.h"

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "TClass.h"
#include "TObjString.h"
#include "TTree.h"
#include "RooLinearVar.h"
#include "RooStreamParser.h"
#include "RooArgSet.h"
#include "RooRealVar.h"
#include "RooNumber.h"
#include "RooBinning.h"
#include "RooMsgService.h"



using namespace std;

ClassImp(RooLinearVar)


//_____________________________________________________________________________
RooLinearVar::RooLinearVar(const char *name, const char *title, RooAbsRealLValue& variable, 
			   const RooAbsReal& slope, const RooAbsReal& offs, const char *unit) :
  RooAbsRealLValue(name, title, unit), 
  _binning(variable.getBinning(),slope.getVal(),offs.getVal()),
  _var("var","variable",this,variable,kTRUE,kTRUE),
  _slope("slope","slope",this,(RooAbsReal&)slope),
  _offset("offset","offset",this,(RooAbsReal&)offs)
{
  // Constructor with RooAbsRealLValue variable and RooAbsReal slope and offset

  // Slope and offset may not depend on variable
  if (slope.dependsOnValue(variable) || offs.dependsOnValue(variable)) {
    coutE(InputArguments) << "RooLinearVar::RooLinearVar(" << GetName() 
			  << "): ERROR, slope(" << slope.GetName() << ") and offset(" 
			  << offs.GetName() << ") may not depend on variable(" 
			  << variable.GetName() << ")" << endl ;
    assert(0) ;
  }

  // Initial plot range and number of bins from dependent variable
//   setPlotRange(variable.getPlotMin()*_slope + _offset,
//                variable.getPlotMax()*_slope + _offset) ;
//   setPlotBins(variable.getPlotBins()) ;
	       
}  



//_____________________________________________________________________________
RooLinearVar::RooLinearVar(const RooLinearVar& other, const char* name) :
  RooAbsRealLValue(other,name), 
  _binning(other._binning),
  _var("var",this,other._var),
  _slope("slope",this,other._slope),
  _offset("offset",this,other._offset)
{
  // Copy constructor
}



//_____________________________________________________________________________
RooLinearVar::~RooLinearVar() 
{
  // Destructor

  _altBinning.Delete() ;
}



//_____________________________________________________________________________
Double_t RooLinearVar::evaluate() const
{
  // Calculate current value of this object  

  return _offset + _var * _slope ;
}



//_____________________________________________________________________________
void RooLinearVar::setVal(Double_t value) 
{
  // Assign given value to linear transformation: sets input variable to (value-offset)/slope
  // If slope is zerom an error message is printed and no assignment is made

  //cout << "RooLinearVar::setVal(" << GetName() << "): new value = " << value << endl ;

  // Prevent DIV0 problems
  if (_slope == 0.) {
    coutE(Eval) << "RooLinearVar::setVal(" << GetName() << "): ERROR: slope is zero, cannot invert relation" << endl ;
    return ;
  }

  // Invert formula 'value = offset + slope*var'
  ((RooRealVar&)_var.arg()).setVal((value - _offset) / _slope) ;

}



//_____________________________________________________________________________
Bool_t RooLinearVar::isJacobianOK(const RooArgSet& depList) const
{
  // Returns true if Jacobian term associated with current
  // expression tree is indeed constant.

  if (!((RooAbsRealLValue&)_var.arg()).isJacobianOK(depList)) {
    return kFALSE ;
  }

  // Check if jacobian has no real-valued dependents
  RooAbsArg* arg ;
  TIterator* dIter = depList.createIterator() ;
  while ((arg=(RooAbsArg*)dIter->Next())) {
    if (arg->IsA()->InheritsFrom(RooAbsReal::Class())) {
      if (_slope.arg().dependsOnValue(*arg)) {
// 	cout << "RooLinearVar::isJacobianOK(" << GetName() << ") return kFALSE because slope depends on value of " << arg->GetName() << endl ;
	return kFALSE ;
      }
    }
  }
  delete dIter ;
//   cout << "RooLinearVar::isJacobianOK(" << GetName() << ") return kTRUE" << endl ;
  return kTRUE ;
}



//_____________________________________________________________________________
Double_t RooLinearVar::jacobian() const 
{
  // Return value of Jacobian associated with the transformation

  return _slope*((RooAbsRealLValue&)_var.arg()).jacobian() ;
}



//_____________________________________________________________________________
Bool_t RooLinearVar::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/) 
{
  // Read object contents from stream
  return kTRUE ;
}



//_____________________________________________________________________________
void RooLinearVar::writeToStream(ostream& os, Bool_t compact) const
{
  // Write object contents to stream

  if (compact) {
    os << getVal() ;
  } else {
    os << _slope.arg().GetName() << " * " << _var.arg().GetName() << " + " << _offset.arg().GetName() ;
  }
}



//_____________________________________________________________________________
 RooAbsBinning& RooLinearVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly) 
{
  // Retrieve binning of this linear transformation. A RooLinearVar does not have its own
  // binnings but uses linearly transformed binnings of teh input variable. If a given
  // binning exists on the input variable, it will also exists on this linear transformation
  // and a binning adaptor object is created on the fly.

  // Normalization binning
  if (name==0) {
    _binning.updateInput(((RooAbsRealLValue&)_var.arg()).getBinning(),_slope,_offset) ;
    return _binning ;
  } 

  // Alternative named range binnings, look for existing translator binning first
  RooLinTransBinning* altBinning = (RooLinTransBinning*) _altBinning.FindObject(name) ;
  if (altBinning) {
    altBinning->updateInput(((RooAbsRealLValue&)_var.arg()).getBinning(name,verbose),_slope,_offset) ;
    return *altBinning ;
  }

  // If binning is not found return default binning, if creation is not requested
  if (!_var.arg().hasRange(name) && !createOnTheFly) {
    return _binning ;
  }

  // Create translator binning on the fly
  RooAbsBinning& sourceBinning = ((RooAbsRealLValue&)_var.arg()).getBinning(name,verbose) ;
  RooLinTransBinning* transBinning = new RooLinTransBinning(sourceBinning,_slope,_offset) ;
  _altBinning.Add(transBinning) ;

  return *transBinning ;
}


//_____________________________________________________________________________
const RooAbsBinning& RooLinearVar::getBinning(const char* name, Bool_t verbose, Bool_t createOnTheFly) const
{
  // Const version of getBinning()

  return const_cast<RooLinearVar*>(this)->getBinning(name,verbose,createOnTheFly) ;
}

//_____________________________________________________________________________
std::list<std::string> RooLinearVar::getBinningNames() const
{
  // Get a list of all binning names. An empty name implies the default binning.
  // A 0 pointer should be passed to getBinning in this case.
  std::list<std::string> binningNames(1, "");

  RooFIter iter = _altBinning.fwdIterator();
  const RooAbsArg* binning = 0;
  while((binning = iter.next())) {
    const char* name = binning->GetName();
    binningNames.push_back(name);
  }

  return binningNames;
}

//_____________________________________________________________________________
Bool_t RooLinearVar::hasBinning(const char* name) const 
{
  // Returns true if binning with given name exists.If a given binning
  // exists on the input variable, it will also exists on this linear
  // transformation.

  return ((RooAbsRealLValue&)_var.arg()).hasBinning(name) ;
}
 RooLinearVar.cxx:1
 RooLinearVar.cxx:2
 RooLinearVar.cxx:3
 RooLinearVar.cxx:4
 RooLinearVar.cxx:5
 RooLinearVar.cxx:6
 RooLinearVar.cxx:7
 RooLinearVar.cxx:8
 RooLinearVar.cxx:9
 RooLinearVar.cxx:10
 RooLinearVar.cxx:11
 RooLinearVar.cxx:12
 RooLinearVar.cxx:13
 RooLinearVar.cxx:14
 RooLinearVar.cxx:15
 RooLinearVar.cxx:16
 RooLinearVar.cxx:17
 RooLinearVar.cxx:18
 RooLinearVar.cxx:19
 RooLinearVar.cxx:20
 RooLinearVar.cxx:21
 RooLinearVar.cxx:22
 RooLinearVar.cxx:23
 RooLinearVar.cxx:24
 RooLinearVar.cxx:25
 RooLinearVar.cxx:26
 RooLinearVar.cxx:27
 RooLinearVar.cxx:28
 RooLinearVar.cxx:29
 RooLinearVar.cxx:30
 RooLinearVar.cxx:31
 RooLinearVar.cxx:32
 RooLinearVar.cxx:33
 RooLinearVar.cxx:34
 RooLinearVar.cxx:35
 RooLinearVar.cxx:36
 RooLinearVar.cxx:37
 RooLinearVar.cxx:38
 RooLinearVar.cxx:39
 RooLinearVar.cxx:40
 RooLinearVar.cxx:41
 RooLinearVar.cxx:42
 RooLinearVar.cxx:43
 RooLinearVar.cxx:44
 RooLinearVar.cxx:45
 RooLinearVar.cxx:46
 RooLinearVar.cxx:47
 RooLinearVar.cxx:48
 RooLinearVar.cxx:49
 RooLinearVar.cxx:50
 RooLinearVar.cxx:51
 RooLinearVar.cxx:52
 RooLinearVar.cxx:53
 RooLinearVar.cxx:54
 RooLinearVar.cxx:55
 RooLinearVar.cxx:56
 RooLinearVar.cxx:57
 RooLinearVar.cxx:58
 RooLinearVar.cxx:59
 RooLinearVar.cxx:60
 RooLinearVar.cxx:61
 RooLinearVar.cxx:62
 RooLinearVar.cxx:63
 RooLinearVar.cxx:64
 RooLinearVar.cxx:65
 RooLinearVar.cxx:66
 RooLinearVar.cxx:67
 RooLinearVar.cxx:68
 RooLinearVar.cxx:69
 RooLinearVar.cxx:70
 RooLinearVar.cxx:71
 RooLinearVar.cxx:72
 RooLinearVar.cxx:73
 RooLinearVar.cxx:74
 RooLinearVar.cxx:75
 RooLinearVar.cxx:76
 RooLinearVar.cxx:77
 RooLinearVar.cxx:78
 RooLinearVar.cxx:79
 RooLinearVar.cxx:80
 RooLinearVar.cxx:81
 RooLinearVar.cxx:82
 RooLinearVar.cxx:83
 RooLinearVar.cxx:84
 RooLinearVar.cxx:85
 RooLinearVar.cxx:86
 RooLinearVar.cxx:87
 RooLinearVar.cxx:88
 RooLinearVar.cxx:89
 RooLinearVar.cxx:90
 RooLinearVar.cxx:91
 RooLinearVar.cxx:92
 RooLinearVar.cxx:93
 RooLinearVar.cxx:94
 RooLinearVar.cxx:95
 RooLinearVar.cxx:96
 RooLinearVar.cxx:97
 RooLinearVar.cxx:98
 RooLinearVar.cxx:99
 RooLinearVar.cxx:100
 RooLinearVar.cxx:101
 RooLinearVar.cxx:102
 RooLinearVar.cxx:103
 RooLinearVar.cxx:104
 RooLinearVar.cxx:105
 RooLinearVar.cxx:106
 RooLinearVar.cxx:107
 RooLinearVar.cxx:108
 RooLinearVar.cxx:109
 RooLinearVar.cxx:110
 RooLinearVar.cxx:111
 RooLinearVar.cxx:112
 RooLinearVar.cxx:113
 RooLinearVar.cxx:114
 RooLinearVar.cxx:115
 RooLinearVar.cxx:116
 RooLinearVar.cxx:117
 RooLinearVar.cxx:118
 RooLinearVar.cxx:119
 RooLinearVar.cxx:120
 RooLinearVar.cxx:121
 RooLinearVar.cxx:122
 RooLinearVar.cxx:123
 RooLinearVar.cxx:124
 RooLinearVar.cxx:125
 RooLinearVar.cxx:126
 RooLinearVar.cxx:127
 RooLinearVar.cxx:128
 RooLinearVar.cxx:129
 RooLinearVar.cxx:130
 RooLinearVar.cxx:131
 RooLinearVar.cxx:132
 RooLinearVar.cxx:133
 RooLinearVar.cxx:134
 RooLinearVar.cxx:135
 RooLinearVar.cxx:136
 RooLinearVar.cxx:137
 RooLinearVar.cxx:138
 RooLinearVar.cxx:139
 RooLinearVar.cxx:140
 RooLinearVar.cxx:141
 RooLinearVar.cxx:142
 RooLinearVar.cxx:143
 RooLinearVar.cxx:144
 RooLinearVar.cxx:145
 RooLinearVar.cxx:146
 RooLinearVar.cxx:147
 RooLinearVar.cxx:148
 RooLinearVar.cxx:149
 RooLinearVar.cxx:150
 RooLinearVar.cxx:151
 RooLinearVar.cxx:152
 RooLinearVar.cxx:153
 RooLinearVar.cxx:154
 RooLinearVar.cxx:155
 RooLinearVar.cxx:156
 RooLinearVar.cxx:157
 RooLinearVar.cxx:158
 RooLinearVar.cxx:159
 RooLinearVar.cxx:160
 RooLinearVar.cxx:161
 RooLinearVar.cxx:162
 RooLinearVar.cxx:163
 RooLinearVar.cxx:164
 RooLinearVar.cxx:165
 RooLinearVar.cxx:166
 RooLinearVar.cxx:167
 RooLinearVar.cxx:168
 RooLinearVar.cxx:169
 RooLinearVar.cxx:170
 RooLinearVar.cxx:171
 RooLinearVar.cxx:172
 RooLinearVar.cxx:173
 RooLinearVar.cxx:174
 RooLinearVar.cxx:175
 RooLinearVar.cxx:176
 RooLinearVar.cxx:177
 RooLinearVar.cxx:178
 RooLinearVar.cxx:179
 RooLinearVar.cxx:180
 RooLinearVar.cxx:181
 RooLinearVar.cxx:182
 RooLinearVar.cxx:183
 RooLinearVar.cxx:184
 RooLinearVar.cxx:185
 RooLinearVar.cxx:186
 RooLinearVar.cxx:187
 RooLinearVar.cxx:188
 RooLinearVar.cxx:189
 RooLinearVar.cxx:190
 RooLinearVar.cxx:191
 RooLinearVar.cxx:192
 RooLinearVar.cxx:193
 RooLinearVar.cxx:194
 RooLinearVar.cxx:195
 RooLinearVar.cxx:196
 RooLinearVar.cxx:197
 RooLinearVar.cxx:198
 RooLinearVar.cxx:199
 RooLinearVar.cxx:200
 RooLinearVar.cxx:201
 RooLinearVar.cxx:202
 RooLinearVar.cxx:203
 RooLinearVar.cxx:204
 RooLinearVar.cxx:205
 RooLinearVar.cxx:206
 RooLinearVar.cxx:207
 RooLinearVar.cxx:208
 RooLinearVar.cxx:209
 RooLinearVar.cxx:210
 RooLinearVar.cxx:211
 RooLinearVar.cxx:212
 RooLinearVar.cxx:213
 RooLinearVar.cxx:214
 RooLinearVar.cxx:215
 RooLinearVar.cxx:216
 RooLinearVar.cxx:217
 RooLinearVar.cxx:218
 RooLinearVar.cxx:219
 RooLinearVar.cxx:220
 RooLinearVar.cxx:221
 RooLinearVar.cxx:222
 RooLinearVar.cxx:223
 RooLinearVar.cxx:224
 RooLinearVar.cxx:225
 RooLinearVar.cxx:226
 RooLinearVar.cxx:227
 RooLinearVar.cxx:228
 RooLinearVar.cxx:229
 RooLinearVar.cxx:230
 RooLinearVar.cxx:231
 RooLinearVar.cxx:232
 RooLinearVar.cxx:233
 RooLinearVar.cxx:234
 RooLinearVar.cxx:235
 RooLinearVar.cxx:236
 RooLinearVar.cxx:237
 RooLinearVar.cxx:238
 RooLinearVar.cxx:239
 RooLinearVar.cxx:240
 RooLinearVar.cxx:241
 RooLinearVar.cxx:242
 RooLinearVar.cxx:243
 RooLinearVar.cxx:244
 RooLinearVar.cxx:245
 RooLinearVar.cxx:246
 RooLinearVar.cxx:247
 RooLinearVar.cxx:248
 RooLinearVar.cxx:249
 RooLinearVar.cxx:250
 RooLinearVar.cxx:251
 RooLinearVar.cxx:252
 RooLinearVar.cxx:253
 RooLinearVar.cxx:254
 RooLinearVar.cxx:255
 RooLinearVar.cxx:256
 RooLinearVar.cxx:257
 RooLinearVar.cxx:258
 RooLinearVar.cxx:259
 RooLinearVar.cxx:260
 RooLinearVar.cxx:261
 RooLinearVar.cxx:262
 RooLinearVar.cxx:263
 RooLinearVar.cxx:264
 RooLinearVar.cxx:265
 RooLinearVar.cxx:266
 RooLinearVar.cxx:267
 RooLinearVar.cxx:268
 RooLinearVar.cxx:269
 RooLinearVar.cxx:270
 RooLinearVar.cxx:271
 RooLinearVar.cxx:272
 RooLinearVar.cxx:273
 RooLinearVar.cxx:274
 RooLinearVar.cxx:275
 RooLinearVar.cxx:276
 RooLinearVar.cxx:277