13 #include "evt/Head.hh"
81 const int NUMBER_OF_BINS = 200;
82 const double SAFETY_FACTOR = 1.7;
88 template<
class function_type,
97 JABC(
const std::string& file_descriptor,
const JPDFType_t type)
101 const std::string file_name =
getFilename(file_descriptor, this->type);
103 STATUS(
"loading input from file " << file_name <<
"... " << flush);
106 function.load(file_name.c_str());
112 integral = integral_type(
function, NUMBER_OF_BINS, SAFETY_FACTOR);
118 function_type
function;
119 integral_type integral;
123 typedef JABC<JCDF4D_t, JCDF1D_t> JCDF_t;
124 typedef JABC<JCDF5D_t, JCDF2D_t> JCDG_t;
167 int main(
int argc,
char **argv)
172 string fileDescriptor;
177 double Ecut_GeV = 0.1;
178 double Emin_GeV = 1.0;
180 double Tmax_ns = 0.1;
181 int Nmax_npe = numeric_limits<int>::max();
197 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
200 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
203 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
205 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
206 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
207 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
213 catch(
const exception &error) {
214 FATAL(error.what() << endl);
218 gRandom->SetSeed(seed);
221 const JMeta meta(argc, argv);
223 const double Zbed = 0.0;
237 double maximal_road_width = 0.0;
238 double maximal_distance = 0.0;
240 for (
size_t i = 0; i != CDF.size(); ++i) {
242 DEBUG(
"Range CDF["<< CDF[i].type <<
"] " << CDF[i].
function.intensity.getXmax() <<
" m" << endl);
244 maximal_road_width = max(maximal_road_width, CDF[i].
function.intensity.getXmax());
247 for (
size_t i = 0; i != CDG.size(); ++i) {
249 DEBUG(
"Range CDG["<< CDG[i].type <<
"] " << CDG[i].
function.intensity.getXmax() <<
" m" << endl);
252 maximal_road_width = max(maximal_road_width, CDG[i].
function.intensity.getXmax());
255 maximal_distance = max(maximal_distance, CDG[i].
function.intensity.getXmax());
258 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
259 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
262 if (detectorFile ==
"" || inputFile.empty()) {
263 STATUS(
"Nothing to be done." << endl);
271 STATUS(
"Load detector... " << flush);
286 STATUS(
"Setting up radiation tables... " << flush);
288 const JRadiation hydrogen( 1.0, 1.0, 40, 0.01, 0.1, 0.1);
289 const JRadiation oxygen ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
290 const JRadiation chlorine(17.0, 35.0, 40, 0.01, 0.1, 0.1);
321 header = inputFile.getHeader();
323 JHead buffer(header);
330 center = get<Vec>(buffer);
338 center += Vec(circle.getX(), circle.getY(), 0.0);
340 push(buffer, &JHead::simul);
341 push(buffer, &JHead::coord_origin);
342 push(buffer, &JHead::can);
343 copy(buffer, header);
349 NOTICE(
"Offset applied to true tracks is: " << center << endl);
355 if (cylinder.getZmin() < Zbed) {
356 cylinder.setZmin(Zbed);
360 TProfile cpu(
"cpu", NULL, 14, 1.0, 8.0);
361 TH1D job(
"job", NULL, 400, 0.5, 400.5);
379 STATUS(
"event: " << setw(10) << in.getCounter() <<
'\r');
DEBUG(endl);
383 Evt* evt = in.next();
386 track->pos += center;
391 event.mc_hits.clear();
412 double Zmin = intersection.first;
413 double Zmax = intersection.second;
415 if (Zmax - Zmin <= Dmin_m) {
419 JVertex vertex(0.0, track->t, track->E);
421 if (track->pos.z < Zbed) {
423 if (track->dir.z > 0.0)
424 vertex.
step(
gRock, (Zbed - track->pos.z) / track->dir.z);
429 if (vertex.
getZ() < Zmin) {
439 const JDetectorSubset_t subdetector(
detector,
getAxis(*track), maximal_road_width);
441 if (subdetector.empty()) {
449 while (vertex.
getE() >= Emin_GeV && vertex.
getZ() < Zmax) {
451 const int N = radiation.size();
456 for (
int i = 0; i != N; ++i) {
457 ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.
getE());
460 const double ds = min(gRandom->Exp(1.0) / ls, vertex.
getRange());
464 if (vertex.
getE() >= Emin_GeV) {
467 double y = gRandom->Uniform(ls);
469 for (
int i = 0; i != N; ++i) {
474 Es = radiation[i]->getEnergyOfShower(vertex.
getE());
481 if (Es >= Ecut_GeV) {
482 muon.push_back(vertex);
489 if (vertex.
getE() < Emin_GeV && vertex.
getRange() > 0.0) {
493 muon.push_back(vertex);
502 if (trk != event.mc_trks.end()) {
503 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
504 trk->setusr(mc_usr_keys::energy_lost_in_can, muon.begin()->
getE() - muon.rbegin()->
getE());
507 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
509 const double z0 = muon.begin()->getZ();
510 const double t0 = muon.begin()->getT();
511 const double R = module->getX();
514 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
516 for (
size_t i = 0; i != CDF.size(); ++i) {
518 if (R < CDF[i].integral.getXmax()) {
528 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
529 const int N = gRandom->Poisson(NPE);
535 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
537 const double R = pmt->getX();
538 const double Z = pmt->getZ() - z0;
539 const double theta = pmt->getTheta();
540 const double phi = fabs(pmt->getPhi());
542 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
548 job.Fill((
double) (100 + CDF[i].type), (
double) n0);
552 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
555 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
567 job.Fill((
double) (300 + CDF[i].type));
571 catch(
const exception& error) {
572 job.Fill((
double) (200 + CDF[i].type));
579 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
581 const double z0 = vertex->
getZ();
582 const double t0 = vertex->
getT();
583 const double Es = vertex->
getEs();
585 int origin = track->id;
587 if (writeEMShowers) {
588 origin =
event.mc_trks.size() + 1;
591 int number_of_hits = 0;
593 JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
594 z0 + maximal_distance);
596 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
599 const double R = module->getX();
600 const double Z = module->getZ() - z0 - dz;
601 const double D = sqrt(R*R + Z*Z);
602 const double cd = Z / D;
604 for (
size_t i = 0; i != CDG.size(); ++i) {
606 if (D < CDG[i].integral.getXmax()) {
610 const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
611 const int N = gRandom->Poisson(NPE);
617 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
620 const double R = pmt->getX();
621 const double Z = pmt->getZ() - z0 - dz;
622 const double theta = pmt->getTheta();
623 const double phi = fabs(pmt->getPhi());
624 const double D = sqrt(R*R + Z*Z);
625 const double cd = Z / D;
627 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor;
633 job.Fill((
double) (100 + CDG[i].type), (
double) n0);
638 const double Z = pmt->getZ() - z0 - dz;
639 const double D = sqrt(R*R + Z*Z);
640 const double cd = Z / D;
642 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
645 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
654 number_of_hits += n1;
659 job.Fill((
double) (300 + CDG[i].type));
663 catch(
const exception& error) {
664 job.Fill((
double) (200 + CDG[i].type));
670 if (writeEMShowers && number_of_hits != 0) {
672 event.mc_trks.push_back(
JTrk_t(origin,
675 track->pos + track->dir * vertex->
getZ(),
682 }
else if (
is_tau(*track)) {
690 const double z0 = 0.0;
691 const double z1 = z0 + track->len;
692 const double t0 = track->t;
693 const double E = track->E;
699 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
703 const double R = pos.
getX();
708 R > maximal_road_width) {
712 for (
size_t i = 0; i != CDF.size(); ++i) {
714 if (R < CDF[i].integral.getXmax()) {
724 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
725 const int N = gRandom->Poisson(NPE);
735 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
737 const double R = pmt->getX();
738 const double Z = pmt->getZ() - z0;
739 const double theta = pmt->getTheta();
740 const double phi = fabs(pmt->getPhi());
742 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
748 job.Fill((
double) (120 + CDF[i].type), (
double) n0);
752 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
755 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
767 job.Fill((
double) (320 + CDF[i].type));
771 catch(
const exception& error) {
772 job.Fill((
double) (220 + CDF[i].type));
779 if (!buffer.empty()) {
798 catch(
const exception& error) {
799 ERROR(error.what() << endl);
802 E =
pythia(track->type, E);
804 if (E < Ecut_GeV || cylinder.getDistance(
getPosition(*track)) > Dmin_m) {
808 const double z0 = 0.0;
809 const double t0 = track->t;
815 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
820 const double R = pos.
getX();
821 const double Z = pos.
getZ() - z0 - dz;
822 const double D = sqrt(R*R + Z*Z);
823 const double cd = Z / D;
825 if (D > maximal_distance) {
829 for (
size_t i = 0; i != CDG.size(); ++i) {
831 if (D < CDG[i].integral.getXmax()) {
835 const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
836 const int N = gRandom->Poisson(NPE);
846 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
849 const double R = pmt->getX();
850 const double Z = pmt->getZ() - z0 - dz;
851 const double theta = pmt->getTheta();
852 const double phi = fabs(pmt->getPhi());
853 const double D = sqrt(R*R + Z*Z);
854 const double cd = Z / D;
856 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * E * factor;
862 job.Fill((
double) (140 + CDG[i].type), (
double) n0);
867 const double Z = pmt->getZ() - z0 - dz;
868 const double D = sqrt(R*R + Z*Z);
869 const double cd = Z / D;
871 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
874 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
886 job.Fill((
double) (340 + CDG[i].type));
890 catch(
const exception& error) {
891 job.Fill((
double) (240 + CDG[i].type));
897 if (!buffer.empty()) {
908 if (!mc_hits.empty()) {
910 mc_hits.
merge(Tmax_ns);
912 event.mc_hits.resize(mc_hits.size());
914 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
920 cpu.Fill(log10(
get_neutrino(event).E), (
double) timer.usec_ucpu * 1.0e-3);
923 if (event.mc_hits.size() >= numberOfHits) {
Auxiliary class to set-up Hit.
Utility class to parse command line options.
Custom class for CDF table in 2 dimensions.
double getEs() const
Get shower energy.
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.
Multi-dimensional CDF table for arrival time of Cherenkov light.
double getT() const
Get time.
JPredicate< JResult_t T::*, JComparison::eq > make_predicate(JResult_t T::*member, const JResult_t value)
Helper method to create predicate for data member.
JVertex & step(const double ds)
Step.
Data structure for a composite optical module.
void applyEloss(const double Es)
Apply energy loss energy.
JTransformation3D getTransformation(const Trk &track)
Get transformation.
Data structure for circle in two dimensions.
#define gmake_property(A)
macro to convert (template) parameter to JPropertiesElement object
scattered light from EM shower
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.
std::string program
program name
Recording of objects on file according a format that follows from the file name extension.
JHitType_t getHitType(const JPDFType_t pdf, const bool shower=false)
Get hit type corresponding to given PDF type.
double getDeltaRaysFromTau(const double E)
Equivalent EM-shower energy due to delta-rays per unit tau track length.
Utility class to parse parameter values.
Structure to store the ToT mean and standard deviation of the hits produced by a nanobeacon in a sour...
void push(JHead &header, T JHead::*p)
Push data of JHead for subsequent copy to Head.
double getE() const
Get muon energy.
Empty structure for specification of parser element that is initialised (i.e.
void merge(const double Tmax_ns)
Merge hits on same PMT that are within given time window.
static const JPythia pythia
Function object for relative light yield as a function of GEANT particle code.
double getTime(const Hit &hit)
Get true time of hit.
Data structure for detector geometry and calibration.
static const JGeane gRock(2.67e-1 *0.9 *JTOOLS::DENSITY_ROCK, 3.4e-4 *1.2 *JTOOLS::DENSITY_ROCK)
Function object for Energy loss of muon in rock.
Utility class to parse parameter values.
Fast implementation of class JRadiation.
Various implementations of functional maps.
Numbering scheme for PDF types.
bool is_neutrino(const Trk &track)
Test whether given track is a neutrino.
Auxiliary class to extract a subset of optical modules from a detector.
scattered light from muon
Auxiliary class for defining the range of iterations of objects.
double getZ() const
Get position.
I/O formatting auxiliaries.
The template JSharedPointer class can be used to share a pointer to an object.
Auxiliary class for the calculation of the muon radiative cross sections.
T & getInstance(const T &object)
Get static instance from temporary object.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
static const JGeanz geanz(1.85, 0.62, 0.54)
Function object for longitudinal EM-shower profile.
JAxis3D getAxis(const Trk &track)
Get axis.
double getE(const double z) const
Get muon energy at given position.
Auxiliary class for CPU timing and usage.
scattered light from delta-rays
std::string version
program version
direct light from EM shower
const char * getGITVersion()
Get GIT version.
Auxiliary data structure for list of hits with hit merging capability.
void addMargin(const double D)
Add (safety) margin.
void load(const JString &file_name, JDetector &detector)
Load detector from input file.
double getKineticEnergy(const double E, const double m)
Get kinetic energy of particle with given mass.
General purpose messaging.
Detector subset with binary search functionality.
Detector subset without binary search functionality.
Vertex of energy loss of muon.
Scanning of objects from multiple files according a format that follows from the extension of each fi...
const char * getDate()
Get ASCII formatted date.
Custom class for CDF table in 1 dimension.
direct light from delta-rays
virtual bool hasNext()
Check availability of next element.
int getNumberOfPhotoElectrons(const double NPE, const int N, const double npe)
Get number of photo-electrons of a hit given the expectation values of the number of photo-electrons ...
double getMaximum(const double E) const
Get depth of shower maximum.
General purpose class for object reading from a list of file names.
std::string date
processing date
Utility class to parse command line options.
bool is_scattered(const int pdf)
Test if given PDF type corresponds to scattered light.
void transform(const JRotation3D &R, const JVector3D &pos)
Transformation of geometry (see method JGEOMETRY3D::JPosition3D::transform(const JRotation3D&, const JVector3D&)).
ROOT TTree parameter settings.
bool is_deltarays(const int pdf)
Test if given PDF type corresponds to Cherenkov light from delta-rays.
double getX() const
Get x position.
double getDeltaRaysFromMuon(const double E)
Equivalent EM-shower energy due to delta-rays per unit muon track length.
void copy(const Head &from, JHead &to)
Copy header from from to to.
Auxiliary class to list files.
std::string getFilename(const std::string &file_name)
Get file name part, i.e.
Data structure for position in three dimensions.
const JLimit & getLimit() const
Get limit.
double getLength(const double E, const double P, const double eps=1.0e-3) const
Get shower length for a given integrated probability.
virtual const char * what() const
Get error message.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
bool is_tau(const Trk &track)
Test whether given track is a (anti-)tau.
std::string time
processing time
double getRange() const
Get range of muon.
JAANET::coord_origin coord_origin
double getZ() const
Get z position.
Auxiliary class to set-up Trk.
#define DEBUG(A)
Message macros.
JPosition3D getPosition(const Vec &v)
Get position.
int main(int argc, char *argv[])