203 string fileDescriptor;
230 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
233 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
236 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
238 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
239 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
240 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
246 catch(
const exception &error) {
247 FATAL(error.what() << endl);
251 gRandom->SetSeed(seed);
254 const JMeta meta(argc, argv);
256 const double Zbed = 0.0;
270 double maximal_road_width = 0.0;
271 double maximal_distance = 0.0;
273 for (
size_t i = 0;
i != CDF.size(); ++
i) {
275 DEBUG(
"Range CDF["<< CDF[
i].
type <<
"] " << CDF[
i].
function.intensity.getXmax() <<
" m" << endl);
277 maximal_road_width = max(maximal_road_width, CDF[
i].
function.intensity.getXmax());
280 for (
size_t i = 0;
i != CDG.size(); ++
i) {
282 DEBUG(
"Range CDG["<< CDG[
i].
type <<
"] " << CDG[
i].
function.intensity.getXmax() <<
" m" << endl);
285 maximal_road_width = max(maximal_road_width, CDG[
i].
function.intensity.getXmax());
288 maximal_distance = max(maximal_distance, CDG[
i].
function.intensity.getXmax());
291 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
292 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
295 if (detectorFile ==
"" || inputFile.empty()) {
296 STATUS(
"Nothing to be done." << endl);
304 STATUS(
"Load detector... " << flush);
316 for (JDetector::iterator module =
detector.begin(); module !=
detector.end(); ) {
317 if (!module->empty())
328 STATUS(
"Setting up radiation tables... " << flush);
330 const JRadiation hydrogen ( 1.0, 1.0, 40, 0.01, 0.1, 0.1);
331 const JRadiation oxygen ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
332 const JRadiation chlorine (17.0, 35.5, 40, 0.01, 0.1, 0.1);
333 const JRadiation sodium (11.0, 23.0, 40, 0.01, 0.1, 0.1);
335 const JRadiation calcium (20.0, 40.0, 40, 0.01, 0.1, 0.1);
336 const JRadiation magnesium(12.0, 24.3, 40, 0.01, 0.1, 0.1);
337 const JRadiation potassium(19.0, 39.0, 40, 0.01, 0.1, 0.1);
338 const JRadiation sulphur (16.0, 32.0, 40, 0.01, 0.1, 0.1);
406 if (cylinder.getZmin() < Zbed) {
407 cylinder.setZmin(Zbed);
410 NOTICE(
"Light generation volume: " << cylinder << endl);
418 header = inputFile.getHeader();
420 JHead buffer(header);
426 buffer.simul.rbegin()->date =
getDate();
427 buffer.simul.rbegin()->time =
getTime();
429 buffer.push(&JHead::simul);
434 buffer.detector.rbegin()->filename = detectorFile;
438 offset +=
Vec(cylinder.getX(), cylinder.getY(), 0.0);
441 if (buffer.is_valid(&JHead::fixedcan)) {
443 buffer.fixedcan.xcenter += offset.x;
444 buffer.fixedcan.ycenter += offset.y;
445 buffer.fixedcan.zmin += offset.z;
446 buffer.fixedcan.zmax += offset.z;
450 buffer.fixedcan.xcenter = cylinder.getX();
451 buffer.fixedcan.ycenter = cylinder.getY();
453 if (buffer.is_valid(&JHead::can)) {
455 buffer.fixedcan.radius = buffer.can.r;
456 buffer.fixedcan.zmin = buffer.can.zmin + offset.z;
457 buffer.fixedcan.zmax = buffer.can.zmax + offset.z;
460 buffer.fixedcan.radius = cylinder.getRadius();
461 buffer.fixedcan.zmin = cylinder.getZmin();
462 buffer.fixedcan.zmax = cylinder.getZmax();
466 buffer.push(&JHead::fixedcan);
468 if (buffer.is_valid(&JHead::coord_origin)) {
472 buffer.push(&JHead::coord_origin);
475 copy(buffer, header);
481 NOTICE(
"Offset applied to true tracks is: " << offset << endl);
483 TH1D job(
"job", NULL, 400, 0.5, 400.5);
484 TProfile cpu(
"cpu", NULL, 16, 0.0, 8.0);
485 TProfile2D rms(
"rms", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
486 TProfile2D rad(
"rad", NULL, 16, 0.0, 8.0, 201, -0.5, 200.5);
506 STATUS(
"event: " << setw(10) <<
in.getCounter() <<
'\r');
DEBUG(endl);
510 Evt* evt =
in.next();
513 track->pos += offset;
518 event.mc_hits.clear();
527 if (!track->is_finalstate()) {
543 double Zmin = intersection.first;
544 double Zmax = intersection.second;
550 JVertex vertex(0.0, track->t, track->E);
552 if (track->pos.z < Zbed) {
554 if (track->dir.z > 0.0)
555 vertex.step(
gRock, (Zbed - track->pos.z) / track->dir.z);
560 if (vertex.getZ() < Zmin) {
561 vertex.step(
gWater, Zmin - vertex.getZ());
570 const JDetectorSubset_t subdetector(
detector,
getAxis(*track), maximal_road_width);
572 if (subdetector.empty()) {
580 while (vertex.getE() >=
parameters.Emin_GeV && vertex.getZ() < Zmax) {
582 const int N = radiation.size();
587 for (
int i = 0;
i !=
N; ++
i) {
588 ls += li[
i] = radiation[
i]->getInverseInteractionLength(vertex.getE());
593 for (
size_t i = 0;
i != ionization.size(); ++
i) {
594 As += ionization[
i]->getA(vertex.getE());
597 double step = gRandom->Exp(1.0) / ls;
598 double range = vertex.getRange(As);
606 double ts =
getThetaMCS(vertex.getE(), min(step,range));
609 rms.Fill(
log10(vertex.getE()), (Double_t) 0, ts*ts);
611 vertex.getDirection() += getRandomDirection(T2/3.0);
613 vertex.step(As, min(step,range));
621 double y = gRandom->Uniform(ls);
623 for (
int i = 0;
i !=
N; ++
i) {
629 Es = radiation[
i]->getEnergyOfShower(vertex.getE());
630 ts = radiation[
i]->getThetaRMS(vertex.getE(), Es);
634 rms.Fill(
log10(vertex.getE()), (Double_t) radiation[
i]->getID(), ts*ts);
635 rad.Fill(
log10(vertex.getE()), (Double_t) radiation[
i]->getID(), Es);
643 vertex.applyEloss(getRandomDirection(T2), Es);
645 muon.push_back(vertex);
650 if (vertex.getZ() < Zmax && vertex.getRange() > 0.0) {
652 vertex.step(vertex.getRange());
654 muon.push_back(vertex);
663 if (trk != event.mc_trks.end()) {
664 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
668 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
670 const double z0 = muon.begin()->getZ();
671 const double t0 = muon.begin()->getT();
672 const double Z = module->getZ() - module->getX() /
getTanThetaC();
674 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
676 const JVector2D pos = muon.getPosition(Z);
677 const double R = hypot(module->getX() - pos.
getX(),
678 module->getY() - pos.
getY());
680 for (
size_t i = 0;
i != CDF.size(); ++
i) {
682 if (R < CDF[
i].integral.getXmax()) {
692 const double NPE = CDF[
i].integral.getNPE(R) * module->size() * factor * W;
693 const int N = gRandom->Poisson(NPE);
699 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
701 const double R = hypot(pmt->getX() - pos.
getX(),
702 pmt->getY() - pos.
getY());
703 const double theta = pi.constrain(pmt->getTheta());
704 const double phi = pi.constrain(fabs(pmt->getPhi()));
706 npe.push_back(CDF[
i].
function.
getNPE(R, theta, phi) * factor * W);
711 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
713 const double R = hypot(pmt->getX() - pos.
getX(),
714 pmt->getY() - pos.
getY());
715 const double Z = pmt->getZ() - z0;
716 const double theta = pi.constrain(pmt->getTheta());
717 const double phi = pi.constrain(fabs(pmt->getPhi()));
721 job.Fill((
double) (100 + CDF[
i].type), (
double) n0);
725 const double t1 = CDF[
i].function.getTime(R, theta, phi, gRandom->Rndm());
728 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
740 job.Fill((
double) (300 + CDF[
i].type));
744 catch(
const exception& error) {
745 job.Fill((
double) (200 + CDF[
i].type));
752 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
754 const double Es = vertex->getEs();
758 const double z0 = vertex->getZ();
759 const double t0 = vertex->getT();
764 if (writeEMShowers) {
765 origin =
event.mc_trks.size() + 1;
768 int number_of_hits = 0;
771 z0 + maximal_distance);
773 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
775 const double R = hypot(module->getX() - vertex->getX(),
776 module->getY() - vertex->getY());
777 const double Z = module->getZ() - z0 -
DZ;
778 const double D = sqrt(R*R + Z*Z);
779 const double cd = Z /
D;
781 for (
size_t i = 0;
i != CDG.size(); ++
i) {
783 if (D < CDG[
i].integral.getXmax()) {
787 const double NPE = CDG[
i].integral.getNPE(D, cd) * Es * module->size() * factor;
788 const int N = gRandom->Poisson(NPE);
794 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
796 const double R = hypot(pmt->getX() - vertex->getX(),
797 pmt->getY() - vertex->getY());
798 const double Z = pmt->getZ() - z0 -
DZ;
799 const double D = sqrt(R*R + Z*Z);
800 const double cd = Z /
D;
801 const double theta = pi.constrain(pmt->getTheta());
802 const double phi = pi.constrain(fabs(pmt->getPhi()));
804 npe.push_back(CDG[
i].
function.
getNPE(D, cd, theta, phi) * Es * factor);
809 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
811 const double R = hypot(pmt->getX() - vertex->getX(),
812 pmt->getY() - vertex->getY());
813 const double theta = pi.constrain(pmt->getTheta());
814 const double phi = pi.constrain(fabs(pmt->getPhi()));
818 job.Fill((
double) (100 + CDG[
i].type), (
double) n0);
823 const double Z = pmt->getZ() - z0 - dz;
824 const double D = sqrt(R*R + Z*Z);
825 const double cd = Z /
D;
827 const double t1 = CDG[
i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
830 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
839 number_of_hits += n1;
844 job.Fill((
double) (300 + CDG[
i].type));
848 catch(
const exception& error) {
849 job.Fill((
double) (200 + CDG[
i].type));
855 if (writeEMShowers && number_of_hits != 0) {
857 event.mc_trks.push_back(
JTrk_t(origin,
860 track->pos + track->dir * vertex->getZ(),
868 }
else if (track->len > 0.0) {
876 const double z0 = 0.0;
877 const double z1 = z0 + track->len;
878 const double t0 = track->t;
879 const double E = track->E;
885 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
889 const double R = pos.
getX();
894 R > maximal_road_width) {
898 for (
size_t i = 0;
i != CDF.size(); ++
i) {
910 if (R < CDF[
i].integral.getXmax()) {
914 const double NPE = CDF[
i].integral.getNPE(R) * module->size() * factor * W;
915 const int N = gRandom->Poisson(NPE);
925 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
927 const double R = pmt->getX();
928 const double theta = pi.constrain(pmt->getTheta());
929 const double phi = pi.constrain(fabs(pmt->getPhi()));
931 npe.push_back(CDF[
i].
function.
getNPE(R, theta, phi) * factor * W);
936 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
938 const double R = pmt->getX();
939 const double Z = pmt->getZ() - z0;
940 const double theta = pi.constrain(pmt->getTheta());
941 const double phi = pi.constrain(fabs(pmt->getPhi()));
945 job.Fill((
double) (120 + CDF[
i].type), (
double) n0);
949 const double t1 = CDF[
i].function.getTime(R, theta, phi, gRandom->Rndm());
952 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
964 job.Fill((
double) (320 + CDF[
i].type));
968 catch(
const exception& error) {
969 job.Fill((
double) (220 + CDF[
i].type));
976 if (!buffer.empty()) {
995 catch(
const exception& error) {
996 ERROR(error.what() << endl);
999 E =
pythia(track->type, E);
1003 const double z0 = 0.0;
1004 const double t0 = track->t;
1011 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
1015 const double R = pos.
getX();
1016 const double Z = pos.
getZ() - z0 -
DZ;
1017 const double D = sqrt(R*R + Z*Z);
1018 const double cd = Z /
D;
1020 for (
size_t i = 0;
i != CDG.size(); ++
i) {
1022 if (D < CDG[
i].integral.getXmax()) {
1026 const double NPE = CDG[
i].integral.getNPE(D, cd) * E * module->size() * factor;
1027 const int N = gRandom->Poisson(NPE);
1037 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1039 const double R = pmt->getX();
1040 const double Z = pmt->getZ() - z0 -
DZ;
1041 const double D = sqrt(R*R + Z*Z);
1042 const double cd = Z /
D;
1043 const double theta = pi.constrain(pmt->getTheta());
1044 const double phi = pi.constrain(fabs(pmt->getPhi()));
1046 npe.push_back(CDG[
i].
function.
getNPE(D, cd, theta, phi) * E * factor);
1051 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1053 const double theta = pi.constrain(pmt->getTheta());
1054 const double phi = pi.constrain(fabs(pmt->getPhi()));
1058 job.Fill((
double) (140 + CDG[
i].type), (
double) n0);
1063 const double Z = pmt->getZ() - z0 - dz;
1064 const double D = sqrt(R*R + Z*Z);
1065 const double cd = Z /
D;
1067 const double t1 = CDG[
i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
1070 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
1082 job.Fill((
double) (340 + CDG[
i].type));
1086 catch(
const exception& error) {
1087 job.Fill((
double) (240 + CDG[
i].type));
1093 if (!buffer.empty()) {
1104 if (!mc_hits.empty()) {
1108 event.mc_hits.resize(mc_hits.size());
1110 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
1119 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.
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.
double getDeltaRaysFromMuon(const double E, const JRange< double > T_GeV=JRange< double >(DELTARAY_TMIN, DELTARAY_TMAX))
Equivalent EM-shower energy due to delta-rays per unit muon track length.
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.
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
double getKineticEnergy(const Trk &trk)
Get track kinetic energy.
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&)).
struct JSIRENE::@62 getNumberOfPhotoElectrons
Auxiliary data structure for determination of number of photo-electrons.
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.
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.
double getDeltaRaysFromTau(const double E, const JRange< double > T_GeV=JRange< double >(DELTARAY_TMIN, DELTARAY_TMAX))
Equivalent EM-shower energy due to delta-rays per unit tau track length.
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.