Jpp  18.5.2
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Functions
JShowerPostfit.cc File Reference

Example program to histogram shower fit results: it handles both neutrino and muon productions. More...

#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
#include <set>
#include "TROOT.h"
#include "TFile.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TProfile.h"
#include "TMath.h"
#include "km3net-dataformat/offline/Head.hh"
#include "km3net-dataformat/offline/Evt.hh"
#include "km3net-dataformat/online/JDAQModuleIdentifier.hh"
#include "km3net-dataformat/definitions/reconstruction.hh"
#include "km3net-dataformat/definitions/fitparameters.hh"
#include "km3net-dataformat/tools/time_converter.hh"
#include "JAAnet/JHead.hh"
#include "JAAnet/JHeadToolkit.hh"
#include "JAAnet/JAAnetToolkit.hh"
#include "JAAnet/JVolume.hh"
#include "JDAQ/JDAQEventIO.hh"
#include "JPhysics/JConstants.hh"
#include "JTools/JQuantile.hh"
#include "JSupport/JTriggeredFileScanner.hh"
#include "JSupport/JMonteCarloFileSupportkit.hh"
#include "JSupport/JSupport.hh"
#include "JReconstruction/JEvt.hh"
#include "JReconstruction/JEvtToolkit.hh"
#include "JLang/JPredicate.hh"
#include "JPhysics/JGeanz.hh"
#include "JGeometry3D/JShower3E.hh"
#include "JGeometry3D/JCylinder3D.hh"
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Detailed Description

Example program to histogram shower fit results: it handles both neutrino and muon productions.

Author
mdejong, adomi

Definition in file JShowerPostfit.cc.

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 79 of file JShowerPostfit.cc.

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 
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  TH2D hY("hY", "Reco Bjorken Y vs MC Bjorken Y", 40, 0, 1, 40, 0, 1);
211  TH2D hby3_5GeV("hby3_5GeV", "Reco Bjorken Y vs MC Bjorken Y for events with Reco E #in [3, 5] GeV", 40, 0, 1, 40, 0, 1);
212  TH2D hby8_10GeV("hby8_10GeV", "Reco Bjorken Y vs MC Bjorken Y for events with Reco E #in [8, 10] GeV", 40, 0, 1, 40, 0, 1);
213 
214  JQuantile Q("Angle", true);
215  JQuantile O("Omega", true);
216 
217 
218  while (inputFile.hasNext()) {
219 
220  STATUS("event: " << setw(10) << inputFile.getCounter() << '\r'); DEBUG(endl);
221 
222  multi_pointer_type ps = inputFile.next();
223 
224  JDAQEvent* tev = ps;
225  JEvt* evt = ps; // Reco event
226  Evt* event = ps; // MC event
227 
228  const time_converter converter(*event, *tev);
229 
230  job.Fill(1.0);
231 
232  double Enu = 0.0;
233  double Elep = 0.0;
234  double Emax = 0.0;
235 
236  Trk neutrino;
237 
238  if(has_neutrino(*event)){
239 
240  neutrino = get_neutrino(*event);
241  Enu = neutrino.E;
242 
243  }
244 
245  vector<Trk>::const_iterator lepton = event->mc_trks.end(); // can be electron or muon
246 
247  for (vector<Trk>::const_iterator mc_evt = event->mc_trks.begin(); mc_evt != event->mc_trks.end(); ++mc_evt) {
248 
249  if (!isMuon && is_electron(*mc_evt)) {
250 
251  Elep += mc_evt->E;
252 
253  if (mc_evt->E > Emax) {
254  lepton = mc_evt;
255  Emax = mc_evt->E;
256  }
257 
258 
259  } else if(isMuon && is_muon(*mc_evt)){
260 
261  Elep += mc_evt->E;
262  if (mc_evt->E > Emax) {
263  lepton = mc_evt;
264  Emax = mc_evt->E;
265  }
266  }
267  }
268 
269  if (lepton == event->mc_trks.end()) {
270  continue;
271  }
272 
273  job.Fill(3.0);
274 
275  double true_BjY = (Enu - Elep) / Enu;
276 
277  // abscissa
278 
279  Double_t x = 0.0;
280 
281  if (option.find('E') != string::npos){
282 
283  if(wrtNeutrino == true && !isMuon) x = volume.getX(neutrino.E);
284  else if(!wrtNeutrino && !isMuon) x = volume.getX(lepton->E);
285 
286  } else{
287  x = getCount(tev->begin<JDAQTriggeredHit>(), tev->end<JDAQTriggeredHit>());
288  }
289 
290  // weight for efficiency determination
291  Double_t W = 0.0;
292 
293  if (!evt->empty()) {
294 
295  JEvt::iterator __end = partition(evt->begin(), evt->end(), JHistory::is_event(application));
296 
297  if (evt->begin() == __end) {
298  continue;
299  }
300 
301  job.Fill(4.0);
302 
303  //if (numberOfPrefits > 0 && numberOfPrefits < (size_t) distance(evt->begin(), evt->end())) {
304  if (numberOfPrefits > 0 ) {
305 
306  JEvt::iterator __q = __end;
307 
308  advance(__end = evt->begin(), min(numberOfPrefits, (size_t) distance(evt->begin(), __q)));
309 
310  partial_sort(evt->begin(), __end, __q, quality_sorter);
311 
312  } else {
313 
314  sort(evt->begin(), __end, quality_sorter);
315  }
316 
317  JEvt::iterator best = evt->begin(); // the best shower is the one with the best quality
318 
319  JPosition position(getPosition(lepton->pos)); // by default the lepton pos is the interaction vertex
320  JPointing pointing(getDirection(*lepton));
321  JShowerEnergy energy(lepton->E);
322 
323  JVector3D showerBrightPoint(getPosition(lepton->pos) + center + getPosition(lepton->dir) * geanz.getMaximum(lepton->E));
324 
325  if(!wrtNeutrino && !isMuon){
326  position = JPosition(showerBrightPoint); // wrt the em shower brightest point
327  } else if(wrtNeutrino == true && !isMuon){
328  position = JPosition(getPosition(neutrino));
329  pointing = JPointing(getDirection(neutrino));
330  energy = JShowerEnergy(Enu);
331  }
332 
333  JEvt::iterator fit_with_smallest_error = best;
334 
335  if(application == JSHOWERPREFIT || application == JSHOWERPOINTSIMPLEX || application == JSHOWERPOSITIONFIT){
336  fit_with_smallest_error = position(evt->begin(), __end);
337  } else if (application == JSHOWERENERGYPREFIT){
338  fit_with_smallest_error = energy(evt->begin(), __end);
339  } else {
340  fit_with_smallest_error = pointing(evt->begin(), __end);
341  }
342 
343  const Double_t beta = pointing.getAngle(*best);
344  const double Efit = best->getE();
345 
346  JCylinder3D containment(JCircle2D(getPosition(*best), radius), height.getLowerLimit(), height.getUpperLimit());
347 
348  if(containment.is_inside(getPosition(*best))){
349 
350  // selection of fit result
351  bool ok = (Efit >= Emin_GeV);
352 
353  if (ok) {
354 
355  W = 1.0;
356 
357  job.Fill(5.0);
358 
359  hn.Fill((Double_t) best->getNDF());
360  hq.Fill(best->getQ());
361  hi.Fill((Double_t) distance(evt->begin(), fit_with_smallest_error));
362 
363  Q.put(beta);
364 
365  JShower3E ta;
366 
367  if(wrtNeutrino){
368  ta = getTrack(neutrino);
369  } else {
370  ta = getTrack(*lepton); // MC event
371  }
372 
373  JShower3E tb = getTrack(*best); // Reco event
374 
375  double zenith = tb.getDirection().getTheta() * 180 / PI;
376 
377  // take into account the difefrent MC/Reco geometry and time
378  ta.add(center);
379  tb.sub(converter.putTime());
380 
381  if(!isMuon && !wrtNeutrino){
382 
383  double distance_m = (tb.getPosition() - JPosition3D(showerBrightPoint)).getLength();
384 
385  hd.Fill(distance_m * distance_m);
386 
387  } else {
388 
389  double distance_m = (tb.getPosition() - ta.getPosition()).getLength();
390 
391  hd.Fill(distance_m * distance_m);
392 
393  }
394 
395  if (has_neutrino(*event)) {
396 
397  job.Fill(6.0);
398 
399  JPosition3D mc_vx = getPosition(neutrino); // mc vertex
400 
401  mc_vx.add(center);
402 
403  if (cylinder.is_inside(mc_vx)) {
404 
405  job.Fill(7.0);
406 
407  hz.Fill(tb.getIntersection(mc_vx));
408  }
409  }
410 
411  if (best->getE() >= EMIN_GEV) {
412  hb.Fill(best->getX()*best->getX() + best->getY()*best->getY(), best->getZ());
413  }
414 
415  ht.Fill(tb.getT() - ta.getT());
416 
417  ha.Fill(getAngle(ta.getDirection(), tb.getDirection()));
418 
419  htheta_nu_lep.Fill(x, getAngle(getDirection(neutrino), getDirection(*lepton)));
420  hmca.Fill(x, getAngle(ta.getDirection(), tb.getDirection()));
421 
422  if(application == JSHOWER_BJORKEN_Y) {
423 
424  hY.Fill(true_BjY, best->getW(5));
425 
426  if(Efit > 2.5 && Efit < 6) hby3_5GeV.Fill(true_BjY, best->getW(5));
427  else if(Efit > 7.5 && Efit < 11) hby8_10GeV.Fill(true_BjY, best->getW(5));
428 
429  }
430  if(wrtNeutrino){
431 
432  e0.Fill(volume.getX(Enu, true));
433  er.Fill(volume.getX(Efit) - volume.getX(Enu));
434  ee.Fill(volume.getX(Enu), volume.getX(Efit));
435  ea.Fill(Efit - Enu);
436  hzenith.Fill(Enu, zenith);
437 
438  herrorE.Fill(x, volume.getX(Efit) - volume.getX(Enu));
439  hfracE.Fill(x, fabs(volume.getX(Efit) - volume.getX(Enu))/volume.getX(Enu));
440 
441  if(Enu >= 3 && Enu <= 5) ed3_5GeV.Fill(Efit - Enu);
442  else if(Enu >= 8 && Enu <= 11) ed8_11GeV.Fill(Efit - Enu);
443  else if(Enu >= 15 && Enu <= 21) ed15_21GeV.Fill(Efit - Enu);
444 
445  } else {
446 
447  e0.Fill(volume.getX(Elep, true));
448  er.Fill(volume.getX(Efit) - volume.getX(Elep));
449  ee.Fill(volume.getX(Elep), volume.getX(Efit));
450  ea.Fill(Efit - Elep);
451  hzenith.Fill(Elep, zenith);
452 
453  herrorE.Fill(x, volume.getX(Efit) - volume.getX(Elep));
454  hfracE.Fill(x, fabs(volume.getX(Efit) - volume.getX(Elep))/volume.getX(Elep));
455 
456  if(Elep >= 3 && Elep <= 5) ed3_5GeV.Fill(Efit - Elep);
457  else if(Elep >= 8 && Elep <= 11) ed8_11GeV.Fill(Efit - Elep);
458  else if(Elep >= 15 && Elep <= 21) ed15_21GeV.Fill(Efit - Elep);
459 
460  }
461 
462  e2.Fill(volume.getX(Efit, true));
463 
464  h2.Fill(x, beta);
465  }
466  }
467  }
468 
469  he.Fill(x, W);}
470 
471  STATUS(endl);
472 
473  NOTICE("Number of events input " << setw(8) << right << job.GetBinContent(1) << endl);
474  if(!isMuon){
475  NOTICE("Number of events with electron " << setw(8) << right << job.GetBinContent(3) << endl);
476  } else{
477  NOTICE("Number of events with muon " << setw(8) << right << job.GetBinContent(3) << endl);
478  }
479  NOTICE("Number of events with fit " << setw(8) << right << job.GetBinContent(4) << endl);
480  NOTICE("Number of events selected " << setw(8) << right << job.GetBinContent(5) << endl);
481  NOTICE("Number of events with neutrino " << setw(8) << right << job.GetBinContent(6) << endl);
482  NOTICE("Number of events contained " << setw(8) << right << job.GetBinContent(7) << endl);
483 
484  if (Q.getCount() != 0) {
485  NOTICE("Median space angle [deg] " << FIXED (6,3) << Q.getQuantile(0.5) << endl);
486  }
487 
488  out.Write();
489  out.Close();
490 }
bool is_electron(const Trk &track)
Test whether given track is a (anti-)electron.
Utility class to parse command line options.
Definition: JParser.hh:1514
double getAngle(const JQuaternion3D &first, const JQuaternion3D &second)
Get space angle between quanternions.
General exception.
Definition: JException.hh:24
Q(UTCMax_s-UTCMin_s)-livetime_s
Auxiliary class to compare fit results with respect to a reference position (e.g. true muon)...
Auxiliary class to compare fit results with respect to a reference direction (e.g. true muon).
JTrack3E getTrack(const Trk &track)
Get track.
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:33
JTime & sub(const JTime &value)
Subtraction operator.
#define STATUS(A)
Definition: JMessage.hh:63
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
double getIntersection(const JVector3D &pos) const
Get longitudinal position along axis of position of closest approach with given position.
Definition: JAxis3D.hh:146
bool is_muon(const Trk &track)
Test whether given track is a (anti-)muon.
static const int JSHOWERPOINTSIMPLEX
General purpose sorter of fit results.
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:83
Auxiliary class to convert DAQ hit time to/from Monte Carlo hit time.
JCylinder3D & add(const JVector3D &pos)
Add position.
Definition: JCylinder3D.hh:156
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:446
string outputFile
double E
Energy [GeV] (either MC truth or reconstructed)
Definition: Trk.hh:20
static const int JSHOWERENERGYPREFIT
3D track with energy.
Definition: JTrack3E.hh:30
JVersor3D getDirection(const JVector3D &pos) const
Get photon direction of Cherenkov light on PMT.
Definition: JTrack3D.hh:147
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 histogramming of effective volume.
Definition: JVolume.hh:29
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
Cylinder object.
Definition: JCylinder3D.hh:39
JDirection3D getDirection(const Vec &dir)
Get direction.
Data structure for vector in three dimensions.
Definition: JVector3D.hh:34
Acoustic event fit.
Monte Carlo run header.
Definition: JHead.hh:1234
const_iterator< T > begin() const
Get begin of data.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1989
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:105
static const int JSHOWERDIRECTIONPREFIT
double getTheta() const
Get theta angle.
Definition: JVersor3D.hh:128
JPosition3D getPosition(const Vec &pos)
Get position.
#define NOTICE(A)
Definition: JMessage.hh:64
static const double PI
Mathematical constants.
static const int JSHOWER_BJORKEN_Y
const JPosition3D & getPosition() const
Get position.
Definition: JPosition3D.hh:130
Reconstruction type dependent comparison of track quality.
Auxiliary class to evaluate atmospheric muon hypothesis.
double getT(const JVector3D &pos) const
Get arrival time of Cherenkov light at given position.
Definition: JTrack3D.hh:126
counter_type advance(counter_type &counter, const counter_type value, const counter_type limit=std::numeric_limits< counter_type >::max())
Advance counter.
static const int JSHOWERCOMPLETEFIT
#define FATAL(A)
Definition: JMessage.hh:67
then for APP in event gandalf start energy
Definition: JMuonMCEvt.sh:44
Auxiliary data structure for average.
Definition: JKatoomba_t.hh:76
double getMaximum(const double E) const
Get depth of shower maximum.
Definition: JGeanz.hh:162
int getCount(const T &hit)
Get hit count.
no fit printf nominal n $STRING awk v X
Data structure for position in three dimensions.
Definition: JPosition3D.hh:36
const JLimit & getLimit() const
Get limit.
Definition: JLimit.hh:84
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:14
JVector3D & add(const JVector3D &vector)
Add vector.
Definition: JVector3D.hh:142
int debug
debug level
The Evt class respresent a Monte Carlo (MC) event as well as an offline event.
Definition: Evt.hh:20
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62