EUDAQ
 All Classes Namespaces Files Functions Variables Pages
ExplorerConverterPluginHelpers.h
1 #ifndef EXPLORER_CONVERTER_PLUGIN_HELPERS_H
2 #define EXPLORER_CONVERTER_PLUGIN_HELPERS_H
3 #if ROOT_FOUND
4 #include <iostream>
5 #include <fstream>
6 #include <vector>
7 #include <string>
8 #include <cstdlib>
9 
10 #ifdef WIN32
11 #include "Windows4Root.h"
12 #endif
13 
14 #include "TCanvas.h"
15 #include "TMath.h"
16 #include "TF1.h"
17 #include "TFitResultPtr.h"
18 #include "TH1D.h"
19 #include "TH2D.h"
20 #include "TGraphErrors.h"
21 #include "TFile.h"
22 
23 //
24 // use namespace instead of class
25 //
26 
27 //-------------------------------------------------------------------------------------------------
28 // static class containing the properties of the Explorer-1 matrices used in
29 // that gain measurement
30 class Ex1Prop {
31 public:
32  static const int n_pix; // number of pixels in the complete matrix
33  static const int n_sec; // number of sectors per pitch
34  static const int n_rst; // different reset types (non-permanent and permanent)
35  static const int n_mem; // different memories (mem1, mem2 and cds:=mem1-mem2)
36  static const int w[2]; // number of pixels per column/row for a given pitch
37  static const int p[2]; // pixel pitch in um
38  static const int n_pitch; // number of different pitches
39  static const float
40  meas_offset; // offset voltage appllied to the op amp on the proximity
41 };
42 
43 const int Ex1Prop::n_pix = 11700;
44 const int Ex1Prop::n_sec = 9;
45 const int Ex1Prop::n_rst = 2;
46 const int Ex1Prop::n_mem = 3;
47 const int Ex1Prop::w[] = {90, 60};
48 const int Ex1Prop::p[] = {20, 30};
49 const int Ex1Prop::n_pitch = sizeof(Ex1Prop::p) / sizeof(int);
50 const float Ex1Prop::meas_offset =
51  1.8 / 2.; // circuit on proximity leads to a divided by 2
52 
53 //-------------------------------------------------------------------------------------------------
54 Float_t ADC_counts_to_V(Float_t val, Bool_t apply_offset = kTRUE) {
55  // theorectical conversion:
59  // const float ADC_val_rng = 4096.; // 12bit
60  // const float ADC_volt_rng = 2.; // Vpp
61  // const float gain = -1.25*2.0; // circuit gain (SRS * Proximity)
62  // return (apply_offset) ? val/ADC_val_rng*ADC_volt_rng/gain +
63  // Ex1Prop::meas_offset
64  // : val/ADC_val_rng*ADC_volt_rng/gain;
65 
66  // measured conversion from self-test hybrid, mean value of all 4 channels:
67  return (apply_offset) ? (6101.8 - val) / 4507.8 : -val / 4507.8;
68 }
69 
70 //-------------------------------------------------------------------------------------------------
71 Float_t V_to_ADC_counts(Float_t val, Bool_t apply_offset = kTRUE) {
72  // theorectical conversion
76  // const float ADC_val_rng = 4096.; // 12bit
77  // const float ADC_volt_rng = 2.; // Vpp
78  // const float gain = -1.25*2.0; // circuit gain (SRS * Proximity)
79  // return (apply_offset) ? (val -
80  // Ex1Prop::meas_offset)*ADC_val_rng/ADC_volt_rng*gain
81  // : val*ADC_val_rng/ADC_volt_rng*gain;
82 
83  // measured conversion from self-test hybrid, mean value of all 4 channels
84  return (apply_offset) ? 6101.8 - val * 4507.8 : -val * 4507.8;
85 }
86 
87 //-------------------------------------------------------------------------------------------------
88 Float_t DAC_counts_to_V(Int_t val) {
89  // input (DAC counts)
90 
91  return val / 4096. * 5.;
92 }
93 
94 //-------------------------------------------------------------------------------------------------
95 Float_t V_to_C(Float_t val) {
96  // converting a signal in volts into a capacitance assuming the signal to be a
97  // Fe-55 generating
98  // 1640 electrons of 1.602e-19C
99 
100  return 1640 * 1.602e-19 / val;
101 }
102 
103 //-------------------------------------------------------------------------------------------------
104 bool read_list_file(std::string name, std::vector<float> *vec) {
105  std::ifstream f(name.c_str());
106  std::string l;
107  if (f.is_open()) {
108  while (f.good()) {
109  getline(f, l);
110  if (l.length() > 0) {
111  vec->push_back(atof(l.c_str())); // C++11 => std::stod(l)
112  }
113  }
114  } else
115  return false;
116  return true;
117 }
118 
119 //-------------------------------------------------------------------------------------------------
120 int pix_pitch(int ipix) {
121  return (ipix < Ex1Prop::w[0] * Ex1Prop::w[0]) ? Ex1Prop::p[0] : Ex1Prop::p[1];
122 }
123 
124 //-------------------------------------------------------------------------------------------------
125 int pix_row(int ipix) {
126  return (ipix < Ex1Prop::w[0] * Ex1Prop::w[0])
127  ? ipix % Ex1Prop::w[0]
128  : (ipix - Ex1Prop::w[0] * Ex1Prop::w[0]) % Ex1Prop::w[1];
129 }
130 
131 //-------------------------------------------------------------------------------------------------
132 int pix_col(int ipix) {
133  return (ipix < Ex1Prop::w[0] * Ex1Prop::w[0])
134  ? ipix / Ex1Prop::w[0]
135  : (ipix - Ex1Prop::w[0] * Ex1Prop::w[0]) / Ex1Prop::w[1];
136 }
137 
138 //-------------------------------------------------------------------------------------------------
139 int pix_sec(int ipix) {
140  int w =
141  (ipix < Ex1Prop::w[0] * Ex1Prop::w[0]) ? Ex1Prop::w[0] : Ex1Prop::w[1];
142  int r_sec = (pix_row(ipix) * 3) / w;
143  int c_sec = (pix_col(ipix) * 3) / w;
144  return r_sec + c_sec * 3;
145 }
146 
147 //-------------------------------------------------------------------------------------------------
148 std::string mem_str(int i) {
149  switch (i) {
150  case 0:
151  return "mem1";
152  break;
153  case 1:
154  return "mem2";
155  break;
156  case 2:
157  return "cds";
158  break;
159  default:
160  return "error";
161  break;
162  }
163  return "error";
164 }
165 
166 //-------------------------------------------------------------------------------------------------
167 std::string rst_str(int i) {
168  switch (i) {
169  case 0:
170  return "perm-rst";
171  break;
172  case 1:
173  return "non-perm-rst";
174  break;
175  default:
176  return "error";
177  break;
178  }
179  return "error";
180 }
181 
182 //-------------------------------------------------------------------------------------------------
183 int transpose_sec(int i) { return (i % 3) * 3 + (i / 3); }
184 
185 //-------------------------------------------------------------------------------------------------
186 int centre_pix_sec(int i_sec, int i_pitch) {
187  // selecting the lower right of the center pixels
188  // [ ][ ]
189  // [ ][x]
190  // starting with (r=0,c=0) top left, (r=0,c=89) top right and (r=89,c=89) at
191  // bottom right
192  int offset = i_pitch * Ex1Prop::w[0] * Ex1Prop::w[0];
193  int row = Ex1Prop::w[i_pitch] * (0.5 + i_sec % 3) / 3.;
194  int col = Ex1Prop::w[i_pitch] * (0.5 + i_sec / 3) / 3.;
195  return offset + col * Ex1Prop::w[i_pitch] + row;
196 }
197 
198 //-------------------------------------------------------------------------------------------------
199 Int_t get_index(Double_t *x, Float_t val, Int_t n) {
200  for (Int_t i = 0; i < n; ++i) {
201  if ((x[i] <= val && x[i + 1] > val) || (x[i] > val && x[i + 1] <= val)) {
202  if (x[i] - val < x[i + 1] - val)
203  return i;
204  else
205  return i + 1;
206  }
207  }
208  return 0;
209 }
210 
211 //-------------------------------------------------------------------------------------------------
212 Float_t calc_gain(Float_t *x, Float_t *y, Int_t index, Int_t mode = 0) {
213  switch (mode) {
214  case 0:
215  return (y[index + 1] - y[index]) / (x[index + 1] - x[index]);
216  break;
217  case 1:
218  return (y[index + 1] - y[index - 1]) / (x[index + 1] - x[index - 1]);
219  break;
220  }
221  return 0.;
222 }
223 
224 //-------------------------------------------------------------------------------------------------
225 Float_t calc_inl(Double_t *x, Double_t *y, Int_t i_start, Int_t i_end,
226  Float_t gain) {
227  Float_t expected_sig = gain * (x[i_end] - x[i_start]);
228  Float_t real_sig = y[i_end] - y[i_start];
229  return (real_sig / expected_sig - 1.);
230 }
231 
232 //-------------------------------------------------------------------------------------------------
233 Float_t calc_dnl(Float_t x, Float_t x2) {
234  return TMath::Abs(TMath::Abs(x - x2) / x);
235 }
236 
237 //-------------------------------------------------------------------------------------------------
238 void average(Int_t n, Float_t *y, Float_t *y_err, Int_t mode = 0,
239  Int_t avg_width = 11) {
240  // mode 0: weighted mean
241  // 1: unweighted mean
242 
243  Float_t *t = new Float_t[n];
244  Float_t *t_err = new Float_t[n];
245 
246  memcpy(t, y, sizeof(Float_t) * n);
247  memcpy(t_err, y_err, sizeof(Float_t) * n);
248  // zero out border values
249  for (Int_t a = 0; a < avg_width; ++a) {
250  y[a] = 0.;
251  y_err[a] = 0.;
252  y[n - 1 - a] = 0.;
253  y_err[n - 1 - a] = 0.;
254  }
255 
256  for (Int_t i = 0; i < n - avg_width; ++i) {
257  Float_t sum_of_weights = 0.;
258  Float_t mean = 0.;
259  Float_t mean_sq = 0.;
260  for (Int_t a = 0; a < avg_width; ++a) {
261  Float_t w = (mode == 0) ? 1. / (t_err[i + a] * t_err[i + a]) : 1.;
262  sum_of_weights += w;
263  mean += w * t[i + a];
264  mean_sq += w * t[i + a] * t[i + a];
265  }
266  mean /= sum_of_weights;
267  mean_sq /= sum_of_weights;
268  y[i + avg_width / 2] = mean;
269  y_err[i + avg_width / 2] = (mode == 0) ? TMath::Sqrt(1 / sum_of_weights)
270  : TMath::Sqrt(mean_sq - mean * mean);
271  }
272 }
273 
274 //-------------------------------------------------------------------------------------------------
275 float read_vrst(std::string file) {
276  std::ifstream f(file.c_str());
277  std::string l;
278  if (f.is_open()) {
279  while (f.good()) {
280  getline(f, l);
281  if (l.length() > 0) {
282  return atof(l.c_str()); // C++11 => std::stod(l)
283  }
284  }
285  } else {
286  std::cerr << "Couldn't read input file" << std::endl;
287  return 0.0;
288  }
289  return 0.0;
290 }
291 
292 //-------------------------------------------------------------------------------------------------
293 struct gain_fit_result {
294  // gain and error obtained from the linear fit
295  Float_t g_lf;
296  Float_t e_lf;
297  Float_t ndf_lf;
298  Float_t chi2_lf;
299 
300  // offset, linear and quadratic gain factors and errors obtained in the
301  // quadratic fit
302  Float_t g_qf; // linear gain factor
303  Float_t e_qf; // inear gain factor error
304  Float_t g2_qf; // quadratic gain factor
305  Float_t e2_qf; // quadratic gain factor error
306  Float_t off_qf; // offset
307  Float_t eff_qf; // offset error
308  Float_t ndf_qf;
309  Float_t chi2_qf;
310 
311  // offset, linear and cubic gain factors and errors obtained in the cubic fit
312  Float_t g_cf; // linear gain factor
313  Float_t e_cf; // inear gain factor error
314  Float_t g2_cf; // quadratic gain factor
315  Float_t e2_cf; // quadratic gain factor error
316  Float_t g3_cf; // cubic gain factor
317  Float_t e3_cf; // cubic gain factor error
318  Float_t off_cf; // offset
319  Float_t eff_cf; // offset error
320  Float_t ndf_cf;
321  Float_t chi2_cf;
322 
323  // the fit results
324  TFitResultPtr r_lf;
325  TFitResultPtr r_qf;
326  TFitResultPtr r_cf;
327 };
328 
329 gain_fit_result *do_gain_fits(TGraphErrors *g, Float_t v_rst = 0.8,
330  Float_t v_sig = 0.10) {
331  if ((v_rst - v_sig) < 0.51) {
332  std::cout << "-->>>>> WARNING: fit range might be going to a to small "
333  "value!!!, please check results" << std::endl;
334  std::cout << g->GetName() << std::endl;
335  }
336 
337  gain_fit_result *result = new gain_fit_result;
338 
339  TF1 *f_lin =
340  new TF1("f_lin", TString::Format("[0]+[1]*(x-%f)", v_rst - .5 * v_sig),
341  v_rst - v_sig, v_rst);
342  f_lin->SetLineWidth(1);
343  TF1 *f_quad =
344  new TF1("f_quad", TString::Format("[0]+[1]*(x-%f)+[2]*(x-%f)*(x-%f)",
345  v_rst - .5 * v_sig, v_rst - .5 * v_sig,
346  v_rst - .5 * v_sig),
347  v_rst - v_sig, v_rst);
348  f_quad->SetLineWidth(1);
349  TF1 *f_cube = new TF1(
350  "f_cube", TString::Format(
351  "[0]+[1]*(x-%f)+[2]*(x-%f)*(x-%f)+[3]*(x-%f)*(x-%f)*(x-%f)",
352  v_rst - .5 * v_sig, v_rst - .5 * v_sig, v_rst - .5 * v_sig,
353  v_rst - .5 * v_sig, v_rst - .5 * v_sig, v_rst - .5 * v_sig),
354  v_rst - v_sig, v_rst);
355  f_cube->SetLineWidth(1);
356 
357  result->r_lf = g->Fit(f_lin, "QSR");
358  result->g_lf = f_lin->GetParameter(1);
359  result->e_lf = f_lin->GetParError(1);
360  result->ndf_lf = f_lin->GetNDF();
361  result->chi2_lf = f_lin->GetChisquare();
362 
363  result->r_qf = g->Fit(f_quad, "QSR");
364  result->g_qf = f_quad->GetParameter(1);
365  result->e_qf = f_quad->GetParError(1);
366  result->g2_qf = f_quad->GetParameter(2);
367  result->e2_qf = f_quad->GetParError(2);
368  result->off_qf = f_quad->GetParameter(0);
369  result->eff_qf = f_quad->GetParError(0);
370  result->ndf_qf = f_quad->GetNDF();
371  result->chi2_qf = f_quad->GetChisquare();
372 
373  f_cube->SetParameters(f_quad->GetParameter(0), f_quad->GetParameter(1),
374  f_quad->GetParameter(2), 0);
375  result->r_cf = g->Fit(f_cube, "QSR");
376  // result->r_cf = g->Fit(f_cube, "SR");
377  result->g_cf = f_cube->GetParameter(1);
378  result->e_cf = f_cube->GetParError(1);
379  result->g2_cf = f_cube->GetParameter(2);
380  result->e2_cf = f_cube->GetParError(2);
381  result->g3_cf = f_cube->GetParameter(3);
382  result->e3_cf = f_cube->GetParError(3);
383  result->off_cf = f_cube->GetParameter(0);
384  result->eff_cf = f_cube->GetParError(0);
385  result->ndf_cf = f_cube->GetNDF();
386  result->chi2_cf = f_cube->GetChisquare();
387 
388  delete f_lin;
389  f_lin = 0x0;
390  delete f_quad;
391  f_quad = 0x0;
392  delete f_cube;
393  f_cube = 0x0;
394 
395  return result;
396 }
397 
398 //-------------------------------------------------------------------------------------------------
399 TH1D *dist_from_map(TH2D *h, Int_t x_low = 1, Int_t x_up = -1, Int_t y_low = 1,
400  Int_t y_up = -1, TString name = "") {
401  // add suffix which indicates, that the distribution is based on a subsection
402  // only
403  name = (name.Length() == 0) ? TString::Format("dist_%s", h->GetName()) : name;
404 
405  TH1D *dist = new TH1D(
406  name, TString::Format(";%s;probability", h->GetZaxis()->GetTitle()), 1000,
407  h->GetMinimum(), h->GetMaximum());
408  dist->Sumw2();
409 
410  x_up = (x_up == -1) ? h->GetNbinsX() : x_up;
411  y_up = (y_up == -1) ? h->GetNbinsY() : y_up;
412 
413  for (Int_t i_x = x_low; i_x <= x_up; ++i_x) {
414  for (Int_t i_y = y_low; i_y <= y_up; ++i_y) {
415  dist->Fill(h->GetBinContent(i_x, i_y));
416  }
417  }
418 
419  dist->Scale(1. / dist->Integral());
420  return dist;
421 }
422 
423 //-------------------------------------------------------------------------------------------------
424 class GainCorrection {
425 protected:
426  TFile *fMapFile;
427  TH2 *fOffsetMap;
428  TH2 *fGainMap;
429  TH2 *fGain2Map;
430  TH2 *fGain3Map;
431  TH2 *fEffVresetMap;
432  TH2 *fVresetNPROutMap;
433 
434  TF1 *fFit;
435 
436  float fVsig;
437 
438  int fPitch;
439  int fMem;
440  float fVbb;
441  float fVrstRef;
442  int fChan;
443 
444  float fOffset;
445  float fGain;
446  float fGain2;
447  float fGain3;
448  float fEffVrst;
449  float fVrstNPROut;
450 
451  bool fMapsAreLoaded;
452 
454  bool LoadMaps() {
455  // loaded the maps necessary to do the correction
456  if (fEffVresetMap) {
457  delete fEffVresetMap;
458  fEffVresetMap = 0x0;
459  }
460  if (fVresetNPROutMap) {
461  delete fVresetNPROutMap;
462  fVresetNPROutMap = 0x0;
463  }
464  if (fOffsetMap) {
465  delete fOffsetMap;
466  fOffsetMap = 0x0;
467  }
468  if (fGainMap) {
469  delete fGainMap;
470  fGainMap = 0x0;
471  }
472  if (fGain2Map) {
473  delete fGain2Map;
474  fGain2Map = 0x0;
475  }
476  if (fGain3Map) {
477  delete fGain3Map;
478  fGain3Map = 0x0;
479  }
480  fMapFile->cd();
481  fMapsAreLoaded =
482  true; // all maps are good -> changed below in case of problems
483 
484  // effective reset voltage
485  TString eff_vrst_map_name = TString::Format(
486  "eff_vrst_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
487  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
488  gDirectory->GetObject(eff_vrst_map_name, fEffVresetMap);
489  if (!fEffVresetMap) {
490  fMapsAreLoaded = false;
491  std::cerr << "Couldn't load the corresponding vrst map: "
492  << eff_vrst_map_name.Data() << std::endl;
493  }
494  // vrst at output for NPR
495  TString vrst_npr_out_map_name = TString::Format(
496  "vrst_npr_out_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
497  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
498  gDirectory->GetObject(vrst_npr_out_map_name, fVresetNPROutMap);
499  if (!fVresetNPROutMap) {
500  fMapsAreLoaded = false;
501  std::cerr << "Couldn't load the corresponding vrst map: "
502  << vrst_npr_out_map_name.Data() << std::endl;
503  }
504 
505  // offset (linear term parameter p0)
506  TString offset_map_name = TString::Format(
507  "off_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
508  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
509  gDirectory->GetObject(offset_map_name, fOffsetMap);
510  if (!fOffsetMap) {
511  fMapsAreLoaded = false;
512  std::cerr << "Couldn't load the corresponding gain map: "
513  << offset_map_name.Data() << std::endl;
514  }
515 
516  // gain (linear term parameter p1)
517  TString g_map_name =
518  TString::Format("g_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
519  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
520  gDirectory->GetObject(g_map_name, fGainMap);
521  if (!fGainMap) {
522  fMapsAreLoaded = false;
523  std::cerr << "Couldn't load the corresponding gain map: "
524  << g_map_name.Data() << std::endl;
525  }
526 
527  // gain correction (quadratic term parameter p2)
528  TString g2_map_name = TString::Format(
529  "g2_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
530  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
531  gDirectory->GetObject(g2_map_name, fGain2Map);
532  if (!fGain2Map) {
533  fMapsAreLoaded = false;
534  std::cerr << "Couldn't load the corresponding gain correction map: "
535  << g2_map_name.Data() << std::endl;
536  }
537 
538  // gain correction (cubic term parameter p3)
539  TString g3_map_name = TString::Format(
540  "g3_map_vbb%0.1f_vrst%.2f_p%d_%s_chan%d", fVbb, fVrstRef,
541  Ex1Prop::p[fPitch], mem_str(fMem).c_str(), fChan);
542  gDirectory->GetObject(g3_map_name, fGain3Map);
543  if (!fGain3Map) {
544  fMapsAreLoaded = false;
545  std::cerr << "Couldn't load the corresponding gain correction map: "
546  << g3_map_name.Data() << std::endl;
547  }
548 
549  // fit function
550  if (fFit) {
551  delete fFit;
552  fFit = 0x0;
553  }
554  fFit = new TF1(
555  "fit",
556  "[0]+[1]*(x-[4])+[2]*(x-[4])*(x-[4])+[3]*(x-[4])*(x-[4])*(x-[4])", 0.5,
557  0.8);
558 
559  return fMapsAreLoaded;
560  }
561 
562 public:
563  GainCorrection()
564  : fMapFile(0x0), fOffsetMap(0x0), fGainMap(0x0), fGain2Map(0x0),
565  fGain3Map(0x0), fEffVresetMap(0x0), fVresetNPROutMap(0x0), fFit(0x0),
566  fVsig(0.1), fPitch(-1), fMem(1), fVbb(1.8), fVrstRef(0.7), fChan(-1),
567  fOffset(0.), fGain(0.), fGain2(0.), fGain3(0.), fEffVrst(0.),
568  fVrstNPROut(0.), fMapsAreLoaded(false) {}
569  bool SetDataFile(TString filename) {
570  TCanvas *mydummycanvas = new TCanvas();
571  if (fMapFile) {
572  delete fMapFile;
573  fMapFile = 0x0;
574  }
575  fMapFile = new TFile(filename.Data());
576  return (fMapFile && fMapFile->IsOpen());
577  };
578  void SetPitch(int p) {
579  fPitch = p;
580  fMapsAreLoaded = false;
581  };
582  void SetVbb(float vbb) {
583  fVbb = vbb - 0.01;
584  fMapsAreLoaded = false;
585  }; // nasty trick to achieve -0.0
586  void SetVrstRef(float vrr) {
587  fVrstRef = vrr;
588  fMapsAreLoaded = false;
589  };
590  void SetMem(int mem) {
591  fMem = mem;
592  fMapsAreLoaded = false;
593  };
594  void SetVsig(float vsig) {
595  fVsig = vsig;
596  fMapsAreLoaded = false;
597  };
598  void SetChan(int chan) {
599  fChan = chan;
600  fMapsAreLoaded = false;
601  };
602 
603  float CorrectValue(float value, int i_row, int i_col, bool woOffset = true) {
604  if (!fMapsAreLoaded)
605  LoadMaps();
606  if (!fMapsAreLoaded) {
607  std::cerr << "Failed to load the corresponding map!" << std::endl;
608  return -1.;
609  }
610  if (i_row < 0 || i_row >= Ex1Prop::w[fPitch]) {
611  std::cerr << "row index out of bounds" << std::endl;
612  return -1;
613  }
614  if (i_col < 0 || i_col >= Ex1Prop::w[fPitch]) {
615  std::cerr << "column index out of bounds" << std::endl;
616  return -1;
617  }
618  fOffset = fOffsetMap->GetBinContent(i_col + 1, i_row + 1);
619  fGain = fGainMap->GetBinContent(i_col + 1, i_row + 1);
620  fGain2 = fGain2Map->GetBinContent(i_col + 1, i_row + 1);
621  fGain3 = fGain3Map->GetBinContent(i_col + 1, i_row + 1);
622  fEffVrst = fEffVresetMap->GetBinContent(i_col + 1, i_row + 1);
623  fVrstNPROut = fVresetNPROutMap->GetBinContent(i_col + 1, i_row + 1);
624 
625  // woOffset assumes the value to be relative to the currently selected
626  // memory
627  // for the explorer this should be the
628  // please note that this is not necessarily correct due to the CDS shifting
629  // the dynamic
630  // range
631 
632  // old: has issue that val is output val, i.e. misses gain correction, but
633  // it enters on Vrst axis in formula
639 
640  // jacobus 20.10.2014
641  // see his notebook for formula changes
642  // if (TMath::Abs(value)>50 && fChan==2) {
643  // std::cout << "------ row: " << i_row << ", col: " << i_col << "
644  // -----" << std::endl;
645  // std::cout << value << std::endl;
646  // std::cout << ADC_counts_to_V(value, !woOffset) << std::endl;
647  // std::cout << fOffset << std::endl;
648  // std::cout << fGain << std::endl;
649  // std::cout << fGainCorr << std::endl;
650  // std::cout << value*(fGain+fGainCorr*(-ADC_counts_to_V(value,
651  // !woOffset)+fVsig)) << std::endl;
652  // //std::cout << fOffset + fGain*(value-fVrstNPROut+0.5*fVsig) +
653  // fGainCorr*(value-fVrstNPROut+0.5*fVsig)*(value-fVrstNPROut+0.5*fVsig)
654  // << std::endl;
655  // std::cout << fVrstNPROut << std::endl;
656  // std::cout << fVsig << std::endl;
657  //}
658 
659  value = ADC_counts_to_V(value, !woOffset);
660 
661  // quadratic fit with start of fit at fVrstNPROut
662  // value = (woOffset) ?
663  // value*(fGain+fGain2*(-value+fVsig)):
664  // fOffset + fGain2*(value-fVrstNPROut+0.5*fVsig) +
665  // fGain2*(value-fVrstNPROut+0.5*fVsig)*(value-fVrstNPROut+0.5*fVsig)
666  // +
667  // fGain3*(value-fVrstNPROut+0.5*fVsig)*(value-fVrstNPROut+0.5*fVsig)*(value-fVrstNPROut+0.5*fVsig);
668 
669  // cubic fit
670  Float_t vref = fVrstNPROut + 0.01 - fVsig / 2;
671  fFit->SetParameters(fOffset, fGain, fGain2, fGain3, vref);
672  value = (woOffset)
673  ? fFit->Eval(fVrstNPROut) - fFit->Eval(fVrstNPROut - value)
674  : fFit->Eval(value);
675 
676  return V_to_ADC_counts(value, !woOffset);
677  }
678 };
679 
680 #endif
681 #endif