aegir-genie
GENIE neutrino event generation for the SHiP experiment's aegir framework.
Loading...
Searching...
No Matches
flux_driver.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5// flux_driver.hpp — GENIE flux driver reading SHiP neutrino flux files
6//
7// Implements genie::GFluxI (and the GFluxExposureI extension for POT
8// accounting) on top of the SHiP neutrino-flux ntuple, schema version 1
9// (see docs/neutrino_flux.md in aegir): an RNTuple `nu_flux` with one entry
10// per neutrino ray (production vertex in mm/ns, momentum in GeV, statistical
11// weight) plus an `flux_meta` RNTuple carrying the POT-equivalent of the
12// file and the maximum neutrino energy.
13//
14// Each entry defines one flux ray exactly — energy, direction and production
15// point stay correlated, unlike the histogram-based FairShip flux files.
16// Positions are converted mm -> m and ns -> s for GENIE (SI units), the
17// 4-momentum is completed with E = |p| (massless neutrinos).
18
19#pragma once
20
21#include <TLorentzVector.h>
22
23#include <cstdint>
24#include <memory>
25#include <string>
26
27#include "Framework/EventGen/GFluxI.h"
28#include "Framework/ParticleData/PDGCodeList.h"
29#include "Tools/Flux/GFluxExposureI.h"
30
31namespace SHiP::aegir::genie {
32
33// GENIE takes a flux driver through both of its interfaces: GFluxI for
34// GMCJDriver and GFluxExposureI for the POT accounting.
35// NOLINTNEXTLINE(misc-multiple-inheritance)
36class FluxDriver : public ::genie::GFluxI,
37 public ::genie::flux::GFluxExposureI {
38 public:
39 // Opens the flux file and reads its metadata; throws std::runtime_error
40 // with a descriptive message if the file is missing, has no nu_flux /
41 // flux_meta ntuples, or declares an unsupported schema version.
42 // With cycle = true the driver restarts from the first entry when the file
43 // is exhausted (exposure keeps accumulating); with cycle = false End()
44 // becomes true instead.
45 explicit FluxDriver(std::string const& path, bool cycle = false);
46 ~FluxDriver() override;
47
48 // GFluxI interface
49 ::genie::PDGCodeList const& FluxParticles() override;
50 double MaxEnergy() override { return max_energy_; }
51 bool GenerateNext() override;
52 int PdgCode() override { return pdg_; }
53 double Weight() override { return weight_; }
54 TLorentzVector const& Momentum() override { return p4_; }
55 TLorentzVector const& Position() override { return x4_; }
56 bool End() override { return end_; }
57 long int Index() override { return index_; }
58 void Clear(Option_t* opt) override;
59 void GenerateWeighted(bool gen_weighted) override;
60
61 // GFluxExposureI interface (kPOTs): the file represents pot() protons on
62 // target; the exposure delivered so far scales with the fraction of the
63 // total statistical weight consumed (cycling accumulates across passes).
64 // NFluxNeutrinos() is the raw ray count, not weight-corrected.
65 double GetTotalExposure() const override;
66 long int NFluxNeutrinos() const override { return n_used_; }
67
68 // SHiP-specific accessors
69 double pot() const { return pot_; }
70 std::uint64_t entries() const { return n_entries_; }
71
72 // First ray of the file (SI units, like Position()/Momentum()), read
73 // without disturbing the sequential driver state — for startup
74 // frame-sanity logging.
75 struct Ray {
76 int pdg;
77 TLorentzVector position; // m, s
78 TLorentzVector momentum; // GeV
79 };
81
82 private:
83 struct Reader; // hides ROOT RNTuple types from this header
84 std::unique_ptr<Reader> reader_;
85
86 std::string path_;
87 bool cycle_ = false;
88 bool gen_weighted_ = true; // rays carry their weight either way
89
90 // file metadata (flux_meta)
91 double pot_ = 0.0;
92 double max_energy_ = 0.0;
93 std::uint64_t n_entries_ = 0;
94 double total_weight_ = 0.0; // Σ weight over the file (> 0, checked)
95
96 // current ray
97 long int index_ = -1; // entry number of the current ray
98 int pdg_ = 0;
99 double weight_ = 0.0;
100 TLorentzVector p4_; // GeV
101 TLorentzVector x4_; // SI: m, s
102 bool end_ = false;
103 long int n_used_ = 0; // rays generated so far (across cycles)
104 double used_weight_ = 0.0; // Σ weight of the rays generated so far
105
106 ::genie::PDGCodeList pdg_list_;
107 bool pdg_list_built_ = false;
108};
109
110} // namespace SHiP::aegir::genie
Definition flux_driver.hpp:37
Ray peek_first_ray()
Definition flux_driver.cpp:179
double MaxEnergy() override
Definition flux_driver.hpp:50
void Clear(Option_t *opt) override
Definition flux_driver.cpp:192
int PdgCode() override
Definition flux_driver.hpp:52
TLorentzVector const & Position() override
Definition flux_driver.hpp:55
void GenerateWeighted(bool gen_weighted) override
Definition flux_driver.cpp:203
double pot() const
Definition flux_driver.hpp:69
bool End() override
Definition flux_driver.hpp:56
long int NFluxNeutrinos() const override
Definition flux_driver.hpp:66
::genie::PDGCodeList const & FluxParticles() override
Definition flux_driver.cpp:126
std::uint64_t entries() const
Definition flux_driver.hpp:70
double GetTotalExposure() const override
Definition flux_driver.cpp:212
TLorentzVector const & Momentum() override
Definition flux_driver.hpp:54
double Weight() override
Definition flux_driver.hpp:53
bool GenerateNext() override
Definition flux_driver.cpp:151
long int Index() override
Definition flux_driver.hpp:57
Definition flux_driver.cpp:15
Definition flux_driver.hpp:75
TLorentzVector momentum
Definition flux_driver.hpp:78
int pdg
Definition flux_driver.hpp:76
TLorentzVector position
Definition flux_driver.hpp:77
Definition flux_driver.cpp:33