KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVCalibrator.cpp
Go to the documentation of this file.
1 #include "KVCalibrator.h"
2 #include "Riostream.h"
3 
4 #include <TGraph.h>
5 using namespace std;
6 
8 
9 
10 
16 void KVCalibrator::adjust_range_of_inverse_calibration()
17 {
18  // For an inverse calibration, the limits [min,max] given in the options concern the Y-values,
19  // i.e. the values Y=f(X) of the function which correspond to the input signal.
20  // We need to find the corresponding values of X in order
21  // to fix the range of the function, and avoid use of TF1::GetX() leading to many error messages.
22 
23  if (fInputMax < fInputMin) return; // no sense trying if this is true
24 
25  Double_t fXmin, fXmax;
26  // Initial range corresponds to estimated output range given as [out_min,out_max] options
27  fCalibFunc->GetRange(fXmin, fXmax);
28  // check if function increases or decreases with X
29  Bool_t fMonoIncreasing = true;
30  Double_t fFuncMax = fCalibFunc->Eval(fXmax);
31  Double_t fFuncMin = fCalibFunc->Eval(fXmin);
32  if (fFuncMin > fFuncMax) {
33  fMonoIncreasing = false;
34  std::swap(fFuncMin, fFuncMax);
35  }
36  // For all to be well, fInputMin & fInputMax need to be within the range of values of the function
37  if (!in_range(fInputMin, fFuncMin, fFuncMax) || !in_range(fInputMax, fFuncMin, fFuncMax)) {
38  Double_t Range = fXmax - fXmin;
39  if (!in_range(fInputMin, fFuncMin, fFuncMax)) {
40  if (fInputMin < fFuncMin) {
41  // need to reduce minimum value of function until it is less than fInputMin
42  if (fMonoIncreasing) {
43  // need to decrease fXmin until fInputMin>fFuncMin
44  do {
45  fXmin -= Range;
46  Range = fXmax - fXmin;
47  fFuncMin = fCalibFunc->Eval(fXmin);
48  }
49  while (fInputMin < fFuncMin);
50  }
51  else {
52  // need to increase fXmax until fInputMin>fFuncMin
53  do {
54  fXmax += Range;
55  Range = fXmax - fXmin;
56  fFuncMin = fCalibFunc->Eval(fXmax);
57  }
58  while (fInputMin < fFuncMin);
59  }
60  }
61  else if (fInputMin > fFuncMax) {
62  // need to increase maximum value of function until it is greater than fInputMin
63  if (fMonoIncreasing) {
64  // need to increase fXmax until fInputMin<fFuncMax
65  do {
66  fXmax += Range;
67  Range = fXmax - fXmin;
68  fFuncMax = fCalibFunc->Eval(fXmax);
69  }
70  while (fInputMin > fFuncMax);
71  }
72  else {
73  // need to decrease fXmin until fInputMin<fFuncMax
74  do {
75  fXmin -= Range;
76  Range = fXmax - fXmin;
77  fFuncMax = fCalibFunc->Eval(fXmin);
78  }
79  while (fInputMin > fFuncMax);
80  }
81  }
82  }
83  if (!in_range(fInputMax, fFuncMin, fFuncMax)) {
84  if (fInputMax < fFuncMin) {
85  // need to reduce minimum value of function until it is less than fInputMax
86  if (fMonoIncreasing) {
87  // need to decrease fXmin until fInputMax>fFuncMin
88  do {
89  fXmin -= Range;
90  Range = fXmax - fXmin;
91  fFuncMin = fCalibFunc->Eval(fXmin);
92  }
93  while (fInputMax < fFuncMin);
94  }
95  else {
96  // need to increase fXmax until fInputMax>fFuncMin
97  do {
98  fXmax += Range;
99  Range = fXmax - fXmin;
100  fFuncMin = fCalibFunc->Eval(fXmax);
101  }
102  while (fInputMax < fFuncMin);
103  }
104  }
105  else if (fInputMax > fFuncMax) {
106  // need to increase maximum value of function until it is greater than fInputMax
107  if (fMonoIncreasing) {
108  // need to increase fXmax until fInputMax<fFuncMax
109  do {
110  fXmax += Range;
111  Range = fXmax - fXmin;
112  fFuncMax = fCalibFunc->Eval(fXmax);
113  }
114  while (fInputMax > fFuncMax);
115  }
116  else {
117  // need to decrease fXmin until fInputMax<fFuncMax
118  do {
119  fXmin -= Range;
120  Range = fXmax - fXmin;
121  fFuncMax = fCalibFunc->Eval(fXmin);
122  }
123  while (fInputMax > fFuncMax);
124  }
125  }
126  }
127  // adjust range of function to new values
128  fCalibFunc->SetRange(fXmin, fXmax);
129  }
130  // at this point fInputMin and fInputMax are certainly within the range of the function values
131  if (fMonoIncreasing) {
132  fXmin = fCalibFunc->GetX(fInputMin);
133  fXmax = fCalibFunc->GetX(fInputMax);
134  }
135  else {
136  fXmin = fCalibFunc->GetX(fInputMax);
137  fXmax = fCalibFunc->GetX(fInputMin);
138  }
139  // set range of function so that [min,max] values correspond to those given in option
140  fCalibFunc->SetRange(fXmin, fXmax);
141 
142 // Info("adjust_range_of_inverse_function", "After adjustment: %s", GetName());
143 // Info("adjust_range_of_inverse_function", "After adjustment: %s INPUT-range = [%f, %f]", GetInputSignalType().Data(), fInputMin, fInputMax);
144 // Info("adjust_range_of_inverse_function", "After adjustment: %s OUTPUT-range = [%f, %f]", GetOutputSignalType().Data(), fXmin, fXmax);
145 }
146 
147 
148 
151 
153 {
154  //Print a description of the calibration object, including a list of its parameters
155  cout << "_________________________________________________" << endl
156  << ClassName() << " :" << endl
157  << " Name : " << GetName() << endl
158  << " Type : " << GetType() << endl
159  << " Number of Parameters : " << GetNumberParams() << endl
160  << " Parameters :" << endl;
161  for (int i = 0; i < GetNumberParams(); i++) {
162  cout << " " << GetParameter(i) << endl;
163  }
164  if (GetStatus())
165  cout << " Status : ready" << endl;
166  else
167  cout << " Status : not ready" << endl;
168 }
169 
170 
171 
176 
178 {
179  // Create a new KVCalibrator object with class given by the plugin of given type
180  //
181  // If type=="" or type is unknown, returns a new base calibrator KVCalibrator
182 
183  TPluginHandler* ph = LoadPlugin("KVCalibrator", type);
184  if (!ph) {
185  return new KVCalibrator;
186  }
187  // execute default constructor
189  return c;
190 }
191 
192 
193 
219 
221 {
222  // Used to set up a function calibrator from infos in a calibration parameter file.
223  // Use an option string like this:
224  //
225  //~~~~~~~~~~~~~~
226  // CalibOptions: func=[function],min=[minimum input],max=[maximum output]
227  //~~~~~~~~~~~~~~
228  //
229  // This is the standard case where the calibration function is fitted to output signal vs. input signal.
230  // In this case `[min,max]` are the expected (allowed) range of input values.
231  //
232  // If the calibration function is fitted to input signal vs. output signal then we have what we
233  // call an 'inverse calibration function' and in this case you should use options like:
234  //
235  //~~~~~~~~~~~~~~
236  // CalibOptions: func=[function],inverse=true,min=[minimum input],max=[maximum input],out_min=[estimate minimum output],out_max=[estimate maximum output]
237  //~~~~~~~~~~~~~~
238  //
239  // In this case we need to calculate the range of output values we can give to the inverse function
240  // in order to have the expected (allowed) range of input values given by `[min,max]`.
241  // In order to do this, it is necessary to give a reasonable
242  // range for the expected output values, `[out_min,out_max]`. If these parameters are not given,
243  // the calibrator will not be valid.
244  //
245  // Throws a std::invalid_argument exception if any of the required options are missing
246 
247  if (!opt.HasStringParameter("func") && !opt.HasNumericParameter("min") && !opt.HasNumericParameter("max")) {
248  throw (std::invalid_argument("missing calibrator options: must give func, min, and max"));
249  }
250  SetUseInverseFunction(opt.IsValue("inverse", "true"));
251  if (IsUseInverseFunction()) {
252  if (!opt.HasNumericParameter("out_min") || !opt.HasNumericParameter("out_max")) {
253  throw (std::invalid_argument("missing inverse calibrator options: must give out_min and out_max"));
254  }
255  fCalibFunc = new TF1("KVCalibrator::fCalibFunc", opt.GetStringValue("func"), opt.GetDoubleValue("out_min"), opt.GetDoubleValue("out_max"));
256  fInputMin = opt.GetDoubleValue("min");
257  fInputMax = opt.GetDoubleValue("max");
258  }
259  else
260  fCalibFunc = new TF1("KVCalibrator::fCalibFunc", opt.GetStringValue("func"), opt.GetDoubleValue("min"), opt.GetDoubleValue("max"));
261 }
262 
263 
264 
268 
270 {
271  // Make graph of calibration function in given range with given number of points. Any extra required parameters
272  // should be given in the KVNameValueList argument.
273 
274  TGraph* gr = new TGraph;
275  for (int i = 0; i < npts; ++i) {
276  double input = input_range.ValueIofN(i, npts);
277  gr->SetPoint(i, input, Compute(input, par));
278  }
279  return gr;
280 }
281 
282 
283 
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define c(i)
char Char_t
bool Bool_t
double Double_t
const char Option_t
int type
Base class for all detector calibrations.
Definition: KVCalibrator.h:98
virtual void SetOptions(const KVNameValueList &)
TGraph * GetGraphOfCalibration(int npts, KVValueRange< double > input_range, const KVNameValueList &par="")
virtual void Print(Option_t *opt="") const
Print a description of the calibration object, including a list of its parameters.
static KVCalibrator * MakeCalibrator(const Char_t *type)
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Double_t GetDoubleValue(const Char_t *name) const
Bool_t HasNumericParameter(const Char_t *name) const
Bool_t HasStringParameter(const Char_t *name) const
Bool_t IsValue(const Char_t *name, value_type value) const
const Char_t * GetStringValue(const Char_t *name) const
Range of values specified by minimum, maximum.
Definition: KVValueRange.h:17
ValueType ValueIofN(Int_t i, Int_t n) const
Definition: KVValueRange.h:58
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Longptr_t ExecPlugin(int nargs, const T &... params)
RooCmdArg ClassName(const char *name)
RooCmdArg Range(const char *rangeName, Bool_t adjustNorm=kTRUE)
void swap(RVec< T > &lhs, RVec< T > &rhs)
TGraphErrors * gr
Type GetType(const std::string &Name)
auto Compute(F &&f) -> Internal::ComputeHelper< std::make_index_sequence< N >, T, F >