13 #include "evt/Head.hh"
81 const int NUMBER_OF_BINS = 200;
82 const double SAFETY_FACTOR = 1.7;
88 template<
class function_type,
97 JABC(
const std::string& file_descriptor,
const JPDFType_t type)
101 const std::string file_name =
getFilename(file_descriptor, this->type);
103 STATUS(
"loading input from file " << file_name <<
"... " << flush);
106 function.load(file_name.c_str());
112 integral = integral_type(
function, NUMBER_OF_BINS, SAFETY_FACTOR);
118 function_type
function;
119 integral_type integral;
123 typedef JABC<JCDF4D_t, JCDF1D_t> JCDF_t;
124 typedef JABC<JCDF5D_t, JCDF2D_t> JCDG_t;
169 int main(
int argc,
char **argv)
174 string fileDescriptor;
177 JLimit_t& numberOfEvents = inputFile.getLimit();
179 double Ecut_GeV = 0.1;
180 double Emin_GeV = 1.0;
182 double Tmax_ns = 0.1;
183 int Nmax_npe = numeric_limits<int>::max();
200 JParser<> zap(
"Main program to simulate detector response to muons and showers.");
203 zap[
'F'] =
make_field(fileDescriptor,
"file name descriptor for CDF tables");
206 zap[
'n'] =
make_field(numberOfEvents) = JLimit::max();
208 zap[
's'] =
make_field(writeEMShowers,
"store generated EM showers in event");
209 zap[
'k'] =
make_field(keep,
"keep position of tracks");
210 zap[
'N'] =
make_field(numberOfHits,
"minimum number of hits to output event") = 1;
211 zap[
'U'] =
make_field(factor,
"scaling factor applied to light yields") = 1.0;
217 catch(
const exception &error) {
218 FATAL(error.what() << endl);
222 gRandom->SetSeed(seed);
225 const JMeta meta(argc, argv);
227 const double Zbed = 0.0;
241 double maximal_road_width = 0.0;
242 double maximal_distance = 0.0;
244 for (
size_t i = 0; i != CDF.size(); ++i) {
246 DEBUG(
"Range CDF["<< CDF[i].type <<
"] " << CDF[i].
function.intensity.getXmax() <<
" m" << endl);
248 maximal_road_width = max(maximal_road_width, CDF[i].
function.intensity.getXmax());
251 for (
size_t i = 0; i != CDG.size(); ++i) {
253 DEBUG(
"Range CDG["<< CDG[i].type <<
"] " << CDG[i].
function.intensity.getXmax() <<
" m" << endl);
256 maximal_road_width = max(maximal_road_width, CDG[i].
function.intensity.getXmax());
259 maximal_distance = max(maximal_distance, CDG[i].
function.intensity.getXmax());
262 NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
263 NOTICE(
"Maximal distance [m] " << maximal_distance << endl);
266 if (detectorFile ==
"" || inputFile.empty()) {
267 STATUS(
"Nothing to be done." << endl);
275 STATUS(
"Load detector... " << flush);
290 STATUS(
"Setting up radiation tables... " << flush);
292 const JRadiation hydrogen( 1.0, 1.0, 40, 0.01, 0.1, 0.1);
293 const JRadiation oxygen ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
294 const JRadiation chlorine(17.0, 35.0, 40, 0.01, 0.1, 0.1);
325 header = inputFile.getHeader();
327 JHead buffer(header);
331 buffer.
simul.rbegin()->program =
"JSirene";
336 buffer.
push(&JHead::simul);
338 center = get<Vec>(buffer);
346 buffer.
push(&JHead::coord_origin);
347 buffer.
push(&JHead::can);
352 center += Vec(circle.getX(), circle.getY(), 0.0);
354 copy(buffer, header);
361 NOTICE(
"Offset applied to true tracks is: " << center << endl);
363 NOTICE(
"No offset applied to true tracks." << endl);
369 if (cylinder.getZmin() < Zbed) {
370 cylinder.setZmin(Zbed);
373 NOTICE(
"Ligth generation volume: " << cylinder << endl);
375 TProfile cpu(
"cpu", NULL, 14, 1.0, 8.0);
376 TH1D job(
"job", NULL, 400, 0.5, 400.5);
394 STATUS(
"event: " << setw(10) << in.getCounter() <<
'\r');
DEBUG(endl);
398 Evt* evt = in.next();
402 track->pos += center;
408 event.mc_hits.clear();
429 double Zmin = intersection.first;
430 double Zmax = intersection.second;
432 if (Zmax - Zmin <= Dmin_m) {
436 JVertex vertex(0.0, track->t, track->E);
438 if (track->pos.z < Zbed) {
440 if (track->dir.z > 0.0)
441 vertex.
step(
gRock, (Zbed - track->pos.z) / track->dir.z);
446 if (vertex.
getZ() < Zmin) {
458 if (subdetector.empty()) {
466 while (vertex.
getE() >= Emin_GeV && vertex.
getZ() < Zmax) {
468 const int N = radiation.size();
473 for (
int i = 0; i != N; ++i) {
474 ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.
getE());
477 const double ds = min(gRandom->Exp(1.0) /
ls, vertex.
getRange());
481 if (vertex.
getE() >= Emin_GeV) {
484 double y = gRandom->Uniform(
ls);
486 for (
int i = 0; i != N; ++i) {
491 Es = radiation[i]->getEnergyOfShower(vertex.
getE());
498 if (Es >= Ecut_GeV) {
499 muon.push_back(vertex);
506 if (vertex.
getE() < Emin_GeV && vertex.
getRange() > 0.0) {
510 muon.push_back(vertex);
519 if (trk != event.mc_trks.end()) {
520 trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
521 trk->setusr(mc_usr_keys::energy_lost_in_can, muon.begin()->
getE() - muon.rbegin()->
getE());
524 for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
526 const double z0 = muon.begin()->getZ();
527 const double t0 = muon.begin()->getT();
528 const double R = module->getX();
531 if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
533 for (
size_t i = 0; i != CDF.size(); ++i) {
535 if (R < CDF[i].integral.getXmax()) {
545 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
546 const int N = gRandom->Poisson(NPE);
552 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
554 const double R = pmt->getX();
555 const double Z = pmt->getZ() - z0;
556 const double theta = pmt->getTheta();
557 const double phi = fabs(pmt->getPhi());
559 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
565 job.Fill((
double) (100 + CDF[i].type), (
double) n0);
569 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
572 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
584 job.Fill((
double) (300 + CDF[i].type));
588 catch(
const exception& error) {
589 job.Fill((
double) (200 + CDF[i].type));
596 for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
598 const double z0 = vertex->
getZ();
599 const double t0 = vertex->
getT();
600 const double Es = vertex->
getEs();
602 int origin = track->id;
604 if (writeEMShowers) {
605 origin =
event.mc_trks.size() + 1;
608 int number_of_hits = 0;
610 JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
611 z0 + maximal_distance);
613 for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
616 const double R = module->getX();
617 const double Z = module->getZ() - z0 - dz;
618 const double D = sqrt(R*R + Z*Z);
619 const double cd = Z / D;
621 for (
size_t i = 0; i != CDG.size(); ++i) {
623 if (D < CDG[i].integral.getXmax()) {
627 const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
628 const int N = gRandom->Poisson(NPE);
634 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
637 const double R = pmt->getX();
638 const double Z = pmt->getZ() - z0 - dz;
639 const double theta = pmt->getTheta();
640 const double phi = fabs(pmt->getPhi());
641 const double D = sqrt(R*R + Z*Z);
642 const double cd = Z / D;
644 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor;
650 job.Fill((
double) (100 + CDG[i].type), (
double) n0);
655 const double Z = pmt->getZ() - z0 - dz;
656 const double D = sqrt(R*R + Z*Z);
657 const double cd = Z / D;
659 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
662 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
671 number_of_hits += n1;
676 job.Fill((
double) (300 + CDG[i].type));
680 catch(
const exception& error) {
681 job.Fill((
double) (200 + CDG[i].type));
687 if (writeEMShowers && number_of_hits != 0) {
689 event.mc_trks.push_back(
JTrk_t(origin,
692 track->pos + track->dir * vertex->
getZ(),
699 }
else if (
is_tau(*track)) {
707 const double z0 = 0.0;
708 const double z1 = z0 + track->len;
709 const double t0 = track->t;
710 const double E = track->E;
716 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
720 const double R = pos.
getX();
725 R > maximal_road_width) {
729 for (
size_t i = 0; i != CDF.size(); ++i) {
731 if (R < CDF[i].integral.getXmax()) {
741 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
742 const int N = gRandom->Poisson(NPE);
752 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
754 const double R = pmt->getX();
755 const double Z = pmt->getZ() - z0;
756 const double theta = pmt->getTheta();
757 const double phi = fabs(pmt->getPhi());
759 const double npe = CDF[i].function.getNPE(R, theta, phi) * factor * W;
765 job.Fill((
double) (120 + CDF[i].type), (
double) n0);
769 const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
772 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
784 job.Fill((
double) (320 + CDF[i].type));
788 catch(
const exception& error) {
789 job.Fill((
double) (220 + CDF[i].type));
796 if (!buffer.empty()) {
815 catch(
const exception& error) {
816 ERROR(error.what() << endl);
819 E =
pythia(track->type, E);
821 if (E < Ecut_GeV || cylinder.getDistance(
getPosition(*track)) > Dmin_m) {
825 const double z0 = 0.0;
826 const double t0 = track->t;
832 for (JDetector::const_iterator module =
detector.begin(); module !=
detector.end(); ++module) {
837 const double R = pos.
getX();
838 const double Z = pos.
getZ() - z0 - dz;
839 const double D = sqrt(R*R + Z*Z);
840 const double cd = Z / D;
842 if (D > maximal_distance) {
846 for (
size_t i = 0; i != CDG.size(); ++i) {
848 if (D < CDG[i].integral.getXmax()) {
852 const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
853 const int N = gRandom->Poisson(NPE);
863 for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
866 const double R = pmt->getX();
867 const double Z = pmt->getZ() - z0 - dz;
868 const double theta = pmt->getTheta();
869 const double phi = fabs(pmt->getPhi());
870 const double D = sqrt(R*R + Z*Z);
871 const double cd = Z / D;
873 const double npe = CDG[i].function.getNPE(D, cd, theta, phi) * E * factor;
879 job.Fill((
double) (140 + CDG[i].type), (
double) n0);
884 const double Z = pmt->getZ() - z0 - dz;
885 const double D = sqrt(R*R + Z*Z);
886 const double cd = Z / D;
888 const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
891 mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
903 job.Fill((
double) (340 + CDG[i].type));
907 catch(
const exception& error) {
908 job.Fill((
double) (240 + CDG[i].type));
914 if (!buffer.empty()) {
925 if (!mc_hits.empty()) {
927 mc_hits.
merge(Tmax_ns);
929 event.mc_hits.resize(mc_hits.size());
931 copy(mc_hits.begin(), mc_hits.end(),
event.mc_hits.begin());
940 if (event.mc_hits.size() >= numberOfHits) {