202 string fileDescriptor;
229 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
232 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
235 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
237 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
238 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
239 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
245 catch(
const exception &error) {
246 FATAL(error.what() << endl);
250 gRandom->SetSeed(seed);
253 const JMeta meta(argc, argv);
255 const double Zbed = 0.0;
269 double maximal_road_width = 0.0;
270 double maximal_distance = 0.0;
272 for (
size_t i = 0;
i != CDF.size(); ++
i) {
274 DEBUG(
"Range CDF["<< CDF[
i].
type <<
"] " << CDF[
i].
function.intensity.getXmax() <<
" m" << endl);
276 maximal_road_width = max(maximal_road_width, CDF[
i].
function.intensity.getXmax());
279 for (
size_t i = 0;
i != CDG.size(); ++
i) {
281 DEBUG(
"Range CDG["<< CDG[
i].
type <<
"] " << CDG[
i].
function.intensity.getXmax() <<
" m" << endl);
284 maximal_road_width = max(maximal_road_width, CDG[
i].
function.intensity.getXmax());
287 maximal_distance = max(maximal_distance, CDG[
i].
function.intensity.getXmax());
290 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
291 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
294 if (detectorFile ==
"" || inputFile.empty()) {
295 STATUS(
"Nothing to be done." << endl);
303 STATUS(
"Load detector... " << flush);
315 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ) {
316 if (!module->empty())
327 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);
334 const JRadiation calcium (20.0, 40.0, 40, 0.01, 0.1, 0.1);
335 const JRadiation magnesium(12.0, 24.3, 40, 0.01, 0.1, 0.1);
336 const JRadiation potassium(19.0, 39.0, 40, 0.01, 0.1, 0.1);
337 const JRadiation sulphur (16.0, 32.0, 40, 0.01, 0.1, 0.1);
405 if (cylinder.getZmin() < Zbed) {
406 cylinder.setZmin(Zbed);
409 NOTICE(
"Light generation volume: " << cylinder << endl);
417 header = inputFile.getHeader();
419 JHead buffer(header);
425 buffer.simul.rbegin()->date =
getDate();
426 buffer.simul.rbegin()->time =
getTime();
428 buffer.push(&JHead::simul);
433 buffer.detector.rbegin()->filename = detectorFile;
437 offset +=
Vec(cylinder.getX(), cylinder.getY(), 0.0);
440 if (buffer.is_valid(&JHead::fixedcan)) {
441 buffer.fixedcan.xcenter += offset.x;
442 buffer.fixedcan.ycenter += offset.y;
443 buffer.fixedcan.zmin += offset.z;
444 buffer.fixedcan.zmax += offset.z;
446 buffer.fixedcan.xcenter = cylinder.getX();
447 buffer.fixedcan.ycenter = cylinder.getY();
448 buffer.fixedcan.radius = cylinder.getRadius();
449 buffer.fixedcan.zmin = cylinder.getZmin();
450 buffer.fixedcan.zmax = cylinder.getZmax();
453 buffer.push(&JHead::fixedcan);
455 if (buffer.is_valid(&JHead::coord_origin)) {
459 buffer.push(&JHead::coord_origin);
462 copy(buffer, header);
468 NOTICE(
"Offset applied to true tracks is: " << offset << endl);
470 TH1D job(
"job", NULL, 400, 0.5, 400.5);
471 TProfile cpu(
"cpu", NULL, 16, 0.0, 8.0);
472 TProfile2D rms(
"rms", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
473 TProfile2D rad(
"rad", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
493 STATUS(
"event: " << setw(10) <<
in.getCounter() <<
'\r');
DEBUG(endl);
497 Evt* evt =
in.next();
500 track->pos += offset;
505 event.mc_hits.clear();
514 if (!track->is_finalstate()) {
530 double Zmin = intersection.first;
531 double Zmax = intersection.second;
537 JVertex vertex(0.0, track->t, track->E);
539 if (track->pos.z < Zbed) {
541 if (track->dir.z > 0.0)
542 vertex.step(
gRock, (Zbed - track->pos.z) / track->dir.z);
547 if (vertex.getZ() < Zmin) {
548 vertex.step(
gWater, Zmin - vertex.getZ());
557 const JDetectorSubset_t subdetector(
detector,
getAxis(*track), maximal_road_width);
559 if (subdetector.empty()) {
567 while (vertex.getE() >=
parameters.Emin_GeV && vertex.getZ() < Zmax) {
569 const int N = radiation.size();
574 for (
int i = 0;
i !=
N; ++
i) {
575 ls += li[
i] = radiation[
i]->getInverseInteractionLength(vertex.getE());
580 for (
size_t i = 0;
i != ionization.size(); ++
i) {
581 As += ionization[
i]->getA(vertex.getE());
584 double step = gRandom->Exp(1.0) / ls;
585 double range = vertex.getRange(As);
593 double ts =
getThetaMCS(vertex.getE(), min(step,range));
596 rms.Fill(
log10(vertex.getE()), (Double_t) 0, ts*ts);
598 vertex.getDirection() += getRandomDirection(T2/3.0);
600 vertex.step(As, min(step,range));
608 double y = gRandom->Uniform(ls);
610 for (
int i = 0;
i !=
N; ++
i) {
616 Es = radiation[
i]->getEnergyOfShower(vertex.getE());
617 ts = radiation[
i]->getThetaRMS(vertex.getE(), Es);
621 rms.Fill(
log10(vertex.getE()), (Double_t) radiation[
i]->getID(), ts*ts);
622 rad.Fill(
log10(vertex.getE()), (Double_t) radiation[
i]->getID(), Es);
630 vertex.applyEloss(getRandomDirection(T2), Es);
632 muon.push_back(vertex);
637 if (vertex.getZ() < Zmax && vertex.getRange() > 0.0) {
639 vertex.step(vertex.getRange());
641 muon.push_back(vertex);
650 if (trk != event.mc_trks.end()) {
651 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
655 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
657 const double z0 = muon.begin()->getZ();
658 const double t0 = muon.begin()->getT();
659 const double Z = module->getZ() - module->getX() /
getTanThetaC();
661 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
663 const JVector2D pos = muon.getPosition(Z);
664 const double R = hypot(module->getX() - pos.
getX(),
665 module->getY() - pos.
getY());
667 for (
size_t i = 0;
i != CDF.size(); ++
i) {
669 if (R < CDF[
i].integral.getXmax()) {
679 const double NPE = CDF[
i].integral.getNPE(R) * module->size() * factor * W;
680 const int N = gRandom->Poisson(NPE);
686 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
688 const double R = hypot(pmt->getX() - pos.
getX(),
689 pmt->getY() - pos.
getY());
690 const double theta = pi.constrain(pmt->getTheta());
691 const double phi = pi.constrain(fabs(pmt->getPhi()));
693 npe.push_back(CDF[
i].
function.
getNPE(R, theta, phi) * factor * W);
698 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
700 const double R = hypot(pmt->getX() - pos.
getX(),
701 pmt->getY() - pos.
getY());
702 const double Z = pmt->getZ() - z0;
703 const double theta = pi.constrain(pmt->getTheta());
704 const double phi = pi.constrain(fabs(pmt->getPhi()));
708 job.Fill((
double) (100 + CDF[
i].type), (
double) n0);
712 const double t1 = CDF[
i].function.getTime(R, theta, phi, gRandom->Rndm());
715 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
727 job.Fill((
double) (300 + CDF[
i].type));
731 catch(
const exception& error) {
732 job.Fill((
double) (200 + CDF[
i].type));
739 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
741 const double Es = vertex->getEs();
745 const double z0 = vertex->getZ();
746 const double t0 = vertex->getT();
751 if (writeEMShowers) {
752 origin =
event.mc_trks.size() + 1;
755 int number_of_hits = 0;
758 z0 + maximal_distance);
760 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
762 const double R = hypot(module->getX() - vertex->getX(),
763 module->getY() - vertex->getY());
764 const double Z = module->getZ() - z0 -
DZ;
765 const double D = sqrt(R*R + Z*Z);
766 const double cd = Z /
D;
768 for (
size_t i = 0;
i != CDG.size(); ++
i) {
770 if (D < CDG[
i].integral.getXmax()) {
774 const double NPE = CDG[
i].integral.getNPE(D, cd) * Es * module->size() * factor;
775 const int N = gRandom->Poisson(NPE);
781 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
783 const double R = hypot(pmt->getX() - vertex->getX(),
784 pmt->getY() - vertex->getY());
785 const double Z = pmt->getZ() - z0 -
DZ;
786 const double D = sqrt(R*R + Z*Z);
787 const double cd = Z /
D;
788 const double theta = pi.constrain(pmt->getTheta());
789 const double phi = pi.constrain(fabs(pmt->getPhi()));
791 npe.push_back(CDG[
i].
function.
getNPE(D, cd, theta, phi) * Es * factor);
796 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
798 const double R = hypot(pmt->getX() - vertex->getX(),
799 pmt->getY() - vertex->getY());
800 const double theta = pi.constrain(pmt->getTheta());
801 const double phi = pi.constrain(fabs(pmt->getPhi()));
805 job.Fill((
double) (100 + CDG[
i].type), (
double) n0);
810 const double Z = pmt->getZ() - z0 - dz;
811 const double D = sqrt(R*R + Z*Z);
812 const double cd = Z /
D;
814 const double t1 = CDG[
i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
817 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
826 number_of_hits += n1;
831 job.Fill((
double) (300 + CDG[
i].type));
835 catch(
const exception& error) {
836 job.Fill((
double) (200 + CDG[
i].type));
842 if (writeEMShowers && number_of_hits != 0) {
844 event.mc_trks.push_back(
JTrk_t(origin,
847 track->pos + track->dir * vertex->getZ(),
855 }
else if (track->len > 0.0) {
863 const double z0 = 0.0;
864 const double z1 = z0 + track->len;
865 const double t0 = track->t;
866 const double E = track->E;
872 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
876 const double R = pos.
getX();
881 R > maximal_road_width) {
885 for (
size_t i = 0;
i != CDF.size(); ++
i) {
897 if (R < CDF[
i].integral.getXmax()) {
901 const double NPE = CDF[
i].integral.getNPE(R) * module->size() * factor * W;
902 const int N = gRandom->Poisson(NPE);
912 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
914 const double R = pmt->getX();
915 const double theta = pi.constrain(pmt->getTheta());
916 const double phi = pi.constrain(fabs(pmt->getPhi()));
918 npe.push_back(CDF[
i].
function.
getNPE(R, theta, phi) * factor * W);
923 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
925 const double R = pmt->getX();
926 const double Z = pmt->getZ() - z0;
927 const double theta = pi.constrain(pmt->getTheta());
928 const double phi = pi.constrain(fabs(pmt->getPhi()));
932 job.Fill((
double) (120 + CDF[
i].type), (
double) n0);
936 const double t1 = CDF[
i].function.getTime(R, theta, phi, gRandom->Rndm());
939 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
951 job.Fill((
double) (320 + CDF[
i].type));
955 catch(
const exception& error) {
956 job.Fill((
double) (220 + CDF[
i].type));
963 if (!buffer.empty()) {
982 catch(
const exception& error) {
983 ERROR(error.what() << endl);
986 E =
pythia(track->type, E);
990 const double z0 = 0.0;
991 const double t0 = track->t;
998 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
1002 const double R = pos.
getX();
1003 const double Z = pos.
getZ() - z0 -
DZ;
1004 const double D = sqrt(R*R + Z*Z);
1005 const double cd = Z /
D;
1007 for (
size_t i = 0;
i != CDG.size(); ++
i) {
1009 if (D < CDG[
i].integral.getXmax()) {
1013 const double NPE = CDG[
i].integral.getNPE(D, cd) * E * module->size() * factor;
1014 const int N = gRandom->Poisson(NPE);
1024 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1026 const double R = pmt->getX();
1027 const double Z = pmt->getZ() - z0 -
DZ;
1028 const double D = sqrt(R*R + Z*Z);
1029 const double cd = Z /
D;
1030 const double theta = pi.constrain(pmt->getTheta());
1031 const double phi = pi.constrain(fabs(pmt->getPhi()));
1033 npe.push_back(CDG[
i].
function.
getNPE(D, cd, theta, phi) * E * factor);
1038 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1040 const double theta = pi.constrain(pmt->getTheta());
1041 const double phi = pi.constrain(fabs(pmt->getPhi()));
1045 job.Fill((
double) (140 + CDG[
i].type), (
double) n0);
1050 const double Z = pmt->getZ() - z0 - dz;
1051 const double D = sqrt(R*R + Z*Z);
1052 const double cd = Z /
D;
1054 const double t1 = CDG[
i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
1057 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
1069 job.Fill((
double) (340 + CDG[
i].type));
1073 catch(
const exception& error) {
1074 job.Fill((
double) (240 + CDG[
i].type));
1080 if (!buffer.empty()) {
1091 if (!mc_hits.empty()) {
1095 event.mc_hits.resize(mc_hits.size());
1097 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
1106 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 uint32_t K[64]
static const JRadiationSource_t EErad_t
Data structure for a composite optical module.
then usage $script< input file >[option[primary[working directory]]] nWhere option can be E
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.
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
#define gmake_property(A)
macros 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.
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.
then set_variable PMT_FILE set_variable DAQ_FILE set_variable OUTPUT_FILE set_variable DETECTOR else fatal Wrong number of arguments fi JPrintTree f $DAQ_FILE type
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
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 ...
Vec getOrigin(const JHead &header)
Get origin.
const char * getDate()
Get current local date conform ISO-8601 standard.
direct light from delta-rays
z range($ZMAX-$ZMIN)< $MINIMAL_DZ." fi fi typeset -Z 4 STRING typeset -Z 2 FLOOR JPlot1D -f $
then JCookie sh JDataQuality D $DETECTOR_ID R
then usage $script< input file >[option[primary[working directory]]] nWhere option can be N
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.
then fatal The output file must have the wildcard in the e g root fi 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
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.
struct JSIRENE::@61 getNumberOfPhotoElectrons
Auxiliary data structure for determination of number of photo-electrons.
double getNPE(const Hit &hit)
Get true charge of hit.
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
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.