Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JVolume1D.cc
Go to the documentation of this file.
1 
2 #include <string>
3 #include <iostream>
4 
5 #include "TROOT.h"
6 #include "TFile.h"
7 #include "TH1D.h"
8 
9 #include "evt/Head.hh"
10 #include "evt/Evt.hh"
11 #include "evt/Vec.hh"
12 #include "JDAQ/JDAQEvent.hh"
13 #include "JAAnet/JAAnetToolkit.hh"
14 #include "JGizmo/JVolume.hh"
17 
20 #include "JSupport/JSupport.hh"
21 
22 #include "JDetector/JDetector.hh"
24 
25 #include "Jeep/JParser.hh"
26 #include "Jeep/JMessage.hh"
27 
28 
29 namespace {
30 
31  using namespace JPP;
32 
33  /**
34  * Test event from genie/gSeaGen simulation.
35  *
36  * The function checks that the vertex of the neutrino event is inside the can volume.
37  *
38  * \param cylinder cylinder
39  * \param event event
40  * \return true if accepted; else false
41  */
42  inline bool test_event(const JCylinder3D& cylinder, const Evt& event) {
43 
44  using namespace std;
45  using namespace JPP;
46 
47  Bool_t accepted = true;
48 
49  if ( has_neutrino(event) ) {
50  accepted = accepted && cylinder.is_inside( getPosition( get_neutrino(event) ) );
51  }
52  else {
53 
54  // future/further logic for atm_muon events here, if any
55 
56  accepted = false;
57  }
58 
59  return accepted;
60  }
61 
62  /** Function to infer the coordinate origin from the header.
63 
64  This bulky logic exists because historically gSeaGen and Jpp have used different coordinate systems. For gSeaGen files the coordinate origin can be syncronised to Jpp, which is performed here.
65 
66  \param header - MC simulation file header
67  \return Coordinate origin in the simulation
68  */
69  inline Vec get_coord_origin(const JHead &header) {
70 
71  Vec coord_origin(0, 0, 0);
72 
73  if ( is_valid(header.coord_origin) ) {
74 
75  coord_origin = header.coord_origin;
76 
77  // using NOTICE here gives a linker error...
78  cout << "JVolume1D::get_coord_origin() Coordinate origin (x, y, z) " << coord_origin << " read from header" << endl;
79 
80  }
81 
82  else if ( is_valid(header.can) ) {
83 
84  if (header.can.zmin < 0) coord_origin.z = -header.can.zmin;
85 
86  cout << "JVolume1D::get_coord_origin() Coordinate origin (x, y, z) " << coord_origin << " calculated from can dimensions (zmin, zmax, r) " << header.can.zmin << " " << header.can.zmax << " " << header.can.r << endl;
87 
88  }
89 
90  else {
91  FATAL("JVolume1D::get_coord_origin() Error in determining the coordinate origin.");
92  }
93 
94  return coord_origin;
95 
96  }
97 
98 }
99 
100 /**
101  * \file
102  *
103  * Example program to histogram neutrino effective volume for triggered events. For genie/gSeaGen events a histogram depicting the fraction of events that triggered the detector inside the instrumented volume is also shown.
104  * The unit of the contents of the histogram is \f$km^{3}\f$.
105  * \author mdejong, bstrandberg
106  */
107 int main(int argc, char **argv)
108 {
109  using namespace std;
110  using namespace JPP;
111  using namespace KM3NETDAQ;
112 
113  //------------------------------------------------------------------------------
114  // parse command line arguments, check that header can be found in the input file
115  //------------------------------------------------------------------------------
116 
117  JTriggeredFileScanner<> inputFile;
118  string outputFile;
119  JLimit& numberOfEvents = inputFile.getLimit();
120  double wall;
121  bool logx;
122  int numberOfBins;
123  int debug;
124  string detectorFile;
125 
126 
127  try {
128 
129  JParser<> zap("Example program to histogram neutrino effective volume for triggered events. For genie/gSeaGen events a histogram depicting the fraction of events that triggered the detector inside the instrumented volume is also shown.");
130 
131  zap['f'] = make_field(inputFile);
132  zap['o'] = make_field(outputFile) = "volume.root";
133  zap['n'] = make_field(numberOfEvents) = JLimit::max();
134  zap['R'] = make_field(wall, "Addition margin around the volume in which the considered events must reside") = 0.0;
135  zap['X'] = make_field(logx, "Use logarithm of energy");
136  zap['N'] = make_field(numberOfBins, "Number of bins in the energy range of the MC simulation") = 10;
137  zap['d'] = make_field(debug) = 1;
138  zap['a'] = make_field(detectorFile, "Detector file: if not provided, trigger fraction is not calculated") = "";
139 
140  zap(argc, argv);
141  }
142  catch(const exception &error) {
143  FATAL(error.what() << endl);
144  }
145 
146  //-------------------------------------------------------------------------
147  // deal with the header and init the detector
148  //-------------------------------------------------------------------------
149 
150  Head head;
151 
152  try {
153  head = getHeader(inputFile);
154  }
155  catch(const JException& error) {
156  FATAL(error);
157  }
158 
160 
161  if (detectorFile != "") {
162 
163  try {
164  load(detectorFile, detector);
165  }
166  catch(const JException& error) {
167  FATAL(error);
168  }
169  }
170 
171  //------------------------------------------------------------------------------
172  // create the can volume from the dimensions stored in the header and instrumented volume from detector file
173  //------------------------------------------------------------------------------
174 
175  const JHead buffer(head);
176 
177  const bool genie = is_genie(buffer);
178 
179  // the can volume comes from the generator header and the coordinate system is consistent by construction
180  const JVolume volume(head, logx);
181  JCylinder3D canvol = get<JCylinder3D>(buffer);
182  canvol.addMargin(wall);
183 
184  // as the detector is constructed from Jpp detector file, the coordinate system needs to be synced
185  // to the one used in the event generator
186  detector -= JAANET::getPosition( get_coord_origin(buffer) );
187  JCylinder3D instvol( detector.begin(), detector.end() );
188  instvol.addMargin(wall);
189 
190  NOTICE("JVolume1D: Instrumented volume dimensions (zmin, zmax, r): " << instvol.getZmin() << " " << instvol.getZmax() << " " << instvol.getRadius() << endl );
191 
192  //------------------------------------------------------------------------------
193  // initialise output
194  //------------------------------------------------------------------------------
195 
196  TFile out(outputFile.c_str(), "recreate");
197 
198  TH1D hV("hV", "effective volume in km^3" , numberOfBins, volume.getXmin(), volume.getXmax());
199  TH1D hF("hF", "n_trig/n_gen in instrumented volume", numberOfBins, volume.getXmin(), volume.getXmax());
200  hV.Sumw2();
201  hF.Sumw2();
202 
203  //------------------------------------------------------------------------------
204  // loop over triggered events in the input file
205  //------------------------------------------------------------------------------
206 
207  NOTICE("JVolume1D: Scanning triggered events." << endl);
208  while (inputFile.hasNext()) {
209 
210  STATUS("event: " << setw(10) << inputFile.getCounter() << '\r'); DEBUG(endl);
211 
212  JTriggeredFileScanner<>::multi_pointer_type ps = inputFile.next();
213 
214  const Evt* event = ps;
215 
216  if (has_neutrino(*event)) {
217 
218  const Trk& neutrino = get_neutrino(*event);
219  const double E = neutrino.E;
220 
221  // genie/gSeaGen events filled with weight 1, histograms normalised after the second loop below
222  if ( genie ) {
223 
224  // events are filled to hV if they are inside the can
225  hV.Fill(volume.getX(E), test_event(canvol, *event) ? 1.0 : 0.0);
226 
227  // events are filled to hF if they are inside the instrumented volume
228  hF.Fill(volume.getX(E), test_event(instvol, *event) ? 1.0 : 0.0);
229 
230  }
231  // for other simulated events effective volume calculated from event weights, normalisation not required
232  else {
233  hV.Fill(volume.getX(E), volume.getW(hV.GetXaxis(), E));
234  }
235 
236  }
237  else {
238  WARNING("JVolume1D: cannot find neutrino in triggered event " << inputFile.getCounter() );
239  }
240 
241  } // end loop over triggered events
242  STATUS(endl);
243 
244  //------------------------------------------------------------------------------
245  // loop over generated events in the input file; FATAL if generator events have not been stored
246  //------------------------------------------------------------------------------
247 
248  if ( genie ) {
249 
250  // this histogram counts the generated events inside the can volume
251  TH1D* hNV = (TH1D*) hV.Clone("hNV");
252  hNV->Reset();
253 
254  // this histogram counts the generated events inside the instrumented volume
255  TH1D* hNF = (TH1D*) hF.Clone("hNF");
256  hNF->Reset();
257 
258  NOTICE("JVolume1D: Scanning generated events." << endl);
259 
260  JMultipleFileScanner<Evt> in(inputFile);
261 
262  while ( in.hasNext() ) {
263 
264  STATUS("event: " << setw(10) << in.getCounter() << '\r'); DEBUG(endl);
265 
266  const Evt* event = in.next();
267 
268  if (has_neutrino(*event)) {
269 
270  const Trk& neutrino = get_neutrino(*event);
271  const double E = neutrino.E;
272 
273  hNV->Fill(volume.getX(E), test_event(canvol, *event) ? 1.0 : 0.0);
274  hNF->Fill(volume.getX(E), test_event(instvol, *event) ? 1.0 : 0.0);
275 
276  }
277  else {
278  WARNING("JVolume1D: cannot find neutrino in generated event " << inputFile.getCounter() );
279  }
280 
281  }
282  STATUS(endl);
283 
284  if ( in.getCounter() == 0 ) {
285  FATAL("JVolume1D: generated events not stored in the input file, JTriggerEfficiency should be run without option -O");
286  }
287 
288  //------------------------------------------------------------------------------
289  // convert 'generated' and 'triggered' histograms to effective volume and trigger fraction
290  //------------------------------------------------------------------------------
291 
292  hV.Divide(hNV);
293  hV.Scale(canvol.getVolume()*1e-9); // km^3
294  hF.Divide(hNF);
295 
296  delete hNV;
297  delete hNF;
298 
299  }
300 
301  out.Write();
302  out.Close();
303 
304 }
double zmin
Bottom [m].
Definition: JHead.hh:352
Utility class to parse command line options.
Definition: JParser.hh:1410
General exception.
Definition: JException.hh:40
virtual const pointer_type & next()
Get next element.
#define WARNING(A)
Definition: JMessage.hh:63
Synchronously read DAQ events and Monte Carlo events (and optionally other events).
#define STATUS(A)
Definition: JMessage.hh:61
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
Detector data structure.
Definition: JDetector.hh:77
Auxiliary class to synchronously read DAQ events and Monte Carlo events (and optionally other events)...
Structure to store the ToT mean and standard deviation of the hits produced by a nanobeacon in a sour...
static counter_type max()
Get maximum counter value.
Definition: JLimit.hh:116
Double_t getX(const Double_t E, double constrain=false) const
Get abscissa value.
Definition: JVolume.hh:115
string outputFile
Data structure for detector geometry and calibration.
Coordinate origin.
Definition: JHead.hh:432
Double_t getXmin() const
Get minimal abscissa value.
Definition: JVolume.hh:91
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
JAANET::can can
Definition: JHead.hh:863
Cylinder object.
Definition: JCylinder3D.hh:37
Detector file.
Definition: JHead.hh:126
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1836
Definition of hit and track types and auxiliary methods for handling Monte Carlo data.
#define NOTICE(A)
Definition: JMessage.hh:62
void addMargin(const double D)
Add (safety) margin.
Definition: JCylinder3D.hh:163
void load(const JString &file_name, JDetector &detector)
Load detector from input file.
int debug
debug level
Definition: JSirene.cc:59
Double_t getW(TAxis *axis, const Double_t E) const
Get bin width corrected energy spectrum dependent weight.
Definition: JVolume.hh:161
General purpose messaging.
Monte Carlo run header.
Definition: JHead.hh:727
#define FATAL(A)
Definition: JMessage.hh:65
double r
Radius [m].
Definition: JHead.hh:354
virtual bool hasNext()
Check availability of next element.
General purpose class for object reading from a list of file names.
Utility class to parse command line options.
ROOT TTree parameter settings.
bool is_inside(const JVector3D &pos) const
Check whether given point is inside cylinder.
Definition: JCylinder3D.hh:199
counter_type getCounter() const
Get counter.
const JLimit & getLimit() const
Get limit.
Definition: JLimit.hh:72
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
JAANET::coord_origin coord_origin
Definition: JHead.hh:865
General purpose class for multiple pointers.
Double_t getXmax() const
Get maximal abscissa value.
Definition: JVolume.hh:102
bool is_valid(const T &value)
Check validity of given value.
Definition: JHead.hh:711
Auxiliary class for histogramming of effective volume.
Definition: JVolume.hh:26
bool is_genie(const JHead &header)
Check for generator.
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:60
double zmax
Top [m].
Definition: JHead.hh:353
JPosition3D getPosition(const Vec &v)
Get position.
int main(int argc, char *argv[])
Definition: Main.cpp:15