199 string fileDescriptor;
226 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
229 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
232 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
234 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
235 zap[
'k'] =
make_field(keep,
"keep position of tracks");
236 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
237 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
243 catch(
const exception &error) {
244 FATAL(error.what() << endl);
248 gRandom->SetSeed(seed);
251 const JMeta meta(argc, argv);
253 const double Zbed = 0.0;
267 double maximal_road_width = 0.0;
268 double maximal_distance = 0.0;
270 for (
size_t i = 0; i != CDF.size(); ++i) {
272 DEBUG(
"Range CDF["<< CDF[i].type <<
"] " << CDF[i].
function.intensity.getXmax() <<
" m" << endl);
274 maximal_road_width = max(maximal_road_width, CDF[i].
function.intensity.getXmax());
277 for (
size_t i = 0; i != CDG.size(); ++i) {
279 DEBUG(
"Range CDG["<< CDG[i].type <<
"] " << CDG[i].
function.intensity.getXmax() <<
" m" << endl);
282 maximal_road_width = max(maximal_road_width, CDG[i].
function.intensity.getXmax());
285 maximal_distance = max(maximal_distance, CDG[i].
function.intensity.getXmax());
288 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
289 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
292 if (detectorFile ==
"" || inputFile.empty()) {
293 STATUS(
"Nothing to be done." << endl);
301 STATUS(
"Load detector... " << flush);
313 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ) {
314 if (!module->empty())
325 STATUS(
"Setting up radiation tables... " << flush);
329 const JRadiation hydrogen ( 1.0, 1.0, 40, 0.01, 0.1, 0.1);
330 const JRadiation oxygen ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
331 const JRadiation chlorine (17.0, 35.5, 40, 0.01, 0.1, 0.1);
332 const JRadiation sodium (11.0, 23.0, 40, 0.01, 0.1, 0.1);
399 header = inputFile.getHeader();
401 JHead buffer(header);
403 center = get<Vec>(buffer);
409 buffer.simul.rbegin()->date =
getDate();
410 buffer.simul.rbegin()->time =
getTime();
415 buffer.detector.rbegin()->filename = detectorFile;
417 buffer.push(&JHead::simul);
423 buffer.can.zmin += center.z;
424 buffer.can.zmax += center.z;
426 buffer.push(&JHead::coord_origin);
427 buffer.push(&JHead::can);
432 center +=
Vec(circle.getX(), circle.getY(), 0.0);
434 copy(buffer, header);
441 NOTICE(
"Offset applied to true tracks is: " << center << endl);
443 NOTICE(
"No offset applied to true tracks." << endl);
449 if (cylinder.getZmin() < Zbed) {
450 cylinder.setZmin(Zbed);
453 NOTICE(
"Light generation volume: " << cylinder << endl);
455 TH1D job(
"job", NULL, 400, 0.5, 400.5);
456 TProfile cpu(
"cpu", NULL, 16, 0.0, 8.0);
457 TProfile2D rms(
"rms", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
458 TProfile2D rad(
"rad", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
478 STATUS(
"event: " << setw(10) <<
in.getCounter() <<
'\r');
DEBUG(endl);
482 Evt* evt =
in.next();
486 track->pos += center;
492 event.mc_hits.clear();
501 if (!track->is_finalstate()) {
517 double Zmin = intersection.first;
518 double Zmax = intersection.second;
524 JVertex vertex(0.0, track->t, track->E);
526 if (track->pos.z < Zbed) {
528 if (track->dir.z > 0.0)
529 vertex.step(
gRock, (Zbed - track->pos.z) / track->dir.z);
534 if (vertex.getZ() < Zmin) {
535 vertex.step(
gWater, Zmin - vertex.getZ());
544 const JDetectorSubset_t subdetector(
detector,
getAxis(*track), maximal_road_width);
546 if (subdetector.empty()) {
554 while (vertex.getE() >=
parameters.Emin_GeV && vertex.getZ() < Zmax) {
556 const int N = radiation.size();
561 for (
int i = 0; i !=
N; ++i) {
562 ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.getE());
567 for (
size_t i = 0; i != ionization.size(); ++i) {
568 As += ionization[i]->getA(vertex.getE());
571 double step = gRandom->Exp(1.0) / ls;
572 double range = vertex.getRange(As);
580 double ts =
getThetaMCS(vertex.getE(), min(step,range));
583 rms.Fill(
log10(vertex.getE()), (Double_t) 0, ts*ts);
585 vertex.getDirection() += getRandomDirection(T2/3.0);
587 vertex.step(As, min(step,range));
595 double y = gRandom->Uniform(ls);
597 for (
int i = 0; i !=
N; ++i) {
603 Es = radiation[i]->getEnergyOfShower(vertex.getE());
604 ts = radiation[i]->getThetaRMS(vertex.getE(), Es);
608 rms.Fill(
log10(vertex.getE()), (Double_t) radiation[i]->getID(), ts*ts);
609 rad.Fill(
log10(vertex.getE()), (Double_t) radiation[i]->getID(), Es);
617 vertex.applyEloss(getRandomDirection(T2), Es);
619 muon.push_back(vertex);
624 if (vertex.getZ() < Zmax && vertex.getRange() > 0.0) {
626 vertex.step(vertex.getRange());
628 muon.push_back(vertex);
637 if (trk != event.mc_trks.end()) {
638 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
642 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
644 const double z0 = muon.begin()->getZ();
645 const double t0 = muon.begin()->getT();
646 const double Z = module->getZ() - module->getX() /
getTanThetaC();
648 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
650 const JVector2D pos = muon.getPosition(Z);
651 const double R = hypot(module->getX() - pos.
getX(),
652 module->getY() - pos.
getY());
654 for (
size_t i = 0; i != CDF.size(); ++i) {
656 if (R < CDF[i].integral.getXmax()) {
666 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
667 const int N = gRandom->Poisson(NPE);
673 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
675 const double R = hypot(pmt->getX() - pos.
getX(),
676 pmt->getY() - pos.
getY());
677 const double Z = pmt->getZ() - z0;
678 const double theta = python.constrain(pmt->getTheta());
679 const double phi = python.constrain(fabs(pmt->getPhi()));
681 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
687 job.Fill((
double) (100 + CDF[i].type), (
double) n0);
691 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
694 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
706 job.Fill((
double) (300 + CDF[i].type));
710 catch(
const exception& error) {
711 job.Fill((
double) (200 + CDF[i].type));
718 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
720 const double Es = vertex->getEs();
724 const double z0 = vertex->getZ();
725 const double t0 = vertex->getT();
728 int origin = track->id;
730 if (writeEMShowers) {
731 origin =
event.mc_trks.size() + 1;
734 int number_of_hits = 0;
736 JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
737 z0 + maximal_distance);
739 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
741 const double R = hypot(module->getX() - vertex->getX(),
742 module->getY() - vertex->getY());
743 const double Z = module->getZ() - z0 -
DZ;
744 const double D = sqrt(R*R + Z*Z);
745 const double cd = Z /
D;
747 for (
size_t i = 0; i != CDG.size(); ++i) {
749 if (D < CDG[i].integral.getXmax()) {
753 const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
754 const int N = gRandom->Poisson(NPE);
760 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
762 const double R = hypot(pmt->getX() - vertex->getX(),
763 pmt->getY() - vertex->getY());
764 const double Z = pmt->getZ() - z0 -
DZ;
765 const double D = sqrt(R*R + Z*Z);
766 const double cd = Z /
D;
767 const double theta = python.constrain(pmt->getTheta());
768 const double phi = python.constrain(fabs(pmt->getPhi()));
770 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor;
776 job.Fill((
double) (100 + CDG[i].type), (
double) n0);
781 const double Z = pmt->getZ() - z0 - dz;
782 const double D = sqrt(R*R + Z*Z);
783 const double cd = Z /
D;
785 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
788 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
797 number_of_hits += n1;
802 job.Fill((
double) (300 + CDG[i].type));
806 catch(
const exception& error) {
807 job.Fill((
double) (200 + CDG[i].type));
813 if (writeEMShowers && number_of_hits != 0) {
815 event.mc_trks.push_back(
JTrk_t(origin,
818 track->pos + track->dir * vertex->getZ(),
826 }
else if (track->len > 0.0) {
834 const double z0 = 0.0;
835 const double z1 = z0 + track->len;
836 const double t0 = track->t;
837 const double E = track->E;
843 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
847 const double R = pos.
getX();
852 R > maximal_road_width) {
856 for (
size_t i = 0; i != CDF.size(); ++i) {
868 if (R < CDF[i].integral.getXmax()) {
872 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
873 const int N = gRandom->Poisson(NPE);
883 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
885 const double R = pmt->getX();
886 const double Z = pmt->getZ() - z0;
887 const double theta = python.constrain(pmt->getTheta());
888 const double phi = python.constrain(fabs(pmt->getPhi()));
890 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
896 job.Fill((
double) (120 + CDF[i].type), (
double) n0);
900 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
903 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
915 job.Fill((
double) (320 + CDF[i].type));
919 catch(
const exception& error) {
920 job.Fill((
double) (220 + CDF[i].type));
927 if (!buffer.empty()) {
946 catch(
const exception& error) {
947 ERROR(error.what() << endl);
950 E =
pythia(track->type, E);
954 const double z0 = 0.0;
955 const double t0 = track->t;
962 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
966 const double R = pos.
getX();
967 const double Z = pos.
getZ() - z0 -
DZ;
968 const double D = sqrt(R*R + Z*Z);
969 const double cd = Z /
D;
971 for (
size_t i = 0; i != CDG.size(); ++i) {
973 if (D < CDG[i].integral.getXmax()) {
977 const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
978 const int N = gRandom->Poisson(NPE);
988 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
990 const double R = pmt->getX();
991 const double Z = pmt->getZ() - z0 -
DZ;
992 const double D = sqrt(R*R + Z*Z);
993 const double cd = Z /
D;
994 const double theta = python.constrain(pmt->getTheta());
995 const double phi = python.constrain(fabs(pmt->getPhi()));
997 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * E * factor;
1003 job.Fill((
double) (140 + CDG[i].type), (
double) n0);
1008 const double Z = pmt->getZ() - z0 - dz;
1009 const double D = sqrt(R*R + Z*Z);
1010 const double cd = Z /
D;
1012 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
1015 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
1027 job.Fill((
double) (340 + CDG[i].type));
1031 catch(
const exception& error) {
1032 job.Fill((
double) (240 + CDG[i].type));
1038 if (!buffer.empty()) {
1049 if (!mc_hits.empty()) {
1053 event.mc_hits.resize(mc_hits.size());
1055 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
1064 if (event.mc_hits.size() >= numberOfHits) {
const char *const energy_lost_in_can
Data structure for vector in two dimensions.
Utility class to parse command line options.
JPredicate< JResult_t T::*, JComparison::eq > make_predicate(JResult_t T::*member, const JResult_t value)
Helper method to create predicate for data member.
static const JRadiationSource_t EErad_t
Data structure for a composite optical module.
void merge(const double Tmax_ns)
Merge hits on same PMT that are within given time window.
Auxiliary class to set-up Trk.
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
double safetyFactor
safety factor for average CDF integral of optical module
Generator for simulation.
double getIndexOfRefraction()
Get average index of refraction of water corresponding to group velocity.
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.
Implementation for calculation of ionization constant.
JHitType_t getHitType(const JPDFType_t pdf, const bool shower=false)
Get hit type corresponding to given PDF type.
Auxiliary class for PMT parameters including threshold.
double getDeltaRaysFromTau(const double E)
Equivalent EM-shower energy due to delta-rays per unit tau track length.
Utility class to parse parameter values.
then JShowerPostfit f $INPUT_FILE o $OUTPUT_FILE N
static const double H
Planck constant [eV s].
*fatal Wrong number of arguments esac JCookie sh typeset Z DETECTOR typeset Z SOURCE_RUN typeset Z TARGET_RUN set_variable PARAMETERS_FILE $WORKDIR parameters
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
static const JGeane_t gRock(2.67e-1 *0.9 *DENSITY_ROCK, 3.40e-4 *1.2 *DENSITY_ROCK)
Function object for energy loss of muon in rock.
static const JGeaneWater gWater
Function object for energy loss of muon in sea water.
static const double DENSITY_SEA_WATER
Fixed environment values.
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.
double getY() const
Get y position.
static const char *const APPLICATION_JSIRENE
detector simulation
Fast implementation of class JRadiation.
Implementation for calculation of inverse interaction length and shower energy.
Auxiliary data structure for list of hits with hit merging capability.
bool is_neutrino(const Trk &track)
Test whether given track is a neutrino.
static const double C
Physics constants.
scattered light from muon
Auxiliary class for defining the range of iterations of objects.
double getThetaMCS(const double E, const double x, const double X0, const double M, const double Q)
Get multiple Coulomb scattering angle.
Implementation for calculation of inverse interaction length and shower energy due to deep-inelastic ...
The Vec class is a straightforward 3-d vector, which also works in pyroot.
std::string getGITVersion(const std::string &tag)
Get GIT version for given GIT tag.
double getKineticEnergy(const double E, const double m)
Get kinetic energy of particle with given mass.
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
set_variable E_E log10(E_{fit}/E_{#mu})"
static const JGeanz geanz(1.85, 0.62, 0.54)
Function object for longitudinal EM-shower profile.
double getX() const
Get x position.
JAxis3D getAxis(const Trk &track)
Get axis.
Auxiliary class for CPU timing and usage.
JPosition3D getPosition(const Vec &pos)
Get position.
scattered light from delta-rays
direct light from EM shower
static const double PI
Mathematical constants.
void addMargin(const double D)
Add (safety) margin.
static const JRadiationSource_t Brems_t
const char * getDate(const JDateAndTimeFormat option=ISO8601)
Get ASCII formatted date.
then usage $script[distance] fi case set_variable R
Detector subset with binary search functionality.
Detector subset without binary search functionality.
Vertex of energy loss of muon.
The Head class reflects the header of Monte-Carlo event files, which consists of keys (also referred ...
direct light from delta-rays
z range($ZMAX-$ZMIN)< $MINIMAL_DZ." fi fi typeset -Z 4 STRING typeset -Z 2 FLOOR JPlot1D -f $
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 ...
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
double getMaximum(const double E) const
Get depth of shower maximum.
General purpose class for object reading from a list of file names.
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&)).
bool is_deltarays(const int pdf)
Test if given PDF type corresponds to Cherenkov light from delta-rays.
Auxiliary class to set-up Hit.
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 data structure to list files in directory.
double getTanThetaC()
Get average tangent of Cherenkov angle of water corresponding to group velocity.
do set_variable MODULE getModule a $WORKDIR detector_a datx L $STRING JEditDetector a $WORKDIR detector_a datx M $MODULE setz o $WORKDIR detector_a datx JEditDetector a $WORKDIR detector_b datx M $MODULE setz o $WORKDIR detector_b datx done echo Output stored at $WORKDIR detector_a datx and $WORKDIR tripod_a txt JDrawDetector2D a $WORKDIR detector_a datx a $WORKDIR detector_b datx L BL o detector $FORMAT $BATCH JDrawDetector2D T $WORKDIR tripod_a txt T $WORKDIR tripod_b txt L BL o tripod $FORMAT $BATCH JCompareDetector a $WORKDIR detector_a datx b $WORKDIR detector_b datx o $WORKDIR abc root &dev null for KEY in X Y Z
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.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
do set_variable DETECTOR_TXT $WORKDIR detector
bool is_tau(const Trk &track)
Test whether given track is a (anti-)tau.
static const JRadiationSource_t GNrad_t
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
do echo Generating $dir eval D
int numberOfBins
number of bins for average CDF integral of optical module
double getZ() const
Get z position.
std::vector< Trk > mc_trks
MC: list of MC truth tracks.
The Evt class respresent a Monte Carlo (MC) event as well as an offline event.
#define DEBUG(A)
Message macros.