#include #include #include #include #include "JSystem/JDateAndTime.hh" #include "JLang/JUUID.hh" #include "Jeep/JPrint.hh" #include "Jeep/JParser.hh" #include "Jeep/JMessage.hh" #include "JTools/JRange.hh" #include "JSupport/JMeta.hh" #include "JSupport/JSingleFileScanner.hh" #include "JDetector/JDetector.hh" #include "JDetector/JModuleRouter.hh" #include "JDetector/JDetectorToolkit.hh" #include "JDetector/JDetectorCalibration.hh" #include "JDB/JUPI.hh" #include "JDB/JUPI_t.hh" #include "JDB/JDBSupportkit.hh" #include "JCalibrate/JFitToT.hh" #include "JCalibrate/JHVInterpolator.hh" #include "JROOT/JManager.hh" #include "JSon/JSon.hh" #include "TFile.h" namespace { /** * Auxiliary class for creating a PMT-UPI look-up table from ASCII DB file. */ struct JUPITable { /** * Initialise * * \param fileName file name */ JUPITable(const char* const fileName) { using namespace std; using namespace JPP; ifstream in(fileName); for (string buffer; getline(in, buffer); ) { istringstream is(buffer); JUPI entry; if (is >> entry.PBS >> entry.VARIANT >> entry.VERSION >> entry.SERIALNUMBER) { if (entry.PBS.is_valid() && entry.PBS == PBS::PMT && entry.SERIALNUMBER >= 0) { number2upi[entry.PBS][entry.SERIALNUMBER] = JUPI_t(entry.PBS, entry.VARIANT, entry.VERSION, entry.SERIALNUMBER); } } } in.close(); } /** * Get %UPI. * * \param pbs %PBS * \param number serial number * \return %UPI */ JDATABASE::JUPI_t operator()(const JDATABASE::JPBS_t& pbs, const int number) { using namespace std; using namespace JPP; map>::const_iterator p = number2upi.find(pbs); if (p != number2upi.end()) { map::const_iterator q = p->second.find(number); if (q != p->second.end()) { return q->second; } else { THROW(JValueOutOfRange, "Invalid serial number " << number); } } else { THROW(JValueOutOfRange, "Invalid PBS " << pbs); } } protected: std::map > number2upi; }; } /** * \file * * Program for inter-/extrapolation of nominal high-voltage settings. * \author acreusot, mdejong and bjung */ int main(int argc, char **argv) { using namespace std; using namespace JPP; string inputFile; string detectorFile; string outputFile; string UPIFile; JDBAPIVersion APIversion; string testType; string login; string locationID; vector runNumbers; int elapsedTime = 0; double HVstepMin = 2 * 3.14; // Minimal HV step [V] JRange HVrange (-1500 + 1e-2, -80 - 1e-2); // Allowed HV range [V] JRange gainRange(FITTOT_GAIN_MIN + 1e-2, FITTOT_GAIN_MAX - 1e-2); // Allowed gain fit-range double gainTarget = NOMINAL_GAIN; // Target nominal gain value int debug; try { JProperties properties; properties.insert(gmake_property(APIversion)); properties.insert(gmake_property(testType)); properties.insert(gmake_property(login)); properties.insert(gmake_property(locationID)); properties.insert(gmake_property(runNumbers)); properties.insert(gmake_property(elapsedTime)); JProperties settings; settings.insert(gmake_property(HVstepMin)); settings.insert(gmake_property(HVrange)); settings.insert(gmake_property(gainRange)); settings.insert(gmake_property(gainTarget)); JParser<> zap("Example program to find optimal HV-settings."); zap['f'] = make_field(inputFile, "input file (ROOT format)"); zap['o'] = make_field(outputFile, "output file (json format)"); zap['a'] = make_field(detectorFile, "detector file"); zap['b'] = make_field(UPIFile, "PMT UPI ASCII table"); zap['#'] = make_field(properties, "database information") = JPARSER::initialised(); zap['@'] = make_field(settings, "interpolation settings") = JPARSER::initialised(); zap['d'] = make_field(debug, "debug") = 1; zap(argc, argv); } catch(const exception &error) { FATAL(error.what() << endl); } if (login.empty() || locationID.empty()) { FATAL("Missing user information (please specify via -#login and -#locationID)."); } else if (testType.empty()) { FATAL("Missing database test type (please specify via -#testType)."); } else if (getDBVersionTuneHV(testType) < 3 && runNumbers.empty()) { FATAL("Missing run numbers."); } JHVCalibration_t::setVersion(getDBVersionTuneHV(testType)); const JUUID& UUID = JUUID::rndm(); JDateAndTime timer; timer.sub(elapsedTime); JDetector detector; try { load(detectorFile, detector); } catch (const exception& error) { FATAL(error.what() << endl); } JModuleRouter router (detector); JUPITable fetchUPI(UPIFile.c_str()); // Read input TFile input(inputFile.c_str(), "READ"); JManager manager(new TMultiGraph(), "%.HVxG"); input >> manager; input.Close(); // Find optimal HV corresponding to a nominal gain of 1.0 // via linear interpolation in log-log scale JHVCalibration HVcalibrations; JHVInterpolator::setMinHVDistance(HVstepMin); JHVInterpolator::setHVRange (HVrange); JHVInterpolator::setGainRange (gainRange); NOTICE("Searching optimal high-voltage settings..." << endl << LEFT(30) << "UPI" << CENTER(35) << "(identifer / location)" << RIGHT(35) << "Inter-/Extrapolated high-voltage [-]" << endl); for (JManager::iterator it = manager.begin(); it != manager.end(); ++it) { const string& name = it->first; JHVInterpolator data(*(it->second)); // Retrieve upi, location and serialID const int seppos = name.find('.'); const int moduleID = stoi(name.substr(0, seppos)); const int tdc = stoi(name.substr(seppos + 1, seppos + 3)); const JModule& module = router.getModule(moduleID); const JPMT& pmt = router.getPMT(JPMTIdentifier(moduleID, tdc)); const JUPI_t& pmtUPI = fetchUPI(PBS::PMT, pmt.getID()); const string location = MAKE_STRING(right << FILL(4,'0') << module.getLocation().getString() << '.' << right << FILL(2,'0') << module.getLocation().getFloor() << '.' << right << FILL(2,'0') << tdc); NOTICE(LEFT(30) << pmtUPI << "(a.k.a. " << name << " / " << location << "): "); if (data.interpolateHV(gainTarget)) { const double result = -data.getHV (); const double error = data.getHVError(); NOTICE(right << FIXED(20,2) << result << " +/- " << FIXED(4,2) << error << endl); HVcalibrations.push_back(JHVCalibration_t(pmtUPI, OK_t, result, runNumbers, gainTarget)); } else { WARNING("Could not find high-voltage corresponding to target gain; Setting zero." << endl); HVcalibrations.push_back(JHVCalibration_t(pmtUPI, Fail_t, 0.0, runNumbers, 0.0)); } } // Update graphical output vector metaInfo; string metaInfoStr; metaInfo.push_back(JMeta(argc, argv)); metaInfoStr += MAKE_STRING(metaInfo.back()); for (JSingleFileScanner in(inputFile); in.hasNext(); ) { metaInfo.push_back(*in.next()); metaInfoStr += MAKE_STRING(metaInfo.back()); } TFile output(inputFile.c_str(), "RECREATE"); for (vector::iterator i = metaInfo.begin(); i != metaInfo.end(); ++i) { putObject(output, *i); } output << manager; output.Close(); // Write json output json js; if (APIversion.getMajorVersion() == 2) { json error = { {Message_t, "" }, {Code_t, OK_t }, {Arguments_t, json::array() } }; json metaData = { {Configuration_t, metaInfoStr }, {UUID_t, MAKE_STRING(UUID) } }; json data = { {Provenance_t + Info_t, json(metaData) }, {User_t, login }, {Location_t, locationID }, {Start_t + Time_t, timer.toString() }, {End_t + Time_t, timer().toString() }, {Test_t + Type_t, testType }, {Tests_t, json(HVcalibrations) } }; js[APIVersion_t] = MAKE_STRING(APIversion); js[Data_t + Type_t] = MAKE_STRING("ProductTestSession"); js[Encoding_t] = MAKE_STRING("NativeJSON"); js[Error_t] = json(error); js[Start_t] = timer.toString(); js[End_t] = timer().toString(); js[Data_t][0] = json(data); } else if (APIversion.getMajorVersion() == 1) { js[User_t] = login; js[Location_t] = locationID; js[Test_t + Type_t] = testType; js[Start_t + Time_t] = timer.toString(); js[End_t + Time_t] = timer().toString(); js[Tests_t] = json(HVcalibrations); } else { FATAL("Invalid API version <" << APIversion << "> accepted major versions 1 and 2." << endl); } ofstream ofs(outputFile.c_str()); ofs << setw(2) << setprecision(8); ofs << js; ofs.close(); }