Jpp 21.0.0-rc.1-88-g0130508c4
the software that should make you happy
Loading...
Searching...
No Matches
JEditPMTParameters.cc
Go to the documentation of this file.
1
2#include <string>
3#include <iostream>
4#include <fstream>
5#include <iomanip>
6#include <vector>
7
19#include "JSupport/JMeta.hh"
20#include "JTools/JRange.hh"
21
22#include "Jeep/JParser.hh"
23#include "Jeep/JMessage.hh"
24
25
26namespace {
27
28 using namespace JPP;
29
30 static const char WILDCARD_RING = '*'; //<! Wild card for ring of PMT in optical module.
31 static const int WILDCARD_POSITION = -1; //<! Wild card for position of PMT in ring.
32 static const int WILDCARD = -1; //<! Wild card for PMT identifier.
33
34
35 /**
36 * Compare PMT physical addresses taking into account wild cards.
37 *
38 * \param first first PMT physical address
39 * \param second second PMT physical address
40 * \return true if addresses are equal; else false
41 */
42 inline bool compare(const JPMTPhysicalAddress& first, const JPMTPhysicalAddress& second)
43 {
44 return (((first == second)) ||
45
46 ((first.ring == WILDCARD_RING || second.ring == WILDCARD_RING) && first.position == second.position) ||
47 ((first.position == WILDCARD_POSITION || second.position == WILDCARD_POSITION) && first.ring == second.ring) ||
48
49 ((first.ring == WILDCARD_RING || second.ring == WILDCARD_RING) &&
50 (first.position == WILDCARD_POSITION || second.position == WILDCARD_POSITION)));
51 }
52
53
54 /**
55 * Compare PMT identifiers taking into account wild cards.
56 *
57 * \param first first PMT identifier
58 * \param second second PMT identifier
59 * \return true if addresses are equal; else false
60 */
61 inline bool compare(const JPMTIdentifier& first, const JPMTIdentifier& second)
62 {
63 return (((first == second)) ||
64
65 ((first.getID() == WILDCARD || second.getID() == WILDCARD) && first.getTDC() == second.getTDC()) ||
66 ((first.getTDC() == WILDCARD || second.getTDC() == WILDCARD) && first.getID() == second.getID()) ||
67
68 ((first.getID() == WILDCARD || second.getID() == WILDCARD) &&
69 (first.getTDC() == WILDCARD || second.getTDC() == WILDCARD)));
70 }
71
72
73 /**
74 * Empty address.
75 */
76 struct JEmptyAddress {
77 friend inline std::istream& operator>>(std::istream& in, JEmptyAddress& object) { return in; }
78 friend inline std::ostream& operator<<(std::ostream& out, const JEmptyAddress& object) { return out; }
79 };
80
81
82 /**
83 * Auxiliary class to apply modifications to PMT parameters.
84 */
85 template<class JAddress_t = JEmptyAddress>
86 class JModifier {
87 public:
88 /**
89 * Default constructor.
90 */
91 JModifier()
92 {}
93
94
95 /**
96 * Apply modification to given parameters.
97 *
98 * \param parameters PMT parameters
99 * \return true if valid action; else false
100 */
101 bool apply(JPMTParameters& parameters) const
102 {
103 using namespace std;
104
105 try {
106
107 if (this->action == "set") {
108
109 parameters.getProperties().getValue<double>(this->key) = this->value;
110
111 } else if (this->action == "add") {
112
113 parameters.getProperties().getValue<double>(this->key) += this->value;
114
115 } else if (this->action == "sub") {
116
117 parameters.getProperties().getValue<double>(this->key) -= this->value;
118
119 } else if (this->action == "mul") {
120
121 parameters.getProperties().getValue<double>(this->key) *= this->value;
122
123 } else if (this->action == "div") {
124
125 parameters.getProperties().getValue<double>(this->key) /= this->value;
126
127 } else {
128
129 return false;
130 }
131 }
132 catch(const std::exception& error) {
133 cerr << error.what() << endl;
134 return false;
135 }
136
137 return true;
138 }
139
140
141 /**
142 * Read modifier from input.
143 *
144 * \param in input stream
145 * \param modifier modifier
146 * \return input stream
147 */
148 friend inline std::istream& operator>>(std::istream& in, JModifier& modifier)
149 {
150 return in >> modifier.address
151 >> modifier.action
152 >> modifier.key
153 >> modifier.value;
154 }
155
156
157 /**
158 * Write modifier to output.
159 *
160 * \param out output stream
161 * \param modifier modifier
162 * \return output stream
163 */
164 friend inline std::ostream& operator<<(std::ostream& out, const JModifier& modifier)
165 {
166 return out << modifier.address << ' '
167 << modifier.action << ' '
168 << modifier.key << ' '
169 << modifier.value;
170 }
171
172
173 JAddress_t address;
174 std::string action;
175 std::string key;
176 double value;
177 };
178}
179
180
181/**
182 * \file
183 *
184 * Auxiliary program to edit PMT parameters map.
185 *
186 * Syntax:
187 * <pre>
188 * -@ "(set|add|sub|mul|div) <key> <value>"
189 * -A "<PMT physical address> (set|add|sub|mul|div) <key> <value>"
190 * -M "<PMT identifier> (set|add|sub|mul|div) <key> <value>"
191 * </pre>
192 * In this, the PMT physical address corresponds to the data structure JDETECTOR::JPMTPhysicalAddress and
193 * the PMT identifier to JDETECTOR::JPMTIdentifier.\n
194 * The key corresponds to one of the data members of the JDETECTOR::JPMTParameters data structure.\n
195 * The option <tt>-\@</tt> corresponds to the default PMT values.
196 *
197 * Note that in the absence of option <tt>-a</tt>, the detector identifier should be specified
198 * using option <tt>-D</tt> so to obtain the correct PMT address mapping.
199 *
200 * The default value for option <tt>-E</tt> (expectation value for npe given two-fold coincidence)
201 * is taken from Analysis e-log entry <a href="https://elog.km3net.de/Analysis/519">519</a>.\n
202 * The (default) values for option <tt>-T</tt> (time-over-threshold range) should correspond to
203 * the minimal and maximal value at option <tt>-t</tt> of application JCalibrateK40.cc.\n
204 * The values for option <tt>-Q</tt> (QE range) can be used to take into account
205 * the light scaling factor applied in the simulation of the detector response.
206 *
207 * Multiple options <tt>-\@</tt>, <tt>-A</tt> and <tt>-M</tt> will be processed in order of appearance.
208 * \author mdejong
209 */
210int main(int argc, char **argv)
211{
212 using namespace std;
213 using namespace JPP;
214
215 typedef JRange<double> JRange_t;
216
217 string detectorFile;
218 int detectorID;
219 JPMTParametersMap parameters;
223 JProxy<double> mu ("?", 2.05644e-01);
224 JProxy<JRange_t> T_ns("?", JRange_t(4, 250));
225 JRange_t QE;
226 string outputFile;
227 bool squash;
228 int debug;
229
230 try {
231
232 JParser<> zap("Auxiliary program to edit PMT parameters map.");
233
234 zap['a'] = make_field(detectorFile, "detector file.") = "";
235 zap['D'] = make_field(detectorID, "detector identifier (in absence of detector file).") = 0;
236 zap['P'] = make_field(parameters, "PMT simulation data (or corresponding file name)") = JPARSER::initialised();
237 zap['@'] = make_field(hdr, "PMT parameter modifier for default values.") = JPARSER::initialised();
238 zap['A'] = make_field(mod, "PMT parameter modifier by physical address (e.g. B1).") = JPARSER::initialised();
239 zap['M'] = make_field(daq, "PMT parameter modifier by DAQ address (e.g. <module> <channel>.") = JPARSER::initialised();
240 zap['E'] = make_field(mu, "expectation value for npe given two-fold coincidence (" << mu .getOption() << " -> " << mu .getCustom() << ")") = 0.0;
241 zap['T'] = make_field(T_ns, "time-over-threshold rang (" << T_ns.getOption() << " -> " << T_ns.getCustom() << ")") = JRange_t();
242 zap['Q'] = make_field(QE, "QE range.") = JRange_t();
243 zap['o'] = make_field(outputFile, "output file.");
244 zap['q'] = make_field(squash, "squash meta data");
245 zap['d'] = make_field(debug, "debug level") = 2;
246
247 zap(argc, argv);
248 }
249 catch(const exception &error) {
250 FATAL(error.what() << endl);
251 }
252
253
254 if (squash) {
255 parameters.comment.clear();
256 }
257
258 for (vector< JModifier<> >::const_iterator i = hdr.begin(); i != hdr.end(); ++i) {
259
260 DEBUG("Modifying default PMT parameters " << i->action << ' ' << i->key << ' ' << i->value << endl);
261
262 if (!i->apply(parameters.getDefaultPMTParameters())) {
263 ERROR("No valid action: " << *i << endl);
264 }
265 }
266
267 if (detectorFile != "") {
268
269 // Setting default PMT parameters for given detector.
270
272
273 try {
274 load(detectorFile, detector);
275 }
276 catch(const JException& error) {
277 FATAL(error);
278 }
279
280 if (detectorID == 0) {
281
282 detectorID = detector.getID();
283
284 } else if (detectorID != detector.getID()) {
285
286 FATAL("Inconsistent detector identifier " << detectorID << " != " << detector.getID() << endl);
287 }
288
289
290 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
291
292 for (unsigned int pmt = 0; pmt != module->size(); ++pmt) {
293
294 const JPMTIdentifier id(module->getID(), pmt);
295
296 if (parameters.find(id) == parameters.end()) {
297
298 DEBUG("Setting default parameters for PMT " << id << endl);
299
300 parameters[id] = parameters.getDefaultPMTParameters();
301 }
302 }
303 }
304
305 const JModuleRouter router(detector);
306
307 for (JPMTParametersMap::iterator ps = parameters.begin(); ps != parameters.end(); ) {
308
309 if (router.hasModule(ps->first))
310 ++ps;
311 else
312 ps = parameters.erase(ps);
313 }
314 }
315
316 if (!mod.empty()) {
317
318 if (!hasDetectorAddressMap(detectorID)) {
319 FATAL("Invalid detector identifier " << detectorID << endl);
320 }
321
322 const JDetectorAddressMap& demo = getDetectorAddressMap(detectorID);
323
324 for (JPMTParametersMap::iterator ps = parameters.begin(); ps != parameters.end(); ++ps) {
325
326 const JPMTPhysicalAddress& address = demo.get(ps->first);
327
328 for (vector< JModifier<JPMTPhysicalAddress> >::const_iterator i = mod.begin(); i != mod.end(); ++i) {
329
330 if (compare(i->address, address)) {
331
332 DEBUG("Modifying parameters for PMT " << ps->first << ' ' << i->action << ' ' << i->key << ' ' << i->value << endl);
333
334 if (!i->apply(ps->second)) {
335 ERROR("No valid action: " << *i << endl);
336 }
337 }
338 }
339 }
340 }
341
342 if (!daq.empty()) {
343
344 for (JPMTParametersMap::iterator ps = parameters.begin(); ps != parameters.end(); ++ps) {
345
346 for (vector< JModifier<JPMTIdentifier> >::const_iterator i = daq.begin(); i != daq.end(); ++i) {
347
348 if (compare(ps->first, i->address)) {
349
350 DEBUG("Modifying parameters for PMT " << ps->first << ' ' << i->action << ' ' << i->key << ' ' << i->value << endl);
351
352 if (!i->apply(ps->second)) {
353 ERROR("No valid action: " << *i << endl);
354 }
355 }
356 }
357 }
358 }
359
360 if (mu != parameters.getMu()) {
361
362 parameters.convertQEToHitProbability();
363
364 if (mu > 0.0) {
365
366 DEBUG("Correct measured QE for two-hit probability " << mu << endl);
367
368 try {
369 parameters.convertHitProbabilityToQE(mu);
370 }
371 catch(const JException& error) {
372 FATAL(error.what());
373 }
374
375 } else if (mu < 0.0) {
376
377 FATAL("Invalid expection value for two-hit probability " << mu << endl);
378 }
379 } else {
380 DEBUG("mu is unchanged" << endl);
381 }
382
383
384 if (T_ns != JRange_t()) {
385
386 DEBUG("Correct measured QE for time-over-threshold range " << T_ns << endl);
387
388 const int NPE = 1;
389
390 for (JPMTParametersMap::iterator i = parameters.begin(); i != parameters.end(); ++i) {
391
392 const JPMTAnalogueSignalProcessor cpu(i->second);
393
394 i->second.QE *= (cpu.getIntegralOfChargeProbability(i->second.threshold,
395 cpu.getNPE(T_ns.getUpperLimit()),
396 NPE)
397 /
398 cpu.getIntegralOfChargeProbability(cpu.getNPE(T_ns.getLowerLimit()),
399 cpu.getNPE(T_ns.getUpperLimit()),
400 NPE));
401 }
402 }
403
404
405 if (QE != JRange_t()) {
406
407 for (JPMTParametersMap::iterator i = parameters.begin(); i != parameters.end(); ++i) {
408 i->second.QE = QE.constrain(i->second.QE);
409 }
410 }
411
412
413 if (outputFile != "") {
414
415 parameters.comment.add(JMeta(argc, argv));
416
417 ofstream out(outputFile.c_str());
418
419 out << parameters << endl;
420
421 out.close();
422 }
423}
424
string outputFile
Detector support kit.
Data structure for detector geometry and calibration.
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:74
ROOT I/O of application specific meta data.
Direct access to module in detector data structure.
PMT analogue signal processor.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2140
Auxiliary class to define a range between two values.
Lookup table for PMT addresses in detector.
const JModuleAddressMap & get(const int id) const
Get module address map.
Detector data structure.
Definition JDetector.hh:96
Router for direct addressing of module data in detector data structure.
bool hasModule(const JModuleIdentifier &id) const
Has module.
Auxiliary class for map of PMT parameters.
double getMu() const
Get expectation value for number of photo-electrons given two-fold (or higher) coincidence rate.
void convertHitProbabilityToQE(const double mu)
Convert the hit probabilities to QEs for given expectation value.
void convertQEToHitProbability()
Convert the QEs to hit probabilities for given expectation value.
const JPMTParameters & getDefaultPMTParameters() const
Get default PMT parameters.
Data structure for PMT parameters.
JProperties getProperties(const JEquationParameters &equation=JPMTParameters::getEquationParameters())
Get properties of this class.
Data structure for PMT physical address.
int position
position within ring [1,6]
const T & getValue(const std::string &key) const
Get value.
General exception.
Definition JException.hh:25
virtual const char * what() const override
Get error message.
Definition JException.hh:65
int getID() const
Get identifier.
Definition JObjectID.hh:63
Utility class to parse command line options.
Definition JParser.hh:1697
Auxiliary class to assign a custom value following the reading of a specific textual value.
Definition JParser.hh:107
Range of values.
Definition JRange.hh:42
T constrain(argument_type x) const
Constrain value to range.
Definition JRange.hh:350
int main()
std::ostream & operator<<(std::ostream &out, const morphology_type &object)
Write morphology to output stream.
std::istream & operator>>(std::istream &in, morphology_type &object)
Read morphology from input stream.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
JDetectorAddressMap & getDetectorAddressMap()
Get detector address map.
bool hasDetectorAddressMap(const int id)
Check if detector address map is available.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Type definition of range.
Definition JHead.hh:43
Detector file.
Definition JHead.hh:227
virtual double getNPE(const double tot_ns) const override
Get number of photo-electrons.
double getIntegralOfChargeProbability(const double xmin, const double xmax, const int NPE) const
Get integral of probability.
JComment & add(const std::string &comment)
Add comment.
Definition JComment.hh:100
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition JParser.hh:67
Auxiliary class for ROOT I/O of application specific meta data.
Definition JMeta.hh:72