219{
222
223 string fileDescriptor;
226 JLimit_t& numberOfEvents = inputFile.getLimit();
230 size_t numberOfHits;
231 double factor;
233
234 try {
235
237
247
250
251 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
252
254 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
260 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
261 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
264
266 }
267 catch(const exception &error) {
269 }
270
271
273
274
276
277 const double Zbed = 0.0;
278
281
282 if (fileDescriptor != "") {
283 CDF.push_back(JCDF_t(fileDescriptor, DIRECT_LIGHT_FROM_MUON));
284 CDF.push_back(JCDF_t(fileDescriptor, SCATTERED_LIGHT_FROM_MUON));
285 CDF.push_back(JCDF_t(fileDescriptor, DIRECT_LIGHT_FROM_DELTARAYS));
286 CDF.push_back(JCDF_t(fileDescriptor, SCATTERED_LIGHT_FROM_DELTARAYS));
287
288 CDG.push_back(
JCDG_t(fileDescriptor, DIRECT_LIGHT_FROM_EMSHOWER));
289 CDG.push_back(
JCDG_t(fileDescriptor, SCATTERED_LIGHT_FROM_EMSHOWER));
290 }
291
294
295 for (
size_t i = 0; i !=
CDF.size(); ++i) {
296
297 DEBUG(
"Range CDF["<<
CDF[i].type <<
"] " <<
CDF[i].function.intensity.getXmax() <<
" m" <<
endl);
298
300 }
301
302 for (
size_t i = 0; i !=
CDG.size(); ++i) {
303
304 DEBUG(
"Range CDG["<<
CDG[i].type <<
"] " <<
CDG[i].function.intensity.getXmax() <<
" m" <<
endl);
305
308 }
309
311 }
312
315
316
319 return 0;
320 }
321
323
324 try {
325
326 STATUS(
"Load detector... " << flush);
327
329
331 }
334 }
335
336
337
338 for (JDetector::iterator
module =
detector.begin();
module != detector.end(); ) {
341 else
342 module = detector.erase(module);
343 }
344
347
348 if (true) {
349
350 STATUS(
"Setting up radiation tables... " << flush);
351
356#ifdef RADIATION
361#endif
362
367#ifdef RADIATION
372#endif
373
378#ifdef RADIATION
383#endif
384
389#ifdef RADIATION
394#endif
395
400#ifdef RADIATION
405#endif
406
408
410
415#ifdef RADIATION
420#endif
421
423 }
424
425
427
429
432 }
433
435
436
439
440 try {
441
442 header = inputFile.getHeader();
443
444 JHead buffer(header);
445
447
450 buffer.simul.rbegin()->date =
getDate();
451 buffer.simul.rbegin()->time =
getTime();
452
454
456
459
461
464
466
467 buffer.fixedcan.xcenter += offset.x;
468 buffer.fixedcan.ycenter += offset.y;
469 buffer.fixedcan.zmin += offset.z;
470 buffer.fixedcan.zmax += offset.z;
471
472 } else {
473
474 buffer.fixedcan.xcenter =
cylinder.getX();
475 buffer.fixedcan.ycenter =
cylinder.getY();
476
478
479 buffer.fixedcan.radius = buffer.can.r;
480 buffer.fixedcan.zmin = buffer.can.zmin + offset.z;
481 buffer.fixedcan.zmax = buffer.can.zmax + offset.z;
482 } else {
483
484 buffer.fixedcan.radius =
cylinder.getRadius();
485 buffer.fixedcan.zmin =
cylinder.getZmin();
486 buffer.fixedcan.zmax =
cylinder.getZmax();
487 }
488 }
489
491
493
495
497 }
498
499 copy(buffer, header);
500 }
503 }
504
505 NOTICE(
"Offset applied to true tracks is: " << offset <<
endl);
506
511
512
514
517 }
518
522
523 const double epsilon = 1.0e-6;
525
527
529
531
533
534 Evt* evt = in.next();
535
537 track->pos += offset;
538 }
539
541
542 event.mc_hits.clear();
543
545
548
550
551 if (!
track->is_finalstate()) {
552 continue;
553 }
554
556
557
558
559
560
562
564
566
569
570 if (
Zmax -
Zmin <= parameters.Dmin_m) {
571 continue;
572 }
573
575
577
578 if (
track->dir.z > 0.0)
580 else
581 continue;
582 }
583
586 }
587
588 if (
vertex.getRange() <= parameters.Dmin_m) {
589 continue;
590 }
591
593
595
597 continue;
598 }
599
601
603
605
607
610
611 for (int i = 0; i != N; ++i) {
613 }
614
615
616
618
619 for (
size_t i = 0; i !=
ionization.size(); ++i) {
621 }
622
625
626 if (
vertex.getE() < parameters.Emax_GeV) {
627 if (parameters.Dmax_m < range) {
628 range = parameters.Dmax_m;
629 }
630 }
631
634
636
638
640
642
643 if (step < range) {
644
645 if (
vertex.getE() >= parameters.Emin_GeV) {
646
648
649 for (int i = 0; i != N; ++i) {
650
652
653 if (y < 0.0) {
654
657
659
662
663 break;
664 }
665 }
666 }
667 }
668
670
672
674 }
675
676
677
679
681
683 }
684
685
686
688 event.mc_trks.end(),
690
691 if (
trk != event.mc_trks.end()) {
692 trk->len = (muon.rbegin()->getZ() <
Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
694 }
695
697
698 const double z0 = muon.begin()->getZ();
699 const double t0 = muon.begin()->getT();
700 const double Z = module->getZ() - module->getX() / getTanThetaC();
701
702 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
703
704 const JVector2D pos = muon.getPosition(Z);
707
708 for (
size_t i = 0; i !=
CDF.size(); ++i) {
709
710 if (R <
CDF[i].integral.getXmax()) {
711
712 try {
713
714 double W = 1.0;
715
718 }
719
720 const double NPE =
CDF[i].integral.getNPE(R) *
module->size() * factor * W;
721 const size_t N = getPoisson(NPE);
722
723 if (N != 0) {
724
726
727 for (JModule::const_iterator pmt =
module->begin(); pmt !=
module->end(); ++pmt) {
728
729 const double R =
hypot(pmt->getX() - pos.
getX(),
730 pmt->getY() - pos.
getY());
731 const double theta =
pi.constrain(pmt->getTheta());
732 const double phi =
pi.constrain(fabs(pmt->getPhi()));
733
734 npe.push_back(
CDF[i].function.getNPE(R, theta, phi) * factor * W);
735 }
736
738
739 for (JModule::const_iterator pmt =
module->begin(); pmt !=
module->end(); ++pmt) {
740
741 const double R =
hypot(pmt->getX() - pos.
getX(),
742 pmt->getY() - pos.
getY());
743 const double Z = pmt->getZ() - z0;
744 const double theta =
pi.constrain(pmt->getTheta());
745 const double phi =
pi.constrain(fabs(pmt->getPhi()));
746
748
749 job.Fill((
double) (100 +
CDF[i].type), (
double)
n0);
750
752
753 const double t1 =
CDF[i].function.getTime(R, theta, phi,
gRandom->Rndm());
755
756 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
757 pmt->getID(),
760 t0 + (R * getTanThetaC() + Z) / C + t1,
762
764 }
765 }
766
767 if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
768 job.Fill((
double) (300 +
CDF[i].type));
769 }
770 }
771 }
772 catch(const exception& error) {
773 job.Fill((
double) (200 +
CDF[i].type));
774 }
775 }
776 }
777 }
778 }
779
781
783
784 if (
Es >= parameters.Ecut_GeV) {
785
786 const double z0 =
vertex->getZ();
787 const double t0 =
vertex->getT();
789
791
793 origin =
event.mc_trks.size() + 1;
794 }
795
797
800
801 for (JDetector::const_iterator
module = range.begin();
module != range.end(); ++
module) {
802
805 const double Z = module->getZ() - z0 - DZ;
806 const double D = sqrt(R*R + Z*Z);
807 const double cd = Z / D;
808
809 for (
size_t i = 0; i !=
CDG.size(); ++i) {
810
811 if (D <
CDG[i].integral.getXmax()) {
812
813 try {
814
815 const double NPE =
CDG[i].integral.getNPE(D,
cd) *
Es *
module->size() * factor;
816 const size_t N = getPoisson(NPE);
817
818 if (N != 0) {
819
821
822 for (JModule::const_iterator pmt =
module->begin(); pmt !=
module->end(); ++pmt) {
823
824 const double R =
hypot(pmt->getX() -
vertex->getX(),
825 pmt->getY() -
vertex->getY());
826 const double Z = pmt->getZ() - z0 -
DZ;
827 const double D = sqrt(R*R + Z*Z);
828 const double cd = Z / D;
829 const double theta =
pi.constrain(pmt->getTheta());
830 const double phi =
pi.constrain(fabs(pmt->getPhi()));
831
832 npe.push_back(
CDG[i].function.getNPE(D,
cd, theta, phi) *
Es * factor);
833 }
834
836
837 for (JModule::const_iterator pmt =
module->begin(); pmt !=
module->end(); ++pmt) {
838
839 const double R =
hypot(pmt->getX() -
vertex->getX(),
840 pmt->getY() -
vertex->getY());
841 const double theta =
pi.constrain(pmt->getTheta());
842 const double phi =
pi.constrain(fabs(pmt->getPhi()));
843
845
846 job.Fill((
double) (100 +
CDG[i].type), (
double)
n0);
847
849
851 const double Z = pmt->getZ() - z0 -
dz;
852 const double D = sqrt(R*R + Z*Z);
853 const double cd = Z / D;
854
855 const double t1 =
CDG[i].function.getTime(D,
cd, theta, phi,
gRandom->Rndm());
857
858 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
859 pmt->getID(),
861 origin,
864
866
868 }
869 }
870
871 if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
872 job.Fill((
double) (300 +
CDG[i].type));
873 }
874 }
875 }
876 catch(const exception& error) {
877 job.Fill((
double) (200 +
CDG[i].type));
878 }
879 }
880 }
881 }
882
884
885 event.mc_trks.push_back(
JTrk_t(origin,
892 }
893 }
894 }
895
896 }
else if (
track->len > 0.0) {
897
898
899
900
901
903
904 const double z0 = 0.0;
905 const double z1 = z0 +
track->len;
906 const double t0 =
track->t;
907 const double E =
track->E;
908
910
912
914
916
917 const double R = pos.
getX();
919
920 if (Z < z0 ||
923 continue;
924 }
925
926 for (
size_t i = 0; i !=
CDF.size(); ++i) {
927
928 double W = 1.0;
929
931
934 else
935 continue;
936 }
937
938 if (R <
CDF[i].integral.getXmax()) {
939
940 try {
941
942 const double NPE =
CDF[i].integral.getNPE(R) *
module->size() * factor * W;
943 const size_t N = getPoisson(NPE);
944
945 if (N != 0) {
946
947 buffer = *module;
948
950
952
953 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
954
955 const double R = pmt->getX();
956 const double theta =
pi.constrain(pmt->getTheta());
957 const double phi =
pi.constrain(fabs(pmt->getPhi()));
958
959 npe.push_back(
CDF[i].function.getNPE(R, theta, phi) * factor * W);
960 }
961
963
964 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
965
966 const double R = pmt->getX();
967 const double Z = pmt->getZ() - z0;
968 const double theta =
pi.constrain(pmt->getTheta());
969 const double phi =
pi.constrain(fabs(pmt->getPhi()));
970
971 size_t n0 = min(ns[
distance(buffer.cbegin(),pmt)], parameters.Nmax_PMT);
972
973 job.Fill((
double) (120 +
CDF[i].type), (
double)
n0);
974
976
977 const double t1 =
CDF[i].function.getTime(R, theta, phi,
gRandom->Rndm());
979
980 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
981 pmt->getID(),
984 t0 + (R * getTanThetaC() + Z) / C + t1,
986
988 }
989 }
990
991 if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
992 job.Fill((
double) (320 +
CDF[i].type));
993 }
994 }
995 }
996 catch(const exception& error) {
997 job.Fill((
double) (220 +
CDF[i].type));
998 }
999 }
1000 }
1001 }
1002
1003 if (!buffer.empty()) {
1005 }
1006
1008
1010
1011
1012
1013
1014
1016
1017 double E =
track->E;
1018
1019 try {
1021 }
1022 catch(const exception& error) {
1024 }
1025
1027
1029
1030 const double z0 = 0.0;
1031 const double t0 =
track->t;
1032 const double DZ =
geanz.getMaximum(E);
1033
1035
1037
1038 for (JDetector::const_iterator
module =
detector.begin();
module != detector.end(); ++
module) {
1039
1041
1042 const double R = pos.
getX();
1043 const double Z = pos.
getZ() - z0 -
DZ;
1044 const double D = sqrt(R*R + Z*Z);
1045 const double cd = Z / D;
1046
1047 for (
size_t i = 0; i !=
CDG.size(); ++i) {
1048
1049 if (D <
CDG[i].integral.getXmax()) {
1050
1051 try {
1052
1053 const double NPE =
CDG[i].integral.getNPE(D,
cd) * E *
module->size() * factor;
1054 const size_t N = getPoisson(NPE);
1055
1056 if (N != 0) {
1057
1058 buffer = *module;
1059
1061
1063
1064 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1065
1066 const double R = pmt->getX();
1067 const double Z = pmt->getZ() - z0 -
DZ;
1068 const double D = sqrt(R*R + Z*Z);
1069 const double cd = Z / D;
1070 const double theta =
pi.constrain(pmt->getTheta());
1071 const double phi =
pi.constrain(fabs(pmt->getPhi()));
1072
1073 npe.push_back(
CDG[i].function.getNPE(D,
cd, theta, phi) * E * factor);
1074 }
1075
1077
1078 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
1079
1080 const double theta =
pi.constrain(pmt->getTheta());
1081 const double phi =
pi.constrain(fabs(pmt->getPhi()));
1082
1083 size_t n0 = min(ns[
distance(buffer.cbegin(),pmt)], parameters.Nmax_PMT);
1084
1085 job.Fill((
double) (140 +
CDG[i].type), (
double)
n0);
1086
1088
1090 const double Z = pmt->getZ() - z0 -
dz;
1091 const double D = sqrt(R*R + Z*Z);
1092 const double cd = Z / D;
1093
1094 const double t1 =
CDG[i].function.getTime(D,
cd, theta, phi,
gRandom->Rndm());
1096
1097 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
1098 pmt->getID(),
1101 t0 + (
dz + D * getIndexOfRefraction()) / C + t1,
1103
1105 }
1106 }
1107
1108 if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
1109 job.Fill((
double) (340 +
CDG[i].type));
1110 }
1111 }
1112 }
1113 catch(const exception& error) {
1114 job.Fill((
double) (240 +
CDG[i].type));
1115 }
1116 }
1117 }
1118 }
1119
1120 if (!buffer.empty()) {
1122 }
1123
1124 } else {
1126 }
1127 }
1128 }
1129 }
1130
1131 if (!mc_hits.empty()) {
1132
1133 mc_hits.
merge(parameters.Tmax_ns);
1134
1135 event.mc_hits.resize(mc_hits.size());
1136
1137 copy(mc_hits.begin(), mc_hits.end(), event.mc_hits.begin());
1138 }
1139
1141
1144 }
1145
1146 if (event.mc_hits.size() >= numberOfHits) {
1147
1149
1151 }
1152 }
1154
1160
1162
1164
1166}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define gmake_property(A)
macros to convert (template) parameter to JPropertiesElement object
int numberOfBins
number of bins for average CDF integral of optical module
double safetyFactor
safety factor for average CDF integral of optical module
static const char *const APPLICATION_JSIRENE
detector simulation
std::vector< JAANET::simul > simul
JAANET::coord_origin coord_origin
std::vector< JAANET::detector > detector
JAANET::fixedcan fixedcan
Detector subset without binary search functionality.
Data structure for a composite optical module.
void transform(const JRotation3D &R, const JVector3D &pos)
Transformation of geometry (see method JGEOMETRY3D::JPosition3D::transform(const JRotation3D&,...
Utility class to parse parameter values.
Auxiliary class for CPU timing and usage.
unsigned long long usec_ucpu
Data structure for vector in two dimensions.
double getY() const
Get y position.
double getX() const
Get x position.
Data structure for position in three dimensions.
double getZ() const
Get z position.
double getX() const
Get x position.
Template definition of a multi-dimensional oscillation probability interpolation table.
Auxiliary class for the calculation of the muon radiative cross sections.
static constexpr radiation_type GNrad_t
static constexpr radiation_type Brems_t
static constexpr radiation_type EErad_t
JAxis3D getAxis(const Trk &track)
Get axis.
Vec getOrigin(const JHead &header)
Get origin.
double getKineticEnergy(const Trk &trk)
Get track kinetic energy.
JTransformation3D getTransformation(const Trk &track)
Get transformation.
bool has_neutrino(const Evt &evt)
Test whether given event has an incoming neutrino.
bool is_neutrino(const Trk &track)
Test whether given track is a neutrino.
void copy(const Head &from, JHead &to)
Copy header from from to to.
JPosition3D getPosition(const Vec &pos)
Get position.
bool is_muon(const Trk &track)
Test whether given track is a (anti-)muon.
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino.
bool is_tau(const Trk &track)
Test whether given track is a (anti-)tau.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
const char * getGITVersion()
Get GIT version.
bool is_deltarays(const int pdf)
Test if given PDF type corresponds to Cherenkov light from delta-rays.
static const double DENSITY_SEA_WATER
Fixed environment values.
static const JGeanz geanz(1.85, 0.62, 0.54)
Function object for longitudinal EM-shower profile.
double getThetaMCS(const double E, const double x, const double X0, const double M, const double Q)
Get multiple Coulomb scattering angle.
double getIndexOfRefraction()
Get average index of refraction of water corresponding to group velocity.
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.
bool is_scattered(const int pdf)
Test if given PDF type corresponds to scattered light.
double getTanThetaC()
Get average tangent of Cherenkov angle of water corresponding to group velocity.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
JHitType_t getHitType(const JPDFType_t pdf, const bool shower=false)
Get hit type corresponding to given PDF type.
static const JPythia pythia
Function object for relative light yield as a function of GEANT particle code.
const struct JSIRENE::number_of_photo_electrons_type getNumberOfPhotoElectrons
const char * getTime()
Get current local time conform ISO-8601 standard.
const char * getDate()
Get current local date conform ISO-8601 standard.
const char *const energy_lost_in_can
The Evt class respresent a Monte Carlo (MC) event as well as an offline event.
std::vector< Trk > mc_trks
MC: list of MC truth tracks.
The Head class reflects the header of Monte-Carlo event files, which consists of keys (also referred ...
static const JPDB & getInstance()
Get particle data book.
Generator for simulation.
Auxiliary class for PMT parameters including threshold.
Template definition of random value generator.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
static double getEnergyLossFromMuon(const double E, const JEnergyRange T_GeV=JEnergyRange(TMIN_GEV, TMAX_GEV))
Equivalent EM-shower energy loss due to delta-rays per unit muon track length in sea water.
static double getTmin()
Get minimum delta-ray kinetic energy.
static constexpr double TMAX_GEV
Maximum allowed delta-ray kinetic energy [GeV].
static double getEnergyLossFromTau(const double E, const JEnergyRange T_GeV=JEnergyRange(TMIN_GEV, TMAX_GEV))
Equivalent EM-shower energy loss due to delta-rays per unit tau track length in sea water.
static constexpr atom_type Cl
static constexpr atom_type H
static constexpr atom_type O
static constexpr atom_type Na
Auxiliary class to set-up Hit.
Auxiliary data structure for list of hits with hit merging capability.
void merge(const double Tmax_ns)
Merge hits on same PMT that are within given time window.
Auxiliary class to set-up Trk.
Vertex of energy loss of muon.
Auxiliary class for defining the range of iterations of objects.
static counter_type max()
Get maximum counter value.
Auxiliary data structure to list files in directory.
The Vec class is a straightforward 3-d vector, which also works in pyroot.