Jpp test-rotations-new
the software that should make you happy
Loading...
Searching...
No Matches
JHVInterpolator.hh
Go to the documentation of this file.
1#ifndef __JCALIBRATE_JHVINTERPOLATOR__
2#define __JCALIBRATE_JHVINTERPOLATOR__
3
4#include "JLang/JException.hh"
5
6#include "JTools/JRange.hh"
7
9
10#include "TKey.h"
11#include "TGraph.h"
12#include "TGraphErrors.h"
13#include "TMultiGraph.h"
14#include "TAttMarker.h"
15#include "TColor.h"
16
17
18/**
19 * \author bjung
20 */
21
22namespace JCALIBRATE {
23
24 using JTOOLS::JRange;
25 using JLANG::JNoValue;
28
29 static const std::string HVINTERPOLATOR_SUFFIX = ".HVxG";
30
31 static const char* HVINTERPOLATOR_DATA = "HVINTERPOLATOR_DATA";
32 static const char* HVINTERPOLATOR_RESULT = "HVINTERPOLATOR_RESULT";
33
34 /**
35 * Auxiliary data structure to store high-voltage versus gain data and interpolate the nominal high-voltage.
36 */
38 {
39 /**
40 * Constructor.
41 *
42 * \param object TMultiGraph object
43 */
44 JHVInterpolator(TMultiGraph& object) :
45 data(&object)
46 {
47 TGraphErrors* g0 = new TGraphErrors();
48
49 g0->SetName(HVINTERPOLATOR_RESULT);
50 g0->SetLineColor (kRed);
51 g0->SetMarkerColor(kRed);
52 g0->SetMarkerStyle(kFullDotSmall);
53 g0->Set(0);
54
55 data->Add(g0);
56
57 TGraphErrors* g1 = new TGraphErrors();
58
59 g1->SetName(HVINTERPOLATOR_DATA);
60 g1->SetMarkerStyle(kFullDotSmall);
61 g1->Set(0);
62
63 data->Add(g1);
64 }
65
66
67 /**
68 * Add point to diagram.
69 *
70 * \param HV high-voltage [V]
71 * \param gain gain value
72 * \param gainError error on gain value
73 */
74 void AddPoint(Double_t HV, Double_t gain, Double_t gainError)
75 {
76 TGraphErrors* g1 = getData();
77
78 const Int_t N = g1->GetN();
79
80 g1->SetPoint (N, fabs(HV), gain);
81 g1->SetPointError(N, 0.0, gainError);
82 }
83
84
85 /**
86 * Set point with index i.
87 *
88 * \param i index of point
89 * \param HV high-voltage [V]
90 * \param gain gain value
91 * \param gainError error on gain value
92 */
93 void SetPoint(Int_t i, Double_t HV, Double_t gain, Double_t gainError)
94 {
95 TGraphErrors* g1 = getData();
96
97 g1->SetPoint (i, fabs(HV), gain);
98 g1->SetPointError(i, 0.0, gainError);
99 }
100
101
102 /**
103 * Checks whether high-voltage is within range
104 *
105 * \param HV high-voltage [V]
106 * \return true if high-voltage is within range; else false
107 */
108 const bool checkHV(const double HV) const
109 {
110 return (HV > hvRange.getLowerLimit() &&
111 HV < hvRange.getUpperLimit());
112 }
113
114
115 /**
116 * Checks whether two high-voltage values are different.
117 *
118 * \param HV1 first high-voltage [V]
119 * \param HV2 second high-voltage [V]
120 * \return true if absolute difference is greater than minimal required difference; else false
121 */
122 const bool checkHV(const double HV1, const double HV2) const
123 {
124 return (fabs(HV1 - HV2) > dHVmin);
125 }
126
127
128 /**
129 * Checks if gain is within range.
130 *
131 * \param gain gain value
132 * \return true if gain within allowed range; else false
133 */
134 const bool checkGain(const double gain) const
135 {
136 return (gain > gainRange.getLowerLimit() &&
137 gain < gainRange.getUpperLimit());
138 }
139
140
141 /**
142 * Checks whether the gains of two points are strictly increasing as function of their absolute high-voltage
143 *
144 * \param i index of first point
145 * \param j index of second point
146 * \return true if gains of given points are strictly increasing\n
147 * as function of the absolute high-voltage; else false
148 */
149 const bool areIncreasing(const Int_t i, const Int_t j) const
150 {
151 TGraphErrors* g1 = getData();
152
153 if ((i >= 0 && i < g1->GetN()) &&
154 (j >= 0 && i < g1->GetN())) {
155
156 return ((g1->GetPointX(i) > g1->GetPointX(j) && g1->GetPointY(i) > g1->GetPointY(j)) ||
157 (g1->GetPointX(i) < g1->GetPointX(j) && g1->GetPointY(i) < g1->GetPointY(j)));
158
159 } else {
160
161 return false;
162 }
163 }
164
165
166 /**
167 * Checks whether two points are valid for inter-/extrapolation.
168 *
169 * \param i index of first point
170 * \param j index of second point
171 * \return true if valid for inter-/extrapolation; else false
172 */
173 const bool areValid(const Int_t i, const Int_t j) const
174 {
175 TGraphErrors* g1 = getData();
176
177 if ((i >= 0 && i < g1->GetN()) &&
178 (j >= 0 && j < g1->GetN())) {
179
180 const double HV_i = -fabs(g1->GetPointX(i));
181 const double HV_j = -fabs(g1->GetPointX(j));
182 const double gain_i = g1->GetPointY(i);
183 const double gain_j = g1->GetPointY(j);
184
185 return (areIncreasing( i, j) && checkHV(HV_i) && checkGain(gain_i) &&
186 checkHV (HV_i, HV_j) && checkHV(HV_j) && checkGain(gain_j));
187
188 } else {
189
190 return false;
191 }
192 }
193
194
195 /**
196 * Inter-/Extrapolate the high-voltage value corresponding to the target gain value.
197 *
198 * \param gainTarget target gain value for inter-/extrapolation
199 * \return true if inter-/extrapolation successful; else false
200 */
201 bool interpolateHV(const double gainTarget)
202 {
203 TGraphErrors* g1 = getData();
204
205 if (g1->GetN() < 2 || !checkGain(gainTarget)) {
206 return false;
207 }
208
209 // Search for valid inter-/extrapolation points
210
211 Int_t i = 0;
212 Int_t j = 1;
213
214 for (Int_t k = 2; k < g1->GetN(); ++k) {
215
216 const double dGain_i = fabs(g1->GetPointY(i) - gainTarget);
217 const double dGain_j = fabs(g1->GetPointY(j) - gainTarget);
218 const double dGain_k = fabs(g1->GetPointY(k) - gainTarget);
219
220 if (dGain_k < dGain_j) {
221 i = (areValid(j,k) ? j : i);
222 j = k;
223 } else if ((dGain_k < dGain_i || !areValid(i,j)) && areValid(j,k)) {
224 i = j;
225 j = k;
226 }
227 }
228
229 // Inter-/Extrapolate high-voltage corresponding to given gain
230
231 if (areValid(i, j)) {
232
233 const double logHV0 = log(fabs(g1->GetPointX(i)));
234 const double logHV1 = log(fabs(g1->GetPointX(j)));
235
236 const double logG0 = log(g1->GetPointY(i));
237 const double logG1 = log(g1->GetPointY(j));
238 const double elogG0 = g1->GetErrorY(i) / g1->GetPointY(i);
239 const double elogG1 = g1->GetErrorY(j) / g1->GetPointY(j);
240
241 const double dlogG0 = log(gainTarget) - logG0;
242 const double dlogG1 = log(gainTarget) - logG1;
243
244 const double slope = (logG1 - logG0) / (logHV1 - logHV0);
245
246 const double HVnom = exp(dlogG0 / slope + logHV0);
247 const double eHVnom = HVnom * sqrt(dlogG1 * dlogG1 * elogG0 * elogG0 +
248 dlogG0 * dlogG0 * elogG1 * elogG1) / fabs(slope * (logG1 - logG0));
249
250 const double distance = fabs((log(HVnom) - logHV0) / (logHV0 - logHV1));
251 static const double maxDist = 2.0;
252
253 if (checkHV(-HVnom) && distance < maxDist) {
254
255 TGraphErrors* g0 = getResult();
256
257 g0->SetPoint (0, HVnom, gainTarget);
258 g0->SetPointError(0, eHVnom, 0.0);
259
260 return true;
261 }
262 }
263
264 return false;
265 }
266
267
268 /**
269 * Get interpolated high-voltage.
270 *
271 * \return inter-/extrapolated high-voltage\n
272 * corresponding to target gain value [V]
273 */
274 double getHV() const
275 {
276 TGraphErrors* g0 = getResult();
277
278 if (g0->GetN() > 0) {
279
280 return g0->GetPointX(0);
281
282 } else {
283
284 THROW(JNoValue, "JHVInterpolator::getHV(): Missing HV inter-/extrapolation point. Please call JHVInterpolator::interpolateHV() first.");
285 }
286 }
287
288
289 /**
290 * Get error estimate on interpolated high-voltage.
291 *
292 * \return error on inter-/extrapolated high-voltage\n
293 * corresponding to the target gain value [V]
294 */
295 double getHVError() const
296 {
297 TGraphErrors* g0 = getResult();
298
299 if (g0->GetN() > 0) {
300
301 return g0->GetErrorX(0);
302
303 } else {
304
305 THROW(JNoValue, "JHVInterpolator::getHVError(): Missing HV inter-/extrpolation point. Please call JHVInterpolator::interpolateHV() first.");
306 }
307 }
308
309
310 /**
311 * Get graph with the input data for the interpolation.
312 *
313 * \return pointer to graph with input data
314 */
315 TGraphErrors* getData() const
316 {
317 TList* list = data->GetListOfGraphs();
318
319 if (list != NULL && list->FindObject(HVINTERPOLATOR_DATA) != NULL) {
320
321 return (TGraphErrors*)list->FindObject(HVINTERPOLATOR_DATA);
322
323 } else if (list == NULL) {
324
325 THROW(JNullPointerException, "JHVInterpolator()::getData(): Emtpy list of graphs.");
326
327 } else {
328
329 THROW(JNullPointerException, "JHVInterpolator()::getData(): No " << HVINTERPOLATOR_DATA << " graph.");
330 }
331 }
332
333
334 /**
335 * Get graph with the interpolation result.
336 *
337 * \return pointer to graph with the interpolation result
338 */
339 TGraphErrors* getResult() const
340 {
341 TList* list = data->GetListOfGraphs();
342
343 if (list != NULL && list->FindObject(HVINTERPOLATOR_RESULT) != NULL) {
344
345 return (TGraphErrors*)list->FindObject(HVINTERPOLATOR_RESULT);
346
347 } else if (list == NULL) {
348
349 THROW(JNullPointerException, "JHVInterpolator::getResult(): Empty list of graphs.");
350
351 } else {
352
353 THROW(JNullPointerException, "JHVInterpolator::getResult(): No " << HVINTERPOLATOR_RESULT << " graph.");
354 }
355 }
356
357
358 /**
359 * Set minimal separation distance for high-voltage.
360 *
361 * \param minDist minimal separation distance for high-voltage
362 */
363 static void setMinHVDistance(const double minDist)
364 {
365 dHVmin = minDist;
366 }
367
368
369 /**
370 * Set valid gain range.
371 *
372 * \param range valid high-voltage range [V]
373 */
374 static void setHVRange(const JRange<double> range)
375 {
376 hvRange = range;
377 }
378
379
380 /**
381 * Set valid gain range.
382 *
383 * \param range valid gain range
384 */
385 static void setGainRange(const JRange<double> range)
386 {
387 gainRange = range;
388 }
389
390
391 private:
392
393 TMultiGraph* data; //!< HV-versus-gain data
394
395 static double dHVmin; //!< Minimal high-voltage difference between two points [V]
396 static JRange<double> hvRange; //!< Allowed high-voltage range [V]
397 static JRange<double> gainRange; //!< Allowed gain range
398 };
399
400
401 /**
402 * Default values.
403 */
404 double JHVInterpolator::dHVmin = 2 * 3.14;
408}
409
410#endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Double_t g1(const Double_t x)
Function.
Definition JQuantiles.cc:25
Auxiliary class to define a range between two values.
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Exception for missing value.
Exception for null pointer operation.
Exception for accessing a value in a collection that is outside of its range.
Range of values.
Definition JRange.hh:42
Auxiliary classes and methods for PMT calibration.
static const std::string HVINTERPOLATOR_SUFFIX
static const char * HVINTERPOLATOR_RESULT
static const double FITTOT_GAIN_MAX
Default maximal gain.
Definition JFitToT.hh:45
static const double FITTOT_GAIN_MIN
Default minimal gain.
Definition JFitToT.hh:44
static const char * HVINTERPOLATOR_DATA
Auxiliary data structure to store high-voltage versus gain data and interpolate the nominal high-volt...
double getHVError() const
Get error estimate on interpolated high-voltage.
TGraphErrors * getData() const
Get graph with the input data for the interpolation.
const bool areValid(const Int_t i, const Int_t j) const
Checks whether two points are valid for inter-/extrapolation.
double getHV() const
Get interpolated high-voltage.
static void setHVRange(const JRange< double > range)
Set valid gain range.
static void setMinHVDistance(const double minDist)
Set minimal separation distance for high-voltage.
static JRange< double > gainRange
Allowed gain range.
const bool checkHV(const double HV1, const double HV2) const
Checks whether two high-voltage values are different.
const bool checkGain(const double gain) const
Checks if gain is within range.
TMultiGraph * data
HV-versus-gain data.
static void setGainRange(const JRange< double > range)
Set valid gain range.
JHVInterpolator(TMultiGraph &object)
Constructor.
bool interpolateHV(const double gainTarget)
Inter-/Extrapolate the high-voltage value corresponding to the target gain value.
void SetPoint(Int_t i, Double_t HV, Double_t gain, Double_t gainError)
Set point with index i.
const bool areIncreasing(const Int_t i, const Int_t j) const
Checks whether the gains of two points are strictly increasing as function of their absolute high-vol...
static JRange< double > hvRange
Allowed high-voltage range [V].
static double dHVmin
Minimal high-voltage difference between two points [V].
TGraphErrors * getResult() const
Get graph with the interpolation result.
void AddPoint(Double_t HV, Double_t gain, Double_t gainError)
Add point to diagram.
const bool checkHV(const double HV) const
Checks whether high-voltage is within range.