9 #include "TDatabasePDG.h" 31 #include "CLHEP/Random/RandFlat.h" 32 #include "CLHEP/Random/RandPoissonQ.h" 230 void openDBs(std::string
const& module_label);
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);
309 ,
fToffset(p.get<
double>(
"TimeOffset", 0.))
310 ,
fBuffBox(p.get<std::vector<double>>(
"BufferBox", {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}))
318 {
"Seed",
"SeedGenerator"}))
329 <<
"ShowerInputFiles and ShowerFluxConstants have different or invalid sizes!" 339 this->
openDBs(p.get<std::string>(
"module_label"));
343 produces<std::vector<simb::MCTruth>>();
344 produces<sumdata::RunData, art::InRun>();
350 sqlite3_close(
fdb[i]);
357 const double indxyz[],
368 const double dxyz[3] = {-indxyz[0], -indxyz[1], -indxyz[2]};
374 if (dxyz[0] > 0.0) { dx = (xhi - xyz[0]) / dxyz[0]; }
375 else if (dxyz[0] < 0.0) {
376 dx = (xlo - xyz[0]) / dxyz[0];
378 if (dxyz[1] > 0.0) { dy = (yhi - xyz[1]) / dxyz[1]; }
379 else if (dxyz[1] < 0.0) {
380 dy = (ylo - xyz[1]) / dxyz[1];
382 if (dxyz[2] > 0.0) { dz = (zhi - xyz[2]) / dxyz[2]; }
383 else if (dxyz[2] < 0.0) {
384 dz = (zlo - xyz[2]) / dxyz[2];
389 if (dx < dy && dx < dz)
391 else if (dy < dz && dy < dx)
393 else if (dz < dx && dz < dy)
397 for (
int i = 0; i < 3; ++i) {
398 xyzout[i] = xyz[i] + dxyz[i] *
d;
411 const char* ifdh_debug_env = std::getenv(
"IFDH_DEBUG_LEVEL");
412 if (ifdh_debug_env) {
413 mf::LogInfo(
"CORSIKAGen") <<
"IFDH_DEBUG_LEVEL: " << ifdh_debug_env <<
"\n";
414 fIFDH->set_debug(ifdh_debug_env);
421 std::vector<std::pair<std::string, long>> selectedflist;
426 mf::LogInfo(
"CorsikaGen") <<
"Selected" << selectedflist.back().first <<
"\n";
431 std::vector<std::pair<std::string, long>> flist;
434 flist =
fIFDH->findMatchingFiles(path, pattern);
435 unsigned int selIndex = -1;
436 if (flist.size() == 1) {
439 else if (flist.size() > 1) {
440 selIndex = (
unsigned int)(flat() * (flist.size() - 1) +
445 <<
"No files returned for path:pattern: " << path <<
":" << pattern << std::endl;
447 selectedflist.push_back(flist[selIndex]);
449 << flist.size() <<
" candidate files" 450 <<
"\nChoosing file number " << selIndex <<
"\n" 451 <<
"\nSelected " << selectedflist.back().first <<
"\n";
456 std::vector<std::string> locallist;
457 for (
unsigned int i = 0; i < selectedflist.size(); i++) {
458 mf::LogInfo(
"CorsikaGen") <<
"Fetching: " << selectedflist[i].first <<
" " 459 << selectedflist[i].second <<
"\n";
461 std::string fetchedfile(
fIFDH->fetchInput(selectedflist[i].first));
462 MF_LOG_DEBUG(
"CorsikaGen") <<
"Fetched; local path: " << fetchedfile <<
"; copy type: IFDH";
463 locallist.push_back(fetchedfile);
466 std::string fetchedfile(selectedflist[i].first);
468 <<
"Fetched; local path: " << fetchedfile <<
"; copy type: DIRECT";
469 locallist.push_back(fetchedfile);
473 <<
"Error copying shower db: ShowerCopyType must be \"IFDH\" or \"DIRECT\"\n";
477 for (
unsigned int i = 0; i < locallist.size(); i++) {
479 int res = sqlite3_open(locallist[i].c_str(), &
fdb[i]);
480 if (res != SQLITE_OK)
482 <<
"Error opening db: (" << locallist[i].c_str() <<
") (" << res
483 <<
"): " << sqlite3_errmsg(
fdb[i]) <<
"; memory used:<<" << sqlite3_memory_used() <<
"/" 484 << sqlite3_memory_highwater(0) <<
"\n";
486 mf::LogInfo(
"CORSIKAGen") <<
"Attached db " << locallist[i] <<
"\n";
493 return (var - (high - low) * floor(var / (high - low))) + low;
499 boxno = int(floor(var / (high - low)));
500 return (var - (high - low) * floor(var / (high - low))) + low;
507 sqlite3_stmt* statement;
508 const std::string kStatement(
"select min(t) from particles");
513 if (sqlite3_prepare(
fdb[i], kStatement.c_str(), -1, &statement, 0) == SQLITE_OK) {
515 res = sqlite3_step(statement);
516 if (res == SQLITE_ROW) {
517 t = sqlite3_column_double(statement, 0);
519 <<
"For showers input " << i <<
" found particles.min(t)=" << t <<
"\n";
524 <<
"Unexpected sqlite3_step return value: (" << res <<
"); " 525 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
529 throw cet::exception(
"CORSIKAGen") <<
"Error preparing statement: (" << kStatement <<
"); " 530 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
549 double bounds[6] = {0.};
550 cryostat.Boundaries(bounds);
551 for (
unsigned int bnd = 0; bnd < 6; bnd++) {
552 mf::LogVerbatim(
"CORSIKAGen") <<
"Cryo Boundary: " << bnd <<
"=" << bounds[bnd]
553 <<
" ( + Buffer=" <<
fBuffBox[bnd] <<
")\n";
566 mf::LogInfo(
"CORSIKAGen") <<
"Area extended by : " << fShowerAreaExtension
567 <<
"\nShowers to be distributed betweeen: x=" <<
fShowerBounds[0]
570 <<
"\nShowers to be distributed with random XZ shift: " 572 <<
"\nShowers to be distributed over area: " << showersArea <<
" m^2" 573 <<
"\nShowers to be distributed over time: " <<
fSampleTime <<
" s" 574 <<
"\nShowers to be distributed with time offset: " <<
fToffset 576 <<
"\nShowers to be distributed at y: " <<
fShowerBounds[3] <<
" cm";
579 sqlite3_stmt* statement;
580 const std::string kStatement(
"select erange_high,erange_low,eslope,nshow from input");
581 double upperLimitOfEnergyRange = 0., lowerLimitOfEnergyRange = 0., energySlope = 0.,
582 oneMinusGamma = 0., EiToOneMinusGamma = 0., EfToOneMinusGamma = 0.;
587 if (sqlite3_prepare(
fdb[i], kStatement.c_str(), -1, &statement, 0) == SQLITE_OK) {
589 res = sqlite3_step(statement);
590 if (res == SQLITE_ROW) {
591 upperLimitOfEnergyRange = sqlite3_column_double(statement, 0);
592 lowerLimitOfEnergyRange = sqlite3_column_double(statement, 1);
593 energySlope = sqlite3_column_double(statement, 2);
594 fMaxShowers.push_back(sqlite3_column_int(statement, 3));
595 oneMinusGamma = 1 + energySlope;
596 EiToOneMinusGamma = pow(lowerLimitOfEnergyRange, oneMinusGamma);
597 EfToOneMinusGamma = pow(upperLimitOfEnergyRange, oneMinusGamma);
599 <<
"For showers input " << i <<
" found e_hi=" << upperLimitOfEnergyRange
600 <<
", e_lo=" << lowerLimitOfEnergyRange <<
", slope=" << energySlope
605 <<
"Unexpected sqlite3_step return value: (" << res <<
"); " 606 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
610 throw cet::exception(
"CORSIKAGen") <<
"Error preparing statement: (" << kStatement <<
"); " 611 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
616 (EfToOneMinusGamma - EiToOneMinusGamma) / oneMinusGamma) *
620 <<
"For showers input " << i <<
" the number of showers per event is " << (int)NShowers
639 static TDatabasePDG* pdgt = TDatabasePDG::Instance();
642 sqlite3_stmt* statement;
643 const TString kStatement(
644 "select shower,pdg,px,py,pz,x,z,t,e from particles where shower in (select id from showers " 645 "ORDER BY substr(id*%f,length(id)+2) limit %d) ORDER BY substr(shower*%f,length(shower)+2)");
655 geom->
WorldBox(&x1, &x2, &y1, &y2, &z1, &z2);
659 double fBoxDelta = 1.e-5;
674 double px, py, pz,
x,
z, tParticleTime, etot,
675 showerTime = 0., showerTimex = 0., showerTimez = 0., showerXOffset = 0., showerZOffset = 0.,
680 <<
" generating " << nShowerCntr;
682 while (nShowerCntr > 0) {
688 nShowerQry = nShowerCntr;
691 double thisrnd = flat();
692 TString kthisStatement = TString::Format(kStatement.Data(), thisrnd, nShowerQry, thisrnd);
693 MF_LOG_DEBUG(
"CORSIKAGen") <<
"Executing: " << kthisStatement;
694 if (sqlite3_prepare(
fdb[i], kthisStatement.Data(), -1, &statement, 0) == SQLITE_OK) {
698 res = sqlite3_step(statement);
699 if (res == SQLITE_ROW) {
712 shower = sqlite3_column_int(statement, 0);
713 if (shower != lastShower) {
722 pdg = sqlite3_column_int(statement, 1);
725 TParticlePDG* pdgp = pdgt->GetParticle(pdg);
726 if (pdgp) m = pdgp->Mass();
730 px = sqlite3_column_double(statement, 4);
731 py = sqlite3_column_double(statement, 3);
732 pz = -sqlite3_column_double(statement, 2);
733 etot = sqlite3_column_double(statement, 8);
736 int boxnoX = 0, boxnoZ = 0;
737 x =
wrapvarBoxNo(sqlite3_column_double(statement, 6) + showerXOffset,
741 z =
wrapvarBoxNo(-sqlite3_column_double(statement, 5) + showerZOffset,
745 tParticleTime = sqlite3_column_double(
753 showerTimex * boxnoX + showerTimez * boxnoZ;
770 double dx[3] = {px, py, pz};
774 xyzo[0], xyzo[1], xyzo[2], t);
775 TLorentzVector mom(px, py, pz, etot);
781 else if (res == SQLITE_DONE) {
786 <<
"Unexpected sqlite3_step return value: (" << res <<
"); " 787 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
793 <<
"Error preparing statement: (" << kthisStatement <<
"); " 794 <<
"ERROR:" << sqlite3_errmsg(
fdb[i]) <<
"\n";
796 nShowerCntr = nShowerCntr - nShowerQry;
809 std::unique_ptr<std::vector<simb::MCTruth>> truthcol(
new std::vector<simb::MCTruth>);
821 for (
int i = 0; i < pretruth.
NParticles(); ++i) {
823 const TLorentzVector& v4 = particle.
Position();
824 const TLorentzVector& p4 = particle.
Momentum();
825 double x0[3] = {v4.X(), v4.Y(), v4.Z()};
826 double dx[3] = {p4.Px(), p4.Py(), p4.Pz()};
831 double bounds[6] = {0.};
832 cryostat.Boundaries(bounds);
836 for (
unsigned int cb = 0; cb < 6; cb++)
837 bounds[cb] = bounds[cb] +
fBuffBox[cb];
840 bool intersects_cryo =
false;
841 for (
int bnd = 0; bnd != 6; ++bnd) {
843 double p2[3] = {bounds[bnd],
844 x0[1] + (dx[1] / dx[0]) * (bounds[bnd] - x0[0]),
845 x0[2] + (dx[2] / dx[0]) * (bounds[bnd] - x0[0])};
846 if (p2[1] >= bounds[2] && p2[1] <= bounds[3] && p2[2] >= bounds[4] &&
847 p2[2] <= bounds[5]) {
848 intersects_cryo =
true;
852 else if (bnd >= 2 && bnd < 4) {
853 double p2[3] = {x0[0] + (dx[0] / dx[1]) * (bounds[bnd] - x0[1]),
855 x0[2] + (dx[2] / dx[1]) * (bounds[bnd] - x0[1])};
856 if (p2[0] >= bounds[0] && p2[0] <= bounds[1] && p2[2] >= bounds[4] &&
857 p2[2] <= bounds[5]) {
858 intersects_cryo =
true;
863 double p2[3] = {x0[0] + (dx[0] / dx[2]) * (bounds[bnd] - x0[2]),
864 x0[1] + (dx[1] / dx[2]) * (bounds[bnd] - x0[2]),
866 if (p2[0] >= bounds[0] && p2[0] <= bounds[1] && p2[1] >= bounds[2] &&
867 p2[1] <= bounds[3]) {
868 intersects_cryo =
true;
874 if (intersects_cryo) {
883 <<
"Number of particles from getsample crossing cryostat + bounding box: " 886 truthcol->push_back(truth);
887 evt.
put(std::move(truthcol));
details::range_type< T > Iterate() const
Initializes the specified ID with the ID of the first cryostat.
base_engine_t & createEngine(seed_t seed)
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].
Float_t y1[n_points_granero]
void SetOrigin(simb::Origin_t origin)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< std::string > fShowerInputFiles
Set of CORSIKA shower data files to use.
void WorldBox(double *xlo, double *xhi, double *ylo, double *yhi, double *zlo, double *zhi) const
Fills the arguments with the boundaries of the world.
Float_t x1[n_points_granero]
EDProducer(fhicl::ParameterSet const &pset)
LArSoft interface to CORSIKA event generator.
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
ifdh_ns::ifdh * fIFDH
(optional) flux file handling
Geometry information for a single cryostat.
Float_t y2[n_points_geant4]
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
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)
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
double wrapvarBoxNo(const double var, const double low, const double high, int &boxno)
std::vector< int > fMaxShowers
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
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)
std::vector< double > fShowerFluxConstants
Set of flux constants to be associated with each shower data file.
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)
std::string const & DetectorName() const
Returns a string with the name of the detector, as configured.
Event generator information.
Float_t x2[n_points_geant4]
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
Namespace collecting geometry-related classes utilities.
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...
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
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].