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;    
 
  167 int main(
int argc, 
char **argv)
 
  172   string         fileDescriptor;
 
  177   double         Ecut_GeV  =  0.1;                            
 
  178   double         Emin_GeV  =  1.0;                            
 
  180   double         Tmax_ns   =  0.1;                            
 
  181   int            Nmax_npe  =  numeric_limits<int>::max();     
 
  197     JParser<> zap(
"Main program to simulate detector response to muons and showers.");
 
  200     zap[
'F'] = 
make_field(fileDescriptor,    
"file name descriptor for CDF tables");
 
  203     zap[
'n'] = 
make_field(numberOfEvents)    = JLimit::max();
 
  205     zap[
's'] = 
make_field(writeEMShowers,    
"store generated EM showers in event");
 
  206     zap[
'N'] = 
make_field(numberOfHits,      
"minimum number of hits to output event") = 1;
 
  207     zap[
'U'] = 
make_field(factor,            
"scaling factor applied to light yields") = 1.0;
 
  213   catch(
const exception &error) {
 
  214     FATAL(error.what() << endl);
 
  218   gRandom->SetSeed(seed);
 
  221   const JMeta meta(argc, argv);
 
  223   const double Zbed = 0.0;                             
 
  237   double maximal_road_width = 0.0;                     
 
  238   double maximal_distance   = 0.0;                     
 
  240   for (
size_t i = 0; i != CDF.size(); ++i) {
 
  242     DEBUG(
"Range CDF["<< CDF[i].type << 
"] " << CDF[i].
function.intensity.getXmax() << 
" m" << endl);
 
  244     maximal_road_width = max(maximal_road_width, CDF[i].
function.intensity.getXmax());
 
  247   for (
size_t i = 0; i != CDG.size(); ++i) {
 
  249     DEBUG(
"Range CDG["<< CDG[i].type << 
"] " << CDG[i].
function.intensity.getXmax() << 
" m" << endl);
 
  252       maximal_road_width = max(maximal_road_width, CDG[i].
function.intensity.getXmax());
 
  255     maximal_distance   = max(maximal_distance,   CDG[i].
function.intensity.getXmax());
 
  258   NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
 
  259   NOTICE(
"Maximal distance   [m] " << maximal_distance   << endl);
 
  262   if (detectorFile == 
"" || inputFile.empty()) {
 
  263     STATUS(
"Nothing to be done." << endl);
 
  271     STATUS(
"Load detector... " << flush);
 
  286     STATUS(
"Setting up radiation tables... " << flush);
 
  288     const JRadiation hydrogen( 1.0,  1.0, 40, 0.01, 0.1, 0.1);
 
  289     const JRadiation oxygen  ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
 
  290     const JRadiation chlorine(17.0, 35.0, 40, 0.01, 0.1, 0.1);
 
  321     header = inputFile.getHeader();
 
  323     JHead buffer(header);
 
  330     center = get<Vec>(buffer);
 
  338     center += Vec(circle.getX(), circle.getY(), 0.0);
 
  340     push(buffer, &JHead::simul);
 
  341     push(buffer, &JHead::coord_origin);
 
  342     push(buffer, &JHead::can);
 
  343     copy(buffer, header);
 
  349   NOTICE(
"Offset applied to true tracks is: " << center << endl);
 
  355   if (cylinder.getZmin() < Zbed) {
 
  356     cylinder.setZmin(Zbed);
 
  360   TProfile cpu(
"cpu", NULL,  14,  1.0,   8.0);
 
  361   TH1D     job(
"job", NULL, 400,  0.5, 400.5);
 
  379     STATUS(
"event: " << setw(10) << in.getCounter() << 
'\r'); 
DEBUG(endl);
 
  383     Evt* evt = in.next();                              
 
  386       track->pos += center;
 
  391     event.mc_hits.clear();
 
  412         double Zmin = intersection.first;
 
  413         double Zmax = intersection.second;
 
  415         if (Zmax - Zmin <= Dmin_m) {
 
  419         JVertex vertex(0.0, track->t, track->E);                        
 
  421         if (track->pos.z < Zbed) {                                      
 
  423           if (track->dir.z > 0.0)
 
  424             vertex.
step(
gRock, (Zbed - track->pos.z) / track->dir.z); 
 
  429         if (vertex.
getZ() < Zmin) {                                     
 
  439         const JDetectorSubset_t subdetector(
detector, 
getAxis(*track), maximal_road_width);
 
  441         if (subdetector.empty()) {
 
  449         while (vertex.
getE() >= Emin_GeV && vertex.
getZ() < Zmax) {
 
  451           const int N = radiation.size();
 
  456           for (
int i = 0; i != N; ++i) {
 
  457             ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.
getE());
 
  460           const double ds = min(gRandom->Exp(1.0) / ls, vertex.
getRange());
 
  464           if (vertex.
getE() >= Emin_GeV) {
 
  467             double y  = gRandom->Uniform(ls);
 
  469             for (
int i = 0; i != N; ++i) {
 
  474                 Es = radiation[i]->getEnergyOfShower(vertex.
getE());    
 
  481             if (Es >= Ecut_GeV) {
 
  482               muon.push_back(vertex);
 
  489         if (vertex.
getE() < Emin_GeV && vertex.
getRange() > 0.0) {
 
  493           muon.push_back(vertex);
 
  502         if (trk != event.mc_trks.end()) {
 
  503           trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
 
  504           trk->setusr(mc_usr_keys::energy_lost_in_can, muon.begin()->
getE() - muon.rbegin()->
getE());
 
  507         for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
 
  509           const double z0 = muon.begin()->getZ();
 
  510           const double t0 = muon.begin()->getT();
 
  511           const double R  = module->getX();
 
  514           if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
 
  516             for (
size_t i = 0; i != CDF.size(); ++i) {
 
  518               if (R < CDF[i].integral.getXmax()) {
 
  528                   const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
 
  529                   const int    N   = gRandom->Poisson(NPE); 
 
  535                     for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
 
  537                       const double R     = pmt->getX();
 
  538                       const double Z     = pmt->getZ() - z0;
 
  539                       const double theta = pmt->getTheta();
 
  540                       const double phi   = fabs(pmt->getPhi());
 
  542                       const double npe   = CDF[i].function.getNPE(R, theta, phi) * factor * W;
 
  548                       job.Fill((
double) (100 + CDF[i].type), (
double) n0);
 
  552                         const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
 
  555                         mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  567                       job.Fill((
double) (300 + CDF[i].type));
 
  571                 catch(
const exception& error) {
 
  572                   job.Fill((
double) (200 + CDF[i].type));
 
  579         for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
 
  581           const double z0 = vertex->
getZ();
 
  582           const double t0 = vertex->
getT();
 
  583           const double Es = vertex->
getEs();
 
  585           int origin = track->id;
 
  587           if (writeEMShowers) {
 
  588             origin = 
event.mc_trks.size() + 1;
 
  591           int number_of_hits = 0;
 
  593           JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
 
  594                                                                      z0 + maximal_distance);
 
  596           for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
 
  599             const double R  = module->getX();
 
  600             const double Z  = module->getZ() - z0 - dz;
 
  601             const double D  = sqrt(R*R + Z*Z);
 
  602             const double cd = Z / D; 
 
  604             for (
size_t i = 0; i != CDG.size(); ++i) {
 
  606               if (D < CDG[i].integral.getXmax()) {
 
  610                   const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
 
  611                   const int    N   = gRandom->Poisson(NPE); 
 
  617                     for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
 
  620                       const double R     = pmt->getX();
 
  621                       const double Z     = pmt->getZ() - z0 - dz;
 
  622                       const double theta = pmt->getTheta();
 
  623                       const double phi   = fabs(pmt->getPhi());
 
  624                       const double D     = sqrt(R*R + Z*Z);
 
  625                       const double cd    = Z / D; 
 
  627                       const double npe   = CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor;
 
  633                       job.Fill((
double) (100 + CDG[i].type), (
double) n0);
 
  638                         const double Z  = pmt->getZ() - z0 - dz;
 
  639                         const double D  = sqrt(R*R + Z*Z);
 
  640                         const double cd = Z / D; 
 
  642                         const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
 
  645                         mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  654                         number_of_hits += n1;
 
  659                       job.Fill((
double) (300 + CDG[i].type));
 
  663                 catch(
const exception& error) {
 
  664                   job.Fill((
double) (200 + CDG[i].type));
 
  670           if (writeEMShowers && number_of_hits != 0) {
 
  672             event.mc_trks.push_back(
JTrk_t(origin,
 
  675                                            track->pos + track->dir * vertex->
getZ(),
 
  682       } 
else if (
is_tau(*track)) {
 
  690         const double z0 = 0.0;
 
  691         const double z1 = z0 + track->len;
 
  692         const double t0 = track->t;
 
  693         const double E  = track->E;
 
  699         for (JDetector::const_iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
  703           const double R  = pos.
getX();
 
  708               R > maximal_road_width) {
 
  712           for (
size_t i = 0; i != CDF.size(); ++i) {
 
  714             if (R < CDF[i].integral.getXmax()) {
 
  724                 const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
 
  725                 const int    N   = gRandom->Poisson(NPE); 
 
  735                   for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
 
  737                     const double R     = pmt->getX();
 
  738                     const double Z     = pmt->getZ() - z0;
 
  739                     const double theta = pmt->getTheta();
 
  740                     const double phi   = fabs(pmt->getPhi());
 
  742                     const double npe   = CDF[i].function.getNPE(R, theta, phi) * factor * W;
 
  748                     job.Fill((
double) (120 + CDF[i].type), (
double) n0);
 
  752                       const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
 
  755                       mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  767                     job.Fill((
double) (320 + CDF[i].type));
 
  771               catch(
const exception& error) {
 
  772                 job.Fill((
double) (220 + CDF[i].type));
 
  779         if (!buffer.empty()) {
 
  798           catch(
const exception& error) {
 
  799             ERROR(error.what() << endl);
 
  802           E = 
pythia(track->type, E);
 
  804           if (E < Ecut_GeV || cylinder.getDistance(
getPosition(*track)) > Dmin_m) {
 
  808           const double z0 = 0.0;
 
  809           const double t0 = track->t;
 
  815           for (JDetector::const_iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
  820             const double R  = pos.
getX();
 
  821             const double Z  = pos.
getZ() - z0 - dz;
 
  822             const double D  = sqrt(R*R + Z*Z);
 
  823             const double cd = Z / D; 
 
  825             if (D > maximal_distance) {
 
  829             for (
size_t i = 0; i != CDG.size(); ++i) {
 
  831               if (D < CDG[i].integral.getXmax()) {
 
  835                   const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
 
  836                   const int    N   = gRandom->Poisson(NPE); 
 
  846                     for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
 
  849                       const double R     = pmt->getX();
 
  850                       const double Z     = pmt->getZ() - z0 - dz;
 
  851                       const double theta = pmt->getTheta();
 
  852                       const double phi   = fabs(pmt->getPhi());
 
  853                       const double D     = sqrt(R*R + Z*Z);
 
  854                       const double cd    = Z / D; 
 
  856                       const double npe   = CDG[i].function.getNPE(D, cd, theta, phi) * E * factor;
 
  862                       job.Fill((
double) (140 + CDG[i].type), (
double) n0);
 
  867                         const double Z  = pmt->getZ() - z0 - dz;
 
  868                         const double D  = sqrt(R*R + Z*Z);
 
  869                         const double cd = Z / D;
 
  871                         const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
 
  874                         mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  886                       job.Fill((
double) (340 + CDG[i].type));
 
  890                 catch(
const exception& error) {
 
  891                   job.Fill((
double) (240 + CDG[i].type));
 
  897           if (!buffer.empty()) {
 
  908     if (!mc_hits.empty()) {
 
  910       mc_hits.
merge(Tmax_ns);
 
  912       event.mc_hits.resize(mc_hits.size());
 
  914       copy(mc_hits.begin(), mc_hits.end(), 
event.mc_hits.begin());
 
  920       cpu.Fill(log10(
get_neutrino(event).E), (
double) timer.usec_ucpu * 1.0e-3);
 
  923     if (event.mc_hits.size() >= numberOfHits) {
 
Auxiliary class to set-up Hit. 
 
Utility class to parse command line options. 
 
Custom class for CDF table in 2 dimensions. 
 
double getEs() const 
Get shower energy. 
 
static const JGeane gWater(2.67e-1 *JTOOLS::DENSITY_SEA_WATER, 3.4e-4 *JTOOLS::DENSITY_SEA_WATER)
Function object for Energy loss of muon in sea water. 
 
Multi-dimensional CDF table for arrival time of Cherenkov light. 
 
double getT() const 
Get time. 
 
JPredicate< JResult_t T::*, JComparison::eq > make_predicate(JResult_t T::*member, const JResult_t value)
Helper method to create predicate for data member. 
 
JVertex & step(const double ds)
Step. 
 
Data structure for a composite optical module. 
 
void applyEloss(const double Es)
Apply energy loss energy. 
 
JTransformation3D getTransformation(const Trk &track)
Get transformation. 
 
Data structure for circle in two dimensions. 
 
#define gmake_property(A)
macro to convert (template) parameter to JPropertiesElement object 
 
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. 
 
std::string program
program name 
 
Recording of objects on file according a format that follows from the file name extension. 
 
JHitType_t getHitType(const JPDFType_t pdf, const bool shower=false)
Get hit type corresponding to given PDF type. 
 
double getDeltaRaysFromTau(const double E)
Equivalent EM-shower energy due to delta-rays per unit tau track length. 
 
Utility class to parse parameter values. 
 
Structure to store the ToT mean and standard deviation of the hits produced by a nanobeacon in a sour...
 
void push(JHead &header, T JHead::*p)
Push data of JHead for subsequent copy to Head. 
 
double getE() const 
Get muon energy. 
 
Empty structure for specification of parser element that is initialised (i.e. 
 
void merge(const double Tmax_ns)
Merge hits on same PMT that are within given time window. 
 
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. 
 
Data structure for detector geometry and calibration. 
 
static const JGeane gRock(2.67e-1 *0.9 *JTOOLS::DENSITY_ROCK, 3.4e-4 *1.2 *JTOOLS::DENSITY_ROCK)
Function object for Energy loss of muon in rock. 
 
Utility class to parse parameter values. 
 
Fast implementation of class JRadiation. 
 
Various implementations of functional maps. 
 
Numbering scheme for PDF types. 
 
bool is_neutrino(const Trk &track)
Test whether given track is a neutrino. 
 
Auxiliary class to extract a subset of optical modules from a detector. 
 
scattered light from muon 
 
Auxiliary class for defining the range of iterations of objects. 
 
double getZ() const 
Get position. 
 
I/O formatting auxiliaries. 
 
The template JSharedPointer class can be used to share a pointer to an object. 
 
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 
 
static const JGeanz geanz(1.85, 0.62, 0.54)
Function object for longitudinal EM-shower profile. 
 
JAxis3D getAxis(const Trk &track)
Get axis. 
 
double getE(const double z) const 
Get muon energy at given position. 
 
Auxiliary class for CPU timing and usage. 
 
scattered light from delta-rays 
 
std::string version
program version 
 
direct light from EM shower 
 
const char * getGITVersion()
Get GIT version. 
 
Auxiliary data structure for list of hits with hit merging capability. 
 
void addMargin(const double D)
Add (safety) margin. 
 
void load(const JString &file_name, JDetector &detector)
Load detector from input file. 
 
double getKineticEnergy(const double E, const double m)
Get kinetic energy of particle with given mass. 
 
General purpose messaging. 
 
Detector subset with binary search functionality. 
 
Detector subset without binary search functionality. 
 
Vertex of energy loss of muon. 
 
Scanning of objects from multiple files according a format that follows from the extension of each fi...
 
const char * getDate()
Get ASCII formatted date. 
 
Custom class for CDF table in 1 dimension. 
 
direct light from delta-rays 
 
virtual bool hasNext()
Check availability of next element. 
 
int getNumberOfPhotoElectrons(const double NPE, const int N, const double npe)
Get number of photo-electrons of a hit given the expectation values of the number of photo-electrons ...
 
double getMaximum(const double E) const 
Get depth of shower maximum. 
 
General purpose class for object reading from a list of file names. 
 
std::string date
processing date 
 
Utility class to parse command line options. 
 
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&)). 
 
ROOT TTree parameter settings. 
 
bool is_deltarays(const int pdf)
Test if given PDF type corresponds to Cherenkov light from delta-rays. 
 
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 class to list files. 
 
std::string getFilename(const std::string &file_name)
Get file name part, i.e. 
 
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. 
 
virtual const char * what() const 
Get error message. 
 
const Trk & get_neutrino(const Evt &evt)
Get incoming neutrino. 
 
bool is_tau(const Trk &track)
Test whether given track is a (anti-)tau. 
 
std::string time
processing time 
 
double getRange() const 
Get range of muon. 
 
JAANET::coord_origin coord_origin
 
double getZ() const 
Get z position. 
 
Auxiliary class to set-up Trk. 
 
#define DEBUG(A)
Message macros. 
 
JPosition3D getPosition(const Vec &v)
Get position. 
 
int main(int argc, char *argv[])