Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JTuneHV.cc
Go to the documentation of this file.
1 
2 #include <time.h>
3 #include <string>
4 #include <iostream>
5 #include <iomanip>
6 
7 #include "Jeep/JPrint.hh"
8 #include "Jeep/JParser.hh"
9 #include "Jeep/JMessage.hh"
10 
11 #include "JSupport/JMeta.hh"
12 
13 #include "JTools/JMap.hh"
14 #include "JTools/JMultiMap.hh"
15 
16 #include "dbclient/KM3NeTDBClient.h"
17 
18 #include "JDB/JDB.hh"
19 #include "JDB/JDBToolkit.hh"
20 #include "JDB/JDBincludes.hh"
21 #include "JDB/JSelector.hh"
24 #include "JDB/JProductRouter.hh"
25 
26 #include "JDetector/JDetector.hh"
30 
31 #include "JCalibrate/JFitToT.hh"
32 
33 #include "JGizmo/JManager.hh"
34 
35 #include "JSon/JSon.hh"
36 
37 #include "JROOT/JRootToolkit.hh"
38 
39 #include "TFile.h"
40 #include "TGraphErrors.h"
41 
42 
43 /**
44  * \file
45  *
46  * Example program to fit the gain to the high-voltage
47  * \author acreusot, mdejong and bjung
48  */
49 int main(int argc, char **argv)
50 {
51  using namespace std;
52  using namespace JPP;
53 
54  typedef JMAPLIST<JMap,JMap,JMap,JMap>::maplist JMapList_t;
55  typedef JMultiMap<int, JUPI, JMapList_t> JMultiMap_t;
56 
57  typedef typename JMultiMap_t::super_const_iterator JSuperIt_t;
58 
59  typedef pair<double,double> element_t;
60  typedef map<JUPI, map<double, element_t>> datamap_t;
61 
62 
63  string usr;
64  string pwd;
65  string cookie;
66  map<int, string> inputFiles;
67  int detid;
68  string outputFile;
69  string graphFile;
70  string testType;
71  string testProduct;
72  double HVerr;
73  string option;
74  int debug;
75 
76 
77  try {
78 
79  JParser<> zap("Example program to find optimal HV-settings.");
80 
81  zap['u'] = make_field(usr) = "";
82  zap['!'] = make_field(pwd) = "";
83  zap['C'] = make_field(cookie) = "";
84  zap['f'] = make_field(inputFiles, "map of run numbers and associated ToT-fit root files (JFitToT output)");
85  zap['D'] = make_field(detid, "detector ID");
86  zap['T'] = make_field(testType, "test type") = "HV-TUNING-SEA-GAIN-v1";
87  zap['P'] = make_field(testProduct, "test product") = ""; // For testing the DB-uploading
88  zap['e'] = make_field(HVerr, "Error on high-voltage measurements [V]") = 5.0; // [V]
89  zap['O'] = make_field(outputFile, "HV tuning calibration file (json format)");
90  zap['o'] = make_field(graphFile, "Graphical output (root format)") = "";
91  zap['d'] = make_field(debug, "debug") = 1;
92 
93  zap(argc, argv);
94  }
95  catch(const exception &error) {
96  FATAL(error.what() << endl);
97  }
98 
99  // Start time
100  time_t startTime = time(0);
101 
102  vector<string> runNumbers;
103 
104  JPersons person;
105  JMultiMap_t locMap;
106  datamap_t dataMap;
107 
108  try {
109 
110  // Extract user info
111  JDB::reset(usr, pwd, cookie);
112  {
113  JSelector selector = getSelector<JPersons>(JDB::get()->User());
114  ResultSet& rs = getResultSet(getTable<JPersons>(), selector);
115  rs >> person;
116  rs.Close();
117  }
118 
119 
120  // Extract detector integration info
121  {
123  ResultSet& rs = getResultSet(getTable<JDetectorIntegration>(), selector);
124 
125  for (JDetectorIntegration detint; rs >> detint; ) {
126 
127  if (detint.PMTID >= 0) {
128 
129  const JUPI upi = detint.PMTUPI;
130 
131  locMap[detint.DOMID][detint.DUID][detint.FLOORID][detint.PMTID] = upi;
132  }
133  }
134 
135  rs.Close();
136  }
137 
138 
139  // Extract gain and high-voltage data
140  for (map<int,string>::const_iterator fileIt = inputFiles.begin(); fileIt != inputFiles.end(); ++fileIt) {
141 
142  const int runNr = fileIt->first;
143 
144  NOTICE("Extracting Gain-/HV-data for run " << runNr << endl);
145  runNumbers.push_back(to_string(runNr));
146 
147  // Retrieve high-voltage settings
148  map<JUPI, double> HVmap;
149 
150  {
151  JSelector selector = getSelector<JPMTHVRunSettings>(getDetector(detid), fileIt->first);
152  ResultSet& rs = getResultSet(getTable<JPMTHVRunSettings>(), selector);
153 
154 
155  for (JPMTHVRunSettings parameters; rs >> parameters; ) {
156 
157  for (JSuperIt_t locIt = locMap.super_begin(); locIt != locMap.super_end(); ++locIt) {
158 
159  if (parameters.DUID == locIt->second->first &&
160  parameters.FLOORID == locIt->second->second->first &&
161  parameters.PMTINTID == locIt->second->second->second->first) {
162 
163  const JUPI upi = locIt.getValue();
164 
165  HVmap[upi] = log(fabs(parameters.HV_VALUE));
166  }
167  }
168  }
169 
170  rs.Close();
171  }
172 
173 
174  // Retrieve fitted gains
175  TFile in(fileIt->second.c_str(), "READ");
176  TIter next(in.GetListOfKeys());
177 
178  while(TKey* key = (TKey*)next()) {
179 
180  const string name(key->GetName());
181  if (!gROOT->GetClass(key->GetClassName())->InheritsFrom("TH1") ||
182  name.find("1ToT") == string::npos) { continue; }
183 
184  const int pos = name.find(".");
185  const int modID = stoi(name.substr(0, pos));
186  const int pmtID = stoi(name.substr(pos+1, 2));
187 
188  for (JSuperIt_t locIt = locMap.super_begin(); locIt != locMap.super_end(); ++locIt) {
189 
190  if (modID == locIt->first &&
191  pmtID == locIt->second->second->second->first) {
192 
193  const JUPI upi = locIt.getValue();
194  const double logAbsHV = HVmap[upi];
195 
196  const TH1* h1 = (TH1*) key->ReadObj();
197  const TF1* f1 = h1->GetFunction(FITTOT_FNAME.c_str());
198 
199  double gain, gainErr;
200  if (f1 != NULL) {
201 
202  const int Ngain = f1->GetParNumber("gain");
203 
204  gain = f1->GetParameter(Ngain);
205  gainErr = f1->GetParError (Ngain);
206 
207  } else {
208 
209  const double prevG = (dataMap[upi].size() > 0 ?
210  (--(dataMap[upi].lower_bound(logAbsHV)))->second.first : log(FITTOT_GAIN_MIN));
211 
212  gain = (prevG > log(NOMINAL_GAIN) ? FITTOT_GAIN_MAX : FITTOT_GAIN_MIN);
213  gainErr = 0.0;
214  }
215 
216  dataMap[upi][logAbsHV] = element_t{log(gain), gainErr / gain};
217  }
218  }
219  }
220  }
221  }
222  catch (const exception& error) {
223  FATAL(error.what() << endl);
224  }
225 
226 
227  // Find optimal HV corresponding to a nominal gain of 1.0
228  // via linear interpolation in log-log scale
229  JHVCalibration HVcalibrations;
230 
231  JManager<string, TGraphErrors> manager(new TGraphErrors(), '%', ios::fmtflags(), MAKE_STRING("%_HVxG"));
232 
233  NOTICE("Searching optimal high-voltage settings...\n\t" <<
234  "High-Voltage [V] --- Gain [-]" << endl);
235 
236  for (datamap_t::const_iterator pmt = (testProduct.empty() ? dataMap.cbegin() : dataMap.find(testProduct)) ;
237  pmt != (testProduct.empty() ? dataMap.cend() : ++(dataMap.find(testProduct)));
238  ++pmt) {
239 
240  const JUPI upi = pmt->first;
241  const map<double, element_t> data = pmt->second;
242 
243  string location, serialID;
244  for (JSuperIt_t locIt = locMap.super_begin(); locIt != locMap.super_end(); ++locIt) {
245 
246  if (locIt.getValue().getVariant() == upi.getVariant()) {
247 
248  char buffer[100];
249 
250  sprintf(buffer, "%02d.%02d.%02d",
251  locIt->second->first,
252  locIt->second->second->first,
253  locIt->second->second->second->first);
254  location = string(buffer);
255 
256  sprintf(buffer, "%08d.%02d",
257  locIt->first,
258  locIt->second->second->second->first);
259  serialID = string(buffer);
260  }
261  }
262 
263  NOTICE(upi << " (a.k.a. " << serialID << " / " << location << "):\n\t");
264 
265  if (data.size() < 2) {
266 
267  WARNING("Insufficient data; skip!" << endl);
268  continue;
269  }
270 
271  manager[serialID]->Set(data.size());
272  manager[serialID]->SetMarkerStyle(kFullDotSmall);
273 
274  const double logNominalGain = log(NOMINAL_GAIN);
275 
276  const double D1 = fabs(logNominalGain - log(FITTOT_GAIN_MAX));
277  const double D2 = fabs(logNominalGain - log(FITTOT_GAIN_MIN));
278  double minDistance = (D2 > D1 ? D2 : D1);
279 
280  map<double, element_t>::const_iterator k0 = data.cbegin();
281  map<double, element_t>::const_iterator k1 = data.cbegin();
282 
283  for (map<double, element_t>::const_iterator it = data.cbegin(); it != data.cend(); ++it) {
284 
285  // Plot point
286  const int dIt = distance(data.cbegin(), it);
287  manager[serialID]->SetPoint(dIt, it->first / log(10), it->second.first / log(10));
288  manager[serialID]->SetPointError(dIt, fabs(HVerr / exp(it->first) / log(10)), fabs(it->second.second / log(10)));
289 
290  // Find the point closest to the nominal gain-value (k0)
291  // and a compatible auxiliary point (k1) for inter-/extrapolation
292  const double distance = fabs(logNominalGain - it->second.first);
293 
294  if (distance < minDistance) {
295 
296  k0 = it;
297 
298  k1 = ( it->second.first < logNominalGain ?
299  (it != --data.cend() ? next(it,1) : prev(it,1)) : // Closest point below nominal gain
300  (it != data.cbegin() ? prev(it,1) : next(it,1)) ); // Closest point above nominal gain
301 
302  minDistance = distance;
303  }
304  }
305 
306  // Determine optimal high-voltage via linear inter-/extrapolation
307  bool valid = false;
308  pair<double, double> result{-exp(k0->first), exp(k0->second.first)};
309  pair<double, double> errors{ HVerr, exp(k0->second.second)};
310 
311  if ((k1->first < k0->first && k1->second.first < k0->second.first) ||
312  (k1->first > k0->first && k1->second.first > k0->second.first)) {
313 
314  // Logarithmic supply-voltage, logarithmic gain and logarithmic errors
315  // for point closest to the nominal gain (0) and for the auxiliary point (1)
316  const double logHV0 = k0->first;
317  const double logHV1 = k1->first;
318 
319  const double logHV0err = HVerr / exp(logHV0);
320  const double logHV1err = HVerr / exp(logHV1);
321 
322  const double logGain0 = k0->second.first;
323  const double logGain1 = k1->second.first;
324 
325  const double logGain0err = k0->second.second;
326  const double logGain1err = k1->second.second;
327 
328  // Interpolate the nominal logarithmic supply-voltage and compute error estimate
329  const double slope = (logGain1 - logGain0) / (logHV1 - logHV0);
330  const double logNominalHV = (logNominalGain - logGain0) / slope + logHV0;
331 
332  const double err1 = logHV0err * logHV0err;
333  const double err2 = logGain0err * logGain0err / slope / slope;
334  const double err3 = ( pow(logNominalGain - logGain0 / slope, 2.0) *
335  ((logGain0err*logGain0err + logGain1err*logGain1err) / pow(logGain1 - logGain0, 2.0) +
336  (logHV0err*logHV0err + logHV1err*logHV1err) / pow(logHV1 - logHV0, 2.0)) );
337 
338  const double logNominalHVerr = sqrt(err1 + err2 + err3);
339 
340  if (fabs(logNominalHV - logHV0) / fabs(logHV1 - logHV0) < 2.0) {
341 
342  valid = true;
343 
344  result.first = -exp(logNominalHV);
345  errors.first = exp(logNominalHV) * logNominalHVerr;
346  result.second = NOMINAL_GAIN;
347  errors.second = 0.0;
348  }
349 
350  if ((k0 == data.cbegin() && logNominalGain < logGain0) ||
351  (k0 == --data.cend() && logNominalGain > logGain0)) {
352 
353  WARNING("Nominal gain " << NOMINAL_GAIN << " lies outside of HV-scan range; " <<
354  "Extrapolation " << (valid ? "successful!" : "failed; Setting closest values!") << "\n\t");
355  }
356 
357  } else {
358 
359  WARNING("Could not find optimal high-voltage; Setting closest values!\n\t");
360  }
361 
362  NOTICE(setw(8) << setprecision(2) << fixed << left <<
363  result.first << setw(0) << " +/- " << setw(4) << errors.first << setw(10) << right <<
364  result.second << setw(0) << " +/- " << setw(3) << errors.second << endl);
365 
366  const JHVCalibration_t HVcal(upi,
367  valid ? OK_t : Failed_t,
368  result.first,
369  result.second,
370  runNumbers);
371 
372  HVcalibrations.push_back(HVcal);
373  }
374 
375 
376  if (! graphFile.empty()) {
377 
378  TFile out(graphFile.c_str(), "RECREATE");
379 
380  putObject(&out, JMeta(argc, argv));
381 
382  out << manager;
383 
384  out.Close();
385  }
386 
387  time_t stopTime = time(0);
388 
389  // Write json output
390  json js;
391 
392  js[User_t] = person.LOGIN;
393  js[Location_t] = person.LOCATIONID;
394  js[StartTime_t] = get_date_string(startTime);
395  js[EndTime_t] = get_date_string(stopTime);
396  js[Test_t + Type_t] = testType;
397  js[Tests_t] = json(HVcalibrations);
398 
399  ofstream ofs(outputFile.c_str());
400 
401  ofs << setw(2) << setprecision(8);
402  ofs << js;
403 
404  ofs.close();
405 }
Auxiliary class for ROOT I/O of application specific meta data.
Definition: JMeta.hh:71
Utility class to parse command line options.
Definition: JParser.hh:1493
#define WARNING(A)
Definition: JMessage.hh:65
JMultiMap is a general purpose multidimensional map based on a type list of maps. ...
static const std::string Failed_t
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
static const std::string Tests_t
static const std::string OK_t
static const double FITTOT_GAIN_MAX
Maximal gain.
Definition: JFitToT.hh:37
static const double FITTOT_GAIN_MIN
Minimal gain.
Definition: JFitToT.hh:36
esac print_variable DETECTOR INPUT_FILE OUTPUT_FILE CDF for TYPE in
Definition: JSirene.sh:45
T get(const JHead &header)
Get object from header.
*fatal Wrong number of arguments esac JCookie sh typeset Z DETECTOR typeset Z SOURCE_RUN typeset Z TARGET_RUN set_variable PARAMETERS_FILE $WORKDIR parameters
Definition: diff-Tuna.sh:38
then for HISTOGRAM in h0 h1
Definition: JMatrixNZ.sh:69
static const std::string Location_t
Dynamic ROOT object management.
Auxiliary class for specifying selection of database data.
string outputFile
Data structure for detector geometry and calibration.
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:699
esac $JPP_DIR examples JDetector JTransitTime o $OUTPUT_FILE n N $NPE T $TTS_NS d $DEBUG for HISTOGRAM in tts tt2 pmt
Definition: JTransitTime.sh:36
JValue_t second
Definition: JPair.hh:129
then echo Variable JPP_DIR undefined exit fi source $JPP_DIR setenv sh $JPP_DIR set_variable DEBUG set_variable NPE set_variable FIT_RANGE set_variable OUTPUT_DIR tmp set_variable OUTPUT_JSON $OUTPUT_DIR HVtuning json set_variable OUTPUT_ROOT $OUTPUT_DIR HVtuning root set_variable FIT_OPTIONS RME set_variable PMT_DEFAULT gain
Definition: JTuneHV.sh:30
Auxiliary class to manage set of compatible ROOT objects (e.g.
Definition: JManager.hh:42
JKey_t first
Definition: JPair.hh:128
I/O formatting auxiliaries.
Map list.
Definition: JMapList.hh:24
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1954
return result
Definition: JPolint.hh:695
ROOT I/O of application specific meta data.
#define NOTICE(A)
Definition: JMessage.hh:64
static const std::string Test_t
const std::string & getVariant() const
Get variant.
Definition: JUPI.hh:79
int debug
debug level
Definition: JSirene.cc:61
const double NOMINAL_GAIN
Specification for normalized gain corresponding to a one photo-electron pulse.
General purpose messaging.
#define FATAL(A)
Definition: JMessage.hh:67
then echo n User name
Definition: JCookie.sh:45
static const JDetectorsHelper & getDetector
Function object for mapping serial number and object identifier of detectors.
Definition: JDBToolkit.hh:131
void reset(T &value)
Reset value.
Universal product identifier (UPI).
Definition: JUPI.hh:30
static const std::string EndTime_t
Utility class to parse command line options.
Data structure for PMT high-voltage calibration.
nlohmann::json json
static const std::string Type_t
std::string to_string(const T &value)
Convert value to string.
ResultSet & getResultSet(const std::string &query)
Get result set.
Definition: JDB.hh:269
static const std::string StartTime_t
std::string get_date_string(const std::time_t &time)
Create ISO 8601 date string for output file header.
static const std::string User_t
Detector calibration key words for JSON I/O.
This file is automatically created by make.
Template definition for getting table specific selector.
static const std::string FITTOT_FNAME
Definition: JFitToT.hh:45
Multidimensional map.
Definition: JMultiMap.hh:46
then set_variable FORMULA *[0] exp(-0.5 *(x-[1])*(x-[1])/([2]*[2]))" set_variable OUTPUT_FILE histogram.root JHistogram1D -o $WORKDIR/$OUTPUT_FILE -F "$FORMULA" -
bool putObject(TDirectory *dir, const T &object)
Write object to ROOT directory.
int main(int argc, char *argv[])
Definition: Main.cpp:15