14 #include "evt/Head.hh"
54 inline double getMuonWeight(
const double E,
71 inline double getMuonWeight(
const double E,
79 return R * exp(+R/l_att) * getMuonWeight(E, npe);
90 inline double getNeutrinoWeight(
const double E,
105 inline double getNeutrinoWeight(
const double E,
109 static const double l_att = 45.0;
111 return D*D * exp(+D/l_att) * getNeutrinoWeight(E, npe);
126 return first.second > second.second;
137 inline TH1D* makeSortedH1(TH1D* in,
const TString& name)
146 for (Int_t ix = 1; ix <= in->GetXaxis()->GetNbins(); ++ix) {
148 const Int_t x = (Int_t) in->GetXaxis()->GetBinCenter(ix);
149 const Double_t y = in->GetBinContent(ix);
152 data.push_back(make_pair(x, y));
158 sort(data.begin(), data.end(), compare);
162 TH1D* out =
new TH1D(name, NULL, data.size(), -0.5, data.size() - 0.5);
164 for (Int_t i = 0; i < (Int_t) data.size(); i++) {
166 const Int_t ix = i + 1;
168 out->GetXaxis()->SetBinLabel(ix,
MAKE_CSTRING(fixed << setprecision(0) << data[i].first));
169 out->SetBinContent(ix, data[i].second);
183 int main(
int argc,
char **argv)
192 JMultipleFileScanner<Evt> inputFile;
201 JParser<> zap(
"Example program to verify Monte Carlo data.");
204 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
212 catch(
const exception &error) {
213 FATAL(error.what() << endl);
225 if (detectorFile !=
"") {
228 load(detectorFile, detector);
230 catch(
const JException& error) {
235 const JPMTRouter router(detector);
244 JPosition3D center = get<JPosition3D>(header);
246 NOTICE(
"Apply detector offset " << center << endl);
255 JCylinder3D inst_vol(detector.begin(), detector.end());
257 NOTICE(
"JDomino: Instrumented volume dimensions (x, y, r, zmin, zmax): " << inst_vol << endl);
266 const double xmin = log10(header.cut_nu.Emin);
267 const double xmax = log10(header.cut_nu.Emax);
268 const int nx = (int) ((xmax - xmin) / 0.1);
270 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,
271 +75.0, +100.0, +150.0, +200.0, +250.0, +300.0, +400.0, +500.0, 1000.0 };
277 TH1D hits(
"hits", NULL, 100, 0.0, 8.0);
278 TH1D trks(
"trks", NULL, 10001, -5000.5, 5000.5);
279 TH1D job (
"job" , NULL, 10001, -5000.5, 5000.5);
281 TProfile hits_per_E_in (
"hits_per_E_in",
"average number of hits per E_{#nu} inside instrumented volume", nx, xmin, xmax);
282 TProfile hits_per_E_out(
"hits_per_E_out",
"average number of hits per E_{#nu} outside instrumented volume", nx, xmin, xmax);
286 JManager_t npe_per_type(
new TH1D(
"npe[%]", NULL, 5000, 0.5, 5000.5),
'%', ios::fmtflags(ios::showpos));
288 TH1D npe_per_pmt (
"pmt", NULL, 100001, -0.5, 100000.5);
295 TH2D nuExD(
"nuExD", NULL, nx, xmin, xmax, 100, 0.0, 1000.0);
296 TH2D* nuExD_tmp = (TH2D*) nuExD.Clone(
"nuExD.tmp");
298 TH2D nuExc(
"nuExc", NULL, nx, xmin, xmax, 100, -1.0, +1.0);
299 TH2D* nuExc_tmp = (TH2D*) nuExc.Clone(
"nuExc.tmp");
301 TH2D nuDxc(
"nuDxc", NULL, 50, 0.0, 1000.0, 100, -1.0, +1.0);
302 TH2D* nuDxc_tmp = (TH2D*) nuDxc.Clone(
"nuDxc.tmp");
304 TH2D nuDxU(
"nuDxU", NULL, 50, 0.0, 1000.0, 100, -1.0, +1.0);
305 TH2D* nuDxU_tmp = (TH2D*) nuDxU.Clone(
"nuDxU.tmp");
307 TH2D nuDxT(
"nuDxT", NULL, 50, 0.0, 1000.0,
getSize(T) - 1, T);
308 TH2D* nuDxT_tmp = (TH2D*) nuDxT.Clone(
"nuDxT.tmp");
321 TH2D muExR(
"muExR", NULL, nx, xmin, xmax, 30, 0.0, 300.0);
322 TH2D* muExR_tmp = (TH2D*) muExR.Clone(
"muExR.tmp");
324 TH2D muRxU(
"muRxU", NULL, 15, 0.0, 300.0, 100, -1.0, +1.0);
325 TH2D* muRxU_tmp = (TH2D*) muRxU.Clone(
"muRxU.tmp");
327 TH2D muRxT(
"muRxT", NULL, 15, 0.0, 300.0,
getSize(T) - 1, T);
328 TH2D* muRxT_tmp = (TH2D*) muRxT.Clone(
"muRxT.tmp");
339 while (inputFile.hasNext()) {
341 STATUS(
"event: " << setw(10) << inputFile.getCounter() <<
'\r');
DEBUG(endl);
343 const Evt*
event = inputFile.next();
351 hits.Fill(log10((Double_t)
event->mc_hits.size()));
354 trks.Fill(track->type);
363 const JVertex3D vertex = neutrino.getVertex();
375 const int type = hit->type;
376 const double t1 = hit->pure_t;
377 const double npe = hit->pure_a;
379 npe_pmt[hit->pmt_id].put(npe);
381 npe_type[0] .put(npe);
382 npe_type[type].put(npe);
384 if (hit_types.empty() || hit_types.count(type) != 0) {
387 event->mc_trks.end(),
390 if (track ==
event->mc_trks.end()) {
391 ERROR(
"Hit " << *hit <<
" has no origin." << endl);
395 if (count_if(
event->mc_trks.begin(),
396 event->mc_trks.end(),
398 ERROR(
"Hit " << *hit <<
" has ambiguous origin." << endl);
402 job.Fill((
double) track->type, npe);
404 if (router.hasPMT(hit->pmt_id)) {
406 const JPMT& pmt = router.getPMT(hit->pmt_id);
410 const JTrack3E muon =
getTrack(*track);
412 const double E = muon.getE();
413 const double x = log10(E);
414 const double R = muon.getDistance(pmt);
415 const double t0 = muon.getT (pmt);
416 const double ct1 = muon.getDot (pmt);
418 muExR.Fill(x, R, getMuonWeight(E, npe));
419 muRxU.Fill(R, ct1, getMuonWeight(E, R, npe));
420 muRxT.Fill(R, t1 - t0, getMuonWeight(E, R, npe));
424 const double E = neutrino.getE();
425 const double x = log10(E);
426 const double D = vertex.getDistance(pmt);
427 const double t0 = vertex.getT(pmt);
428 const double ct0 = neutrino.getDot(pmt.getPosition());
429 const double ct1 = vertex.getDot(pmt);
431 nuExD.Fill(x, D, getNeutrinoWeight(E, npe));
432 nuExc.Fill(x, ct0, getNeutrinoWeight(E, npe));
433 nuDxc.Fill(D, ct0, getNeutrinoWeight(E, D, npe));
434 nuDxU.Fill(D, ct1, getNeutrinoWeight(E, D, npe));
435 nuDxT.Fill(D, t1 - t0, getNeutrinoWeight(E, D, npe));
446 for (map_type::const_iterator i = npe_pmt.begin(); i != npe_pmt.end(); ++i) {
447 npe_per_pmt.Fill(i->second.getTotal());
450 for (map_type::const_iterator i = npe_type.begin(); i != npe_type.end(); ++i) {
451 npe_per_type[i->first]->Fill(i->second.getTotal());
463 const JTrack3E muon =
getTrack(*track);
465 const double E = muon.getE();
466 const double x = log10(E);
468 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
470 const double R = muon.getDistance(*module);
472 muExR_tmp->Fill(x, R, module->size());
474 if (R < muRxU.GetXaxis()->GetXmax()) {
475 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
476 muRxU_tmp->Fill(R, muon.getDot(*pmt));
480 if (R < muRxT.GetXaxis()->GetXmax()) {
481 for (Int_t iy = 1; iy <= muRxT_tmp->GetYaxis()->GetNbins(); ++iy) {
482 muRxT_tmp->Fill(R, muRxT_tmp->GetYaxis()->GetBinCenter(iy), muRxT_tmp->GetYaxis()->GetBinWidth(iy));
496 const double E = neutrino.getE();
497 const double x = log10(E);
499 if (inst_vol.is_inside(vertex))
500 hits_per_E_in .Fill(x, NPE);
502 hits_per_E_out.Fill(x, NPE);
504 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
506 const double D = vertex.getDistance(*module);
507 const double ct0 = neutrino.getDot(module->getPosition());
509 nuExD_tmp->Fill(x, D, module->size());
510 nuExc_tmp->Fill(x, ct0, module->size());
511 nuDxc_tmp->Fill(D, ct0, module->size());
513 if (D < nuDxU.GetXaxis()->GetXmax()) {
514 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
515 nuDxU_tmp->Fill(D, neutrino.getDot(*pmt));
519 if (D < nuDxT.GetXaxis()->GetXmax()) {
520 for (Int_t iy = 1; iy <= nuDxT_tmp->GetYaxis()->GetNbins(); ++iy) {
521 nuDxT_tmp->Fill(D, nuDxT_tmp->GetYaxis()->GetBinCenter(iy), nuDxT_tmp->GetYaxis()->GetBinWidth(iy));
535 TH1D *job_sorted = makeSortedH1(&job,
"hits_by_pdg");
536 TH1D *trks_sorted = makeSortedH1(&trks,
"trks_sorted");
538 if (inputFile.getCounter() != 0) {
540 const Double_t W = 1.0 / ((Double_t) inputFile.getCounter());
542 for (TH1D* buffer[] = { &hits, &npe_per_pmt, &job, &trks, job_sorted, trks_sorted, NULL }, **i = buffer; *i != NULL; ++i) {
546 for (JManager_t::iterator i = npe_per_type.begin(); i != npe_per_type.end(); ++i) {
550 nuExD.Divide(nuExD_tmp);
551 nuExc.Divide(nuExc_tmp);
552 nuDxc.Divide(nuDxc_tmp);
553 nuDxU.Divide(nuDxU_tmp);
554 nuDxT.Divide(nuDxT_tmp);
556 muExR.Divide(muExR_tmp);
557 muRxU.Divide(muRxU_tmp);
558 muRxT.Divide(muRxT_tmp);
568 out << hits << job << *job_sorted << trks << *trks_sorted << hits_per_E_in << hits_per_E_out << npe_per_type << npe_per_pmt;
570 out << nuExD << nuExc << nuDxc << nuDxU << nuDxT;
571 out << muExR << muRxU << muRxT;
Utility class to parse command line options.
static const JGeane gWater(2.67e-1 *JTOOLS::DENSITY_SEA_WATER, 3.4e-4 *JTOOLS::DENSITY_SEA_WATER)
Function object for Energy loss of muon in sea water.
JPredicate< JResult_t T::*, JComparison::eq > make_predicate(JResult_t T::*member, const JResult_t value)
Helper method to create predicate for data member.
JTrack3E getTrack(const Trk &track)
Get track.
double geanc()
Equivalent muon track length per unit shower energy.
Auxiliary class to manage set of histograms.
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
bool is_muon(const Trk &track)
Test whether given track is a (anti-)muon.
double getB() const
Get energy loss constant.
Structure to store the ToT mean and standard deviation of the hits produced by a nanobeacon in a sour...
#define MAKE_CSTRING(A)
Make C-string.
Empty structure for specification of parser element that is initialised (i.e.
Dynamic ROOT object management.
size_t getSize(T(&array)[N])
Get size of c-array.
Data structure for detector geometry and calibration.
Head getHeader(const JMultipleFileScanner_t &file_list)
Get Monte Carlo header.
JLimit JLimit_t
Type definition of limit.
I/O formatting auxiliaries.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
void load(const JString &file_name, JDetector &detector)
Load detector from input file.
Direct access to PMT in detector data structure.
General purpose messaging.
Scanning of objects from multiple files according a format that follows from the extension of each fi...
Utility class to parse command line options.
ROOT TTree parameter settings.
const JLimit & getLimit() const
Get limit.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
#define DEBUG(A)
Message macros.
int main(int argc, char *argv[])