#include #include #include #include #include #include "JLang/JLangToolkit.hh" #include "JDetector/JDetector.hh" #include "JDetector/JDetectorToolkit.hh" #include "JDetector/JPMTParametersMap.hh" #include "JDetector/JPMTReadoutAddress.hh" #include "JDetector/JPMTPhysicalAddress.hh" #include "JDetector/JModuleAddressMap.hh" #include "JDetector/JDetectorAddressMap.hh" #include "JDetector/JDetectorAddressMapToolkit.hh" #include "JDetector/JPMTAnalogueSignalProcessor.hh" #include "JSupport/JMeta.hh" #include "JTools/JRange.hh" #include "Jeep/JParser.hh" #include "Jeep/JMessage.hh" namespace { using namespace JPP; static const char WILDCARD_RING = '*'; //>(std::istream& in, JEmptyAddress& object) { return in; } friend inline std::ostream& operator<<(std::ostream& out, const JEmptyAddress& object) { return out; } }; /** * Auxiliary class to apply modifications to PMT parameters. */ template class JModifier { public: /** * Default constructor. */ JModifier() {} /** * Apply modification to given parameters. * * \param parameters PMT parameters * \return true if valid action; else false */ bool apply(JPMTParameters& parameters) const { using namespace std; try { if (this->action == "set") { parameters.getProperties().getValue(this->key) = this->value; } else if (this->action == "add") { parameters.getProperties().getValue(this->key) += this->value; } else if (this->action == "sub") { parameters.getProperties().getValue(this->key) -= this->value; } else if (this->action == "mul") { parameters.getProperties().getValue(this->key) *= this->value; } else if (this->action == "div") { parameters.getProperties().getValue(this->key) /= this->value; } else { return false; } } catch(const std::exception& error) { cerr << error.what() << endl; return false; } return true; } /** * Read modifier from input. * * \param in input stream * \param modifier modifier * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JModifier& modifier) { return in >> modifier.address >> modifier.action >> modifier.key >> modifier.value; } /** * Write modifier to output. * * \param out output stream * \param modifier modifier * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JModifier& modifier) { return out << modifier.address << ' ' << modifier.action << ' ' << modifier.key << ' ' << modifier.value; } JAddress_t address; std::string action; std::string key; double value; }; } /** * \file * * Auxiliary program to edit PMT parameters map. * * Syntax: *
 *     -@ "(set|add|sub|mul|div)  "
 *     -A " (set|add|sub|mul|div)  "
 *     -M "       (set|add|sub|mul|div)  "
 * 
* In this, the PMT physical address corresponds to the data structure JDETECTOR::JPMTPhysicalAddress and * the PMT identifier to JDETECTOR::JPMTIdentifier.\n * The key corresponds to one of the data members of the JDETECTOR::JPMTParameters data structure.\n * The option -\@ corresponds to the default PMT values. * * Note that in the absence of option -a, the detector identifier should be specified * using option -D so to obtain the correct PMT address mapping. * * Multiple options -\@, -A and -M will be processed in order of appearance. * \author mdejong */ int main(int argc, char **argv) { using namespace std; using namespace JPP; typedef JRange JRange_t; string detectorFile; int detectorID; JPMTParametersMap parameters; vector< JModifier<> > hdr; vector< JModifier > mod; vector< JModifier > daq; double mu; JRange_t T_ns; JRange_t QE; string outputFile; bool squash; int debug; try { JParser<> zap("Auxiliary program to edit PMT parameters map."); zap['a'] = make_field(detectorFile, "detector file.") = ""; zap['D'] = make_field(detectorID, "detector identifier (in absence of detector file).") = 0; zap['P'] = make_field(parameters, "PMT simulation data (or corresponding file name)") = JPARSER::initialised(); zap['@'] = make_field(hdr, "PMT parameter modifier for default values.") = JPARSER::initialised(); zap['A'] = make_field(mod, "PMT parameter modifier by physical address (e.g. B1).") = JPARSER::initialised(); zap['M'] = make_field(daq, "PMT parameter modifier by DAQ address (e.g. .") = JPARSER::initialised(); zap['E'] = make_field(mu, "expectation value for npe given two-fold coincidence") = 0.0; zap['T'] = make_field(T_ns, "time-over-threshold range.") = JRange_t(); zap['Q'] = make_field(QE, "QE range.") = JRange_t(); zap['o'] = make_field(outputFile, "output file."); zap['q'] = make_field(squash, "squash meta data"); zap['d'] = make_field(debug, "debug level") = 2; zap(argc, argv); } catch(const exception &error) { FATAL(error.what() << endl); } if (squash) { parameters.comment.clear(); } parameters.comment.add(JMeta(argc,argv)); for (vector< JModifier<> >::const_iterator i = hdr.begin(); i != hdr.end(); ++i) { DEBUG("Modifying default PMT parameters " << i->action << ' ' << i->key << ' ' << i->value << endl); if (!i->apply(parameters.getDefaultPMTParameters())) { ERROR("No valid action: " << *i << endl); } } if (detectorFile != "") { // Setting default PMT parameters for given detector. JDetector detector; try { load(detectorFile, detector); } catch(const JException& error) { FATAL(error); } if (detectorID == 0) { detectorID = detector.getID(); } else if (detectorID != detector.getID()) { FATAL("Inconsistent detector identifier " << detectorID << " != " << detector.getID() << endl); } for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) { for (unsigned int pmt = 0; pmt != module->size(); ++pmt) { const JPMTIdentifier id(module->getID(), pmt); if (parameters.find(id) == parameters.end()) { DEBUG("Setting default parameters for PMT " << id << endl); parameters[id] = parameters.getDefaultPMTParameters(); } } } } if (!mod.empty()) { if (!hasDetectorAddressMap(detectorID)) { FATAL("Invalid detector identifier " << detectorID << endl); } const JDetectorAddressMap& demo = getDetectorAddressMap(detectorID); for (JPMTParametersMap::iterator ps = parameters.begin(); ps != parameters.end(); ++ps) { const JPMTPhysicalAddress& address = demo.get(ps->first); for (vector< JModifier >::const_iterator i = mod.begin(); i != mod.end(); ++i) { if (compare(i->address, address)) { DEBUG("Modifying parameters for PMT " << ps->first << ' ' << i->action << ' ' << i->key << ' ' << i->value << endl); if (!i->apply(ps->second)) { ERROR("No valid action: " << *i << endl); } } } } } if (!daq.empty()) { for (JPMTParametersMap::iterator ps = parameters.begin(); ps != parameters.end(); ++ps) { for (vector< JModifier >::const_iterator i = daq.begin(); i != daq.end(); ++i) { if (compare(ps->first, i->address)) { DEBUG("Modifying parameters for PMT " << ps->first << ' ' << i->action << ' ' << i->key << ' ' << i->value << endl); if (!i->apply(ps->second)) { ERROR("No valid action: " << *i << endl); } } } } } if (mu > 0.0) { DEBUG("Correct measured QE for two-hit probability " << mu << endl); try { parameters.convertHitProbabilityToQE(mu); } catch(const JException& error) { FATAL(error.what()); } } else if (mu < 0.0) { FATAL("Invalid expection value for two-hit probability " << mu << endl); } if (T_ns != JRange_t()) { DEBUG("Correct measured QE for time-over-threshold range " << T_ns << endl); const int NPE = 1; for (JPMTParametersMap::iterator i = parameters.begin(); i != parameters.end(); ++i) { const JPMTAnalogueSignalProcessor cpu(i->second); i->second.QE *= (cpu.getIntegralOfChargeProbability(i->second.threshold, cpu.getNPE(T_ns.getUpperLimit()), NPE) / cpu.getIntegralOfChargeProbability(cpu.getNPE(T_ns.getLowerLimit()), cpu.getNPE(T_ns.getUpperLimit()), NPE)); } } if (QE != JRange_t()) { for (JPMTParametersMap::iterator i = parameters.begin(); i != parameters.end(); ++i) { i->second.QE = QE.constrain(i->second.QE); } } if (outputFile != "") { parameters.comment.add(JMeta(argc, argv)); ofstream out(outputFile.c_str()); out << parameters << endl; out.close(); } }