Jpp 19.3.0-rc.3
the software that should make you happy
Loading...
Searching...
No Matches
JDomino.cc File Reference

Example program to verify Monte Carlo data. More...

#include <string>
#include <iostream>
#include <iomanip>
#include <map>
#include <sstream>
#include "TROOT.h"
#include "TFile.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TProfile.h"
#include "km3net-dataformat/offline/Head.hh"
#include "km3net-dataformat/offline/Evt.hh"
#include "JAAnet/JHead.hh"
#include "JAAnet/JHeadToolkit.hh"
#include "JAAnet/JAAnetToolkit.hh"
#include "JDetector/JDetector.hh"
#include "JDetector/JDetectorToolkit.hh"
#include "JDetector/JPMTRouter.hh"
#include "JGeometry3D/JCylinder3D.hh"
#include "JSupport/JMultipleFileScanner.hh"
#include "JSupport/JMonteCarloFileSupportkit.hh"
#include "JSupport/JSupport.hh"
#include "JROOT/JManager.hh"
#include "JGizmo/JGizmoToolkit.hh"
#include "JTools/JWeight.hh"
#include "JROOT/JRootToolkit.hh"
#include "JPhysics/JPDFToolkit.hh"
#include "JLang/JException.hh"
#include "JLang/JPredicate.hh"
#include "JLang/JLangToolkit.hh"
#include "Jeep/JPrint.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 verify Monte Carlo data.

Author
mdejong

Definition in file software/JSirene/JDomino.cc.

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 183 of file software/JSirene/JDomino.cc.

184{
185 using namespace std;
186 using namespace JPP;
187
188 //-------------------------------------------------------------------------
189 // command-line arguments
190 //-------------------------------------------------------------------------
191
193 JLimit_t& numberOfEvents = inputFile.getLimit();
194 string outputFile;
195 string detectorFile;
196 set<int> hit_types;
197 int debug;
198
199 try {
200
201 JParser<> zap("Example program to verify Monte Carlo data.");
202
203 zap['f'] = make_field(inputFile);
204 zap['n'] = make_field(numberOfEvents) = JLimit::max();
205 zap['o'] = make_field(outputFile) = "domino.root";
206 zap['a'] = make_field(detectorFile) = "";
207 zap['T'] = make_field(hit_types) = JPARSER::initialised();
208 zap['d'] = make_field(debug) = 2;
209
210 zap(argc, argv);
211 }
212 catch(const exception &error) {
213 FATAL(error.what() << endl);
214 }
215
216
217 //-------------------------------------------------------------------------
218 // load detector file
219 //-------------------------------------------------------------------------
220
222
223 if (detectorFile != "") {
224
225 try {
226 load(detectorFile, detector);
227 }
228 catch(const JException& error) {
229 FATAL(error);
230 }
231 }
232
233 const JPMTRouter router(detector);
234
235 const JHead header = getHeader(inputFile);
236
237
238 //-------------------------------------------------------------------------
239 // try to determine coordinate origin
240 //-------------------------------------------------------------------------
241
242 const Vec offset = getOffset(header);
243
244 NOTICE("Apply detector offset " << offset << endl);
245
246 detector -= getPosition(offset);
247
248
249 //-------------------------------------------------------------------------
250 // calculate instrumented volume
251 //-------------------------------------------------------------------------
252
253 JCylinder3D inst_vol(detector.begin(), detector.end());
254
255 NOTICE("JDomino: Instrumented volume dimensions (x, y, r, zmin, zmax): " << inst_vol << endl);
256
257
258 //-------------------------------------------------------------------------
259 // histogram binning
260 //-------------------------------------------------------------------------
261
263
264 double xmin = 2.0;
265 double xmax = 8.0;
266
267 // energy range is taken from -in order of priority- neutrino or muon data
268
269 if (header.is_valid(&JHead::cut_nu)) {
270 xmin = log10(header.cut_nu.E.getLowerLimit());
271 xmax = log10(header.cut_nu.E.getUpperLimit());
272 } else if (header.is_valid(&JHead::cut_in)) {
273 xmin = log10(header.cut_in.E.getLowerLimit());
274 xmax = log10(header.cut_in.E.getUpperLimit());
275 }
276 const int nx = (int) ((xmax - xmin) / 0.1);
277
278 const Double_t T[] = { -50.0, -20.0, -10.0, -5.0, -2.0, 0.0, +2.0, +5.0, +10.0, +15.0, +20.0, +30.0, +40.0, +50.0,
279 +75.0, +100.0, +150.0, +200.0, +250.0, +300.0, +400.0, +500.0, 1000.0 }; // [ns]
280
281 //-------------------------------------------------------------------------
282 // histograms for events
283 //-------------------------------------------------------------------------
284
285 TH1D hits("hits", NULL, 100, 0.0, 8.0); // number of mc_hits per event
286 TH1D trks("trks", NULL, 10001, -5000.5, 5000.5); // number of track_in type's per event
287 TH1D job ("job" , NULL, 10001, -5000.5, 5000.5); // number of photo-electrons by track_in type
288
289 TProfile hits_per_E_in ("hits_per_E_in", "average number of hits per E_{#nu} inside instrumented volume", nx, xmin, xmax);
290 TProfile hits_per_E_out("hits_per_E_out", "average number of hits per E_{#nu} outside instrumented volume", nx, xmin, xmax);
291
292 typedef JManager<int, TH1D> JManager_t;
293
294 JManager_t npe_per_type(new TH1D("npe[%]", NULL, 5000, 0.5, 5000.5), '%', ios::fmtflags(ios::showpos));
295
296 TH1D npe_per_pmt ("pmt", NULL, 100001, -0.5, 100000.5); // number of photo-electrons per PMT
297
298
299 //-------------------------------------------------------------------------
300 // histograms for neutrino
301 //-------------------------------------------------------------------------
302
303 TH2D nuExD("nuExD", NULL, nx, xmin, xmax, 100, 0.0, 1000.0); // Enu versus distance between vertex and PMT
304 TH2D* nuExD_tmp = (TH2D*) nuExD.Clone("nuExD.tmp"); // normalisation
305
306 TH2D nuExc("nuExc", NULL, nx, xmin, xmax, 100, -1.0, +1.0); // Enu versus emission angle
307 TH2D* nuExc_tmp = (TH2D*) nuExc.Clone("nuExc.tmp"); // normalisation
308
309 TH2D nuDxc("nuDxc", NULL, 50, 0.0, 1000.0, 100, -1.0, +1.0); // distance between vertex and PMT versus emission angle
310 TH2D* nuDxc_tmp = (TH2D*) nuDxc.Clone("nuDxc.tmp"); // normalisation
311
312 TH2D nuDxU("nuDxU", NULL, 50, 0.0, 1000.0, 100, -1.0, +1.0); // distance between vertex and PMT versus incidence angle
313 TH2D* nuDxU_tmp = (TH2D*) nuDxU.Clone("nuDxU.tmp"); // normalisation
314
315 TH2D nuDxT("nuDxT", NULL, 50, 0.0, 1000.0, getSize(T) - 1, T); // distance between vertex and PMT versus time residual
316 TH2D* nuDxT_tmp = (TH2D*) nuDxT.Clone("nuDxT.tmp"); // normalisation
317
318 nuExD.Sumw2();
319 nuExc.Sumw2();
320 nuDxc.Sumw2();
321 nuDxU.Sumw2();
322 nuDxT.Sumw2();
323
324
325 //-------------------------------------------------------------------------
326 // histograms for muon
327 //-------------------------------------------------------------------------
328
329 TH2D muExR("muExR", NULL, nx, xmin, xmax, 30, 0.0, 300.0); // Emu versus distance between muon and PMT
330 TH2D* muExR_tmp = (TH2D*) muExR.Clone("muExR.tmp"); // normalisation
331
332 TH2D muRxU("muRxU", NULL, 15, 0.0, 300.0, 100, -1.0, +1.0); // distance between muon and PMT versus incidence angle
333 TH2D* muRxU_tmp = (TH2D*) muRxU.Clone("muRxU.tmp"); // normalisation
334
335 TH2D muRxT("muRxT", NULL, 15, 0.0, 300.0, getSize(T) - 1, T); // distance between muon and PMT versus time residual
336 TH2D* muRxT_tmp = (TH2D*) muRxT.Clone("muRxT.tmp"); // normalisation
337
338 muExR.Sumw2();
339 muRxU.Sumw2();
340 muRxT.Sumw2();
341
342
343 //-------------------------------------------------------------------------
344 // loop over events
345 //-------------------------------------------------------------------------
346
347 while (inputFile.hasNext()) {
348
349 STATUS("event: " << setw(10) << inputFile.getCounter() << '\r'); DEBUG(endl);
350
351 const Evt* event = inputFile.next();
352
353 double NPE = 0.0;
354
355 for (vector<Hit>::const_iterator hit = event->mc_hits.begin(); hit != event->mc_hits.end(); ++hit) {
356 NPE += getNPE(*hit);
357 }
358
359 hits.Fill(log10((Double_t) event->mc_hits.size()));
360
361 for (vector<Trk>::const_iterator track = event->mc_trks.begin(); track != event->mc_trks.end(); ++track) {
362 trks.Fill(track->type);
363 }
364
365 JTrack3E neutrino;
366
367 if (has_neutrino(*event)) {
368 neutrino = getTrack(get_neutrino(*event));
369 }
370
371 const JVertex3D vertex = neutrino.getVertex();
372
373 map_type npe_pmt; // temporary buffer to accumulate total npe's by individual PMTs
374 map_type npe_type; // temporary buffer to accumulate total npe's by hit origin track
375
376
377 //-------------------------------------------------------------------------
378 // loop over hits
379 //-------------------------------------------------------------------------
380
381 for (vector<Hit>::const_iterator hit = event->mc_hits.begin(); hit != event->mc_hits.end(); ++hit) {
382
383 const int type = hit->type;
384 const double t1 = getTime(*hit);
385 const double npe = getNPE (*hit);
386
387 npe_pmt[hit->pmt_id].put(npe);
388
389 npe_type[0] .put(npe);
390 npe_type[type].put(npe);
391
392 if (hit_types.empty() || hit_types.count(type) != 0) {
393
394 vector<Trk>::const_iterator track = find_if(event->mc_trks.begin(),
395 event->mc_trks.end(),
396 make_predicate(&Trk::id, hit->origin));
397
398 if (track == event->mc_trks.end()) {
399 ERROR("Hit " << *hit << " has no origin." << endl);
400 continue;
401 }
402
403 if (count_if(event->mc_trks.begin(),
404 event->mc_trks.end(),
405 make_predicate(&Trk::id, hit->origin)) > 1) {
406 ERROR("Hit " << *hit << " has ambiguous origin." << endl);
407 continue;
408 }
409
410 job.Fill((double) track->type, npe);
411
412 if (router.hasPMT(hit->pmt_id)) {
413
414 const JPMT& pmt = router.getPMT(hit->pmt_id);
415
416 if (is_muon(*track)) {
417
418 const JTrack3E muon = getTrack(*track);
419
420 const double E = muon.getE();
421 const double x = log10(E);
422 const double R = muon.getDistance(pmt);
423 const double t0 = muon.getT (pmt);
424 const double ct1 = muon.getDot (pmt);
425
426 muExR.Fill(x, R, getMuonWeight(E, npe));
427 muRxU.Fill(R, ct1, getMuonWeight(E, R, npe));
428 muRxT.Fill(R, t1 - t0, getMuonWeight(E, R, npe));
429
430 } else if (has_neutrino(*event)) {
431
432 const double E = neutrino.getE();
433 const double x = log10(E);
434 const double D = vertex.getDistance(pmt);
435 const double t0 = vertex.getT(pmt);
436 const double ct0 = neutrino.getDot(pmt.getPosition());
437 const double ct1 = vertex.getDot(pmt);
438
439 nuExD.Fill(x, D, getNeutrinoWeight(E, npe));
440 nuExc.Fill(x, ct0, getNeutrinoWeight(E, npe));
441 nuDxc.Fill(D, ct0, getNeutrinoWeight(E, D, npe));
442 nuDxU.Fill(D, ct1, getNeutrinoWeight(E, D, npe));
443 nuDxT.Fill(D, t1 - t0, getNeutrinoWeight(E, D, npe));
444 }
445 }
446 } // end if PMT of hit found in PMT router
447 } // end loop over hits
448
449
450 //-------------------------------------------------------------------------
451 // continue with logic for event, fill histograms common to all input files
452 //-------------------------------------------------------------------------
453
454 for (map_type::const_iterator i = npe_pmt.begin(); i != npe_pmt.end(); ++i) {
455 npe_per_pmt.Fill(i->second.getTotal()); // npe / PMT
456 }
457
458 for (map_type::const_iterator i = npe_type.begin(); i != npe_type.end(); ++i) {
459 npe_per_type[i->first]->Fill(i->second.getTotal()); // npe / type
460 }
461
462
463 //-------------------------------------------------------------------------
464 // normalisation of muon histograms
465 //-------------------------------------------------------------------------
466
467 for (vector<Trk>::const_iterator track = event->mc_trks.begin(); track != event->mc_trks.end(); ++track) {
468
469 if (is_muon(*track)) {
470
471 const JTrack3E muon = getTrack(*track);
472
473 const double E = muon.getE();
474 const double x = log10(E);
475
476 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
477
478 const double R = muon.getDistance(*module);
479
480 muExR_tmp->Fill(x, R, module->size());
481
482 if (R < muRxU.GetXaxis()->GetXmax()) {
483 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
484 muRxU_tmp->Fill(R, muon.getDot(*pmt));
485 }
486 }
487
488 if (R < muRxT.GetXaxis()->GetXmax()) {
489 for (Int_t iy = 1; iy <= muRxT_tmp->GetYaxis()->GetNbins(); ++iy) {
490 muRxT_tmp->Fill(R, muRxT_tmp->GetYaxis()->GetBinCenter(iy), muRxT_tmp->GetYaxis()->GetBinWidth(iy));
491 }
492 }
493 }
494 }
495 }
496
497
498 //-------------------------------------------------------------------------
499 // normalisation of neutrino histograms
500 //-------------------------------------------------------------------------
501
502 if (has_neutrino(*event)) {
503
504 const double E = neutrino.getE();
505 const double x = log10(E);
506
507 if (inst_vol.is_inside(vertex))
508 hits_per_E_in .Fill(x, NPE);
509 else
510 hits_per_E_out.Fill(x, NPE);
511
512 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
513
514 const double D = vertex.getDistance(*module);
515 const double ct0 = neutrino.getDot(module->getPosition());
516
517 nuExD_tmp->Fill(x, D, module->size());
518 nuExc_tmp->Fill(x, ct0, module->size());
519 nuDxc_tmp->Fill(D, ct0, module->size());
520
521 if (D < nuDxU.GetXaxis()->GetXmax()) {
522 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
523 nuDxU_tmp->Fill(D, neutrino.getDot(*pmt));
524 }
525 }
526
527 if (D < nuDxT.GetXaxis()->GetXmax()) {
528 for (Int_t iy = 1; iy <= nuDxT_tmp->GetYaxis()->GetNbins(); ++iy) {
529 nuDxT_tmp->Fill(D, nuDxT_tmp->GetYaxis()->GetBinCenter(iy), nuDxT_tmp->GetYaxis()->GetBinWidth(iy));
530 }
531 }
532 }
533 }
534 } // end loop over events
535
536 STATUS(endl);
537
538
539 //-------------------------------------------------------------------------
540 // normalisation of histograms
541 //-------------------------------------------------------------------------
542
543 TH1D *job_sorted = makeSortedH1(&job, "hits_by_pdg"); // hits by track_in particles (PDG codes) per event, sorted
544 TH1D *trks_sorted = makeSortedH1(&trks, "trks_sorted"); // track_in particles (PDG codes) per event, sorted
545
546 if (inputFile.getCounter() != 0) {
547
548 const Double_t W = 1.0 / ((Double_t) inputFile.getCounter());
549
550 for (TH1D* p : { &hits, &npe_per_pmt, &job, &trks, job_sorted, trks_sorted }) {
551 p->Scale(W);
552 }
553
554 for (JManager_t::iterator i = npe_per_type.begin(); i != npe_per_type.end(); ++i) {
555 i->second->Scale(W);
556 }
557
558 nuExD.Divide(nuExD_tmp);
559 nuExc.Divide(nuExc_tmp);
560 nuDxc.Divide(nuDxc_tmp);
561 nuDxU.Divide(nuDxU_tmp);
562 nuDxT.Divide(nuDxT_tmp);
563
564 muExR.Divide(muExR_tmp);
565 muRxU.Divide(muRxU_tmp);
566 muRxT.Divide(muRxT_tmp);
567 }
568
569
570 //-------------------------------------------------------------------------
571 // output
572 //-------------------------------------------------------------------------
573
574 TFile out(outputFile.c_str(), "recreate");
575
576 out << hits << job << *job_sorted << trks << *trks_sorted << hits_per_E_in << hits_per_E_out << npe_per_type << npe_per_pmt;
577
578 out << nuExD << nuExc << nuDxc << nuDxU << nuDxT;
579 out << muExR << muRxU << muRxT;
580
581 out.Write();
582 out.Close();
583}
string outputFile
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
#define STATUS(A)
Definition JMessage.hh:63
#define NOTICE(A)
Definition JMessage.hh:64
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:72
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2142
Monte Carlo run header.
Definition JHead.hh:1236
JAANET::cut_in cut_in
Definition JHead.hh:1595
JAANET::cut_nu cut_nu
Definition JHead.hh:1596
bool is_valid(T JHead::*pd) const
Check validity of given data member in JHead.
Definition JHead.hh:1319
Detector data structure.
Definition JDetector.hh:96
Router for direct addressing of PMT data in detector data structure.
Definition JPMTRouter.hh:37
Data structure for PMT geometry, calibration and status.
Definition JPMT.hh:49
double getDistance(const JVector3D &pos) const
Get distance.
Definition JAxis3D.hh:213
const JPosition3D & getPosition() const
Get position.
double getDot(const JAxis3D &axis) const
Get cosine angle of impact of Cherenkov light on PMT.
Definition JTrack3D.hh:170
double getT(const JVector3D &pos) const
Get arrival time of Cherenkov light at given position.
Definition JTrack3D.hh:126
JVertex3D getVertex() const
Get vertex of this track.
Definition JTrack3D.hh:99
3D track with energy.
Definition JTrack3E.hh:32
double getE() const
Get energy.
Definition JTrack3E.hh:93
double getDistance(const JVector3D &pos) const
Get distance to point.
Definition JVector3D.hh:270
double getT(const JVector3D &pos) const
Get arrival time of Cherenkov light at given position.
Definition JVertex3D.hh:147
double getDot(const JAxis3D &axis) const
Get cosine angle of impact of Cherenkov light on PMT.
Definition JVertex3D.hh:177
General exception.
Definition JException.hh:24
Utility class to parse command line options.
Definition JParser.hh:1698
Auxiliary class to manage set of compatible ROOT objects (e.g. histograms) using unique keys.
Definition JManager.hh:47
General purpose class for object reading from a list of file names.
virtual bool hasNext() override
Check availability of next element.
counter_type getCounter() const
Get counter.
virtual const pointer_type & next() override
Get next element.
T getLowerLimit() const
Get lower limit.
Definition JRange.hh:202
T getUpperLimit() const
Get upper limit.
Definition JRange.hh:213
const double xmax
const double xmin
JTrack3E getTrack(const Trk &track)
Get track.
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
JPosition3D getPosition(const Vec &pos)
Get position.
bool is_muon(const Trk &track)
Test whether given track is a (anti-)muon.
double getNPE(const Hit &hit)
Get true charge of hit.
Vec getOffset(const JHead &header)
Get offset.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
size_t getSize(T(&array)[N])
Get size of c-array.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Head getHeader(const JMultipleFileScanner_t &file_list)
Get Monte Carlo header.
const char * getTime()
Get current local time conform ISO-8601 standard.
std::map< int, range_type > map_type
The Evt class respresent a Monte Carlo (MC) event as well as an offline event.
Definition Evt.hh:21
JRange_t E
Energy range [GeV].
Definition JHead.hh:419
Detector file.
Definition JHead.hh:227
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition JParser.hh:68
Auxiliary class for defining the range of iterations of objects.
Definition JLimit.hh:45
static counter_type max()
Get maximum counter value.
Definition JLimit.hh:128
int id
track identifier
Definition Trk.hh:16
The Vec class is a straightforward 3-d vector, which also works in pyroot.
Definition Vec.hh:13