18 #include "art/Framework/Core/EDProducer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Framework/Principal/Event.h"
21 #include "art/Framework/Principal/Run.h"
22 #include "art/Framework/Services/Registry/ServiceHandle.h"
23 #include "art_root_io/TFileService.h"
24 #include "art_root_io/TFileDirectory.h"
25 #include "canvas/Persistency/Common/Assns.h"
26 #include "cetlib_except/exception.h"
27 #include "fhiclcpp/ParameterSet.h"
28 #include "fhiclcpp/types/OptionalAtom.h"
29 #include "fhiclcpp/types/Table.h"
30 #include "messagefacility/MessageLogger/MessageLogger.h"
31 #include "art/Persistency/Common/PtrMaker.h"
34 #include "nurandom/RandomUtils/NuRandomService.h"
42 #include "nusimdata/SimulationBase/MCTruth.h"
51 #include "marley/marley_root.hh"
52 #include "marley/marley_utils.hh"
53 #include "marley/Integrator.hh"
60 constexpr
int MAX_UNIFORM_ENERGY_ITERATIONS = 1000;
64 constexpr
double ONE = 1.;
68 constexpr
int NUM_INTEGRATION_SAMPLING_POINTS = 100;
72 constexpr
double MeV_to_erg = 1.6021766208e-6;
75 constexpr std::array<int, 4> NU_X_PDG_CODES
77 marley_utils::MUON_NEUTRINO, marley_utils::MUON_ANTINEUTRINO,
78 marley_utils::TAU_NEUTRINO, marley_utils::TAU_ANTINEUTRINO,
83 bool is_nux(
int pdg_code) {
89 const std::regex rx_comment_or_empty = std::regex(
"\\s*(#.*)?");
93 double flux_averaged_total_xs(marley::NeutrinoSource& nu_source,
99 double flux_averaged_total_xs(marley::NeutrinoSource& nu_source,
104 double integrate(
const std::function<
double(
double)>& f,
double x_min,
124 return {
"marley_parameters" };
131 fhicl::Table<evgen::ActiveVolumeVertexSampler::Config>
vertex_ {
133 Comment(
"Configuration for selecting the vertex location(s)")
143 Name(
"sampling_mode"),
144 Comment(
"Technique to use when sampling times and energies. Valid"
145 " options are \"histogram\", \"uniform time\","
146 " and \"uniform energy\""),
147 std::string(
"histogram")
151 Name(
"nu_per_event"),
152 Comment(
"The number of neutrino vertices to generate in"
158 Name(
"spectrum_file_format"),
159 Comment(
"Format to assume for the neutrino spectrum file."
160 " Valid options are \"th2d\" (a ROOT file containing a "
161 " TH2D object) and \"fit\" (an ASCII text file containing"
162 " fit parameters for each time bin). This parameter is not"
168 Name(
"spectrum_file"),
169 Comment(
"Name of a file that contains a representation"
170 " of the incident (not cross section weighted) neutrino spectrum"
171 " as a function of time and energy.")
175 Name(
"pinching_parameter_type"),
176 Comment(
"Type of pinching parameter to assume when parsing"
177 " the time-dependent fit parameters for the incident neutrino"
178 " spectrum. Valid options are \"alpha\" and \"beta\". This"
179 " parameter is not case-sensitive."),
181 auto spectrum_file_format
183 return (spectrum_file_format ==
"fit");
189 Comment(
"Name of the TH2D object to use to represent the"
190 " incident neutrino spectrum. This value should match the"
191 " name of the TH2D as given in the ROOT file specified"
192 " in the \"spectrum_file\" parameter. The TH2D should use "
193 " time bins on the X axis (seconds) and energy bins on the "
196 auto spectrum_file_format
198 return (spectrum_file_format ==
"th2d");
204 Comment(
"Minimum allowed neutrino energy (MeV) for a \"fit\" format"
207 auto spectrum_file_format
209 return (spectrum_file_format ==
"fit");
215 Comment(
"Maximum allowed neutrino energy (MeV) for a \"fit\" format"
218 auto spectrum_file_format
220 return (spectrum_file_format ==
"fit");
227 using Parameters = art::EDProducer::Table<Config, KeysToIgnore>;
232 virtual void produce(art::Event&
e)
override;
233 virtual void beginRun(art::Run& run)
override;
267 template<
typename It>
static marley::IteratorToMember<It, double>
270 return marley::IteratorToMember<It, double>(
284 TimeFit(
double time,
double Emean_nue,
double alpha_nue,
285 double lum_nue,
double Emean_nuebar,
double alpha_nuebar,
286 double lum_nuebar,
double Emean_nux,
double alpha_nux,
287 double lum_nux) :
fTime(time),
305 if (pdg_code == marley_utils::ELECTRON_NEUTRINO) {
308 else if (pdg_code == marley_utils::ELECTRON_ANTINEUTRINO) {
311 else if ( is_nux(pdg_code) )
316 else throw cet::exception(
"MARLEYTimeGen") <<
"Invalid neutrino"
317 <<
" PDG code " << pdg_code <<
" encountered in MARLEYTimeGen"
318 <<
"::TimeFit::GetFitParametersMemberPointer()";
341 template<
typename It>
static marley::IteratorToMember<It,
345 return marley::IteratorToMember<It, FitParameters>(
371 double& E_nu,
const TLorentzVector& vertex_pos);
530 : EDProducer{ p.get_PSet() }, fEvent(
new marley::Event), fRunNumber(0),
531 fSubRunNumber(0), fEventNumber(0), fTNu(0.), fFluxAveragedCrossSection(0.)
538 art::ServiceHandle<art::TFileService const>
tfs;
539 fEventTree = tfs->make<TTree>(
"MARLEY_event_tree",
540 "Neutrino events generated by MARLEY");
541 fEventTree->Branch(
"event",
"marley::Event", fEvent.get());
546 fEventTree->Branch(
"run_number", &fRunNumber,
"run_number/i");
547 fEventTree->Branch(
"subrun_number", &fSubRunNumber,
"subrun_number/i");
548 fEventTree->Branch(
"event_number", &fEventNumber,
"event_number/i");
549 fEventTree->Branch(
"tSN", &fTNu,
"tSN/D");
550 fEventTree->Branch(
"weight", &fWeight,
"weight/D");
552 produces< std::vector<simb::MCTruth> >();
553 produces< std::vector<sim::SupernovaTruth> >();
554 produces< art::Assns<simb::MCTruth, sim::SupernovaTruth> >();
560 art::ServiceHandle<geo::Geometry const> geo;
561 run.put(std::make_unique<sumdata::RunData>(geo->DetectorName()));
572 if (fSamplingMode == TimeGenSamplingMode::HISTOGRAM)
576 mc_truth = fMarleyHelper->create_MCTruth(vertex_pos,
580 double E_nu = fEvent->projectile().total_energy();
581 int E_bin_index = fSpectrumHist->GetYaxis()->FindBin(E_nu);
582 TH1D* t_hist = fSpectrumHist->ProjectionX(
"dummy_time_hist", E_bin_index,
584 double* time_bin_weights = t_hist->GetArray();
587 std::discrete_distribution<int> time_dist;
588 std::discrete_distribution<int>::param_type time_params(time_bin_weights,
589 &(time_bin_weights[t_hist->GetNbinsX() + 1]));
590 int time_bin_index = gen.sample_from_distribution(time_dist, time_params);
593 double t_min = t_hist->GetBinLowEdge(time_bin_index);
594 double t_max = t_min + t_hist->GetBinWidth(time_bin_index);
596 fTNu = gen.uniform_random_double(t_min, t_max,
false);
605 else if (fSamplingMode == TimeGenSamplingMode::UNIFORM_TIME)
609 mc_truth = fMarleyHelper->create_MCTruth(vertex_pos,
613 TAxis* time_axis = fSpectrumHist->GetXaxis();
615 double t_min = time_axis->GetBinLowEdge(1);
616 double t_max = time_axis->GetBinLowEdge(time_axis->GetNbins() + 1);
618 fTNu = gen.uniform_random_double(t_min, t_max,
false);
623 double E_nu = fEvent->projectile().total_energy();
624 int E_bin_index = fSpectrumHist->GetYaxis()->FindBin(E_nu);
625 TH1D* t_hist = fSpectrumHist->ProjectionX(
"dummy_time_hist", E_bin_index,
627 int t_bin_index = t_hist->FindBin(fTNu);
628 double weight_bias = t_hist->GetBinContent(t_bin_index) * (t_max - t_min)
629 / ( t_hist->Integral() * t_hist->GetBinWidth(t_bin_index) );
631 fWeight = weight_bias;
637 else if (fSamplingMode == TimeGenSamplingMode::UNIFORM_ENERGY)
640 TH1D* t_hist = fSpectrumHist->ProjectionX(
"dummy_time_hist");
641 double* time_bin_weights = t_hist->GetArray();
644 std::discrete_distribution<int> time_dist;
645 std::discrete_distribution<int>::param_type time_params(time_bin_weights,
646 &(time_bin_weights[t_hist->GetNbinsX() + 1]));
647 int time_bin_index = gen.sample_from_distribution(time_dist, time_params);
650 double t_min = t_hist->GetBinLowEdge(time_bin_index);
651 double t_max = t_min + t_hist->GetBinWidth(time_bin_index);
653 fTNu = gen.uniform_random_double(t_min, t_max,
false);
657 TAxis* energy_axis = fSpectrumHist->GetYaxis();
658 double E_min = energy_axis->GetBinLowEdge(1);
659 double E_max = energy_axis->GetBinLowEdge(energy_axis->GetNbins() + 1);
661 double E_nu = std::numeric_limits<double>::lowest();
664 mc_truth = make_uniform_energy_mctruth(E_min, E_max, E_nu, vertex_pos);
671 TH1D* energy_spect = fSpectrumHist->ProjectionY(
"energy_spect",
672 time_bin_index, time_bin_index);
677 auto nu_source = marley_root::make_root_neutrino_source(
678 marley_utils::ELECTRON_NEUTRINO, energy_spect);
679 double new_source_E_min = nu_source->get_Emin();
680 double new_source_E_max = nu_source->get_Emax();
681 gen.set_source(std::move(nu_source));
684 double E_pdf_integ = integrate([&gen](
double E_nu)
685 ->
double {
return gen.E_pdf(E_nu); }, new_source_E_min,
690 double weight_bias = (gen.E_pdf(E_nu) / E_pdf_integ) * (E_max - E_min);
692 fWeight = weight_bias;
699 throw cet::exception(
"MARLEYTimeGen") <<
"Unrecognized sampling mode"
700 <<
" encountered in evgen::MarleyTimeGen::produce()";
708 art::ServiceHandle<geo::Geometry const> geo;
711 fRunNumber = e.run();
712 fSubRunNumber = e.subRun();
713 fEventNumber = e.event();
717 std::unique_ptr< std::vector<simb::MCTruth> >
718 truthcol(
new std::vector<simb::MCTruth>);
720 std::unique_ptr< std::vector<sim::SupernovaTruth> >
721 sn_truthcol(
new std::vector<sim::SupernovaTruth>);
723 std::unique_ptr< art::Assns<simb::MCTruth, sim::SupernovaTruth> >
724 truth_assns(
new art::Assns<simb::MCTruth, sim::SupernovaTruth>);
730 for (
unsigned int n = 0;
n < fNeutrinosPerEvent; ++
n) {
733 TLorentzVector vertex_pos = fVertexSampler->sample_vertex_pos(*geo);
736 fTNu = std::numeric_limits<double>::lowest();
738 if (fSpectrumFileFormat == SpectrumFileFormat::RootTH2D) {
739 create_truths_th2d(truth, sn_truth, vertex_pos);
741 else if (fSpectrumFileFormat == SpectrumFileFormat::FIT) {
742 create_truths_time_fit(truth, sn_truth, vertex_pos);
745 throw cet::exception(
"MARLEYTimeGen") <<
"Invalid spectrum file"
746 <<
" format encountered in evgen::MarleyTimeGen::produce()";
753 truthcol->push_back(truth);
755 sn_truthcol->push_back(sn_truth);
760 truth_assns->addSingle(art::PtrMaker<simb::MCTruth>{e}(truthcol->size() - 1),
761 art::PtrMaker<sim::SupernovaTruth>{e}(sn_truthcol->size() - 1));
765 e.put(std::move(truthcol));
767 e.put(std::move(sn_truthcol));
769 e.put(std::move(truth_assns));
775 const auto& seed_service = art::ServiceHandle<rndm::NuRandomService>();
776 const auto& geom_service = art::ServiceHandle<geo::Geometry const>();
780 fVertexSampler = std::make_unique<evgen::ActiveVolumeVertexSampler>(
781 p().vertex_, *seed_service, *geom_service,
"MARLEY_Vertex_Sampler");
784 const fhicl::ParameterSet marley_pset = p.get_PSet()
785 .get< fhicl::ParameterSet >(
"marley_parameters" );
786 fMarleyHelper = std::make_unique<MARLEYHelper>( marley_pset,
787 *seed_service,
"MARLEY" );
790 fNeutrinosPerEvent =
p().nu_per_event_();
793 const std::string& samp_mode_str =
p().sampling_mode_();
794 if (samp_mode_str ==
"histogram")
795 fSamplingMode = TimeGenSamplingMode::HISTOGRAM;
796 else if (samp_mode_str ==
"uniform time")
797 fSamplingMode = TimeGenSamplingMode::UNIFORM_TIME;
798 else if (samp_mode_str ==
"uniform energy")
799 fSamplingMode = TimeGenSamplingMode::UNIFORM_ENERGY;
800 else throw cet::exception(
"MARLEYTimeGen")
801 <<
"Invalid sampling mode \"" << samp_mode_str <<
"\""
802 <<
" specified for the MARLEYTimeGen module.";
804 MF_LOG_INFO(
"MARLEYTimeGen") << fNeutrinosPerEvent <<
" neutrino vertices"
805 <<
" will be generated for each art::Event using the \"" << samp_mode_str
806 <<
"\" sampling mode.";
810 std::string spectrum_file_format = marley_utils::to_lowercase(
811 p().spectrum_file_format_());
813 if (spectrum_file_format ==
"th2d")
814 fSpectrumFileFormat = SpectrumFileFormat::RootTH2D;
815 else if (spectrum_file_format ==
"fit") {
816 fSpectrumFileFormat = SpectrumFileFormat::FIT;
818 std::string pinch_type;
819 if ( !
p().pinching_parameter_type_(pinch_type) ) {
820 throw cet::exception(
"MARLEYTimeGen") <<
"Missing pinching parameter"
821 <<
" type for a \"fit\" format spectrum file";
824 marley_utils::to_lowercase_inplace(pinch_type);
825 if (pinch_type ==
"alpha") fPinchType = PinchParamType::ALPHA;
826 else if (pinch_type ==
"beta") fPinchType = PinchParamType::BETA;
827 else throw cet::exception(
"MARLEYTimeGen")
828 <<
"Invalid pinching parameter type \"" << pinch_type
829 <<
"\" specified for the MARLEYTimeGen module.";
831 if ( !
p().fit_Emin_(fFitEmin) )
throw cet::exception(
"MARLEYTimeGen")
832 <<
"Missing minimum energy for a \"fit\" format spectrum"
833 <<
" used by the MARLEYTimeGen module.";
835 if ( !
p().fit_Emax_(fFitEmax) )
throw cet::exception(
"MARLEYTimeGen")
836 <<
"Missing maximum energy for a \"fit\" format spectrum"
837 <<
" used by the MARLEYTimeGen module.";
839 if (fFitEmax < fFitEmin)
throw cet::exception(
"MARLEYTimeGen")
840 <<
"Maximum energy is less than the minimum energy for"
841 <<
" a \"fit\" format spectrum used by the MARLEYTimeGen module.";
843 else throw cet::exception(
"MARLEYTimeGen")
844 <<
"Invalid spectrum file format \"" <<
p().spectrum_file_format_()
845 <<
"\" specified for the MARLEYTimeGen module.";
848 std::string full_spectrum_file_name
849 = fMarleyHelper->find_file(
p().spectrum_file_(),
"spectrum");
853 if (fSpectrumFileFormat == SpectrumFileFormat::RootTH2D) {
856 std::unique_ptr<TFile> spectrum_file
857 = std::make_unique<TFile>(full_spectrum_file_name.c_str(),
"read");
858 TH2D* temp_h2 =
nullptr;
859 std::string namecycle;
860 if ( !
p().namecycle_(namecycle) ) {
861 throw cet::exception(
"MARLEYTimeGen") <<
"Missing namecycle for"
862 <<
" a TH2D spectrum file";
865 spectrum_file->GetObject(namecycle.c_str(), temp_h2);
866 fSpectrumHist.reset(temp_h2);
870 fSpectrumHist->SetDirectory(
nullptr);
877 TH1D* energy_spect = fSpectrumHist->ProjectionY(
"energy_spect");
883 std::unique_ptr<marley::NeutrinoSource> nu_source
884 = marley_root::make_root_neutrino_source(marley_utils::ELECTRON_NEUTRINO,
888 fFluxAveragedCrossSection = marley_utils::hbar_c2
889 * flux_averaged_total_xs(*nu_source, gen);
894 if (fSamplingMode == TimeGenSamplingMode::HISTOGRAM ||
895 fSamplingMode == TimeGenSamplingMode::UNIFORM_TIME)
897 gen.set_source(std::move(nu_source));
902 else if (fSpectrumFileFormat == SpectrumFileFormat::FIT) {
907 std::ifstream fit_file(full_spectrum_file_name);
910 bool found_end =
false;
915 int lines_checked = 0;
917 double old_time = std::numeric_limits<double>::lowest();
919 while ( line = marley_utils::get_next_line(fit_file, rx_comment_or_empty,
920 false, lines_checked), line_num += lines_checked, !line.empty() )
923 MF_LOG_WARNING(
"MARLEYTimeGen") <<
"Trailing content after last time"
924 <<
" bin found on line " << line_num <<
" of the spectrum file "
925 << full_spectrum_file_name;
929 double Emean_nue, alpha_nue, luminosity_nue;
930 double Emean_nuebar, alpha_nuebar, luminosity_nuebar;
931 double Emean_nux, alpha_nux, luminosity_nux;
932 std::istringstream iss(line);
933 bool ok_first =
static_cast<bool>( iss >> time );
935 if (time <= old_time)
throw cet::exception(
"MARLEYTimeGen")
936 <<
"Time bin left edges given in the spectrum file must be"
937 <<
" strictly increasing. Invalid time bin value found on line "
938 << line_num <<
" of the spectrum file " << full_spectrum_file_name;
939 else old_time = time;
941 bool ok_rest =
static_cast<bool>( iss >> Emean_nue >> alpha_nue
942 >> luminosity_nue >> Emean_nuebar >> alpha_nuebar >> luminosity_nuebar
943 >> Emean_nux >> alpha_nux >> luminosity_nux
950 fTimeFits.emplace_back(time, Emean_nue, alpha_nue, luminosity_nue,
951 Emean_nuebar, alpha_nuebar, luminosity_nuebar, Emean_nux,
952 alpha_nux, luminosity_nux);
955 make_final_timefit(time);
959 else throw cet::exception(
"MARLEYTimeGen") <<
"Parse error on line "
960 << line_num <<
" of the spectrum file " << full_spectrum_file_name;
965 size_t num_time_bins = fTimeFits.size();
966 if (num_time_bins < 2)
throw cet::exception(
"MARLEYTimeGen")
967 <<
"Missing right edge for the final time bin in the spectrum file "
968 << full_spectrum_file_name <<
". Unable to guess a bin width for the "
973 double delta_t_bin = fTimeFits.back().Time()
974 - fTimeFits.at(num_time_bins - 2).Time();
976 double last_bin_right_edge = fTimeFits.back().Time() + delta_t_bin;
978 make_final_timefit(last_bin_right_edge);
981 <<
" edge for the final time bin in the spectrum file "
982 << full_spectrum_file_name <<
". Assuming a width of "
983 << delta_t_bin <<
" s for the final bin.";
989 std::vector< std::unique_ptr< marley::NeutrinoSource > > fit_sources;
990 for (
const auto& fit : fTimeFits) {
991 fit_sources.emplace_back( source_from_time_fit(fit) );
996 auto temp_source = std::make_unique<marley::FunctionNeutrinoSource>(
997 marley_utils::ELECTRON_NEUTRINO, fFitEmin, fFitEmax,
998 [&fit_sources,
this](
double E_nu) ->
double {
1000 for (
size_t s = 0;
s < fit_sources.size(); ++
s) {
1002 const TimeFit& current_fit = this->fTimeFits.at(
s);
1003 const auto& current_source = fit_sources.at(
s);
1005 current_source->get_pid() );
1012 if (lum <= 0.)
continue;
1014 flux += lum * current_source->pdf(E_nu);
1020 double flux_integ = 0.;
1021 double tot_xs_integ = 0.;
1022 flux_averaged_total_xs(*temp_source, gen, flux_integ, tot_xs_integ);
1025 fFluxAveragedCrossSection = marley_utils::hbar_c2
1026 * tot_xs_integ / flux_integ;
1028 make_nu_emission_histograms();
1033 throw cet::exception(
"MARLEYTimeGen") <<
"Unrecognized neutrino spectrum"
1034 <<
" file format \"" <<
p().spectrum_file_format_() <<
"\" encountered"
1035 <<
" in evgen::MarleyTimeGen::reconfigure()";
1038 MF_LOG_INFO(
"MARLEYTimeGen") <<
"The flux-averaged total cross section"
1039 <<
" predicted by MARLEY for the current supernova spectrum is "
1040 << fFluxAveragedCrossSection <<
" fm^2";
1054 size_t time_bin_index = std::numeric_limits<size_t>::max();
1061 int source_pdg_code = gen.get_source().get_pid();
1063 const auto fit_params_begin = TimeFit::make_FitParameters_iterator(
1064 source_pdg_code, fTimeFits.begin() );
1065 const auto fit_params_end = TimeFit::make_FitParameters_iterator(
1066 source_pdg_code, fTimeFits.end() );
1068 const auto lum_begin = FitParameters::make_luminosity_iterator(
1070 const auto lum_end = FitParameters::make_luminosity_iterator(
1073 std::discrete_distribution<size_t> time_dist(lum_begin, lum_end);
1075 if (fSamplingMode == TimeGenSamplingMode::HISTOGRAM
1076 || fSamplingMode == TimeGenSamplingMode::UNIFORM_ENERGY)
1078 time_bin_index = gen.sample_from_distribution(time_dist);
1081 else if (fSamplingMode == TimeGenSamplingMode::UNIFORM_TIME) {
1082 int last_time_index = 0;
1083 if (fTimeFits.size() > 0) last_time_index = fTimeFits.size() - 1;
1084 std::uniform_int_distribution<size_t> uid(0, last_time_index);
1086 time_bin_index = gen.sample_from_distribution(uid);
1090 throw cet::exception(
"MARLEYTimeGen") <<
"Unrecognized sampling mode"
1091 <<
" encountered in evgen::MarleyTimeGen::produce()";
1100 double t_min = fTimeFits.at(time_bin_index).Time();
1101 double t_max = fTimeFits.at(time_bin_index + 1).Time();
1103 fTNu = gen.uniform_random_double(t_min, t_max,
false);
1109 const auto& fit = fTimeFits.at(time_bin_index);
1110 std::unique_ptr<marley::NeutrinoSource> nu_source = source_from_time_fit(fit);
1112 if (fSamplingMode == TimeGenSamplingMode::HISTOGRAM
1113 || fSamplingMode == TimeGenSamplingMode::UNIFORM_TIME)
1117 gen.set_source(std::move(nu_source));
1120 mc_truth = fMarleyHelper->create_MCTruth(vertex_pos, fEvent.get());
1122 if (fSamplingMode == TimeGenSamplingMode::HISTOGRAM) {
1133 double weight_bias = time_dist.probabilities().at(time_bin_index)
1134 / (t_max - t_min) * ( fTimeFits.back().Time()
1135 - fTimeFits.front().Time() );
1137 fWeight = weight_bias;
1143 else if (fSamplingMode == TimeGenSamplingMode::UNIFORM_ENERGY)
1145 double E_nu = std::numeric_limits<double>::lowest();
1146 mc_truth = make_uniform_energy_mctruth(fFitEmin, fFitEmax, E_nu,
1157 double nu_source_E_min = nu_source->get_Emin();
1158 double nu_source_E_max = nu_source->get_Emax();
1159 gen.set_source(std::move(nu_source));
1163 double E_pdf_integ = integrate([&gen](
double E_nu)
1164 ->
double {
return gen.E_pdf(E_nu); }, nu_source_E_min,
1169 double weight_bias = (gen.E_pdf(E_nu) / E_pdf_integ)
1170 * (fFitEmax - fFitEmin);
1172 fWeight = weight_bias;
1178 throw cet::exception(
"MARLEYTimeGen") <<
"Unrecognized sampling mode"
1179 <<
" encountered in evgen::MarleyTimeGen::produce()";
1185 std::unique_ptr<marley::NeutrinoSource>
1196 double beta = nue_parameters.
Alpha();
1197 if (fPinchType == PinchParamType::ALPHA) beta += 1.;
1198 else if (fPinchType != PinchParamType::BETA) {
1199 throw cet::exception(
"MARLEYTimeGen") <<
"Unreognized pinching parameter"
1200 <<
" type encountered in evgen::MarleyTimeGen::source_from_time_fit()";
1204 std::unique_ptr<marley::NeutrinoSource> nu_source
1205 = std::make_unique<marley::BetaFitNeutrinoSource>(
1206 marley_utils::ELECTRON_NEUTRINO, fFitEmin, fFitEmax,
1207 nue_parameters.
Emean(), beta);
1214 double E_max,
double& E_nu,
const TLorentzVector& vertex_pos)
1228 if (j >= MAX_UNIFORM_ENERGY_ITERATIONS) {
1229 throw cet::exception(
"MARLEYTimeGen") <<
"Exceeded the maximum of "
1230 << MAX_UNIFORM_ENERGY_ITERATIONS <<
" while attempting to sample"
1231 <<
" a neutrino energy uniformly.";
1234 E_nu = gen.uniform_random_double(E_min, E_max,
false);
1239 for (
const auto& react : gen.get_reactions()) {
1240 total_xs += react->total_xs(marley_utils::ELECTRON_NEUTRINO, E_nu);
1244 }
while (total_xs <= 0.);
1248 std::unique_ptr<marley::NeutrinoSource> nu_source
1249 = std::make_unique<marley::MonoNeutrinoSource>(
1250 marley_utils::ELECTRON_NEUTRINO, E_nu);
1251 gen.set_source(std::move(nu_source));
1254 auto mc_truth = fMarleyHelper->create_MCTruth(vertex_pos, fEvent.get());
1265 fTimeFits.emplace_back(time, 0., 0., 0., 0., 0., 0., 0., 0., 0.);
1275 std::vector<double> temp_times;
1276 for (
const auto& fit : fTimeFits) temp_times.push_back(fit.Time());
1281 if (temp_times.size() < 2)
return;
1284 int num_bins = temp_times.size() - 1;
1288 art::ServiceHandle<art::TFileService const>
tfs;
1289 TH1D* nue_hist = tfs->make<TH1D>(
"NueEmission",
1290 "Number of emitted #nu_{e}; time (s); number of neutrinos in time bin",
1291 num_bins, temp_times.data());
1292 TH1D* nuebar_hist = tfs->make<TH1D>(
"NuebarEmission",
1293 "Number of emitted #bar{#nu}_{e}; time (s); number of neutrinos in"
1294 " time bin", num_bins, temp_times.data());
1295 TH1D* nux_hist = tfs->make<TH1D>(
"NuxEmission",
1296 "Number of emitted #nu_{x}; time (s); number of neutrinos in time bin",
1297 num_bins, temp_times.data());
1300 for (
size_t b = 1; b < temp_times.size(); ++b) {
1301 const TimeFit& current_fit = fTimeFits.at(b - 1);
1302 const TimeFit& next_fit = fTimeFits.at(b);
1303 double bin_deltaT = next_fit.
Time() - current_fit.
Time();
1306 marley_utils::ELECTRON_NEUTRINO);
1308 marley_utils::ELECTRON_ANTINEUTRINO);
1310 marley_utils::MUON_NEUTRINO);
1315 double num_nue = 0.;
1316 double num_nuebar = 0.;
1317 double num_nux = 0.;
1318 if (nue_params.Emean() != 0.) num_nue = nue_params.
Luminosity()
1319 * bin_deltaT / (nue_params.Emean() * MeV_to_erg);
1320 if (nuebar_params.Emean() != 0.) num_nuebar = nuebar_params.Luminosity()
1321 * bin_deltaT / (nuebar_params.Emean() * MeV_to_erg);
1322 if (nux_params.Emean() != 0.) num_nux = nux_params.Luminosity()
1323 * bin_deltaT / (nux_params.Emean() * MeV_to_erg);
1325 nue_hist->SetBinContent(b, num_nue);
1326 nuebar_hist->SetBinContent(b, num_nuebar);
1327 nux_hist->SetBinContent(b, num_nux);
1337 double flux_averaged_total_xs(marley::NeutrinoSource& nu_source,
1341 source_integ = integrate(
1342 [&nu_source](
double E_nu) ->
double {
return nu_source.pdf(E_nu); },
1343 nu_source.get_Emin(), nu_source.get_Emax()
1346 tot_xs_integ = integrate(
1347 [&nu_source, &gen](
double E_nu) ->
double
1350 for (
const auto& react : gen.get_reactions()) {
1351 xs += react->total_xs(marley_utils::ELECTRON_NEUTRINO, E_nu);
1353 return xs * nu_source.pdf(E_nu);
1354 }, nu_source.get_Emin(), nu_source.get_Emax()
1357 return tot_xs_integ / source_integ;
1360 double flux_averaged_total_xs(marley::NeutrinoSource& nu_source,
1363 double dummy1, dummy2;
1364 return flux_averaged_total_xs(nu_source, gen, dummy1, dummy2);
1367 double integrate(
const std::function<
double(
double)>& f,
double x_min,
1370 static marley::Integrator integrator(NUM_INTEGRATION_SAMPLING_POINTS);
1371 return integrator.num_integrate(f, x_min, x_max);
double fLuminosity
Luminosity (erg / s)
SpectrumFileFormat
Enumerated type that defines the allowed neutrino spectrum input file formats.
virtual void produce(art::Event &e) override
LArSoft interface to the MARLEY (Model of Argon Reaction Low Energy Yields) supernova neutrino event ...
FitParameters fNuebarFitParams
Fitting parameters for electron antineutrinos in this time bin.
SpectrumFileFormat fSpectrumFileFormat
Format to assume for the neutrino spectrum input file.
uint_fast32_t fEventNumber
Event number from the art::Event being processed.
double Alpha() const
Pinching parameter (dimensionless)
Stores fitting parameters for all neutrino types from a single time bin in a "fit"-format spectrum fi...
TimeFit(double time, double Emean_nue, double alpha_nue, double lum_nue, double Emean_nuebar, double alpha_nuebar, double lum_nuebar, double Emean_nux, double alpha_nux, double lum_nux)
double fTime
Time bin low edge (s)
void create_truths_time_fit(simb::MCTruth &mc_truth, sim::SupernovaTruth &sn_truth, const TLorentzVector &vertex_pos)
Create simb::MCTruth and sim::SupernovaTruth objects using a neutrino spectrum described by a previou...
void set_Alpha(double alpha)
Set the pinching parameter.
fhicl::Atom< std::string > sampling_mode_
virtual void reconfigure(const Parameters &p)
PinchParamType fPinchType
The pinching parameter convention to use when interpreting the time-dependent fits.
double fEmean
Mean neutrino energy (MeV)
produces< sumdata::RunData, art::InRun >()
FitParameters fNueFitParams
Fitting parameters for electron neutrinos in this time bin.
Stores parsed fit parameters from a single time bin and neutrino type in a "fit"-format spectrum file...
std::unique_ptr< evgen::ActiveVolumeVertexSampler > fVertexSampler
Algorithm that allows us to sample vertex locations within the active volume(s) of the detector...
fhicl::Atom< std::string > module_type_
std::unique_ptr< evgen::MARLEYHelper > fMarleyHelper
Object that provides an interface to the MARLEY event generator.
double fFluxAveragedCrossSection
Flux-averaged total cross section (fm2, average is taken over all energies and times for all defined ...
double fWeight
Statistical weight for the current MARLEY neutrino vertex.
TTree * fEventTree
The event TTree created by MARLEY.
double Time() const
Returns the low edge (in s) of the time bin that uses these fit parameters.
void set_Luminosity(double lum)
Set the luminosity (erg / s)
uint_fast32_t fSubRunNumber
Subrun number from the art::Event being processed.
Arrival times were sampled uniformly.
Algorithm that samples vertex locations uniformly within the active volume of a detector. It is fully experiment-agnostic and multi-TPC aware.
uint_fast32_t fRunNumber
Run number from the art::Event being processed.
std::unique_ptr< marley::NeutrinoSource > source_from_time_fit(const TimeFit &fit)
Create a MARLEY neutrino source object using a set of fit parameters for a particular time bin...
double fAlpha
Pinching parameter.
FitParameters fNuxFitParams
Fitting parameters for non-electron-flavor neutrinos in this time bin.
TimeGenSamplingMode
Enumerated type that defines the allowed ways that a neutrino's energy and arrival time may be sample...
static marley::IteratorToMember< It, double > make_luminosity_iterator(It it)
Converts an iterator that points to a FitParameters object into an iterator that points to that objec...
art::EDProducer::Table< Config, KeysToIgnore > Parameters
MF_LOG_WARNING("SimWire")<< "SimWire is an example module that works for the "<< "MicroBooNE detector. Each experiment should implement "<< "its own version of this module to simulate electronics "<< "response."
void create_truths_th2d(simb::MCTruth &mc_truth, sim::SupernovaTruth &sn_truth, const TLorentzVector &vertex_pos)
Create simb::MCTruth and sim::SupernovaTruth objects using spectrum information from a ROOT TH2D...
double fTNu
Time since the supernova core bounce for the current MARLEY neutrino vertex.
auto end(FixedBins< T, C > const &) noexcept
PinchParamType
Enumerated type that defines the pinching parameter conventions that are understood by this module...
void set_Emean(double Emean)
Set the mean neutrino energy (MeV)
virtual void beginRun(art::Run &run) override
static FitParameters TimeFit::* GetFitParametersMemberPointer(int pdg_code)
Helper function that returns a pointer-to-member for the FitParameters object appropriate for a given...
simb::MCTruth make_uniform_energy_mctruth(double E_min, double E_max, double &E_nu, const TLorentzVector &vertex_pos)
Creates a simb::MCTruth object using a uniformly-sampled neutrino energy.
BEGIN_PROLOG vertical distance to the surface Name
double fFitEmax
Maximum neutrino energy to consider when using a "fit"-format spectrum file.
fhicl::OptionalAtom< double > fit_Emax_
static marley::IteratorToMember< It, FitParameters > make_FitParameters_iterator(int pdg_code, It iterator)
Converts an iterator that points to a TimeFit object into an iterator that points to the appropriate ...
MarleyTimeGen(const Parameters &p)
const FitParameters & GetFitParameters(int pdg_code) const
Retrieves fit parameters for a specific neutrino type for this time bin.
FitParameters(double Emean, double alpha, double luminosity)
fhicl::OptionalAtom< std::string > namecycle_
double Luminosity() const
Luminosity (erg / s)
std::unique_ptr< TH2D > fSpectrumHist
ROOT TH2D that contains the time-dependent spectrum to use when sampling neutrino times and energies...
fhicl::Atom< std::string > spectrum_file_format_
auto begin(FixedBins< T, C > const &) noexcept
std::unique_ptr< marley::Event > fEvent
unique_ptr to the current event created by MARLEY
unsigned int fNeutrinosPerEvent
The number of MARLEY neutrino vertices to generate in each art::Event.
then echo File list $list not found else cat $list while read file do echo $file sed s
Stores extra MC truth information that is recorded when generating events using a time-dependent supe...
Collection of configuration parameters for the module.
Sample directly from cross-section weighted spectrum.
TimeGenSamplingMode fSamplingMode
Represents the sampling mode to use when selecting neutrino times and energies.
double fFitEmin
Minimum neutrino energy to consider when using a "fit"-format spectrum file.
void make_final_timefit(double time)
Helper function that makes a final dummy TimeFit object so that the final real time bin can have a ri...
fhicl::Atom< unsigned int > nu_per_event_
fhicl::OptionalAtom< std::string > pinching_parameter_type_
std::vector< TimeFit > fTimeFits
Vector that contains the fit parameter information for each time bin when using a "fit"-format spectr...
art::ServiceHandle< art::TFileService > tfs
fhicl::Table< evgen::ActiveVolumeVertexSampler::Config > vertex_
std::set< std::string > operator()()
void make_nu_emission_histograms() const
Makes ROOT histograms showing the emitted neutrinos in each time bin when using a "fit"-format spectr...
Neutrino energies were sampled uniformly.
art framework interface to geometry description
fhicl::Atom< std::string > spectrum_file_
fhicl::OptionalAtom< double > fit_Emin_
double Emean() const
Mean neutrino energy (MeV)