Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JShowerPostfit.cc
Go to the documentation of this file.
1 #include <string>
2 #include <iostream>
3 #include <iomanip>
4 #include <vector>
5 #include <set>
6 
7 #include "TROOT.h"
8 #include "TFile.h"
9 #include "TH1D.h"
10 #include "TH2D.h"
11 #include "TProfile.h"
12 #include "TMath.h"
13 
19 
20 #include "JAAnet/JHead.hh"
21 #include "JAAnet/JHeadToolkit.hh"
22 #include "JDAQ/JDAQEventIO.hh"
23 #include "JTools/JConstants.hh"
24 #include "JTools/JQuantile.hh"
28 #include "JSupport/JSupport.hh"
29 #include "JReconstruction/JEvt.hh"
31 #include "JGizmo/JVolume.hh"
32 #include "JLang/JPredicate.hh"
33 #include "JPhysics/JGeanz.hh"
34 #include "JGeometry3D/JShower3E.hh"
36 
37 #include "Jeep/JParser.hh"
38 #include "Jeep/JMessage.hh"
39 
40 namespace {
41 
43 
44 
45  /**
46  * Count number of unique identifiers in event.
47  *
48  * \param __begin begin of data
49  * \param __end end of data
50  * \return number of unique identifiers
51  */
52  template<class JHit_t>
53  inline int getCount(JDAQEvent::const_iterator<JHit_t> __begin,
55  {
56  using namespace std;
57  using namespace KM3NETDAQ;
58 
59  typedef JDAQModuleIdentifier JType_t;
60 
61  set<JType_t> buffer;
62 
63  for (JDAQEvent::const_iterator<JHit_t> i = __begin; i != __end; ++i) {
64  buffer.insert(JType_t(*i));
65  }
66 
67  return buffer.size();
68  }
69 }
70 
71 
72 /**
73  * \file
74  *
75  * Example program to histogram shower fit results: it handles both neutrino and muon productions.
76  *
77  * \author mdejong, adomi
78  */
79 int main(int argc, char **argv)
80 {
81  using namespace std;
82  using namespace JPP;
83  using namespace KM3NETDAQ;
84 
85  typedef JTriggeredFileScanner<JEvt> JTriggeredFileScanner_t;
86  typedef JTriggeredFileScanner_t::multi_pointer_type multi_pointer_type;
87 
88  JTriggeredFileScanner_t inputFile;
89  JLimit_t& numberOfEvents = inputFile.getLimit();
90  string outputFile;
91  size_t numberOfPrefits;
93  JAtmosphericMuon atmosphere;
94  double Emin_GeV;
95  double NPE;
96  int application;
97  string option;
98  bool isMuon;
99  bool wrtNeutrino;
100  double radius;
101  JRange<double> height;
102  int debug;
103 
104  try {
105 
106  JParser<> zap("Example program to histogram fit results.");
107 
108  zap['f'] = make_field(inputFile);
109  zap['o'] = make_field(outputFile) = "postfit.root";
110  zap['n'] = make_field(numberOfEvents) = JLimit::max();
111  zap['N'] = make_field(numberOfPrefits) = 1;
113  zap['E'] = make_field(Emin_GeV) = 0.0;
114  zap['M'] = make_field(NPE) = 0.0;
116  zap['a'] = make_field(atmosphere) = JAtmosphericMuon(90.0, 90.0);
117  zap['O'] = make_field(option) = "E", "N", "LINE", "LOGE";
118  zap['I'] = make_field(isMuon);
119  zap['w'] = make_field(wrtNeutrino);
120  zap['r'] = make_field(radius) = JLimit::max(); // no containment
121  zap['z'] = make_field(height) = JRange<double>(-JLimit::max(), JLimit::max()); // no containment
122  zap['d'] = make_field(debug) = 2;
123 
124  zap(argc, argv);
125  }
126  catch(const exception& error) {
127  FATAL(error.what() << endl);
128  }
129 
130  cout << "APPLICATION " << application << endl;
131 
132  JHead head;
133 
134  try {
135  head = getHeader(inputFile);
136  }
137  catch(const JException& error) {
138  FATAL(error);
139  }
140 
141  const JVolume volume(head, option != "LINE");
142  const JPosition3D center = get<JPosition3D>(head);
143  JCylinder3D cylinder = get<JCylinder3D>(head);
144 
145  cylinder.add(center);
146 
147  NOTICE("Center: " << center << endl);
148  NOTICE("Reposition can [m]: " << cylinder << endl);
149 
150  const double EMIN_GEV = 10e3; // MUPAGE
151 
152  TFile out(outputFile.c_str(), "recreate");
153 
154  TH1D job("job", NULL, 100, 0.5, 100.5);
155 
156  TH1D hn("hn", "NDF (Number of Degrees of Freedom)", 250, -0.5, 249.5);
157  TH1D hq("hq", "Fit Quality", 300, 0.0, 600.0);
158  TH1D hi("hi", "Fit Index vs Best Resolution", 101, -0.5, 100.5); // to see if the fit with the best quality has also the best resolution
159  TH1D hd("hd", "Square Distance between Reco and True position", 2000, 0.0, 400.0); // [m]
160  TH1D hz("hz", "Longitudinal Distance between Reco and MC lepton position", 100, -200.0, 200.0); // [m]
161  TH1D ht("ht", "Time difference between Reco and MC lepton", 100, -100.0, 100.0); // [ns]
162 
163  TH1D ha("ha", "Angle between reco direction and true direction", 1000, 0.0, 180.0); // [ns]
164 
165  TH1D e0("e0", "True lepton energy", 100, volume.getXmin(), volume.getXmax()); // [log(E)]
166  TH1D e2("e2", "Reconstructed energy", 100, volume.getXmin(), volume.getXmax()); // [log(E)]
167  TH1D er("er", "Ratio of reconstructed energy and true energy", 100, -5.0, +5.0); // [log(E/E)]
168  TH1D ea("ea", "Distribution of Energy error for all the events; E_{reco}-E_{true}", 100, -30, +30);
169  TH1D ed3_5GeV("ed3_5GeV", "Distribution of Energy error for events with MC energy #in [3,5] GeV; E_{reco}-E_{true}", 100, -30, +30);
170  TH1D ed8_11GeV("ed8_11GeV", "Distribution of Energy error for events with MC energy #in [8,11] GeV; E_{reco}-E_{true}", 100, -30, +30);
171  TH1D ed15_21GeV("ed15_21GeV", "Distribution of Energy error for events with MC energy #in [15,21] GeV; E_{reco}-E_{true}", 100, -30, +30);
172  TH2D ee("ee", "; E_{true} [GeV]; E_{reco} [GeV]",
173  40, volume.getXmin(), volume.getXmax(),
174  40, volume.getXmin(), volume.getXmax());
175 
176  const Int_t ny = 28800;
177  const Double_t ymin = 0.0; // [deg]
178  const Double_t ymax = 180.0; // [deg]
179 
180  vector<double> X;
181 
182  if (option.find('E') != string::npos) {
183 
184  for (double x = volume.getXmin(); x <= volume.getXmax(); x += (volume.getXmax() - volume.getXmin()) / 20) {
185  X.push_back(x);
186  }
187 
188  } else {
189 
190  double x = -0.5;
191 
192  for ( ; x <= 15.5; x += 1.0) { X.push_back(x); }
193  for ( ; x <= 25.5; x += 2.0) { X.push_back(x); }
194  for ( ; x <= 50.5; x += 5.0) { X.push_back(x); }
195  for ( ; x <= 100.5; x += 10.0) { X.push_back(x); }
196  for ( ; x <= 250.5; x += 20.0) { X.push_back(x); }
197  }
198 
199  TH2D h2("h2", NULL, X.size() - 1, X.data(), ny, ymin, ymax);
200 
201  TProfile herrorE("herrorE", "Energy Error", X.size() - 1, X.data());
202  TProfile hfracE( "hfracE", "Fractional Energy Error", X.size() - 1, X.data());
203  TProfile he("he","Reconstruction Efficiency", X.size() - 1, X.data());
204  TProfile htheta_nu_lep("htheta_nu_lep", "Angle between neutrino and primary lepton", X.size() - 1, X.data());
205 
206  TH2D hb("hb", NULL, 100, 0.0, 0.5e6, 100, -100.0, +900.0);
207  TH2S hmca("hmca", NULL, X.size() - 1, X.data(), 1000, 0, 180);
208 
209  TH2D hzenith("hzenith", "Reco Zenith vs MC Energy", 100, 0, 100, ny, ymin, ymax);
210 
211 
212  JQuantile Q("Angle", true);
213  JQuantile O("Omega", true);
214 
215 
216  while (inputFile.hasNext()) {
217 
218  STATUS("event: " << setw(10) << inputFile.getCounter() << '\r'); DEBUG(endl);
219 
220  multi_pointer_type ps = inputFile.next();
221 
222  JDAQEvent* tev = ps;
223  JEvt* evt = ps; // Reco event
224  Evt* event = ps; // MC event
225 
226  const JTimeConverter converter(*event, *tev);
227 
228  job.Fill(1.0);
229 
230  double Enu = 0.0;
231  double Elep = 0.0;
232  double Emax = 0.0;
233 
234  Trk neutrino;
235 
236  if(has_neutrino(*event)){
237 
238  neutrino = get_neutrino(*event);
239  Enu = neutrino.E;
240 
241  }
242 
243  vector<Trk>::const_iterator lepton = event->mc_trks.end(); // can be electron or muon
244 
245  for (vector<Trk>::const_iterator mc_evt = event->mc_trks.begin(); mc_evt != event->mc_trks.end(); ++mc_evt) {
246 
247  if (!isMuon && is_electron(*mc_evt)) {
248 
249  Elep += mc_evt->E;
250 
251  if (mc_evt->E > Emax) {
252  lepton = mc_evt;
253  Emax = mc_evt->E;
254  }
255 
256 
257  } else if(isMuon && is_muon(*mc_evt)){
258 
259  Elep += mc_evt->E;
260  if (mc_evt->E > Emax) {
261  lepton = mc_evt;
262  Emax = mc_evt->E;
263  }
264  }
265  }
266 
267  if (lepton == event->mc_trks.end()) {
268  continue;
269  }
270 
271  job.Fill(3.0);
272 
273 
274  // abscissa
275 
276  Double_t x = 0.0;
277 
278  if (option.find('E') != string::npos){
279 
280  if(wrtNeutrino == true && !isMuon) x = volume.getX(neutrino.E);
281  else if(!wrtNeutrino && !isMuon) x = volume.getX(lepton->E);
282 
283  } else{
284  x = getCount(tev->begin<JDAQTriggeredHit>(), tev->end<JDAQTriggeredHit>());
285  }
286 
287  // weight for efficiency determination
288  Double_t W = 0.0;
289 
290  if (!evt->empty()) {
291 
292  JEvt::iterator __end = partition(evt->begin(), evt->end(), JHistory::is_event(application));
293 
294  if (evt->begin() == __end) {
295  continue;
296  }
297 
298  job.Fill(4.0);
299 
300  //if (numberOfPrefits > 0 && numberOfPrefits < (size_t) distance(evt->begin(), evt->end())) {
301  if (numberOfPrefits > 0 ) {
302 
303  JEvt::iterator __q = __end;
304 
305  advance(__end = evt->begin(), min(numberOfPrefits, (size_t) distance(evt->begin(), __q)));
306 
307  partial_sort(evt->begin(), __end, __q, quality_sorter);
308 
309  } else {
310 
311  sort(evt->begin(), __end, quality_sorter);
312  }
313 
314  JEvt::iterator best = evt->begin(); // the best shower is the one with the best quality
315 
316  JPosition position(getPosition(lepton->pos)); // by default the lepton pos is the interaction vertex
317  JPointing pointing(getDirection(*lepton));
318  JShowerEnergy energy(lepton->E);
319 
320  JVector3D showerBrightPoint(getPosition(lepton->pos) + center + getPosition(lepton->dir) * geanz.getMaximum(lepton->E));
321 
322  if(!wrtNeutrino && !isMuon){
323  position = JPosition(showerBrightPoint); // wrt the em shower brightest point
324  } else if(wrtNeutrino == true && !isMuon){
325  position = JPosition(getPosition(neutrino));
326  pointing = JPointing(getDirection(neutrino));
327  energy = JShowerEnergy(Enu);
328  }
329 
330  JEvt::iterator fit_with_smallest_error = best;
331 
332  if(application == JSHOWERPREFIT || application == JSHOWERPOINTSIMPLEX || application == JSHOWERPOSITIONFIT){
333  fit_with_smallest_error = position(evt->begin(), __end);
334  } else if (application == JSHOWERENERGYPREFIT){
335  fit_with_smallest_error = energy(evt->begin(), __end);
336  } else {
337  fit_with_smallest_error = pointing(evt->begin(), __end);
338  }
339 
340  const Double_t beta = pointing.getAngle(*best);
341  const double Efit = best->getE();
342 
343  JCylinder3D containment(JCircle2D(getPosition(*best), radius), height.getLowerLimit(), height.getUpperLimit());
344 
345  if(containment.is_inside(getPosition(*best))){
346 
347  // selection of fit result
348  bool ok = (Efit >= Emin_GeV);
349 
350  if (ok) {
351 
352  W = 1.0;
353 
354  job.Fill(5.0);
355 
356  hn.Fill((Double_t) best->getNDF());
357  hq.Fill(best->getQ());
358  hi.Fill((Double_t) distance(evt->begin(), fit_with_smallest_error));
359 
360  Q.put(beta);
361 
362  JShower3E ta;
363 
364  if(wrtNeutrino){
365  ta = getTrack(neutrino);
366  } else {
367  ta = getTrack(*lepton); // MC event
368  }
369 
370  JShower3E tb = getTrack(*best); // Reco event
371 
372  double zenith = tb.getDirection().getTheta() * 180 / PI;
373 
374  // take into account the difefrent MC/Reco geometry and time
375  ta.add(center);
376  tb.sub(converter.putTime());
377 
378  if(!isMuon && !wrtNeutrino){
379 
380  double distance_m = (tb.getPosition() - JPosition3D(showerBrightPoint)).getLength();
381 
382  hd.Fill(distance_m * distance_m);
383 
384  } else {
385 
386  double distance_m = (tb.getPosition() - ta.getPosition()).getLength();
387 
388  hd.Fill(distance_m * distance_m);
389 
390  }
391 
392  if (has_neutrino(*event)) {
393 
394  job.Fill(6.0);
395 
396  JPosition3D mc_vx = getPosition(neutrino); // mc vertex
397 
398  mc_vx.add(center);
399 
400  if (cylinder.is_inside(mc_vx)) {
401 
402  job.Fill(7.0);
403 
404  hz.Fill(tb.getIntersection(mc_vx));
405  }
406  }
407 
408  if (best->getE() >= EMIN_GEV) {
409  hb.Fill(best->getX()*best->getX() + best->getY()*best->getY(), best->getZ());
410  }
411 
412  ht.Fill(tb.getT() - ta.getT());
413 
414  ha.Fill(getAngle(ta.getDirection(), tb.getDirection()));
415 
416  htheta_nu_lep.Fill(x, getAngle(getDirection(neutrino), getDirection(*lepton)));
417  hmca.Fill(x, getAngle(ta.getDirection(), tb.getDirection()));
418 
419  if(wrtNeutrino){
420 
421  e0.Fill(volume.getX(Enu, true));
422  er.Fill(volume.getX(Efit) - volume.getX(Enu));
423  ee.Fill(volume.getX(Enu), volume.getX(Efit));
424  ea.Fill(Efit - Enu);
425  hzenith.Fill(Enu, zenith);
426 
427  herrorE.Fill(x, volume.getX(Efit) - volume.getX(Enu));
428  hfracE.Fill(x, abs(volume.getX(Efit) - volume.getX(Enu))/volume.getX(Enu));
429 
430  if(Enu >= 3 && Enu <= 5) ed3_5GeV.Fill(Efit - Enu);
431  else if(Enu >= 8 && Enu <= 11) ed8_11GeV.Fill(Efit - Enu);
432  else if(Enu >= 15 && Enu <= 21) ed15_21GeV.Fill(Efit - Enu);
433 
434  } else {
435 
436  e0.Fill(volume.getX(Elep, true));
437  er.Fill(volume.getX(Efit) - volume.getX(Elep));
438  ee.Fill(volume.getX(Elep), volume.getX(Efit));
439  ea.Fill(Efit - Elep);
440  hzenith.Fill(Elep, zenith);
441 
442  herrorE.Fill(x, volume.getX(Efit) - volume.getX(Elep));
443  hfracE.Fill(x, abs(volume.getX(Efit) - volume.getX(Elep))/volume.getX(Elep));
444 
445  if(Elep >= 3 && Elep <= 5) ed3_5GeV.Fill(Efit - Elep);
446  else if(Elep >= 8 && Elep <= 11) ed8_11GeV.Fill(Efit - Elep);
447  else if(Elep >= 15 && Elep <= 21) ed15_21GeV.Fill(Efit - Elep);
448 
449  }
450 
451  e2.Fill(volume.getX(Efit, true));
452 
453  h2.Fill(x, beta);
454  }
455  }
456  }
457 
458  he.Fill(x, W);}
459 
460  STATUS(endl);
461 
462  NOTICE("Number of events input " << setw(8) << right << job.GetBinContent(1) << endl);
463  if(!isMuon){
464  NOTICE("Number of events with electron " << setw(8) << right << job.GetBinContent(3) << endl);
465  } else{
466  NOTICE("Number of events with muon " << setw(8) << right << job.GetBinContent(3) << endl);
467  }
468  NOTICE("Number of events with fit " << setw(8) << right << job.GetBinContent(4) << endl);
469  NOTICE("Number of events selected " << setw(8) << right << job.GetBinContent(5) << endl);
470  NOTICE("Number of events with neutrino " << setw(8) << right << job.GetBinContent(6) << endl);
471  NOTICE("Number of events contained " << setw(8) << right << job.GetBinContent(7) << endl);
472 
473  if (Q.getCount() != 0 && application == JSHOWERFIT) {
474  NOTICE("Median space angle [deg] " << FIXED (6,3) << Q.getQuantile(0.5) << endl);
475  }
476 
477  out.Write();
478  out.Close();
479 }
bool is_electron(const Trk &track)
Test whether given track is a (anti-)electron.
Utility class to parse command line options.
Definition: JParser.hh:1493
General exception.
Definition: JException.hh:23
ROOT TTree parameter settings.
Auxiliary class to compare fit results with respect to a reference position (e.g. ...
Definition: JEvtToolkit.hh:683
double getAngle(const JFirst_t &first, const JSecond_t &second)
Get space angle between objects.
Auxiliary class to compare fit results with respect to a reference direction (e.g.
Definition: JEvtToolkit.hh:586
JTrack3E getTrack(const Trk &track)
Get track.
Synchronously read DAQ events and Monte Carlo events (and optionally other events).
double putTime() const
Get Monte Carlo minus DAQ/trigger hit time.
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Data structure for circle in two dimensions.
Definition: JCircle2D.hh:29
JTime & sub(const JTime &value)
Subtraction operator.
Quantile calculator.
Definition: JQuantile.hh:83
#define STATUS(A)
Definition: JMessage.hh:63
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
Template const_iterator.
Definition: JDAQEvent.hh:68
double getIntersection(const JVector3D &pos) const
Get longitudinal position along axis of position of closest approach with given position.
Definition: JAxis3D.hh:157
bool is_muon(const Trk &track)
Test whether given track is a (anti-)muon.
static const int JSHOWERPOINTSIMPLEX
General purpose sorter of fit results.
Definition: JEvtToolkit.hh:262
static const double PI
Constants.
Definition: JConstants.hh:20
Auxiliary class to synchronously read DAQ events and Monte Carlo events (and optionally other events)...
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:63
Double_t getX(const Double_t E, double constrain=false) const
Get abscissa value.
Definition: JVolume.hh:115
JCylinder3D & add(const JVector3D &pos)
Add position.
Definition: JCylinder3D.hh:146
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:481
string outputFile
double E
Energy [GeV] (either MC truth or reconstructed)
Definition: Trk.hh:18
static const int JSHOWERENERGYPREFIT
3D track with energy.
Definition: JTrack3E.hh:29
JVersor3D getDirection(const JVector3D &pos) const
Get photon direction of Cherenkov light on PMT.
Definition: JTrack3D.hh:147
double getQuantile(const double Q, const bool reverse=false) const
Get quantile.
Definition: JQuantile.hh:402
Double_t getXmin() const
Get minimal abscissa value.
Definition: JVolume.hh:91
JTime & add(const JTime &value)
Addition operator.
static const int JSHOWERPOSITIONFIT
Head getHeader(const JMultipleFileScanner_t &file_list)
Get Monte Carlo header.
Auxiliary class for defining the range of iterations of objects.
Definition: JLimit.hh:41
const_iterator< T > end() const
Get end of data.
static const int JSHOWERPREFIT
Constants.
Cylinder object.
Definition: JCylinder3D.hh:37
double getAngle(const JFit &fit) const
Get angle between reference direction and fit result.
Definition: JEvtToolkit.hh:635
Data structure for vector in three dimensions.
Definition: JVector3D.hh:33
const_iterator< T > begin() const
Get begin of data.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1954
static const JGeanz geanz(1.85, 0.62, 0.54)
Function object for longitudinal EM-shower profile.
Auxiliary class to test history.
Definition: JHistory.hh:104
static const int JSHOWERDIRECTIONPREFIT
double getTheta() const
Get theta angle.
Definition: JVersor3D.hh:125
#define NOTICE(A)
Definition: JMessage.hh:64
void put(const double x, const double w=1.0)
Put value.
Definition: JQuantile.hh:198
int debug
debug level
Definition: JSirene.cc:61
const JPosition3D & getPosition() const
Get position.
Definition: JPosition3D.hh:129
long long int getCount() const
Get total count.
Definition: JQuantile.hh:276
Reconstruction type dependent comparison of track quality.
Auxiliary class to evaluate atmospheric muon hypothesis.
Definition: JEvtToolkit.hh:772
double getT(const JVector3D &pos) const
Get arrival time of Cherenkov light at given position.
Definition: JTrack3D.hh:126
General purpose messaging.
counter_type advance(counter_type &counter, const counter_type value, const counter_type limit=std::numeric_limits< counter_type >::max())
Advance counter.
Monte Carlo run header.
Definition: JHead.hh:836
static const int JSHOWERCOMPLETEFIT
#define FATAL(A)
Definition: JMessage.hh:67
then for APP in event gandalf start energy
Definition: JMuonMCEvt.sh:42
Data structure for set of track fit results.
Definition: JEvt.hh:294
double getMaximum(const double E) const
Get depth of shower maximum.
Definition: JGeanz.hh:162
Utility class to parse command line options.
int getCount(const T &hit)
Get hit count.
JDirection3D getDirection(const Vec &v)
Get direction.
Auxiliary class to convert DAQ/trigger hit time to/from Monte Carlo hit time.
Data structure for position in three dimensions.
Definition: JPosition3D.hh:35
const JLimit & getLimit() const
Get limit.
Definition: JLimit.hh:73
Longitudinal emission profile EM-shower.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
The Trk class represents a Monte Carlo (MC) particle as well as a reconstructed track/shower.
Definition: Trk.hh:12
Double_t getXmax() const
Get maximal abscissa value.
Definition: JVolume.hh:102
Auxiliary class for histogramming of effective volume.
Definition: JVolume.hh:26
JVector3D & add(const JVector3D &vector)
Add vector.
Definition: JVector3D.hh:141
static const int JSHOWERFIT
Jpp shower reconstruction type.
The Evt class respresent a Monte Carlo (MC) event as well as an offline event.
Definition: Evt.hh:19
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
JPosition3D getPosition(const Vec &v)
Get position.
int main(int argc, char *argv[])
Definition: Main.cpp:15