12 #include "dbclient/KM3NeTDBClient.h"
16 #include "JDB/JDBincludes.hh"
35 #include "TGraphErrors.h"
59 interpolator(
const double minHVdiff,
const double minGain,
const double maxGain,
const double targetGain) :
60 dHV(minHVdiff), gainMin(minGain), gainMax(maxGain), gainTarget(targetGain) {}
70 const bool checkHV(map_t::const_reference entry1, map_t::const_reference entry2)
const {
72 return (fabs(entry1.first - entry2.first) > dHV);
82 const bool checkGain(map_t::const_reference entry)
const {
84 return (entry.second.first > gainMin && entry.second.first < gainMax);
95 const bool areIncreasing(map_t::const_reference entry1, map_t::const_reference entry2)
const {
97 return ((entry1.first < entry2.first && entry1.second.first > entry2.second.first) ||
98 (entry1.first > entry2.first && entry1.second.first < entry2.second.first));
109 const bool areValid(map_t::const_reference entry1,
110 map_t::const_reference entry2)
const {
112 return (checkHV (entry1, entry2) && checkGain(entry1) &&
113 areIncreasing(entry1, entry2) && checkGain(entry2));
123 const pair<map_t::const_reference,
124 map_t::const_reference> getPoints(
const map_t& data)
const {
126 map_t::const_iterator point0 = data.cbegin();
127 map_t::const_iterator point1 = next(data.cbegin());
129 for (map_t::const_iterator it = next(data.cbegin()); it != data.cend(); ++it) {
131 if (fabs(it->second.first - gainTarget) < fabs(point0->second.first - gainTarget)) {
133 point1 = (areValid(*point0, *it) ? point0 : point1);
136 }
else if ((fabs(it->second.first - gainTarget) < fabs(point1->second.first - gainTarget) ||
137 !areValid(*point0, *point1)) && areValid(*point0, *it)) {
143 return pair<map_t::const_reference,
144 map_t::const_reference>(*point0, *point1);
156 map_t::const_reference entry2)
const {
160 if (areValid(entry1, entry2)) {
162 const double logHV0 = log(fabs(entry1.first));
163 const double logHV1 = log(fabs(entry2.first));
165 const double logG0 = log(entry1.second.first);
166 const double logG1 = log(entry2.second.first);
167 const double elogG0 = entry1.second.second / entry1.second.first;
168 const double elogG1 = entry2.second.second / entry2.second.first;
170 const double dlogG0 = log(gainTarget) - logG0;
171 const double dlogG1 = log(gainTarget) - logG1;
173 const double slope = (logG1 - logG0) / (logHV1 - logHV0);
174 const double logHVnom = dlogG0 / slope + logHV0;
175 const double elogHVnom = sqrt(dlogG1 * dlogG1 * elogG0 * elogG0 +
176 dlogG0 * dlogG0 * elogG1 * elogG1) / fabs(slope * (logG1 - logG0));
179 result.second =
exp(logHVnom) * elogHVnom;
194 pair<map_t::const_reference,
195 map_t::const_reference> intpPoints = getPoints(data);
197 return getNominalHV(intpPoints.first, intpPoints.second);
202 const double gainMin;
203 const double gainMax;
204 const double gainTarget;
216 int main(
int argc,
char **argv)
236 double HVstepMin = 2 * 3.14;
253 JParser<> zap(
"Example program to find optimal HV-settings.");
258 zap[
'f'] =
make_field(inputFiles,
"map of run numbers to file strings (i.e. to the output of JFitToT)");
259 zap[
'a'] =
make_field(detectorFile,
"detector file");
260 zap[
'T'] =
make_field(testType,
"test type") =
"HV-TUNING-SEA-GAIN-v1";
262 zap[
'o'] =
make_field(graphFile,
"Graphical output (root format)") =
"";
268 catch(
const exception &error) {
269 FATAL(error.what() << endl);
285 NOTICE(
"Loading database tables..." << endl);
295 ResultSet& rs =
getResultSet(getTable<JPersons>(), selector);
303 const int runNr = fileIt->first;
305 NOTICE(
"Extracting Gain-/HV-data for run " << runNr << endl);
309 TFile fitData(fileIt->second.c_str(),
"READ");
312 ResultSet& rs =
getResultSet(getTable<JPMTHVRunSettings>(), selector);
316 const int domID =
detector.getModule(
JLocation(table.DUID, table.FLOORID)).getID();
320 const TF1* f1 = (h1 != NULL ? h1->GetFunction(
FITTOT_FNAME.c_str()) : NULL);
322 double gain = (fabs(gainMin - gainTarget) > fabs(gainMax - gainTarget) ? gainMin : gainMax);
323 double gainError = 0.0;
327 const int Ngain = f1->GetParNumber(
"gain");
329 gain = f1->GetParameter(Ngain);
330 gainError = f1->GetParError (Ngain);
332 }
else if (h1 == NULL && find(missingDOMs.cbegin(), missingDOMs.cend(), domID) == missingDOMs.cend()) {
334 missingDOMs.push_back(domID);
337 data[domID][table.PMTSERIAL][table.DUID][table.FLOORID][table.PMTINTID].insert(make_pair(table.HV_VALUE, make_pair(gain, gainError)));
340 const int index =
distance(inputFiles.cbegin(), fileIt);
342 manager[
name]->SetPoint (index, log10(fabs(table.HV_VALUE)), log10(gain));
343 manager[
name]->SetPointError(index, 0.0, gainError / gain / log(10));
350 }
catch (
const exception& error) {
352 FATAL(error.what() << endl);
360 NOTICE(
"Searching optimal high-voltage settings..." << endl <<
361 LEFT(30) <<
"UPI" <<
CENTER(35) <<
"(identifer / location)" <<
RIGHT(35) <<
"Inter-/Extrapolated high-voltage [-]" << endl);
363 for (pmtMap_t::super_const_iterator pmt = data.super_begin(); pmt != data.super_end(); ++pmt) {
366 const int domID = pmt->first;
368 const JLocation_t location(pmt->second->second->first,
369 pmt->second->second->second->first,
370 pmt->second->second->second->second->first);
372 const runMap_t& data = pmt.getValue();
374 NOTICE(
LEFT(30) << pmtUPI <<
"(a.k.a. " << domID <<
'.' <<
FILL(2,
'0') << location.
position <<
" / " << location <<
"):");
377 if (data.size() < 2 || find(missingDOMs.cbegin(), missingDOMs.cend(), domID) != missingDOMs.cend()) {
379 NOTICE (setprecision(2) << right <<
FIXED(20,2) << 0.0 <<
" +/- " <<
FIXED(4,2) << 0.0 << endl);
380 WARNING((data.size() < 2 ?
"Insufficient data" :
"Missing (dead?) DOM") << endl);
387 const interpolator interpolator(HVstepMin, gainMin, gainMax, gainTarget);
389 const pair<runMap_t::const_reference,
390 runMap_t::const_reference> points = interpolator.getPoints(data);
393 const bool valid = (interpolator.areValid(points.first, points.second) && result.first < 0.0 &&
394 ((log(fabs(result.first)) - log(fabs(points.first.first))) /
395 (log(fabs(points.second.first)) - log(fabs(points.first.first))) < 2.0));
397 NOTICE(setprecision(2) << right <<
FIXED(20,2) << result.first <<
" +/- " <<
FIXED(4,2) << result.second << endl);
399 if (result.first < data.cbegin() ->
first ||
400 result.first > data.crbegin() ->
first) {
402 WARNING(
"Nominal gain " << gainTarget <<
" lies outside of HV-scan range; " <<
403 "Extrapolation " << (valid ?
"successful." :
"failed; Setting zero.") << endl);
407 WARNING(
"Could not find optimal high-voltage; Setting zero." << endl);
412 valid ? result.first : 0.0,
416 HVcalibrations.push_back(HVcal);
420 if (! graphFile.empty()) {
422 TFile out(graphFile.c_str(),
"RECREATE");
427 it->second->SetMarkerStyle(kFullDotSmall);
438 js[
User_t] = person.LOGIN;
447 ofs << setw(2) << setprecision(8);
Utility class to parse command line options.
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.
#define gmake_property(A)
macro to convert (template) parameter to JPropertiesElement object
static const std::string Tests_t
static const JPBS_t PMT(3, 4, 2, 3)
PBS of photo-multiplier tube (PMT)
static const std::string OK_t
static const double FITTOT_GAIN_MAX
Default maximal gain.
static const double FITTOT_GAIN_MIN
Default minimal gain.
Utility class to parse parameter values.
T get(const JHead &header)
Get object from header.
#define MAKE_CSTRING(A)
Make C-string.
then for HISTOGRAM in h0 h1
static const std::string Location_t
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Universal product identifier (UPI).
Dynamic ROOT object management.
Auxiliary data structure for floating point format specification.
Auxiliary class for specifying selection of database data.
then set_variable FORMULA *[0] exp(-0.5 *(x-[1])*(x-[1])/([2]*[2]))*exp(-0.5 *(y-[1])*(y-[1])/([2]*[2]))" JF2 -o $WORKDIR/f2.root -F "$FORMULA" -@ "p0
Data structure for detector geometry and calibration.
then echo The file $DIR KM3NeT_00000001_00000000 root already please rename or remove it first
#define MAKE_STRING(A)
Make string.
static const std::string FITTOT_SUFFIX
Auxiliary data structure for alignment of data.
JDetectorsHelper getDetector
Function object for mapping serial number to object identifier of detector and vice versa...
Auxiliary class to manage set of compatible ROOT objects (e.g. histograms) using unique keys...
I/O formatting auxiliaries.
static const char FITTOT_SEPARATOR
Logical location of module.
Auxiliary data structure for location of product in detector.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
static const std::string Test_t
const double NOMINAL_GAIN
Specification for normalized gain corresponding to a one photo-electron pulse.
General purpose messaging.
Auxiliary data structure for sequence of same character.
then $JPP_DIR examples JDetector JToT o $OUTPUT_FILE n N $NPE P gain
int position
position in floor
static const std::string EndTime_t
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
Auxililary class to get date and time.
Utility class to parse command line options.
Data structure for PMT high-voltage calibration.
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.
static const std::string StartTime_t
static const std::string User_t
Detector calibration key words for JSON I/O.
JUPIHelper getUPI
Function object for mapping PBS and serial number to UPI.
do set_variable DETECTOR_TXT $WORKDIR detector
Template definition for getting table specific selector.
static const std::string FITTOT_FNAME
bool putObject(TDirectory *dir, const T &object)
Write object to ROOT directory.
int main(int argc, char *argv[])