219{
  222 
  223  string         fileDescriptor;
  225  JFileRecorder       <JTYPELIST<JAAnetTypes_t, JMetaTypes_t, JRootTypes_t>::typelist> 
outputFile;
 
  226  JLimit_t&      numberOfEvents = inputFile.getLimit();
 
  227  string         detectorFile;
  229  bool           writeEMShowers;
  230  size_t         numberOfHits;
  231  double         factor;
  233 
  234  try { 
  235 
  237 
  246 
  249 
  250    JParser<> zap(
"Main program to simulate detector response to muons and showers.");
 
  251 
  253    zap[
'F'] = 
make_field(fileDescriptor,    
"file name descriptor for CDF tables");
 
  258    zap[
's'] = 
make_field(writeEMShowers,    
"store generated EM showers in event");
 
  259    zap[
'N'] = 
make_field(numberOfHits,      
"minimum number of hits to output event") = 1;
 
  260    zap[
'U'] = 
make_field(factor,            
"scaling factor applied to light yields") = 1.0;
 
  263    
  264    zap(argc, argv);
  265  }
  266  catch(const exception &error) {
  267    FATAL(error.what() << endl);
 
  268  }
  269 
  270 
  271  seed.set(gRandom);
  272 
  273 
  274  const JMeta meta(argc, argv);
 
  275 
  276  const double Zbed = 0.0;                             
  277 
  280 
  281  if (fileDescriptor != "") {
  282    CDF.push_back(JCDF_t(fileDescriptor, DIRECT_LIGHT_FROM_MUON));
  283    CDF.push_back(JCDF_t(fileDescriptor, SCATTERED_LIGHT_FROM_MUON));
  284    CDF.push_back(JCDF_t(fileDescriptor, DIRECT_LIGHT_FROM_DELTARAYS));
  285    CDF.push_back(JCDF_t(fileDescriptor, SCATTERED_LIGHT_FROM_DELTARAYS));
  286  
  287    CDG.push_back(JCDG_t(fileDescriptor, DIRECT_LIGHT_FROM_EMSHOWER));
  288    CDG.push_back(JCDG_t(fileDescriptor, SCATTERED_LIGHT_FROM_EMSHOWER));
  289  }
  290  
  291  double maximal_road_width = 0.0;                     
  292  double maximal_distance   = 0.0;                     
  293 
  294  for (size_t i = 0; i != CDF.size(); ++i) {
  295    
  296    DEBUG(
"Range CDF["<< CDF[i].type << 
"] " << CDF[i].function.intensity.getXmax() << 
" m" << endl);
 
  297 
  298    maximal_road_width = max(maximal_road_width, CDF[i].function.intensity.getXmax());
  299  }
  300 
  301  for (size_t i = 0; i != CDG.size(); ++i) {
  302 
  303    DEBUG(
"Range CDG["<< CDG[i].type << 
"] " << CDG[i].function.intensity.getXmax() << 
" m" << endl);
 
  304 
  306      maximal_road_width = max(maximal_road_width, CDG[i].function.intensity.getXmax());
  307    }
  308    
  309    maximal_distance   = max(maximal_distance,   CDG[i].function.intensity.getXmax());
  310  }
  311  
  312  NOTICE(
"Maximal road width [m] " << maximal_road_width << endl);
 
  313  NOTICE(
"Maximal distance   [m] " << maximal_distance   << endl);
 
  314 
  315 
  316  if (detectorFile == "" || inputFile.empty()) {
  317    STATUS(
"Nothing to be done." << endl);
 
  318    return 0;
  319  }
  320 
  322 
  323  try {
  324 
  325    STATUS(
"Load detector... " << flush);
 
  326 
  328 
  330  }
  333  }
  334 
  335  
  336 
  337  for (JDetector::iterator module = 
detector.begin(); module != 
detector.end(); ) {
 
  338    if (!module->empty())
  339      ++module;
  340    else
  341      module = detector.erase(module);
  342  }
  343 
  346  
  347  if (true) {
  348 
  349    STATUS(
"Setting up radiation tables... " << flush);
 
  350 
  351    const JRadiation hydrogen ( 1.0,  1.0, 40, 0.01, 0.1, 0.1);
 
  352    const JRadiation oxygen   ( 8.0, 16.0, 40, 0.01, 0.1, 0.1);
 
  353    const JRadiation chlorine (17.0, 35.5, 40, 0.01, 0.1, 0.1);
 
  354    const JRadiation sodium   (11.0, 23.0, 40, 0.01, 0.1, 0.1);
 
  355#ifdef RADIATION
  356    const JRadiation calcium  (20.0, 40.0, 40, 0.01, 0.1, 0.1);
 
  357    const JRadiation magnesium(12.0, 24.3, 40, 0.01, 0.1, 0.1);
 
  358    const JRadiation potassium(19.0, 39.0, 40, 0.01, 0.1, 0.1);
 
  359    const JRadiation sulphur  (16.0, 32.0, 40, 0.01, 0.1, 0.1);
 
  360#endif
  361 
  366#ifdef RADIATION
  371#endif
  372 
  377#ifdef RADIATION
  382#endif
  383 
  388#ifdef RADIATION
  393#endif
  394 
  399#ifdef RADIATION
  404#endif
  405 
  407 
  412#ifdef RADIATION
  417#endif
  418    
  420  }
  421 
  422 
  424 
  425  cylinder.addMargin(maximal_distance);
  426 
  427  if (cylinder.getZmin() < Zbed) {
  428    cylinder.setZmin(Zbed);
  429  }
  430 
  431  NOTICE(
"Light generation volume: " << cylinder << endl);
 
  432 
  433 
  436 
  437  try {
  438 
  439    header = inputFile.getHeader();
  440 
  441    JHead buffer(header);
 
  442 
  444 
  447    buffer.simul.rbegin()->date    = 
getDate();
 
  448    buffer.simul.rbegin()->time    = 
getTime();
 
  449 
  451 
  453 
  455    buffer.detector.rbegin()->filename = detectorFile;
  456 
  458 
  459    offset += 
Vec(cylinder.getX(), cylinder.getY(), 0.0);
 
  461 
  463 
  464      buffer.fixedcan.xcenter += offset.x;
  465      buffer.fixedcan.ycenter += offset.y;
  466      buffer.fixedcan.zmin    += offset.z;
  467      buffer.fixedcan.zmax    += offset.z;
  468 
  469    } else {
  470 
  471      buffer.fixedcan.xcenter  = cylinder.getX();
  472      buffer.fixedcan.ycenter  = cylinder.getY();
  473 
  475 
  476        buffer.fixedcan.radius   = buffer.can.r;
  477        buffer.fixedcan.zmin     = buffer.can.zmin + offset.z;
  478        buffer.fixedcan.zmax     = buffer.can.zmax + offset.z;
  479      } else {
  480 
  481        buffer.fixedcan.radius   = cylinder.getRadius();
  482        buffer.fixedcan.zmin     = cylinder.getZmin();
  483        buffer.fixedcan.zmax     = cylinder.getZmax();
  484      }
  485    }
  486 
  488 
  490 
  492 
  494    }
  495 
  496    copy(buffer, header);
 
  497  }
  500  }
  501 
  502  NOTICE(
"Offset applied to true tracks is: " << offset << endl);
 
  503 
  504  TH1D       job("job", NULL, 400,  0.5, 400.5);
  505  TProfile   cpu("cpu", NULL,  16,  0.0,   8.0);
  506  TProfile2D rms("rms", NULL,  16,  0.0,   8.0, 201, -0.5, 200.5);
  507  TProfile2D rad("rad", NULL,  16,  0.0,   8.0, 201, -0.5, 200.5);
  508 
  509 
  511 
  514  }
  515 
  519 
  520  const double         epsilon = 1.0e-6;                 
  522 
  524 
  526 
  527    STATUS(
"event: " << setw(10) << in.getCounter() << 
'\r'); 
DEBUG(endl);
 
  528 
  529    job.Fill(1.0);
  530 
  531    Evt* evt = in.next(); 
 
  532 
  534      track->pos += offset;
  535    }
  536    
  538 
  539    event.mc_hits.clear();
  540 
  542 
  545    
  546    for (vector<Trk>::const_iterator track = evt->
mc_trks.begin(); track != evt->
mc_trks.end(); ++track) {
 
  547 
  548      if (!track->is_finalstate()) {
  549        continue;                                      
  550      }
  551 
  553 
  554        
  555        
  556        
  557 
  558        job.Fill(2.0);
  559 
  561 
  563 
  564        double Zmin = intersection.first;
  565        double Zmax = intersection.second;
  566 
  567        if (Zmax - Zmin <= parameters.Dmin_m) {
  568          continue;
  569        }
  570        
  571        JVertex vertex(0.0, track->t, track->E);                        
 
  572      
  573        if (track->pos.z < Zbed) {                                      
  574            
  575          if (track->dir.z > 0.0)
  576            vertex.step(
gRock, (Zbed - track->pos.z) / track->dir.z); 
 
  577          else
  578            continue;
  579        }
  580 
  581        if (vertex.getZ() < Zmin) {                                     
  582          vertex.step(gWater, Zmin - vertex.getZ());
  583        }
  584 
  585        if (vertex.getRange() <= parameters.Dmin_m) {
  586          continue;
  587        }
  588 
  589        job.Fill(3.0);
  590 
  592 
  593        if (subdetector.empty()) {
  594          continue;
  595        }
  596 
  597        job.Fill(4.0);
  598        
  599        JTrack muon(vertex);                                            
  600 
  601        while (vertex.getE() >= parameters.Emin_GeV && vertex.getZ() < Zmax) {
  602 
  603          const int N = radiation.size();
  604        
  605          double li[N];                                                 
  607        
  608          for (int i = 0; i != N; ++i) {
  609            ls += li[i] = radiation[i]->getInverseInteractionLength(vertex.getE());
 
  610          }
  611 
  612          double As = 0.0;                                              
  613 
  614          for (size_t i = 0; i != ionization.size(); ++i) {
  615            As += ionization[i]->getA(vertex.getE());
  616          }
  617 
  618          double step  = gRandom->Exp(1.0) / 
ls;                        
 
  619          double range = vertex.getRange(As);                           
  620 
  621          if (vertex.getE() < parameters.Emax_GeV) {                    
  622            if (parameters.Dmax_m < range) {
  623              range = parameters.Dmax_m;
  624            }
  625          }
  626 
  627          double ts = 
getThetaMCS(vertex.getE(), min(step,range));      
 
  628          double T2 = ts*ts;                                            
  629 
  630          rms.Fill(log10(vertex.getE()), (Double_t) 0, ts*ts);
  631          
  632          vertex.getDirection() += getRandomDirection(T2/3.0);          
  633 
  634          vertex.step(As, min(step,range));                             
  635 
  636          double Es = 0.0;                                              
  637 
  638          if (step < range) {
  639 
  640            if (vertex.getE() >= parameters.Emin_GeV) {
  641 
  642              double y  = gRandom->Uniform(
ls);
 
  643            
  644              for (int i = 0; i != N; ++i) {
  645              
  647              
  648                if (y < 0.0) {
  649 
  650                  Es = radiation[i]->getEnergyOfShower(vertex.getE());  
  651                  ts = radiation[i]->getThetaRMS(vertex.getE(), Es);    
  652 
  653                  T2 += ts*ts;
  654 
  655                  rms.Fill(log10(vertex.getE()), (Double_t) radiation[i]->getID(), ts*ts);
  656                  rad.Fill(log10(vertex.getE()), (Double_t) radiation[i]->getID(), Es);
  657                  
  658                  break;
  659                }
  660              }
  661            }
  662          }
  663 
  664          vertex.applyEloss(getRandomDirection(T2), Es);
  665 
  666          muon.push_back(vertex);
  667        }
  668 
  669        
  670 
  671        if (vertex.getZ() < Zmax && vertex.getRange() > 0.0) {
  672 
  673          vertex.step(vertex.getRange());
  674 
  675          muon.push_back(vertex);
  676        }
  677 
  678        
  679        
  681                                            event.mc_trks.end(),
  682                                            make_predicate(&
Trk::id, track->id));
 
  683 
  684        if (trk != event.mc_trks.end()) {
  685          trk->len = (muon.rbegin()->getZ() < Zmax ? +1 : -1) * (muon.rbegin()->getZ() - muon.begin()->getZ());
  687        }
  688 
  689        for (JDetector::const_iterator module = subdetector.begin(); module != subdetector.end(); ++module) {
  690 
  691          const double z0 = muon.begin()->getZ();
  692          const double t0 = muon.begin()->getT();
  693          const double Z  = module->getZ() - module->getX() / getTanThetaC();
  694 
  695          if (Z >= muon.begin()->getZ() && Z <= muon.rbegin()->getZ()) {
  696          
  697            const JVector2D pos = muon.getPosition(Z);
 
  698            const double    R   = hypot(module->getX() - pos.
getX(), 
 
  699                                        module->getY() - pos.
getY());
 
  700 
  701            for (size_t i = 0; i != CDF.size(); ++i) {
  702                      
  703              if (R < CDF[i].integral.getXmax()) {
  704              
  705                try {
  706 
  707                  double W = 1.0;                                       
  708                  
  711                  }
  712 
  713                  const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
  714                  const size_t N   = getPoisson(NPE); 
  715 
  716                  if (N != 0) {
  717                    
  719 
  720                    for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
  721 
  722                      const double R     = hypot(pmt->getX() - pos.
getX(), 
 
  723                                                 pmt->getY() - pos.
getY());
 
  724                      const double theta = pi.constrain(pmt->getTheta());
  725                      const double phi   = pi.constrain(fabs(pmt->getPhi()));
  726                    
  727                      npe.push_back(CDF[i].function.getNPE(R, theta, phi) * factor * W);
  728                    }
  729 
  731 
  732                    for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
  733 
  734                      const double R     = hypot(pmt->getX() - pos.
getX(), 
 
  735                                                 pmt->getY() - pos.
getY());
 
  736                      const double Z     = pmt->getZ() - z0;
  737                      const double theta = pi.constrain(pmt->getTheta());
  738                      const double phi   = pi.constrain(fabs(pmt->getPhi()));
  739                    
  740                      size_t n0 = min(ns[
distance(module->begin(),pmt)], parameters.Nmax_PMT);
 
  741                    
  742                      job.Fill((double) (100 + CDF[i].type), (double) n0);
  743                    
  744                      while (n0 != 0) {
  745                      
  746                        const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
  748                     
  749                        mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  750                                                 pmt->getID(),
  752                                                 track->id,
  753                                                 t0  +  (R * getTanThetaC() + Z) / C  +  t1,
  754                                                 n1));
  755 
  756                        n0 -= n1;
  757                      }
  758                    }
  759 
  760                    if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
  761                      job.Fill((double) (300 + CDF[i].type));
  762                    }
  763                  }
  764                }
  765                catch(const exception& error) {
  766                  job.Fill((double) (200 + CDF[i].type));
  767                }
  768              }
  769            }
  770          }
  771        }
  772 
  773        for (JTrack::const_iterator vertex = muon.begin(); vertex != muon.end(); ++vertex) {
  774 
  775          const double Es = vertex->getEs();
  776          
  777          if (Es >= parameters.Ecut_GeV) {
  778 
  779            const double z0 = vertex->getZ();
  780            const double t0 = vertex->getT();
  782 
  784 
  785            if (writeEMShowers) {
  786              origin = 
event.mc_trks.size() + 1;
 
  787            }
  788 
  789            int number_of_hits = 0;
  790            
  791            JDetectorSubset_t::range_type range = subdetector.getRange(z0 - maximal_distance,
  792                                                                       z0 + maximal_distance);
  793 
  794            for (JDetector::const_iterator module = range.begin(); module != range.end(); ++module) {
  795 
  796              const double R  = hypot(module->getX() - vertex->getX(),
  797                                      module->getY() - vertex->getY());
  798              const double Z  = module->getZ() - z0 - DZ;
  799              const double D  = sqrt(R*R + Z*Z);
  800              const double cd = Z / D; 
  801            
  802              for (size_t i = 0; i != CDG.size(); ++i) {
  803              
  804                if (D < CDG[i].integral.getXmax()) {
  805                
  806                  try {
  807 
  808                    const double NPE = CDG[i].integral.getNPE(D, cd) * Es * module->size() * factor;
  809                    const size_t N   = getPoisson(NPE); 
  810 
  811                    if (N != 0) {
  812                      
  814 
  815                      for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
  816 
  817                        const double R     = hypot(pmt->getX() - vertex->getX(), 
  818                                                   pmt->getY() - vertex->getY());
  819                        const double Z     = pmt->getZ() - z0 - DZ;
  820                        const double D     = sqrt(R*R + Z*Z);
  821                        const double cd    = Z / D; 
  822                        const double theta = pi.constrain(pmt->getTheta());
  823                        const double phi   = pi.constrain(fabs(pmt->getPhi()));
  824                        
  825                        npe.push_back(CDG[i].function.getNPE(D, cd, theta, phi) * Es * factor);
  826                      }
  827 
  829                        
  830                      for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
  831 
  832                        const double R     = hypot(pmt->getX() - vertex->getX(), 
  833                                                   pmt->getY() - vertex->getY());
  834                        const double theta = pi.constrain(pmt->getTheta());
  835                        const double phi   = pi.constrain(fabs(pmt->getPhi()));
  836                        
  837                        size_t n0 = min(ns[
distance(module->begin(),pmt)], parameters.Nmax_PMT);
 
  838 
  839                        job.Fill((double) (100 + CDG[i].type), (double) n0);
  840                      
  841                        while (n0 != 0) {
  842 
  844                          const double Z  = pmt->getZ() - z0 - dz;
  845                          const double D  = sqrt(R*R + Z*Z);
  846                          const double cd = Z / D; 
  847                          
  848                          const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
  850 
  851                          mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  852                                                   pmt->getID(),
  854                                                   origin,
  856                                                   n1));
  857 
  858                          n0 -= n1;
  859                        
  860                          number_of_hits += n1;
  861                        }
  862                      }
  863                    
  864                      if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
  865                        job.Fill((double) (300 + CDG[i].type));
  866                      }
  867                    }
  868                  }
  869                  catch(const exception& error) {
  870                    job.Fill((double) (200 + CDG[i].type));
  871                  }
  872                }
  873              }
  874            }
  875          
  876            if (writeEMShowers && number_of_hits != 0) {
  877 
  878              event.mc_trks.push_back(
JTrk_t(origin,
 
  880                                             track->id,
  881                                             track->pos + track->dir * vertex->getZ(),
  882                                             track->dir,
  883                                             vertex->getT(),
  884                                             Es));
  885            }
  886          }
  887        }
  888 
  889      } else if (track->len > 0.0) {
  890 
  891        
  892        
  893        
  894 
  895        job.Fill(6.0);
  896 
  897        const double z0 = 0.0;
  898        const double z1 = z0 + track->len;
  899        const double t0 = track->t;
  900        const double E  = track->E;
  901 
  903        
  905        
  906        for (JDetector::const_iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
  907 
  909 
  910          const double R  = pos.
getX();
 
  912 
  913          if (Z < z0  ||
  914              Z > z1  ||
  915              R > maximal_road_width) {
  916            continue;
  917          }
  918          
  919          for (size_t i = 0; i != CDF.size(); ++i) {
  920                
  921            double W = 1.0;                                   
  922 
  924 
  927              else
  928                continue;
  929            }    
  930 
  931            if (R < CDF[i].integral.getXmax()) {
  932              
  933              try {
  934                
  935                const double NPE = CDF[i].integral.getNPE(R) * module->size() * factor * W;
  936                const size_t N   = getPoisson(NPE); 
  937                
  938                if (N != 0) {
  939                    
  940                  buffer = *module;
  941            
  943 
  945                  
  946                  for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
  947 
  948                    const double R     = pmt->getX();
  949                    const double theta = pi.constrain(pmt->getTheta());
  950                    const double phi   = pi.constrain(fabs(pmt->getPhi()));
  951                    
  952                    npe.push_back(CDF[i].function.getNPE(R, theta, phi) * factor * W);
  953                  }
  954 
  956 
  957                  for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
  958                    
  959                    const double R     = pmt->getX();
  960                    const double Z     = pmt->getZ() - z0;
  961                    const double theta = pi.constrain(pmt->getTheta());
  962                    const double phi   = pi.constrain(fabs(pmt->getPhi()));
  963                    
  964                    size_t n0 = min(ns[
distance(buffer.cbegin(),pmt)], parameters.Nmax_PMT);
 
  965                    
  966                    job.Fill((double) (120 + CDF[i].type), (double) n0);
  967                    
  968                    while (n0 != 0) {
  969                      
  970                      const double t1 = CDF[i].function.getTime(R, theta, phi, gRandom->Rndm());
  972                      
  973                      mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
  974                                               pmt->getID(),
  976                                               track->id,
  977                                               t0  +  (R * getTanThetaC() + Z) / C  +  t1,
  978                                               n1));
  979                      
  980                      n0 -= n1;
  981                    }
  982                  }
  983 
  984                  if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
  985                    job.Fill((double) (320 + CDF[i].type));
  986                  }
  987                }
  988              }
  989              catch(const exception& error) {
  990                job.Fill((double) (220 + CDF[i].type));
  991              }
  992            }
  993          }
  994        }
  995        
  996        if (!buffer.empty()) {
  997          job.Fill(7.0);
  998        }
  999          
 1001 
 1003    
 1004          
 1005          
 1006          
 1007          
 1008          job.Fill(8.0);
 1009        
 1010          double E = track->E;
 1011 
 1012          try {
 1014          }
 1015          catch(const exception& error) {
 1016            ERROR(error.what() << endl);
 
 1017          }
 1018 
 1019          E = 
pythia(track->type, E);
 
 1020 
 1021          if (E >= parameters.Ecut_GeV && cylinder.getDistance(
getPosition(*track)) < parameters.Dmin_m) {
 
 1022        
 1023            const double z0 = 0.0;
 1024            const double t0 = track->t;
 1026 
 1028        
 1030        
 1031            for (JDetector::const_iterator module = 
detector.begin(); module != 
detector.end(); ++module) {
 
 1032 
 1034 
 1035              const double R  = pos.
getX();
 
 1036              const double Z  = pos.
getZ() - z0 - DZ;
 
 1037              const double D  = sqrt(R*R + Z*Z);
 1038              const double cd = Z / D; 
 1039            
 1040              for (size_t i = 0; i != CDG.size(); ++i) {
 1041                    
 1042                if (D < CDG[i].integral.getXmax()) {
 1043                
 1044                  try {
 1045                        
 1046                    const double NPE = CDG[i].integral.getNPE(D, cd) * E * module->size() * factor;
 1047                    const size_t N   = getPoisson(NPE); 
 1048 
 1049                    if (N != 0) {
 1050 
 1051                      buffer = *module;
 1052            
 1054          
 1056                        
 1057                      for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
 1058                    
 1059                        const double R     = pmt->getX();
 1060                        const double Z     = pmt->getZ() - z0 - DZ;
 1061                        const double D     = sqrt(R*R + Z*Z);
 1062                        const double cd    = Z / D; 
 1063                        const double theta = pi.constrain(pmt->getTheta());
 1064                        const double phi   = pi.constrain(fabs(pmt->getPhi()));
 1065                          
 1066                        npe.push_back(CDG[i].function.getNPE(D, cd, theta, phi) * E * factor);
 1067                      }
 1068                          
 1070 
 1071                      for (JModule::const_iterator pmt = buffer.begin(); pmt != buffer.end(); ++pmt) {
 1072                    
 1073                        const double theta = pi.constrain(pmt->getTheta());
 1074                        const double phi   = pi.constrain(fabs(pmt->getPhi()));
 1075                          
 1076                        size_t n0 = min(ns[
distance(buffer.cbegin(),pmt)], parameters.Nmax_PMT);
 
 1077                 
 1078                        job.Fill((double) (140 + CDG[i].type), (double) n0);
 1079                          
 1080                        while (n0 != 0) {
 1081                      
 1083                          const double Z  = pmt->getZ() - z0 - dz;
 1084                          const double D  = sqrt(R*R + Z*Z);
 1085                          const double cd = Z / D;
 1086                      
 1087                          const double t1 = CDG[i].function.getTime(D, cd, theta, phi, gRandom->Rndm());
 1089 
 1090                          mc_hits.push_back(
JHit_t(mc_hits.size() + 1,
 
 1091                                                   pmt->getID(),
 1093                                                   track->id,
 1094                                                   t0  +  (dz +  D * getIndexOfRefraction()) / C  +  t1,
 1095                                                   n1));
 1096 
 1097                          n0 -= n1;
 1098                        }
 1099                      }
 1100                  
 1101                      if (std::accumulate(npe.begin(), npe.end(), 0.0) > NPE) {
 1102                        job.Fill((double) (340 + CDG[i].type));
 1103                      }
 1104                    }
 1105                  }
 1106                  catch(const exception& error) {
 1107                    job.Fill((double) (240 + CDG[i].type));
 1108                  }
 1109                }
 1110              }
 1111            }
 1112 
 1113            if (!buffer.empty()) {
 1114              job.Fill(9.0);
 1115            }
 1116 
 1117          } else {
 1118            job.Fill(21.0);
 1119          }
 1120        }
 1121      }
 1122    }
 1123 
 1124    if (!mc_hits.empty()) {
 1125 
 1126      mc_hits.
merge(parameters.Tmax_ns);
 
 1127 
 1128      event.mc_hits.resize(mc_hits.size());
 1129 
 1130      copy(mc_hits.begin(), mc_hits.end(), event.mc_hits.begin());
 
 1131    }
 1132 
 1134 
 1137    }
 1138 
 1139    if (event.mc_hits.size() >= numberOfHits) {
 1140 
 1142 
 1143      job.Fill(10.0);
 1144    }
 1145  }
 1147 
 1153 
 1155 
 1157 
 1159}
#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.
 
Detector subset with 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.
 
The template JSharedPointer class can be used to share a pointer to an object.
 
Utility class to parse command line options.
 
Implementation for calculation of ionization constant.
 
Implementation for calculation of inverse interaction length and shower energy due to deep-inelastic ...
 
double getLength(const double E, const double P, const double eps=1.0e-5) const
Get shower length for a given integrated probability.
 
double getMaximum(const double E) const
Get depth of shower maximum.
 
Fast implementation of class JRadiation.
 
Implementation for calculation of inverse interaction length and shower energy.
 
Auxiliary class for the calculation of the muon radiative cross sections.
 
static double O()
Estimated mass fractions of chemical elements in sea water.
 
General purpose class for object reading from a list of file names.
 
virtual bool hasNext() override
Check availability of next element.
 
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.
 
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.
 
bool is_deltarays(const int pdf)
Test if given PDF type corresponds to Cherenkov light from delta-rays.
 
static const JRadiationSource_t GNrad_t
 
static const double DENSITY_SEA_WATER
Fixed environment values.
 
static const JRadiationSource_t Brems_t
 
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.
 
static const JRadiationSource_t EErad_t
 
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.
 
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)...
 
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.