41 #include <TGeoManager.h> 42 #include <TGeoMaterial.h> 44 #include <TGeoVolume.h> 55 #include "cetlib_except/exception.h" 60 #include "nurandom/RandomUtils/NuRandomService.h" 65 #include "nugen/EventGeneratorBase/evgenbase.h" 87 #include "TLorentzVector.h" 88 #include "TGenPhaseSpace.h" 95 #include "CLHEP/Random/RandFlat.h" 96 #include "CLHEP/Random/RandPoisson.h" 98 namespace simb {
class MCTruth; }
199 std::size_t addvolume(
std::string const& volumeName);
202 void SampleOne(
unsigned int i,
205 TLorentzVector dirCalc(
double p,
double m);
208 void samplespectrum(
std::string nuclide,
int &itype,
double &
t,
double &
m,
double &
p);
210 void Ar42Gamma2(
std::vector<std::tuple<ti_PDGID, td_Mass, TLorentzVector>>& v_prods);
211 void Ar42Gamma3(
std::vector<std::tuple<ti_PDGID, td_Mass, TLorentzVector>>& v_prods);
212 void Ar42Gamma4(
std::vector<std::tuple<ti_PDGID, td_Mass, TLorentzVector>>& v_prods);
213 void Ar42Gamma5(
std::vector<std::tuple<ti_PDGID, td_Mass, TLorentzVector>>& v_prods);
216 double samplefromth1d(TH1D&
hist);
219 template <
typename Stream>
220 void dumpNuclideSettings
221 (Stream&& out, std::size_t iNucl,
std::string const& volumeName = {})
226 std::pair<double, double> defaulttimewindow()
const;
271 constexpr
double m_e = 0.000510998928;
272 constexpr
double m_alpha = 3.727379240;
273 constexpr
double m_neutron = 0.9395654133;
282 ,
fX0{pset.get< std::vector<double> >(
"X0", {})}
283 ,
fY0{pset.get< std::vector<double> >(
"Y0", {})}
284 ,
fZ0{pset.get< std::vector<double> >(
"Z0", {})}
285 ,
fX1{pset.get< std::vector<double> >(
"X1", {})}
286 ,
fY1{pset.get< std::vector<double> >(
"Y1", {})}
287 ,
fZ1{pset.get< std::vector<double> >(
"Z1", {})}
293 produces< std::vector<simb::MCTruth> >();
294 produces< sumdata::RunData, art::InRun >();
297 auto const nuclide = pset.get< std::vector<std::string>>(
"Nuclide");
298 auto const material = pset.get< std::vector<std::string>>(
"Material");
299 auto const Bq = pset.get< std::vector<double> >(
"BqPercc");
300 auto t0 = pset.get< std::vector<double> >(
"T0", {});
301 auto t1 = pset.get< std::vector<double> >(
"T1", {});
303 if (
fT0.empty() ||
fT1.empty()) {
304 if (!
fT0.empty() || !
fT1.empty()) {
306 <<
"RadioGen T0 and T1 need to be both non-empty, or both empty" 307 " (now T0 has " <<
fT0.size() <<
" entries and T1 has " <<
fT0.size()
311 t0.push_back(defaultT0);
312 t1.push_back(defaultT1);
321 mf::LogInfo(
"RadioGen") <<
"Configuring activity:";
324 fNuclide.push_back(nuclide.at(iCoord));
325 fMaterial.push_back(material.at(iCoord));
326 fBq.push_back(Bq.at(iCoord));
328 fT0.push_back(t0[
std::min(iCoord, t0.size() - 1U)]);
329 fT1.push_back(t1[
std::min(iCoord, t1.size() - 1U)]);
335 std::size_t iNext =
fX0.size();
336 auto const volumes = pset.get<std::vector<std::string>>(
"Volumes", {});
339 auto const nVolumes =
addvolume(volName);
342 <<
"No volume named '" << volName <<
"' was found!\n";
345 std::size_t
const iVolFirst =
fNuclide.size();
347 fNuclide.push_back(nuclide.at(iNext));
349 fBq.push_back(Bq.at(iNext));
351 fT0.push_back(t0[
std::min(iNext, t0.size() - 1U)]);
352 fT1.push_back(t1[
std::min(iNext, t1.size() - 1U)]);
362 unsigned int nsize =
fNuclide.size();
365 <<
"No nuclide configured!\n";
368 if (
fMaterial.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Material vector and Nuclide vector\n";
369 if (
fBq.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Bq vector and Nuclide vector\n";
370 if (
fT0.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size T0 vector and Nuclide vector\n";
371 if (
fT1.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size T1 vector and Nuclide vector\n";
372 if (
fX0.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size X0 vector and Nuclide vector\n";
373 if (
fY0.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Y0 vector and Nuclide vector\n";
374 if (
fZ0.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Z0 vector and Nuclide vector\n";
375 if (
fX1.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size X1 vector and Nuclide vector\n";
376 if (
fY1.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Y1 vector and Nuclide vector\n";
377 if (
fZ1.size() != nsize )
throw cet::exception(
"RadioGen") <<
"Different size Z1 vector and Nuclide vector\n";
380 if(nuclideName==
"39Ar" ){
readfile(
"39Ar",
"Argon_39.root") ;}
381 else if(nuclideName==
"60Co" ){
readfile(
"60Co",
"Cobalt_60.root") ;}
382 else if(nuclideName==
"85Kr" ){
readfile(
"85Kr",
"Krypton_85.root") ;}
383 else if(nuclideName==
"40K" ){
readfile(
"40K",
"Potassium_40.root") ;}
384 else if(nuclideName==
"232Th"){
readfile(
"232Th",
"Thorium_232.root");}
385 else if(nuclideName==
"238U" ){
readfile(
"238U",
"Uranium_238.root") ;}
386 else if(nuclideName==
"222Rn"){
continue;}
387 else if(nuclideName==
"59Ni"){
continue;}
388 else if(nuclideName==
"42Ar" ){
389 readfile(
"42Ar_1",
"Argon_42_1.root");
390 readfile(
"42Ar_2",
"Argon_42_2.root");
391 readfile(
"42Ar_3",
"Argon_42_3.root");
392 readfile(
"42Ar_4",
"Argon_42_4.root");
393 readfile(
"42Ar_5",
"Argon_42_5.root");
415 std::unique_ptr< std::vector<simb::MCTruth> > truthcol(
new std::vector<simb::MCTruth>);
421 for (
unsigned int i=0; i<
fNuclide.size(); ++i) {
426 truthcol->push_back(truth);
433 auto const& geom = *(lar::providerFrom<geo::Geometry>());
435 std::vector<geo::GeoNodePath> volumePaths;
436 auto findVolume = [&volumePaths, volumeName](
auto& path)
438 if (path.current().GetVolume()->GetName() == volumeName)
439 volumePaths.push_back(path);
445 navigator.
apply(findVolume);
452 TGeoShape
const* pShape = path.current().GetVolume()->GetShape();
453 auto pBox =
dynamic_cast<TGeoBBox
const*
>(pShape);
456 << path.current().GetName() <<
"' is a " << pShape->IsA()->GetName()
457 <<
", not a TGeoBBox.\n";
461 = geo::vect::makeFromCoords<geo::Point_t>(pBox->GetOrigin());
463 = { pBox->GetDX(), pBox->GetDY(), pBox->GetDZ() };
473 trans.Transform(origin - diag, min);
474 trans.Transform(origin + diag, max);
488 return volumePaths.size();
501 CLHEP::RandPoisson poisson(
fEngine);
507 long ndecays = poisson.shoot(rate);
509 std::regex
const re_material{
fMaterial[i]};
510 for (
unsigned int idecay=0; idecay<ndecays; idecay++)
517 TLorentzVector
pos(
fX0[i] + flat.fire()*(
fX1[i] -
fX0[i]),
523 std::string volmaterial = geomanager->FindNode(
pos.X(),
pos.Y(),
pos.Z())->GetMedium()->GetMaterial()->GetName();
524 if (!std::regex_match(volmaterial, re_material))
continue;
530 std::vector<std::tuple<ti_PDGID, td_Mass, TLorentzVector>> v_prods;
536 double p2 = energy*energy - m*
m;
537 if (p2 > 0) p = TMath::Sqrt(p2);
539 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
543 v_prods.emplace_back(pdgid, m,
dirCalc(p,m));
547 double bSelect = flat.fire();
550 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
552 }
else if(bSelect<0.9954){
554 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
556 }
else if(bSelect<0.9988){
558 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
560 }
else if(bSelect<0.9993){
562 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
566 v_prods.emplace_back(pdgid, m,
dirCalc(p, m));
575 std::tuple<ti_PDGID, td_Mass, TLorentzVector> partMassMom = std::make_tuple(pdgid, m,
dirCalc(p,m));
576 v_prods.push_back(partMassMom);
580 for(
auto prodEntry : v_prods){
583 ti_PDGID pdgid = std::get<0>(prodEntry);
585 TLorentzVector pvec = std::get<2>(prodEntry);
591 if (pdgid == 1000020040){
610 double costheta = (2.0*flat.fire() - 1.0);
611 if (costheta < -1.0) costheta = -1.0;
612 if (costheta > 1.0) costheta = 1.0;
613 double const sintheta = sqrt(1.0-costheta*costheta);
614 double const phi = 2.0*
M_PI*flat.fire();
615 return TLorentzVector{p*sintheta*std::cos(phi),
616 p*sintheta*std::sin(phi),
626 std::regex
const re_argon{
"42Ar.*"};
627 for (
size_t i=0; i<
fNuclide.size(); i++)
633 else if (std::regex_match(nuclide, re_argon) &&
fNuclide[i]==
"42Ar") {
640 Bool_t addStatus = TH1::AddDirectoryStatus();
641 TH1::AddDirectory(kFALSE);
651 if (fullname.empty() ||
stat(fullname.c_str(), &sb)!=0)
654 <<
" not found in FW_SEARCH_PATH!\n";
656 TFile
f(fullname.c_str(),
"READ");
657 TGraph *alphagraph = (TGraph*)
f.Get(
"Alphas");
658 TGraph *betagraph = (TGraph*)
f.Get(
"Betas");
659 TGraph *gammagraph = (TGraph*)
f.Get(
"Gammas");
660 TGraph *neutrongraph = (TGraph*)
f.Get(
"Neutrons");
664 int np = alphagraph->GetN();
665 double *
y = alphagraph->GetY();
670 auto alphahist = std::make_unique<TH1D>(name.c_str(),
"Alpha Spectrum",np,0,np);
671 for (
int i=0; i<np; i++) {
672 alphahist->SetBinContent(i+1,y[i]);
673 alphahist->SetBinError(i+1,0);
687 int np = betagraph->GetN();
689 double *
y = betagraph->GetY();
694 auto betahist = std::make_unique<TH1D>(name.c_str(),
"Beta Spectrum",np,0,np);
695 for (
int i=0; i<np; i++) {
696 betahist->SetBinContent(i+1,y[i]);
697 betahist->SetBinError(i+1,0);
710 int np = gammagraph->GetN();
711 double *
y = gammagraph->GetY();
716 auto gammahist = std::make_unique<TH1D>(name.c_str(),
"Gamma Spectrum",np,0,np);
717 for (
int i=0; i<np; i++) {
718 gammahist->SetBinContent(i+1,y[i]);
719 gammahist->SetBinError(i+1,0);
732 int np = neutrongraph->GetN();
733 double *
y = neutrongraph->GetY();
738 auto neutronhist = std::make_unique<TH1D>(name.c_str(),
"Neutron Spectrum",np,0,np);
739 for (
int i=0; i<np; i++)
741 neutronhist->SetBinContent(i+1,y[i]);
742 neutronhist->SetBinError(i+1,0);
754 TH1::AddDirectory(addStatus);
784 throw cet::exception(
"RadioGen") <<
"Ununderstood nuclide: " << nuclide <<
"\n";
787 double rtype = flat.fire();
792 for (
int itry=0;itry<10;itry++)
818 if (itype >= 0)
break;
822 throw cet::exception(
"RadioGen") <<
"Normalization problem with nuclide: " << nuclide <<
"\n";
827 { p = TMath::Sqrt(p); }
839 int nbinsx = hist.GetNbinsX();
840 std::vector<double> partialsum;
841 partialsum.resize(nbinsx+1);
844 for (
int i=1;i<=
nbinsx;i++)
846 double hc = hist.GetBinContent(i);
847 if ( hc < 0)
throw cet::exception(
"RadioGen") <<
"Negative bin: " << i <<
" " << hist.GetName() <<
"\n";
848 partialsum[i] = partialsum[i-1] + hc;
851 if (integral == 0)
return 0;
853 for (
int i=1;i<=
nbinsx;i++) partialsum[i] /= integral;
855 double r1 = flat.fire();
856 int ibin = TMath::BinarySearch(nbinsx,&(partialsum[0]),r1);
857 Double_t
x = hist.GetBinLowEdge(ibin+1);
858 if (r1 > partialsum[ibin]) {
859 x += hist.GetBinWidth(ibin+1)*(r1-partialsum[ibin])/(partialsum[ibin+1] - partialsum[ibin]);
875 std::vector<double> vd_p = {.0015246};
877 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
884 std::vector<double> vd_p = {.0003126};
886 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
895 double chan1 = (0.052 / (0.052+0.020) );
896 if(flat.fire()<chan1){
897 std::vector<double> vd_p = {.0008997};
899 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
903 std::vector<double> vd_p = {.0024243};
905 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
914 double chan1 = ( 0.0033 / (0.0033 + 0.0201 + 0.041) );
double chan2 = ( 0.0201 / (0.0033 + 0.0201 + 0.041) );
915 double chanPick = flat.fire();
916 if(chanPick < chan1){
917 std::vector<double> vd_p = {0.000692, 0.001228};
919 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
922 }
else if (chanPick<(chan1+chan2)){
923 std::vector<double> vd_p = {0.0010212};
925 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
929 std::vector<double> vd_p = {0.0019208};
931 v_prods.emplace_back(pdgid, m,
dirCalc(
p, m));
960 template <
typename Stream>
966 out <<
"[#" << iNucl <<
"] " 968 <<
" (" <<
fBq[iNucl] <<
" Bq/cm^3)" 970 <<
" from " <<
fT0[iNucl] <<
" to " <<
fT1[iNucl] <<
" ns in ( " 971 <<
fX0[iNucl] <<
", " <<
fY0[iNucl] <<
", " <<
fZ0[iNucl] <<
") to ( " 972 <<
fX1[iNucl] <<
", " <<
fY1[iNucl] <<
", " <<
fZ1[iNucl] <<
")";
973 if (!volumeName.empty()) out <<
" (\"" << volumeName <<
"\")";
994 auto const trigTimeTick
1001 double(timings.toTimeScale<
simulation_time>(trigTimeTick + beforeTicks)),
1002 double(timings.toTimeScale<
simulation_time>(trigTimeTick + afterTicks))
code to link reconstructed objects back to the MC truth information
std::vector< std::unique_ptr< TH1D > > gammaspectrum
Utilities to extend the interface of geometry vectors.
TLorentzVector dirCalc(double p, double m)
timescale_traits< ElectronicsTimeCategory >::tick_t electronics_tick
A point on the electronics time scale expressed in its ticks.
bool apply(geo::GeoNodePath &path, Op &&op) const
Applies the specified operation to all nodes under the path.
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
std::vector< double > fZ0
Bottom corner z position (cm) in world coordinates.
void SetOrigin(simb::Origin_t origin)
Executes an operation on all the nodes of the ROOT geometry.
Definition of util::enumerate().
std::vector< std::string > fNuclide
List of nuclides to simulate. Example: "39Ar".
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::pair< double, double > defaulttimewindow() const
Returns the start and end of the readout window.
Class representing a path in ROOT geometry.
unsigned int ReadOutWindowSize() const
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Class representing a path in ROOT geometry.
void Ar42Gamma5(std::vector< std::tuple< ti_PDGID, td_Mass, TLorentzVector >> &v_prods)
void dumpNuclideSettings(Stream &&out, std::size_t iNucl, std::string const &volumeName={}) const
Prints the settings for the specified nuclide and volume.
void readfile(std::string nuclide, std::string const &filename)
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
std::vector< double > neutronintegral
art framework interface to geometry description
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
std::vector< std::string > spectrumname
Interface to detinfo::DetectorClocks.
std::vector< std::unique_ptr< TH1D > > alphaspectrum
std::vector< double > fT1
End of time window to simulate in ns.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
std::vector< double > fY1
Top corner y position (cm) in world coordinates.
timescale_traits< ElectronicsTimeCategory >::tick_interval_t electronics_time_ticks
An interval on the electronics time scale expressed in its ticks.
#define DEFINE_ART_MODULE(klass)
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
timescale_traits< SimulationTimeCategory >::time_point_t simulation_time
A point in time on the simulation time scale.
std::vector< double > fZ1
Top corner z position (cm) in world coordinates.
single particles thrown at the detector
detinfo::DetectorTimings makeDetectorTimings(detinfo::DetectorClocksData const &detClocks)
int trackidcounter
Serial number for the MC track ID.
void SampleOne(unsigned int i, simb::MCTruth &mct)
Checks that the node represents a box well aligned to world frame axes.
void Ar42Gamma3(std::vector< std::tuple< ti_PDGID, td_Mass, TLorentzVector >> &v_prods)
unsigned int NumberTimeSamples() const
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Test of util::counter and support utilities.
static int max(int a, int b)
void beginRun(art::Run &run)
Module to generate particles created by radiological decay, patterned off of SingleGen.
Base utilities and modules for event generation and detector simulation.
double samplefromth1d(TH1D &hist)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
std::vector< double > alphaintegral
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
std::size_t addvolume(std::string const &volumeName)
void samplespectrum(std::string nuclide, int &itype, double &t, double &m, double &p)
std::vector< double > betaintegral
void Add(simb::MCParticle const &part)
void Ar42Gamma2(std::vector< std::tuple< ti_PDGID, td_Mass, TLorentzVector >> &v_prods)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
CLHEP::HepRandomEngine & fEngine
std::vector< double > fT0
Beginning of time window to simulate in ns.
std::string find_file(std::string const &filename) const
Definitions of geometry vector data types.
Access the description of detector geometry.
Representation of a node and its ancestry.
void Ar42Gamma4(std::vector< std::tuple< ti_PDGID, td_Mass, TLorentzVector >> &v_prods)
std::vector< std::unique_ptr< TH1D > > neutronspectrum
std::vector< std::string > fMaterial
List of regexes of materials in which to generate the decays. Example: "LAr".
std::vector< double > fX0
Bottom corner x position (cm) in world coordinates.
Event generator information.
bool fIsFirstSignalSpecial
std::vector< double > gammaintegral
std::vector< double > fBq
Radioactivity in Becquerels (decay per sec) per cubic cm.
LArSoft geometry interface.
Event Generation using GENIE, cosmics or single particles.
Namespace including different time scales as defined in LArSoft.
nbinsx
New: trying to make a variation.
std::vector< std::unique_ptr< TH1D > > betaspectrum
std::vector< double > fX1
Top corner x position (cm) in world coordinates.
ROOT::Math::Transform3D TransformationMatrix
Type of transformation matrix used in geometry.
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
std::vector< double > fY0
Bottom corner y position (cm) in world coordinates.
void produce(art::Event &evt)