9 #include "TDatabasePDG.h" 22 #include "nurandom/RandomUtils/NuRandomService.h" 31 #include "CLHEP/Random/RandFlat.h" 32 #include "CLHEP/Random/RandPoissonQ.h" 234 double wrapvar(
const double var,
const double low,
const double high);
235 double wrapvarBoxNo(
const double var,
const double low,
const double high,
int& boxno);
297 fToffset(
p.get<
double >(
"TimeOffset",0.)),
298 fBuffBox(
p.get< std::vector< double > >(
"BufferBox",{0.0, 0.0, 0.0, 0.0, 0.0, 0.0})),
305 throw cet::exception(
"CORSIKAGen") <<
"ShowerInputFiles and ShowerFluxConstants have different or invalid sizes!"<<
"\n";
319 produces< std::vector<simb::MCTruth> >();
320 produces< sumdata::RunData, art::InRun >();
326 sqlite3_close(
fdb[i]);
333 const double indxyz[],
344 const double dxyz[3]={-indxyz[0],-indxyz[1],-indxyz[2]};
350 if (dxyz[0] > 0.0) { dx = (xhi-xyz[0])/dxyz[0]; }
351 else if (dxyz[0] < 0.0) { dx = (xlo-xyz[0])/dxyz[0]; }
352 if (dxyz[1] > 0.0) { dy = (yhi-xyz[1])/dxyz[1]; }
353 else if (dxyz[1] < 0.0) { dy = (ylo-xyz[1])/dxyz[1]; }
354 if (dxyz[2] > 0.0) { dz = (zhi-xyz[2])/dxyz[2]; }
355 else if (dxyz[2] < 0.0) { dz = (zlo-xyz[2])/dxyz[2]; }
360 if (dx < dy && dx < dz) d = dx;
361 else if (dy < dz && dy < dx) d = dy;
362 else if (dz < dx && dz < dy) d = dz;
365 for (
int i = 0; i < 3; ++i) {
366 xyzout[i] = xyz[i] + dxyz[i]*
d;
379 const char* ifdh_debug_env =
std::getenv(
"IFDH_DEBUG_LEVEL");
380 if ( ifdh_debug_env ) {
381 mf::LogInfo(
"CORSIKAGen") <<
"IFDH_DEBUG_LEVEL: " << ifdh_debug_env<<
"\n";
382 fIFDH->set_debug(ifdh_debug_env);
389 std::vector<std::pair<std::string,long>> selectedflist;
394 mf::LogInfo(
"CorsikaGen") <<
"Selected"<<selectedflist.back().first<<
"\n";
398 std::vector<std::pair<std::string,long>>
flist;
401 flist =
fIFDH->findMatchingFiles(path,pattern);
402 unsigned int selIndex=-1;
405 }
else if(flist.size()>1){
406 selIndex= (
unsigned int) (
flat()*(flist.size()-1)+0.5);
410 selectedflist.push_back(flist[selIndex]);
412 <<
"\nFound "<< flist.size() <<
" candidate files" 413 <<
"\nChoosing file number "<< selIndex <<
"\n" 414 <<
"\nSelected "<<selectedflist.back().first<<
"\n";
420 std::vector<std::string> locallist;
421 for(
unsigned int i=0; i<selectedflist.size(); i++){
423 <<
"Fetching: "<<selectedflist[i].first<<
" "<<selectedflist[i].second<<
"\n";
426 MF_LOG_DEBUG(
"CorsikaGen") <<
"Fetched; local path: "<<fetchedfile <<
"; copy type: IFDH";
427 locallist.push_back(fetchedfile);
431 MF_LOG_DEBUG(
"CorsikaGen") <<
"Fetched; local path: "<<fetchedfile <<
"; copy type: DIRECT";
432 locallist.push_back(fetchedfile);
434 else throw cet::exception(
"CORSIKAGen") <<
"Error copying shower db: ShowerCopyType must be \"IFDH\" or \"DIRECT\"\n";
438 for(
unsigned int i=0; i<locallist.size(); i++){
440 int res=sqlite3_open(locallist[i].c_str(),&
fdb[i]);
442 throw cet::exception(
"CORSIKAGen") <<
"Error opening db: (" <<locallist[i].c_str()<<
") ("<<res<<
"): " << sqlite3_errmsg(
fdb[i]) <<
"; memory used:<<"<<sqlite3_memory_used()<<
"/"<<sqlite3_memory_highwater(0)<<
"\n";
444 mf::LogInfo(
"CORSIKAGen")<<
"Attached db "<< locallist[i]<<
"\n";
450 return (var - (high - low) * floor(var/(high-low))) + low;
455 boxno=
int(floor(var/(high-low)));
456 return (var - (high - low) * floor(var/(high-low))) + low;
463 const std::string kStatement(
"select min(t) from particles");
468 if ( sqlite3_prepare(
fdb[i], kStatement.c_str(), -1, &statement, 0 ) == SQLITE_OK ){
470 res = sqlite3_step(statement);
471 if ( res == SQLITE_ROW ){
472 t=sqlite3_column_double(statement,0);
473 mf::LogInfo(
"CORSIKAGen")<<
"For showers input "<< i<<
" found particles.min(t)="<<t<<
"\n";
476 throw cet::exception(
"CORSIKAGen") <<
"Unexpected sqlite3_step return value: (" <<res<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
479 throw cet::exception(
"CORSIKAGen") <<
"Error preparing statement: (" <<kStatement<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
500 for (
unsigned int bnd = 0; bnd<6; bnd++){
516 <<
"Area extended by : "<<fShowerAreaExtension
519 <<
"\nShowers to be distributed with random XZ shift: "<<
fRandomXZShift<<
" cm" 520 <<
"\nShowers to be distributed over area: "<<showersArea<<
" m^2" 521 <<
"\nShowers to be distributed over time: "<<
fSampleTime<<
" s" 522 <<
"\nShowers to be distributed with time offset: "<<
fToffset<<
" s" 523 <<
"\nShowers to be distributed at y: "<<
fShowerBounds[3]<<
" cm" 528 const std::string kStatement(
"select erange_high,erange_low,eslope,nshow from input");
529 double upperLimitOfEnergyRange=0.,lowerLimitOfEnergyRange=0.,energySlope=0.,oneMinusGamma=0.,EiToOneMinusGamma=0.,EfToOneMinusGamma=0.;
534 if ( sqlite3_prepare(
fdb[i], kStatement.c_str(), -1, &statement, 0 ) == SQLITE_OK ){
536 res = sqlite3_step(statement);
537 if ( res == SQLITE_ROW ){
538 upperLimitOfEnergyRange=sqlite3_column_double(statement,0);
539 lowerLimitOfEnergyRange=sqlite3_column_double(statement,1);
540 energySlope = sqlite3_column_double(statement,2);
541 fMaxShowers.push_back(sqlite3_column_int(statement,3));
542 oneMinusGamma = 1 + energySlope;
543 EiToOneMinusGamma =
pow(lowerLimitOfEnergyRange, oneMinusGamma);
544 EfToOneMinusGamma =
pow(upperLimitOfEnergyRange, oneMinusGamma);
545 mf::LogVerbatim(
"CORSIKAGen")<<
"For showers input "<< i<<
" found e_hi="<<upperLimitOfEnergyRange<<
", e_lo="<<lowerLimitOfEnergyRange<<
", slope="<<energySlope<<
", k="<<
fShowerFluxConstants[i]<<
"\n";
547 throw cet::exception(
"CORSIKAGen") <<
"Unexpected sqlite3_step return value: (" <<res<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
550 throw cet::exception(
"CORSIKAGen") <<
"Error preparing statement: (" <<kStatement<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
557 <<
" the number of showers per event is "<<(
int)NShowers<<
"\n";
574 static TDatabasePDG* pdgt = TDatabasePDG::Instance();
578 const TString kStatement(
"select shower,pdg,px,py,pz,x,z,t,e from particles where shower in (select id from showers ORDER BY substr(id*%f,length(id)+2) limit %d) ORDER BY substr(shower*%f,length(shower)+2)");
588 geom->
WorldBox(&x1, &x2, &y1, &y2, &z1, &z2);
592 double fBoxDelta=1.e-5;
606 double px,
py,
pz,
x,
z,tParticleTime,etot,showerTime=0.,showerTimex=0.,showerTimez=0.,showerXOffset=0.,showerZOffset=0.,
t;
611 while(nShowerCntr>0){
616 nShowerQry=nShowerCntr;
619 double thisrnd=
flat();
620 TString kthisStatement=
TString::Format(kStatement.Data(),thisrnd,nShowerQry,thisrnd);
621 MF_LOG_DEBUG(
"CORSIKAGen")<<
"Executing: "<<kthisStatement;
622 if ( sqlite3_prepare(
fdb[i], kthisStatement.Data(), -1, &statement, 0 ) == SQLITE_OK ){
626 res = sqlite3_step(statement);
627 if ( res == SQLITE_ROW ){
640 shower=sqlite3_column_int(statement,0);
641 if(shower!=lastShower){
650 pdg=sqlite3_column_int(statement,1);
653 TParticlePDG* pdgp = pdgt->GetParticle(pdg);
654 if (pdgp) m = pdgp->Mass();
658 px=sqlite3_column_double(statement,4);
659 py=sqlite3_column_double(statement,3);
660 pz=-sqlite3_column_double(statement,2);
661 etot=sqlite3_column_double(statement,8);
664 int boxnoX=0,boxnoZ=0;
667 tParticleTime=sqlite3_column_double(statement,7);
690 double dx[3]={
px,
py,pz};
693 TLorentzVector
pos(xyzo[0],xyzo[1],xyzo[2],t);
694 TLorentzVector mom(px,py,pz,etot);
699 }
else if ( res == SQLITE_DONE ){
702 throw cet::exception(
"CORSIKAGen") <<
"Unexpected sqlite3_step return value: (" <<res<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
706 throw cet::exception(
"CORSIKAGen") <<
"Error preparing statement: (" <<kthisStatement<<
"); "<<
"ERROR:"<<sqlite3_errmsg(
fdb[i])<<
"\n";
708 nShowerCntr=nShowerCntr-nShowerQry;
720 std::unique_ptr< std::vector<simb::MCTruth> > truthcol(
new std::vector<simb::MCTruth>);
731 for(
int i = 0; i < pretruth.
NParticles(); ++i){
733 const TLorentzVector& v4 = particle.
Position();
734 const TLorentzVector& p4 = particle.
Momentum();
735 double x0[3] = {v4.X(), v4.Y(), v4.Z() };
736 double dx[3] = {p4.Px(), p4.Py(), p4.Pz()};
746 for (
unsigned int cb=0; cb<6; cb++)
747 bounds[cb] = bounds[cb]+
fBuffBox[cb];
750 bool intersects_cryo =
false;
751 for (
int bnd=0; bnd!=6; ++bnd) {
753 double p2[3] = {bounds[bnd], x0[1] + (dx[1]/dx[0])*(bounds[bnd] - x0[0]), x0[2] + (dx[2]/dx[0])*(bounds[bnd] - x0[0])};
754 if ( p2[1] >= bounds[2] && p2[1] <= bounds[3] &&
755 p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
756 intersects_cryo =
true;
760 else if (bnd>=2 && bnd<4) {
761 double p2[3] = {x0[0] + (dx[0]/dx[1])*(bounds[bnd] - x0[1]), bounds[bnd], x0[2] + (dx[2]/dx[1])*(bounds[bnd] - x0[1])};
762 if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
763 p2[2] >= bounds[4] && p2[2] <= bounds[5] ) {
764 intersects_cryo =
true;
769 double p2[3] = {x0[0] + (dx[0]/dx[2])*(bounds[bnd] - x0[2]), x0[1] + (dx[1]/dx[2])*(bounds[bnd] - x0[2]), bounds[bnd]};
770 if ( p2[0] >= bounds[0] && p2[0] <= bounds[1] &&
771 p2[1] >= bounds[2] && p2[1] <= bounds[3] ) {
772 intersects_cryo =
true;
778 if (intersects_cryo){
786 mf::LogInfo(
"CORSIKAGen")<<
"Number of particles from getsample crossing cryostat + bounding box: "<<truth.
NParticles()<<
"\n";
788 truthcol->push_back(truth);
double fToffset
Time offset of sample, defaults to zero (no offset) [s].
double wrapvar(const double var, const double low, const double high)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const TLorentzVector & Position(const int i=0) const
double fSampleTime
Duration of sample [s].
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
double fProjectToHeight
Height to which particles will be projected [cm].
void SetOrigin(simb::Origin_t origin)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void WorldBox(double *xlo, double *xhi, double *ylo, double *yhi, double *zlo, double *zhi) const
Fills the arguments with the boundaries of the world.
EDProducer(fhicl::ParameterSet const &pset)
LArSoft interface to CORSIKA event generator.
struct sqlite3_stmt sqlite3_stmt
ifdh_ns::ifdh * fIFDH
(optional) flux file handling
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::vector< std::string > fShowerInputFiles
Set of CORSIKA shower data files to use.
void CryostatBoundaries(double *boundaries, geo::CryostatID const &cid) const
Returns the boundaries of the specified cryostat.
art framework interface to geometry description
int fShowerInputs
Number of shower inputs to process from.
sqlite3 * fdb[5]
Pointers to sqlite3 database object, max of 5.
#define DEFINE_ART_MODULE(klass)
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
std::vector< double > fShowerFluxConstants
Set of flux constants to be associated with each shower data file.
std::string getenv(std::string const &name)
void ProjectToBoxEdge(const double xyz[], const double dxyz[], const double xlo, const double xhi, const double ylo, const double yhi, const double zlo, const double zhi, double xyzout[])
Propagates a point back to the surface of a box.
CLHEP::HepRandomEngine & fPoisEngine
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
double wrapvarBoxNo(const double var, const double low, const double high, int &boxno)
std::vector< int > fMaxShowers
BoundingBox bounds(int x, int y, int w, int h)
const simb::MCParticle & GetParticle(int i) const
double fToffset_corsika
Timing offset to account for propagation time through atmosphere, populated from db.
std::string fShowerCopyType
void produce(art::Event &evt)
void Add(simb::MCParticle const &part)
const TLorentzVector & Momentum(const int i=0) const
double fRandomXZShift
Each shower will be shifted by a random amount in xz so that showers won't repeatedly sample the same...
double fShowerBounds[6]
Boundaries of area over which showers are to be distributed (x(min), x(max), unused, y, z(min), z(max) )
CORSIKAGen(fhicl::ParameterSet const &pset)
void beginRun(art::Run &run)
Event generator information.
void GetSample(simb::MCTruth &)
std::vector< double > fNShowersPerEvent
Number of showers to put in each event of duration fSampleTime; one per showerinput.
CLHEP::HepRandomEngine & fGenEngine
LArSoft geometry interface.
Event Generation using GENIE, cosmics or single particles.
void openDBs(std::string const &module_label)
double fShowerAreaExtension
Extend distribution of corsika particles in x,z by this much (e.g. 1000 will extend 10 m in -x...
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
std::vector< double > fBuffBox
Buffer box extensions to cryostat in each direction (6 of them: x_lo,x_hi,y_lo,y_hi,z_lo,z_hi) [cm].