Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JHVGainGraph.hh
Go to the documentation of this file.
1 #ifndef __JCALIBRATE_JHVGAINGRAPH__
2 #define __JCALIBRATE_JHVGAINGRAPH__
3 
4 #include "JLang/JException.hh"
5 
6 #include "JTools/JRange.hh"
7 
8 #include "JCalibrate/JFitToT.hh"
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 
22 namespace JCALIBRATE {
23 
24  using JTOOLS::JRange;
26 
27  static const std::string HVGAINGRAPH_SUFFIX = ".HVxG";
28 
29  static const char* HVGAINGRAPH_DATA = "HVGAINGRAPH_DATA";
30  static const char* HVGAINGRAPH_RESULT = "HVGAINGRAPH_RESULT";
31 
32  /**
33  * Auxiliary data structure to store high-voltage versus gain data and interpolate the nominal high-voltage.
34  */
35  struct JHVGainGraph :
36  public TMultiGraph
37  {
38  /**
39  * Constructor.
40  *
41  * \param name name
42  * \param logScale set logarithmic scaling
43  * \param base base for logarithmic scaling
44  */
45  JHVGainGraph(const char* name = "HVGainGraph",
46  const bool logScale = false,
47  const double base = 10.0) :
48  loglog(logScale), base(base)
49  {
50  this->SetName(name);
51 
52  TGraphErrors* g0 = getResult();
53  TGraphErrors* g1 = getData();
54 
55  g0->SetName(HVGAINGRAPH_RESULT);
56  g0->SetLineColor (kRed);
57  g0->SetMarkerColor(kRed);
58  g0->SetMarkerStyle(kFullDotSmall);
59 
60  g1->SetName(HVGAINGRAPH_DATA);
61  g1->SetMarkerStyle(kFullDotSmall);
62  }
63 
64 
65  /**
66  * Copy constructor.
67  *
68  * \param object TMultiGraph object
69  * \param logScale set logarithmic scale
70  * \param base base for logarithmic scaling
71  */
72  JHVGainGraph(const TMultiGraph& object,
73  const bool logScale,
74  const double base = 10.0) :
75  loglog(logScale), base(base)
76  {
77  TList* graphs = object.GetListOfGraphs();
78 
79  if (graphs != NULL) {
80 
81  TGraphErrors* g0 = (TGraphErrors*)graphs->FindObject(HVGAINGRAPH_RESULT);
82  TGraphErrors* g1 = (TGraphErrors*)graphs->FindObject(HVGAINGRAPH_DATA);
83 
84  if (g0 != NULL) {
85  this->Add((TGraphErrors*)g0->Clone());
86  }
87 
88  if (g1 != NULL) {
89  this->Add((TGraphErrors*)g1->Clone());
90  }
91  }
92  }
93 
94 
95  /**
96  * Add point to diagram.
97  *
98  * \param HV high-voltage [V]
99  * \param gain gain value
100  * \param gainError error on gain value
101  */
102  void AddPoint(Double_t HV, Double_t gain, Double_t gainError)
103  {
104  TGraphErrors* g1 = getData();
105 
106  const Int_t N = g1->GetN();
107 
108  if (loglog) {
109 
110  g1->SetPoint (N, log(fabs(HV)) / log(base), log(gain) / log(base));
111  g1->SetPointError(N, 0.0, gainError / log(base) / gain);
112 
113  } else {
114 
115  g1->SetPoint (N, HV, gain);
116  g1->SetPointError(N, 0.0, gainError);
117  }
118  }
119 
120 
121  /**
122  * Set point with index i.
123  *
124  * \param i index of point
125  * \param HV high-voltage [V]
126  * \param gain gain value
127  * \param gainError error on gain value
128  */
129  void SetPoint(Int_t i, Double_t HV, Double_t gain, Double_t gainError)
130  {
131  TGraphErrors* g1 = getData();
132 
133  if (loglog) {
134 
135  g1->SetPoint (i, log(fabs(HV)) / log(base), log(gain) / log(base));
136  g1->SetPointError(i, 0.0, gainError / log(base) / gain);
137 
138  } else {
139 
140  g1->SetPoint (i, HV, gain);
141  g1->SetPointError(i, 0.0, gainError);
142  }
143  }
144 
145 
146  /**
147  * Checks whether high-voltage is within range
148  *
149  * \param HV high-voltage [V]
150  * \return true if high-voltage is within range; else false
151  */
152  const bool checkHV(const double HV) const
153  {
154  return (HV > hvRange.getLowerLimit() &&
155  HV < hvRange.getUpperLimit());
156  }
157 
158 
159  /**
160  * Checks whether two high-voltage values are different.
161  *
162  * \param HV1 first high-voltage [V]
163  * \param HV2 second high-voltage [V]
164  * \return true if absolute difference is greater than minimal required difference; else false
165  */
166  const bool checkHV(const double HV1, const double HV2) const
167  {
168  return (fabs(HV1 - HV2) > dHVmin);
169  }
170 
171 
172  /**
173  * Checks if gain is within range.
174  *
175  * \param gain gain value
176  * \return true if gain within allowed range; else false
177  */
178  const bool checkGain(const double gain) const
179  {
180  return (gain > gainRange.getLowerLimit() &&
181  gain < gainRange.getUpperLimit());
182  }
183 
184 
185  /**
186  * Checks whether the gains of two points are strictly increasing as function of their absolute high-voltage
187  *
188  * \param i index of first point
189  * \param j index of second point
190  * \return true if gains of given points are strictly increasing\n
191  * as function of the absolute high-voltage; else false
192  */
193  const bool areIncreasing(const Int_t i, const Int_t j)
194  {
195  TGraphErrors* g1 = getData();
196 
197  if ( (g1 != NULL) && ((i >= 0 && i < g1->GetN()) &&
198  (j >= 0 && i < g1->GetN())) ) {
199 
200  if (loglog) {
201 
202  return ((g1->GetPointX(i) > g1->GetPointX(j) && g1->GetPointY(i) > g1->GetPointY(j)) ||
203  (g1->GetPointX(i) < g1->GetPointX(j) && g1->GetPointY(i) < g1->GetPointY(j)));
204 
205  } else {
206 
207  return ((g1->GetPointX(i) < g1->GetPointX(j) && g1->GetPointY(i) > g1->GetPointY(j)) ||
208  (g1->GetPointX(i) > g1->GetPointX(j) && g1->GetPointY(i) < g1->GetPointY(j)));
209  }
210 
211  } else {
212 
213  return false;
214  }
215  }
216 
217 
218  /**
219  * Checks whether two points are valid for inter-/extrapolation.
220  *
221  * \param i index of first point
222  * \param j index of second point
223  * \return true if valid for inter-/extrapolation; else false
224  */
225  const bool areValid(const Int_t i, const Int_t j)
226  {
227  TGraphErrors* g1 = getData();
228 
229  if ((i >= 0 && i < g1->GetN()) &&
230  (j >= 0 && i < g1->GetN())) {
231 
232  double HV_i, HV_j, gain_i, gain_j;
233 
234  if (loglog) {
235 
236  HV_i = -pow(base, g1->GetPointX(i));
237  HV_j = -pow(base, g1->GetPointX(j));
238  gain_i = pow(base, g1->GetPointY(i));
239  gain_j = pow(base, g1->GetPointY(j));
240 
241  } else {
242 
243  HV_i = g1->GetPointX(i);
244  HV_j = g1->GetPointX(j);
245  gain_i = g1->GetPointY(i);
246  gain_j = g1->GetPointY(j);
247  }
248 
249  return (areIncreasing( i, j) && checkHV(HV_i) && checkGain(gain_i) &&
250  checkHV (HV_i, HV_j) && checkHV(HV_j) && checkGain(gain_j));
251 
252  } else {
253 
254  return false;
255  }
256  }
257 
258 
259  /**
260  * Inter-/Extrapolate the high-voltage value corresponding to the target gain value.
261  *
262  * \param gainTarget target gain value for inter-/extrapolation
263  * \return true if inter-/extrapolation successful; else false
264  */
265  bool interpolate(const double gainTarget)
266  {
267  TGraphErrors* g1 = getData();
268 
269  if (g1->GetN() < 2 || !checkGain(gainTarget)) {
270  return false;
271  }
272 
273  const bool isLogLog = loglog;
274 
275  if (!isLogLog) {
276  setLogLog();
277  }
278 
279  // Search for valid inter-/extrapolation points
280 
281  Int_t i = 0;
282  Int_t j = 1;
283 
284  const double logGainTarget = log(gainTarget) / log(base);
285 
286  for (Int_t k = 1; k < g1->GetN(); ++k) {
287 
288  const double dlogG_i = fabs(g1->GetPointY(i) - logGainTarget);
289  const double dlogG_j = fabs(g1->GetPointY(j) - logGainTarget);
290  const double dlogG_k = fabs(g1->GetPointY(k) - logGainTarget);
291 
292  if (dlogG_k < dlogG_i) {
293 
294  j = (areValid(i, k) ? i : j);
295  i = k;
296 
297  } else if ((dlogG_k < dlogG_j || !areValid(i, j)) &&
298  areValid(i, k)) {
299  j = k;
300  }
301  }
302 
303  // Inter-/Extrapolate high-voltage corresponding to given gain
304 
305  bool valid = areValid(i, j);
306 
307  if (valid) {
308 
309  const double logHV0 = g1->GetPointX(i);
310  const double logHV1 = g1->GetPointX(j);
311 
312  const double logG0 = g1->GetPointY(i);
313  const double logG1 = g1->GetPointY(j);
314  const double elogG0 = g1->GetErrorY(i);
315  const double elogG1 = g1->GetErrorY(j);
316 
317  const double dlogG0 = logGainTarget - logG0;
318  const double dlogG1 = logGainTarget - logG1;
319 
320  const double slope = (logG1 - logG0) / (logHV1 - logHV0);
321 
322  const double logHVnom = dlogG0 / slope + logHV0;
323  const double elogHVnom = sqrt(dlogG1 * dlogG1 * elogG0 * elogG0 +
324  dlogG0 * dlogG0 * elogG1 * elogG1) / fabs(slope * (logG1 - logG0));
325 
326  const double distance = fabs((logHVnom - logHV0) / (logHV0 - logHV1));
327 
328  static const double maxDist = 2.0;
329 
330  valid = (logHVnom > 0.0 && checkHV(-pow(base, logHVnom)) && distance < maxDist);
331 
332  if (valid) {
333 
334  TGraphErrors* g0 = getResult();
335 
336  g0->SetPoint (0, logHVnom, logGainTarget);
337  g0->SetPointError(0, elogHVnom, 0.0);
338  }
339  }
340 
341  if (!isLogLog) {
342  unsetLogLog();
343  }
344 
345  return valid;
346  }
347 
348 
349  /**
350  * Get high-voltage corresponding to given target gain value.
351  *
352  * \param gainTarget target gain value for inter-/extrapolation
353  * \return inter-/extrapolated high-voltage\n
354  * corresponding to target gain value [V]
355  */
356  double getTargetHV(const double gainTarget)
357  {
358  static const double precision = 1e-3;
359 
360  const double target = (loglog ? log(gainTarget) / log(base) : gainTarget);
361 
362  TGraphErrors* g0 = getResult();
363 
364  if ((g0->GetN() > 0 && fabs(g0->GetPointY(0) - target < precision)) || interpolate(gainTarget)) {
365 
366  return (loglog ? -pow(base, g0->GetPointX(0)) : g0->GetPointX(0));
367 
368  } else {
369 
370  THROW(JValueOutOfRange, "JHVGainGraph::getTargetError(): No valid inter-/extrapolation candidate found for given target gain.");
371  }
372  }
373 
374 
375  /**
376  * Get error estimate on high-voltage corresponding to given target gain value.
377  *
378  * \param gainTarget target gain value for inter-/extrapolation
379  * \return error on inter-/extrapolated high-voltage\n
380  * corresponding to the target gain value [V]
381  */
382  double getTargetHVError(const double gainTarget)
383  {
384  static const double precision = 1e-3;
385 
386  const double target = (loglog ? log(gainTarget) / log(base) : gainTarget);
387 
388  TGraphErrors* g0 = getResult();
389 
390  if ((g0->GetN() > 0 && fabs(g0->GetPointY(0) - target) < precision) || interpolate(gainTarget)) {
391 
392  return (loglog ? g0->GetErrorX(0) * pow(base, g0->GetPointX(0)) * log(base) : g0->GetErrorX(0));
393 
394  } else {
395 
396  THROW(JValueOutOfRange, "JHVGainGraph::getTargetError(): No valid inter-/extrapolation candidate found for given target gain.");
397  }
398  }
399 
400 
401  /**
402  * Set log-log scale.
403  */
404  void setLogLog()
405  {
406  if (!loglog) {
407 
408  TIter next(this->GetListOfGraphs());
409 
410  while (TGraphErrors* graph = (TGraphErrors*)next()) {
411 
412  if (graph != NULL) {
413 
414  for (Int_t i = 0; i < graph->GetN(); ++i) {
415 
416  Double_t absLogHV = log(fabs(graph->GetPointX(i))) / log(base);
417  Double_t logGain = log(graph->GetPointY(i)) / log(base);
418 
419  Double_t absLogHVerror = graph->GetErrorX(i) / fabs(graph->GetPointX(i)) / log(base);
420  Double_t logGainError = graph->GetErrorY(i) / fabs(graph->GetPointY(i)) / log(base);
421 
422  graph->SetPoint (i, absLogHV, logGain);
423  graph->SetPointError(i, absLogHVerror, logGainError);
424  }
425  }
426  }
427 
428  loglog = true;
429  }
430  }
431 
432 
433  /**
434  * Unset log-log scale.
435  */
436  void unsetLogLog()
437  {
438  if (loglog) {
439 
440  TIter next(this->GetListOfGraphs());
441 
442  while (TGraphErrors* graph = (TGraphErrors*)next()) {
443 
444  if (graph != NULL) {
445 
446  for (Int_t i = 0; i < graph->GetN(); ++i) {
447 
448  Double_t HV = -pow(base, graph->GetPointX(i));
449  Double_t gain = pow(base, graph->GetPointY(i));
450 
451  Double_t HVerror = graph->GetErrorX(i) * -HV * log(base);
452  Double_t gainError = graph->GetErrorY(i) * gain * log(base);
453 
454  graph->SetPoint (i, HV, gain);
455  graph->SetPointError(i, HVerror, gainError);
456  }
457  }
458  }
459 
460  loglog = false;
461  }
462  }
463 
464 
465  /**
466  * Set logarithmic base for log-log scaling.
467  *
468  * \param base logarithmic base for scaling
469  */
470  void setLogBase(const double base)
471  {
472  if (loglog) {
473 
474  TIter next(this->GetListOfGraphs());
475 
476  while (TGraphErrors* graph = (TGraphErrors*)next()) {
477 
478  if (graph != NULL) {
479 
480  for (Int_t i = 0; i < graph->GetN(); ++i) {
481 
482  Double_t absLogHV = graph->GetPointX(i) * log(this->base) / log(base);
483  Double_t logGain = graph->GetPointY(i) * log(this->base) / log(base);
484 
485  Double_t abslogHVerror = graph->GetErrorX(i) * log(this->base) / log(base);
486  Double_t logGainError = graph->GetErrorY(i) * log(this->base) / log(base);
487 
488  graph->SetPoint (i, absLogHV, logGain);
489  graph->SetPointError(i, abslogHVerror, logGainError);
490  }
491  }
492  }
493  }
494 
495  this->base = base;
496  }
497 
498 
499  /**
500  * Get graph with the input data for the interpolation.
501  *
502  * \return pointer to graph with input data
503  */
504  TGraphErrors* getData()
505  {
506  TGraphErrors* g1;
507 
508  TList* list = this->GetListOfGraphs();
509 
510  if (list != NULL && list->FindObject(HVGAINGRAPH_DATA) != NULL) {
511 
512  g1 = (TGraphErrors*)list->FindObject(HVGAINGRAPH_DATA);
513 
514  } else {
515 
516  g1 = new TGraphErrors();
517 
518  g1->SetName(HVGAINGRAPH_DATA);
519 
520  g1->Set(0);
521 
522  this->Add(g1);
523  }
524 
525  return g1;
526  }
527 
528 
529  /**
530  * Get graph with the interpolation result.
531  *
532  * \return pointer to graph with the interpolation result
533  */
534  TGraphErrors* getResult()
535  {
536  TGraphErrors* g0;
537 
538  TList* list = this->GetListOfGraphs();
539 
540  if (list != NULL && list->FindObject(HVGAINGRAPH_RESULT) != NULL) {
541 
542  g0 = (TGraphErrors*)list->FindObject(HVGAINGRAPH_RESULT);
543 
544  } else {
545 
546  g0 = new TGraphErrors();
547 
548  g0->SetName(HVGAINGRAPH_RESULT);
549 
550  g0->Set(0);
551 
552  this->Add(g0);
553  }
554 
555  return g0;
556  }
557 
558 
559  /**
560  * Clone this object.
561  *
562  * \param newname new name
563  */
564  JHVGainGraph* Clone(const char* newname = "") const
565  {
566  JHVGainGraph* clone = new JHVGainGraph(*this, loglog, base);
567 
568  clone->SetName(newname);
569 
570  return clone;
571  }
572 
573 
574  /**
575  * Set minimal separation distance for high-voltage.
576  *
577  * \param minDist minimal separation distance for high-voltage
578  */
579  static void setMinHVDistance(const double minDist)
580  {
581  dHVmin = minDist;
582  }
583 
584 
585  /**
586  * Set valid gain range.
587  *
588  * \param range valid high-voltage range [V]
589  */
590  static void setHVRange(const JRange<double> range)
591  {
592  hvRange = range;
593  }
594 
595 
596  /**
597  * Set valid gain range.
598  *
599  * \param range valid gain range
600  */
601  static void setGainRange(const JRange<double> range)
602  {
603  gainRange = range;
604  }
605 
606 
607  private:
608 
609  bool loglog; //!< Log-log scale toggle
610  double base; //!< Base for logarithmic scaling
611 
612  static double dHVmin; //!< Minimal high-voltage difference between two points [V]
613  static JRange<double> hvRange; //!< Allowed high-voltage range [V]
614  static JRange<double> gainRange; //!< Allowed gain range
615  };
616 
617 
618  /**
619  * Default values.
620  */
621  double JHVGainGraph::dHVmin = 2 * 3.14;
625 }
626 
627 #endif
static const char * HVGAINGRAPH_RESULT
Definition: JHVGainGraph.hh:30
const bool checkHV(const double HV1, const double HV2) const
Checks whether two high-voltage values are different.
void unsetLogLog()
Unset log-log scale.
Exceptions.
static void setGainRange(const JRange< double > range)
Set valid gain range.
T getLowerLimit() const
Get lower limit.
Definition: JRange.hh:202
JHVGainGraph(const char *name="HVGainGraph", const bool logScale=false, const double base=10.0)
Constructor.
Definition: JHVGainGraph.hh:45
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
TGraphErrors * getData()
Get graph with the input data for the interpolation.
static const char * HVGAINGRAPH_DATA
Definition: JHVGainGraph.hh:29
static const double FITTOT_GAIN_MAX
Default maximal gain.
Definition: JFitToT.hh:44
static const double FITTOT_GAIN_MIN
Default minimal gain.
Definition: JFitToT.hh:43
then fatal No sound hydrophone file $HYDROPHONE_TXT fi JGraph f $HYDROPHONE_TXT o $HYDROPHONE_ROOT sort gr k
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:670
JHVGainGraph(const TMultiGraph &object, const bool logScale, const double base=10.0)
Copy constructor.
Definition: JHVGainGraph.hh:72
const bool areIncreasing(const Int_t i, const Int_t j)
Checks whether the gains of two points are strictly increasing as function of their absolute high-vol...
void setLogBase(const double base)
Set logarithmic base for log-log scaling.
const bool checkHV(const double HV) const
Checks whether high-voltage is within range.
bool interpolate(const double gainTarget)
Inter-/Extrapolate the high-voltage value corresponding to the target gain value. ...
const bool checkGain(const double gain) const
Checks if gain is within range.
double getTargetHVError(const double gainTarget)
Get error estimate on high-voltage corresponding to given target gain value.
const bool areValid(const Int_t i, const Int_t j)
Checks whether two points are valid for inter-/extrapolation.
void SetPoint(Int_t i, Double_t HV, Double_t gain, Double_t gainError)
Set point with index i.
static void setHVRange(const JRange< double > range)
Set valid gain range.
TGraphErrors * getResult()
Get graph with the interpolation result.
Auxiliary data structure to store high-voltage versus gain data and interpolate the nominal high-volt...
Definition: JHVGainGraph.hh:35
static JRange< double > hvRange
Allowed high-voltage range [V].
T getUpperLimit() const
Get upper limit.
Definition: JRange.hh:213
T pow(const T &x, const double y)
Power .
Definition: JMath.hh:98
static void setMinHVDistance(const double minDist)
Set minimal separation distance for high-voltage.
void AddPoint(Double_t HV, Double_t gain, Double_t gainError)
Add point to diagram.
static const std::string HVGAINGRAPH_SUFFIX
Definition: JHVGainGraph.hh:27
JHVGainGraph * Clone(const char *newname="") const
Clone this object.
Range of values.
Definition: JRange.hh:38
double base
Base for logarithmic scaling.
z range($ZMAX-$ZMIN)< $MINIMAL_DZ." fi fi mv $WORKDIR/fit.root $MODULE_ROOT typeset -Z 4 STRING typeset -Z 2 FLOOR JPlot1D -f $
Definition: module-Z:fit.sh:84
then echo n User name
Definition: JCookie.sh:45
then $JPP_DIR examples JDetector JToT o $OUTPUT_FILE n N $NPE P gain
Definition: JToT.sh:45
double getTargetHV(const double gainTarget)
Get high-voltage corresponding to given target gain value.
Auxiliary class to define a range between two values.
static double dHVmin
Minimal high-voltage difference between two points [V].
int j
Definition: JPolint.hh:666
Exception for accessing a value in a collection that is outside of its range.
Definition: JException.hh:162
static JRange< double > gainRange
Allowed gain range.
bool loglog
Log-log scale toggle.
void setLogLog()
Set log-log scale.
then usage $script[input file[working directory[option]]] nWhere option can be N
Definition: JMuonPostfit.sh:37
Double_t g1(const Double_t x)
Function.
Definition: JQuantiles.cc:25