176 string fileDescriptor;
179 JLimit_t& numberOfEvents = inputFile.getLimit();
181 double Ecut_GeV = 0.1;
182 double Emin_GeV = 1.0;
184 double Tmax_ns = 0.1;
185 int Nmax_npe = numeric_limits<int>::max();
202 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
205 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
208 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
210 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
211 zap[
'k'] =
make_field(keep,
"keep position of tracks");
212 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
213 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
219 catch(
const exception &error) {
220 FATAL(error.what() << endl);
224 gRandom->SetSeed(seed);
227 const JMeta meta(argc, argv);
229 const double Zbed = 0.0;
243 double maximal_road_width = 0.0;
244 double maximal_distance = 0.0;
246 for (
size_t i = 0; i != CDF.size(); ++i) {
248 DEBUG(
"Range CDF["<< CDF[i].type <<
"] " << CDF[i].
function.intensity.getXmax() <<
" m" << endl);
250 maximal_road_width = max(maximal_road_width, CDF[i].
function.intensity.getXmax());
253 for (
size_t i = 0; i != CDG.size(); ++i) {
255 DEBUG(
"Range CDG["<< CDG[i].type <<
"] " << CDG[i].
function.intensity.getXmax() <<
" m" << endl);
258 maximal_road_width = max(maximal_road_width, CDG[i].
function.intensity.getXmax());
261 maximal_distance = max(maximal_distance, CDG[i].
function.intensity.getXmax());
264 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
265 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
268 if (detectorFile ==
"" || inputFile.empty()) {
269 STATUS(
"Nothing to be done." << endl);
277 STATUS(
"Load detector... " << flush);
292 STATUS(
"Setting up radiation tables... " << flush);
294 const JRadiation hydrogen( 1.0, 1.0, 40, 0.01, 0.1, 0.1);
295 const JRadiation oxygen ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
296 const JRadiation chlorine(17.0, 35.0, 40, 0.01, 0.1, 0.1);
327 header = inputFile.getHeader();
329 JHead buffer(header);
331 center = get<Vec>(buffer);
335 buffer.simul.rbegin()->program =
"JSirene";
337 buffer.simul.rbegin()->date =
getDate();
338 buffer.simul.rbegin()->time =
getTime();
340 buffer.push(&JHead::simul);
345 buffer.can.zmin += center.z;
346 buffer.can.zmax += center.z;
348 buffer.push(&JHead::coord_origin);
349 buffer.push(&JHead::can);
354 center +=
Vec(circle.getX(), circle.getY(), 0.0);
356 copy(buffer, header);
363 NOTICE(
"Offset applied to true tracks is: " << center << endl);
365 NOTICE(
"No offset applied to true tracks." << endl);
371 if (cylinder.getZmin() < Zbed) {
372 cylinder.setZmin(Zbed);
375 NOTICE(
"Ligth generation volume: " << cylinder << endl);
377 TProfile cpu(
"cpu", NULL, 14, 1.0, 8.0);
378 TH1D job(
"job", NULL, 400, 0.5, 400.5);
396 STATUS(
"event: " << setw(10) << in.getCounter() <<
'\r');
DEBUG(endl);
400 Evt* evt = in.next();
404 track->pos += center;
410 event.mc_hits.clear();
431 double Zmin = intersection.first;
432 double Zmax = intersection.second;
434 if (Zmax - Zmin <= Dmin_m) {
438 JVertex vertex(0.0, track->t, track->E);
440 if (track->pos.z < Zbed) {
442 if (track->dir.z > 0.0)
443 vertex.step(
gRock, (Zbed - track->pos.z) / track->dir.z);
448 if (vertex.getZ() < Zmin) {
449 vertex.step(
gWater, Zmin - vertex.getZ());
452 if (vertex.getRange() <= Dmin_m) {
460 if (subdetector.empty()) {
468 while (vertex.getE() >= Emin_GeV && vertex.getZ() < Zmax) {
470 const int N = radiation.size();
475 for (
int i = 0; i != N; ++i) {
476 ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.getE());
479 const double ds = min(gRandom->Exp(1.0) /
ls, vertex.getRange());
483 if (vertex.getE() >= Emin_GeV) {
486 double y = gRandom->Uniform(
ls);
488 for (
int i = 0; i != N; ++i) {
493 Es = radiation[i]->getEnergyOfShower(vertex.getE());
498 vertex.applyEloss(Es);
500 if (Es >= Ecut_GeV) {
501 muon.push_back(vertex);
508 if (vertex.getE() < Emin_GeV && vertex.getRange() > 0.0) {
510 vertex.step(vertex.getRange());
512 muon.push_back(vertex);
521 if (trk != event.mc_trks.end()) {
522 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
526 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
528 const double z0 = muon.begin()->getZ();
529 const double t0 = muon.begin()->getT();
530 const double R = module->getX();
533 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
535 for (
size_t i = 0; i != CDF.size(); ++i) {
537 if (R < CDF[i].integral.getXmax()) {
547 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
548 const int N = gRandom->Poisson(NPE);
554 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
556 const double R = pmt->getX();
557 const double Z = pmt->getZ() - z0;
558 const double theta = pmt->getTheta();
559 const double phi = fabs(pmt->getPhi());
561 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
567 job.Fill((
double) (100 + CDF[i].type), (
double) n0);
571 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
574 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
586 job.Fill((
double) (300 + CDF[i].type));
590 catch(
const exception& error) {
591 job.Fill((
double) (200 + CDF[i].type));
598 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
600 const double z0 = vertex->getZ();
601 const double t0 = vertex->getT();
602 const double Es = vertex->getEs();
604 int origin = track->id;
606 if (writeEMShowers) {
607 origin =
event.mc_trks.size() + 1;
610 int number_of_hits = 0;
612 JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
613 z0 + maximal_distance);
615 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
618 const double R = module->getX();
619 const double Z = module->getZ() - z0 - dz;
620 const double D = sqrt(R*R + Z*Z);
621 const double cd = Z / D;
623 for (
size_t i = 0; i != CDG.size(); ++i) {
625 if (D < CDG[i].integral.getXmax()) {
629 const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
630 const int N = gRandom->Poisson(NPE);
636 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
639 const double R = pmt->getX();
640 const double Z = pmt->getZ() - z0 - dz;
641 const double theta = pmt->getTheta();
642 const double phi = fabs(pmt->getPhi());
643 const double D = sqrt(R*R + Z*Z);
644 const double cd = Z / D;
646 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor;
652 job.Fill((
double) (100 + CDG[i].type), (
double) n0);
657 const double Z = pmt->getZ() - z0 - dz;
658 const double D = sqrt(R*R + Z*Z);
659 const double cd = Z / D;
661 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
664 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
673 number_of_hits += n1;
678 job.Fill((
double) (300 + CDG[i].type));
682 catch(
const exception& error) {
683 job.Fill((
double) (200 + CDG[i].type));
689 if (writeEMShowers && number_of_hits != 0) {
691 event.mc_trks.push_back(
JTrk_t(origin,
694 track->pos + track->dir * vertex->getZ(),
701 }
else if (
is_tau(*track)) {
709 const double z0 = 0.0;
710 const double z1 = z0 + track->len;
711 const double t0 = track->t;
712 const double E = track->E;
718 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
722 const double R = pos.
getX();
727 R > maximal_road_width) {
731 for (
size_t i = 0; i != CDF.size(); ++i) {
733 if (R < CDF[i].integral.getXmax()) {
743 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
744 const int N = gRandom->Poisson(NPE);
754 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
756 const double R = pmt->getX();
757 const double Z = pmt->getZ() - z0;
758 const double theta = pmt->getTheta();
759 const double phi = fabs(pmt->getPhi());
761 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
767 job.Fill((
double) (120 + CDF[i].type), (
double) n0);
771 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
774 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
786 job.Fill((
double) (320 + CDF[i].type));
790 catch(
const exception& error) {
791 job.Fill((
double) (220 + CDF[i].type));
798 if (!buffer.empty()) {
817 catch(
const exception& error) {
818 ERROR(error.what() << endl);
821 E =
pythia(track->type, E);
823 if (E < Ecut_GeV || cylinder.getDistance(
getPosition(*track)) > Dmin_m) {
827 const double z0 = 0.0;
828 const double t0 = track->t;
834 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
839 const double R = pos.
getX();
840 const double Z = pos.
getZ() - z0 - dz;
841 const double D = sqrt(R*R + Z*Z);
842 const double cd = Z / D;
844 if (D > maximal_distance) {
848 for (
size_t i = 0; i != CDG.size(); ++i) {
850 if (D < CDG[i].integral.getXmax()) {
854 const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
855 const int N = gRandom->Poisson(NPE);
865 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
868 const double R = pmt->getX();
869 const double Z = pmt->getZ() - z0 - dz;
870 const double theta = pmt->getTheta();
871 const double phi = fabs(pmt->getPhi());
872 const double D = sqrt(R*R + Z*Z);
873 const double cd = Z / D;
875 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * E * factor;
881 job.Fill((
double) (140 + CDG[i].type), (
double) n0);
886 const double Z = pmt->getZ() - z0 - dz;
887 const double D = sqrt(R*R + Z*Z);
888 const double cd = Z / D;
890 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
893 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
905 job.Fill((
double) (340 + CDG[i].type));
909 catch(
const exception& error) {
910 job.Fill((
double) (240 + CDG[i].type));
916 if (!buffer.empty()) {
927 if (!mc_hits.empty()) {
929 mc_hits.
merge(Tmax_ns);
931 event.mc_hits.resize(mc_hits.size());
933 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
942 if (event.mc_hits.size() >= numberOfHits) {