Jpp  19.1.0
the software that should make you happy
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 
17 #include "JDetector/JDetector.hh"
20 
21 #include "JTrigger/JHitL0.hh"
22 #include "JTrigger/JHitR1.hh"
23 #include "JTrigger/JBuildL0.hh"
24 
26 
27 #include "JFit/JLine1Z.hh"
28 #include "JFit/JEnergyRegressor.hh"
29 #include "JFit/JFitToolkit.hh"
30 #include "JFit/JModel.hh"
31 #include "JFit/JNPEHit.hh"
32 #include "JFit/JEnergy.hh"
33 
35 #include "JReconstruction/JEvt.hh"
38 
39 #include "JPhysics/JGeane.hh"
40 
41 
42 /**
43  * \author mdejong, azegarelli, scelli
44  */
45 namespace JRECONSTRUCTION {}
46 namespace JPP { using namespace JRECONSTRUCTION; }
47 
48 namespace JRECONSTRUCTION {
49 
52  using JFIT::JRegressor;
53  using JFIT::JEnergy;
54 
55  /**
56  * Auxiliary class to to determine muon energy.
57  */
58  class JMuonEnergy :
60  public JRegressor<JEnergy>
61  {
62  public:
67 
68  using JRegressor_t::operator();
69 
70  /**
71  * Constructor.
72  *
73  * \param parameters parameters
74  * \param router module router
75  * \param summary summary router
76  * \param pdfFile PDF file
77  * \param debug debug
78  */
80  const JModuleRouter& router,
81  const JSummaryRouter& summary,
82  const std::string& pdfFile,
83  const int debug = 0):
84  JMuonEnergyParameters_t(parameters),
85  JRegressor_t(pdfFile),
86  router(router),
88  debug(debug)
89  {
90  using namespace JPP;
91 
93  JRegressor_t::T_ns.setRange(TMin_ns, TMax_ns);
94 
95  if (this->getRmax() < roadWidth_m) {
96  roadWidth_m = this->getRmax();
97  }
98 
99  this->estimator.reset(getMEstimator(mestimator));
100 
101  if (!this->estimator.is_valid()) {
102  FATAL("Invalid M-Estimator." << endl);
103  }
104  }
105 
106 
107  /**
108  * Auxiliary class for energy estimation.
109  */
110  struct JResult {
111  /**
112  * Constructor.
113  *
114  * \param x Energy [log(E/GeV)]
115  * \param chi2 chi2
116  */
117  JResult(const JEnergy& x = 0.0,
118  const double chi2 = std::numeric_limits<double>::max())
119  {
120  this->x = x;
121  this->chi2 = chi2;
122  }
123 
124  /**
125  * Type conversion.
126  *
127  * \return true if valid chi2; else false
128  */
129  operator bool() const
130  {
131  return chi2 != std::numeric_limits<double>::max();
132  }
133 
134  JEnergy x; //!< Energy
135  double chi2; //!< chi2
136  };
137 
138 
139  /**
140  * Fit function.
141  *
142  * \param event event
143  * \param in start values
144  * \return fit results
145  */
146  JEvt operator()(const KM3NETDAQ::JDAQEvent& event, const JEvt& in)
147  {
148  using namespace std;
149  using namespace JPP;
150 
151  JEvt out;
152 
153  typedef vector<JHitL0> JDataL0_t;
154  const JBuildL0<JHitL0> buildL0;
155 
157 
158  JDataL0_t dataL0;
159 
160  buildL0(JDAQTimeslice(event, true), router, back_inserter(dataL0));
161 
162  for (JEvt::const_iterator track = in.begin(); track != in.end(); ++track) {
163 
164  const JRotation3D R (getDirection(*track));
165  const JLine1Z tz(getPosition (*track).rotate(R), track->getT());
166  const JFIT::JModel<JLine1Z> match(tz, roadWidth_m, JRegressor_t::T_ns);
167 
169 
171 
172  for (JDataL0_t::const_iterator i = dataL0.begin(); i !=dataL0.end(); ++i) {
173 
174  JHitR1 hit(*i);
175 
176  hit.rotate(R);
177 
178  if (match(hit)) {
179  top.insert(i->getPMTIdentifier());
180  }
181  }
182 
183  JRange<double> Z_m;
184 
185  if ( track->hasW(JSTART_LENGTH_METRES) && track->getW(JSTART_LENGTH_METRES) > 0.0 ) {
186  Z_m.setLowerLimit(this->ZMin_m);
187  }
188 
189  const JDetectorSubset_t subdetector(detector, getAxis(*track), roadWidth_m, Z_m);
190 
191  for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
192 
193  if (summary.hasSummaryFrame(module->getID())) {
194 
195  const JDAQSummaryFrame& frame = summary.getSummaryFrame(module->getID());
196 
197  for (size_t i = 0; i != module->size(); ++i) {
198 
199  if (getDAQStatus(frame, *module, i) &&
200  getPMTStatus(frame, *module, i) &&
201  frame[i].is_valid() &&
202  !module->getPMT(i).has(PMT_DISABLE)) {
203 
204  const JDAQPMTIdentifier id(module->getID(), i);
205 
206  const double rate_Hz = summary.getRate(id);
207  const size_t count = top.count(id);
208 
209  data.push_back(JNPEHit(this->getNPE(module->getPMT(i), rate_Hz), count));
210  }
211  }
212  }
213  }
214 
215  const int NDF = distance(data.begin(), data.end()) - 1;
216 
217  if( NDF >= 0 ) {
218 
219  // 5-point search between given limits
220 
221  const int N = 5;
222 
223  JResult result[N];
224 
225  for (int i = 0; i != N; ++i) {
226  result[i].x = EMin_log + i * (EMax_log - EMin_log) / (N-1);
227  }
228 
229  map<double, double> buffer;
230 
231  do {
232 
233  int j = 0;
234 
235  for (int i = 0; i != N; ++i) {
236 
237  if (!result[i]) {
238 
239  const JEnergy x = result[i].x;
240  const double chi2 = (*this)(x, data.begin(), data.end());
241 
242  result[i].chi2 = chi2;
243  buffer[chi2] = x.getE();
244  }
245 
246  if (result[i].chi2 < result[j].chi2) {
247  j = i;
248  }
249  }
250 
251 
252  for (int i = 0; i != N; ++i) {
253  DEBUG(' ' << FIXED(5,2) << result[i].x << ' ' << FIXED(9,3) << result[i].chi2);
254  }
255  DEBUG(endl);
256 
257  // squeeze range
258 
259  switch (j) {
260 
261  case 0:
262  result[4] = result[1];
263  result[2] = result[0];
264  result[0] = JResult(2*result[2].x - result[4].x);
265  break;
266 
267  case 1:
268  result[4] = result[2];
269  result[2] = result[1];
270  break;
271 
272  case 2:
273  result[0] = result[1];
274  result[4] = result[3];
275  break;
276 
277  case 3:
278  result[0] = result[2];
279  result[2] = result[3];
280  break;
281 
282  case 4:
283  result[0] = result[3];
284  result[2] = result[4];
285  result[4] = JResult(2*result[2].x - result[0].x);
286  break;
287  }
288 
289  result[1] = JResult(0.5 * (result[0].x + result[2].x));
290  result[3] = JResult(0.5 * (result[2].x + result[4].x));
291 
292  } while (result[4].x - result[0].x > resolution);
293 
294 
295  if (result[1].chi2 != result[3].chi2) {
296 
297  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);
298  result[2].chi2 = (*this)(result[2].x, data.begin(), data.end());
299 
300  }
301 
302  const double chi2 = result[2].chi2;
303  const double E = result[2].x.getE();
304 
305  // calculate additional variables
306 
307  double Emin = numeric_limits<double>::max();
308  double Emax = numeric_limits<double>::lowest();
309 
310  for (map<double, double>::const_iterator i = buffer.begin(); i != buffer.end() && i->first <= chi2 + 1.0; ++i) {
311  if (i->second < Emin) { Emin = i->second; }
312  if (i->second > Emax) { Emax = i->second; }
313  }
314 
315  const double mu_range = gWater(E); // range of a muon with the reconstructed energy
316 
317  double noise_likelihood = 0.0; // log-likelihood of every hit being from K40
318  int number_of_hits = 0; // number of hits selected for JEnergy
319 
320  for (vector<JNPEHit>::const_iterator i = data.begin(); i != data.end(); ++i) {
321  noise_likelihood += log10(getP(i->getY0(), i->getN())); // probability of getting the observed multiplicity with K40
322  number_of_hits += i->getN(); // hit multiplicity
323  }
324 
325  out.push_back(JFit(*track).add(JMUONENERGY));
326 
327  out.rbegin()->setE(E);
328 
329  out.rbegin()->setW(track->getW());
330  out.rbegin()->setW(JENERGY_ENERGY, E);
331  out.rbegin()->setW(JENERGY_CHI2, chi2);
332  out.rbegin()->setW(JENERGY_MUON_RANGE_METRES, mu_range);
333  out.rbegin()->setW(JENERGY_NOISE_LIKELIHOOD, noise_likelihood);
334  out.rbegin()->setW(JENERGY_NDF, NDF);
335  out.rbegin()->setW(JENERGY_NUMBER_OF_HITS, number_of_hits);
336  out.rbegin()->setW(JENERGY_MINIMAL_ENERGY, Emin);
337  out.rbegin()->setW(JENERGY_MAXIMAL_ENERGY, Emax);
338  }
339  }
340 
341  return out;
342  }
343 
344  private:
347  int debug;
348  };
349 }
350 
351 #endif
352 
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.
Reduced data structure for L1 hit.
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
#define FATAL(A)
Definition: JMessage.hh:67
int debug
debug level
Definition: JSirene.cc:69
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.
Detector subset without binary search functionality.
Detector data structure.
Definition: JDetector.hh:96
Router for direct addressing of module data in detector data structure.
Data structure for fit of energy.
Definition: JEnergy.hh:31
Data structure for set of track fit results.
JFit & add(const int type)
Add event to history.
Data structure for fit of straight line paralel to z-axis.
Definition: JLine1Z.hh:29
JPosition3D & rotate(const JRotation3D &R)
Rotate.
Definition: JPosition3D.hh:186
Rotation matrix.
Definition: JRotation3D.hh:114
const JClass_t & getReference() const
Get reference to object.
Definition: JReference.hh:38
Auxiliary class to to determine muon energy.
Definition: JMuonEnergy.hh:61
JTRIGGER::JHitR1 hit_type
Definition: JMuonEnergy.hh:64
JTOOLS::JRange< JEnergy > JEnergyRange
Definition: JMuonEnergy.hh:66
JMuonEnergy(const JMuonEnergyParameters_t &parameters, const JModuleRouter &router, const JSummaryRouter &summary, const std::string &pdfFile, const int debug=0)
Constructor.
Definition: JMuonEnergy.hh:79
std::vector< hit_type > buffer_type
Definition: JMuonEnergy.hh:65
const JModuleRouter & router
Definition: JMuonEnergy.hh:345
JEvt operator()(const KM3NETDAQ::JDAQEvent &event, const JEvt &in)
Fit function.
Definition: JMuonEnergy.hh:146
const JSummaryRouter & summary
Definition: JMuonEnergy.hh:346
JRegressor< JEnergy > JRegressor_t
Definition: JMuonEnergy.hh:63
Router for fast addressing of summary data in KM3NETDAQ::JDAQSummaryslice data structure as a functio...
bool hasSummaryFrame(const JDAQModuleIdentifier &module) const
Has summary frame.
const JDAQSummaryFrame & getSummaryFrame() const
Get default summary frame.
double getRate() const
Get default rate.
Range of values.
Definition: JRange.hh:42
void setLowerLimit(argument_type x)
Set lower limit.
Definition: JRange.hh:224
Template specialisation of L0 builder for JHitL0 data type.
Definition: JBuildL0.hh:105
Reduced data structure for L1 hit.
Definition: JHitR1.hh:35
Data storage class for rate measurements of all PMTs in one module.
static const int JMUONENERGY
static const int JENERGY_NDF
number of degrees of freedom from JEnergy.cc
static const int JENERGY_ENERGY
uncorrected energy [GeV] from JEnergy.cc
static const int JENERGY_NOISE_LIKELIHOOD
log likelihood of every hit being K40 from JEnergy.cc
static const int JENERGY_CHI2
chi2 from JEnergy.cc
static const int JENERGY_MUON_RANGE_METRES
range of a muon with the reconstructed energy [m] from JEnergy.cc
static const int JENERGY_NUMBER_OF_HITS
number of hits from JEnergy.cc
static const int JSTART_LENGTH_METRES
distance between first and last hits in metres from JStart.cc
static const int JENERGY_MINIMAL_ENERGY
minimal energy [GeV] from JEnergy.cc
static const int JENERGY_MAXIMAL_ENERGY
maximal energy [GeV] from JEnergy.cc
JAxis3D getAxis(const Trk &track)
Get axis.
JDirection3D getDirection(const Vec &dir)
Get direction.
JPosition3D getPosition(const Vec &pos)
Get position.
double getNPE(const Hit &hit)
Get true charge of hit.
JMEstimator * getMEstimator(const int type)
Get M-Estimator.
Definition: JMEstimator.hh:203
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.
Definition: JFitToolkit.hh:41
static const JGeaneWater gWater
Function object for energy loss of muon in sea water.
Definition: JGeane.hh:381
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Model fits to data.
bool is_valid(const json &js)
Check validity of JSon data.
int j
Definition: JPolint.hh:792
bool getDAQStatus(const JDAQFrameStatus &frame, const JStatus &status)
Test status of DAQ.
bool getPMTStatus(const JStatus &status)
Test status of PMT.
Definition: JSTDTypes.hh:14
static const int PMT_DISABLE
KM3NeT Data Definitions v3.4.0-8-ge14cb17 https://git.km3net.de/common/km3net-dataformat.
Definition: pmt_status.hh:12
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:448
Detector file.
Definition: JHead.hh:227
Template specialisation of class JModel to match hit with muon trajectory along z-axis.
Definition: JFit/JModel.hh:36
Auxiliary class for simultaneously handling light yields and response of PMT.
Definition: JNPEHit.hh:21
Regressor function object for fit of muon energy.
Template definition of a data regressor of given model.
Definition: JRegressor.hh:70
Data structure for fit parameters.
double TMin_ns
minimal time w.r.t. Cherenkov hypothesis [ns]
double resolution
energy resolution [log10(GeV)]
double EMin_log
minimal energy [log10(GeV)]
double TMax_ns
maximal time w.r.t. Cherenkov hypothesis [ns]
double EMax_log
maximal energy [log10(GeV)]
Auxiliary class for energy estimation.
Definition: JMuonEnergy.hh:110
JResult(const JEnergy &x=0.0, const double chi2=std::numeric_limits< double >::max())
Constructor.
Definition: JMuonEnergy.hh:117