Jpp 20.0.0-72-g597b30bc9
the software that should make you happy
Loading...
Searching...
No Matches
JMuonEnergy.hh
Go to the documentation of this file.
1#ifndef __JRECONSTRUCTION__JMUONENERGY__
2#define __JRECONSTRUCTION__JMUONENERGY__
3
4#include <string>
5#include <istream>
6#include <ostream>
7#include <iomanip>
8#include <set>
9#include <vector>
10#include <algorithm>
11#include <cmath>
12
16
22
24
25#include "JTrigger/JHitR0.hh"
26#include "JTrigger/JBuildL0.hh"
27
29
30#include "JFit/JLine1Z.hh"
32#include "JFit/JFitToolkit.hh"
33#include "JFit/JModel.hh"
34#include "JFit/JNPEHit.hh"
35#include "JFit/JEnergy.hh"
36
43
44#include "JPhysics/JGeane.hh"
45
46
47/**
48 * \author mdejong, azegarelli, scelli
49 */
50namespace JRECONSTRUCTION {}
51namespace JPP { using namespace JRECONSTRUCTION; }
52
53namespace JRECONSTRUCTION {
54
61 using JFIT::JRegressor;
62 using JFIT::JEnergy;
64
65
66 /**
67 * Auxiliary class to to determine muon energy.
68 */
69 class JMuonEnergy :
71 public JRegressor<JEnergy>
72 {
73 public:
77
78 using JRegressor_t::operator();
79
80 /**
81 * Input data type.
82 */
83 struct input_type :
84 public JDAQEventHeader
85 {
86 /**
87 * Default constructor.
88 */
90 {}
91
92
93 /**
94 * Constructor.
95 *
96 * \param header header
97 * \param in start values
98 * \param coverage coverage
99 */
101 const JEvt& in,
102 const coverage_type& coverage) :
103 JDAQEventHeader(header),
104 in(in),
106 {}
107
111 };
112
113
114 /**
115 * Constructor.
116 *
117 * \param parameters parameters
118 * \param storage storage
119 * \param pmtParameters PMT parameters
120 * \param correct energy correction
121 * \param debug debug
122 */
124 const storage_type& storage,
127 const int debug = 0):
128 JMuonEnergyParameters_t(parameters),
129 JRegressor_t (storage),
132 {
133 using namespace JPP;
134
135 if (this->getRmax() < roadWidth_m) {
136 roadWidth_m = this->getRmax();
137 }
138
139 JRegressor_t::debug = debug;
140
141 this->estimator.reset(getMEstimator(mestimator));
142 }
143
144
145 /**
146 * Get input data.
147 *
148 * \param router module router
149 * \param summary summary data
150 * \param event event
151 * \param in start values
152 * \param coverage coverage
153 * \return input data
154 */
156 const JSummaryRouter& summary,
157 const JDAQEvent& event,
158 const JEvt& in,
159 const coverage_type& coverage) const
160 {
161 using namespace std;
162 using namespace JTRIGGER;
163
164 input_type input(event.getDAQEventHeader(), in, coverage);
165
166 const JBuildL0 <JHitR0> buildL0;
168
169 const JDAQTimeslice timeslice(event, true);
170
171 JSuperFrame2D<JHit> buffer;
172
173 for (JDAQTimeslice::const_iterator i = timeslice.begin(); i != timeslice.end(); ++i) {
174
175 if (router.hasModule(i->getModuleID())) {
176
177 buffer(*i, router.getModule(i->getModuleID()));
178
179 buildL0(buffer, back_inserter(data[i->getModuleID()]));
180 }
181 }
182
183 for (const auto& module : router.getReference()) {
184 if (!module.empty()) {
185 input.data.push_back(module_type(module, summary.getSummaryFrame(module.getID(), R_Hz), data[module.getID()]));
186 }
187 }
188
189 return input;
190 }
191
192
193 /**
194 * Auxiliary class for energy estimation.
195 */
196 struct JResult {
197 /**
198 * Constructor.
199 *
200 * \param x Energy [log(E/GeV)]
201 * \param chi2 chi2
202 */
203 JResult(const JEnergy& x = 0.0,
204 const double chi2 = std::numeric_limits<double>::max())
205 {
206 this->x = x;
207 this->chi2 = chi2;
208 }
209
210 /**
211 * Type conversion.
212 *
213 * \return true if valid chi2; else false
214 */
215 operator bool() const
216 {
217 return chi2 != std::numeric_limits<double>::max();
218 }
219
220 JEnergy x; //!< Energy
221 double chi2; //!< chi2
222 };
223
224
225 /**
226 * Fit function.
227 *
228 * \param input input data
229 * \return fit results
230 */
232 {
233 using namespace std;
234 using namespace JPP;
235
236 JEvent event(JMUONENERGY);
237
238 JEvt out;
239
240 // select start values
241
242 JEvt in = input.in;
243
245
246 if (!in.empty()) {
247 in.select(JHistory::is_event(in.begin()->getHistory()));
248 }
249
250 for (JEvt::const_iterator track = in.begin(); track != in.end(); ++track) {
251
252 JFit fit(*track);
253
254 // move track
255
256 if (fit.getW(JSTART_LENGTH_METRES, 0.0) > 0.0) {
257
258 fit.move(fit.getW(JSTART_ZMIN_M), getSpeedOfLight());
259
260 fit.setW(JSTART_ZMIN_M, 0.0);
262 }
263
264 const JRotation3D R (getDirection(fit));
265 const JLine1Z tz(getPosition (fit).rotate(R), fit.getT());
266
267 double zmin = numeric_limits<double>::lowest();
268
269 if (fit.getW(JSTART_LENGTH_METRES, 0.0) > 0.0) {
270 zmin = this->ZMin_m;
271 }
272
273 vector<JNPEHit> data;
274
275 for (const auto& module : input.data) {
276
277 JPosition3D pos(module->getPosition());
278
279 pos.transform(R, tz.getPosition());
280
281 if (pos.getX() <= roadWidth_m) {
282
283 const double z1 = pos.getZ() - pos.getX() / getTanThetaC();
284 const double t1 = tz .getT() + (pos.getZ() + pos.getX() * getKappaC()) * getInverseSpeedOfLight();
285
286 if (z1 >= zmin) {
287
288 for (size_t i = 0; i != module->size(); ++i) {
289
290 if (module.getStatus(i)) {
291
292 const struct {
293
294 bool operator()(const JHitR0& hit) const
295 {
296 return (hit.getPMT() == pmt && T_ns(hit.getT()));
297 }
298
299 const JTimeRange T_ns;
300 const size_t pmt;
301
302 } match = { T_ns + t1, i };
303
304 const JPMTIdentifier id(module->getID(), i);
305
307
308 JPMT pmt = module->getPMT(i);
309
310 pmt.transform(R, tz.getPosition());
311
312 const JNPEHit hit(this->getNPE(pmt, module.frame.getRate(i)), count_if(module.begin(), module.end(), match), ps);
313
314 DEBUG("hit: " << setw(8) << module->getID() << '.' << FILL(2,'0') << i << ' '
315 << FIXED(7,3) << hypot(pmt.getX(), pmt.getY()) << ' '
316 << FIXED(7,3) << module.frame.getRate(i) * 1.0e-3 << ' '
317 << SCIENTIFIC(9,3) << hit.getY0() << ' '
318 << SCIENTIFIC(9,3) << hit.getY1() << ' '
319 << SCIENTIFIC(9,3) << hit.getYA() << ' '
320 << SCIENTIFIC(9,3) << hit.getYB() << ' '
321 << setw(2) << hit.getN() << endl);
322
323 data.push_back(hit);
324 }
325 }
326 }
327 }
328 }
329
330 const int NDF = distance(data.begin(), data.end()) - 1;
331
332 if (NDF >= 0) {
333
334 // 5-point search between given limits
335
336 const int N = 5;
337
338 JResult result[N];
339
340 for (int i = 0; i != N; ++i) {
341 result[i].x = EMin_log + i * (EMax_log - EMin_log) / (N-1);
342 }
343
344 map<double, double> buffer;
345
346 do {
347
348 int j = 0;
349
350 for (int i = 0; i != N; ++i) {
351
352 if (!result[i]) {
353
354 const JEnergy x = result[i].x;
355 const double chi2 = (*this)(x, data.begin(), data.end());
356
357 result[i].chi2 = chi2;
358 buffer[chi2] = x.getE();
359 }
360
361 if (result[i].chi2 < result[j].chi2) {
362 j = i;
363 }
364 }
365
366
367 for (int i = 0; i != N; ++i) {
368 DEBUG(' ' << FIXED(5,2) << result[i].x << ' ' << FIXED(9,3) << result[i].chi2);
369 }
370 DEBUG(endl);
371
372 // squeeze range
373
374 switch (j) {
375
376 case 0:
377 result[4] = result[1];
378 result[2] = result[0];
379 result[0] = JResult(2*result[2].x - result[4].x);
380 break;
381
382 case 1:
383 result[4] = result[2];
384 result[2] = result[1];
385 break;
386
387 case 2:
388 result[0] = result[1];
389 result[4] = result[3];
390 break;
391
392 case 3:
393 result[0] = result[2];
394 result[2] = result[3];
395 break;
396
397 case 4:
398 result[0] = result[3];
399 result[2] = result[4];
400 result[4] = JResult(2*result[2].x - result[0].x);
401 break;
402 }
403
404 result[1] = JResult(0.5 * (result[0].x + result[2].x));
405 result[3] = JResult(0.5 * (result[2].x + result[4].x));
406
407 } while (result[4].x - result[0].x > resolution);
408
409
410 if (result[1].chi2 != result[3].chi2) {
411
412 result[2].x += 0.25 * (result[3].x - result[1].x) * (result[1].chi2 - result[3].chi2) / (result[1].chi2 + result[3].chi2 - 2*result[2].chi2);
413 result[2].chi2 = (*this)(result[2].x, data.begin(), data.end());
414
415 }
416
417 const double chi2 = result[2].chi2;
418 const double E = result[2].x.getE();
419
420 // calculate additional variables
421
422 double Emin = numeric_limits<double>::max();
423 double Emax = numeric_limits<double>::lowest();
424
425 for (map<double, double>::const_iterator i = buffer.begin(); i != buffer.end() && i->first <= chi2 + 1.0; ++i) {
426 if (i->second < Emin) { Emin = i->second; }
427 if (i->second > Emax) { Emax = i->second; }
428 }
429
430 const double mu_range = gWater(E); // range of a muon with the reconstructed energy
431
432 double noise_likelihood = 0.0; // log-likelihood of every hit being from K40
433 int number_of_hits = 0; // number of hits selected for JEnergy
434
435 for (vector<JNPEHit>::const_iterator i = data.begin(); i != data.end(); ++i) {
436 noise_likelihood += log10(getP(i->getY0(), i->getN())); // probability of getting the observed multiplicity with K40
437 number_of_hits += i->getN(); // hit multiplicity
438 }
439
440 fit.push_back(event());
441
442 // set corrected energy
443
444 fit.setE(pow(10.0, correct(log10(E))));
445
446 out.push_back(fit);
447
448 // set additional values
449
450 out.rbegin()->setW(JENERGY_ENERGY, E);
451 out.rbegin()->setW(JENERGY_CHI2, chi2);
452 out.rbegin()->setW(JENERGY_MUON_RANGE_METRES, mu_range);
453 out.rbegin()->setW(JENERGY_NOISE_LIKELIHOOD, noise_likelihood);
454 out.rbegin()->setW(JENERGY_NDF, NDF);
455 out.rbegin()->setW(JENERGY_NUMBER_OF_HITS, number_of_hits);
456 out.rbegin()->setW(JENERGY_MINIMAL_ENERGY, Emin);
457 out.rbegin()->setW(JENERGY_MAXIMAL_ENERGY, Emax);
458 out.rbegin()->setW(JPP_COVERAGE_ORIENTATION, input.coverage.orientation);
459 out.rbegin()->setW(JPP_COVERAGE_POSITION, input.coverage.position);
460 }
461 }
462
463 // apply default sorter
464
465 sort(out.begin(), out.end(), qualitySorter);
466
467 copy(input.in.begin(), input.in.end(), back_inserter(out));
468
469 return out;
470 }
471
473
475 };
476}
477
478#endif
479
Coverage of dynamical detector calibration.
Auxiliary class to extract a subset of optical modules from a detector.
Data structure for detector geometry and calibration.
Data regression method for JFIT::JEnergy.
Auxiliary methods to evaluate Poisson probabilities and chi2.
Energy loss of muon.
Basic data structure for L0 hit.
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
int debug
debug level
Definition JSirene.cc:72
Direct access to module in detector data structure.
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Router for direct addressing of module data in detector data structure.
bool hasModule(const JObjectID &id) const
Has module.
const JModule & getModule(const JObjectID &id) const
Get module parameters.
Data structure for a composite optical module.
Definition JModule.hh:76
Auxiliary class for map of PMT parameters.
const JPMTParameters & getPMTParameters(const JPMTIdentifier &id) const
Get PMT parameters.
Data structure for PMT geometry, calibration and status.
Definition JPMT.hh:49
Data structure for fit of energy.
Data structure for set of track fit results.
void select(const JSelector_t &selector)
Select fits.
Data structure for track fit results with history and optional associated values.
void setW(const std::vector< double > &W)
Set associated values.
void move(const double step, const double velocity)
Move vertex along this track with given velocity.
const std::vector< double > & getW() const
Get associated values.
double getT() const
Get time.
void setE(const double E)
Set energy.
Data structure for fit of straight line paralel to z-axis.
Definition JLine1Z.hh:29
double getT(const JVector3D &pos) const
Get arrival time of Cherenkov light at given position.
Definition JLine1Z.hh:114
void transform(const JAxis3D &axis)
Transform axis to reference frame of given axis.
Definition JAxis3D.hh:359
Data structure for position in three dimensions.
void transform(const JRotation3D &R, const JVector3D &pos)
Transform position.
const JPosition3D & getPosition() const
Get position.
double getY() const
Get y position.
Definition JVector3D.hh:104
double getZ() const
Get z position.
Definition JVector3D.hh:115
double getX() const
Get x position.
Definition JVector3D.hh:94
const JClass_t & getReference() const
Get reference to object.
Definition JReference.hh:38
Auxiliary class for correction of energy determined by JEnergy.cc.
Auxiliary class to to determine muon energy.
const JPMTParametersMap & pmtParameters
JEvt operator()(const input_type &input)
Fit function.
JRegressor< JEnergy > JRegressor_t
std::vector< module_type > detector_type
input_type getInput(const JModuleRouter &router, const JSummaryRouter &summary, const JDAQEvent &event, const JEvt &in, const coverage_type &coverage) const
Get input data.
JMuonEnergy(const JMuonEnergyParameters_t &parameters, const storage_type &storage, const JPMTParametersMap &pmtParameters, const JEnergyCorrection &correct, const int debug=0)
Constructor.
Router for fast addressing of summary data in KM3NETDAQ::JDAQSummaryslice data structure as a functio...
const JDAQSummaryFrame & getSummaryFrame(const JDAQModuleIdentifier &module) const
Get summary frame.
Reduced data structure for L0 hit.
Definition JHitR0.hh:27
JPMT_t getPMT() const
Get PMT.
Definition JHitR0.hh:60
double getT() const
Get calibrated time of hit.
2-dimensional frame with time calibrated data from one optical module.
const JDAQEventHeader & getDAQEventHeader() const
Get DAQ event header.
Data storage class for rate measurements of all PMTs in one module.
static const int JSTART_ZMAX_M
end position of track see JRECONSTRUCTION::JMuonStart
static const int JENERGY_NDF
number of degrees of freedom see JRECONSTRUCTION::JMuonEnergy
static const int JENERGY_ENERGY
uncorrected energy [GeV] see JRECONSTRUCTION::JMuonEnergy
static const int JENERGY_NOISE_LIKELIHOOD
log likelihood of every hit being K40 see JRECONSTRUCTION::JMuonEnergy
static const int JENERGY_CHI2
chi2 see JRECONSTRUCTION::JMuonEnergy
static const int JENERGY_MUON_RANGE_METRES
range of a muon with the reconstructed energy [m] see JRECONSTRUCTION::JMuonEnergy
static const int JPP_COVERAGE_POSITION
coverage of dynamic position calibration of this event
static const int JENERGY_NUMBER_OF_HITS
number of hits see JRECONSTRUCTION::JMuonEnergy
static const int JSTART_LENGTH_METRES
distance between projected positions on the track of optical modules for which the response does not ...
static const int JSTART_ZMIN_M
start position of track see JRECONSTRUCTION::JMuonStart
static const int JPP_COVERAGE_ORIENTATION
coverage of dynamic orientation calibration of this event
static const int JENERGY_MINIMAL_ENERGY
minimal energy [GeV] see JRECONSTRUCTION::JMuonEnergy
static const int JENERGY_MAXIMAL_ENERGY
maximal energy [GeV] see JRECONSTRUCTION::JMuonEnergy
double getNPE(const Hit &hit)
Get true charge of hit.
double getSurvivalProbability(const JPMTParameters &parameters)
Get model dependent probability that a one photo-electron hit survives the simulation of the PMT assu...
JMEstimator * getMEstimator(const int type)
Get M-Estimator.
double getP(const double expval, bool hit)
Get Poisson probability to observe a hit or not for given expectation value for the number of hits.
T pow(const T &x, const double y)
Power .
Definition JMath.hh:97
double getKappaC()
Get average R-dependence of arrival time of Cherenkov light (a.k.a.
const double getInverseSpeedOfLight()
Get inverse speed of light.
static const JGeaneWater gWater
Function object for energy loss of muon in sea water.
Definition JGeane.hh:381
double getTanThetaC()
Get average tangent of Cherenkov angle of water corresponding to group velocity.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
JPosition3D getPosition(const JFit &fit)
Get position.
void copy(const JFIT::JEvt::const_iterator __begin, const JFIT::JEvt::const_iterator __end, Evt &out)
Copy tracks.
bool qualitySorter(const JFit &first, const JFit &second)
Comparison of fit results.
JDirection3D getDirection(const JFit &fit)
Get direction.
return result
Definition JPolint.hh:862
int j
Definition JPolint.hh:801
Auxiliary classes and methods for triggering.
Auxiliary data structure for sequence of same character.
Definition JManip.hh:330
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Data structure for coverage of detector by dynamical calibrations.
Definition JCoverage.hh:19
double position
coverage of detector by available position calibration [0,1]
Definition JCoverage.hh:42
double orientation
coverage of detector by available orientation calibration [0,1]
Definition JCoverage.hh:41
Auxiliary class for historical event.
Definition JHistory.hh:40
Auxiliary class to test history.
Definition JHistory.hh:157
double getY0() const
Get light yield due to random background.
Definition JK40.hh:49
Auxiliary class for simultaneously handling light yields and response of PMT.
Definition JNPEHit.hh:21
size_t getN() const
Get number of hits.
Definition JNPEHit.hh:53
double getYB() const
Get light yield due to bremsstrahlung.
Definition JNPE.hh:93
double getY1() const
Get light yield due to minimum ionizing particle.
Definition JNPE.hh:71
double getYA() const
Get light yield due to delta-rays.
Definition JNPE.hh:82
Template definition of a data regressor of given model.
Definition JRegressor.hh:70
Auxiliary class for handling module response.
Definition JModuleL0.hh:45
double resolution
energy resolution [log10(GeV)]
int mestimator
M-estimator (see JFIT::JMEstimator_t)
double EMin_log
minimal energy [log10(GeV)]
double EMax_log
maximal energy [log10(GeV)]
Auxiliary class for energy estimation.
JResult(const JEnergy &x=0.0, const double chi2=std::numeric_limits< double >::max())
Constructor.
input_type(const JDAQEventHeader &header, const JEvt &in, const coverage_type &coverage)
Constructor.
Auxiliary data structure for floating point format specification.
Definition JManip.hh:488