diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 74917a398..9db73a931 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -3,21 +3,20 @@ name: Build on: [pull_request] jobs: - build_wheels: + build_wheels_linux: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: - #os: [ubuntu-20.04, windows-2019, macos-11] - os: [ubuntu-20.04, macos-11] - arch: [x86_64, auto32, auto64, aarch64, ppc64le, s390x, arm64] + os: [ubuntu-20.04] + arch: [x86_64, i686, aarch64, ppc64le, s390x] steps: - name: Checkout LeptonInjector - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.9' # update once build dependencies are available @@ -28,6 +27,36 @@ jobs: if: ${{ failure() }} uses: mxschmitt/action-tmate@v3 - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + build_wheels_macos: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-11] + # arch: [x86_64, arm64] + arch: [x86_64] + + steps: + - name: Checkout LeptonInjector + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.9' # update once build dependencies are available + + - name: Build wheels + uses: pypa/cibuildwheel@v2.16.2 + + - name: Setup tmate session + if: ${{ failure() }} + uses: mxschmitt/action-tmate@v3 + + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: ./wheelhouse/*.whl diff --git a/.gitignore b/.gitignore index 55fe83fab..0968a41d8 100644 --- a/.gitignore +++ b/.gitignore @@ -48,21 +48,13 @@ *.swp # rk -*/*rk* -*/*/*rk* +vendor/rk/ # ipynb_checkpoint *ipynb_checkpoint* -*/*ipynb_checkpoint* -*/*/*ipynb_checkpoint* -*/*/*/*ipynb_checkpoint* # build *build # pycache *pycache* -*/*pycache* -*/*/*pycache* -*/*/*/*pycache* -*/*/*/*/*pycache* diff --git a/projects/dataclasses/CMakeLists.txt b/projects/dataclasses/CMakeLists.txt index 694a5c56b..20b9c4b06 100644 --- a/projects/dataclasses/CMakeLists.txt +++ b/projects/dataclasses/CMakeLists.txt @@ -6,7 +6,8 @@ LIST (APPEND dataclasses_SOURCES ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/InteractionRecord.cxx ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/InteractionTree.cxx ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/DecaySignature.cxx - ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/DecayRecord.cxx + ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/ParticleID.cxx + ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/ParticleType.cxx ) add_library(LI_dataclasses OBJECT ${dataclasses_SOURCES}) set_property(TARGET LI_dataclasses PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -29,6 +30,10 @@ install(DIRECTORY "${PROJECT_SOURCE_DIR}/projects/dataclasses/public/" PATTERN "*.tcc" ) +package_add_test(UnitTest_InteractionSignature ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/test/InteractionSignature_TEST.cxx) +package_add_test(UnitTest_InteractionRecord ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/test/InteractionRecord_TEST.cxx) +package_add_test(UnitTest_InteractionTree ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/test/InteractionTree_TEST.cxx) + pybind11_add_module(dataclasses ${PROJECT_SOURCE_DIR}/projects/dataclasses/private/pybindings/dataclasses.cxx) target_link_libraries(dataclasses PRIVATE LeptonInjector) if(DEFINED SKBUILD) diff --git a/projects/dataclasses/private/DecayRecord.cxx b/projects/dataclasses/private/DecayRecord.cxx deleted file mode 100644 index 2014c4c8a..000000000 --- a/projects/dataclasses/private/DecayRecord.cxx +++ /dev/null @@ -1,33 +0,0 @@ -#include "LeptonInjector/dataclasses/DecayRecord.h" - -#include - -namespace LI { -namespace dataclasses { - -bool DecayRecord::operator==(DecayRecord const & other) const { - return std::tie( - signature, - primary_mass, - primary_momentum, - primary_helicity, - decay_vertex, - secondary_masses, - secondary_momenta, - secondary_helicity, - decay_parameters) - == - std::tie( - other.signature, - other.primary_mass, - other.primary_momentum, - other.primary_helicity, - other.decay_vertex, - other.secondary_masses, - other.secondary_momenta, - other.secondary_helicity, - other.decay_parameters); -} - -} // namespace dataclasses -} // namespace LI diff --git a/projects/dataclasses/private/InteractionRecord.cxx b/projects/dataclasses/private/InteractionRecord.cxx index b516c0107..ee73a714e 100644 --- a/projects/dataclasses/private/InteractionRecord.cxx +++ b/projects/dataclasses/private/InteractionRecord.cxx @@ -1,44 +1,1104 @@ #include "LeptonInjector/dataclasses/InteractionRecord.h" +#include #include // for tie, operator==, tuple +#include #include // for operator<<, basic_ostream, char_traits, endl, ost... +std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionRecord const& record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::PrimaryDistributionRecord const& record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::SecondaryParticleRecord const& record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::CrossSectionDistributionRecord const& record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::SecondaryDistributionRecord const& record); + namespace LI { namespace dataclasses { +PrimaryDistributionRecord::PrimaryDistributionRecord(ParticleType type) : + id(ParticleID::GenerateID()), + type(type) +{} + +Particle PrimaryDistributionRecord::GetParticle() const { + Particle p; + p.id = id; + p.type = type; + try { + p.mass = GetMass(); + } catch(...) { + p.mass = 0; + } + try { + p.momentum = GetFourMomentum(); + } catch(...) { + p.momentum = {0, 0, 0, 0}; + } + try { + p.position = GetInitialPosition(); + } catch(...) { + p.position = {0, 0, 0}; + } + try { + p.length = GetLength(); + } catch(...) { + p.length = 0; + } + try { + p.helicity = GetHelicity(); + } catch(...) { + p.helicity = 0; + } + return p; +} + +ParticleID const & PrimaryDistributionRecord::GetID() const { + return id; +} + +ParticleType const & PrimaryDistributionRecord::GetType() const { + return type; +} + +double const & PrimaryDistributionRecord::GetMass() const { + if(not mass_set) { + UpdateMass(); + } + return mass; +} + +double const & PrimaryDistributionRecord::GetEnergy() const { + if(not energy_set) { + UpdateEnergy(); + } + return energy; +} + +double const & PrimaryDistributionRecord::GetKineticEnergy() const { + if(not kinetic_energy_set) { + UpdateKineticEnergy(); + } + return kinetic_energy; +} + + +std::array const & PrimaryDistributionRecord::GetDirection() const { + if(not direction_set) { + UpdateDirection(); + } + return direction; +} + +std::array const & PrimaryDistributionRecord::GetThreeMomentum() const { + if(not momentum_set) { + UpdateMomentum(); + } + return momentum; +} + +std::array PrimaryDistributionRecord::GetFourMomentum() const { + if(not (momentum_set and energy_set)) { + UpdateMomentum(); + UpdateEnergy(); + } + return {energy, momentum.at(0), momentum.at(1), momentum.at(2)}; +} + +double const & PrimaryDistributionRecord::GetLength() const { + if(not length_set) { + UpdateLength(); + } + return length; +} + +std::array const & PrimaryDistributionRecord::GetInitialPosition() const { + if(not initial_position_set) { + UpdateInitialPosition(); + } + return initial_position; +} + +std::array const & PrimaryDistributionRecord::GetInteractionVertex() const { + if(not interaction_vertex_set) { + UpdateInteractionVertex(); + } + return interaction_vertex; +} + +double const & PrimaryDistributionRecord::GetHelicity() const { + return helicity; +} + +void PrimaryDistributionRecord::SetParticle(Particle const & particle) { + if(particle.id != id) { + throw std::runtime_error("Cannot set particle with different ID!"); + } + if(particle.type != type) { + throw std::runtime_error("Cannot set particle with different type!"); + } + + mass_set = true; + mass = particle.mass; + + momentum_set = true; + momentum = {particle.momentum.at(1), particle.momentum.at(2), particle.momentum.at(3)}; + + energy_set = true; + energy = particle.momentum.at(0); + + initial_position_set = true; + initial_position = particle.position; + + length_set = true; + length = particle.length; + + helicity_set = true; + helicity = particle.helicity; +} + +void PrimaryDistributionRecord::SetMass(double mass) { + mass_set = true; + this->mass = mass; +} + +void PrimaryDistributionRecord::SetEnergy(double energy) { + energy_set = true; + this->energy = energy; +} + +void PrimaryDistributionRecord::SetKineticEnergy(double kinetic_energy) { + kinetic_energy_set = true; + this->kinetic_energy = kinetic_energy; +} + +void PrimaryDistributionRecord::SetDirection(std::array direction) { + direction_set = true; + this->direction = direction; +} + +void PrimaryDistributionRecord::SetThreeMomentum(std::array momentum) { + momentum_set = true; + this->momentum = momentum; +} + +void PrimaryDistributionRecord::SetFourMomentum(std::array momentum) { + momentum_set = true; + this->momentum = {momentum.at(1), momentum.at(2), momentum.at(3)}; + energy_set = true; + this->energy = momentum.at(0); +} + +void PrimaryDistributionRecord::SetLength(double length) { + length_set = true; + this->length = length; +} + +void PrimaryDistributionRecord::SetInitialPosition(std::array initial_position) { + initial_position_set = true; + this->initial_position = initial_position; +} + +void PrimaryDistributionRecord::SetInteractionVertex(std::array interaction_vertex) { + interaction_vertex_set = true; + this->interaction_vertex = interaction_vertex; +} + +void PrimaryDistributionRecord::SetHelicity(double helicity) { + helicity_set = true; + this->helicity = helicity; +} + +void PrimaryDistributionRecord::UpdateMass() const { + if(mass_set) + return; + if(energy_set and momentum_set) { + mass = std::sqrt(energy*energy - momentum.at(0)*momentum.at(0) - momentum.at(1)*momentum.at(1) - momentum.at(2)*momentum.at(2)); + } else if(energy_set and kinetic_energy_set) { + mass = std::sqrt(energy*energy - kinetic_energy*kinetic_energy); + } else { + throw std::runtime_error("Cannot calculate mass without energy and momentum or energy and kinetic energy!"); + } +} + +void PrimaryDistributionRecord::UpdateEnergy() const { + if(energy_set) + return; + if(mass_set and momentum_set) { + energy = std::sqrt(mass*mass + momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + } else if(mass_set and kinetic_energy_set) { + energy = std::sqrt(mass*mass + kinetic_energy*kinetic_energy); + } else { + throw std::runtime_error("Cannot calculate energy without mass and momentum or mass and kinetic energy!"); + } +} + +void PrimaryDistributionRecord::UpdateKineticEnergy() const { + if(kinetic_energy_set) + return; + if(mass_set and energy_set) { + kinetic_energy = std::sqrt(energy*energy - mass*mass); + } else if(momentum_set) { + kinetic_energy = std::sqrt(momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + } else { + throw std::runtime_error("Cannot calculate kinetic energy without mass and energy or momentum!"); + } +} + +void PrimaryDistributionRecord::UpdateDirection() const { + if(direction_set) + return; + if(momentum_set) { + double magnitude = std::sqrt(momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + direction = {momentum.at(0)/magnitude, momentum.at(1)/magnitude, momentum.at(2)/magnitude}; + } else if(initial_position_set and interaction_vertex_set) { + direction = {interaction_vertex.at(0) - initial_position.at(0), interaction_vertex.at(1) - initial_position.at(1), interaction_vertex.at(2) - initial_position.at(2)}; + double magnitude = std::sqrt(direction.at(0)*direction.at(0) + direction.at(1)*direction.at(1) + direction.at(2)*direction.at(2)); + direction = {direction.at(0)/magnitude, direction.at(1)/magnitude, direction.at(2)/magnitude}; + } else { + throw std::runtime_error("Cannot calculate direction without momentum or initial position and interaction vertex!"); + } +} + +void PrimaryDistributionRecord::UpdateMomentum() const { + if(momentum_set) + return; + if(energy_set and mass_set and direction_set) { + double magnitude = std::sqrt(energy*energy - mass*mass); + momentum = {magnitude*direction.at(0), magnitude*direction.at(1), magnitude*direction.at(2)}; + } else if(kinetic_energy_set and direction_set) { + double magnitude = kinetic_energy; + momentum = {magnitude*direction.at(0), magnitude*direction.at(1), magnitude*direction.at(2)}; + } else { + throw std::runtime_error("Cannot calculate momentum without energy and mass and direction or kinetic energy and direction!"); + } +} + +void PrimaryDistributionRecord::UpdateLength() const { + if(length_set) + return; + if(initial_position_set and interaction_vertex_set) { + length = std::sqrt( + (interaction_vertex.at(0) - initial_position.at(0))*(interaction_vertex.at(0) - initial_position.at(0)) + + (interaction_vertex.at(1) - initial_position.at(1))*(interaction_vertex.at(1) - initial_position.at(1)) + + (interaction_vertex.at(2) - initial_position.at(2))*(interaction_vertex.at(2) - initial_position.at(2)) + ); + } else { + throw std::runtime_error("Cannot calculate length without initial position and interaction vertex!"); + } +} + +void PrimaryDistributionRecord::UpdateInitialPosition() const { + if(initial_position_set) + return; + if(interaction_vertex_set and direction_set and length_set) { + initial_position = {interaction_vertex.at(0) - length*direction.at(0), interaction_vertex.at(1) - length*direction.at(1), interaction_vertex.at(2) - length*direction.at(2)}; + } else { + throw std::runtime_error("Cannot calculate initial position without interaction vertex and direction and length!"); + } +} + +void PrimaryDistributionRecord::UpdateInteractionVertex() const { + if(interaction_vertex_set) + return; + if(initial_position_set and direction_set and length_set) { + interaction_vertex = {initial_position.at(0) + length*direction.at(0), initial_position.at(1) + length*direction.at(1), initial_position.at(2) + length*direction.at(2)}; + } else { + throw std::runtime_error("Cannot calculate interaction vertex without initial position and direction and length!"); + } +} + +void PrimaryDistributionRecord::FinalizeAvailable(InteractionRecord & record) const { + record.signature.primary_type = type; + record.primary_id = GetID(); + try { + record.primary_initial_position = GetInitialPosition(); + } catch(std::runtime_error e) {} + try { + record.interaction_vertex = GetInteractionVertex(); + } catch(std::runtime_error e) {} + try { + record.primary_mass = GetMass(); + } catch(std::runtime_error e) {} + try { + record.primary_momentum = GetFourMomentum(); + } catch(std::runtime_error e) {} + try { + record.primary_helicity = GetHelicity(); + } catch(std::runtime_error e) {} +} + +void PrimaryDistributionRecord::Finalize(InteractionRecord & record) const { + record.signature.primary_type = type; + record.primary_id = GetID(); + record.interaction_vertex = GetInteractionVertex(); + record.primary_initial_position = GetInitialPosition(); + record.primary_mass = GetMass(); + record.primary_momentum = GetFourMomentum(); + record.primary_helicity = GetHelicity(); +} + +///////////////////////////////////////// + +SecondaryParticleRecord::SecondaryParticleRecord(InteractionRecord const & record, size_t secondary_index) : + secondary_index(secondary_index), + id((record.secondary_ids.size() > secondary_index and record.secondary_ids.at(secondary_index)) ? (record.secondary_ids.at(secondary_index)) : (ParticleID::GenerateID())), + type(record.signature.secondary_types.at(secondary_index)), + initial_position(record.interaction_vertex) +{} + +Particle SecondaryParticleRecord::GetParticle() const { + Particle p; + p.id = id; + p.type = type; + try { + p.mass = GetMass(); + } catch(...) { + p.mass = 0; + } + try { + p.momentum = GetFourMomentum(); + } catch(...) { + p.momentum = {0, 0, 0, 0}; + } + try { + p.position = GetInitialPosition(); + } catch(...) { + p.position = {0, 0, 0}; + } + try { + p.helicity = GetHelicity(); + } catch(...) { + p.helicity = 0; + } + return p; +} + +void SecondaryParticleRecord::SetParticle(Particle const & particle) { + if(particle.id != id) { + throw std::runtime_error("Cannot set particle with different ID!"); + } + if(particle.type != type) { + throw std::runtime_error("Cannot set particle with different type!"); + } + + mass_set = true; + mass = particle.mass; + + momentum_set = true; + momentum = {particle.momentum.at(1), particle.momentum.at(2), particle.momentum.at(3)}; + + energy_set = true; + energy = particle.momentum.at(0); + + helicity_set = true; + helicity = particle.helicity; +} + +ParticleID const & SecondaryParticleRecord::GetID() const { + return id; +} + +ParticleType const & SecondaryParticleRecord::GetType() const { + return type; +} + +double const & SecondaryParticleRecord::GetMass() const { + if(not mass_set) { + UpdateMass(); + } + return mass; +} + +double const & SecondaryParticleRecord::GetEnergy() const { + if(not energy_set) { + UpdateEnergy(); + } + return energy; +} + +double const & SecondaryParticleRecord::GetKineticEnergy() const { + if(not kinetic_energy_set) { + UpdateKineticEnergy(); + } + return kinetic_energy; +} + +std::array const & SecondaryParticleRecord::GetDirection() const { + if(not direction_set) { + UpdateDirection(); + } + return direction; +} + +std::array const & SecondaryParticleRecord::GetThreeMomentum() const { + if(not momentum_set) { + UpdateMomentum(); + } + return momentum; +} + +std::array SecondaryParticleRecord::GetFourMomentum() const { + if(not momentum_set) { + UpdateMomentum(); + } + if(not energy_set) { + UpdateEnergy(); + } + return {energy, momentum.at(0), momentum.at(1), momentum.at(2)}; +} + +std::array const & SecondaryParticleRecord::GetInitialPosition() const { + return initial_position; +} + +double const & SecondaryParticleRecord::GetHelicity() const { + return helicity; +} + +void SecondaryParticleRecord::SetMass(double mass) { + mass_set = true; + this->mass = mass; +} + +void SecondaryParticleRecord::SetEnergy(double energy) { + energy_set = true; + this->energy = energy; +} + +void SecondaryParticleRecord::SetKineticEnergy(double kinetic_energy) { + kinetic_energy_set = true; + this->kinetic_energy = kinetic_energy; +} + +void SecondaryParticleRecord::SetDirection(std::array direction) { + direction_set = true; + this->direction = direction; +} + +void SecondaryParticleRecord::SetThreeMomentum(std::array momentum) { + momentum_set = true; + this->momentum = momentum; +} + +void SecondaryParticleRecord::SetFourMomentum(std::array momentum) { + momentum_set = true; + this->momentum = {momentum.at(1), momentum.at(2), momentum.at(3)}; + energy_set = true; + this->energy = momentum.at(0); +} + +void SecondaryParticleRecord::SetHelicity(double helicity) { + helicity_set = true; + this->helicity = helicity; +} + +void SecondaryParticleRecord::UpdateMass() const { + if(mass_set) + return; + if(energy_set and momentum_set) { + mass = std::sqrt(energy*energy - momentum.at(0)*momentum.at(0) - momentum.at(1)*momentum.at(1) - momentum.at(2)*momentum.at(2)); + } else if(energy_set and kinetic_energy_set) { + mass = std::sqrt(energy*energy - kinetic_energy*kinetic_energy); + } else { + throw std::runtime_error("Cannot calculate mass without energy and momentum or energy and kinetic energy!"); + } +} + +void SecondaryParticleRecord::UpdateEnergy() const { + if(energy_set) + return; + if(mass_set and momentum_set) { + energy = std::sqrt(mass*mass + momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + } else if(mass_set and kinetic_energy_set) { + energy = std::sqrt(mass*mass + kinetic_energy*kinetic_energy); + } else { + throw std::runtime_error("Cannot calculate energy without mass and momentum or mass and kinetic energy!"); + } +} + +void SecondaryParticleRecord::UpdateKineticEnergy() const { + if(kinetic_energy_set) + return; + if(mass_set and energy_set) { + kinetic_energy = std::sqrt(energy*energy - mass*mass); + } else if(momentum_set) { + kinetic_energy = std::sqrt(momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + } else { + throw std::runtime_error("Cannot calculate kinetic energy without mass and energy or momentum!"); + } +} + +void SecondaryParticleRecord::UpdateDirection() const { + if(direction_set) + return; + if(momentum_set) { + double magnitude = std::sqrt(momentum.at(0)*momentum.at(0) + momentum.at(1)*momentum.at(1) + momentum.at(2)*momentum.at(2)); + direction = {momentum.at(0)/magnitude, momentum.at(1)/magnitude, momentum.at(2)/magnitude}; + } else { + throw std::runtime_error("Cannot calculate direction without momentum or initial position and interaction vertex!"); + } +} + +void SecondaryParticleRecord::UpdateMomentum() const { + if(momentum_set) + return; + if(energy_set and mass_set and direction_set) { + double magnitude = std::sqrt(energy*energy - mass*mass); + momentum = {magnitude*direction.at(0), magnitude*direction.at(1), magnitude*direction.at(2)}; + } else if(kinetic_energy_set and direction_set) { + double magnitude = kinetic_energy; + momentum = {magnitude*direction.at(0), magnitude*direction.at(1), magnitude*direction.at(2)}; + } else { + throw std::runtime_error("Cannot calculate momentum without energy and mass and direction or kinetic energy and direction!"); + } +} + +void SecondaryParticleRecord::Finalize(InteractionRecord & record) const { + assert(record.signature.secondary_types.at(secondary_index) == type); + record.secondary_ids.at(secondary_index) = GetID(); + record.secondary_masses.at(secondary_index) = GetMass(); + record.secondary_momenta.at(secondary_index) = GetFourMomentum(); + record.secondary_helicities.at(secondary_index) = GetHelicity(); +} + +///////////////////////////////////////// + +CrossSectionDistributionRecord::CrossSectionDistributionRecord(InteractionRecord const & record) : + record(record), + signature(record.signature), + primary_id(record.primary_id), + primary_type(record.signature.primary_type), + primary_initial_position(record.primary_initial_position), + primary_mass(record.primary_mass), + primary_momentum(record.primary_momentum), + primary_helicity(record.primary_helicity), + interaction_vertex(record.interaction_vertex), + target_id((record.target_id) ? (record.target_id) : (ParticleID::GenerateID())), + target_type(record.signature.target_type), + target_mass(record.target_mass), + target_helicity(record.target_helicity) { + + secondary_particles.reserve(record.signature.secondary_types.size()); + for(size_t i = 0; i < record.signature.secondary_types.size(); ++i) { + secondary_particles.emplace_back(record, i); + } +} + +InteractionSignature const & CrossSectionDistributionRecord::GetSignature() const { + return signature; +} + +ParticleID const & CrossSectionDistributionRecord::GetPrimaryID() const { + return primary_id; +} + +ParticleType const & CrossSectionDistributionRecord::GetPrimaryType() const { + return primary_type; +} + +std::array const & CrossSectionDistributionRecord::GetPrimaryInitialPosition() const { + return primary_initial_position; +} + +double const & CrossSectionDistributionRecord::GetPrimaryMass() const { + return primary_mass; +} + +std::array const & CrossSectionDistributionRecord::GetPrimaryMomentum() const { + return primary_momentum; +} + +double const & CrossSectionDistributionRecord::GetPrimaryHelicity() const { + return primary_helicity; +} + +std::array const & CrossSectionDistributionRecord::GetInteractionVertex() const { + return interaction_vertex; +} + +ParticleID const & CrossSectionDistributionRecord::GetTargetID() const { + return target_id; +} + +ParticleType const & CrossSectionDistributionRecord::GetTargetType() const { + return target_type; +} + +double const & CrossSectionDistributionRecord::GetTargetMass() const { + return target_mass; +} + +double const & CrossSectionDistributionRecord::GetTargetHelicity() const { + return target_helicity; +} + +double & CrossSectionDistributionRecord::GetTargetMass() { + return target_mass; +} + +double & CrossSectionDistributionRecord::GetTargetHelicity() { + return target_helicity; +} + +std::map & CrossSectionDistributionRecord::GetInteractionParameters() { + return interaction_parameters; +} + +void CrossSectionDistributionRecord::SetTargetMass(double mass) { + target_mass = mass; +} + +void CrossSectionDistributionRecord::SetTargetHelicity(double helicity) { + target_helicity = helicity; +} + +void CrossSectionDistributionRecord::SetInteractionParameters(std::map const & parameters) { + interaction_parameters = parameters; +} + +void CrossSectionDistributionRecord::SetInteractionParameter(std::string const & name, double value) { + interaction_parameters[name] = value; +} + +std::vector & CrossSectionDistributionRecord::GetSecondaryParticleRecords() { + return secondary_particles; +} + +std::vector const & CrossSectionDistributionRecord::GetSecondaryParticleRecords() const { + return secondary_particles; +} + +SecondaryParticleRecord & CrossSectionDistributionRecord::GetSecondaryParticleRecord(size_t index) { + return secondary_particles.at(index); +} + +SecondaryParticleRecord const & CrossSectionDistributionRecord::GetSecondaryParticleRecord(size_t index) const { + return secondary_particles.at(index); +} + +void CrossSectionDistributionRecord::Finalize(InteractionRecord & record) const { + record.target_id = target_id; + record.target_mass = target_mass; + record.target_helicity = target_helicity; + + record.interaction_parameters = interaction_parameters; + + record.secondary_ids.resize(secondary_particles.size()); + record.secondary_masses.resize(secondary_particles.size()); + record.secondary_momenta.resize(secondary_particles.size()); + record.secondary_helicities.resize(secondary_particles.size()); + + for(SecondaryParticleRecord const & secondary : secondary_particles) { + secondary.Finalize(record); + } +} + +///////////////////////////////////////// + +InteractionRecord SecondaryDistributionRecord::CreateSecondaryRecord(InteractionRecord const & parent_record, size_t secondary_index) { + InteractionRecord record; + + record.primary_id = ((parent_record.secondary_ids.at(secondary_index)) ? (parent_record.secondary_ids.at(secondary_index)) : (ParticleID::GenerateID())), + record.signature.primary_type = parent_record.signature.secondary_types.at(secondary_index); + record.primary_mass = parent_record.secondary_masses.at(secondary_index); + record.primary_momentum = parent_record.secondary_momenta.at(secondary_index); + record.primary_helicity = parent_record.secondary_helicities.at(secondary_index); + record.primary_initial_position = parent_record.interaction_vertex; + return record; +} + +SecondaryDistributionRecord::SecondaryDistributionRecord(InteractionRecord & record) : + record([](InteractionRecord & record) -> InteractionRecord & { + record.primary_id = ((record.primary_id) ? (record.primary_id) : (ParticleID::GenerateID())); + return record; + }(record)), + id(record.primary_id), + type(record.signature.primary_type), + mass(record.primary_mass), + direction([](InteractionRecord const & record) -> std::array { + std::array direction; + if(record.primary_momentum.at(0) != 0) { + double magnitude = std::sqrt(record.primary_momentum.at(1)*record.primary_momentum.at(1) + record.primary_momentum.at(2)*record.primary_momentum.at(2) + record.primary_momentum.at(3)*record.primary_momentum.at(3)); + direction = {record.primary_momentum.at(1)/magnitude, record.primary_momentum.at(2)/magnitude, record.primary_momentum.at(3)/magnitude}; + } else { + direction = {0, 0, 0}; + } + return direction; + }(record)), + momentum(record.primary_momentum), + helicity(record.primary_helicity), + initial_position(record.primary_initial_position) {} + +SecondaryDistributionRecord::SecondaryDistributionRecord(InteractionRecord const & parent_record, size_t secondary_index) : + secondary_index(secondary_index), + record(SecondaryDistributionRecord::CreateSecondaryRecord(parent_record, secondary_index)), + id(record.primary_id), + type(record.signature.primary_type), + mass(record.primary_mass), + direction([](InteractionRecord const & record) -> std::array { + std::array direction; + if(record.primary_momentum.at(0) != 0) { + double magnitude = std::sqrt(record.primary_momentum.at(1)*record.primary_momentum.at(1) + record.primary_momentum.at(2)*record.primary_momentum.at(2) + record.primary_momentum.at(3)*record.primary_momentum.at(3)); + direction = {record.primary_momentum.at(1)/magnitude, record.primary_momentum.at(2)/magnitude, record.primary_momentum.at(3)/magnitude}; + } else { + direction = {0, 0, 0}; + } + return direction; + }(record)), + momentum(record.primary_momentum), + helicity(record.primary_helicity), + initial_position(record.primary_initial_position) {} + +double const & SecondaryDistributionRecord::GetLength() const { + if(not length_set) { + throw std::runtime_error("Length not set!"); + } + return length; +} + +void SecondaryDistributionRecord::SetLength(double const & length) { + length_set = true; + this->length = length; +} + +void SecondaryDistributionRecord::Finalize(InteractionRecord & record) const { + record.signature.primary_type = type; + record.primary_id = id; + record.primary_initial_position = initial_position; + record.primary_mass = mass; + record.primary_momentum = momentum; + record.primary_helicity = helicity; + record.interaction_vertex = initial_position; + record.interaction_vertex.at(0) += length*direction.at(0); + record.interaction_vertex.at(1) += length*direction.at(1); + record.interaction_vertex.at(2) += length*direction.at(2); +} + +///////////////////////////////////////// + bool InteractionRecord::operator==(InteractionRecord const & other) const { return std::tie( signature, + primary_id, + primary_initial_position, primary_mass, primary_momentum, primary_helicity, + target_id, target_mass, - target_momentum, target_helicity, interaction_vertex, + secondary_ids, secondary_masses, secondary_momenta, - secondary_helicity, + secondary_helicities, interaction_parameters) == std::tie( other.signature, + other.primary_id, + other.primary_initial_position, other.primary_mass, other.primary_momentum, other.primary_helicity, + other.target_id, other.target_mass, - other.target_momentum, other.target_helicity, other.interaction_vertex, + other.secondary_ids, other.secondary_masses, other.secondary_momenta, - other.secondary_helicity, + other.secondary_helicities, + other.interaction_parameters); +} + +bool InteractionRecord::operator<(InteractionRecord const & other) const { + return std::tie( + signature, + primary_id, + primary_initial_position, + primary_mass, + primary_momentum, + primary_helicity, + target_id, + target_mass, + target_helicity, + interaction_vertex, + secondary_ids, + secondary_masses, + secondary_momenta, + secondary_helicities, + interaction_parameters) + < + std::tie( + other.signature, + other.primary_id, + other.primary_initial_position, + other.primary_mass, + other.primary_momentum, + other.primary_helicity, + other.target_id, + other.target_mass, + other.target_helicity, + other.interaction_vertex, + other.secondary_ids, + other.secondary_masses, + other.secondary_momenta, + other.secondary_helicities, other.interaction_parameters); } } // namespace dataclasses } // namespace LI +std::ostream & operator<<(std::ostream & os, LI::dataclasses::PrimaryDistributionRecord const & record) { + std::stringstream ss; + ss << "PrimaryDistributionRecord (" << &record << ") "; + os << ss.str() << '\n'; + + ss.str(std::string()); + std::string id_str; + ss << record.GetID(); + id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "ID: " << id_str << "\n"; + + os << "Type: " << record.GetType() << "\n"; + + if(record.mass_set) { + os << "Mass: " << record.GetMass() << "\n"; + } else { + os << "Mass: " << "None" << "\n"; + } + + if(record.energy_set) { + os << "Energy: " << record.GetEnergy() << "\n"; + } else { + os << "Energy: " << "None" << "\n"; + } + + if(record.kinetic_energy_set) { + os << "KineticEnergy: " << record.GetKineticEnergy() << "\n"; + } else { + os << "KineticEnergy: " << "None" << "\n"; + } + + if(record.direction_set) { + os << "Direction: " << record.GetDirection().at(0) << " " << record.GetDirection().at(1) << " " << record.GetDirection().at(2) << "\n"; + } else { + os << "Direction: " << "None" << "\n"; + } + + if(record.momentum_set) { + os << "Momentum: " << record.GetThreeMomentum().at(0) << " " << record.GetThreeMomentum().at(1) << " " << record.GetThreeMomentum().at(2) << "\n"; + } else { + os << "Momentum: " << "None" << "\n"; + } + + if(record.length_set) { + os << "Length: " << record.GetLength() << "\n"; + } else { + os << "Length: " << "None" << "\n"; + } + + if(record.initial_position_set) { + os << "InitialPosition: " << record.GetInitialPosition().at(0) << " " << record.GetInitialPosition().at(1) << " " << record.GetInitialPosition().at(2) << "\n"; + } else { + os << "InitialPosition: " << "None" << "\n"; + } + + if(record.interaction_vertex_set) { + os << "InteractionVertex: " << record.GetInteractionVertex().at(0) << " " << record.GetInteractionVertex().at(1) << " " << record.GetInteractionVertex().at(2) << "\n"; + } else { + os << "InteractionVertex: " << "None" << "\n"; + } + + if(record.helicity_set) { + os << "Helicity: " << record.GetHelicity() << "\n"; + } else { + os << "Helicity: " << "None" << "\n"; + } + + return os; +} + +std::ostream & operator<<(std::ostream & os, LI::dataclasses::CrossSectionDistributionRecord const & record) { + std::stringstream ss; + ss << "CrossSectionDistributionRecord (" << &record << ") "; + os << ss.str() << '\n'; + + ss.str(std::string()); + std::string id_str; + ss << record.GetPrimaryID(); + id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "PrimaryID: " << id_str << "\n"; + + os << "PrimaryType: " << record.primary_type << "\n"; + + os << "PrimaryInitialPosition: " << record.primary_initial_position.at(0) << " " << record.primary_initial_position.at(1) << " " << record.primary_initial_position.at(2) << "\n"; + + os << "PrimaryMass: " << record.primary_mass << "\n"; + + os << "PrimaryMomentum: " << record.primary_momentum.at(0) << " " << record.primary_momentum.at(1) << " " << record.primary_momentum.at(2) << " " << record.primary_momentum.at(3) << "\n"; + + os << "PrimaryHelicity: " << record.primary_helicity << "\n"; + + os << "InteractionVertex: " << record.interaction_vertex.at(0) << " " << record.interaction_vertex.at(1) << " " << record.interaction_vertex.at(2) << "\n"; + + ss.str(std::string()); + ss << record.GetTargetID(); + id_str = ss.str(); + start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "TargetID: " << id_str << "\n"; + + os << "TargetType: " << record.target_type << "\n"; + + os << "TargetMass: " << record.target_mass << "\n"; + + os << "TargetHelicity: " << record.target_helicity << "\n"; + + if(record.interaction_parameters.size() > 0) { + os << "InteractionParameters:\n"; + for(auto const & parameter: record.interaction_parameters) { + os << "\t" << parameter.first << ": " << parameter.second << "\n"; + } + } else { + os << "InteractionParameters: " << "None" << "\n"; + } + + os << "SecondaryParticles:\n"; + std::string secondary_str; + for(size_t i = 0; i < record.signature.secondary_types.size(); ++i) { + ss.str(std::string()); + ss << record.GetSecondaryParticleRecord(i); + secondary_str = ss.str(); + start_pos = 0; + while((start_pos = secondary_str.find(from, start_pos)) != std::string::npos) { + secondary_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << secondary_str << "\n"; + } + + return os; +} + +std::ostream & operator<<(std::ostream & os, LI::dataclasses::SecondaryParticleRecord const & record) { + std::stringstream ss; + ss << "SecondaryParticleRecord (" << &record << ") "; + os << ss.str() << '\n'; + + ss.str(std::string()); + std::string id_str; + ss << record.GetID(); + id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "ID: " << id_str << "\n"; + + os << "Type: " << record.GetType() << "\n"; + + if(record.mass_set) { + os << "Mass: " << record.mass << "\n"; + } else { + os << "Mass: " << "None" << "\n"; + } + + if(record.energy_set) { + os << "Energy: " << record.energy << "\n"; + } else { + os << "Energy: " << "None" << "\n"; + } + + if(record.kinetic_energy_set) { + os << "KineticEnergy: " << record.kinetic_energy << "\n"; + } else { + os << "KineticEnergy: " << "None" << "\n"; + } + + if(record.direction_set) { + os << "Direction: " << record.direction.at(0) << " " << record.direction.at(1) << " " << record.direction.at(2) << "\n"; + } else { + os << "Direction: " << "None" << "\n"; + } + + if(record.momentum_set) { + os << "Momentum: " << record.momentum.at(0) << " " << record.momentum.at(1) << " " << record.momentum.at(2) << "\n"; + } else { + os << "Momentum: " << "None" << "\n"; + } + + os << "InitialPosition: " << record.initial_position.at(0) << " " << record.initial_position.at(1) << " " << record.initial_position.at(2) << "\n"; + + if(record.helicity_set) { + os << "Helicity: " << record.helicity << "\n"; + } else { + os << "Helicity: " << "None" << "\n"; + } + + return os; +} + +std::ostream& operator<<(std::ostream& os, LI::dataclasses::SecondaryDistributionRecord const& record) { + std::stringstream ss; + ss << "SecondaryDistributionRecord (" << &record << ") "; + os << ss.str() << '\n'; + + ss.str(std::string()); + std::string id_str; + ss << record.id; + id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "ID: " << id_str << "\n"; + + os << "Type: " << record.type << "\n"; + + os << "Mass: " << record.mass << "\n"; + + os << "Direction: " << record.direction.at(0) << " " << record.direction.at(1) << " " << record.direction.at(2) << "\n"; + + os << "Momentum: " << record.momentum.at(0) << " " << record.momentum.at(1) << " " << record.momentum.at(2) << " " << record.momentum.at(3) << "\n"; + + os << "Helicity: " << record.helicity << "\n"; + + os << "InitialPosition: " << record.initial_position.at(0) << " " << record.initial_position.at(1) << " " << record.initial_position.at(2) << "\n"; + + if(record.length_set) { + os << "Length: " << record.GetLength() << "\n"; + } else { + os << "Length: " << "None" << "\n"; + } + + return os; +} + std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionRecord const& record) { std::stringstream ss; ss << "InteractionRecord (" << &record << ") "; @@ -49,22 +1109,48 @@ std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionRecord co } os << "\n"; - os << "InteractionVertex: " << record.interaction_vertex[0] << " " << record.interaction_vertex[1] << " " << record.interaction_vertex[2] << "\n"; + ss.str(std::string()); + std::string id_str; + ss << record.primary_id; + id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + ss << "PrimaryID: " << id_str << "\n"; + os << "PrimaryInitialPosition: " << record.primary_initial_position.at(0) << " " << record.primary_initial_position.at(1) << " " << record.primary_initial_position.at(2) << "\n"; + os << "InteractionVertex: " << record.interaction_vertex.at(0) << " " << record.interaction_vertex.at(1) << " " << record.interaction_vertex.at(2) << "\n"; os << "PrimaryMass: " << record.primary_mass << "\n"; - os << "PrimaryMomentum: " << record.primary_momentum[0] << " " << record.primary_momentum[1] << " " << record.primary_momentum[2] << " " << record.primary_momentum[3] << "\n"; + os << "PrimaryMomentum: " << record.primary_momentum.at(0) << " " << record.primary_momentum.at(1) << " " << record.primary_momentum.at(2) << " " << record.primary_momentum.at(3) << "\n"; + os << "TargetID: " << record.target_id << "\n"; os << "TargetMass: " << record.target_mass << "\n"; - os << "TargetMomentum: " << record.target_momentum[0] << " " << record.target_momentum[1] << " " << record.target_momentum[2] << " " << record.target_momentum[3] << "\n"; + os << "SecondaryIDs:\n"; + for(auto const & secondary: record.secondary_ids) { + ss.str(std::string()); + id_str.clear(); + ss << secondary; + id_str = ss.str(); + start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + os << "\t" << id_str << "\n"; + } os << "SecondaryMomenta:\n"; for(auto const & secondary: record.secondary_momenta) { - os << "\t" << secondary[0] << " " << secondary[1] << " " << secondary[2] << " " << secondary[3] << "\n"; + os << "\t" << secondary.at(0) << " " << secondary.at(1) << " " << secondary.at(2) << " " << secondary.at(3) << "\n"; } os << "SecondaryMasses:\n"; for(auto const & secondary: record.secondary_masses) { os << "\t" << secondary << "\n"; } - os << "InteractionParameters:"; - for(auto param: record.interaction_parameters) { - os << " " << param; + os << "InteractionParameters:\n"; + for(std::pair const & param : record.interaction_parameters) { + os << "\t\"" << param.first << "\": " << param.second << "\n"; } os << std::endl; diff --git a/projects/dataclasses/private/InteractionSignature.cxx b/projects/dataclasses/private/InteractionSignature.cxx index d2a1e2bef..46639573c 100644 --- a/projects/dataclasses/private/InteractionSignature.cxx +++ b/projects/dataclasses/private/InteractionSignature.cxx @@ -11,31 +11,6 @@ bool InteractionSignature::operator==(InteractionSignature const & other) const std::tie(primary_type, target_type, secondary_types) == std::tie(other.primary_type, other.target_type, other.secondary_types); - /* - if(primary_type != other.primary_type or target_type != other.target_type) { - return false; - } else { - std::map m0; - for(auto p : secondary_types) { - auto it = m0.find(p); - if(it == m0.end()) { - m0.insert({p, 1}); - } else { - it->second += 1; - } - } - std::map m1; - for(auto p : other.secondary_types) { - auto it = m1.find(p); - if(it == m1.end()) { - m1.insert({p, 1}); - } else { - it->second += 1; - } - } - return m0 == m1; - } - */ } bool InteractionSignature::operator<(InteractionSignature const & other) const { diff --git a/projects/dataclasses/private/InteractionTree.cxx b/projects/dataclasses/private/InteractionTree.cxx index f54709a7a..d867cbd16 100644 --- a/projects/dataclasses/private/InteractionTree.cxx +++ b/projects/dataclasses/private/InteractionTree.cxx @@ -6,37 +6,47 @@ namespace LI { namespace dataclasses { int InteractionTreeDatum::depth() const { - int depth = 0; - if(parent==NULL) return depth; - std::shared_ptr test = std::make_shared(*parent); - while(true) { - ++depth; - if(test->parent==NULL) return depth; - test = std::make_shared(*(test->parent)); - } - return -1; + int depth = 0; + if(parent==NULL) return depth; + std::shared_ptr test = std::make_shared(*parent); + while(true) { + ++depth; + if(test->parent==NULL) return depth; + test = std::make_shared(*(test->parent)); + } + return -1; +} + +std::shared_ptr InteractionTree::add_entry(std::shared_ptr datum, + std::shared_ptr parent) { + if (parent) { + datum->parent = parent; + parent->daughters.push_back(datum); + } + tree.insert(datum); + return datum; } std::shared_ptr InteractionTree::add_entry(InteractionTreeDatum& datum, - std::shared_ptr parent) { - std::shared_ptr _datum = std::make_shared(datum); - _datum->parent = parent; - if (parent) { - parent->daughters.push_back(_datum); - } - tree.insert(_datum); - return _datum; + std::shared_ptr parent) { + std::shared_ptr _datum = std::make_shared(datum); + if (parent) { + _datum->parent = parent; + parent->daughters.push_back(_datum); + } + tree.insert(_datum); + return _datum; } std::shared_ptr InteractionTree::add_entry(InteractionRecord& record, - std::shared_ptr parent) { - std::shared_ptr datum = std::make_shared(record); - datum->parent = parent; - if (parent) { - parent->daughters.push_back(datum); - } - tree.insert(datum); - return datum; + std::shared_ptr parent) { + std::shared_ptr datum = std::make_shared(record); + if (parent) { + datum->parent = parent; + parent->daughters.push_back(datum); + } + tree.insert(datum); + return datum; } } // namespace dataclasses diff --git a/projects/dataclasses/private/Particle.cxx b/projects/dataclasses/private/Particle.cxx index 2a237ec81..906e33a60 100644 --- a/projects/dataclasses/private/Particle.cxx +++ b/projects/dataclasses/private/Particle.cxx @@ -12,307 +12,76 @@ #include "LeptonInjector/utilities/Constants.h" -namespace LI { -namespace dataclasses { - Particle::Particle(void){ - // Just sit it at the origin - - // note that - // static_cast(ParticleType::EMinus) == 11 - type = ParticleType::unknown; - - // instantiate with minimum energy - energy = 0.0; - direction = std::make_pair( 0.0, 0.0) ; - for (uint8_t var = 0; var<3; var++){ - position[var] = 0.0; - } - } - - // constructor for specific type - Particle::Particle( ParticleType type ){ - this->type = type; - - // energy will instead be built using particle's mass - energy = this->GetMass(); - direction = std::make_pair(0.0, 0.0); - for (uint8_t var = 0; var<3; var++){ - position[var] = 0.0; - } +std::ostream& operator<<(std::ostream& os, LI::dataclasses::Particle const& p) { + os << "Particle (" << &p << ")\n"; + + std::stringstream ss; + ss << p.id; + std::string id_str = ss.str(); + std::string from = "\n"; + std::string to = "\n "; + size_t start_pos = 0; + while((start_pos = id_str.find(from, start_pos)) != std::string::npos) { + id_str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' } + os << "ID: " << id_str << "\n"; + os << "Type: " << p.type << "\n"; + os << "Mass: " << p.mass << "\n"; + os << "Momentum: " << p.momentum.at(0) << " " << p.momentum.at(1) << " " << p.momentum.at(2) << " " << p.momentum.at(3) << "\n"; + os << "Position: " << p.position.at(0) << " " << p.position.at(1) << " " << p.position.at(2) << "\n"; + os << "Length: " << p.length << "\n"; + os << "Helicity: " << p.helicity; + return os; +} - // returns name for particle of known type. - // If this code is to be expanded, this should really be modified to use the boost preprocessor libraries - // atm, only implemented for the particles relevant to LeptonInjector - std::string Particle::GetTypeString(){ - - // there is a way to do this better with boost preprocessor libraries, but I think that's a little unnecessary given the scope of what LI does. - - // this just casts the particle type to its pdg code, and uses a switch to grab the name - switch( static_cast(this->type) ){ - case 0: return("Unknown"); break; - case 22: return("Gamma"); break; - case 11: return("EMinus"); break; - case -11: return("EPlus"); break; - case 13: return("MuMinus"); break; - case -13: return("MuPlus"); break; - case 15: return("TauMinus"); break; - case -15: return("TauPlus"); break; - case 12: return("NuE"); break; - case -12: return("NuEBar"); break; - case 14: return("NuMu"); break; - case -14: return("NuMuBar"); break; - case 16: return("NuTau"); break; - case -16: return("NuTauBar"); break; - case -2000001006: return("Hadrons"); break; - default: return("Unsupported"); break; - } - - } - - bool Particle::HasMass(){ - // return the negation of the bool that (particle is massless) - return(!( this->type == ParticleType::Gamma || - this->type == ParticleType::NuE || this->type==ParticleType::NuEBar || - this->type == ParticleType::NuMu || this->type==ParticleType::NuMuBar || - this->type == ParticleType::NuTau || this->type==ParticleType::NuTauBar || - this->type == ParticleType::Hadrons) ); - } - - // only implemented for the charged leptons to stay within scope - double Particle::GetMass(){ - switch(this->type){ - case ParticleType::EPlus: - return( LI::utilities::Constants::electronMass ); - break; - case ParticleType::EMinus: - return( LI::utilities::Constants::electronMass ); - break; - case ParticleType::MuPlus: - return( LI::utilities::Constants::muonMass ); - break; - case ParticleType::MuMinus: - return( LI::utilities::Constants::muonMass ); - break; - case ParticleType::TauPlus: - return( LI::utilities::Constants::tauMass ); - break; - case ParticleType::TauMinus: - return( LI::utilities::Constants::tauMass ); - break; - case ParticleType::PPlus: - return( LI::utilities::Constants::protonMass ); - break; - case ParticleType::Neutron: - return( LI::utilities::Constants::neutronMass); - default: - return(0.0); - } - } - - +namespace LI { +namespace dataclasses { - // Helper functions for dealing with particle types - bool isNeutrino(Particle::ParticleType p) { - return ( - p==Particle::ParticleType::NuE || p==Particle::ParticleType::NuEBar || - p==Particle::ParticleType::NuMu || p==Particle::ParticleType::NuMuBar || - p==Particle::ParticleType::NuTau || p==Particle::ParticleType::NuTauBar - ); +Particle::Particle(ParticleID id, ParticleType type, double mass, std::array momentum, std::array position, double length, double helicity) : id(id), type(type), mass(mass), momentum(momentum), position(position), length(length), helicity(helicity) {} + +Particle::Particle(ParticleType type, double mass, std::array momentum, std::array position, double length, double helicity) : type(type), mass(mass), momentum(momentum), position(position), length(length), helicity(helicity) {} + +ParticleID & Particle::GenerateID() { + id = ParticleID::GenerateID(); + return id; +} + +// Helper functions for dealing with particle types +bool isNeutrino(Particle::ParticleType p) { + return ( + p==Particle::ParticleType::NuE || p==Particle::ParticleType::NuEBar || + p==Particle::ParticleType::NuMu || p==Particle::ParticleType::NuMuBar || + p==Particle::ParticleType::NuTau || p==Particle::ParticleType::NuTauBar + ); +} + +// returns true if a particle is a Lepton. False if not +bool isLepton(Particle::ParticleType p){ + return(p==Particle::ParticleType::EMinus || p==Particle::ParticleType::EPlus || + p==Particle::ParticleType::MuMinus || p==Particle::ParticleType::MuPlus || + p==Particle::ParticleType::TauMinus || p==Particle::ParticleType::TauPlus || + p==Particle::ParticleType::NuE || p==Particle::ParticleType::NuEBar || + p==Particle::ParticleType::NuMu || p==Particle::ParticleType::NuMuBar || + p==Particle::ParticleType::NuTau || p==Particle::ParticleType::NuTauBar); +} + +// returns true if the particle is either +// a charged lepton +// (OR) a "hadrons" particle +bool isCharged(Particle::ParticleType p){ + if( !(isLepton(p) || p==Particle::ParticleType::Hadrons) ){ + throw std::runtime_error("You should only be using Leptons or Hadrons!"); } - // returns true if a particle is a Lepton. False if not - bool isLepton(Particle::ParticleType p){ - return(p==Particle::ParticleType::EMinus || p==Particle::ParticleType::EPlus || - p==Particle::ParticleType::MuMinus || p==Particle::ParticleType::MuPlus || - p==Particle::ParticleType::TauMinus || p==Particle::ParticleType::TauPlus || - p==Particle::ParticleType::NuE || p==Particle::ParticleType::NuEBar || - p==Particle::ParticleType::NuMu || p==Particle::ParticleType::NuMuBar || - p==Particle::ParticleType::NuTau || p==Particle::ParticleType::NuTauBar); - } - - // returns true if the particle is either - // a charged lepton - // (OR) a "hadrons" particle - bool isCharged(Particle::ParticleType p){ - if( !(isLepton(p) || p==Particle::ParticleType::Hadrons) ){ - throw std::runtime_error("You should only be using Leptons or Hadrons!"); - } - - // keeps this within scope. Shouldn't be getting some other kind of charged particle - return(p==Particle::ParticleType::EMinus || p==Particle::ParticleType::EPlus || - p==Particle::ParticleType::MuMinus || p==Particle::ParticleType::MuPlus || - p==Particle::ParticleType::TauMinus || p==Particle::ParticleType::TauPlus || - p==Particle::ParticleType::Hadrons); - } - - - // returns string of particle's name - std::string particleName(Particle::ParticleType p){ - return(Particle(p).GetTypeString()); - } - - - // gets the mass of a particle for a given type - double particleMass(Particle::ParticleType type){ - Particle p(type); - if(!p.HasMass()){ - return(0); - } - return(p.GetMass()); - } - - // Uses a particle's type (mass) and total energy to calculate kinetic energy - double kineticEnergy(Particle::ParticleType type, double totalEnergy){ - double mass=particleMass(type); - if(totalEnergy0 THEN return mass/(stuff) ... ELSE return 0 - double r=(mass>0 ? mass/(kineticEnergy+mass) : 0.); - return(LI::utilities::Constants::c*sqrt(1-r*r)); - } - - Particle::ParticleShape decideShape(Particle::ParticleType t){ - switch(t){ - case Particle::ParticleType::MuMinus: case Particle::ParticleType::MuPlus: - case Particle::ParticleType::TauMinus: case Particle::ParticleType::TauPlus: - case Particle::ParticleType::NuE: case Particle::ParticleType::NuEBar: - case Particle::ParticleType::NuMu: case Particle::ParticleType::NuMuBar: - case Particle::ParticleType::NuTau: case Particle::ParticleType::NuTauBar: - return(Particle::ParticleShape::MCTrack); - case Particle::ParticleType::EMinus: case Particle::ParticleType::EPlus: - case Particle::ParticleType::Hadrons: - return(Particle::ParticleShape::Cascade); - case Particle::ParticleType::unknown: - return(Particle::ParticleShape::unknown); - default: - throw "BadShape"; // this replaces the previous fatal log -// log_fatal_stream("Unable to decide shape for unexpected particle type: " << particleName(t)); - } - } - - uint8_t getInteraction( Particle::ParticleType final_1 , Particle::ParticleType final_2){ - // check for GR - if ((final_1==Particle::ParticleType::EMinus && final_2 == Particle::ParticleType::NuEBar)|| - (final_1==Particle::ParticleType::MuMinus && final_2 == Particle::ParticleType::NuMuBar)|| - (final_1==Particle::ParticleType::TauMinus && final_2 == Particle::ParticleType::NuTauBar)|| - (final_2==Particle::ParticleType::EMinus && final_1 == Particle::ParticleType::NuEBar)|| - (final_2==Particle::ParticleType::MuMinus && final_1 == Particle::ParticleType::NuMuBar)|| - (final_2==Particle::ParticleType::TauMinus && final_1 == Particle::ParticleType::NuTauBar)|| - (final_1==Particle::ParticleType::Hadrons && final_2 == Particle::ParticleType::Hadrons)){ - return( 2 ); // glashow resonance - }else if( ((final_2==Particle::ParticleType::Hadrons) and ( - final_1==Particle::Particle::EPlus || final_1==Particle::Particle::EMinus || - final_1==Particle::Particle::MuPlus || final_1==Particle::Particle::MuMinus || - final_1==Particle::Particle::TauPlus || final_1==Particle::Particle::TauMinus)) or - ((final_1==Particle::ParticleType::Hadrons) and ( - final_2==Particle::Particle::EPlus || final_2==Particle::Particle::EMinus || - final_2==Particle::Particle::MuPlus || final_2==Particle::Particle::MuMinus || - final_2==Particle::Particle::TauPlus || final_2==Particle::Particle::TauMinus ))){ - return( 0 ); // charged current - }else if( ((final_2==Particle::ParticleType::Hadrons) and ( - final_1==Particle::Particle::NuEBar || final_1==Particle::Particle::NuE || - final_1==Particle::Particle::NuMuBar || final_1==Particle::Particle::NuMu || - final_1==Particle::Particle::NuTauBar || final_1==Particle::Particle::NuTau )) or - ((final_1==Particle::ParticleType::Hadrons) and ( - final_2==Particle::Particle::NuEBar || final_2==Particle::Particle::NuE || - final_2==Particle::Particle::NuMuBar || final_2==Particle::Particle::NuMu || - final_2==Particle::Particle::NuTauBar || final_2==Particle::Particle::NuTau ))){ - return( 1 ); // neutral current - } - - throw std::runtime_error("Interaction type not recognized"); - } - - // This function returns the primary particle type given the final state particles - // returns a particle type object - Particle::ParticleType deduceInitialType(Particle::ParticleType pType1, Particle::ParticleType pType2){ - //only accept certain particle types in general - if(!isLepton(pType1) && pType1!=Particle::ParticleType::Hadrons) - throw std::runtime_error("BadParticle"); - if(!isLepton(pType2) && pType2!=Particle::ParticleType::Hadrons) - throw std::runtime_error("BadParticle"); - - bool c1=isCharged(pType1); - bool c2=isCharged(pType2); - bool l1=isLepton(pType1); - bool l2=isLepton(pType2); - - //at least one particle should be charged - if(!c1 && !c2) - throw std::runtime_error("Final state should have at least one charged particle"); - //first particle is charged, second is not - if(c1 && !c2){ - //valid cases are charged lepton + matching antineutrino for GR - if(l1){ - //!c2 => pType2 is a neutrino - if(!((pType1==Particle::ParticleType::EMinus && pType2==Particle::ParticleType::NuEBar) || - (pType1==Particle::ParticleType::EPlus && pType2==Particle::ParticleType::NuE) || - (pType1==Particle::ParticleType::MuMinus && pType2==Particle::ParticleType::NuMuBar) || - (pType1==Particle::ParticleType::MuPlus && pType2==Particle::ParticleType::NuMu) || - (pType1==Particle::ParticleType::TauMinus && pType2==Particle::ParticleType::NuTauBar) || - (pType1==Particle::ParticleType::TauPlus && pType2==Particle::ParticleType::NuTau))) - throw std::runtime_error("Final states with a charged lepton must have an anti-matching neutrino."); - return(Particle::ParticleType::NuEBar); - } - throw std::runtime_error("BadFinal"); - } - - //first particle is neutral, second is charged - if(!c1 && c2){ - if(l1 && pType2==Particle::ParticleType::Hadrons){ - //particle 1 is a neutral lepton, so it must be a neutrino - return(pType1); //the incoming neutrino type is the same as the outgoing - } - throw std::runtime_error("BadFinal"); - } - - //have two charged particles - if(c1 && c2){ - //no two charged lepton states - if(l1 && l2) - throw std::runtime_error("BadFinal"); - //lepton should be given first - if(!l1 && l2) - throw std::runtime_error("BadFinal"); - if(l1 && !l2){ //valid: charged lepton + Hadrons for CC - switch(pType1){ - case Particle::ParticleType::EMinus: return(Particle::ParticleType::NuE); - case Particle::ParticleType::EPlus: return(Particle::ParticleType::NuEBar); - case Particle::ParticleType::MuMinus: return(Particle::ParticleType::NuMu); - case Particle::ParticleType::MuPlus: return(Particle::ParticleType::NuMuBar); - case Particle::ParticleType::TauMinus: return(Particle::ParticleType::NuTau); - case Particle::ParticleType::TauPlus: return(Particle::ParticleType::NuTauBar); - default: assert(false && "This point should be unreachable"); - } - } - if(!l1 && !l2){ //valid: two hadrons (for GR) - return(Particle::ParticleType::NuEBar); - } - } - throw std::runtime_error("You must be a wizard: this point should be unreachable"); - } - - - // Particle-based exceptions: + // keeps this within scope. Shouldn't be getting some other kind of charged particle + return(p==Particle::ParticleType::EMinus || p==Particle::ParticleType::EPlus || + p==Particle::ParticleType::MuMinus || p==Particle::ParticleType::MuPlus || + p==Particle::ParticleType::TauMinus || p==Particle::ParticleType::TauPlus || + p==Particle::ParticleType::Hadrons); +} } // namespace utilities } // namespace LI diff --git a/projects/dataclasses/private/ParticleID.cxx b/projects/dataclasses/private/ParticleID.cxx new file mode 100644 index 000000000..c986daefe --- /dev/null +++ b/projects/dataclasses/private/ParticleID.cxx @@ -0,0 +1,105 @@ +#include "LeptonInjector/dataclasses/ParticleID.h" + +#include +#include +#include +#include +#include + +std::ostream& operator<<(std::ostream& os, LI::dataclasses::ParticleID const& record) { + os << "ParticleID (" << &record << ")\n"; + os << "IDSet: " << record.id_set << "\n"; + os << "MajorID: " << record.major_id << "\n"; + os << "MinorID: " << record.minor_id; + + return os; +} + +namespace LI { +namespace dataclasses { + +namespace { + std::mutex global_id_lock; + std::atomic global_last_pid_(0); + std::atomic global_minor_id_(0); + std::atomic global_major_id_(0); +} + +ParticleID::ParticleID() : id_set(false), major_id(0), minor_id(0) {}; + +ParticleID::ParticleID(uint64_t major, int32_t minor) : + id_set(true), major_id(major), minor_id(minor) {}; + +bool ParticleID::IsSet() const { + return id_set; +} + +ParticleID::operator bool() const { + return id_set; +} + +uint64_t ParticleID::GetMajorID() const { + return major_id; +} + +int32_t ParticleID::GetMinorID() const { + return minor_id; +} + +void ParticleID::SetID(uint64_t major, int32_t minor) { + id_set = true; + major_id = major; + minor_id = minor; +} + +bool ParticleID::operator<(ParticleID const & other) const { + return std::tie(id_set, major_id, minor_id) < std::tie(id_set, other.major_id, other.minor_id); +} + +bool ParticleID::operator==(ParticleID const & other) const { + return std::tie(id_set, major_id, minor_id) == std::tie(id_set, other.major_id, other.minor_id); +} + +// Adapted from https://github.com/icecube/icetray-public/blob/4436c3e10c23f95a8965c98fecccb7775a361fab/dataclasses/private/dataclasses/physics/I3Particle.cxx#L42-L93 +ParticleID ParticleID::GenerateID() { + int this_pid = getpid(); + + int32_t last_pid = global_last_pid_.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); //keep memory ops from wandering + if (this_pid != last_pid) { + std::lock_guard lg(global_id_lock); //acquire the lock + //check whether another thread already updated this + last_pid = global_last_pid_.load(std::memory_order_relaxed); + if(this_pid != last_pid){ + std::atomic_thread_fence(std::memory_order_release); + global_last_pid_.store(this_pid, std::memory_order_relaxed); + global_major_id_.store(0, std::memory_order_relaxed); // this will cause a new major ID to be generated + global_minor_id_.store(0, std::memory_order_relaxed); // reset the minor ID, too + } + } + + uint64_t old_major_id = global_major_id_.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); //keep memory ops from wandering + if(old_major_id == 0){ + std::lock_guard lg(global_id_lock); //acquire the lock + //check whether another thread already updated this + old_major_id = global_major_id_.load(std::memory_order_relaxed); + if(old_major_id == 0) { + std::hash string_hash; + std::stringstream s; + s << time(0) << this_pid< +#include +#include +#include + +std::ostream & operator<<(std::ostream & os, LI::dataclasses::ParticleType const & p) { + if (LI::dataclasses::ParticleTypeNames.find(p) != LI::dataclasses::ParticleTypeNames.end()) + os << LI::dataclasses::ParticleTypeNames.at(p); + else + os << static_cast(p); + return os; +} diff --git a/projects/dataclasses/private/pybindings/dataclasses.cxx b/projects/dataclasses/private/pybindings/dataclasses.cxx index 179a0d4c1..a5c89bd93 100644 --- a/projects/dataclasses/private/pybindings/dataclasses.cxx +++ b/projects/dataclasses/private/pybindings/dataclasses.cxx @@ -3,6 +3,8 @@ #include #include "../../public/LeptonInjector/dataclasses/Particle.h" +#include "../../public/LeptonInjector/dataclasses/ParticleID.h" +#include "../../public/LeptonInjector/dataclasses/ParticleType.h" #include "../../public/LeptonInjector/dataclasses/InteractionSignature.h" #include "../../public/LeptonInjector/dataclasses/InteractionRecord.h" #include "../../public/LeptonInjector/dataclasses/InteractionTree.h" @@ -10,8 +12,6 @@ #include #include - - using namespace pybind11; PYBIND11_MODULE(dataclasses,m) { @@ -20,192 +20,23 @@ PYBIND11_MODULE(dataclasses,m) { class_> particle(m, "Particle"); particle.def(init<>()) - .def(init()) + .def(init()) + .def(init, std::array, double, double>()) + .def(init, std::array, double, double>()) + .def("__str__", [](Particle const & p) { std::stringstream ss; ss << p; return ss.str(); }) + .def_readwrite("id",&Particle::id) .def_readwrite("type",&Particle::type) - .def_readwrite("energy",&Particle::energy) - .def("GetMass",&Particle::GetMass) - .def("HasMass",&Particle::HasMass) - .def("GetTypeString",&Particle::GetTypeString); - - enum_(particle, "ParticleType") - .value("unknown", Particle::ParticleType::unknown) - .value("Gamma", Particle::ParticleType::Gamma) - .value("EPlus", Particle::ParticleType::EPlus) - .value("EMinus", Particle::ParticleType::EMinus) - .value("MuPlus", Particle::ParticleType::MuPlus) - .value("MuMinus", Particle::ParticleType::MuMinus) - .value("Pi0", Particle::ParticleType::Pi0) - .value("PiPlus", Particle::ParticleType::PiPlus) - .value("PiMinus", Particle::ParticleType::PiMinus) - .value("K0_Long", Particle::ParticleType::K0_Long) - .value("KPlus", Particle::ParticleType::KPlus) - .value("KMinus", Particle::ParticleType::KMinus) - .value("Neutron", Particle::ParticleType::Neutron) - .value("PPlus", Particle::ParticleType::PPlus) - .value("PMinus", Particle::ParticleType::PMinus) - .value("K0_Short", Particle::ParticleType::K0_Short) - .value("Eta", Particle::ParticleType::Eta) - .value("Lambda", Particle::ParticleType::Lambda) - .value("SigmaPlus", Particle::ParticleType::SigmaPlus) - .value("Sigma0", Particle::ParticleType::Sigma0) - .value("SigmaMinus", Particle::ParticleType::SigmaMinus) - .value("Xi0", Particle::ParticleType::Xi0) - .value("XiMinus", Particle::ParticleType::XiMinus) - .value("OmegaMinus", Particle::ParticleType::OmegaMinus) - .value("NeutronBar", Particle::ParticleType::NeutronBar) - .value("LambdaBar", Particle::ParticleType::LambdaBar) - .value("SigmaMinusBar", Particle::ParticleType::SigmaMinusBar) - .value("Sigma0Bar", Particle::ParticleType::Sigma0Bar) - .value("SigmaPlusBar", Particle::ParticleType::SigmaPlusBar) - .value("Xi0Bar", Particle::ParticleType::Xi0Bar) - .value("XiPlusBar", Particle::ParticleType::XiPlusBar) - .value("OmegaPlusBar", Particle::ParticleType::OmegaPlusBar) - .value("DPlus", Particle::ParticleType::DPlus) - .value("DMinus", Particle::ParticleType::DMinus) - .value("D0", Particle::ParticleType::D0) - .value("D0Bar", Particle::ParticleType::D0Bar) - .value("DsPlus", Particle::ParticleType::DsPlus) - .value("DsMinusBar", Particle::ParticleType::DsMinusBar) - .value("LambdacPlus", Particle::ParticleType::LambdacPlus) - .value("WPlus", Particle::ParticleType::WPlus) - .value("WMinus", Particle::ParticleType::WMinus) - .value("Z0", Particle::ParticleType::Z0) - .value("NuE", Particle::ParticleType::NuE) - .value("NuEBar", Particle::ParticleType::NuEBar) - .value("NuMu", Particle::ParticleType::NuMu) - .value("NuMuBar", Particle::ParticleType::NuMuBar) - .value("TauPlus", Particle::ParticleType::TauPlus) - .value("TauMinus", Particle::ParticleType::TauMinus) - .value("NuTau", Particle::ParticleType::NuTau) - .value("NuTauBar", Particle::ParticleType::NuTauBar) - .value("HNucleus", Particle::ParticleType::HNucleus) - .value("H2Nucleus", Particle::ParticleType::H2Nucleus) - .value("He3Nucleus", Particle::ParticleType::He3Nucleus) - .value("He4Nucleus", Particle::ParticleType::He4Nucleus) - .value("Li6Nucleus", Particle::ParticleType::Li6Nucleus) - .value("Li7Nucleus", Particle::ParticleType::Li7Nucleus) - .value("Be9Nucleus", Particle::ParticleType::Be9Nucleus) - .value("B10Nucleus", Particle::ParticleType::B10Nucleus) - .value("B11Nucleus", Particle::ParticleType::B11Nucleus) - .value("C12Nucleus", Particle::ParticleType::C12Nucleus) - .value("C13Nucleus", Particle::ParticleType::C13Nucleus) - .value("N14Nucleus", Particle::ParticleType::N14Nucleus) - .value("N15Nucleus", Particle::ParticleType::N15Nucleus) - .value("O16Nucleus", Particle::ParticleType::O16Nucleus) - .value("O17Nucleus", Particle::ParticleType::O17Nucleus) - .value("O18Nucleus", Particle::ParticleType::O18Nucleus) - .value("F19Nucleus", Particle::ParticleType::F19Nucleus) - .value("Ne20Nucleus", Particle::ParticleType::Ne20Nucleus) - .value("Ne21Nucleus", Particle::ParticleType::Ne21Nucleus) - .value("Ne22Nucleus", Particle::ParticleType::Ne22Nucleus) - .value("Na23Nucleus", Particle::ParticleType::Na23Nucleus) - .value("Mg24Nucleus", Particle::ParticleType::Mg24Nucleus) - .value("Mg25Nucleus", Particle::ParticleType::Mg25Nucleus) - .value("Mg26Nucleus", Particle::ParticleType::Mg26Nucleus) - .value("Al26Nucleus", Particle::ParticleType::Al26Nucleus) - .value("Al27Nucleus", Particle::ParticleType::Al27Nucleus) - .value("Si28Nucleus", Particle::ParticleType::Si28Nucleus) - .value("Si29Nucleus", Particle::ParticleType::Si29Nucleus) - .value("Si30Nucleus", Particle::ParticleType::Si30Nucleus) - .value("Si31Nucleus", Particle::ParticleType::Si31Nucleus) - .value("Si32Nucleus", Particle::ParticleType::Si32Nucleus) - .value("P31Nucleus", Particle::ParticleType::P31Nucleus) - .value("P32Nucleus", Particle::ParticleType::P32Nucleus) - .value("P33Nucleus", Particle::ParticleType::P33Nucleus) - .value("S32Nucleus", Particle::ParticleType::S32Nucleus) - .value("S33Nucleus", Particle::ParticleType::S33Nucleus) - .value("S34Nucleus", Particle::ParticleType::S34Nucleus) - .value("S35Nucleus", Particle::ParticleType::S35Nucleus) - .value("S36Nucleus", Particle::ParticleType::S36Nucleus) - .value("Cl35Nucleus", Particle::ParticleType::Cl35Nucleus) - .value("Cl36Nucleus", Particle::ParticleType::Cl36Nucleus) - .value("Cl37Nucleus", Particle::ParticleType::Cl37Nucleus) - .value("Ar36Nucleus", Particle::ParticleType::Ar36Nucleus) - .value("Ar37Nucleus", Particle::ParticleType::Ar37Nucleus) - .value("Ar38Nucleus", Particle::ParticleType::Ar38Nucleus) - .value("Ar39Nucleus", Particle::ParticleType::Ar39Nucleus) - .value("Ar40Nucleus", Particle::ParticleType::Ar40Nucleus) - .value("Ar41Nucleus", Particle::ParticleType::Ar41Nucleus) - .value("Ar42Nucleus", Particle::ParticleType::Ar42Nucleus) - .value("K39Nucleus", Particle::ParticleType::K39Nucleus) - .value("K40Nucleus", Particle::ParticleType::K40Nucleus) - .value("K41Nucleus", Particle::ParticleType::K41Nucleus) - .value("Ca40Nucleus", Particle::ParticleType::Ca40Nucleus) - .value("Ca41Nucleus", Particle::ParticleType::Ca41Nucleus) - .value("Ca42Nucleus", Particle::ParticleType::Ca42Nucleus) - .value("Ca43Nucleus", Particle::ParticleType::Ca43Nucleus) - .value("Ca44Nucleus", Particle::ParticleType::Ca44Nucleus) - .value("Ca45Nucleus", Particle::ParticleType::Ca45Nucleus) - .value("Ca46Nucleus", Particle::ParticleType::Ca46Nucleus) - .value("Ca47Nucleus", Particle::ParticleType::Ca47Nucleus) - .value("Ca48Nucleus", Particle::ParticleType::Ca48Nucleus) - .value("Sc44Nucleus", Particle::ParticleType::Sc44Nucleus) - .value("Sc45Nucleus", Particle::ParticleType::Sc45Nucleus) - .value("Sc46Nucleus", Particle::ParticleType::Sc46Nucleus) - .value("Sc47Nucleus", Particle::ParticleType::Sc47Nucleus) - .value("Sc48Nucleus", Particle::ParticleType::Sc48Nucleus) - .value("Ti44Nucleus", Particle::ParticleType::Ti44Nucleus) - .value("Ti45Nucleus", Particle::ParticleType::Ti45Nucleus) - .value("Ti46Nucleus", Particle::ParticleType::Ti46Nucleus) - .value("Ti47Nucleus", Particle::ParticleType::Ti47Nucleus) - .value("Ti48Nucleus", Particle::ParticleType::Ti48Nucleus) - .value("Ti49Nucleus", Particle::ParticleType::Ti49Nucleus) - .value("Ti50Nucleus", Particle::ParticleType::Ti50Nucleus) - .value("V48Nucleus", Particle::ParticleType::V48Nucleus) - .value("V49Nucleus", Particle::ParticleType::V49Nucleus) - .value("V50Nucleus", Particle::ParticleType::V50Nucleus) - .value("V51Nucleus", Particle::ParticleType::V51Nucleus) - .value("Cr50Nucleus", Particle::ParticleType::Cr50Nucleus) - .value("Cr51Nucleus", Particle::ParticleType::Cr51Nucleus) - .value("Cr52Nucleus", Particle::ParticleType::Cr52Nucleus) - .value("Cr53Nucleus", Particle::ParticleType::Cr53Nucleus) - .value("Cr54Nucleus", Particle::ParticleType::Cr54Nucleus) - .value("Mn52Nucleus", Particle::ParticleType::Mn52Nucleus) - .value("Mn53Nucleus", Particle::ParticleType::Mn53Nucleus) - .value("Mn54Nucleus", Particle::ParticleType::Mn54Nucleus) - .value("Mn55Nucleus", Particle::ParticleType::Mn55Nucleus) - .value("Fe54Nucleus", Particle::ParticleType::Fe54Nucleus) - .value("Fe55Nucleus", Particle::ParticleType::Fe55Nucleus) - .value("Fe56Nucleus", Particle::ParticleType::Fe56Nucleus) - .value("Fe57Nucleus", Particle::ParticleType::Fe57Nucleus) - .value("Fe58Nucleus", Particle::ParticleType::Fe58Nucleus) - .value("Cu63Nucleus", Particle::ParticleType::Cu63Nucleus) - .value("Cu65Nucleus", Particle::ParticleType::Cu65Nucleus) - .value("W183Nucleus", Particle::ParticleType::W183Nucleus) - .value("Pb208Nucleus", Particle::ParticleType::Pb208Nucleus) - .value("Qball", Particle::ParticleType::Qball) - .value("NuLight",Particle::ParticleType::NuLight) - .value("Nu1",Particle::ParticleType::Nu1) - .value("Nu2",Particle::ParticleType::Nu2) - .value("Nu3",Particle::ParticleType::Nu3) - .value("N4",Particle::ParticleType::N4) - .value("N5",Particle::ParticleType::N5) - .value("N6",Particle::ParticleType::N6) - .value("ZPrime",Particle::ParticleType::ZPrime) - .value("HPrime",Particle::ParticleType::HPrime) - .value("PhiPrime",Particle::ParticleType::PhiPrime) - .value("ALP",Particle::ParticleType::ALP) - .value("NuF4", Particle::ParticleType::NuF4) - .value("NuF4Bar", Particle::ParticleType::NuF4Bar) - .value("Nucleon", Particle::ParticleType::Nucleon) - .value("CherenkovPhoton", Particle::ParticleType::CherenkovPhoton) - .value("Nu", Particle::ParticleType::Nu) - .value("Monopole", Particle::ParticleType::Monopole) - .value("Brems", Particle::ParticleType::Brems) - .value("DeltaE", Particle::ParticleType::DeltaE) - .value("PairProd", Particle::ParticleType::PairProd) - .value("NuclInt", Particle::ParticleType::NuclInt) - .value("MuPair", Particle::ParticleType::MuPair) - .value("Hadrons", Particle::ParticleType::Hadrons) - .value("Decay", Particle::ParticleType::Decay) - .value("ContinuousEnergyLoss", Particle::ParticleType::ContinuousEnergyLoss) - .value("FiberLaser", Particle::ParticleType::FiberLaser) - .value("N2Laser", Particle::ParticleType::N2Laser) - .value("YAGLaser", Particle::ParticleType::YAGLaser) - .value("STauPlus", Particle::ParticleType::STauPlus) - .value("STauMinus", Particle::ParticleType::STauMinus) - .value("SMPPlus", Particle::ParticleType::SMPPlus) - .value("SMPMinus", Particle::ParticleType::SMPMinus) + .def_readwrite("mass",&Particle::mass) + .def_readwrite("momentum",&Particle::momentum) + .def_readwrite("position",&Particle::position) + .def_readwrite("length",&Particle::length) + .def_readwrite("helicity",&Particle::helicity) + .def("GenerateID",&Particle::GenerateID); + + enum_(particle, "ParticleType", arithmetic()) +#define X(a, b) .value( #a , ParticleType:: a ) +#include "../../public/LeptonInjector/dataclasses/ParticleTypes.def" +#undef X .export_values(); class_>(m, "InteractionSignature") @@ -214,19 +45,94 @@ PYBIND11_MODULE(dataclasses,m) { .def_readwrite("target_type",&InteractionSignature::target_type) .def_readwrite("secondary_types",&InteractionSignature::secondary_types); + class_>(m, "PrimaryDistributionRecord") + .def(init()) + .def_property_readonly("id", + [](LI::dataclasses::PrimaryDistributionRecord const & pdr) {LI::dataclasses::ParticleID id = pdr.id; return id;}) + .def_property_readonly("type", + [](LI::dataclasses::PrimaryDistributionRecord const & pdr) {LI::dataclasses::ParticleType pt = pdr.type; return pt;}) + .def("GetParticle", &PrimaryDistributionRecord::GetParticle) + .def("SetParticle", &PrimaryDistributionRecord::SetParticle) + .def_property("mass", ((double const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetMass)), &PrimaryDistributionRecord::SetMass) + .def_property("energy", ((double const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetEnergy)), &PrimaryDistributionRecord::SetEnergy) + .def_property("kinetic_energy", ((double const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetKineticEnergy)), &PrimaryDistributionRecord::SetKineticEnergy) + .def_property("direction", ((std::array const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetDirection)), &PrimaryDistributionRecord::SetDirection) + .def_property("three_momentum", ((std::array const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetThreeMomentum)), &PrimaryDistributionRecord::SetThreeMomentum) + .def_property("four_momentum", ((std::array (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetFourMomentum)), &PrimaryDistributionRecord::SetFourMomentum) + .def_property("length", ((double const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetLength)), &PrimaryDistributionRecord::SetLength) + .def_property("initial_position", ((std::array const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetInitialPosition)), &PrimaryDistributionRecord::SetInitialPosition) + .def_property("interaction_vertex", ((std::array const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetInteractionVertex)), &PrimaryDistributionRecord::SetInteractionVertex) + .def_property("helicity", ((double const & (PrimaryDistributionRecord::*)())(&PrimaryDistributionRecord::GetHelicity)), &PrimaryDistributionRecord::SetHelicity) + .def("Finalize", &PrimaryDistributionRecord::Finalize); + + class_>(m, "SecondaryParticleRecord") + .def(init()) + .def_property_readonly("id", + [](LI::dataclasses::SecondaryParticleRecord const & spr) {LI::dataclasses::ParticleID id = spr.id; return id;}) + .def_property_readonly("type", + [](LI::dataclasses::SecondaryParticleRecord const & spr) {LI::dataclasses::ParticleType pt = spr.type; return pt;}) + .def_property_readonly("initial_position", + [](LI::dataclasses::SecondaryParticleRecord const & spr) {std::array ip = spr.initial_position; return ip;}) + .def("GetParticle", &SecondaryParticleRecord::GetParticle) + .def("SetParticle", &SecondaryParticleRecord::SetParticle) + .def_property("mass", ((double const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetMass)), &SecondaryParticleRecord::SetMass) + .def_property("energy", ((double const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetEnergy)), &SecondaryParticleRecord::SetEnergy) + .def_property("kinetic_energy", ((double const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetKineticEnergy)), &SecondaryParticleRecord::SetKineticEnergy) + .def_property("direction", ((std::array const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetDirection)), &SecondaryParticleRecord::SetDirection) + .def_property("three_momentum", ((std::array const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetThreeMomentum)), &SecondaryParticleRecord::SetThreeMomentum) + .def_property("four_momentum", ((std::array (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetFourMomentum)), &SecondaryParticleRecord::SetFourMomentum) + .def_property("helicity", ((double const & (SecondaryParticleRecord::*)())(&SecondaryParticleRecord::GetHelicity)), &SecondaryParticleRecord::SetHelicity) + .def("Finalize", &SecondaryParticleRecord::Finalize); + + class_>(m, "CrossSectionDistributionRecord") + .def(init()) + .def_property_readonly("record", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::InteractionRecord ir = cdr.record; return ir;}) + .def_property_readonly("signature", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::InteractionSignature is = cdr.signature; return is;}) + .def_property_readonly("primary_id", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::ParticleID id = cdr.primary_id; return id;}) + .def_property_readonly("primary_type", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::ParticleType pt = cdr.primary_type; return pt;}) + .def_property_readonly("primary_initial_position", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {std::array ip = cdr.primary_initial_position; return ip;}) + .def_property_readonly("primary_mass", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {double m = cdr.primary_mass; return m;}) + .def_property_readonly("primary_momentum", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {std::array p = cdr.primary_momentum; return p;}) + .def_property_readonly("primary_helicity", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {double h = cdr.primary_helicity; return h;}) + .def_property_readonly("interaction_vertex", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {std::array iv = cdr.interaction_vertex; return iv;}) + .def_property_readonly("target_id", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::ParticleID id = cdr.target_id; return id;}) + .def_property_readonly("target_type", + [](LI::dataclasses::CrossSectionDistributionRecord const & cdr) {LI::dataclasses::ParticleType pt = cdr.target_type; return pt;}) + .def_property("target_mass", ((double const & (LI::dataclasses::CrossSectionDistributionRecord::*)() const)(&LI::dataclasses::CrossSectionDistributionRecord::GetTargetMass)), &LI::dataclasses::CrossSectionDistributionRecord::SetTargetMass) + .def_property("target_helicity", ((double const & (LI::dataclasses::CrossSectionDistributionRecord::*)() const)(&LI::dataclasses::CrossSectionDistributionRecord::GetTargetHelicity)), &LI::dataclasses::CrossSectionDistributionRecord::SetTargetHelicity) + .def_property("interaction_parameters", ((std::map const & (LI::dataclasses::CrossSectionDistributionRecord::*)())(&LI::dataclasses::CrossSectionDistributionRecord::GetInteractionParameters)), &LI::dataclasses::CrossSectionDistributionRecord::SetInteractionParameters) + .def("GetSecondaryParticleRecord", + [](LI::dataclasses::CrossSectionDistributionRecord & cdr, size_t i) -> LI::dataclasses::SecondaryParticleRecord & {return cdr.GetSecondaryParticleRecord(i);}, + return_value_policy::reference_internal) + .def("GetSecondaryParticleRecords", + [](LI::dataclasses::CrossSectionDistributionRecord & cdr) -> std::vector & {return cdr.GetSecondaryParticleRecords();}, + return_value_policy::reference_internal) + .def("Finalize", &CrossSectionDistributionRecord::Finalize); + + class_>(m, "InteractionRecord") .def(init<>()) + .def("__str__", [](InteractionRecord const & r) { std::stringstream ss; ss << r; return ss.str(); }) .def_readwrite("signature",&InteractionRecord::signature) .def_readwrite("primary_mass",&InteractionRecord::primary_mass) .def_readwrite("primary_momentum",&InteractionRecord::primary_momentum) .def_readwrite("primary_helicity",&InteractionRecord::primary_helicity) .def_readwrite("target_mass",&InteractionRecord::target_mass) - .def_readwrite("target_momentum",&InteractionRecord::target_momentum) .def_readwrite("target_helicity",&InteractionRecord::target_helicity) .def_readwrite("interaction_vertex",&InteractionRecord::interaction_vertex) .def_readwrite("secondary_masses",&InteractionRecord::secondary_masses) .def_readwrite("secondary_momenta",&InteractionRecord::secondary_momenta) - .def_readwrite("secondary_helicity",&InteractionRecord::secondary_helicity) + .def_readwrite("secondary_helicities",&InteractionRecord::secondary_helicities) .def_readwrite("interaction_parameters",&InteractionRecord::interaction_parameters); class_>(m, "InteractionTreeDatum") diff --git a/projects/dataclasses/private/test/InteractionRecord_TEST.cxx b/projects/dataclasses/private/test/InteractionRecord_TEST.cxx new file mode 100644 index 000000000..5f3dfdf29 --- /dev/null +++ b/projects/dataclasses/private/test/InteractionRecord_TEST.cxx @@ -0,0 +1,352 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionSignature.h" +#include "LeptonInjector/dataclasses/InteractionRecord.h" + +using namespace LI::dataclasses; + +std::mt19937 rng_; +std::uniform_real_distribution uniform_distribution(0.0, 1.0); + +double RandomDouble() { + return uniform_distribution(rng_); +} + +TEST(Comparison, Comparison_equal) +{ + InteractionRecord A; + InteractionRecord B; + EXPECT_TRUE(A == B); + + A.signature.primary_type = Particle::ParticleType::EMinus; + EXPECT_FALSE(A == B); + B.signature.primary_type = Particle::ParticleType::EMinus; + EXPECT_TRUE(A == B); + + A.signature.target_type = Particle::ParticleType::PPlus; + EXPECT_FALSE(A == B); + B.signature.target_type = Particle::ParticleType::PPlus; + EXPECT_TRUE(A == B); + + A.signature.secondary_types.push_back(Particle::ParticleType::EMinus); + EXPECT_FALSE(A == B); + B.signature.secondary_types.push_back(Particle::ParticleType::EMinus); + EXPECT_TRUE(A == B); + + A.primary_id = ParticleID(1, 1); + EXPECT_FALSE(A == B); + B.primary_id = ParticleID(1, 1); + EXPECT_TRUE(A == B); + + A.primary_initial_position = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A == B); + B.primary_initial_position = {1.0, 2.0, 3.0}; + EXPECT_TRUE(A == B); + + A.primary_mass = 1.0; + EXPECT_FALSE(A == B); + B.primary_mass = 1.0; + EXPECT_TRUE(A == B); + + A.primary_momentum = {1.0, 2.0, 3.0, 4.0}; + EXPECT_FALSE(A == B); + B.primary_momentum = {1.0, 2.0, 3.0, 4.0}; + EXPECT_TRUE(A == B); + + A.primary_helicity = 1.0; + EXPECT_FALSE(A == B); + B.primary_helicity = 1.0; + EXPECT_TRUE(A == B); + + A.target_mass = 1.0; + EXPECT_FALSE(A == B); + B.target_mass = 1.0; + EXPECT_TRUE(A == B); + + A.target_helicity = 1.0; + EXPECT_FALSE(A == B); + B.target_helicity = 1.0; + EXPECT_TRUE(A == B); + + A.interaction_vertex = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A == B); + B.interaction_vertex = {1.0, 2.0, 3.0}; + EXPECT_TRUE(A == B); + + A.secondary_masses.push_back(1.0); + EXPECT_FALSE(A == B); + B.secondary_masses.push_back(1.0); + EXPECT_TRUE(A == B); + + A.secondary_momenta.push_back({1.0, 2.0, 3.0, 4.0}); + EXPECT_FALSE(A == B); + B.secondary_momenta.push_back({1.0, 2.0, 3.0, 4.0}); + EXPECT_TRUE(A == B); + + A.secondary_helicities.push_back(1.0); + EXPECT_FALSE(A == B); + B.secondary_helicities.push_back(1.0); + EXPECT_TRUE(A == B); + + A.interaction_parameters["test"] = 1.0; + EXPECT_FALSE(A == B); + B.interaction_parameters["test"] = 1.0; + EXPECT_TRUE(A == B); + + A.interaction_parameters["test"] = 2.0; + EXPECT_FALSE(A == B); + B.interaction_parameters["test"] = 2.0; + EXPECT_TRUE(A == B); + +} + +TEST(Comparison, LessThan) +{ + InteractionRecord A; + InteractionRecord B; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.signature.primary_type = Particle::ParticleType::EMinus; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.signature.primary_type = Particle::ParticleType::EMinus; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.signature.target_type = Particle::ParticleType::PPlus; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.signature.target_type = Particle::ParticleType::PPlus; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.signature.secondary_types.push_back(Particle::ParticleType::EMinus); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.signature.secondary_types.push_back(Particle::ParticleType::EMinus); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_id = ParticleID(1, 1); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.primary_id = ParticleID(1, 1); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_initial_position = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.primary_initial_position = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_mass = 1.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.primary_mass = 1.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_momentum = {1.0, 2.0, 3.0, 4.0}; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.primary_momentum = {1.0, 2.0, 3.0, 4.0}; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_helicity = 1.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.primary_helicity = 1.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.target_mass = 1.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.target_mass = 1.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.target_helicity = 1.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.target_helicity = 1.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.interaction_vertex = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.interaction_vertex = {1.0, 2.0, 3.0}; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.secondary_masses.push_back(1.0); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.secondary_masses.push_back(1.0); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.secondary_momenta.push_back({1.0, 2.0, 3.0, 4.0}); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.secondary_momenta.push_back({1.0, 2.0, 3.0, 4.0}); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.secondary_helicities.push_back(1.0); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.secondary_helicities.push_back(1.0); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.interaction_parameters["test"] = 1.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.interaction_parameters["test"] = 1.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.interaction_parameters["test"] = 2.0; + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.interaction_parameters["test"] = 2.0; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); +} + +TEST(Serialization, Save) +{ + InteractionRecord record; + record.signature.primary_type = Particle::ParticleType::EMinus; + record.signature.target_type = Particle::ParticleType::PPlus; + record.signature.secondary_types.push_back(Particle::ParticleType::EMinus); + record.primary_id = ParticleID(1, 1); + record.primary_initial_position = {1.0, 2.0, 3.0}; + record.primary_mass = 1.0; + record.primary_momentum = {1.0, 2.0, 3.0, 4.0}; + record.primary_helicity = 1.0; + record.target_mass = 1.0; + record.target_helicity = 1.0; + + record.interaction_vertex = {1.0, 2.0, 3.0}; + record.secondary_masses.push_back(1.0); + record.secondary_momenta.push_back({1.0, 2.0, 3.0, 4.0}); + record.secondary_helicities.push_back(1.0); + record.interaction_parameters["test"] = 1.0; + + std::stringstream ss; + { + cereal::JSONOutputArchive oarchive(ss); + oarchive(record); + } + + std::string expected = "{\n\ + \"value0\": {\n\ + \"cereal_class_version\": 0,\n\ + \"InteractionSignature\": {\n\ + \"cereal_class_version\": 0,\n\ + \"PrimaryType\": 11,\n\ + \"TargetType\": 2212,\n\ + \"SecondaryTypes\": [\n\ + 11\n\ + ]\n\ + },\n\ + \"PrimaryID\": {\n\ + \"cereal_class_version\": 0,\n\ + \"IDSet\": true,\n\ + \"MajorID\": 1,\n\ + \"MinorID\": 1\n\ + },\n\ + \"PrimaryInitialPosition\": [\n\ + 1.0,\n\ + 2.0,\n\ + 3.0\n\ + ],\n\ + \"PrimaryMass\": 1.0,\n\ + \"PrimaryMomentum\": [\n\ + 1.0,\n\ + 2.0,\n\ + 3.0,\n\ + 4.0\n\ + ],\n\ + \"PrimaryHelicity\": 1.0,\n\ + \"TargetID\": {\n\ + \"IDSet\": false,\n\ + \"MajorID\": 0,\n\ + \"MinorID\": 0\n\ + },\n\ + \"TargetMass\": 1.0,\n\ + \"TargetHelicity\": 1.0,\n\ + \"InteractionVertex\": [\n\ + 1.0,\n\ + 2.0,\n\ + 3.0\n\ + ],\n\ + \"SecondaryIDs\": [],\n\ + \"SecondaryMasses\": [\n\ + 1.0\n\ + ],\n\ + \"SecondaryMomenta\": [\n\ + [\n\ + 1.0,\n\ + 2.0,\n\ + 3.0,\n\ + 4.0\n\ + ]\n\ + ],\n\ + \"SecondaryHelicities\": [\n\ + 1.0\n\ + ],\n\ + \"InteractionParameters\": [\n\ + {\n\ + \"key\": \"test\",\n\ + \"value\": 1.0\n\ + }\n\ + ]\n\ + }\n\ +}"; + + EXPECT_EQ(ss.str(), expected); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/projects/dataclasses/private/test/InteractionSignature_TEST.cxx b/projects/dataclasses/private/test/InteractionSignature_TEST.cxx new file mode 100644 index 000000000..926bb6750 --- /dev/null +++ b/projects/dataclasses/private/test/InteractionSignature_TEST.cxx @@ -0,0 +1,163 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionSignature.h" + +using namespace LI::dataclasses; + +std::mt19937 rng_; +std::uniform_real_distribution uniform_distribution(0.0, 1.0); + +double RandomDouble() { + return uniform_distribution(rng_); +} + +TEST(Comparison, Comparison_equal) +{ + InteractionSignature A; + InteractionSignature B; + EXPECT_TRUE(A == B); + + A.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_FALSE(A == B); + B.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_TRUE(A == B); + + A.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_FALSE(A == B); + B.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_TRUE(A == B); + + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_FALSE(A == B); + B.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_TRUE(A == B); + + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + EXPECT_FALSE(A == B); + B.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + EXPECT_TRUE(A == B); + + std::swap(A.secondary_types[0], A.secondary_types[1]); + EXPECT_FALSE(A == B); + std::swap(A.secondary_types[0], A.secondary_types[1]); + EXPECT_TRUE(A == B); +} + +TEST(Comparison, LessThan) +{ + InteractionSignature A; + InteractionSignature B; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_TRUE(A < B); + EXPECT_FALSE(B < A); + + B.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_TRUE(A < B); + EXPECT_FALSE(B < A); + + B.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + // + InteractionSignature C; + InteractionSignature D; + EXPECT_FALSE(C < D); + EXPECT_FALSE(D < C); + + C.primary_type = LI::dataclasses::Particle::ParticleType::EMinus; + EXPECT_FALSE(C < D); + EXPECT_TRUE(D < C); + + D.primary_type = LI::dataclasses::Particle::ParticleType::EMinus; + EXPECT_FALSE(C < D); + EXPECT_FALSE(D < C); + + C.target_type = LI::dataclasses::Particle::ParticleType::EMinus; + EXPECT_FALSE(C < D); + EXPECT_TRUE(D < C); + + D.target_type = LI::dataclasses::Particle::ParticleType::EMinus; + EXPECT_FALSE(C < D); + EXPECT_FALSE(D < C); + // + + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + B.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); + + std::swap(A.secondary_types[0], A.secondary_types[1]); + EXPECT_FALSE(A < B); + EXPECT_TRUE(B < A); + + std::swap(A.secondary_types[0], A.secondary_types[1]); + EXPECT_FALSE(A < B); + EXPECT_FALSE(B < A); +} + +TEST(Serialization, Save) +{ + InteractionSignature A; + A.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + A.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + A.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + std::stringstream ss; + { + cereal::JSONOutputArchive oarchive(ss); + oarchive(cereal::make_nvp("InteractionSignature", A)); + } + + std::string expected = "{\n\ + \"InteractionSignature\": {\n\ + \"cereal_class_version\": 0,\n\ + \"PrimaryType\": -11,\n\ + \"TargetType\": -11,\n\ + \"SecondaryTypes\": [\n\ + -11,\n\ + 11\n\ + ]\n\ + }\n\ +}"; + EXPECT_EQ(ss.str(), expected); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/projects/dataclasses/private/test/InteractionTree_TEST.cxx b/projects/dataclasses/private/test/InteractionTree_TEST.cxx new file mode 100644 index 000000000..a0caa5070 --- /dev/null +++ b/projects/dataclasses/private/test/InteractionTree_TEST.cxx @@ -0,0 +1,169 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionTree.h" + +using namespace LI::dataclasses; + +std::mt19937 rng_; +std::uniform_real_distribution uniform_distribution(0.0, 1.0); + +double RandomDouble() { + return uniform_distribution(rng_); +} + +int InteractionTreeDatum::depth() const { + int depth = 0; + if(parent==NULL) return depth; + std::shared_ptr test = std::make_shared(*parent); + while(true) { + ++depth; + if(test->parent==NULL) return depth; + test = std::make_shared(*(test->parent)); + } + return -1; +} + +std::shared_ptr InteractionTree::add_entry(std::shared_ptr datum, + std::shared_ptr parent) { + if (parent) { + datum->parent = parent; + parent->daughters.push_back(datum); + } + tree.insert(datum); + return datum; +} + +std::shared_ptr InteractionTree::add_entry(InteractionTreeDatum& datum, + std::shared_ptr parent) { + std::shared_ptr _datum = std::make_shared(datum); + if (parent) { + _datum->parent = parent; + parent->daughters.push_back(_datum); + } + tree.insert(_datum); + return _datum; +} + +std::shared_ptr InteractionTree::add_entry(InteractionRecord& record, + std::shared_ptr parent) { + std::shared_ptr datum = std::make_shared(record); + if (parent) { + datum->parent = parent; + parent->daughters.push_back(datum); + } + tree.insert(datum); + return datum; +} + +TEST(DatumConstructor, InteractionRecord) +{ + InteractionRecord record; + record.signature.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + InteractionTreeDatum datum(record); + EXPECT_EQ(datum.record.signature.primary_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum.record.signature.target_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum.record.signature.secondary_types[0], LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum.record.signature.secondary_types[1], LI::dataclasses::Particle::ParticleType::EMinus); +} + +TEST(TreeConstructor, Default) +{ + InteractionTree tree; + EXPECT_EQ(tree.tree.size(), 0); +} + +TEST(TreeAddEntry, Record) +{ + InteractionTree tree; + InteractionRecord record; + record.signature.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + std::shared_ptr datum = tree.add_entry(record); + EXPECT_EQ(tree.tree.size(), 1); + EXPECT_EQ(datum->record.signature.primary_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum->record.signature.target_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum->record.signature.secondary_types[0], LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum->record.signature.secondary_types[1], LI::dataclasses::Particle::ParticleType::EMinus); +} + +TEST(TreeAddEntry, DatumReference) +{ + InteractionTree tree; + InteractionRecord record; + record.signature.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + InteractionTreeDatum datum = InteractionTreeDatum(record); + std::shared_ptr datum2 = tree.add_entry(datum); + EXPECT_EQ(tree.tree.size(), 1); + EXPECT_EQ(datum2->record.signature.primary_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.target_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[0], LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[1], LI::dataclasses::Particle::ParticleType::EMinus); +} + +TEST(TreeAddEntry, DatumPointer) +{ + InteractionTree tree; + InteractionRecord record; + record.signature.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + std::shared_ptr datum = std::make_shared(record); + std::shared_ptr datum2 = tree.add_entry(datum); + EXPECT_EQ(tree.tree.size(), 1); + EXPECT_EQ(datum2->record.signature.primary_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.target_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[0], LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[1], LI::dataclasses::Particle::ParticleType::EMinus); +} + +TEST(TreeAddEntry, Parent) +{ + InteractionTree tree; + InteractionRecord record; + record.signature.primary_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.target_type = LI::dataclasses::Particle::ParticleType::EPlus; + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EPlus); + record.signature.secondary_types.push_back(LI::dataclasses::Particle::ParticleType::EMinus); + + auto datum = tree.add_entry(record); + auto datum2 = tree.add_entry(record, datum); + EXPECT_EQ(tree.tree.size(), 2); + EXPECT_EQ(datum2->record.signature.primary_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.target_type, LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[0], LI::dataclasses::Particle::ParticleType::EPlus); + EXPECT_EQ(datum2->record.signature.secondary_types[1], LI::dataclasses::Particle::ParticleType::EMinus); + EXPECT_EQ(datum2->parent, datum); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/DecayRecord.h b/projects/dataclasses/public/LeptonInjector/dataclasses/DecayRecord.h deleted file mode 100644 index 8672300f9..000000000 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/DecayRecord.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef LI_DecayRecord_H -#define LI_DecayRecord_H - -#include // for array -#include // for vector -#include // for uint32_t -#include // for ostream -#include // for runtime_error - -#include -#include -#include -#include -#include -#include -#include - -#include "LeptonInjector/dataclasses/DecaySignature.h" - -namespace LI { -namespace dataclasses { - -struct DecayRecord { - DecaySignature signature; - double primary_mass; - std::array primary_momentum; - double primary_helicity; - std::array decay_vertex = {0, 0, 0}; - std::vector secondary_masses; - std::vector> secondary_momenta; - std::vector secondary_helicity; - std::vector decay_parameters; - bool operator==(DecayRecord const & other) const; - friend std::ostream& operator<<(std::ostream& os, DecayRecord const& record); - template - void serialize(Archive & archive, std::uint32_t const version) { - if(version == 0) { - archive(::cereal::make_nvp("DecaySignature", signature)); - archive(::cereal::make_nvp("PrimaryMass", primary_mass)); - archive(::cereal::make_nvp("PrimaryMomentum", primary_momentum)); - archive(::cereal::make_nvp("PrimaryHelicity", primary_helicity)); - archive(::cereal::make_nvp("DecayVertex", decay_vertex)); - archive(::cereal::make_nvp("SecondaryMasses", secondary_masses)); - archive(::cereal::make_nvp("SecondaryMomenta", secondary_momenta)); - archive(::cereal::make_nvp("SecondaryHelicity", secondary_helicity)); - archive(::cereal::make_nvp("DecayParameters", decay_parameters)); - } else { - throw std::runtime_error("DecayRecord only supports version <= 0!"); - } - }; -}; - -} // namespace dataclasses -} // namespace LI - -CEREAL_CLASS_VERSION(LI::dataclasses::DecayRecord, 0); - -#endif // LI_DecayRecord_H diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/DecaySignature.h b/projects/dataclasses/public/LeptonInjector/dataclasses/DecaySignature.h index 7024a31d6..e06d9911e 100644 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/DecaySignature.h +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/DecaySignature.h @@ -22,6 +22,7 @@ namespace dataclasses { struct DecaySignature { LI::dataclasses::Particle::ParticleType primary_type; std::vector secondary_types; + bool operator==(DecaySignature const & other) const; friend std::ostream& operator<<(std::ostream& os, DecaySignature const& signature); template diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionRecord.h b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionRecord.h index ae5327692..041f2af79 100644 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionRecord.h +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionRecord.h @@ -19,51 +19,331 @@ #include "LeptonInjector/serialization/array.h" +#include "LeptonInjector/dataclasses/Particle.h" +#include "LeptonInjector/dataclasses/ParticleID.h" +#include "LeptonInjector/dataclasses/ParticleType.h" #include "LeptonInjector/dataclasses/InteractionSignature.h" -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class PrimaryDistributionRecord; } } +namespace LI { namespace dataclasses { class SecondaryParticleRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } +namespace LI { namespace dataclasses { class SecondaryDistributionRecord; } } -std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionRecord const& record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionRecord const & record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::PrimaryDistributionRecord const & record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::SecondaryParticleRecord const & record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::CrossSectionDistributionRecord const & record); +std::ostream& operator<<(std::ostream& os, LI::dataclasses::SecondaryDistributionRecord const & record); namespace LI { namespace dataclasses { -struct InteractionRecord { - dataclasses::InteractionSignature signature; +// Record intended to be passed to the primary particle injection distributions +class PrimaryDistributionRecord { +public: + // The id and type should be constant + ParticleID const id; + ParticleType const type; +private: + // The rest of the primary particle properties can be changed + bool mass_set = false; + bool energy_set = false; + bool kinetic_energy_set = false; + bool direction_set = false; + bool momentum_set = false; + bool length_set = false; + bool initial_position_set = false; + bool interaction_vertex_set = false; + bool helicity_set = false; + + mutable double mass; + mutable double energy; + mutable double kinetic_energy; + mutable std::array direction; + mutable std::array momentum; + mutable double length; + mutable std::array initial_position; + mutable std::array interaction_vertex; + mutable double helicity = 0; +public: + friend std::ostream& ::operator<<(std::ostream& os, PrimaryDistributionRecord const& record); + + PrimaryDistributionRecord(PrimaryDistributionRecord const & other) = delete; + PrimaryDistributionRecord(PrimaryDistributionRecord && other) = default; + PrimaryDistributionRecord & operator=(PrimaryDistributionRecord const & other) = delete; + PrimaryDistributionRecord & operator=(PrimaryDistributionRecord && other) = delete; + + PrimaryDistributionRecord(ParticleType type); + + Particle GetParticle() const; + void SetParticle(Particle const & particle); + + ParticleID const & GetID() const; + ParticleType const & GetType() const; + + double const & GetMass() const; + double const & GetEnergy() const; + double const & GetKineticEnergy() const; + std::array const & GetDirection() const; + std::array const & GetThreeMomentum() const; + std::array GetFourMomentum() const; + double const & GetLength() const; + std::array const & GetInitialPosition() const; + std::array const & GetInteractionVertex() const; + double const & GetHelicity() const; + + void SetMass(double mass); + void SetEnergy(double energy); + void SetKineticEnergy(double kinetic_energy); + void SetDirection(std::array direction); + void SetThreeMomentum(std::array momentum); + void SetFourMomentum(std::array momentum); + void SetLength(double length); + void SetInitialPosition(std::array initial_position); + void SetInteractionVertex(std::array interaction_vertex); + void SetHelicity(double helicity); + + void UpdateMass() const; + void UpdateEnergy() const; + void UpdateKineticEnergy() const; + void UpdateDirection() const; + void UpdateMomentum() const; + void UpdateLength() const; + void UpdateInitialPosition() const; + void UpdateInteractionVertex() const; + + void FinalizeAvailable(InteractionRecord & record) const; + void Finalize(InteractionRecord & record) const; +}; + +class SecondaryParticleRecord { +public: + size_t const secondary_index; + ParticleID const id; + ParticleType const & type; + std::array const & initial_position; +private: + // The rest of the primary particle properties can be changed + bool mass_set = false; + bool energy_set = false; + bool kinetic_energy_set = false; + bool direction_set = false; + bool momentum_set = false; + bool helicity_set = false; + + mutable double mass = 0; + mutable double energy = 0; + mutable double kinetic_energy = 0; + mutable std::array direction = {0, 0, 0}; + mutable std::array momentum = {0, 0, 0}; + mutable double helicity = 0; +public: + friend std::ostream& ::operator<<(std::ostream& os, SecondaryParticleRecord const& record); + + SecondaryParticleRecord(SecondaryParticleRecord const & other) = delete; + SecondaryParticleRecord(SecondaryParticleRecord && other) = default; + SecondaryParticleRecord & operator=(SecondaryParticleRecord const & other) = delete; + SecondaryParticleRecord & operator=(SecondaryParticleRecord && other) = delete; + + SecondaryParticleRecord(InteractionRecord const & record, size_t secondary_index); + + InteractionSignature const & GetSignature() const; + + Particle GetParticle() const; + void SetParticle(Particle const & particle); + + ParticleID const & GetID() const; + + ParticleType const & GetType() const; + double const & GetMass() const; + double const & GetEnergy() const; + double const & GetKineticEnergy() const; + std::array const & GetDirection() const; + std::array const & GetThreeMomentum() const; + std::array GetFourMomentum() const; + std::array const & GetInitialPosition() const; + double const & GetHelicity() const; + + void SetMass(double mass); + void SetEnergy(double energy); + void SetKineticEnergy(double kinetic_energy); + void SetDirection(std::array direction); + void SetThreeMomentum(std::array momentum); + void SetFourMomentum(std::array momentum); + void SetHelicity(double helicity); + + void UpdateMass() const; + void UpdateEnergy() const; + void UpdateKineticEnergy() const; + void UpdateDirection() const; + void UpdateMomentum() const; + + void Finalize(InteractionRecord & record) const; +}; + +class CrossSectionDistributionRecord { +public: + InteractionRecord const & record; + InteractionSignature const & signature; + ParticleID const & primary_id; + ParticleType const & primary_type; + std::array const & primary_initial_position; + double const & primary_mass; + std::array const & primary_momentum; + double const & primary_helicity; + std::array const & interaction_vertex; + + ParticleID const target_id; + ParticleType const & target_type; + + double target_mass = 0; + double target_helicity = 0; + std::map interaction_parameters; +private: + std::vector secondary_particles; +public: + friend std::ostream& ::operator<<(std::ostream& os, CrossSectionDistributionRecord const& record); + + CrossSectionDistributionRecord(CrossSectionDistributionRecord const & other) = delete; + CrossSectionDistributionRecord(CrossSectionDistributionRecord && other) = default; + CrossSectionDistributionRecord & operator=(CrossSectionDistributionRecord const & other) = delete; + CrossSectionDistributionRecord & operator=(CrossSectionDistributionRecord && other) = delete; + + CrossSectionDistributionRecord(InteractionRecord const & record); + + InteractionSignature const & GetSignature() const; + ParticleID const & GetPrimaryID() const; + ParticleType const & GetPrimaryType() const; + std::array const & GetPrimaryInitialPosition() const; + double const & GetPrimaryMass() const; + std::array const & GetPrimaryMomentum() const; + double const & GetPrimaryHelicity() const; + + std::array const & GetInteractionVertex() const; + ParticleID const & GetTargetID() const; + ParticleType const & GetTargetType() const; + + double const & GetTargetMass() const; + double const & GetTargetHelicity() const; + double & GetTargetMass(); + double & GetTargetHelicity(); + std::map & GetInteractionParameters(); + + void SetTargetMass(double mass); + void SetTargetHelicity(double helicity); + void SetInteractionParameters(std::map const & parameters); + void SetInteractionParameter(std::string const & name, double value); + + std::vector & GetSecondaryParticleRecords(); + std::vector const & GetSecondaryParticleRecords() const; + SecondaryParticleRecord & GetSecondaryParticleRecord(size_t index); + SecondaryParticleRecord const & GetSecondaryParticleRecord(size_t index) const; + + void Finalize(InteractionRecord & record) const; +}; + +class InteractionRecord { +public: + InteractionSignature signature; + ParticleID primary_id; + std::array primary_initial_position = {0, 0, 0}; double primary_mass = 0; std::array primary_momentum = {0, 0, 0, 0}; double primary_helicity = 0; + ParticleID target_id; double target_mass = 0; - std::array target_momentum = {0, 0, 0, 0}; double target_helicity = 0; std::array interaction_vertex = {0, 0, 0}; + std::vector secondary_ids; std::vector secondary_masses; std::vector> secondary_momenta; - std::vector secondary_helicity; - std::vector interaction_parameters; + std::vector secondary_helicities; + std::map interaction_parameters; + bool operator==(InteractionRecord const & other) const; + bool operator<(InteractionRecord const & other) const; friend std::ostream& ::operator<<(std::ostream& os, InteractionRecord const& record); - template - void serialize(Archive & archive, std::uint32_t const version) { + + template + void save(Archive & archive, std::uint32_t const version) const { + if(version == 0) { + archive(::cereal::make_nvp("InteractionSignature", signature)); + archive(::cereal::make_nvp("PrimaryID", primary_id)); + archive(::cereal::make_nvp("PrimaryInitialPosition", primary_initial_position)); + archive(::cereal::make_nvp("PrimaryMass", primary_mass)); + archive(::cereal::make_nvp("PrimaryMomentum", primary_momentum)); + archive(::cereal::make_nvp("PrimaryHelicity", primary_helicity)); + archive(::cereal::make_nvp("TargetID", target_id)); + archive(::cereal::make_nvp("TargetMass", target_mass)); + archive(::cereal::make_nvp("TargetHelicity", target_helicity)); + archive(::cereal::make_nvp("InteractionVertex", interaction_vertex)); + archive(::cereal::make_nvp("SecondaryIDs", secondary_ids)); + archive(::cereal::make_nvp("SecondaryMasses", secondary_masses)); + archive(::cereal::make_nvp("SecondaryMomenta", secondary_momenta)); + archive(::cereal::make_nvp("SecondaryHelicities", secondary_helicities)); + archive(::cereal::make_nvp("InteractionParameters", interaction_parameters)); + } else { + throw std::runtime_error("InteractionRecord only supports version <= 0!"); + } + } + template + void load(Archive & archive, std::uint32_t const version) { if(version == 0) { archive(::cereal::make_nvp("InteractionSignature", signature)); + archive(::cereal::make_nvp("PrimaryID", primary_id)); + archive(::cereal::make_nvp("PrimaryInitialPosition", primary_initial_position)); archive(::cereal::make_nvp("PrimaryMass", primary_mass)); archive(::cereal::make_nvp("PrimaryMomentum", primary_momentum)); archive(::cereal::make_nvp("PrimaryHelicity", primary_helicity)); + archive(::cereal::make_nvp("TargetID", target_id)); archive(::cereal::make_nvp("TargetMass", target_mass)); - archive(::cereal::make_nvp("TargetMomentum", target_momentum)); archive(::cereal::make_nvp("TargetHelicity", target_helicity)); archive(::cereal::make_nvp("InteractionVertex", interaction_vertex)); + archive(::cereal::make_nvp("SecondaryIDs", secondary_ids)); archive(::cereal::make_nvp("SecondaryMasses", secondary_masses)); archive(::cereal::make_nvp("SecondaryMomenta", secondary_momenta)); - archive(::cereal::make_nvp("SecondaryHelicity", secondary_helicity)); + archive(::cereal::make_nvp("SecondaryHelicities", secondary_helicities)); archive(::cereal::make_nvp("InteractionParameters", interaction_parameters)); } else { throw std::runtime_error("InteractionRecord only supports version <= 0!"); } - }; + } }; +class SecondaryDistributionRecord { + size_t const secondary_index = 0; +public: + InteractionRecord const record; + + ParticleID const id; + ParticleType const & type; + double const & mass; + std::array const direction; + std::array const & momentum; + double const & helicity; + std::array const & initial_position; +private: + bool length_set = false; + mutable double length; +public: + friend std::ostream& ::operator<<(std::ostream& os, SecondaryDistributionRecord const& record); + + SecondaryDistributionRecord(SecondaryDistributionRecord const & other) = default; + SecondaryDistributionRecord & operator=(SecondaryDistributionRecord const & other) = delete; + SecondaryDistributionRecord & operator=(SecondaryDistributionRecord && other) = delete; + + static InteractionRecord CreateSecondaryRecord(InteractionRecord const & parent_record, size_t secondary_index); + SecondaryDistributionRecord(InteractionRecord & record); + SecondaryDistributionRecord(InteractionRecord const & parent_record, size_t secondary_index); + + void SetLength(double const & length); + double const & GetLength() const; + + void Finalize(InteractionRecord & record) const; +}; + + } // namespace dataclasses } // namespace LI diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionSignature.h b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionSignature.h index 730705b44..367f937cf 100644 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionSignature.h +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionSignature.h @@ -9,17 +9,23 @@ #include // for make_nvp, CEREAL_CL... #include "LeptonInjector/dataclasses/Particle.h" // for Particle + // + +namespace LI { namespace dataclasses { struct InteractionSignature; } } + +std::ostream& operator<<(std::ostream& os, LI::dataclasses::InteractionSignature const& signature); namespace LI { namespace dataclasses { struct InteractionSignature { - LI::dataclasses::Particle::ParticleType primary_type; - LI::dataclasses::Particle::ParticleType target_type; + LI::dataclasses::Particle::ParticleType primary_type = LI::dataclasses::Particle::ParticleType::unknown; + LI::dataclasses::Particle::ParticleType target_type = LI::dataclasses::Particle::ParticleType::unknown; std::vector secondary_types; + bool operator==(InteractionSignature const & other) const; bool operator<(InteractionSignature const & other) const; - friend std::ostream& operator<<(std::ostream& os, InteractionSignature const& signature); + friend std::ostream& ::operator<<(std::ostream& os, InteractionSignature const& signature); template void serialize(Archive & archive, std::uint32_t const version) { if(version == 0) { diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionTree.h b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionTree.h index 42f6a2d8c..bedc6d622 100644 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionTree.h +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/InteractionTree.h @@ -43,7 +43,9 @@ struct InteractionTreeDatum { struct InteractionTree { std::set> tree; - std::shared_ptr add_entry(dataclasses::InteractionTreeDatum& record, + std::shared_ptr add_entry(std::shared_ptr datum, + std::shared_ptr parent = NULL); + std::shared_ptr add_entry(dataclasses::InteractionTreeDatum& datum, std::shared_ptr parent = NULL); std::shared_ptr add_entry(dataclasses::InteractionRecord& record, std::shared_ptr parent = NULL); diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/Particle.h b/projects/dataclasses/public/LeptonInjector/dataclasses/Particle.h index d2ca95c15..73948c3ff 100644 --- a/projects/dataclasses/public/LeptonInjector/dataclasses/Particle.h +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/Particle.h @@ -7,251 +7,66 @@ #include #include -#include #include +#include "LeptonInjector/dataclasses/ParticleID.h" +#include "LeptonInjector/dataclasses/ParticleType.h" + #include #include #include #include -#include +#include +#include #include #include +#include "LeptonInjector/serialization/array.h" + +namespace LI { namespace dataclasses { class Particle; } } + +std::ostream & operator<<(std::ostream & os, LI::dataclasses::Particle const & p); + namespace LI { namespace dataclasses { // simple data structure for particles class Particle { public: - // these match the PDG codes! - // copied over from IceCube's dataclasses I3Particle definition - enum ParticleType : int32_t { - unknown = 0, - Gamma = 22, - EPlus = -11, - EMinus = 11, - MuPlus = -13, - MuMinus = 13, - Pi0 = 111, - PiPlus = 211, - PiMinus = -211, - Rho0 = 113, - RhoPlus = 213, - RhoMinus = -213, - K0_Long = 130, - KPlus = 321, - KMinus = -321, - KStarPlus = 9000311, - KStarMinus = -9000311, - Neutron = 2112, - PPlus = 2212, - PMinus = -2212, - K0_Short = 310, - Eta = 221, - EtaPrime= 331, - Omega = 223, - Phi = 333, - Lambda = 3122, - SigmaPlus = 3222, - Sigma0 = 3212, - SigmaMinus = 3112, - Xi0 = 3322, - XiMinus = 3312, - OmegaMinus = 3334, - NeutronBar = -2112, - LambdaBar = -3122, - SigmaMinusBar = -3222, - Sigma0Bar = -3212, - SigmaPlusBar = -3112, - Xi0Bar = -3322, - XiPlusBar = -3312, - OmegaPlusBar = -3334, - DPlus = 411, - DMinus = -411, - D0 = 421, - D0Bar = -421, - DsPlus = 431, - DsMinusBar = -431, - LambdacPlus = 4122, - WPlus = 24, - WMinus = -24, - Z0 = 23, - NuE = 12, - NuEBar = -12, - NuMu = 14, - NuMuBar = -14, - TauPlus = -15, - TauMinus = 15, - NuTau = 16, - NuTauBar = -16, - - /* Nuclei */ - HNucleus = 1000010010, - H2Nucleus = 1000010020, - He3Nucleus = 1000020030, - He4Nucleus = 1000020040, - Li6Nucleus = 1000030060, - Li7Nucleus = 1000030070, - Be9Nucleus = 1000040090, - B10Nucleus = 1000050100, - B11Nucleus = 1000050110, - C12Nucleus = 1000060120, - C13Nucleus = 1000060130, - N14Nucleus = 1000070140, - N15Nucleus = 1000070150, - O16Nucleus = 1000080160, - O17Nucleus = 1000080170, - O18Nucleus = 1000080180, - F19Nucleus = 1000090190, - Ne20Nucleus = 1000100200, - Ne21Nucleus = 1000100210, - Ne22Nucleus = 1000100220, - Na23Nucleus = 1000110230, - Mg24Nucleus = 1000120240, - Mg25Nucleus = 1000120250, - Mg26Nucleus = 1000120260, - Al26Nucleus = 1000130260, - Al27Nucleus = 1000130270, - Si28Nucleus = 1000140280, - Si29Nucleus = 1000140290, - Si30Nucleus = 1000140300, - Si31Nucleus = 1000140310, - Si32Nucleus = 1000140320, - P31Nucleus = 1000150310, - P32Nucleus = 1000150320, - P33Nucleus = 1000150330, - S32Nucleus = 1000160320, - S33Nucleus = 1000160330, - S34Nucleus = 1000160340, - S35Nucleus = 1000160350, - S36Nucleus = 1000160360, - Cl35Nucleus = 1000170350, - Cl36Nucleus = 1000170360, - Cl37Nucleus = 1000170370, - Ar36Nucleus = 1000180360, - Ar37Nucleus = 1000180370, - Ar38Nucleus = 1000180380, - Ar39Nucleus = 1000180390, - Ar40Nucleus = 1000180400, - Ar41Nucleus = 1000180410, - Ar42Nucleus = 1000180420, - K39Nucleus = 1000190390, - K40Nucleus = 1000190400, - K41Nucleus = 1000190410, - Ca40Nucleus = 1000200400, - Ca41Nucleus = 1000200410, - Ca42Nucleus = 1000200420, - Ca43Nucleus = 1000200430, - Ca44Nucleus = 1000200440, - Ca45Nucleus = 1000200450, - Ca46Nucleus = 1000200460, - Ca47Nucleus = 1000200470, - Ca48Nucleus = 1000200480, - Sc44Nucleus = 1000210440, - Sc45Nucleus = 1000210450, - Sc46Nucleus = 1000210460, - Sc47Nucleus = 1000210470, - Sc48Nucleus = 1000210480, - Ti44Nucleus = 1000220440, - Ti45Nucleus = 1000220450, - Ti46Nucleus = 1000220460, - Ti47Nucleus = 1000220470, - Ti48Nucleus = 1000220480, - Ti49Nucleus = 1000220490, - Ti50Nucleus = 1000220500, - V48Nucleus = 1000230480, - V49Nucleus = 1000230490, - V50Nucleus = 1000230500, - V51Nucleus = 1000230510, - Cr50Nucleus = 1000240500, - Cr51Nucleus = 1000240510, - Cr52Nucleus = 1000240520, - Cr53Nucleus = 1000240530, - Cr54Nucleus = 1000240540, - Mn52Nucleus = 1000250520, - Mn53Nucleus = 1000250530, - Mn54Nucleus = 1000250540, - Mn55Nucleus = 1000250550, - Fe54Nucleus = 1000260540, - Fe55Nucleus = 1000260550, - Fe56Nucleus = 1000260560, - Fe57Nucleus = 1000260570, - Fe58Nucleus = 1000260580, - Cu63Nucleus = 1000290630, - Cu65Nucleus = 1000290650, - W183Nucleus = 1000741830, - Pb208Nucleus = 1000822080, - - /* Exotics */ - Qball = 10000000, - - /* The following are fake particles used in Icetray and have no official codes */ - - /* Start with DarkNews particles. These are defined according to: - PDGID = 59(particle spin code: 0-scalar 1-fermion 2-vector)(generation number) - */ - NuLight = 5910, - Nu1 = 5911, - Nu2 = 5912, - Nu3 = 5913, - N4 = 5914, - N5 = 5915, - N6 = 5916, - ZPrime = 5921, - HPrime = 5901, - PhiPrime = 5902, - ALP = 5903, - - /* The section abs(code) > 2000000000 is reserved for this kind of use */ - NuF4 = 2000000018, - NuF4Bar = -2000000018, - Nucleon = 2000002112, - CherenkovPhoton = 2000009900, - Nu = -2000000004, - Monopole = -2000000041, - Brems = -2000001001, - DeltaE = -2000001002, - PairProd = -2000001003, - NuclInt = -2000001004, - MuPair = -2000001005, - Hadrons = -2000001006, - Decay = -2000001007, - ContinuousEnergyLoss = -2000001111, - FiberLaser = -2000002100, - N2Laser = -2000002101, - YAGLaser = -2000002201, - STauPlus = -2000009131, - STauMinus = -2000009132, - SMPPlus = -2000009500, - SMPMinus = -2000009501, - - }; - - // There are two kinds of event topologies in IceCube - // cascades - // tracks - enum class ParticleShape{ MCTrack, Cascade, unknown }; - -public: - - Particle(); - - Particle(ParticleType type); - - - // what kind of particle is this (see below) - ParticleType type; - // what is this event's topology? (see below) - - double energy; // GeV - std::pair direction; //( zenith, azimuth ) in degrees - double position[3]; // (x,y,z) in meters - - double GetMass(); //GeV/c^2 - bool HasMass(); // .... - std::string GetTypeString(); + typedef LI::dataclasses::ParticleType ParticleType; + + Particle() = default; + Particle(Particle const & other) = default; + Particle(ParticleID id, ParticleType type, double mass, std::array momentum, std::array position, double length, double helicity); + Particle(ParticleType type, double mass, std::array momentum, std::array position, double length, double helicity); + + ParticleID id; + ParticleType type = ParticleType::unknown; + double mass = 0; + std::array momentum = {0, 0, 0, 0}; + std::array position = {0, 0, 0}; + double length = 0; + double helicity = 0; + + ParticleID & GenerateID(); + + friend std::ostream & ::operator<<(std::ostream & os, LI::dataclasses::Particle const & p); + + template + void serialize(Archive & archive, std::uint32_t const version) { + if(version == 0) { + archive(::cereal::make_nvp("ID", id)); + archive(::cereal::make_nvp("Type", type)); + archive(::cereal::make_nvp("Mass", mass)); + archive(::cereal::make_nvp("Momentum", momentum)); + archive(::cereal::make_nvp("Position", position)); + archive(::cereal::make_nvp("Length", length)); + archive(::cereal::make_nvp("helicity", helicity)); + } else { + throw std::runtime_error("Particle only supports version <= 0!"); + } + } }; // prototype some of the particle helper functions @@ -259,82 +74,10 @@ class Particle { bool isLepton(Particle::ParticleType p); bool isCharged(Particle::ParticleType p); bool isNeutrino(Particle::ParticleType p); -std::string particleName( Particle::ParticleType p); -double particleMass( Particle::ParticleType type); -double kineticEnergy( Particle::ParticleType type, double totalEnergy); -double particleSpeed( Particle::ParticleType type, double kineticEnergy); -Particle::ParticleShape decideShape(Particle::ParticleType t); -Particle::ParticleType deduceInitialType( Particle::ParticleType pType1, Particle::ParticleType pType2); -uint8_t getInteraction( Particle::ParticleType final_1 , Particle::ParticleType final_2); -} // namespace utilities +} // namespace dataclasses } // namespace LI -namespace cereal { - template - int save_minimal(Archive const &, LI::dataclasses::Particle::ParticleType const & p) { - return static_cast(p); - } - - template - void load_minimal(Archive const &, LI::dataclasses::Particle::ParticleType & p, int const & value ) - { - p = static_cast(value); - } - - template inline - void save( Archive & ar, std::set const & set ) - { - ar( make_size_tag( static_cast(set.size()) ) ); - - for( const auto & i : set ) - ar( i ); - } - - template inline - void load( Archive & ar, std::set & set ) - { - size_type size; - ar( make_size_tag( size ) ); - - set.clear(); - - auto hint = set.begin(); - for( size_type i = 0; i < size; ++i ) - { - typename std::set::key_type key; - ar( key ); - hint = set.emplace_hint( hint, std::move( key ) ); - } - } -} - -#define PARTICLE_H_Particle_ParticleType \ - (unknown)(Gamma)(EPlus)(EMinus)(MuPlus)(MuMinus)(Pi0) \ - (PiPlus)(PiMinus)(K0_Long)(KPlus)(KMinus)(Neutron)(PPlus)(PMinus)(K0_Short) \ - (Eta)(Lambda)(SigmaPlus)(Sigma0)(SigmaMinus)(Xi0)(XiMinus)(OmegaMinus) \ - (NeutronBar)(LambdaBar)(SigmaMinusBar)(Sigma0Bar)(SigmaPlusBar)(Xi0Bar) \ - (XiPlusBar)(OmegaPlusBar)(DPlus)(DMinus)(D0)(D0Bar)(DsPlus)(DsMinusBar) \ - (LambdacPlus)(WPlus)(WMinus)(Z0)(NuE)(NuEBar) \ - (NuMu)(NuMuBar)(TauPlus)(TauMinus)(NuTau)(NuTauBar)(H2Nucleus) \ - (He3Nucleus)(He4Nucleus)(Li6Nucleus)(Li7Nucleus)(Be9Nucleus)(B10Nucleus) \ - (B11Nucleus)(C12Nucleus)(C13Nucleus)(N14Nucleus)(N15Nucleus)(O16Nucleus) \ - (O17Nucleus)(O18Nucleus)(F19Nucleus)(Ne20Nucleus)(Ne21Nucleus)(Ne22Nucleus) \ - (Na23Nucleus)(Mg24Nucleus)(Mg25Nucleus)(Mg26Nucleus)(Al26Nucleus)(Al27Nucleus)\ - (Si28Nucleus)(Si29Nucleus)(Si30Nucleus)(Si31Nucleus)(Si32Nucleus)(P31Nucleus) \ - (P32Nucleus)(P33Nucleus)(S32Nucleus)(S33Nucleus)(S34Nucleus)(S35Nucleus) \ - (S36Nucleus)(Cl35Nucleus)(Cl36Nucleus)(Cl37Nucleus)(Ar36Nucleus)(Ar37Nucleus) \ - (Ar38Nucleus)(Ar39Nucleus)(Ar40Nucleus)(Ar41Nucleus)(Ar42Nucleus)(K39Nucleus) \ - (K40Nucleus)(K41Nucleus)(Ca40Nucleus)(Ca41Nucleus)(Ca42Nucleus)(Ca43Nucleus) \ - (Ca44Nucleus)(Ca45Nucleus)(Ca46Nucleus)(Ca47Nucleus)(Ca48Nucleus)(Sc44Nucleus)\ - (Sc45Nucleus)(Sc46Nucleus)(Sc47Nucleus)(Sc48Nucleus)(Ti44Nucleus)(Ti45Nucleus)\ - (Ti46Nucleus)(Ti47Nucleus)(Ti48Nucleus)(Ti49Nucleus)(Ti50Nucleus)(V48Nucleus) \ - (V49Nucleus)(V50Nucleus)(V51Nucleus)(Cr50Nucleus)(Cr51Nucleus)(Cr52Nucleus) \ - (Cr53Nucleus)(Cr54Nucleus)(Mn52Nucleus)(Mn53Nucleus)(Mn54Nucleus)(Mn55Nucleus)\ - (Fe54Nucleus)(Fe55Nucleus)(Fe56Nucleus)(Fe57Nucleus)(Fe58Nucleus)(Qball) \ - (CherenkovPhoton)(Nu)(Monopole)(Brems)(DeltaE)(PairProd)(NuclInt)(MuPair) \ - (Hadrons)(Decay)(ContinuousEnergyLoss)(FiberLaser)(N2Laser)(YAGLaser) \ - +CEREAL_CLASS_VERSION(LI::dataclasses::Particle, 0); #endif // LI_Particle_H - diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleID.h b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleID.h new file mode 100644 index 000000000..44232f6f8 --- /dev/null +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleID.h @@ -0,0 +1,65 @@ +#ifndef LI_ParticleID_H +#define LI_ParticleID_H + +#include // for uint32_t +#include // for ostream +#include // for runtime_error + +#include +#include +#include +#include +#include +#include + +namespace LI { namespace dataclasses { class ParticleID; } } + +std::ostream& operator<<(std::ostream& os, LI::dataclasses::ParticleID const& record); + +namespace LI { +namespace dataclasses { + +class ParticleID { + bool id_set = false; + uint64_t major_id = 0; + int64_t minor_id = 0; +public: + static ParticleID GenerateID(); + + ParticleID(); + ParticleID(uint64_t major, int32_t minor); + ParticleID & operator=(ParticleID const & other) = default; + ParticleID(ParticleID const & other) = default; + ParticleID & operator=(ParticleID && other) = default; + ParticleID(ParticleID && other) = default; + + bool IsSet() const; + operator bool() const; + + uint64_t GetMajorID() const; + int32_t GetMinorID() const; + + void SetID(uint64_t major, int32_t minor); + + bool operator<(ParticleID const & other) const; + + bool operator==(ParticleID const & other) const; + friend std::ostream& ::operator<<(std::ostream& os, ParticleID const& record); + template + void serialize(Archive & archive, std::uint32_t const version) { + if(version == 0) { + archive(::cereal::make_nvp("IDSet", id_set)); + archive(::cereal::make_nvp("MajorID", major_id)); + archive(::cereal::make_nvp("MinorID", minor_id)); + } else { + throw std::runtime_error("ParticleID only supports version <= 0!"); + } + }; +}; + +} // namespace dataclasses +} // namespace LI + +CEREAL_CLASS_VERSION(LI::dataclasses::ParticleID, 0); + +#endif // LI_ParticleID_H diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleType.h b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleType.h new file mode 100644 index 000000000..ac05c375e --- /dev/null +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleType.h @@ -0,0 +1,90 @@ +#pragma once +#ifndef LI_ParticleType_H +#define LI_ParticleType_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace LI { +namespace dataclasses { + +enum class ParticleType : int32_t { +#define X(a, b) a = b, +#include "LeptonInjector/dataclasses/ParticleTypes.def" +#undef X +}; + +static const std::map ParticleTypeNames = { +#define X(a, b) {ParticleType:: a , #a }, +#include "LeptonInjector/dataclasses/ParticleTypes.def" +#undef X +}; + +static const std::map ParticleTypeMap = { +#define X(a, b) { #a , ParticleType:: a }, +#include "LeptonInjector/dataclasses/ParticleTypes.def" +#undef X +}; + +static const std::map ParticleTypeIntNames = { +#define X(a, b) { b , #a }, +#include "LeptonInjector/dataclasses/ParticleTypes.def" +#undef X +}; + +} // namespace LI +} // namespace dataclasses + +std::ostream & operator<<(std::ostream & os, LI::dataclasses::ParticleType const & p); + +namespace cereal { + template + int save_minimal(Archive const &, LI::dataclasses::ParticleType const & p) { + return static_cast(p); + } + + template + void load_minimal(Archive const &, LI::dataclasses::ParticleType & p, int const & value ) + { + p = static_cast(value); + } + + template inline + void save( Archive & ar, std::set const & set ) + { + ar( make_size_tag( static_cast(set.size()) ) ); + + for( const auto & i : set ) + ar( i ); + } + + template inline + void load( Archive & ar, std::set & set ) + { + size_type size; + ar( make_size_tag( size ) ); + + set.clear(); + + auto hint = set.begin(); + for( size_type i = 0; i < size; ++i ) + { + typename std::set::key_type key; + ar( key ); + hint = set.emplace_hint( hint, std::move( key ) ); + } + } +} + +#endif // LI_ParticleType_H diff --git a/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleTypes.def b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleTypes.def new file mode 100644 index 000000000..8c0687c3c --- /dev/null +++ b/projects/dataclasses/public/LeptonInjector/dataclasses/ParticleTypes.def @@ -0,0 +1,198 @@ +X(unknown, 0) +X(Gamma, 22) +X(EPlus, -11) +X(EMinus, 11) +X(MuPlus, -13) +X(MuMinus, 13) +X(Pi0, 111) +X(PiPlus, 211) +X(PiMinus, -211) +X(Rho0, 113) +X(RhoPlus, 213) +X(RhoMinus, -213) +X(K0_Long, 130) +X(KPlus, 321) +X(KMinus, -321) +X(KStarPlus, 9000311) +X(KStarMinus, -9000311) +X(Neutron, 2112) +X(PPlus, 2212) +X(PMinus, -2212) +X(K0_Short, 310) +X(Eta, 221) +X(EtaPrime, 331) +X(Omega, 223) +X(Phi, 333) +X(Lambda, 3122) +X(SigmaPlus, 3222) +X(Sigma0, 3212) +X(SigmaMinus, 3112) +X(Xi0, 3322) +X(XiMinus, 3312) +X(OmegaMinus, 3334) +X(NeutronBar, -2112) +X(LambdaBar, -3122) +X(SigmaMinusBar, -3222) +X(Sigma0Bar, -3212) +X(SigmaPlusBar, -3112) +X(Xi0Bar, -3322) +X(XiPlusBar, -3312) +X(OmegaPlusBar, -3334) +X(DPlus, 411) +X(DMinus, -411) +X(D0, 421) +X(D0Bar, -421) +X(DsPlus, 431) +X(DsMinusBar, -431) +X(LambdacPlus, 4122) +X(WPlus, 24) +X(WMinus, -24) +X(Z0, 23) +X(NuE, 12) +X(NuEBar, -12) +X(NuMu, 14) +X(NuMuBar, -14) +X(TauPlus, -15) +X(TauMinus, 15) +X(NuTau, 16) +X(NuTauBar, -16) + +/* Nuclei */ +X(HNucleus, 1000010010) +X(H2Nucleus, 1000010020) +X(He3Nucleus, 1000020030) +X(He4Nucleus, 1000020040) +X(Li6Nucleus, 1000030060) +X(Li7Nucleus, 1000030070) +X(Be9Nucleus, 1000040090) +X(B10Nucleus, 1000050100) +X(B11Nucleus, 1000050110) +X(C12Nucleus, 1000060120) +X(C13Nucleus, 1000060130) +X(N14Nucleus, 1000070140) +X(N15Nucleus, 1000070150) +X(O16Nucleus, 1000080160) +X(O17Nucleus, 1000080170) +X(O18Nucleus, 1000080180) +X(F19Nucleus, 1000090190) +X(Ne20Nucleus, 1000100200) +X(Ne21Nucleus, 1000100210) +X(Ne22Nucleus, 1000100220) +X(Na23Nucleus, 1000110230) +X(Mg24Nucleus, 1000120240) +X(Mg25Nucleus, 1000120250) +X(Mg26Nucleus, 1000120260) +X(Al26Nucleus, 1000130260) +X(Al27Nucleus, 1000130270) +X(Si28Nucleus, 1000140280) +X(Si29Nucleus, 1000140290) +X(Si30Nucleus, 1000140300) +X(Si31Nucleus, 1000140310) +X(Si32Nucleus, 1000140320) +X(P31Nucleus, 1000150310) +X(P32Nucleus, 1000150320) +X(P33Nucleus, 1000150330) +X(S32Nucleus, 1000160320) +X(S33Nucleus, 1000160330) +X(S34Nucleus, 1000160340) +X(S35Nucleus, 1000160350) +X(S36Nucleus, 1000160360) +X(Cl35Nucleus, 1000170350) +X(Cl36Nucleus, 1000170360) +X(Cl37Nucleus, 1000170370) +X(Ar36Nucleus, 1000180360) +X(Ar37Nucleus, 1000180370) +X(Ar38Nucleus, 1000180380) +X(Ar39Nucleus, 1000180390) +X(Ar40Nucleus, 1000180400) +X(Ar41Nucleus, 1000180410) +X(Ar42Nucleus, 1000180420) +X(K39Nucleus, 1000190390) +X(K40Nucleus, 1000190400) +X(K41Nucleus, 1000190410) +X(Ca40Nucleus, 1000200400) +X(Ca41Nucleus, 1000200410) +X(Ca42Nucleus, 1000200420) +X(Ca43Nucleus, 1000200430) +X(Ca44Nucleus, 1000200440) +X(Ca45Nucleus, 1000200450) +X(Ca46Nucleus, 1000200460) +X(Ca47Nucleus, 1000200470) +X(Ca48Nucleus, 1000200480) +X(Sc44Nucleus, 1000210440) +X(Sc45Nucleus, 1000210450) +X(Sc46Nucleus, 1000210460) +X(Sc47Nucleus, 1000210470) +X(Sc48Nucleus, 1000210480) +X(Ti44Nucleus, 1000220440) +X(Ti45Nucleus, 1000220450) +X(Ti46Nucleus, 1000220460) +X(Ti47Nucleus, 1000220470) +X(Ti48Nucleus, 1000220480) +X(Ti49Nucleus, 1000220490) +X(Ti50Nucleus, 1000220500) +X(V48Nucleus, 1000230480) +X(V49Nucleus, 1000230490) +X(V50Nucleus, 1000230500) +X(V51Nucleus, 1000230510) +X(Cr50Nucleus, 1000240500) +X(Cr51Nucleus, 1000240510) +X(Cr52Nucleus, 1000240520) +X(Cr53Nucleus, 1000240530) +X(Cr54Nucleus, 1000240540) +X(Mn52Nucleus, 1000250520) +X(Mn53Nucleus, 1000250530) +X(Mn54Nucleus, 1000250540) +X(Mn55Nucleus, 1000250550) +X(Fe54Nucleus, 1000260540) +X(Fe55Nucleus, 1000260550) +X(Fe56Nucleus, 1000260560) +X(Fe57Nucleus, 1000260570) +X(Fe58Nucleus, 1000260580) +X(Cu63Nucleus, 1000290630) +X(Cu65Nucleus, 1000290650) +X(W183Nucleus, 1000741830) +X(Pb208Nucleus, 1000822080) + +/* Exotics */ +X(Qball, 10000000) + +/* The following are fake particles used in Icetray and have no official codes */ + +/* Start with DarkNews particles. These are defined according to: + PDGID = 59(particle spin code: 0-scalar 1-fermion 2-vector)(generation number) +*/ +X(NuLight, 5910) +X(Nu1, 5911) +X(Nu2, 5912) +X(Nu3, 5913) +X(N4, 5914) +X(N5, 5915) +X(N6, 5916) +X(ZPrime, 5921) +X(HPrime, 5901) +X(PhiPrime, 5902) +X(ALP, 5903) + +/* The section abs(code) > 2000000000 is reserved for this kind of use */ +X(NuF4, 2000000018) +X(NuF4Bar, -2000000018) +X(Nucleon, 2000002112) +X(CherenkovPhoton, 2000009900) +X(Nu, -2000000004) +X(Monopole, -2000000041) +X(Brems, -2000001001) +X(DeltaE, -2000001002) +X(PairProd, -2000001003) +X(NuclInt, -2000001004) +X(MuPair, -2000001005) +X(Hadrons, -2000001006) +X(Decay, -2000001007) +X(ContinuousEnergyLoss, -2000001111) +X(FiberLaser, -2000002100) +X(N2Laser, -2000002101) +X(YAGLaser, -2000002201) +X(STauPlus, -2000009131) +X(STauMinus, -2000009132) +X(SMPPlus, -2000009500) +X(SMPMinus, -2000009501) diff --git a/projects/detector/private/DetectorModel.cxx b/projects/detector/private/DetectorModel.cxx index d4e67e895..4812759de 100644 --- a/projects/detector/private/DetectorModel.cxx +++ b/projects/detector/private/DetectorModel.cxx @@ -592,7 +592,7 @@ double DetectorModel::GetInteractionDensity(Geometry::IntersectionList const & i // If we have only decays, avoid the sector loop // total_decay_length is in m if(targets.empty()) { - return 1./total_decay_length; + return 1.0 / total_decay_length; } double interaction_density = std::numeric_limits::quiet_NaN(); @@ -622,7 +622,7 @@ double DetectorModel::GetInteractionDensity(Geometry::IntersectionList const & i assert(interaction_density >= 0); - interaction_density += 1./total_decay_length; + interaction_density += 1.0 / total_decay_length; return interaction_density; } diff --git a/projects/detector/private/Path.cxx b/projects/detector/private/Path.cxx index c993e8b25..f369368c9 100644 --- a/projects/detector/private/Path.cxx +++ b/projects/detector/private/Path.cxx @@ -810,6 +810,7 @@ bool Path::IsWithinBounds(GeometryPosition point) { return d0 <= 0 and d1 >= 0; } else { EnsurePoints(); + return false; } } @@ -821,6 +822,7 @@ double Path::GetDistanceFromStartInBounds(GeometryPosition point) { return std::max(0.0, d0); } else { EnsurePoints(); + return false; } } diff --git a/projects/detector/private/test/Path_TEST.cxx b/projects/detector/private/test/Path_TEST.cxx index 2dc4227b5..36486d9ea 100644 --- a/projects/detector/private/test/Path_TEST.cxx +++ b/projects/detector/private/test/Path_TEST.cxx @@ -31,6 +31,14 @@ using namespace LI::detector; using namespace LI::geometry; +#define EXPECT_NEAR_REL(A, B, C) \ + EXPECT_NEAR(A, B, C * std::max(std::abs(A), std::abs(B))); + +#define EXPECT_VECTOR3D_NEAR_REL(A, B, C) \ + EXPECT_NEAR(A.GetX(), B.GetX(), C * std::max(std::abs(A.GetX()), std::abs(B.GetX()))); \ + EXPECT_NEAR(A.GetY(), B.GetY(), C * std::max(std::abs(A.GetY()), std::abs(B.GetY()))); \ + EXPECT_NEAR(A.GetZ(), B.GetZ(), C * std::max(std::abs(A.GetZ()), std::abs(B.GetZ()))); + TEST(DefaultConstructor, NoThrow) { EXPECT_NO_THROW(Path()); @@ -431,10 +439,10 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndByColumnDepth) { ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); P = Path(A, GeometryPosition(p0), GeometryPosition(p1)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); P = Path(A, GeometryPosition(inner_p0), GeometryPosition(inner_p1)); P.EnsureIntersections(); @@ -442,7 +450,7 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndByColumnDepth) { double extra_column_depth = extra_distance * rho * 100; P.ExtendFromEndByColumnDepth(extra_column_depth); extra_distance = A->DistanceForColumnDepthFromPoint(inner_p1_det, direction_det, extra_column_depth); - EXPECT_DOUBLE_EQ(distance/3.0, extra_distance); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); Vector3D end = inner_p1_det + direction_det.get() * extra_distance; EXPECT_NEAR((end - P.GetLastPoint()).magnitude(), 0, 1e-8); EXPECT_EQ(distance + extra_distance, P.GetDistance()); @@ -453,7 +461,7 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndByColumnDepth) { extra_column_depth = extra_distance * rho * 100; P.ExtendFromEndByColumnDepth(extra_column_depth); extra_distance = A->DistanceForColumnDepthFromPoint(inner_p1_det, direction_det, extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); end = inner_p1_det + direction_det.get() * extra_distance; EXPECT_NEAR((end - P.GetLastPoint()).magnitude(), 0, 1e-8); EXPECT_EQ(distance + extra_distance, P.GetDistance()); @@ -464,7 +472,7 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndByColumnDepth) { extra_column_depth = extra_distance * rho * 100; P.ExtendFromEndByColumnDepth(extra_column_depth); extra_distance = A->DistanceForColumnDepthFromPoint(inner_p1_det, direction_det, extra_column_depth); - EXPECT_DOUBLE_EQ(-distance*1.5, extra_distance); + EXPECT_NEAR_REL(-distance*1.5, extra_distance, 1e-8); end = inner_p1_det + direction_det.get() * extra_distance; EXPECT_NEAR((inner_p0_det - P.GetLastPoint())->magnitude(), 0, 1e-8); EXPECT_EQ(0, P.GetDistance()); @@ -524,61 +532,65 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromStartByColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); - Vector3D direction = p1 - p0; + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); + Vector3D direction = p1_det - p0_det; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); ASSERT_TRUE(inner_p1.magnitude() < max_radius); - direction = inner_p1 - inner_p0; + direction = inner_p1_det - inner_p0_det; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double extra_column_depth = extra_distance * rho * 100; - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(-direction), extra_column_depth); - ASSERT_DOUBLE_EQ(distance/3.0, extra_distance); - ASSERT_DOUBLE_EQ(A->DistanceForColumnDepthFromPoint(P.GetFirstPoint(), DetectorDirection(-direction), extra_column_depth), A->DistanceForColumnDepthFromPoint(P.GetIntersections(), P.GetFirstPoint(), DetectorDirection(-direction), extra_column_depth)); - ASSERT_DOUBLE_EQ(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth)); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); + EXPECT_NEAR_REL(A->DistanceForColumnDepthFromPoint(P.GetFirstPoint(), DetectorDirection(-direction), extra_column_depth), A->DistanceForColumnDepthFromPoint(P.GetIntersections(), P.GetFirstPoint(), DetectorDirection(-direction), extra_column_depth), 1e-8); + EXPECT_NEAR_REL(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth), 1e-8); P.ExtendFromStartByColumnDepth(extra_column_depth); - Vector3D end = inner_p0 - direction * extra_distance; - ASSERT_EQ(end, P.GetFirstPoint()); + Vector3D end = inner_p0_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetFirstPoint()), 1e-8); ASSERT_EQ(distance + extra_distance, P.GetDistance()); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; extra_column_depth = extra_distance * rho * 100; P.ExtendFromStartByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); - end = inner_p0 - direction * extra_distance; - EXPECT_EQ(end, P.GetFirstPoint()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); + end = inner_p0_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetFirstPoint()), 1e-8); EXPECT_EQ(distance + extra_distance, P.GetDistance()); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance*1.5; extra_column_depth = extra_distance * rho * 100; P.ExtendFromStartByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance*1.5, extra_distance); - end = inner_p0 - direction * extra_distance; - EXPECT_EQ(inner_p1, P.GetFirstPoint()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(-distance*1.5, extra_distance, 1e-8); + end = inner_p0_det - direction * extra_distance; + EXPECT_EQ(inner_p1_det, P.GetFirstPoint()); EXPECT_EQ(0, P.GetDistance()); } } @@ -635,11 +647,15 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromEndByColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -647,48 +663,48 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromEndByColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double extra_column_depth = extra_distance * rho * 100; P.ShrinkFromEndByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance/3.0, extra_distance); - Vector3D end = inner_p1 - direction * extra_distance; - EXPECT_EQ(end, P.GetLastPoint()); - EXPECT_EQ(distance - extra_distance, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); + Vector3D end = inner_p1_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(distance - extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; extra_column_depth = extra_distance * rho * 100; P.ShrinkFromEndByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); - end = inner_p1 - direction * extra_distance; - EXPECT_EQ(end, P.GetLastPoint()); - EXPECT_EQ(distance - extra_distance, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); + end = inner_p1_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(distance - extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = distance*1.5; extra_column_depth = extra_distance * rho * 100; P.ShrinkFromEndByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance*1.5, extra_distance); - end = inner_p1 - direction * extra_distance; - EXPECT_EQ(inner_p0, P.GetLastPoint()); - EXPECT_EQ(0, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance*1.5, extra_distance, 1e-8); + end = inner_p1_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p0_det, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(0.0, P.GetDistance(), 1e-8); } } @@ -745,11 +761,15 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromStartByColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); - Vector3D direction = p1 - p0; + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); + Vector3D direction = p1_det - p0_det; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -757,49 +777,49 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromStartByColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double extra_column_depth = extra_distance * rho * 100; - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), extra_column_depth); - ASSERT_DOUBLE_EQ(distance/3.0, extra_distance); - ASSERT_DOUBLE_EQ(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth)); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), extra_column_depth); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); + EXPECT_NEAR_REL(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth), 1e-8); P.ShrinkFromStartByColumnDepth(extra_column_depth); - Vector3D end = inner_p0 + direction * extra_distance; - ASSERT_EQ(end, P.GetFirstPoint()); - ASSERT_EQ(distance - extra_distance, P.GetDistance()); + Vector3D end = inner_p0_det + direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(distance - extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; extra_column_depth = extra_distance * rho * 100; P.ShrinkFromStartByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); - end = inner_p0 + direction * extra_distance; - EXPECT_EQ(end, P.GetFirstPoint()); - EXPECT_EQ(distance - extra_distance, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), extra_column_depth); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); + end = inner_p0_det + direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(end, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(distance - extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = distance*1.5; extra_column_depth = extra_distance * rho * 100; P.ShrinkFromStartByColumnDepth(extra_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance*1.5, extra_distance); - end = inner_p0 + direction * extra_distance; - EXPECT_EQ(inner_p1, P.GetFirstPoint()); - EXPECT_EQ(0, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), extra_column_depth); + EXPECT_NEAR_REL(distance*1.5, extra_distance, 1e-8); + end = inner_p0_det + direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p1_det, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(0.0, P.GetDistance(), 1e-8); } } @@ -858,11 +878,15 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndToColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -870,54 +894,54 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromEndToColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double target_distance = distance + extra_distance; double target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), target_column_depth); - ASSERT_DOUBLE_EQ(distance + distance/3.0, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth)); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), target_column_depth); + EXPECT_NEAR_REL(distance + distance/3.0, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth), 1e-8); P.ExtendFromEndToColumnDepth(target_column_depth); - Vector3D end = inner_p0 + direction * target_distance; + Vector3D end = inner_p0_det + direction * target_distance; ASSERT_TRUE((end - P.GetLastPoint()).magnitude() < 1e-6 * std::max(end.magnitude(), P.GetLastPoint()->magnitude())); - ASSERT_DOUBLE_EQ(distance + extra_distance, P.GetDistance()); + EXPECT_NEAR_REL(distance + extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; target_distance = distance + extra_distance; target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), target_column_depth); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), target_column_depth); P.ExtendFromEndToColumnDepth(target_column_depth); - ASSERT_DOUBLE_EQ(distance - distance/3.0, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth)); - end = inner_p0 + direction * target_distance; - ASSERT_EQ(inner_p1, P.GetLastPoint()); - ASSERT_DOUBLE_EQ(distance, P.GetDistance()); + EXPECT_NEAR_REL(distance - distance/3.0, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth), 1e-8); + end = inner_p0_det + direction * target_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p1_det, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance*1.5; target_distance = distance + extra_distance; target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), target_column_depth); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), target_column_depth); P.ExtendFromEndToColumnDepth(target_column_depth); - ASSERT_DOUBLE_EQ(distance - distance*1.5, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth)); - end = inner_p0 + direction * target_distance; - ASSERT_EQ(inner_p1, P.GetLastPoint()); - ASSERT_DOUBLE_EQ(distance, P.GetDistance()); + EXPECT_NEAR_REL(distance - distance*1.5, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromStartAlongPath(target_column_depth), 1e-8); + end = inner_p0_det + direction * target_distance; + ASSERT_EQ(inner_p1_det, P.GetLastPoint()); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); } } @@ -978,11 +1002,15 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromStartToColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -990,56 +1018,56 @@ TEST_F(FakeLegacyDetectorModelTest, ExtendFromStartToColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double target_distance = distance + extra_distance; double target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), target_column_depth); - ASSERT_DOUBLE_EQ(distance + distance/3.0, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromEndInReverse(target_column_depth)); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), target_column_depth); + EXPECT_NEAR_REL(distance + distance/3.0, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromEndInReverse(target_column_depth), 1e-8); P.ExtendFromStartToColumnDepth(target_column_depth); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ(target_column_depth, sum); - Vector3D end = inner_p1 - direction * target_distance; - ASSERT_DOUBLE_EQ(target_distance, P.GetDistance()); + EXPECT_NEAR_REL(target_column_depth, sum, 1e-8); + Vector3D end = inner_p1_det - direction * target_distance; + EXPECT_NEAR_REL(target_distance, P.GetDistance(), 1e-8); ASSERT_TRUE((end - P.GetFirstPoint()).magnitude() < 1e-6 * std::max(end.magnitude(), P.GetFirstPoint()->magnitude())); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; target_distance = distance + extra_distance; target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), target_column_depth); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), target_column_depth); P.ExtendFromStartToColumnDepth(target_column_depth); - ASSERT_DOUBLE_EQ(distance - distance/3.0, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromEndInReverse(target_column_depth)); - end = inner_p1 - direction * target_distance; - ASSERT_EQ(inner_p0, P.GetFirstPoint()); - ASSERT_DOUBLE_EQ(distance, P.GetDistance()); + EXPECT_NEAR_REL(distance - distance/3.0, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromEndInReverse(target_column_depth), 1e-8); + end = inner_p1_det - direction * target_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p0_det, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance*1.5; target_distance = distance + extra_distance; target_column_depth = target_distance * rho * 100; - target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), target_column_depth); + target_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), target_column_depth); P.ExtendFromStartToColumnDepth(target_column_depth); - ASSERT_DOUBLE_EQ(distance - distance*1.5, target_distance); - ASSERT_DOUBLE_EQ(target_distance, P.GetDistanceFromEndAlongPath(target_column_depth)); - end = inner_p1 - direction * target_distance; - ASSERT_EQ(inner_p0, P.GetFirstPoint()); - ASSERT_DOUBLE_EQ(distance, P.GetDistance()); + EXPECT_NEAR_REL(distance - distance*1.5, target_distance, 1e-8); + EXPECT_NEAR_REL(target_distance, P.GetDistanceFromEndAlongPath(target_column_depth), 1e-8); + end = inner_p1_det - direction * target_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p0_det, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); } } @@ -1098,11 +1126,15 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromEndToColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -1110,54 +1142,54 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromEndToColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double extra_column_depth = extra_distance * rho * 100; double target_distance = distance - extra_distance; double target_column_depth = target_distance * rho * 100; P.ShrinkFromEndToColumnDepth(target_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance/3.0, extra_distance); - Vector3D end = inner_p1 - direction * extra_distance; + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); + Vector3D end = inner_p1_det - direction * extra_distance; ASSERT_TRUE((end - P.GetLastPoint()).magnitude() < 1e-6 * std::max(end.magnitude(), P.GetLastPoint()->magnitude())); - EXPECT_DOUBLE_EQ(distance - extra_distance, P.GetDistance()); + EXPECT_NEAR_REL(distance - extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; extra_column_depth = extra_distance * rho * 100; target_distance = distance - extra_distance; target_column_depth = target_distance * rho * 100; P.ShrinkFromEndToColumnDepth(target_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); - end = inner_p1 - direction * extra_distance; - EXPECT_EQ(inner_p1, P.GetLastPoint()); - EXPECT_DOUBLE_EQ(distance, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); + end = inner_p1_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p1_det, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = distance*1.5; extra_column_depth = extra_distance * rho * 100; target_distance = distance - extra_distance; target_column_depth = target_distance * rho * 100; P.ShrinkFromEndToColumnDepth(target_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance*1.5, extra_distance); - end = inner_p1 - direction * extra_distance; - EXPECT_EQ(inner_p0, P.GetLastPoint()); - EXPECT_DOUBLE_EQ(0, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p1_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance*1.5, extra_distance, 1e-8); + end = inner_p1_det - direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p0_det, Vector3D(P.GetLastPoint()), 1e-8); + EXPECT_NEAR_REL(0.0, P.GetDistance(), 1e-8); } } @@ -1217,11 +1249,15 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromStartToColumnDepth) { double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); ASSERT_TRUE(p0.magnitude() < max_radius); ASSERT_TRUE(p1.magnitude() < max_radius); ASSERT_TRUE(inner_p0.magnitude() < max_radius); @@ -1229,55 +1265,55 @@ TEST_F(FakeLegacyDetectorModelTest, ShrinkFromStartToColumnDepth) { direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); - P = Path(A, DetectorPosition(p0), DetectorPosition(p1)); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); + P = Path(A, DetectorPosition(p0_det), DetectorPosition(p1_det)); sum = P.GetColumnDepthInBounds(); - ASSERT_DOUBLE_EQ((p1 - p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((p1 - p0).magnitude() * rho * 100, sum, 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); double extra_distance = distance/3.0; double target_distance = distance + extra_distance; double extra_column_depth = extra_distance * rho * 100; double target_column_depth = target_distance * rho * 100; - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(-direction), extra_column_depth); - ASSERT_DOUBLE_EQ(distance/3.0, extra_distance); - ASSERT_DOUBLE_EQ(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth)); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(distance/3.0, extra_distance, 1e-8); + EXPECT_NEAR_REL(extra_distance, P.GetDistanceFromStartInReverse(extra_column_depth), 1e-8); P.ShrinkFromStartToColumnDepth(target_column_depth); - Vector3D end = inner_p0 + direction * extra_distance; - ASSERT_EQ(inner_p0, P.GetFirstPoint()); - ASSERT_EQ(distance, P.GetDistance()); + Vector3D end = inner_p0_det + direction * extra_distance; + EXPECT_VECTOR3D_NEAR_REL(inner_p0_det, Vector3D(P.GetFirstPoint()), 1e-8); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = -distance/3.0; target_distance = distance + extra_distance; extra_column_depth = extra_distance * rho * 100; target_column_depth = target_distance * rho * 100; P.ShrinkFromStartToColumnDepth(target_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(-direction), extra_column_depth); - EXPECT_DOUBLE_EQ(-distance/3.0, extra_distance); - end = inner_p0 - direction * extra_distance; + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(-direction), extra_column_depth); + EXPECT_NEAR_REL(-distance/3.0, extra_distance, 1e-8); + end = inner_p0_det - direction * extra_distance; ASSERT_TRUE((end - P.GetFirstPoint()).magnitude() < 1e-6 * std::max(end.magnitude(), P.GetFirstPoint()->magnitude())); - EXPECT_DOUBLE_EQ(distance + extra_distance, P.GetDistance()); + EXPECT_NEAR_REL(distance + extra_distance, P.GetDistance(), 1e-8); - P = Path(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + P = Path(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); P.EnsureIntersections(); extra_distance = distance*1.5; target_distance = distance + extra_distance; extra_column_depth = extra_distance * rho * 100; target_column_depth = target_distance * rho * 100; P.ShrinkFromStartToColumnDepth(target_column_depth); - extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0), DetectorDirection(direction), extra_column_depth); - EXPECT_DOUBLE_EQ(distance*1.5, extra_distance); - end = inner_p0 + direction * extra_distance; - ASSERT_TRUE((inner_p0 - P.GetFirstPoint()).magnitude() < 1e-6 * std::max(inner_p0.magnitude(), P.GetFirstPoint()->magnitude())); - EXPECT_EQ(distance, P.GetDistance()); + extra_distance = A->DistanceForColumnDepthFromPoint(DetectorPosition(inner_p0_det), DetectorDirection(direction), extra_column_depth); + EXPECT_NEAR_REL(distance*1.5, extra_distance, 1e-8); + end = inner_p0_det + direction * extra_distance; + ASSERT_TRUE((inner_p0_det - P.GetFirstPoint()).magnitude() < 1e-6 * std::max(inner_p0.magnitude(), P.GetFirstPoint()->magnitude())); + EXPECT_NEAR_REL(distance, P.GetDistance(), 1e-8); } } @@ -1302,17 +1338,21 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthInBounds) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); double sum = P.GetColumnDepthInBounds(); - EXPECT_DOUBLE_EQ((inner_p1 - inner_p0).magnitude() * rho * 100, sum); + EXPECT_NEAR_REL((inner_p1 - inner_p0).magnitude() * rho * 100, sum, 1e-8); } } @@ -1337,15 +1377,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromStartInBounds) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1358,12 +1402,12 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromStartInBounds) target_distance = -distance / 3.0; target_column_depth = target_distance * rho * 100; sum = P.GetColumnDepthFromStartInBounds(target_distance); - EXPECT_DOUBLE_EQ(0, sum); + EXPECT_NEAR_REL(0.0, sum, 1e-8); target_distance = distance * 1.5; target_column_depth = target_distance * rho * 100; sum = P.GetColumnDepthFromStartInBounds(target_distance); - EXPECT_DOUBLE_EQ(distance * rho * 100, sum); + EXPECT_NEAR_REL(distance * rho * 100, sum, 1e-8); } } @@ -1388,15 +1432,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromEndInBounds) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1409,12 +1457,12 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromEndInBounds) target_distance = -distance / 3.0; target_column_depth = target_distance * rho * 100; sum = P.GetColumnDepthFromEndInBounds(target_distance); - EXPECT_DOUBLE_EQ(0, sum); + EXPECT_NEAR_REL(0.0, sum, 1e-8); target_distance = distance * 1.5; target_column_depth = target_distance * rho * 100; sum = P.GetColumnDepthFromEndInBounds(target_distance); - EXPECT_DOUBLE_EQ(distance * rho * 100, sum); + EXPECT_NEAR_REL(distance * rho * 100, sum, 1e-8); } } @@ -1439,15 +1487,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromStartAlongPath) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1490,15 +1542,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromEndAlongPath) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1541,15 +1597,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromStartInReverse) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1592,15 +1652,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetColumnDepthFromEndInReverse) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1645,15 +1709,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromStartInBounds) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1666,12 +1734,12 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromStartInBounds) target_distance = -distance / 3.0; target_column_depth = target_distance * rho * 100; sum = P.GetDistanceFromStartInBounds(target_column_depth); - EXPECT_DOUBLE_EQ(0, sum); + EXPECT_NEAR_REL(0.0, sum, 1e-8); target_distance = distance * 1.5; target_column_depth = target_distance * rho * 100; sum = P.GetDistanceFromStartInBounds(target_column_depth); - EXPECT_DOUBLE_EQ(distance, sum); + EXPECT_NEAR_REL(distance, sum, 1e-8); } } @@ -1696,15 +1764,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromEndInBounds) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1717,12 +1789,12 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromEndInBounds) target_distance = -distance / 3.0; target_column_depth = target_distance * rho * 100; sum = P.GetDistanceFromEndInBounds(target_column_depth); - EXPECT_DOUBLE_EQ(0, sum); + EXPECT_NEAR_REL(0.0, sum, 1e-8); target_distance = distance * 1.5; target_column_depth = target_distance * rho * 100; sum = P.GetDistanceFromEndInBounds(target_column_depth); - EXPECT_DOUBLE_EQ(distance, sum); + EXPECT_NEAR_REL(distance, sum, 1e-8); } } @@ -1747,15 +1819,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromStartAlongPath) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1798,15 +1874,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromEndAlongPath) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1849,15 +1929,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromStartInReverse) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); @@ -1900,15 +1984,19 @@ TEST_F(FakeLegacyDetectorModelTest, GetDistanceFromEndInReverse) double min_radius = sphere->GetInnerRadius(); Vector3D p0 = RandomVector(max_radius, min_radius); Vector3D p1 = RandomVector(max_radius, min_radius); + Vector3D p0_det = A->ToDet(GeometryPosition(p0)); + Vector3D p1_det = A->ToDet(GeometryPosition(p1)); Vector3D direction = p1 - p0; double distance = direction.magnitude(); direction.normalize(); Vector3D inner_p0 = p0 + direction * distance / 4.0; Vector3D inner_p1 = p1 - direction * distance / 4.0; + Vector3D inner_p0_det = A->ToDet(GeometryPosition(inner_p0)); + Vector3D inner_p1_det = A->ToDet(GeometryPosition(inner_p1)); direction = inner_p1 - inner_p0; distance = direction.magnitude(); direction.normalize(); - Path P(A, DetectorPosition(inner_p0), DetectorPosition(inner_p1)); + Path P(A, DetectorPosition(inner_p0_det), DetectorPosition(inner_p1_det)); DensityDistribution1D const * density = dynamic_cast const *>(sector.density.get()); ASSERT_TRUE(density); double rho = density->Evaluate(Vector3D()); diff --git a/projects/distributions/CMakeLists.txt b/projects/distributions/CMakeLists.txt index 2dfbe3cce..d07b6f1e0 100644 --- a/projects/distributions/CMakeLists.txt +++ b/projects/distributions/CMakeLists.txt @@ -16,7 +16,7 @@ LIST (APPEND distributions_SOURCES ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/helicity/PrimaryNeutrinoHelicityDistribution.cxx - ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/type/PrimaryInjector.cxx + ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/mass/PrimaryMass.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/RangeFunction.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/DecayRangeFunction.cxx @@ -24,15 +24,15 @@ LIST (APPEND distributions_SOURCES ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/LeptonDepthFunction.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/VertexPositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/PointSourcePositionDistribution.cxx - ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/SecondaryPositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/RangePositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/DecayRangePositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/OrientedCylinderPositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/CylinderVolumePositionDistribution.cxx ${PROJECT_SOURCE_DIR}/projects/distributions/private/primary/vertex/ColumnDepthPositionDistribution.cxx - ${PROJECT_SOURCE_DIR}/projects/distributions/private/target/momentum/TargetMomentumDistribution.cxx - + ${PROJECT_SOURCE_DIR}/projects/distributions/private/secondary/vertex/SecondaryVertexPositionDistribution.cxx + ${PROJECT_SOURCE_DIR}/projects/distributions/private/secondary/vertex/SecondaryPhysicalVertexDistribution.cxx + ${PROJECT_SOURCE_DIR}/projects/distributions/private/secondary/vertex/SecondaryBoundedVertexDistribution.cxx ) add_library(LI_distributions OBJECT ${distributions_SOURCES}) set_property(TARGET LI_distributions PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/projects/distributions/private/Distributions.cxx b/projects/distributions/private/Distributions.cxx index b0c032857..11486c04e 100644 --- a/projects/distributions/private/Distributions.cxx +++ b/projects/distributions/private/Distributions.cxx @@ -57,10 +57,6 @@ bool WeightableDistribution::AreEquivalent(std::shared_ptroperator==(*distribution); } -double WeightableDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const { - return GenerationProbability(detector_model, interactions, datum.record); -} - //--------------- // class NormalizationConstant : WeightableDistribution, PhysicallyNormalizedDistribution //--------------- @@ -91,16 +87,5 @@ bool NormalizationConstant::less(WeightableDistribution const & distribution) co return normalizationGetNormalization(); } -//--------------- -// class InjectionDistribution -//--------------- - -void InjectionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { -} - -void InjectionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const { - Sample(rand, detector_model, interactions, datum.record); -} - } // namespace distributions } // namespace LeptonInjector diff --git a/projects/distributions/private/primary/direction/Cone.cxx b/projects/distributions/private/primary/direction/Cone.cxx index d438afd54..13c48a50a 100644 --- a/projects/distributions/private/primary/direction/Cone.cxx +++ b/projects/distributions/private/primary/direction/Cone.cxx @@ -34,7 +34,7 @@ Cone::Cone(LI::math::Vector3D dir, double opening_angle) : dir(dir), opening_ang } } -LI::math::Vector3D Cone::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const{ +LI::math::Vector3D Cone::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const{ double theta = acos(rand->Uniform(cos(opening_angle), 1)); double phi = rand->Uniform(0, 2.0 * M_PI); LI::math::Quaternion q; @@ -57,8 +57,8 @@ double Cone::GenerationProbability(std::shared_ptr Cone::clone() const { - return std::shared_ptr(new Cone(*this)); +std::shared_ptr Cone::clone() const { + return std::shared_ptr(new Cone(*this)); } std::string Cone::Name() const { diff --git a/projects/distributions/private/primary/direction/FixedDirection.cxx b/projects/distributions/private/primary/direction/FixedDirection.cxx index e552fae3a..212a45fce 100644 --- a/projects/distributions/private/primary/direction/FixedDirection.cxx +++ b/projects/distributions/private/primary/direction/FixedDirection.cxx @@ -19,7 +19,7 @@ namespace distributions { //--------------- // class FixedDirection : PrimaryDirectionDistribution //--------------- -LI::math::Vector3D FixedDirection::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +LI::math::Vector3D FixedDirection::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { return dir; } @@ -36,8 +36,8 @@ std::vector FixedDirection::DensityVariables() const { return std::vector(); } -std::shared_ptr FixedDirection::clone() const { - return std::shared_ptr(new FixedDirection(*this)); +std::shared_ptr FixedDirection::clone() const { + return std::shared_ptr(new FixedDirection(*this)); } std::string FixedDirection::Name() const { diff --git a/projects/distributions/private/primary/direction/IsotropicDirection.cxx b/projects/distributions/private/primary/direction/IsotropicDirection.cxx index c3ccfb181..d4269128a 100644 --- a/projects/distributions/private/primary/direction/IsotropicDirection.cxx +++ b/projects/distributions/private/primary/direction/IsotropicDirection.cxx @@ -8,7 +8,7 @@ #include "LeptonInjector/utilities/Random.h" // for LI_random namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { @@ -17,7 +17,7 @@ namespace distributions { //--------------- // class IsotropicDirection : PrimaryDirectionDistribution //--------------- -LI::math::Vector3D IsotropicDirection::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +LI::math::Vector3D IsotropicDirection::SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { double nz = rand->Uniform(-1, 1); double nr = sqrt(1.0 - nz*nz); double phi = rand->Uniform(-M_PI, M_PI); @@ -32,8 +32,8 @@ double IsotropicDirection::GenerationProbability(std::shared_ptr IsotropicDirection::clone() const { - return std::shared_ptr(new IsotropicDirection(*this)); +std::shared_ptr IsotropicDirection::clone() const { + return std::shared_ptr(new IsotropicDirection(*this)); } std::string IsotropicDirection::Name() const { diff --git a/projects/distributions/private/primary/direction/PrimaryDirectionDistribution.cxx b/projects/distributions/private/primary/direction/PrimaryDirectionDistribution.cxx index b0938a58c..72ff89926 100644 --- a/projects/distributions/private/primary/direction/PrimaryDirectionDistribution.cxx +++ b/projects/distributions/private/primary/direction/PrimaryDirectionDistribution.cxx @@ -11,16 +11,11 @@ namespace LI { namespace distributions { //--------------- -// class PrimaryDirectionDistribution : InjectionDistribution +// class PrimaryDirectionDistribution : PrimaryInjectionDistribution //--------------- -void PrimaryDirectionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { +void PrimaryDirectionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { LI::math::Vector3D dir = SampleDirection(rand, detector_model, interactions, record); - double energy = record.primary_momentum[0]; - double mass = record.primary_mass; - double momentum = std::sqrt(energy*energy - mass*mass); - record.primary_momentum[1] = momentum * dir.GetX(); - record.primary_momentum[2] = momentum * dir.GetY(); - record.primary_momentum[3] = momentum * dir.GetZ(); + record.SetDirection(dir); } std::vector PrimaryDirectionDistribution::DensityVariables() const { diff --git a/projects/distributions/private/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.cxx b/projects/distributions/private/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.cxx index 06256c05a..847a4d810 100644 --- a/projects/distributions/private/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.cxx +++ b/projects/distributions/private/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.cxx @@ -62,7 +62,7 @@ ModifiedMoyalPlusExponentialEnergyDistribution::ModifiedMoyalPlusExponentialEner } } -double ModifiedMoyalPlusExponentialEnergyDistribution::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +double ModifiedMoyalPlusExponentialEnergyDistribution::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { // Metropolis-Hastings algorithm to sample from PDF. // Pass in a function pointer for the PDF @@ -100,8 +100,8 @@ std::string ModifiedMoyalPlusExponentialEnergyDistribution::Name() const { return "ModifiedMoyalPlusExponentialEnergyDistribution"; } -std::shared_ptr ModifiedMoyalPlusExponentialEnergyDistribution::clone() const { - return std::shared_ptr(new ModifiedMoyalPlusExponentialEnergyDistribution(*this)); +std::shared_ptr ModifiedMoyalPlusExponentialEnergyDistribution::clone() const { + return std::shared_ptr(new ModifiedMoyalPlusExponentialEnergyDistribution(*this)); } bool ModifiedMoyalPlusExponentialEnergyDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/energy/Monoenergetic.cxx b/projects/distributions/private/primary/energy/Monoenergetic.cxx index ccebd7a40..024525651 100644 --- a/projects/distributions/private/primary/energy/Monoenergetic.cxx +++ b/projects/distributions/private/primary/energy/Monoenergetic.cxx @@ -23,7 +23,7 @@ Monoenergetic::Monoenergetic(double gen_energy) : gen_energy(gen_energy) {} -double Monoenergetic::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +double Monoenergetic::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { return gen_energy; } @@ -41,8 +41,8 @@ std::string Monoenergetic::Name() const { return "Monoenergetic"; } -std::shared_ptr Monoenergetic::clone() const { - return std::shared_ptr(new Monoenergetic(*this)); +std::shared_ptr Monoenergetic::clone() const { + return std::shared_ptr(new Monoenergetic(*this)); } bool Monoenergetic::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/energy/PowerLaw.cxx b/projects/distributions/private/primary/energy/PowerLaw.cxx index 4b9f0bee6..0486cbd11 100644 --- a/projects/distributions/private/primary/energy/PowerLaw.cxx +++ b/projects/distributions/private/primary/energy/PowerLaw.cxx @@ -24,7 +24,7 @@ PowerLaw::PowerLaw(double powerLawIndex, double energyMin, double energyMax) , energyMax(energyMax) {} -double PowerLaw::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +double PowerLaw::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { if(energyMin == energyMax) return energyMin; //return the only allowed energy @@ -56,8 +56,8 @@ std::string PowerLaw::Name() const { return "PowerLaw"; } -std::shared_ptr PowerLaw::clone() const { - return std::shared_ptr(new PowerLaw(*this)); +std::shared_ptr PowerLaw::clone() const { + return std::shared_ptr(new PowerLaw(*this)); } bool PowerLaw::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/energy/PrimaryEnergyDistribution.cxx b/projects/distributions/private/primary/energy/PrimaryEnergyDistribution.cxx index adbe20c3c..64a940049 100644 --- a/projects/distributions/private/primary/energy/PrimaryEnergyDistribution.cxx +++ b/projects/distributions/private/primary/energy/PrimaryEnergyDistribution.cxx @@ -9,14 +9,16 @@ namespace LI { namespace distributions { //--------------- -// class PrimaryEnergyDistribution : InjectionDistribution +// class PrimaryEnergyDistribution : PrimaryInjectionDistribution //--------------- void PrimaryEnergyDistribution::Sample( std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, - LI::dataclasses::InteractionRecord & record) const { - record.primary_momentum[0] = SampleEnergy(rand, detector_model, interactions, record); + LI::dataclasses::PrimaryDistributionRecord & record) const { + + double energy = SampleEnergy(rand, detector_model, interactions, record); + record.SetEnergy(energy); } std::vector PrimaryEnergyDistribution::DensityVariables() const { diff --git a/projects/distributions/private/primary/energy/TabulatedFluxDistribution.cxx b/projects/distributions/private/primary/energy/TabulatedFluxDistribution.cxx index 4acfd8ccc..3e10bb1bf 100644 --- a/projects/distributions/private/primary/energy/TabulatedFluxDistribution.cxx +++ b/projects/distributions/private/primary/energy/TabulatedFluxDistribution.cxx @@ -213,7 +213,7 @@ TabulatedFluxDistribution::TabulatedFluxDistribution(double energyMin, double en ComputeCDF(); } -double TabulatedFluxDistribution::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +double TabulatedFluxDistribution::SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { // inverse CDF algorithm to sample from PDF. double randomValue = rand->Uniform(0,1); @@ -233,8 +233,8 @@ std::string TabulatedFluxDistribution::Name() const { return "TabulatedFluxDistribution"; } -std::shared_ptr TabulatedFluxDistribution::clone() const { - return std::shared_ptr(new TabulatedFluxDistribution(*this)); +std::shared_ptr TabulatedFluxDistribution::clone() const { + return std::shared_ptr(new TabulatedFluxDistribution(*this)); } bool TabulatedFluxDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/helicity/PrimaryNeutrinoHelicityDistribution.cxx b/projects/distributions/private/primary/helicity/PrimaryNeutrinoHelicityDistribution.cxx index 9221773f4..a1f1a8a83 100644 --- a/projects/distributions/private/primary/helicity/PrimaryNeutrinoHelicityDistribution.cxx +++ b/projects/distributions/private/primary/helicity/PrimaryNeutrinoHelicityDistribution.cxx @@ -14,14 +14,14 @@ namespace LI { namespace distributions { //--------------- -// class PrimaryNeutrinoHelicityDistribution : InjectionDistribution +// class PrimaryNeutrinoHelicityDistribution : PrimaryInjectionDistribution //--------------- -void PrimaryNeutrinoHelicityDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::dataclasses::Particle::ParticleType & t = record.signature.primary_type; - if(t > 0) // Particles are left handed, anti-particles are right handed - record.primary_helicity = -0.5; +void PrimaryNeutrinoHelicityDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::dataclasses::Particle::ParticleType const & t = record.type; + if(static_cast(t) > 0) // Particles are left handed, anti-particles are right handed + record.SetHelicity(-0.5); else - record.primary_helicity = 0.5; + record.SetHelicity(0.5); } double PrimaryNeutrinoHelicityDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { @@ -34,7 +34,7 @@ double PrimaryNeutrinoHelicityDistribution::GenerationProbability(std::shared_pt LI::dataclasses::Particle::ParticleType const & t = record.signature.primary_type; // Particles are left handed, anti-particles are right handed - if(t > 0) { + if(static_cast(t) > 0) { if(record.primary_helicity < 0) // expect opposite direction return 1.0; else @@ -57,7 +57,7 @@ std::string PrimaryNeutrinoHelicityDistribution::Name() const { return "PrimaryNeutrinoHelicityDistribution"; } -std::shared_ptr PrimaryNeutrinoHelicityDistribution::clone() const { +std::shared_ptr PrimaryNeutrinoHelicityDistribution::clone() const { return std::shared_ptr(new PrimaryNeutrinoHelicityDistribution(*this)); } diff --git a/projects/distributions/private/primary/mass/PrimaryMass.cxx b/projects/distributions/private/primary/mass/PrimaryMass.cxx new file mode 100644 index 000000000..e0227b5b6 --- /dev/null +++ b/projects/distributions/private/primary/mass/PrimaryMass.cxx @@ -0,0 +1,71 @@ +#include "LeptonInjector/distributions/primary/mass/PrimaryMass.h" + +#include // for tie +#include // for basic_s... +#include // for operator<< +#include // for abs + +#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Interac... +#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Interac... +#include "LeptonInjector/dataclasses/Particle.h" // for Particle +#include "LeptonInjector/distributions/Distributions.h" // for Injecti... + +namespace LI { +namespace distributions { + +//--------------- +// class PrimaryMass : PrimaryInjectionDistribution +//--------------- + +PrimaryMass::PrimaryMass(double primary_mass) : + primary_mass(primary_mass) +{} + +double PrimaryMass::GetPrimaryMass() const { + return primary_mass; +} + +void PrimaryMass::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + record.SetMass(primary_mass); +} + +double PrimaryMass::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { + if(2.0 * abs(record.primary_mass - primary_mass) / (record.primary_mass + primary_mass) > 1e-9) { + std::cerr << "Event primary mass does not match injector primary mass!" << std::endl; + std::cerr << "Event primary_mass: " << record.primary_mass << std::endl; + std::cerr << "Injector primary_mass: " << primary_mass << std::endl; + std::cerr << "Particle mass definitions should be consistent." << std::endl; + std::cerr << "Are you using the wrong simulation?" << std::endl; + return 0.0; + } + return 1.0; +} + +std::vector PrimaryMass::DensityVariables() const { + return std::vector{}; +} + +std::string PrimaryMass::Name() const { + return "PrimaryMass"; +} + +std::shared_ptr PrimaryMass::clone() const { + return std::shared_ptr(new PrimaryMass(*this)); +} + +bool PrimaryMass::equal(WeightableDistribution const & other) const { + const PrimaryMass* x = dynamic_cast(&other); + + if(!x) + return false; + else + return primary_mass == x->primary_mass; +} + +bool PrimaryMass::less(WeightableDistribution const & other) const { + const PrimaryMass* x = dynamic_cast(&other); + return primary_mass == x->primary_mass; +} + +} // namespace distributions +} // namespace LeptonInjector diff --git a/projects/distributions/private/primary/type/PrimaryInjector.cxx b/projects/distributions/private/primary/type/PrimaryInjector.cxx deleted file mode 100644 index a4ec476aa..000000000 --- a/projects/distributions/private/primary/type/PrimaryInjector.cxx +++ /dev/null @@ -1,84 +0,0 @@ -#include "LeptonInjector/distributions/primary/type/PrimaryInjector.h" - -#include // for tie -#include // for basic_s... -#include // for operator<< -#include // for abs - -#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Interac... -#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Interac... -#include "LeptonInjector/dataclasses/Particle.h" // for Particle -#include "LeptonInjector/distributions/Distributions.h" // for Injecti... - -namespace LI { -namespace distributions { - -//--------------- -// class PrimaryInjector : InjectionDistribution -//--------------- - -PrimaryInjector::PrimaryInjector(LI::dataclasses::Particle::ParticleType primary_type, double primary_mass) : - primary_type(primary_type), - primary_mass(primary_mass) -{} - -LI::dataclasses::Particle::ParticleType PrimaryInjector::PrimaryType() const { - return primary_type; -} - -double PrimaryInjector::PrimaryMass() const { - return primary_mass; -} - -void PrimaryInjector::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - record.signature.primary_type = primary_type; - record.primary_mass = primary_mass; -} -double PrimaryInjector::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { - if(record.signature.primary_type != primary_type) - return 0.0; - if(2.0 * abs(record.primary_mass - primary_mass) / (record.primary_mass + primary_mass) > 1e-9) { - std::cerr << "Event primary mass does not match injector primary mass!" << std::endl; - std::cerr << "Event primary_mass: " << record.primary_mass << std::endl; - std::cerr << "Injector primary_mass: " << primary_mass << std::endl; - std::cerr << "Particle mass definitions should be consistent." << std::endl; - std::cerr << "Are you using the wrong simulation?" << std::endl; - return 0.0; - } - return 1.0; -} - -std::vector PrimaryInjector::DensityVariables() const { - return std::vector{}; -} - -std::string PrimaryInjector::Name() const { - return "PrimaryInjector"; -} - -std::shared_ptr PrimaryInjector::clone() const { - return std::shared_ptr(new PrimaryInjector(*this)); -} - -bool PrimaryInjector::equal(WeightableDistribution const & other) const { - const PrimaryInjector* x = dynamic_cast(&other); - - if(!x) - return false; - else - return - std::tie(primary_type, primary_mass) - == - std::tie(x->primary_type, x->primary_mass); -} - -bool PrimaryInjector::less(WeightableDistribution const & other) const { - const PrimaryInjector* x = dynamic_cast(&other); - return - std::tie(primary_type, primary_mass) - < - std::tie(x->primary_type, x->primary_mass); -} - -} // namespace distributions -} // namespace LeptonInjector diff --git a/projects/distributions/private/primary/vertex/ColumnDepthPositionDistribution.cxx b/projects/distributions/private/primary/vertex/ColumnDepthPositionDistribution.cxx index 04d1fcca5..3e85d10ce 100644 --- a/projects/distributions/private/primary/vertex/ColumnDepthPositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/ColumnDepthPositionDistribution.cxx @@ -56,12 +56,12 @@ LI::math::Vector3D ColumnDepthPositionDistribution::SampleFromDisk(std::shared_p return q.rotate(pos, false); } -LI::math::Vector3D ColumnDepthPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); +std::tuple ColumnDepthPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::math::Vector3D dir(record.GetDirection()); dir.normalize(); LI::math::Vector3D pca = SampleFromDisk(rand, dir); - double lepton_depth = (*depth_function)(record.signature, record.primary_momentum[0]);//note: return is in cgs units!!! + double lepton_depth = (*depth_function)(record.type, record.GetEnergy());//note: return is in cgs units!!! LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -74,15 +74,17 @@ LI::math::Vector3D ColumnDepthPositionDistribution::SamplePosition(std::shared_p std::vector targets(possible_targets.begin(), possible_targets.end()); std::vector total_cross_sections(targets.size(), 0.0); - double total_decay_length = interactions->TotalDecayLength(record); - LI::dataclasses::InteractionRecord fake_record = record; + LI::dataclasses::InteractionRecord fake_record; + fake_record.signature.primary_type = record.type; + fake_record.primary_mass = record.GetMass(); + fake_record.primary_momentum[0] = record.GetEnergy(); + double total_decay_length = interactions->TotalDecayLength(fake_record); for(unsigned int i=0; iGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -101,15 +103,16 @@ LI::math::Vector3D ColumnDepthPositionDistribution::SamplePosition(std::shared_p } double dist = path.GetDistanceFromStartAlongPath(traversed_interaction_depth, targets, total_cross_sections, total_decay_length); + LI::math::Vector3D init_pos = path.GetFirstPoint(); LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); - return vertex; + return {init_pos, vertex}; } // public getter function for the private SamplePosition function (for debugging) -LI::math::Vector3D ColumnDepthPositionDistribution::GetSamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) { +std::tuple ColumnDepthPositionDistribution::GetSamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) { - LI::math::Vector3D samplepos = ColumnDepthPositionDistribution::SamplePosition(rand, detector_model, interactions, record); + std::tuple samplepos = ColumnDepthPositionDistribution::SamplePosition(rand, detector_model, interactions, record); return samplepos; } @@ -123,8 +126,7 @@ double ColumnDepthPositionDistribution::GenerationProbability(std::shared_ptr
  • = radius) return 0.0; - double lepton_depth = (*depth_function)(record.signature, record.primary_momentum[0]); - + double lepton_depth = (*depth_function)(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - (endcap_length * dir); LI::math::Vector3D endcap_1 = pca + (endcap_length * dir); @@ -147,9 +149,8 @@ double ColumnDepthPositionDistribution::GenerationProbability(std::shared_ptr
  • GetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -178,20 +179,20 @@ std::string ColumnDepthPositionDistribution::Name() const { return "ColumnDepthPositionDistribution"; } -std::shared_ptr ColumnDepthPositionDistribution::clone() const { - return std::shared_ptr(new ColumnDepthPositionDistribution(*this)); +std::shared_ptr ColumnDepthPositionDistribution::clone() const { + return std::shared_ptr(new ColumnDepthPositionDistribution(*this)); } -std::pair ColumnDepthPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +std::tuple ColumnDepthPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); dir.normalize(); LI::math::Vector3D vertex(record.interaction_vertex); // m LI::math::Vector3D pca = vertex - dir * LI::math::scalar_product(dir, vertex); if(pca.magnitude() >= radius) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - double lepton_depth = (*depth_function)(record.signature, record.primary_momentum[0]); + double lepton_depth = (*depth_function)(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -199,7 +200,7 @@ std::pair ColumnDepthPositionDistributio LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), endcap_length*2); path.ExtendFromStartByColumnDepth(lepton_depth); path.ClipToOuterBounds(); - return std::pair(path.GetFirstPoint(), path.GetLastPoint()); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); } bool ColumnDepthPositionDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/vertex/CylinderVolumePositionDistribution.cxx b/projects/distributions/private/primary/vertex/CylinderVolumePositionDistribution.cxx index 0ff9db99a..7f7921e49 100644 --- a/projects/distributions/private/primary/vertex/CylinderVolumePositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/CylinderVolumePositionDistribution.cxx @@ -21,7 +21,7 @@ namespace distributions { //--------------- // class CylinderVolumePositionDistribution : public VertexPositionDistribution //--------------- -LI::math::Vector3D CylinderVolumePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { +std::tuple CylinderVolumePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { double t = rand->Uniform(0, 2 * M_PI); const double outer_radius = cylinder.GetRadius(); const double inner_radius = cylinder.GetInnerRadius(); @@ -29,7 +29,23 @@ LI::math::Vector3D CylinderVolumePositionDistribution::SamplePosition(std::share double r = std::sqrt(rand->Uniform(inner_radius*inner_radius, outer_radius*outer_radius)); double z = rand->Uniform(-height/2.0, height/2.0); LI::math::Vector3D pos(r * cos(t), r * sin(t), z); - return cylinder.LocalToGlobalPosition(pos); + LI::math::Vector3D final_pos = cylinder.LocalToGlobalPosition(pos); + + LI::math::Vector3D dir = record.GetDirection(); + std::vector intersections = cylinder.Intersections(final_pos, dir); + LI::detector::DetectorModel::SortIntersections(intersections); + + LI::math::Vector3D init_pos; + + if(intersections.size() == 0) { + init_pos = final_pos; + } else if(intersections.size() >= 2) { + init_pos = intersections.front().position; + } else { + throw std::runtime_error("Only found one cylinder intersection!"); + } + + return {init_pos, final_pos}; } double CylinderVolumePositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { @@ -52,20 +68,20 @@ std::string CylinderVolumePositionDistribution::Name() const { return "CylinderVolumePositionDistribution"; } -std::shared_ptr CylinderVolumePositionDistribution::clone() const { - return std::shared_ptr(new CylinderVolumePositionDistribution(*this)); +std::shared_ptr CylinderVolumePositionDistribution::clone() const { + return std::shared_ptr(new CylinderVolumePositionDistribution(*this)); } -std::pair CylinderVolumePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple CylinderVolumePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const { LI::math::Vector3D dir(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]); dir.normalize(); LI::math::Vector3D pos(interaction.interaction_vertex); std::vector intersections = cylinder.Intersections(pos, dir); LI::detector::DetectorModel::SortIntersections(intersections); if(intersections.size() == 0) { - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); } else if(intersections.size() >= 2) { - return std::pair(intersections.front().position, intersections.back().position); + return std::tuple(intersections.front().position, intersections.back().position); } else { throw std::runtime_error("Only found one cylinder intersection!"); } diff --git a/projects/distributions/private/primary/vertex/DecayRangeFunction.cxx b/projects/distributions/private/primary/vertex/DecayRangeFunction.cxx index 127900ac0..9e4004ee2 100644 --- a/projects/distributions/private/primary/vertex/DecayRangeFunction.cxx +++ b/projects/distributions/private/primary/vertex/DecayRangeFunction.cxx @@ -1,10 +1,11 @@ #include "LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h" +#include #include // for tie, operator<, operator==, tuple #include // for sqrt #include // for min -namespace LI { namespace dataclasses { struct InteractionSignature; } } +namespace LI { namespace dataclasses { enum class ParticleType : int32_t; } } namespace LI { namespace distributions { @@ -23,16 +24,16 @@ double DecayRangeFunction::DecayLength(double particle_mass, double decay_width, return length; // meters } -double DecayRangeFunction::DecayLength(LI::dataclasses::InteractionSignature const & signature, double energy) const { +double DecayRangeFunction::DecayLength(LI::dataclasses::ParticleType const & primary_type, double energy) const { return DecayRangeFunction::DecayLength(particle_mass, decay_width, energy); } -double DecayRangeFunction::Range(LI::dataclasses::InteractionSignature const & signature, double energy) const { - return std::min(DecayLength(signature, energy) * multiplier, max_distance); +double DecayRangeFunction::Range(LI::dataclasses::ParticleType const & primary_type, double energy) const { + return std::min(DecayLength(primary_type, energy) * multiplier, max_distance); } -double DecayRangeFunction::operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const { - return Range(signature, energy); +double DecayRangeFunction::operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const { + return Range(primary_type, energy); } double DecayRangeFunction::Multiplier() const { diff --git a/projects/distributions/private/primary/vertex/DecayRangePositionDistribution.cxx b/projects/distributions/private/primary/vertex/DecayRangePositionDistribution.cxx index 107b41673..11a450788 100644 --- a/projects/distributions/private/primary/vertex/DecayRangePositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/DecayRangePositionDistribution.cxx @@ -34,12 +34,12 @@ LI::math::Vector3D DecayRangePositionDistribution::SampleFromDisk(std::shared_pt return q.rotate(pos, false); } -LI::math::Vector3D DecayRangePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); +std::tuple DecayRangePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::math::Vector3D dir(record.GetDirection()); dir.normalize(); LI::math::Vector3D pca = SampleFromDisk(rand, dir); - double decay_length = range_function->DecayLength(record.signature, record.primary_momentum[0]); + double decay_length = range_function->DecayLength(record.type, record.GetEnergy()); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -52,9 +52,10 @@ LI::math::Vector3D DecayRangePositionDistribution::SamplePosition(std::shared_pt double total_distance = path.GetDistance(); double dist = -decay_length * log(y * (exp(-total_distance/decay_length) - 1) + 1); + LI::math::Vector3D init_pos = path.GetFirstPoint(); LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); - return vertex; + return {init_pos, vertex}; } double DecayRangePositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { @@ -66,7 +67,7 @@ double DecayRangePositionDistribution::GenerationProbability(std::shared_ptr= radius) return 0.0; - double decay_length = range_function->DecayLength(record.signature, record.primary_momentum[0]); + double decay_length = range_function->DecayLength(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -94,20 +95,20 @@ std::string DecayRangePositionDistribution::Name() const { return "DecayRangePositionDistribution"; } -std::shared_ptr DecayRangePositionDistribution::clone() const { - return std::shared_ptr(new DecayRangePositionDistribution(*this)); +std::shared_ptr DecayRangePositionDistribution::clone() const { + return std::shared_ptr(new DecayRangePositionDistribution(*this)); } -std::pair DecayRangePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +std::tuple DecayRangePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); dir.normalize(); LI::math::Vector3D vertex(record.interaction_vertex); // m LI::math::Vector3D pca = vertex - dir * LI::math::scalar_product(dir, vertex); if(pca.magnitude() >= radius) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - double decay_length = range_function->DecayLength(record.signature, record.primary_momentum[0]); + double decay_length = range_function->DecayLength(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -117,9 +118,9 @@ std::pair DecayRangePositionDistribution path.ClipToOuterBounds(); if(not path.IsWithinBounds(DetectorPosition(vertex))) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - return std::pair(path.GetFirstPoint(), path.GetLastPoint()); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); } bool DecayRangePositionDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/vertex/DepthFunction.cxx b/projects/distributions/private/primary/vertex/DepthFunction.cxx index 3f4a4fe7f..c2ff8240b 100644 --- a/projects/distributions/private/primary/vertex/DepthFunction.cxx +++ b/projects/distributions/private/primary/vertex/DepthFunction.cxx @@ -3,7 +3,7 @@ #include // for type_info #include // for type_index -namespace LI { namespace dataclasses { struct InteractionSignature; } } +namespace LI { namespace dataclasses { enum class ParticleType : int32_t; } } namespace LI { namespace distributions { @@ -13,7 +13,7 @@ namespace distributions { //--------------- DepthFunction::DepthFunction() {} -double DepthFunction::operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const { +double DepthFunction::operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const { return 0.0; } diff --git a/projects/distributions/private/primary/vertex/LeptonDepthFunction.cxx b/projects/distributions/private/primary/vertex/LeptonDepthFunction.cxx index 9c21ba9b5..9c0fc7f72 100644 --- a/projects/distributions/private/primary/vertex/LeptonDepthFunction.cxx +++ b/projects/distributions/private/primary/vertex/LeptonDepthFunction.cxx @@ -58,16 +58,16 @@ double LeptonDepthFunction::GetMaxDepth() const { return max_depth; } -double LeptonDepthFunction::operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const { +double LeptonDepthFunction::operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const { double range = std::log(1.0 + energy * mu_beta / mu_alpha) / mu_beta; - if(tau_primaries.count(signature.primary_type) > 0) + if(tau_primaries.count(primary_type) > 0) range += std::log(1.0 + energy * tau_beta / tau_alpha) / tau_beta; return std::min(range, max_depth); } -double LeptonDepthFunction::GetLeptonDepthFunctionReturnValue(LI::dataclasses::InteractionSignature const & signature, double energy) const { +double LeptonDepthFunction::GetLeptonDepthFunctionReturnValue(LI::dataclasses::ParticleType const & primary_type, double energy) const { double range = log(1.0 + energy * mu_beta / mu_alpha) / mu_beta; - if(tau_primaries.count(signature.primary_type) > 0) + if(tau_primaries.count(primary_type) > 0) range += log(1.0 + energy * tau_beta / tau_alpha) / tau_beta; return std::min(1e7*range, max_depth); } diff --git a/projects/distributions/private/primary/vertex/OrientedCylinderPositionDistribution.cxx b/projects/distributions/private/primary/vertex/OrientedCylinderPositionDistribution.cxx index 4eea705f8..e7ac95619 100644 --- a/projects/distributions/private/primary/vertex/OrientedCylinderPositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/OrientedCylinderPositionDistribution.cxx @@ -25,13 +25,13 @@ LI::math::Vector3D OrientedCylinderPositionDistribution::SampleFromDisk(std::sha return q.rotate(pos, false); } -LI::math::Vector3D OrientedCylinderPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); +std::tuple OrientedCylinderPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::math::Vector3D dir(record.GetDirection()); dir.normalize(); LI::math::Vector3D pca = SampleFromDisk(rand, dir); /* - std::pair GetBounds(detector_model, interactions, pca); + std::tuple GetBounds(detector_model, interactions, pca); LI::math::Vector3D p0; LI::math::Vector3D p1; @@ -40,15 +40,15 @@ LI::math::Vector3D OrientedCylinderPositionDistribution::SamplePosition(std::sha path.ExtendFromStartByColumnDepth(lepton_depth); path.ClipToOuterBounds(); */ - return LI::math::Vector3D(); + return {LI::math::Vector3D(), LI::math::Vector3D()}; } double OrientedCylinderPositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { return 0.0; } -std::pair OrientedCylinderPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const { - return std::make_pair(LI::math::Vector3D(), LI::math::Vector3D()); +std::tuple OrientedCylinderPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const { + return std::make_tuple(LI::math::Vector3D(), LI::math::Vector3D()); } bool OrientedCylinderPositionDistribution::AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const { diff --git a/projects/distributions/private/primary/vertex/PointSourcePositionDistribution.cxx b/projects/distributions/private/primary/vertex/PointSourcePositionDistribution.cxx index fd38c9e31..7ad4ba27f 100644 --- a/projects/distributions/private/primary/vertex/PointSourcePositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/PointSourcePositionDistribution.cxx @@ -47,9 +47,8 @@ namespace { // class PointSourcePositionDistribution : public VertexPositionDistribution //--------------- -LI::math::Vector3D PointSourcePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); - dir.normalize(); +std::tuple PointSourcePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::math::Vector3D dir(record.GetDirection()); LI::math::Vector3D endcap_0 = origin; LI::math::Vector3D endcap_1 = origin + max_distance * dir; @@ -61,15 +60,18 @@ LI::math::Vector3D PointSourcePositionDistribution::SamplePosition(std::shared_p std::vector targets(possible_targets.begin(), possible_targets.end()); std::vector total_cross_sections(targets.size(), 0.0); - double total_decay_length = interactions->TotalDecayLength(record); - LI::dataclasses::InteractionRecord fake_record = record; + LI::dataclasses::InteractionRecord fake_record; + fake_record.signature.primary_type = record.type; + fake_record.primary_mass = record.GetMass(); + fake_record.primary_momentum[0] = record.GetEnergy(); + double total_decay_length = interactions->TotalDecayLength(fake_record); for(unsigned int i=0; iGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + double cross_section_value = cross_section->TotalCrossSectionAllFinalStates(fake_record); + total_cross_sections[i] += cross_section_value; } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -87,9 +89,10 @@ LI::math::Vector3D PointSourcePositionDistribution::SamplePosition(std::shared_p } double dist = path.GetDistanceFromStartAlongPath(traversed_interaction_depth, targets, total_cross_sections, total_decay_length); + LI::math::Vector3D init_pos = path.GetFirstPoint(); LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); - return vertex; + return {init_pos, vertex}; } double PointSourcePositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { @@ -117,9 +120,8 @@ double PointSourcePositionDistribution::GenerationProbability(std::shared_ptr
  • GetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -148,11 +150,11 @@ std::string PointSourcePositionDistribution::Name() const { return "PointSourcePositionDistribution"; } -std::shared_ptr PointSourcePositionDistribution::clone() const { - return std::shared_ptr(new PointSourcePositionDistribution(*this)); +std::shared_ptr PointSourcePositionDistribution::clone() const { + return std::shared_ptr(new PointSourcePositionDistribution(*this)); } -std::pair PointSourcePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +std::tuple PointSourcePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); dir.normalize(); LI::math::Vector3D vertex(record.interaction_vertex); // m @@ -164,8 +166,8 @@ std::pair PointSourcePositionDistributio path.ClipToOuterBounds(); if(not path.IsWithinBounds(DetectorPosition(vertex))) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - return std::pair(path.GetFirstPoint(), path.GetLastPoint()); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); } bool PointSourcePositionDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/vertex/RangeFunction.cxx b/projects/distributions/private/primary/vertex/RangeFunction.cxx index a42d2e34e..fcbe63c43 100644 --- a/projects/distributions/private/primary/vertex/RangeFunction.cxx +++ b/projects/distributions/private/primary/vertex/RangeFunction.cxx @@ -12,7 +12,7 @@ namespace distributions { RangeFunction::RangeFunction() {} -double RangeFunction::operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const { +double RangeFunction::operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const { return 0.0; } diff --git a/projects/distributions/private/primary/vertex/RangePositionDistribution.cxx b/projects/distributions/private/primary/vertex/RangePositionDistribution.cxx index 6d498b525..80d50e9ef 100644 --- a/projects/distributions/private/primary/vertex/RangePositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/RangePositionDistribution.cxx @@ -56,12 +56,12 @@ LI::math::Vector3D RangePositionDistribution::SampleFromDisk(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); +std::tuple RangePositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + LI::math::Vector3D dir(record.GetDirection()); dir.normalize(); LI::math::Vector3D pca = SampleFromDisk(rand, dir); - double lepton_range = range_function->operator()(record.signature, record.primary_momentum[0]); + double lepton_range = range_function->operator()(record.type, record.GetEnergy()); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -74,15 +74,17 @@ LI::math::Vector3D RangePositionDistribution::SamplePosition(std::shared_ptr targets(possible_targets.begin(), possible_targets.end()); std::vector total_cross_sections(targets.size(), 0.0); - double total_decay_length = interactions->TotalDecayLength(record); - LI::dataclasses::InteractionRecord fake_record = record; + LI::dataclasses::InteractionRecord fake_record; + fake_record.signature.primary_type = record.type; + fake_record.primary_mass = record.GetMass(); + fake_record.primary_momentum[0] = record.GetEnergy(); + double total_decay_length = interactions->TotalDecayLength(fake_record); for(unsigned int i=0; iGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -100,9 +102,10 @@ LI::math::Vector3D RangePositionDistribution::SamplePosition(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { @@ -114,7 +117,7 @@ double RangePositionDistribution::GenerationProbability(std::shared_ptr= radius) return 0.0; - double lepton_range = range_function->operator()(record.signature, record.primary_momentum[0]); + double lepton_range = range_function->operator()(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -136,9 +139,8 @@ double RangePositionDistribution::GenerationProbability(std::shared_ptrGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); } } double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); @@ -168,20 +170,20 @@ std::string RangePositionDistribution::Name() const { return "RangePositionDistribution"; } -std::shared_ptr RangePositionDistribution::clone() const { - return std::shared_ptr(new RangePositionDistribution(*this)); +std::shared_ptr RangePositionDistribution::clone() const { + return std::shared_ptr(new RangePositionDistribution(*this)); } -std::pair RangePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { +std::tuple RangePositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); dir.normalize(); LI::math::Vector3D vertex(record.interaction_vertex); // m LI::math::Vector3D pca = vertex - dir * LI::math::scalar_product(dir, vertex); if(pca.magnitude() >= radius) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - double lepton_range = range_function->operator()(record.signature, record.primary_momentum[0]); + double lepton_range = range_function->operator()(record.signature.primary_type, record.primary_momentum[0]); LI::math::Vector3D endcap_0 = pca - endcap_length * dir; LI::math::Vector3D endcap_1 = pca + endcap_length * dir; @@ -191,8 +193,8 @@ std::pair RangePositionDistribution::Inj path.ClipToOuterBounds(); if(not path.IsWithinBounds(DetectorPosition(vertex))) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - return std::pair(path.GetFirstPoint(), path.GetLastPoint()); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); } bool RangePositionDistribution::equal(WeightableDistribution const & other) const { diff --git a/projects/distributions/private/primary/vertex/SecondaryPositionDistribution.cxx b/projects/distributions/private/primary/vertex/SecondaryPositionDistribution.cxx deleted file mode 100644 index 493ceb032..000000000 --- a/projects/distributions/private/primary/vertex/SecondaryPositionDistribution.cxx +++ /dev/null @@ -1,260 +0,0 @@ -#include "LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h" - -#include // for set -#include // for array -#include // for exp -#include // for tie -#include // for bas... -#include // for vector - -#include "LeptonInjector/interactions/CrossSection.h" // for Cro... -#include "LeptonInjector/interactions/InteractionCollection.h" // for Cro... -#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Int... -#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Int... -#include "LeptonInjector/dataclasses/Particle.h" // for Par... -#include "LeptonInjector/detector/DetectorModel.h" // for Ear... -#include "LeptonInjector/detector/Path.h" // for Path -#include "LeptonInjector/detector/Coordinates.h" -#include "LeptonInjector/distributions/Distributions.h" // for Inj... -#include "LeptonInjector/geometry/Geometry.h" // for Geo... -#include "LeptonInjector/math/Vector3D.h" // for Vec... -#include "LeptonInjector/utilities/Errors.h" // for Sec... -#include "LeptonInjector/utilities/Random.h" // for LI_... - -namespace LI { -namespace distributions { - -using detector::DetectorPosition; -using detector::DetectorDirection; - -namespace { - double log_one_minus_exp_of_negative(double x) { - if(x < 1e-1) { - return std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0; - } else if(x > 3) { - double ex = std::exp(-x); - double ex2 = ex * ex; - double ex3 = ex2 * ex; - double ex4 = ex3 * ex; - double ex5 = ex4 * ex; - double ex6 = ex5 * ex; - return -(ex + ex2 / 2.0 + ex3 / 3.0 + ex4 / 4.0 + ex5 / 5.0 + ex6 / 6.0); - } else { - return std::log(1.0 - std::exp(-x)); - } - } -} - -//--------------- -// class SecondaryPositionDistribution : public VertexPositionDistribution -//--------------- - -LI::math::Vector3D SecondaryPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - throw(LI::utilities::SecondaryProcessFailure("Cannot call SecondaryPositionDistribution::SamplePosition without a datum to access the parent")); - return LI::math::Vector3D(0,0,0); -} - -void SecondaryPositionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const { - LI::math::Vector3D pos = SamplePosition(rand, detector_model, interactions, datum); - datum.record.interaction_vertex[0] = pos.GetX(); - datum.record.interaction_vertex[1] = pos.GetY(); - datum.record.interaction_vertex[2] = pos.GetZ(); -} - -void SecondaryPositionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - throw(LI::utilities::SecondaryProcessFailure("Cannot call SecondaryPositionDistribution::Sample without a datum to access the parent")); -} - -LI::math::Vector3D SecondaryPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const { - LI::math::Vector3D dir(datum.record.primary_momentum[1], datum.record.primary_momentum[2], datum.record.primary_momentum[3]); - dir.normalize(); - - - - LI::math::Vector3D endcap_0 = LI::math::Vector3D(datum.parent->record.interaction_vertex); - LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; - - LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); - path.ClipToOuterBounds(); - - // Check if fiducial volume is provided - if(fiducial) { - std::vector fid_intersections = fiducial->Intersections(DetectorPosition(endcap_0), - DetectorDirection(dir)); - // If the path intersects the fiducial volume, restrict position to that volume - if(!fid_intersections.empty()) { - // make sure the first intersection happens before the maximum generation length - // and the last intersection happens in front of the generation point - bool update_path = (fid_intersections.front().distance < max_length - && fid_intersections.back().distance > 0); - if(update_path) { - LI::math::Vector3D first_point = (fid_intersections.front().distance > 0) ? fid_intersections.front().position : endcap_0; - LI::math::Vector3D last_point = (fid_intersections.back().distance < max_length) ? fid_intersections.back().position : endcap_1; - path.SetPoints(DetectorPosition(first_point), DetectorPosition(last_point)); - } - } - } - - std::set const & possible_targets = interactions->TargetTypes(); - - std::vector targets(possible_targets.begin(), possible_targets.end()); - std::vector total_cross_sections(targets.size(), 0.0); - double total_decay_length = interactions->TotalDecayLength(datum.record); - LI::dataclasses::InteractionRecord fake_record = datum.record; - for(unsigned int i=0; iGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; - for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); - } - } - double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); - if(total_interaction_depth == 0) { - throw(LI::utilities::InjectionFailure("No available interactions along path!")); - } - double traversed_interaction_depth; - if(total_interaction_depth < 1e-6) { - traversed_interaction_depth = rand->Uniform() * total_interaction_depth; - } else { - double exp_m_total_interaction_depth = exp(-total_interaction_depth); - - double y = rand->Uniform(); - traversed_interaction_depth = -log(y * exp_m_total_interaction_depth + (1.0 - y)); - } - - double dist = path.GetDistanceFromStartAlongPath(traversed_interaction_depth, targets, total_cross_sections, total_decay_length); - LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); - - return vertex; -} - -double SecondaryPositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { - throw(LI::utilities::SecondaryProcessFailure("Cannot call SecondaryPositionDistribution::GenerationProbability without a datum to access the parent")); - return 0; -} - -double SecondaryPositionDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const { - LI::math::Vector3D dir(datum.record.primary_momentum[1], datum.record.primary_momentum[2], datum.record.primary_momentum[3]); - dir.normalize(); - LI::math::Vector3D vertex(datum.record.interaction_vertex); - - LI::math::Vector3D endcap_0 = LI::math::Vector3D(datum.parent->record.interaction_vertex); - LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; - - LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); - path.ClipToOuterBounds(); - - if(not path.IsWithinBounds(DetectorPosition(vertex))) - return 0.0; - - // Check if fiducial volume is provided - if(fiducial) { - std::vector fid_intersections = fiducial->Intersections(DetectorPosition(endcap_0), - DetectorDirection(dir)); - // If the path intersects the fiducial volume, restrict position to that volume - if(!fid_intersections.empty()) { - // make sure the first intersection happens before the maximum generation length - // and the last intersection happens in front of the generation point - bool update_path = (fid_intersections.front().distance < max_length - && fid_intersections.back().distance > 0); - if(update_path) { - LI::math::Vector3D first_point = (fid_intersections.front().distance > 0) ? fid_intersections.front().position : endcap_0; - LI::math::Vector3D last_point = (fid_intersections.back().distance < max_length) ? fid_intersections.back().position : endcap_1; - path.SetPoints(DetectorPosition(first_point), DetectorPosition(last_point)); - } - } - } - - std::set const & possible_targets = interactions->TargetTypes(); - - std::vector targets(possible_targets.begin(), possible_targets.end()); - std::vector total_cross_sections(targets.size(), 0.0); - double total_decay_length = interactions->TotalDecayLength(datum.record); - LI::dataclasses::InteractionRecord fake_record = datum.record; - for(unsigned int i=0; iGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; - for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { - total_cross_sections[i] += cross_section->TotalCrossSection(fake_record); - } - } - double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); - - path.SetPointsWithRay(path.GetFirstPoint(), path.GetDirection(), path.GetDistanceFromStartInBounds(DetectorPosition(vertex))); - - double traversed_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); - - double interaction_density = detector_model->GetInteractionDensity(path.GetIntersections(), DetectorPosition(vertex), targets, total_cross_sections, total_decay_length); - - double prob_density; - if(total_interaction_depth < 1e-6) { - prob_density = interaction_density / total_interaction_depth; - } else { - prob_density = interaction_density * exp(-log_one_minus_exp_of_negative(total_interaction_depth) - traversed_interaction_depth); - } - - return prob_density; -} - -SecondaryPositionDistribution::SecondaryPositionDistribution() {} - -SecondaryPositionDistribution::SecondaryPositionDistribution(double max_length) : max_length(max_length) {} - -SecondaryPositionDistribution::SecondaryPositionDistribution(double max_length, std::shared_ptr fiducial) : - max_length(max_length), - fiducial(fiducial) {} - -SecondaryPositionDistribution::SecondaryPositionDistribution(std::shared_ptr fiducial) : fiducial(fiducial) {} - -std::string SecondaryPositionDistribution::Name() const { - return "SecondaryPositionDistribution"; -} - -std::shared_ptr SecondaryPositionDistribution::clone() const { - return std::shared_ptr(new SecondaryPositionDistribution(*this)); -} - -std::pair SecondaryPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { - throw(LI::utilities::SecondaryProcessFailure("Cannot call SecondaryPositionDistribution::InjectionBounds without a datum to access the parent")); - return std::make_pair(LI::math::Vector3D(0,0,0),LI::math::Vector3D(0,0,0)); -} - -std::pair SecondaryPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const { - LI::math::Vector3D dir(datum.record.primary_momentum[1], datum.record.primary_momentum[2], datum.record.primary_momentum[3]); - dir.normalize(); - LI::math::Vector3D vertex(datum.record.interaction_vertex); - - LI::math::Vector3D endcap_0 = LI::math::Vector3D(datum.parent->record.interaction_vertex); - LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; - - LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); - path.ClipToOuterBounds(); - - if(not path.IsWithinBounds(DetectorPosition(vertex))) - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); - return std::pair(path.GetFirstPoint(), path.GetLastPoint()); -} - -bool SecondaryPositionDistribution::equal(WeightableDistribution const & other) const { - const SecondaryPositionDistribution* x = dynamic_cast(&other); - - if(!x) - return false; - else - return (max_length == x->max_length); -} - -bool SecondaryPositionDistribution::less(WeightableDistribution const & other) const { - const SecondaryPositionDistribution* x = dynamic_cast(&other); - return - std::tie(max_length) - < - std::tie(x->max_length); -} - -} // namespace distributions -} // namespace LeptonInjector diff --git a/projects/distributions/private/primary/vertex/VertexPositionDistribution.cxx b/projects/distributions/private/primary/vertex/VertexPositionDistribution.cxx index 1ba53cdd9..a232ea7cf 100644 --- a/projects/distributions/private/primary/vertex/VertexPositionDistribution.cxx +++ b/projects/distributions/private/primary/vertex/VertexPositionDistribution.cxx @@ -12,24 +12,21 @@ namespace LI { namespace distributions { //--------------- -// class VertexPositionDistribution : InjectionDistribution +// class VertexPositionDistribution : PrimaryInjectionDistribution //--------------- -LI::math::Vector3D VertexPositionDistribution::SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const { - return SamplePosition(rand, detector_model, interactions, datum.record); -} - -void VertexPositionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const { - LI::math::Vector3D pos = SamplePosition(rand, detector_model, interactions, record); - record.interaction_vertex[0] = pos.GetX(); - record.interaction_vertex[1] = pos.GetY(); - record.interaction_vertex[2] = pos.GetZ(); +void VertexPositionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const { + std::tuple init_and_pos = SamplePosition(rand, detector_model, interactions, record); + LI::math::Vector3D const & init = std::get<0>(init_and_pos); + LI::math::Vector3D const & pos = std::get<1>(init_and_pos); + record.SetInitialPosition((std::array)init); + record.SetInteractionVertex((std::array)pos); } std::vector VertexPositionDistribution::DensityVariables() const { return std::vector{"InteractionVertexPosition"}; } -std::pair VertexPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const { +std::tuple VertexPositionDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const { return InjectionBounds(detector_model, interactions, datum.record); } diff --git a/projects/distributions/private/pybindings/distributions.cxx b/projects/distributions/private/pybindings/distributions.cxx index 1b122aaa2..0cb4cd697 100644 --- a/projects/distributions/private/pybindings/distributions.cxx +++ b/projects/distributions/private/pybindings/distributions.cxx @@ -11,7 +11,7 @@ #include "../../public/LeptonInjector/distributions/primary/energy/PowerLaw.h" #include "../../public/LeptonInjector/distributions/primary/energy/TabulatedFluxDistribution.h" #include "../../public/LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h" -#include "../../public/LeptonInjector/distributions/primary/type/PrimaryInjector.h" +#include "../../public/LeptonInjector/distributions/primary/mass/PrimaryMass.h" #include "../../public/LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h" #include "../../public/LeptonInjector/distributions/primary/vertex/ColumnDepthPositionDistribution.h" #include "../../public/LeptonInjector/distributions/primary/vertex/CylinderVolumePositionDistribution.h" @@ -22,8 +22,8 @@ #include "../../public/LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h" #include "../../public/LeptonInjector/distributions/primary/vertex/RangeFunction.h" #include "../../public/LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h" -#include "../../public/LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h" -#include "../../public/LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h" +#include "../../public/LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h" +#include "../../public/LeptonInjector/distributions/secondary/vertex/SecondaryBoundedVertexDistribution.h" #include "../../../utilities/public/LeptonInjector/utilities/Random.h" #include "../../../detector/public/LeptonInjector/detector/DetectorModel.h" @@ -55,14 +55,13 @@ PYBIND11_MODULE(distributions,m) { .def("GenerationProbability",&NormalizationConstant::GenerationProbability) .def("Name",&NormalizationConstant::Name); - class_, WeightableDistribution>(m, "InjectionDistribution") - .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::InteractionRecord &>(&InjectionDistribution::Sample, const_)) - .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::InteractionTreeDatum &>(&InjectionDistribution::Sample, const_)) - .def("IsPositionDistribution",&InjectionDistribution::IsPositionDistribution); + class_, WeightableDistribution>(m, "PrimaryInjectionDistribution") + .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::PrimaryDistributionRecord &>(&PrimaryInjectionDistribution::Sample, const_)) + ; // Direciton distributions - class_, InjectionDistribution>(m, "PrimaryDirectionDistribution") + class_, PrimaryInjectionDistribution>(m, "PrimaryDirectionDistribution") .def("Sample",&PrimaryDirectionDistribution::Sample) .def("DensityVariables",&PrimaryDirectionDistribution::DensityVariables) .def("GenerationProbability",&PrimaryDirectionDistribution::GenerationProbability); @@ -81,7 +80,7 @@ PYBIND11_MODULE(distributions,m) { // Energy distributions - class_, InjectionDistribution, PhysicallyNormalizedDistribution>(m, "PrimaryEnergyDistribution") + class_, PrimaryInjectionDistribution, PhysicallyNormalizedDistribution>(m, "PrimaryEnergyDistribution") .def("Sample",&PrimaryEnergyDistribution::Sample); class_, PrimaryEnergyDistribution>(m, "Monoenergetic") @@ -116,7 +115,7 @@ PYBIND11_MODULE(distributions,m) { // Helicity distributions - class_, InjectionDistribution>(m, "PrimaryNeutrinoHelicityDistribution") + class_, PrimaryInjectionDistribution>(m, "PrimaryNeutrinoHelicityDistribution") .def(init<>()) .def("Sample",&PrimaryNeutrinoHelicityDistribution::Sample) .def("GenerationProbability",&PrimaryNeutrinoHelicityDistribution::GenerationProbability) @@ -125,18 +124,17 @@ PYBIND11_MODULE(distributions,m) { // Type distributions - class_, InjectionDistribution>(m, "PrimaryInjector") - .def(init()) - .def("PrimaryMass",&PrimaryInjector::PrimaryMass) - .def("Sample",&PrimaryInjector::Sample) - .def("GenerationProbability",&PrimaryInjector::GenerationProbability) - .def("DensityVariables",&PrimaryInjector::DensityVariables) - .def("Name",&PrimaryInjector::Name); + class_, PrimaryInjectionDistribution>(m, "PrimaryMass") + .def(init()) + .def("GetPrimaryMass",&PrimaryMass::GetPrimaryMass) + .def("Sample",&PrimaryMass::Sample) + .def("GenerationProbability",&PrimaryMass::GenerationProbability) + .def("DensityVariables",&PrimaryMass::DensityVariables) + .def("Name",&PrimaryMass::Name); // Vertex distributions - class_, InjectionDistribution>(m, "VertexPositionDistribution") - .def("IsPositionDistribution",&VertexPositionDistribution::IsPositionDistribution) + class_, PrimaryInjectionDistribution>(m, "VertexPositionDistribution") .def("DensityVariables",&VertexPositionDistribution::DensityVariables) //.def("InjectionBounds",&VertexPositionDistribution::InjectionBounds) .def("AreEquivalent",&VertexPositionDistribution::AreEquivalent); @@ -150,7 +148,7 @@ PYBIND11_MODULE(distributions,m) { class_, RangeFunction>(m, "DecayRangeFunction") .def(init()) //.def((LI::dataclasses::InteractionSignature const &, double)) - .def("DecayLength",overload_cast(&DecayRangeFunction::DecayLength, const_)) + .def("DecayLength",overload_cast(&DecayRangeFunction::DecayLength, const_)) .def("DecayLength",overload_cast(&DecayRangeFunction::DecayLength)) .def("Range",&DecayRangeFunction::Range) .def("Multiplier",&DecayRangeFunction::Multiplier) @@ -214,29 +212,31 @@ PYBIND11_MODULE(distributions,m) { .def("InjectionBounds",&RangePositionDistribution::InjectionBounds) .def("Name",&RangePositionDistribution::Name); - class_, VertexPositionDistribution>(m, "SecondaryPositionDistribution") - .def(init<>()) - .def(init()) - .def(init>()) - .def(init>()) - .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::InteractionRecord &>(&SecondaryPositionDistribution::Sample, const_)) - .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::InteractionTreeDatum &>(&SecondaryPositionDistribution::Sample, const_)) - .def("GenerationProbability",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryPositionDistribution::GenerationProbability, const_)) - .def("GenerationProbability",overload_cast, std::shared_ptr, LI::dataclasses::InteractionTreeDatum const &>(&SecondaryPositionDistribution::GenerationProbability, const_)) - .def("InjectionBounds",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryPositionDistribution::InjectionBounds, const_)) - .def("InjectionBounds",overload_cast, std::shared_ptr, LI::dataclasses::InteractionTreeDatum const &>(&SecondaryPositionDistribution::InjectionBounds, const_)) - .def("Name",&SecondaryPositionDistribution::Name); - // Target momentum distributions + class_, WeightableDistribution>(m, "SecondaryInjectionDistribution") + .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::SecondaryDistributionRecord &>(&SecondaryInjectionDistribution::Sample, const_)); - class_, InjectionDistribution>(m, "TargetMomentumDistribution") - .def("Sample",&TargetMomentumDistribution::Sample); + class_, SecondaryInjectionDistribution>(m, "SecondaryVertexPositionDistribution") + .def("DensityVariables",&SecondaryVertexPositionDistribution::DensityVariables) + .def("AreEquivalent",&SecondaryVertexPositionDistribution::AreEquivalent) + .def("Sample",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::SecondaryDistributionRecord &>(&SecondaryVertexPositionDistribution::Sample, const_)); - class_, TargetMomentumDistribution>(m, "TargetAtRest") + class_, SecondaryVertexPositionDistribution>(m, "SecondaryPhysicalVertexDistribution") .def(init<>()) - .def("GenerationProbability",&TargetAtRest::GenerationProbability) - .def("DensityVariables",&TargetAtRest::DensityVariables) - .def("Name",&TargetAtRest::Name); + .def("SampleVertex",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::SecondaryDistributionRecord &>(&SecondaryPhysicalVertexDistribution::SampleVertex, const_)) + .def("GenerationProbability",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryPhysicalVertexDistribution::GenerationProbability, const_)) + .def("InjectionBounds",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryPhysicalVertexDistribution::InjectionBounds, const_)) + .def("Name",&SecondaryPhysicalVertexDistribution::Name); + + class_, SecondaryVertexPositionDistribution>(m, "SecondaryBoundedVertexDistribution") + .def(init<>()) + .def(init()) + .def(init>()) + .def(init, double>()) + .def("SampleVertex",overload_cast, std::shared_ptr, std::shared_ptr, LI::dataclasses::SecondaryDistributionRecord &>(&SecondaryBoundedVertexDistribution::SampleVertex, const_)) + .def("GenerationProbability",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryBoundedVertexDistribution::GenerationProbability, const_)) + .def("InjectionBounds",overload_cast, std::shared_ptr, LI::dataclasses::InteractionRecord const &>(&SecondaryBoundedVertexDistribution::InjectionBounds, const_)) + .def("Name",&SecondaryBoundedVertexDistribution::Name); } diff --git a/projects/distributions/private/secondary/vertex/SecondaryBoundedVertexDistribution.cxx b/projects/distributions/private/secondary/vertex/SecondaryBoundedVertexDistribution.cxx new file mode 100644 index 000000000..69e091066 --- /dev/null +++ b/projects/distributions/private/secondary/vertex/SecondaryBoundedVertexDistribution.cxx @@ -0,0 +1,249 @@ +#include "LeptonInjector/distributions/secondary/vertex/SecondaryBoundedVertexDistribution.h" + +#include // for set +#include // for array +#include // for exp +#include // for tie +#include // for bas... +#include // for vector + +#include "LeptonInjector/interactions/CrossSection.h" // for Cro... +#include "LeptonInjector/interactions/InteractionCollection.h" // for Cro... +#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Int... +#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Int... +#include "LeptonInjector/dataclasses/Particle.h" // for Par... +#include "LeptonInjector/detector/DetectorModel.h" // for Ear... +#include "LeptonInjector/detector/Path.h" // for Path +#include "LeptonInjector/detector/Coordinates.h" +#include "LeptonInjector/distributions/Distributions.h" // for Inj... +#include "LeptonInjector/geometry/Geometry.h" // for Geo... +#include "LeptonInjector/math/Vector3D.h" // for Vec... +#include "LeptonInjector/utilities/Errors.h" // for Sec... +#include "LeptonInjector/utilities/Random.h" // for LI_... + +namespace LI { +namespace distributions { + +using detector::DetectorPosition; +using detector::DetectorDirection; + +namespace { +double log_one_minus_exp_of_negative(double x) { + if(x < 1e-1) { + return std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0; + } else if(x > 3) { + double ex = std::exp(-x); + double ex2 = ex * ex; + double ex3 = ex2 * ex; + double ex4 = ex3 * ex; + double ex5 = ex4 * ex; + double ex6 = ex5 * ex; + return -(ex + ex2 / 2.0 + ex3 / 3.0 + ex4 / 4.0 + ex5 / 5.0 + ex6 / 6.0); + } else { + return std::log(1.0 - std::exp(-x)); + } +} +} + +//--------------- +// class SecondaryBoundedVertexDistribution : public VertexPositionDistribution +//--------------- + + +void SecondaryBoundedVertexDistribution::SampleVertex(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const { + LI::math::Vector3D pos = record.initial_position; + LI::math::Vector3D dir = record.direction; + + LI::math::Vector3D endcap_0 = pos; + LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); + path.ClipToOuterBounds(); + + // Check if fiducial volume is provided + if(fiducial_volume) { + std::vector fid_intersections = fiducial_volume->Intersections(DetectorPosition(endcap_0), + DetectorDirection(dir)); + // If the path intersects the fiducial volume, restrict position to that volume + if(!fid_intersections.empty()) { + // make sure the first intersection happens before the maximum generation length + // and the last intersection happens in front of the generation point + bool update_path = (fid_intersections.front().distance < max_length + && fid_intersections.back().distance > 0); + if(update_path) { + LI::math::Vector3D first_point = (fid_intersections.front().distance > 0) ? fid_intersections.front().position : endcap_0; + LI::math::Vector3D last_point = (fid_intersections.back().distance < max_length) ? fid_intersections.back().position : endcap_1; + path.SetPoints(DetectorPosition(first_point), DetectorPosition(last_point)); + } + } + } + + std::vector targets(interactions->TargetTypes().begin(), interactions->TargetTypes().end()); + + std::vector total_cross_sections(targets.size(), 0.0); + double total_decay_length = interactions->TotalDecayLength(record.record); + LI::dataclasses::InteractionRecord fake_record = record.record; + for(unsigned int i=0; iGetTargetMass(target); + for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); + } + } + + double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + if(total_interaction_depth == 0) { + throw(LI::utilities::InjectionFailure("No available interactions along path!")); + } + + double traversed_interaction_depth; + if(total_interaction_depth < 1e-6) { + traversed_interaction_depth = rand->Uniform() * total_interaction_depth; + } else { + double exp_m_total_interaction_depth = exp(-total_interaction_depth); + + double y = rand->Uniform(); + traversed_interaction_depth = -log(y * exp_m_total_interaction_depth + (1.0 - y)); + } + + double dist = path.GetDistanceFromStartAlongPath(traversed_interaction_depth, targets, total_cross_sections, total_decay_length); + LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); + + double length = (vertex - pos) * dir; + record.SetLength(length); +} + +double SecondaryBoundedVertexDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { + LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); + dir.normalize(); + LI::math::Vector3D vertex(record.interaction_vertex); + + LI::math::Vector3D endcap_0 = record.primary_initial_position; + LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); + path.ClipToOuterBounds(); + + // Check if fiducial volume is provided + if(fiducial_volume) { + std::vector fid_intersections = fiducial_volume->Intersections(DetectorPosition(endcap_0), + DetectorDirection(dir)); + // If the path intersects the fiducial volume, restrict position to that volume + if(!fid_intersections.empty()) { + // make sure the first intersection happens before the maximum generation length + // and the last intersection happens in front of the generation point + bool update_path = (fid_intersections.front().distance < max_length + && fid_intersections.back().distance > 0); + if(update_path) { + LI::math::Vector3D first_point = (fid_intersections.front().distance > 0) ? fid_intersections.front().position : endcap_0; + LI::math::Vector3D last_point = (fid_intersections.back().distance < max_length) ? fid_intersections.back().position : endcap_1; + path.SetPoints(DetectorPosition(first_point), DetectorPosition(last_point)); + } + } + } + + if(not path.IsWithinBounds(DetectorPosition(vertex))) + return 0.0; + + std::set const & possible_targets = interactions->TargetTypes(); + + std::vector targets(possible_targets.begin(), possible_targets.end()); + std::vector total_cross_sections(targets.size(), 0.0); + double total_decay_length = interactions->TotalDecayLength(record); + LI::dataclasses::InteractionRecord fake_record = record; + for(unsigned int i=0; iGetTargetMass(target); + for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); + } + } + double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + + path.SetPointsWithRay(path.GetFirstPoint(), path.GetDirection(), path.GetDistanceFromStartInBounds(DetectorPosition(vertex))); + + double traversed_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + + double interaction_density = detector_model->GetInteractionDensity(path.GetIntersections(), DetectorPosition(vertex), targets, total_cross_sections, total_decay_length); + + double prob_density; + if(total_interaction_depth < 1e-6) { + prob_density = interaction_density / total_interaction_depth; + } else { + prob_density = interaction_density * exp(-log_one_minus_exp_of_negative(total_interaction_depth) - traversed_interaction_depth); + } + + return prob_density; +} + +SecondaryBoundedVertexDistribution::SecondaryBoundedVertexDistribution() {} + +SecondaryBoundedVertexDistribution::SecondaryBoundedVertexDistribution(double max_length) : max_length(max_length) {} + +SecondaryBoundedVertexDistribution::SecondaryBoundedVertexDistribution(std::shared_ptr fiducial_volume) : fiducial_volume(fiducial_volume) {} + +SecondaryBoundedVertexDistribution::SecondaryBoundedVertexDistribution(std::shared_ptr fiducial_volume, double max_length) : fiducial_volume(fiducial_volume), max_length(max_length) {} + +std::string SecondaryBoundedVertexDistribution::Name() const { + return "SecondaryBoundedVertexDistribution"; +} + +std::shared_ptr SecondaryBoundedVertexDistribution::clone() const { + return std::shared_ptr(new SecondaryBoundedVertexDistribution(*this)); +} + +std::tuple SecondaryBoundedVertexDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { + LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); + dir.normalize(); + LI::math::Vector3D vertex(record.interaction_vertex); + + LI::math::Vector3D endcap_0 = record.primary_initial_position; + LI::math::Vector3D endcap_1 = endcap_0 + max_length * dir; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), max_length); + path.ClipToOuterBounds(); + + // Check if fiducial volume is provided + if(fiducial_volume) { + std::vector fid_intersections = fiducial_volume->Intersections(DetectorPosition(endcap_0), + DetectorDirection(dir)); + // If the path intersects the fiducial volume, restrict position to that volume + if(!fid_intersections.empty()) { + // make sure the first intersection happens before the maximum generation length + // and the last intersection happens in front of the generation point + bool update_path = (fid_intersections.front().distance < max_length + && fid_intersections.back().distance > 0); + if(update_path) { + LI::math::Vector3D first_point = (fid_intersections.front().distance > 0) ? fid_intersections.front().position : endcap_0; + LI::math::Vector3D last_point = (fid_intersections.back().distance < max_length) ? fid_intersections.back().position : endcap_1; + path.SetPoints(DetectorPosition(first_point), DetectorPosition(last_point)); + } + } + } + + if(not path.IsWithinBounds(DetectorPosition(vertex))) + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); +} + +bool SecondaryBoundedVertexDistribution::equal(WeightableDistribution const & other) const { + const SecondaryBoundedVertexDistribution* x = dynamic_cast(&other); + + if(!x) + return false; + else + return (max_length == x->max_length); +} + +bool SecondaryBoundedVertexDistribution::less(WeightableDistribution const & other) const { + const SecondaryBoundedVertexDistribution* x = dynamic_cast(&other); + return + std::tie(max_length) + < + std::tie(x->max_length); +} + +} // namespace distributions +} // namespace LeptonInjector diff --git a/projects/distributions/private/secondary/vertex/SecondaryPhysicalVertexDistribution.cxx b/projects/distributions/private/secondary/vertex/SecondaryPhysicalVertexDistribution.cxx new file mode 100644 index 000000000..1e1cd2b8f --- /dev/null +++ b/projects/distributions/private/secondary/vertex/SecondaryPhysicalVertexDistribution.cxx @@ -0,0 +1,183 @@ +#include "LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h" + +#include // for set +#include // for array +#include // for exp +#include // for tie +#include // for bas... +#include // for vector + +#include "LeptonInjector/interactions/CrossSection.h" // for Cro... +#include "LeptonInjector/interactions/InteractionCollection.h" // for Cro... +#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Int... +#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Int... +#include "LeptonInjector/dataclasses/Particle.h" // for Par... +#include "LeptonInjector/detector/DetectorModel.h" // for Ear... +#include "LeptonInjector/detector/Path.h" // for Path +#include "LeptonInjector/detector/Coordinates.h" +#include "LeptonInjector/distributions/Distributions.h" // for Inj... +#include "LeptonInjector/geometry/Geometry.h" // for Geo... +#include "LeptonInjector/math/Vector3D.h" // for Vec... +#include "LeptonInjector/utilities/Errors.h" // for Sec... +#include "LeptonInjector/utilities/Random.h" // for LI_... + +namespace LI { +namespace distributions { + +using detector::DetectorPosition; +using detector::DetectorDirection; + +namespace { +double log_one_minus_exp_of_negative(double x) { + if(x < 1e-1) { + return std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0; + } else if(x > 3) { + double ex = std::exp(-x); + double ex2 = ex * ex; + double ex3 = ex2 * ex; + double ex4 = ex3 * ex; + double ex5 = ex4 * ex; + double ex6 = ex5 * ex; + return -(ex + ex2 / 2.0 + ex3 / 3.0 + ex4 / 4.0 + ex5 / 5.0 + ex6 / 6.0); + } else { + return std::log(1.0 - std::exp(-x)); + } +} +} + +//--------------- +// class SecondaryPhysicalVertexDistribution : public VertexPositionDistribution +//--------------- + + +void SecondaryPhysicalVertexDistribution::SampleVertex(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const { + LI::math::Vector3D pos = record.initial_position; + LI::math::Vector3D dir = record.direction; + + LI::math::Vector3D endcap_0 = pos; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), std::numeric_limits::infinity()); + path.ClipToOuterBounds(); + + std::vector targets(interactions->TargetTypes().begin(), interactions->TargetTypes().end()); + + std::vector total_cross_sections(targets.size(), 0.0); + double total_decay_length = interactions->TotalDecayLength(record.record); + LI::dataclasses::InteractionRecord fake_record = record.record; + for(unsigned int i=0; iGetTargetMass(target); + for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); + } + } + + double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + if(total_interaction_depth == 0) { + throw(LI::utilities::InjectionFailure("No available interactions along path!")); + } + + double traversed_interaction_depth; + if(total_interaction_depth < 1e-6) { + traversed_interaction_depth = rand->Uniform() * total_interaction_depth; + } else { + double exp_m_total_interaction_depth = exp(-total_interaction_depth); + + double y = rand->Uniform(); + traversed_interaction_depth = -log(y * exp_m_total_interaction_depth + (1.0 - y)); + } + + double dist = path.GetDistanceFromStartAlongPath(traversed_interaction_depth, targets, total_cross_sections, total_decay_length); + LI::math::Vector3D vertex = path.GetFirstPoint() + dist * path.GetDirection(); + + double length = (vertex - pos) * dir; + record.SetLength(length); +} + +double SecondaryPhysicalVertexDistribution::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { + LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); + dir.normalize(); + LI::math::Vector3D vertex(record.interaction_vertex); + + LI::math::Vector3D endcap_0 = record.primary_initial_position; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), std::numeric_limits::infinity()); + path.ClipToOuterBounds(); + + if(not path.IsWithinBounds(DetectorPosition(vertex))) + return 0.0; + + std::set const & possible_targets = interactions->TargetTypes(); + + std::vector targets(possible_targets.begin(), possible_targets.end()); + std::vector total_cross_sections(targets.size(), 0.0); + double total_decay_length = interactions->TotalDecayLength(record); + LI::dataclasses::InteractionRecord fake_record = record; + for(unsigned int i=0; iGetTargetMass(target); + for(auto const & cross_section : interactions->GetCrossSectionsForTarget(target)) { + total_cross_sections[i] += cross_section->TotalCrossSectionAllFinalStates(fake_record); + } + } + double total_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + + path.SetPointsWithRay(path.GetFirstPoint(), path.GetDirection(), path.GetDistanceFromStartInBounds(DetectorPosition(vertex))); + + double traversed_interaction_depth = path.GetInteractionDepthInBounds(targets, total_cross_sections, total_decay_length); + + double interaction_density = detector_model->GetInteractionDensity(path.GetIntersections(), DetectorPosition(vertex), targets, total_cross_sections, total_decay_length); + + double prob_density; + if(total_interaction_depth < 1e-6) { + prob_density = interaction_density / total_interaction_depth; + } else { + prob_density = interaction_density * exp(-log_one_minus_exp_of_negative(total_interaction_depth) - traversed_interaction_depth); + } + + return prob_density; +} + +SecondaryPhysicalVertexDistribution::SecondaryPhysicalVertexDistribution() {} + +std::string SecondaryPhysicalVertexDistribution::Name() const { + return "SecondaryPhysicalVertexDistribution"; +} + +std::shared_ptr SecondaryPhysicalVertexDistribution::clone() const { + return std::shared_ptr(new SecondaryPhysicalVertexDistribution(*this)); +} + +std::tuple SecondaryPhysicalVertexDistribution::InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { + LI::math::Vector3D dir(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]); + dir.normalize(); + LI::math::Vector3D vertex(record.interaction_vertex); + + LI::math::Vector3D endcap_0 = record.primary_initial_position; + + LI::detector::Path path(detector_model, DetectorPosition(endcap_0), DetectorDirection(dir), std::numeric_limits::infinity()); + path.ClipToOuterBounds(); + + if(not path.IsWithinBounds(DetectorPosition(vertex))) + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(path.GetFirstPoint(), path.GetLastPoint()); +} + +bool SecondaryPhysicalVertexDistribution::equal(WeightableDistribution const & other) const { + const SecondaryPhysicalVertexDistribution* x = dynamic_cast(&other); + + if(!x) + return false; + else + return true; +} + +bool SecondaryPhysicalVertexDistribution::less(WeightableDistribution const & other) const { + const SecondaryPhysicalVertexDistribution* x = dynamic_cast(&other); + return false; +} + +} // namespace distributions +} // namespace LeptonInjector diff --git a/projects/distributions/private/secondary/vertex/SecondaryVertexPositionDistribution.cxx b/projects/distributions/private/secondary/vertex/SecondaryVertexPositionDistribution.cxx new file mode 100644 index 000000000..b846b7930 --- /dev/null +++ b/projects/distributions/private/secondary/vertex/SecondaryVertexPositionDistribution.cxx @@ -0,0 +1,30 @@ +#include "LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h" + +#include // for array +#include // for bas... + +#include "LeptonInjector/interactions/InteractionCollection.h" // for Cro... +#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Int... +#include "LeptonInjector/detector/DetectorModel.h" // for Ear... +#include "LeptonInjector/math/Vector3D.h" // for Vec... + +namespace LI { +namespace distributions { + +//--------------- +// class SecondaryVertexPositionDistribution : InjectionDistribution +//--------------- +void SecondaryVertexPositionDistribution::Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const { + SampleVertex(rand, detector_model, interactions, record); +} + +std::vector SecondaryVertexPositionDistribution::DensityVariables() const { + return std::vector{"Length"}; +} + +bool SecondaryVertexPositionDistribution::AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const { + return this->operator==(*distribution) and detector_model->operator==(*second_detector_model) and interactions->operator==(*second_interactions); +} + +} // namespace distributions +} // namespace LeptonInjector diff --git a/projects/distributions/private/target/momentum/TargetMomentumDistribution.cxx b/projects/distributions/private/target/momentum/TargetMomentumDistribution.cxx deleted file mode 100644 index 6f74c21c7..000000000 --- a/projects/distributions/private/target/momentum/TargetMomentumDistribution.cxx +++ /dev/null @@ -1,68 +0,0 @@ -#include "LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h" - -#include // for basic_string - -#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Interactio... -#include "LeptonInjector/distributions/Distributions.h" // for InjectionD... - -namespace LI { -namespace distributions { - -//--------------- -// class TargetMomentumDistribution : InjectionDistribution -//--------------- - -void TargetMomentumDistribution::Sample( - std::shared_ptr rand, - std::shared_ptr detector_model, - std::shared_ptr interactions, - LI::dataclasses::InteractionRecord & record) const { - record.target_momentum = SampleMomentum(rand, detector_model, interactions, record); -} - -std::vector TargetMomentumDistribution::DensityVariables() const { - return std::vector{"TargetMomentum"}; -} - -//--------------- -// class TargetAtRest : TargetMomentumDistribution : InjectionDistribution -//--------------- -std::array TargetAtRest::SampleMomentum( - std::shared_ptr rand, - std::shared_ptr detector_model, - std::shared_ptr interactions, - LI::dataclasses::InteractionRecord const & record) const { - return std::array{record.target_mass, 0, 0, 0}; -} - -double TargetAtRest::GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const { - return 1.0; -} - -std::vector TargetAtRest::DensityVariables() const { - return std::vector(); -} - -std::shared_ptr TargetAtRest::clone() const { - return std::shared_ptr(new TargetAtRest(*this)); -} - -std::string TargetAtRest::Name() const { - return "TargetAtRest"; -} - -bool TargetAtRest::equal(WeightableDistribution const & other) const { - const TargetAtRest* x = dynamic_cast(&other); - - if(!x) - return false; - else - return true; -} - -bool TargetAtRest::less(WeightableDistribution const & other) const { - return false; -} - -} // namespace distributions -} // namespace LeptonInjector diff --git a/projects/distributions/private/test/PrimaryDirectionDistribution_TEST.cxx b/projects/distributions/private/test/PrimaryDirectionDistribution_TEST.cxx index 2967e7944..76e2edcd8 100644 --- a/projects/distributions/private/test/PrimaryDirectionDistribution_TEST.cxx +++ b/projects/distributions/private/test/PrimaryDirectionDistribution_TEST.cxx @@ -44,12 +44,11 @@ TEST(Cone, SampleBounds) { double opening_angle = M_PI * RandomDouble(); Cone A(direction, opening_angle); for(size_t j=0; j= 0); @@ -76,12 +75,11 @@ TEST(Cone, SampleDistributionTheta) { double bin_min = cos(opening_angle); DistributionTest test(bin_min, bin_max, n_bins); for(size_t j=0; j= energyMin); EXPECT_TRUE(test_energy <= energyMax); } @@ -151,9 +151,9 @@ TEST(PowerLaw, SampleDistribution) { } for(size_t j=0; j detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const = 0; - virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const; virtual std::vector DensityVariables() const; virtual std::string Name() const = 0; template @@ -136,21 +135,19 @@ friend cereal::access; virtual bool less(WeightableDistribution const & distribution) const override; }; -class InjectionDistribution : virtual public WeightableDistribution { +class PrimaryInjectionDistribution : virtual public WeightableDistribution { friend cereal::access; private: public: - virtual ~InjectionDistribution() {}; - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const; - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const; - virtual bool IsPositionDistribution() const {return false;} - virtual std::shared_ptr clone() const = 0; + virtual ~PrimaryInjectionDistribution() {}; + virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const = 0; + virtual std::shared_ptr clone() const = 0; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { archive(cereal::virtual_base_class(this)); } else { - throw std::runtime_error("InjectionDistribution only supports version <= 0!"); + throw std::runtime_error("PrimaryInjectionDistribution only supports version <= 0!"); } } template @@ -158,9 +155,38 @@ friend cereal::access; if(version == 0) { archive(cereal::virtual_base_class(this)); } else { - throw std::runtime_error("InjectionDistribution only supports version <= 0!"); + throw std::runtime_error("PrimaryInjectionDistribution only supports version <= 0!"); } } + virtual bool equal(WeightableDistribution const & distribution) const override = 0; + virtual bool less(WeightableDistribution const & distribution) const override = 0; +}; + +class SecondaryInjectionDistribution : virtual public WeightableDistribution { +friend cereal::access; +private: +public: + virtual ~SecondaryInjectionDistribution() {}; + virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const = 0; + virtual std::shared_ptr clone() const = 0; + template + void save(Archive & archive, std::uint32_t const version) const { + if(version == 0) { + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryInjectionDistribution only supports version <= 0!"); + } + } + template + void load(Archive & archive, std::uint32_t const version) { + if(version == 0) { + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryInjectionDistribution only supports version <= 0!"); + } + } + virtual bool equal(WeightableDistribution const & distribution) const override = 0; + virtual bool less(WeightableDistribution const & distribution) const override = 0; }; } // namespace distributions @@ -175,9 +201,13 @@ CEREAL_REGISTER_TYPE(LI::distributions::NormalizationConstant); CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::WeightableDistribution, LI::distributions::NormalizationConstant); CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PhysicallyNormalizedDistribution, LI::distributions::NormalizationConstant); -CEREAL_CLASS_VERSION(LI::distributions::InjectionDistribution, 0); -CEREAL_REGISTER_TYPE(LI::distributions::InjectionDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::WeightableDistribution, LI::distributions::InjectionDistribution); +CEREAL_CLASS_VERSION(LI::distributions::PrimaryInjectionDistribution, 0); +CEREAL_REGISTER_TYPE(LI::distributions::PrimaryInjectionDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::WeightableDistribution, LI::distributions::PrimaryInjectionDistribution); + +CEREAL_CLASS_VERSION(LI::distributions::SecondaryInjectionDistribution, 0); +CEREAL_REGISTER_TYPE(LI::distributions::SecondaryInjectionDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::WeightableDistribution, LI::distributions::SecondaryInjectionDistribution); #endif // LI_Distributions_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/direction/Cone.h b/projects/distributions/public/LeptonInjector/distributions/primary/direction/Cone.h index abf24b04b..52ed3ce56 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/direction/Cone.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/direction/Cone.h @@ -16,9 +16,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -35,9 +35,9 @@ friend cereal::access; double opening_angle; public: Cone(LI::math::Vector3D dir, double opening_angle); - LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; std::string Name() const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/direction/FixedDirection.h b/projects/distributions/public/LeptonInjector/distributions/primary/direction/FixedDirection.h index 5111dccab..cbecd7c0a 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/direction/FixedDirection.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/direction/FixedDirection.h @@ -16,9 +16,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -34,10 +34,10 @@ friend cereal::access; public: FixedDirection(LI::math::Vector3D dir) : dir(dir) {}; private: - LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; virtual std::vector DensityVariables() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; std::string Name() const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/direction/IsotropicDirection.h b/projects/distributions/public/LeptonInjector/distributions/primary/direction/IsotropicDirection.h index 77e00d136..762b0fe5e 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/direction/IsotropicDirection.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/direction/IsotropicDirection.h @@ -16,9 +16,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -31,9 +31,9 @@ namespace distributions { class IsotropicDirection : virtual public PrimaryDirectionDistribution { friend cereal::access; public: - LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; std::string Name() const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/direction/PrimaryDirectionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/direction/PrimaryDirectionDistribution.h index 531da96ea..5591246f1 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/direction/PrimaryDirectionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/direction/PrimaryDirectionDistribution.h @@ -8,10 +8,10 @@ #include // for uint32_t #include // for runtime_error -#include "LeptonInjector/distributions/Distributions.h" // for WeightableDi... +#include "LeptonInjector/distributions/Distributions.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace math { class Vector3D; } } namespace LI { namespace utilities { class LI_random; } } @@ -30,7 +30,7 @@ class DetectorModel; } // namespace detector namespace dataclasses { -struct InteractionRecord; +class InteractionRecord; struct InteractionSignature; } namespace interactions { @@ -41,23 +41,23 @@ class InteractionCollection; namespace LI { namespace distributions { -class PrimaryDirectionDistribution : virtual public InjectionDistribution { +class PrimaryDirectionDistribution : virtual public PrimaryInjectionDistribution { friend cereal::access; public: virtual ~PrimaryDirectionDistribution() {}; protected: PrimaryDirectionDistribution() {}; private: - virtual LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const = 0; + virtual LI::math::Vector3D SampleDirection(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const = 0; public: - void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override = 0; virtual std::vector DensityVariables() const override; - virtual std::shared_ptr clone() const override = 0; + virtual std::shared_ptr clone() const override = 0; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryDirectionDistribution only supports version <= 0!"); } @@ -65,7 +65,7 @@ friend cereal::access; template void load(Archive & archive, std::uint32_t const version) { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryDirectionDistribution only supports version <= 0!"); } @@ -80,6 +80,6 @@ friend cereal::access; CEREAL_CLASS_VERSION(LI::distributions::PrimaryDirectionDistribution, 0); CEREAL_REGISTER_TYPE(LI::distributions::PrimaryDirectionDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::PrimaryDirectionDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PrimaryInjectionDistribution, LI::distributions::PrimaryDirectionDistribution); #endif // LI_PrimaryDirectionDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.h index bb57ee316..3511f8b88 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/energy/ModifiedMoyalPlusExponentialEnergyDistribution.h @@ -16,9 +16,9 @@ #include "LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -43,11 +43,11 @@ friend cereal::access; double pdf(double energy) const; double pdf_integral() const; public: - double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; ModifiedMoyalPlusExponentialEnergyDistribution(double energyMin, double energyMax, double mu, double sigma, double A, double l, double B, bool has_physical_normalization=false); std::string Name() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/energy/Monoenergetic.h b/projects/distributions/public/LeptonInjector/distributions/primary/energy/Monoenergetic.h index 1cb5ce2e0..4fd77cace 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/energy/Monoenergetic.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/energy/Monoenergetic.h @@ -15,9 +15,9 @@ #include "LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -33,10 +33,10 @@ friend cereal::access; public: Monoenergetic(double gen_energy); double pdf(double energy) const; - double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + virtual double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; std::string Name() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/energy/PowerLaw.h b/projects/distributions/public/LeptonInjector/distributions/primary/energy/PowerLaw.h index ffc13079d..e0fd083ea 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/energy/PowerLaw.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/energy/PowerLaw.h @@ -15,9 +15,10 @@ #include "LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class PrimaryDistributionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -35,11 +36,11 @@ friend cereal::access; public: PowerLaw(double powerLawIndex, double energyMin, double energyMax); double pdf(double energy) const; - double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; std::string Name() const override; void SetNormalizationAtEnergy(double normalization, double energy); - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h index 1ffd357c7..3ba3a0720 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/energy/PrimaryEnergyDistribution.h @@ -16,7 +16,7 @@ #include "LeptonInjector/distributions/Distributions.h" // for WeightableDi... namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace utilities { class LI_random; } } namespace cereal { class access; } @@ -24,22 +24,22 @@ namespace cereal { class access; } namespace LI { namespace distributions { -class PrimaryEnergyDistribution : virtual public InjectionDistribution, virtual public PhysicallyNormalizedDistribution { +class PrimaryEnergyDistribution : virtual public PrimaryInjectionDistribution, virtual public PhysicallyNormalizedDistribution { friend cereal::access; public: virtual ~PrimaryEnergyDistribution() {}; private: - virtual double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const = 0; + virtual double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const = 0; public: - void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override = 0; virtual std::vector DensityVariables() const override; virtual std::string Name() const override = 0; - virtual std::shared_ptr clone() const override = 0; + virtual std::shared_ptr clone() const override = 0; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryEnergyDistribution only supports version <= 0!"); @@ -48,7 +48,7 @@ friend cereal::access; template void load(Archive & archive, std::uint32_t const version) { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryEnergyDistribution only supports version <= 0!"); @@ -64,7 +64,7 @@ friend cereal::access; CEREAL_CLASS_VERSION(LI::distributions::PrimaryEnergyDistribution, 0); CEREAL_REGISTER_TYPE(LI::distributions::PrimaryEnergyDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::PrimaryEnergyDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PrimaryInjectionDistribution, LI::distributions::PrimaryEnergyDistribution); CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PhysicallyNormalizedDistribution, LI::distributions::PrimaryEnergyDistribution); #endif // LI_PrimaryEnergyDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/energy/TabulatedFluxDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/energy/TabulatedFluxDistribution.h index 169105d3a..13ecd7b6b 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/energy/TabulatedFluxDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/energy/TabulatedFluxDistribution.h @@ -18,9 +18,9 @@ #include "LeptonInjector/utilities/Interpolator.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -56,13 +56,13 @@ friend cereal::access; std::vector GetCDF() const; std::vector GetEnergyNodes() const; std::vector GetCDFEnergyNodes() const; - double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + double SampleEnergy(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; void SetEnergyBounds(double energyMin, double energyMax); TabulatedFluxDistribution(std::string fluxTableFilename, bool has_physical_normalization=false); TabulatedFluxDistribution(double energyMin, double energyMax, std::string fluxTableFilename, bool has_physical_normalization=false); std::string Name() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h index 615c17493..342e32e70 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h @@ -16,27 +16,27 @@ #include "LeptonInjector/distributions/Distributions.h" // for InjectionDis... namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace utilities { class LI_random; } } namespace LI { namespace distributions { -class PrimaryNeutrinoHelicityDistribution : virtual public InjectionDistribution { +class PrimaryNeutrinoHelicityDistribution : virtual public PrimaryInjectionDistribution { friend cereal::access; public: - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; PrimaryNeutrinoHelicityDistribution(); PrimaryNeutrinoHelicityDistribution(const PrimaryNeutrinoHelicityDistribution &) = default; virtual std::vector DensityVariables() const override; std::string Name() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryNeutrinoHelicityDistribution only supports version <= 0!"); } @@ -44,7 +44,7 @@ friend cereal::access; template void load(Archive & archive, std::uint32_t const version) { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("PrimaryNeutrinoHelicityDistribution only supports version <= 0!"); } @@ -59,6 +59,6 @@ friend cereal::access; CEREAL_CLASS_VERSION(LI::distributions::PrimaryNeutrinoHelicityDistribution, 0); CEREAL_REGISTER_TYPE(LI::distributions::PrimaryNeutrinoHelicityDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::PrimaryNeutrinoHelicityDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PrimaryInjectionDistribution, LI::distributions::PrimaryNeutrinoHelicityDistribution); #endif // LI_PrimaryNeutrinoHelicityDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/type/PrimaryInjector.h b/projects/distributions/public/LeptonInjector/distributions/primary/mass/PrimaryMass.h similarity index 59% rename from projects/distributions/public/LeptonInjector/distributions/primary/type/PrimaryInjector.h rename to projects/distributions/public/LeptonInjector/distributions/primary/mass/PrimaryMass.h index b82dc73e3..42ebcc391 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/type/PrimaryInjector.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/mass/PrimaryMass.h @@ -1,6 +1,6 @@ #pragma once -#ifndef LI_PrimaryInjector_H -#define LI_PrimaryInjector_H +#ifndef LI_PrimaryMass_H +#define LI_PrimaryMass_H #include // for string #include // for shared_ptr @@ -17,50 +17,45 @@ #include "LeptonInjector/distributions/Distributions.h" // for InjectionDis... namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace utilities { class LI_random; } } namespace LI { namespace distributions { -class PrimaryInjector : virtual public InjectionDistribution { +class PrimaryMass : virtual public PrimaryInjectionDistribution { friend cereal::access; protected: - PrimaryInjector() {}; + PrimaryMass() {}; private: - LI::dataclasses::Particle::ParticleType primary_type; double primary_mass; public: - PrimaryInjector(LI::dataclasses::Particle::ParticleType primary_type, double primary_mass = 0); - LI::dataclasses::Particle::ParticleType PrimaryType() const; - double PrimaryMass() const; - void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + PrimaryMass(double primary_mass = 0); + double GetPrimaryMass() const; + void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; virtual std::vector DensityVariables() const override; virtual std::string Name() const override; - virtual std::shared_ptr clone() const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { - archive(::cereal::make_nvp("PrimaryType", primary_type)); archive(::cereal::make_nvp("PrimaryMass", primary_mass)); - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { - throw std::runtime_error("PrimaryInjector only supports version <= 0!"); + throw std::runtime_error("PrimaryMass only supports version <= 0!"); } } template - static void load_and_construct(Archive & archive, cereal::construct & construct, std::uint32_t const version) { + static void load_and_construct(Archive & archive, cereal::construct & construct, std::uint32_t const version) { if(version == 0) { - LI::dataclasses::Particle::ParticleType t; double m; - archive(::cereal::make_nvp("PrimaryType", t)); archive(::cereal::make_nvp("PrimaryMass", m)); - construct(t, m); - archive(cereal::virtual_base_class(construct.ptr())); + construct(m); + archive(cereal::virtual_base_class(construct.ptr())); } else { - throw std::runtime_error("PrimaryInjector only supports version <= 0!"); + throw std::runtime_error("PrimaryMass only supports version <= 0!"); } } protected: @@ -71,8 +66,8 @@ friend cereal::access; } // namespace distributions } // namespace LI -CEREAL_CLASS_VERSION(LI::distributions::PrimaryInjector, 0); -CEREAL_REGISTER_TYPE(LI::distributions::PrimaryInjector); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::PrimaryInjector); +CEREAL_CLASS_VERSION(LI::distributions::PrimaryMass, 0); +CEREAL_REGISTER_TYPE(LI::distributions::PrimaryMass); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PrimaryInjectionDistribution, LI::distributions::PrimaryMass); -#endif // LI_PrimaryInjector_H +#endif // LI_PrimaryMass_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/ColumnDepthPositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/ColumnDepthPositionDistribution.h index beb1e7b4b..35774cfc3 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/ColumnDepthPositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/ColumnDepthPositionDistribution.h @@ -3,10 +3,10 @@ #define LI_ColumnDepthPositionDistribution_H #include +#include #include #include #include -#include #include #include @@ -21,9 +21,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -42,14 +42,14 @@ friend cereal::access; LI::math::Vector3D SampleFromDisk(std::shared_ptr rand, LI::math::Vector3D const & dir) const; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: - LI::math::Vector3D GetSamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record); + std::tuple GetSamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record); virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; ColumnDepthPositionDistribution(double radius, double endcap_length, std::shared_ptr depth_function, std::set target_types); std::string Name() const override; - virtual std::shared_ptr clone() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/CylinderVolumePositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/CylinderVolumePositionDistribution.h index 429d34e58..d214fc1d2 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/CylinderVolumePositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/CylinderVolumePositionDistribution.h @@ -2,10 +2,10 @@ #ifndef LI_CylinderVolumePositionDistribution_H #define LI_CylinderVolumePositionDistribution_H +#include #include #include #include -#include #include #include @@ -18,9 +18,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -33,13 +33,13 @@ friend cereal::access; CylinderVolumePositionDistribution() {}; private: LI::geometry::Cylinder cylinder; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; CylinderVolumePositionDistribution(LI::geometry::Cylinder); std::string Name() const override; - virtual std::shared_ptr clone() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; virtual bool AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h index b46597064..880e9bb0e 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h @@ -14,7 +14,7 @@ #include "LeptonInjector/distributions/primary/vertex/RangeFunction.h" -namespace LI { namespace dataclasses { struct InteractionSignature; } } +namespace LI { namespace dataclasses { enum class ParticleType : int32_t; } } namespace LI { namespace distributions { @@ -31,9 +31,9 @@ friend cereal::access; public: DecayRangeFunction(double particle_mass, double decay_width, double multiplier, double max_distance); static double DecayLength(double mass, double width, double energy); - double operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const override; - double DecayLength(LI::dataclasses::InteractionSignature const & signature, double energy) const; - double Range(LI::dataclasses::InteractionSignature const & signature, double energy) const; + double operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const override; + double DecayLength(LI::dataclasses::ParticleType const & primary_type, double energy) const; + double Range(LI::dataclasses::ParticleType const & primary_type, double energy) const; double Multiplier() const; double ParticleMass() const; double DecayWidth() const; diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangePositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangePositionDistribution.h index 90844554b..824df5af5 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangePositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DecayRangePositionDistribution.h @@ -3,9 +3,9 @@ #define LI_DecayRangePositionDistribution_H #include +#include #include #include -#include #include #include @@ -21,9 +21,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -38,15 +38,15 @@ class DecayRangePositionDistribution : virtual public VertexPositionDistribution LI::math::Vector3D SampleFromDisk(std::shared_ptr rand, LI::math::Vector3D const & dir) const; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; DecayRangePositionDistribution(); DecayRangePositionDistribution(const DecayRangePositionDistribution &) = default; DecayRangePositionDistribution(double radius, double endcap_length, std::shared_ptr range_function); std::string Name() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; - virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override; virtual bool AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DepthFunction.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DepthFunction.h index f40620315..42ae00ed5 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DepthFunction.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/DepthFunction.h @@ -12,7 +12,7 @@ #include #include -namespace LI { namespace dataclasses { struct InteractionSignature; } } +namespace LI { namespace dataclasses { enum class ParticleType : int32_t; } } namespace LI { namespace distributions { @@ -23,7 +23,7 @@ friend cereal::access; virtual ~DepthFunction() {}; public: DepthFunction(); - virtual double operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const; + virtual double operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/LeptonDepthFunction.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/LeptonDepthFunction.h index 07fc21c5f..6e44d85ee 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/LeptonDepthFunction.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/LeptonDepthFunction.h @@ -15,11 +15,9 @@ #include #include -#include "LeptonInjector/dataclasses/Particle.h" +#include "LeptonInjector/dataclasses/ParticleType.h" #include "LeptonInjector/distributions/primary/vertex/DepthFunction.h" -namespace LI { namespace dataclasses { struct InteractionSignature; } } - namespace LI { namespace distributions { @@ -32,10 +30,10 @@ friend cereal::access; double tau_beta = 2.6315789473684212e-7; double scale = 1.0; double max_depth = 3e7; - std::set tau_primaries = {LI::dataclasses::Particle::ParticleType::NuTau, LI::dataclasses::Particle::ParticleType::NuTauBar}; + std::set tau_primaries = {LI::dataclasses::ParticleType::NuTau, LI::dataclasses::ParticleType::NuTauBar}; public: LeptonDepthFunction(); - double GetLeptonDepthFunctionReturnValue(LI::dataclasses::InteractionSignature const & signature, double energy) const; + double GetLeptonDepthFunctionReturnValue(LI::dataclasses::ParticleType const & primary_type, double energy) const; void SetMuParams(double mu_alpha, double mu_beta); void SetTauParams(double tau_alpha, double tau_beta); void SetScale(double scale); @@ -46,7 +44,7 @@ friend cereal::access; double GetTauBeta() const; double GetScale() const; double GetMaxDepth() const; - virtual double operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const override; + virtual double operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/OrientedCylinderPositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/OrientedCylinderPositionDistribution.h index df72344c7..16677f5c2 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/OrientedCylinderPositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/OrientedCylinderPositionDistribution.h @@ -2,10 +2,10 @@ #ifndef LI_OrientedPositionDistribution_H #define LI_OrientedPositionDistribution_H +#include #include #include #include -#include #include #include @@ -17,9 +17,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -32,15 +32,15 @@ friend cereal::access; double radius; LI::math::Vector3D SampleFromDisk(std::shared_ptr rand, LI::math::Vector3D const & dir) const; - virtual std::pair GetBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record, LI::math::Vector3D & point_of_closest_approach) const = 0; - virtual void SampleWithinBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record, std::pair boundaries) const = 0; - virtual LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + virtual std::tuple GetBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record, LI::math::Vector3D & point_of_closest_approach) const = 0; + virtual void SampleWithinBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record, std::tuple boundaries) const = 0; + virtual std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: - virtual double PositionProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record, std::pair boundaries) const = 0; + virtual double PositionProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record, std::tuple boundaries) const = 0; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; virtual std::string Name() const override = 0; - virtual std::shared_ptr clone() const override = 0; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override = 0; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; virtual bool AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h index 44e5f62b9..fd233d08e 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h @@ -3,9 +3,9 @@ #define LI_PointSourcePositionDistribution_H #include +#include #include #include -#include #include #include @@ -20,9 +20,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -38,15 +38,15 @@ friend cereal::access; LI::math::Vector3D SampleFromDisk(std::shared_ptr rand, LI::math::Vector3D const & dir) const; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; PointSourcePositionDistribution(); PointSourcePositionDistribution(const PointSourcePositionDistribution &) = default; PointSourcePositionDistribution(LI::math::Vector3D origin, double max_distance, std::set target_types); std::string Name() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; - virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangeFunction.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangeFunction.h index 07c31da3e..d5683fbf7 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangeFunction.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangeFunction.h @@ -12,7 +12,7 @@ #include #include -namespace LI { namespace dataclasses { struct InteractionSignature; } } +namespace LI { namespace dataclasses { enum class ParticleType : int32_t; } } namespace LI { namespace distributions { @@ -23,7 +23,7 @@ friend cereal::access; virtual ~RangeFunction() {}; public: RangeFunction(); - virtual double operator()(LI::dataclasses::InteractionSignature const & signature, double energy) const; + virtual double operator()(LI::dataclasses::ParticleType const & primary_type, double energy) const; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h index 7c29682c9..9c2881c0c 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h @@ -3,10 +3,10 @@ #define LI_RangePositionDistribution_H #include +#include #include #include #include -#include #include #include @@ -21,9 +21,9 @@ #include "LeptonInjector/math/Vector3D.h" namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace utilities { class LI_random; } } @@ -40,15 +40,15 @@ friend cereal::access; LI::math::Vector3D SampleFromDisk(std::shared_ptr rand, LI::math::Vector3D const & dir) const; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; + std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; public: virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; RangePositionDistribution(); RangePositionDistribution(const RangePositionDistribution &) = default; RangePositionDistribution(double radius, double endcap_length, std::shared_ptr range_function, std::set target_types); std::string Name() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; - virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::shared_ptr clone() const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h deleted file mode 100644 index 98cee9d13..000000000 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#ifndef LI_SecondaryPositionDistribution_H -#define LI_SecondaryPositionDistribution_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "LeptonInjector/dataclasses/InteractionTree.h" -#include "LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h" -#include "LeptonInjector/math/Vector3D.h" - -namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } -namespace LI { namespace distributions { class WeightableDistribution; } } -namespace LI { namespace geometry { class Geometry; } } -namespace LI { namespace utilities { class LI_random; } } - -namespace LI { -namespace distributions { - -class SecondaryPositionDistribution : virtual public VertexPositionDistribution { -friend cereal::access; -private: - double max_length = std::numeric_limits::infinity(); - std::shared_ptr fiducial = NULL; - - - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; - LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const override; -public: - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const override; - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; - virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; - virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const override; - SecondaryPositionDistribution(); - SecondaryPositionDistribution(const SecondaryPositionDistribution &) = default; - SecondaryPositionDistribution(double max_length); - SecondaryPositionDistribution(double max_length, std::shared_ptr fiducial); - SecondaryPositionDistribution(std::shared_ptr fiducial); - std::string Name() const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const override; - virtual std::shared_ptr clone() const override; - template - void save(Archive & archive, std::uint32_t const version) const { - if(version == 0) { - archive(::cereal::make_nvp("MaxLength", max_length)); - archive(cereal::virtual_base_class(this)); - } else { - throw std::runtime_error("SecondaryPositionDistribution only supports version <= 0!"); - } - } - template - static void load_and_construct(Archive & archive, cereal::construct & construct, std::uint32_t const version) { - if(version == 0) { - double max_length; - archive(::cereal::make_nvp("MaxLength", max_length)); - construct(max_length); - archive(cereal::virtual_base_class(construct.ptr())); - } else { - throw std::runtime_error("SecondaryPositionDistribution only supports version <= 0!"); - } - } -protected: - virtual bool equal(WeightableDistribution const & distribution) const override; - virtual bool less(WeightableDistribution const & distribution) const override; -}; - -} // namespace distributions -} // namespace LI - -CEREAL_CLASS_VERSION(LI::distributions::SecondaryPositionDistribution, 0); -CEREAL_REGISTER_TYPE(LI::distributions::SecondaryPositionDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::VertexPositionDistribution, LI::distributions::SecondaryPositionDistribution); - -#endif // LI_SecondaryPositionDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h index 77e9ad5d0..b30212069 100644 --- a/projects/distributions/public/LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h +++ b/projects/distributions/public/LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h @@ -2,11 +2,11 @@ #ifndef LI_VertexPositionDistribution_H #define LI_VertexPositionDistribution_H +#include // for tuple #include // for shared_ptr #include // for string #include // for vector #include // for uint32_t -#include // for pair #include // for runtime_error #include @@ -19,34 +19,32 @@ #include "LeptonInjector/math/Vector3D.h" // for Vector3D namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace utilities { class LI_random; } } namespace LI { namespace distributions { -class VertexPositionDistribution : virtual public InjectionDistribution { +class VertexPositionDistribution : virtual public PrimaryInjectionDistribution { friend cereal::access; public: virtual ~VertexPositionDistribution() {}; private: - virtual LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const = 0; - virtual LI::math::Vector3D SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum & datum) const; + virtual std::tuple SamplePosition(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const = 0; public: - virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; - virtual bool IsPositionDistribution() const override {return true;} + virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::PrimaryDistributionRecord & record) const override; virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override = 0; virtual std::vector DensityVariables() const override; virtual std::string Name() const override = 0; - virtual std::shared_ptr clone() const override = 0; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const = 0; - virtual std::pair InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const; + virtual std::shared_ptr clone() const override = 0; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const = 0; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionTreeDatum const & datum) const; virtual bool AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("VertexPositionDistribution only supports version <= 0!"); } @@ -54,7 +52,7 @@ friend cereal::access; template void load(Archive & archive, std::uint32_t const version) { if(version == 0) { - archive(cereal::virtual_base_class(this)); + archive(cereal::virtual_base_class(this)); } else { throw std::runtime_error("VertexPositionDistribution only supports version <= 0!"); } @@ -69,6 +67,6 @@ friend cereal::access; CEREAL_CLASS_VERSION(LI::distributions::VertexPositionDistribution, 0); CEREAL_REGISTER_TYPE(LI::distributions::VertexPositionDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::VertexPositionDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::PrimaryInjectionDistribution, LI::distributions::VertexPositionDistribution); #endif // LI_VertexPositionDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryBoundedVertexDistribution.h b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryBoundedVertexDistribution.h new file mode 100644 index 000000000..9eda8f1e3 --- /dev/null +++ b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryBoundedVertexDistribution.h @@ -0,0 +1,86 @@ +#pragma once +#ifndef LI_SecondaryBoundedVertexDistribution_H +#define LI_SecondaryBoundedVertexDistribution_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionTree.h" +#include "LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h" +#include "LeptonInjector/math/Vector3D.h" + +namespace LI { namespace interactions { class InteractionCollection; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace detector { class DetectorModel; } } +namespace LI { namespace distributions { class SecondaryInjectionDistribution; } } +namespace LI { namespace distributions { class WeightableDistribution; } } +namespace LI { namespace geometry { class Geometry; } } +namespace LI { namespace utilities { class LI_random; } } + +namespace LI { +namespace distributions { + +class SecondaryBoundedVertexDistribution : virtual public SecondaryVertexPositionDistribution { +friend cereal::access; +private: + std::shared_ptr fiducial_volume = nullptr; + double max_length = std::numeric_limits::infinity(); +public: + + SecondaryBoundedVertexDistribution(); + SecondaryBoundedVertexDistribution(const SecondaryBoundedVertexDistribution &) = default; + SecondaryBoundedVertexDistribution(double max_length); + SecondaryBoundedVertexDistribution(std::shared_ptr fiducial_volume); + SecondaryBoundedVertexDistribution(std::shared_ptr fiducial_volume, double max_length); + + virtual void SampleVertex(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const override; + virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + + std::string Name() const override; + virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + + template + void save(Archive & archive, std::uint32_t const version) const { + if(version == 0) { + archive(::cereal::make_nvp("MaxLength", max_length)); + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryBoundedVertexDistribution only supports version <= 0!"); + } + } + template + static void load_and_construct(Archive & archive, cereal::construct & construct, std::uint32_t const version) { + if(version == 0) { + double max_length; + archive(::cereal::make_nvp("MaxLength", max_length)); + construct(max_length); + archive(cereal::virtual_base_class(construct.ptr())); + } else { + throw std::runtime_error("SecondaryBoundedVertexDistribution only supports version <= 0!"); + } + } +protected: + virtual bool equal(WeightableDistribution const & distribution) const override; + virtual bool less(WeightableDistribution const & distribution) const override; +}; + +} // namespace distributions +} // namespace LI + +CEREAL_CLASS_VERSION(LI::distributions::SecondaryBoundedVertexDistribution, 0); +CEREAL_REGISTER_TYPE(LI::distributions::SecondaryBoundedVertexDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::SecondaryVertexPositionDistribution, LI::distributions::SecondaryBoundedVertexDistribution); + +#endif // LI_SecondaryBoundedVertexDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h new file mode 100644 index 000000000..528cb4be4 --- /dev/null +++ b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h @@ -0,0 +1,77 @@ +#pragma once +#ifndef LI_SecondaryPhysicalVertexDistribution_H +#define LI_SecondaryPhysicalVertexDistribution_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionTree.h" +#include "LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h" +#include "LeptonInjector/math/Vector3D.h" + +namespace LI { namespace interactions { class InteractionCollection; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace detector { class DetectorModel; } } +namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class WeightableDistribution; } } +namespace LI { namespace geometry { class Geometry; } } +namespace LI { namespace utilities { class LI_random; } } + +namespace LI { +namespace distributions { + +class SecondaryPhysicalVertexDistribution : virtual public SecondaryVertexPositionDistribution { +friend cereal::access; +public: + + SecondaryPhysicalVertexDistribution(); + SecondaryPhysicalVertexDistribution(const SecondaryPhysicalVertexDistribution &) = default; + + virtual void SampleVertex(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const override; + virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; + + std::string Name() const override; + virtual std::shared_ptr clone() const override; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const override; + + template + void save(Archive & archive, std::uint32_t const version) const { + if(version == 0) { + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryPhysicalVertexDistribution only supports version <= 0!"); + } + } + template + static void load_and_construct(Archive & archive, cereal::construct & construct, std::uint32_t const version) { + if(version == 0) { + construct(); + archive(cereal::virtual_base_class(construct.ptr())); + } else { + throw std::runtime_error("SecondaryPhysicalVertexDistribution only supports version <= 0!"); + } + } +protected: + virtual bool equal(WeightableDistribution const & distribution) const override; + virtual bool less(WeightableDistribution const & distribution) const override; +}; + +} // namespace distributions +} // namespace LI + +CEREAL_CLASS_VERSION(LI::distributions::SecondaryPhysicalVertexDistribution, 0); +CEREAL_REGISTER_TYPE(LI::distributions::SecondaryPhysicalVertexDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::SecondaryVertexPositionDistribution, LI::distributions::SecondaryPhysicalVertexDistribution); + +#endif // LI_SecondaryPhysicalVertexDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h new file mode 100644 index 000000000..fd477621a --- /dev/null +++ b/projects/distributions/public/LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h @@ -0,0 +1,75 @@ +#pragma once +#ifndef LI_SecondaryVertexPositionDistribution_H +#define LI_SecondaryVertexPositionDistribution_H + +#include +#include // for shared_ptr +#include // for string +#include // for vector +#include // for uint32_t +#include // for runtime_error + +#include +#include +#include +#include + +#include "LeptonInjector/dataclasses/InteractionTree.h" // for InteractionT... +#include "LeptonInjector/distributions/Distributions.h" // for WeightableDi... +#include "LeptonInjector/math/Vector3D.h" // for Vector3D + +namespace LI { namespace interactions { class InteractionCollection; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace detector { class DetectorModel; } } +namespace LI { namespace utilities { class LI_random; } } + +namespace LI { +namespace distributions { + +class SecondaryVertexPositionDistribution : virtual public SecondaryInjectionDistribution { +friend cereal::access; +public: + virtual ~SecondaryVertexPositionDistribution() {}; +public: + virtual void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const override; + + virtual void SampleVertex(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::SecondaryDistributionRecord & record) const = 0; + virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override = 0; + + virtual std::vector DensityVariables() const override; + + virtual std::string Name() const override = 0; + virtual std::shared_ptr clone() const override = 0; + virtual std::tuple InjectionBounds(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & interaction) const = 0; + + virtual bool AreEquivalent(std::shared_ptr detector_model, std::shared_ptr interactions, std::shared_ptr distribution, std::shared_ptr second_detector_model, std::shared_ptr second_interactions) const override; + + template + void save(Archive & archive, std::uint32_t const version) const { + if(version == 0) { + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryVertexPositionDistribution only supports version <= 0!"); + } + } + template + void load(Archive & archive, std::uint32_t const version) { + if(version == 0) { + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryVertexPositionDistribution only supports version <= 0!"); + } + } +protected: + virtual bool equal(WeightableDistribution const & distribution) const override = 0; + virtual bool less(WeightableDistribution const & distribution) const override = 0; +}; + +} // namespace distributions +} // namespace LI + +CEREAL_CLASS_VERSION(LI::distributions::SecondaryVertexPositionDistribution, 0); +CEREAL_REGISTER_TYPE(LI::distributions::SecondaryVertexPositionDistribution); +CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::SecondaryInjectionDistribution, LI::distributions::SecondaryVertexPositionDistribution); + +#endif // LI_SecondaryVertexPositionDistribution_H diff --git a/projects/distributions/public/LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h b/projects/distributions/public/LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h deleted file mode 100644 index 27c65e52e..000000000 --- a/projects/distributions/public/LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#ifndef LI_TargetMomentumDistribution_H -#define LI_TargetMomentumDistribution_H - -#include // for array -#include -#include -#include // for vector -#include // for uint32_t -#include // for runtime_error - -#include -#include -#include -#include -#include - -#include "LeptonInjector/distributions/Distributions.h" // for InjectionDis... - -namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace utilities { class LI_random; } } - -namespace LI { -namespace distributions { - -class TargetMomentumDistribution : virtual public InjectionDistribution { -friend cereal::access; -private: - virtual std::array SampleMomentum(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const = 0; -public: - void Sample(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord & record) const override; - virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override = 0; - virtual std::vector DensityVariables() const override; - template - void save(Archive & archive, std::uint32_t const version) const { - if(version == 0) { - archive(cereal::virtual_base_class(this)); - } else { - throw std::runtime_error("TargetMomentumDistribution only supports version <= 0!"); - } - } - template - void load(Archive & archive, std::uint32_t const version) { - if(version == 0) { - archive(cereal::virtual_base_class(this)); - } else { - throw std::runtime_error("TargetMomentumDistribution only supports version <= 0!"); - } - } -protected: - virtual bool equal(WeightableDistribution const & distribution) const override = 0; - virtual bool less(WeightableDistribution const & distribution) const override = 0; -}; - -class TargetAtRest : virtual public TargetMomentumDistribution { -friend cereal::access; -private: - virtual std::array SampleMomentum(std::shared_ptr rand, std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; -public: - virtual double GenerationProbability(std::shared_ptr detector_model, std::shared_ptr interactions, LI::dataclasses::InteractionRecord const & record) const override; - virtual std::vector DensityVariables() const override; - virtual std::shared_ptr clone() const override; - std::string Name() const override; - template - void save(Archive & archive, std::uint32_t const version) const { - if(version == 0) { - archive(cereal::virtual_base_class(this)); - } else { - throw std::runtime_error("TargetAtRest only supports version <= 0!"); - } - } - template - void load(Archive & archive, std::uint32_t const version) { - if(version == 0) { - archive(cereal::virtual_base_class(this)); - } else { - throw std::runtime_error("TargetAtRest only supports version <= 0!"); - } - } -protected: - virtual bool equal(WeightableDistribution const & distribution) const override; - virtual bool less(WeightableDistribution const & distribution) const override; -}; - -} // namespace distributions -} // namespace LI - -CEREAL_CLASS_VERSION(LI::distributions::TargetMomentumDistribution, 0); -CEREAL_REGISTER_TYPE(LI::distributions::TargetMomentumDistribution); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::InjectionDistribution, LI::distributions::TargetMomentumDistribution); - -CEREAL_CLASS_VERSION(LI::distributions::TargetAtRest, 0); -CEREAL_REGISTER_TYPE(LI::distributions::TargetAtRest); -CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::distributions::TargetMomentumDistribution, LI::distributions::TargetAtRest); - -#endif // LI_TargetMomentumDistribution_H diff --git a/projects/injection/private/ColumnDepthLeptonInjector.cxx b/projects/injection/private/ColumnDepthLeptonInjector.cxx index 0105022f4..0de0d621b 100644 --- a/projects/injection/private/ColumnDepthLeptonInjector.cxx +++ b/projects/injection/private/ColumnDepthLeptonInjector.cxx @@ -1,9 +1,9 @@ #include "LeptonInjector/injection/ColumnDepthLeptonInjector.h" #include +#include #include #include -#include #include "LeptonInjector/interactions/InteractionCollection.h" #include "LeptonInjector/dataclasses/Particle.h" @@ -12,7 +12,7 @@ #include "LeptonInjector/injection/Process.h" #include "LeptonInjector/math/Vector3D.h" -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace distributions { class DepthFunction; } } @@ -27,8 +27,8 @@ ColumnDepthLeptonInjector::ColumnDepthLeptonInjector() {} ColumnDepthLeptonInjector::ColumnDepthLeptonInjector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, - std::vector> secondary_processes, + std::shared_ptr primary_process, + std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr depth_func, double disk_radius, @@ -41,7 +41,7 @@ ColumnDepthLeptonInjector::ColumnDepthLeptonInjector( interactions = primary_process->GetInteractions(); std::set target_types = interactions->TargetTypes(); position_distribution = std::make_shared(disk_radius, endcap_length, depth_func, target_types); - primary_process->AddInjectionDistribution(position_distribution); + primary_process->AddPrimaryInjectionDistribution(position_distribution); SetPrimaryProcess(primary_process); for(auto & sec_process : secondary_processes) { AddSecondaryProcess(sec_process); @@ -49,7 +49,7 @@ ColumnDepthLeptonInjector::ColumnDepthLeptonInjector( // Otherwise uncomment below /* target_types = sec_process->GetInteractions()->TargetTypes(); - sec_process->GetInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, depth_func, target_types)); + sec_process->GetPrimaryInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, depth_func, target_types)); */ } } @@ -58,7 +58,7 @@ std::string ColumnDepthLeptonInjector::Name() const { return("ColumnDepthInjector"); } -std::pair ColumnDepthLeptonInjector::InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple ColumnDepthLeptonInjector::PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { return position_distribution->InjectionBounds(detector_model, interactions, interaction); } diff --git a/projects/injection/private/CylinderVolumeLeptonInjector.cxx b/projects/injection/private/CylinderVolumeLeptonInjector.cxx index afdcad131..b0b4a5b7e 100644 --- a/projects/injection/private/CylinderVolumeLeptonInjector.cxx +++ b/projects/injection/private/CylinderVolumeLeptonInjector.cxx @@ -8,7 +8,7 @@ #include "LeptonInjector/injection/Process.h" #include "LeptonInjector/math/Vector3D.h" -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { @@ -22,21 +22,21 @@ CylinderVolumeLeptonInjector::CylinderVolumeLeptonInjector() {} CylinderVolumeLeptonInjector::CylinderVolumeLeptonInjector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, - std::vector> secondary_processes, + std::shared_ptr primary_process, + std::vector> secondary_processes, std::shared_ptr random, LI::geometry::Cylinder cylinder) : Injector(events_to_inject, detector_model, random), position_distribution(std::make_shared(cylinder)) { interactions = primary_process->GetInteractions(); - primary_process->AddInjectionDistribution(position_distribution); + primary_process->AddPrimaryInjectionDistribution(position_distribution); SetPrimaryProcess(primary_process); for(auto & sec_process : secondary_processes) { AddSecondaryProcess(sec_process); // Assume each secondary process already has a position distribution // Otherwise uncomment below /* - sec_process->GetInjectionDistributions().push_back(position_distribution); + sec_process->GetPrimaryInjectionDistributions().push_back(position_distribution); */ } } @@ -45,7 +45,7 @@ std::string CylinderVolumeLeptonInjector::Name() const { return("VolumeInjector"); } -std::pair CylinderVolumeLeptonInjector::InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple CylinderVolumeLeptonInjector::PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { return position_distribution->InjectionBounds(detector_model, interactions, interaction); } diff --git a/projects/injection/private/DecayRangeLeptonInjector.cxx b/projects/injection/private/DecayRangeLeptonInjector.cxx index e9ead5983..7835ab370 100644 --- a/projects/injection/private/DecayRangeLeptonInjector.cxx +++ b/projects/injection/private/DecayRangeLeptonInjector.cxx @@ -12,7 +12,7 @@ #include "LeptonInjector/injection/Process.h" #include "LeptonInjector/math/Vector3D.h" -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { @@ -26,8 +26,8 @@ DecayRangeLeptonInjector::DecayRangeLeptonInjector() {} DecayRangeLeptonInjector::DecayRangeLeptonInjector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, - std::vector> secondary_processes, + std::shared_ptr primary_process, + std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, @@ -39,7 +39,7 @@ DecayRangeLeptonInjector::DecayRangeLeptonInjector( { interactions = primary_process->GetInteractions(); position_distribution = std::make_shared(disk_radius, endcap_length, range_func); - primary_process->AddInjectionDistribution(position_distribution); + primary_process->AddPrimaryInjectionDistribution(position_distribution); SetPrimaryProcess(primary_process); for(auto & sec_process : secondary_processes) { AddSecondaryProcess(sec_process); @@ -47,7 +47,7 @@ DecayRangeLeptonInjector::DecayRangeLeptonInjector( // Otherwise uncomment below /* target_types = sec_process->GetInteractions()->TargetTypes(); - sec_process->GetInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, range_func, target_types)); + sec_process->GetPrimaryInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, range_func, target_types)); */ } } @@ -56,7 +56,7 @@ std::string DecayRangeLeptonInjector::Name() const { return("DecayRangeInjector"); } -std::pair DecayRangeLeptonInjector::InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple DecayRangeLeptonInjector::PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { return position_distribution->InjectionBounds(detector_model, interactions, interaction); } diff --git a/projects/injection/private/Injector.cxx b/projects/injection/private/Injector.cxx index 0fb695dfb..a434fb807 100644 --- a/projects/injection/private/Injector.cxx +++ b/projects/injection/private/Injector.cxx @@ -10,7 +10,6 @@ #include "LeptonInjector/interactions/CrossSection.h" #include "LeptonInjector/interactions/InteractionCollection.h" #include "LeptonInjector/interactions/Decay.h" -#include "LeptonInjector/dataclasses/DecayRecord.h" #include "LeptonInjector/dataclasses/DecaySignature.h" #include "LeptonInjector/dataclasses/InteractionSignature.h" #include "LeptonInjector/dataclasses/Particle.h" @@ -21,6 +20,7 @@ #include "LeptonInjector/distributions/Distributions.h" #include "LeptonInjector/distributions/primary/vertex/DecayRangeFunction.h" #include "LeptonInjector/distributions/primary/vertex/VertexPositionDistribution.h" +#include "LeptonInjector/distributions/secondary/vertex/SecondaryVertexPositionDistribution.h" #include "LeptonInjector/geometry/Geometry.h" #include "LeptonInjector/injection/Process.h" #include "LeptonInjector/injection/WeightingUtils.h" @@ -53,62 +53,74 @@ Injector::Injector( Injector::Injector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, + std::shared_ptr primary_process, std::shared_ptr random) : events_to_inject(events_to_inject), random(random), detector_model(detector_model) { - SetPrimaryProcess(primary_process); + SetPrimaryProcess(primary_process); } Injector::Injector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, - std::vector> secondary_processes, + std::shared_ptr primary_process, + std::vector> secondary_processes, std::shared_ptr random) : events_to_inject(events_to_inject), random(random), detector_model(detector_model) { - SetPrimaryProcess(primary_process); - for(auto secondary_process : secondary_processes) { - AddSecondaryProcess(secondary_process); - } + SetPrimaryProcess(primary_process); + for(auto secondary_process : secondary_processes) { + AddSecondaryProcess(secondary_process); + } } -std::shared_ptr Injector::FindPositionDistribution(std::shared_ptr process) { - for(auto distribution : process->GetInjectionDistributions()) { - if(distribution->IsPositionDistribution()) return std::dynamic_pointer_cast(distribution); - } - throw(LI::utilities::AddProcessFailure("No vertex distribution specified!")); + +std::shared_ptr Injector::FindPrimaryVertexDistribution(std::shared_ptr process) { + for(auto distribution : process->GetPrimaryInjectionDistributions()) { + distributions::VertexPositionDistribution * raw_ptr = dynamic_cast(distribution.get()); + if(raw_ptr) + return std::dynamic_pointer_cast(distribution); + } + throw(LI::utilities::AddProcessFailure("No primary vertex distribution specified!")); } -void Injector::SetPrimaryProcess(std::shared_ptr primary) { - std::shared_ptr vtx_dist; - try { - vtx_dist = FindPositionDistribution(primary); - } catch(LI::utilities::AddProcessFailure const & e) { - std::cerr << e.what() << std::endl; - exit(0); - } - primary_process = primary; - primary_position_distribution = vtx_dist; +std::shared_ptr Injector::FindSecondaryVertexDistribution(std::shared_ptr process) { + for(std::shared_ptr distribution : process->GetSecondaryInjectionDistributions()) { + distributions::SecondaryVertexPositionDistribution * raw_ptr = dynamic_cast(distribution.get()); + if(raw_ptr) + return std::dynamic_pointer_cast(distribution); + } + throw(LI::utilities::AddProcessFailure("No secondary vertex distribution specified!")); } -void Injector::AddSecondaryProcess(std::shared_ptr secondary) { - std::shared_ptr vtx_dist; - try { - vtx_dist = FindPositionDistribution(secondary); - } catch(LI::utilities::AddProcessFailure const & e) { - std::cerr << e.what() << std::endl; - exit(0); - } - secondary_processes.push_back(secondary); - secondary_position_distributions.push_back(vtx_dist); - secondary_process_map.insert({secondary->GetPrimaryType(), secondary}); - secondary_position_distribution_map.insert({secondary->GetPrimaryType(), vtx_dist}); +void Injector::SetPrimaryProcess(std::shared_ptr primary) { + std::shared_ptr vtx_dist; + try { + vtx_dist = FindPrimaryVertexDistribution(primary); + } catch(LI::utilities::AddProcessFailure const & e) { + std::cerr << e.what() << std::endl; + exit(0); + } + primary_process = primary; + primary_position_distribution = vtx_dist; +} + +void Injector::AddSecondaryProcess(std::shared_ptr secondary) { + std::shared_ptr vtx_dist; + try { + vtx_dist = FindSecondaryVertexDistribution(secondary); + } catch(LI::utilities::AddProcessFailure const & e) { + std::cerr << e.what() << std::endl; + exit(0); + } + secondary_processes.push_back(secondary); + secondary_position_distributions.push_back(vtx_dist); + secondary_process_map.insert({secondary->GetPrimaryType(), secondary}); + secondary_position_distribution_map.insert({secondary->GetPrimaryType(), vtx_dist}); } LI::dataclasses::InteractionRecord Injector::NewRecord() const { @@ -122,16 +134,15 @@ void Injector::SetRandom(std::shared_ptr random) { } void Injector::SampleCrossSection(LI::dataclasses::InteractionRecord & record) const { - SampleCrossSection(record, primary_process->GetInteractions()); + SampleCrossSection(record, primary_process->GetInteractions()); } void Injector::SampleCrossSection(LI::dataclasses::InteractionRecord & record, std::shared_ptr interactions) const { - // Make sure the particle has interacted if(std::isnan(record.interaction_vertex[0]) || - std::isnan(record.interaction_vertex[1]) || - std::isnan(record.interaction_vertex[2])) { - throw(LI::utilities::InjectionFailure("No particle interaction!")); + std::isnan(record.interaction_vertex[1]) || + std::isnan(record.interaction_vertex[2])) { + throw(LI::utilities::InjectionFailure("No particle interaction!")); } std::set const & possible_targets = interactions->TargetTypes(); @@ -147,7 +158,6 @@ void Injector::SampleCrossSection(LI::dataclasses::InteractionRecord & record, s record.primary_momentum[3]); primary_direction.normalize(); - LI::geometry::Geometry::IntersectionList intersections = detector_model->GetIntersections(DetectorPosition(interaction_vertex), DetectorDirection(primary_direction)); std::set available_targets = detector_model->GetAvailableTargets(intersections, DetectorPosition(record.interaction_vertex)); @@ -161,55 +171,57 @@ void Injector::SampleCrossSection(LI::dataclasses::InteractionRecord & record, s LI::dataclasses::InteractionRecord fake_record = record; double fake_prob; if (interactions->HasCrossSections()) { - for(auto const target : available_targets) { - if(possible_targets.find(target) != possible_targets.end()) { - // Get target density - double target_density = detector_model->GetParticleDensity(intersections, DetectorPosition(interaction_vertex), target); - // Loop over cross sections that have this target - std::vector> const & target_cross_sections = interactions->GetCrossSectionsForTarget(target); - for(auto const & cross_section : target_cross_sections) { - // Loop over cross section signatures with the same target - std::vector signatures = cross_section->GetPossibleSignaturesFromParents(record.signature.primary_type, target); - for(auto const & signature : signatures) { - fake_record.signature = signature; - fake_record.target_mass = detector_model->GetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; - // Add total cross section times density to the total prob - fake_prob = target_density * cross_section->TotalCrossSection(fake_record); - total_prob += fake_prob; - xsec_prob += fake_prob; - // Add total prob to probs - probs.push_back(total_prob); - // Add target and cross section pointer to the lists - matching_targets.push_back(target); - matching_cross_sections.push_back(cross_section); - matching_signatures.push_back(signature); - } - } - } - } + for(auto const target : available_targets) { + if(possible_targets.find(target) != possible_targets.end()) { + // Get target density + double target_density = detector_model->GetParticleDensity(intersections, DetectorPosition(interaction_vertex), target); + // Loop over cross sections that have this target + std::vector> const & target_cross_sections = interactions->GetCrossSectionsForTarget(target); + for(auto const & cross_section : target_cross_sections) { + // Loop over cross section signatures with the same target + std::vector signatures = cross_section->GetPossibleSignaturesFromParents(record.signature.primary_type, target); + for(auto const & signature : signatures) { + fake_record.signature = signature; + fake_record.target_mass = detector_model->GetTargetMass(target); + // Add total cross section times density to the total prob + fake_prob = target_density * cross_section->TotalCrossSection(fake_record); + total_prob += fake_prob; + xsec_prob += fake_prob; + // Add total prob to probs + probs.push_back(total_prob); + // Add target and cross section pointer to the lists + matching_targets.push_back(target); + matching_cross_sections.push_back(cross_section); + matching_signatures.push_back(signature); + } + } + } + } } if (interactions->HasDecays()) { - for(auto const & decay : interactions->GetDecays() ) { - for(auto const & signature : decay->GetPossibleSignaturesFromParent(record.signature.primary_type)) { - fake_record.signature = signature; - // fake_prob has units of 1/cm to match cross section probabilities - fake_prob = 1./(decay->TotalDecayLengthForFinalState(fake_record)/LI::utilities::Constants::cm); - total_prob += fake_prob; - // Add total prob to probs - probs.push_back(total_prob); - // Add target and decay pointer to the lists - matching_targets.push_back(LI::dataclasses::Particle::ParticleType::Decay); - matching_decays.push_back(decay); - matching_signatures.push_back(signature); + for(auto const & decay : interactions->GetDecays() ) { + for(auto const & signature : decay->GetPossibleSignaturesFromParent(record.signature.primary_type)) { + fake_record.signature = signature; + // fake_prob has units of 1/cm to match cross section probabilities + fake_prob = 1./(decay->TotalDecayLengthForFinalState(fake_record)/LI::utilities::Constants::cm); + total_prob += fake_prob; + // Add total prob to probs + probs.push_back(total_prob); + // Add target and decay pointer to the lists + matching_targets.push_back(LI::dataclasses::Particle::ParticleType::Decay); + matching_decays.push_back(decay); + matching_signatures.push_back(signature); + } } - } } + + if(total_prob == 0) + throw(LI::utilities::InjectionFailure("No valid interactions for this event!")); // Throw a random number double r = random->Uniform(0, total_prob); // Choose the target and cross section unsigned int index = 0; - for(; (index < probs.size()-1) and (r > probs[index]); ++index) {} + for(; (index+1 < probs.size()) and (r > probs[index]); ++index) {} record.signature.target_type = matching_targets[index]; record.signature = matching_signatures[index]; double selected_prob = 0.0; @@ -218,220 +230,157 @@ void Injector::SampleCrossSection(LI::dataclasses::InteractionRecord & record, s selected_prob += (i > 0 ? probs[i] - probs[i - 1] : probs[i]); } } - if(total_prob == 0 or selected_prob == 0) + if(selected_prob == 0) throw(LI::utilities::InjectionFailure("No valid interactions for this event!")); record.target_mass = detector_model->GetTargetMass(record.signature.target_type); - record.target_momentum = {record.target_mass,0,0,0}; - if(r <= xsec_prob) - matching_cross_sections[index]->SampleFinalState(record, random); - else - matching_decays[index - matching_cross_sections.size()]->SampleFinalState(record, random); -} - -void Injector::SampleNeutrissimoDecay(LI::dataclasses::InteractionRecord const & interaction, LI::dataclasses::DecayRecord & decay, double decay_width, double alpha_gen, double alpha_phys, LI::geometry::Geometry *fiducial = nullptr, double buffer = 0) const { - // This function takes an interaction record containing an HNL and simulates the decay to a photon - // Samples according to (1 + alpha * cos(theta))/2 and returns physical weight - // Final state photon added to secondary particle vectors in LI::dataclasses::InteractionRecord - - // Find the HNL in the secondary particle vector and save its momentum/cartesian direction - unsigned int lepton_index = (interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar) ? 0 : 1; - LI::dataclasses::Particle::ParticleType hnl_type = interaction.signature.secondary_types[lepton_index]; - double hnl_mass = interaction.secondary_masses[lepton_index]; - std::array hnl_momentum = interaction.secondary_momenta[lepton_index]; - double hnl_helicity = interaction.secondary_helicity[lepton_index]; - - // Store the HNL as the primary for the decay - decay.signature.primary_type = hnl_type; - decay.primary_mass = hnl_mass; - decay.primary_momentum = hnl_momentum; - decay.primary_helicity = hnl_helicity; - - rk::P4 pHNL_lab(geom3::Vector3(hnl_momentum[1], hnl_momentum[2], hnl_momentum[3]), hnl_mass); - LI::math::Vector3D hnl_dir(hnl_momentum[1], hnl_momentum[2], hnl_momentum[3]); - hnl_dir.normalize(); - - // Calculate the decay location of the HNL - // Require the decay to happen within a fid vol if possible - double decay_length = LI::distributions::DecayRangeFunction::DecayLength(hnl_mass, decay_width, hnl_momentum[0]); - double decay_weight = 1.0; - double a=0,b=0; - double C = random->Uniform(0,1); - if(fiducial) { - std::vector ints = fiducial->Intersections(interaction.interaction_vertex,hnl_dir); - if(ints.size()!=0 && ints[ints.size()-1].distance > 0) { - a = std::max(0.,ints[0].distance - buffer); - b = ints[ints.size()-1].distance; - C*=(1-std::exp(-(b-a)/decay_length)); - decay_weight = std::exp(-a/decay_length) - std::exp(-b/decay_length); - } - + LI::dataclasses::CrossSectionDistributionRecord xsec_record(record); + if(r <= xsec_prob) { + matching_cross_sections[index]->SampleFinalState(xsec_record, random); + } else { + matching_decays[index - matching_cross_sections.size()]->SampleFinalState(xsec_record, random); } - - double decay_loc = a + -1 * decay_length * std::log(1-C); - decay.decay_vertex = LI::math::Vector3D(interaction.interaction_vertex) + decay_loc * hnl_dir; - - // Sample decay angles - double X = random->Uniform(0,1); - double costh; - // Majorana Case - if(alpha_gen==0) { - costh = 2*X - 1; - } - // Dirac case (alpha = 1,-1 based for L/R handed HNLs) - else { - costh = -1./alpha_gen + sqrt(1./std::pow(alpha_gen,2) + (4*X - 2)/alpha_gen + 1); - } - - double theta = std::acos(costh); - double phi = random->Uniform(0,2*LI::utilities::Constants::pi); - rk::P4 pGamma_HNLrest( - geom3::Vector3( - hnl_mass/2.0*std::cos(phi)*std::sin(theta), - hnl_mass/2.0*std::sin(phi)*std::sin(theta), - hnl_mass/2.0*costh), - 0.0); - - // Boost gamma to lab frame - rk::Boost boost_to_lab = pHNL_lab.labBoost(); - rk::P4 pGamma_lab = boost_to_lab * pGamma_HNLrest; - - decay.signature.secondary_types.resize(1); - decay.secondary_masses.resize(1); - decay.secondary_momenta.resize(2); - decay.secondary_helicity.resize(1); - - decay.signature.secondary_types[0] = LI::dataclasses::Particle::ParticleType::Gamma; - decay.secondary_masses[0] = 0; - decay.secondary_momenta[0][0] = pGamma_lab.e(); - decay.secondary_momenta[0][1] = pGamma_lab.px(); - decay.secondary_momenta[0][2] = pGamma_lab.py(); - decay.secondary_momenta[0][3] = pGamma_lab.pz(); - decay.secondary_momenta[1][0] = pGamma_HNLrest.e(); - decay.secondary_momenta[1][1] = pGamma_HNLrest.px(); - decay.secondary_momenta[1][2] = pGamma_HNLrest.py(); - decay.secondary_momenta[1][3] = pGamma_HNLrest.pz(); - decay.secondary_helicity[0] = std::copysign(1.0, decay.primary_helicity); - - decay.decay_parameters.resize(5); - decay.decay_parameters[0] = decay_length; - decay.decay_parameters[1] = decay_weight; - decay.decay_parameters[2] = (1+alpha_phys*costh)/(1+alpha_gen*costh); - decay.decay_parameters[3] = a; - decay.decay_parameters[4] = b; + xsec_record.Finalize(record); } // Function to sample secondary processes // -// Throws exception if no secondary process exists for the given particle -// // Modifies an InteractionRecord with the new event -// Returns true if the sampling was successful -// -// TODO: convert to using an std::map of secondary processes -bool Injector::SampleSecondaryProcess(unsigned int idx, - std::shared_ptr parent, - LI::dataclasses::InteractionTreeDatum & datum) { - - LI::dataclasses::Particle::ParticleType const primary = parent->record.signature.secondary_types[idx]; - std::vector>::iterator it; - for(it = secondary_processes.begin(); it != secondary_processes.end(); ++it) { - if ((*it)->GetPrimaryType() == primary) break; - } - if(it==secondary_processes.end()) { - return false; - throw(LI::utilities::SecondaryProcessFailure("No process defined for this particle type!")); - } - std::shared_ptr sec_interactions = (*it)->GetInteractions(); - std::vector> sec_distributions = (*it)->GetInjectionDistributions(); - datum.record.signature.primary_type = parent->record.signature.secondary_types[idx]; - datum.record.primary_mass = parent->record.secondary_masses[idx]; - datum.record.primary_momentum = parent->record.secondary_momenta[idx]; - datum.record.primary_helicity = parent->record.secondary_helicity[idx]; - datum.parent = parent; - for(auto & distribution : sec_distributions) { - distribution->Sample(random, detector_model, sec_interactions, datum); - } - SampleCrossSection(datum.record,sec_interactions); - // TODO: properly weight for secondary injection failure - /*while(true) { - try { - for(auto & distribution : sec_distributions) { - distribution->Sample(random, detector_model, sec_interactions, datum); - } - SampleCrossSection(record,sec_interactions); - break; - } catch(LI::utilities::InjectionFailure const & e) { - continue; - } - }*/ - return true; +LI::dataclasses::InteractionRecord Injector::SampleSecondaryProcess(LI::dataclasses::SecondaryDistributionRecord & secondary_record) const { + std::shared_ptr secondary_process = secondary_process_map.at(secondary_record.type); + std::shared_ptr secondary_interactions = secondary_process->GetInteractions(); + std::vector> secondary_distributions = secondary_process->GetSecondaryInjectionDistributions(); + + size_t max_tries = 100; + size_t tries = 0; + size_t failed_tries = 0; + while(true) { + try { + for(auto & distribution : secondary_distributions) { + distribution->Sample(random, detector_model, secondary_process->GetInteractions(), secondary_record); + } + LI::dataclasses::InteractionRecord record; + secondary_record.Finalize(record); + SampleCrossSection(record, secondary_interactions); + return record; + } catch(LI::utilities::InjectionFailure const & e) { + failed_tries += 1; + if(tries > max_tries) { + throw(LI::utilities::InjectionFailure("Failed to generate secondary process!")); + break; + } + continue; + } + if(tries > max_tries) { + throw(LI::utilities::InjectionFailure("Failed to generate secondary process!")); + break; + } + } + return LI::dataclasses::InteractionRecord(); } LI::dataclasses::InteractionTree Injector::GenerateEvent() { LI::dataclasses::InteractionRecord record; + size_t max_tries = 100; + size_t tries = 0; + size_t failed_tries = 0; // Initial Process while(true) { + tries += 1; try { - record = this->NewRecord(); - for(auto & distribution : primary_process->GetInjectionDistributions()) { - distribution->Sample(random, detector_model, primary_process->GetInteractions(), record); + LI::dataclasses::PrimaryDistributionRecord primary_record(primary_process->GetPrimaryType()); + for(auto & distribution : primary_process->GetPrimaryInjectionDistributions()) { + distribution->Sample(random, detector_model, primary_process->GetInteractions(), primary_record); } + primary_record.Finalize(record); SampleCrossSection(record); break; } catch(LI::utilities::InjectionFailure const & e) { + failed_tries += 1; + if(tries > max_tries) { + throw(LI::utilities::InjectionFailure("Failed to generate primary process!")); + break; + } continue; } + if(tries > max_tries) { + throw(LI::utilities::InjectionFailure("Failed to generate primary process!")); + break; + } } LI::dataclasses::InteractionTree tree; std::shared_ptr parent = tree.add_entry(record); // Secondary Processes - std::vector> current_parents; - std::vector> new_parents; - current_parents.push_back(parent); - while(current_parents.size() > 0) { - for(unsigned int ip = 0; ip < current_parents.size(); ++ip) { - for(unsigned int idx = 0; idx < current_parents[ip]->record.signature.secondary_types.size(); ++idx) { - LI::dataclasses::InteractionRecord record; - LI::dataclasses::InteractionTreeDatum datum(record); - bool success = SampleSecondaryProcess(idx,current_parents[ip],datum); - if(!success) continue; - std::shared_ptr new_parent = tree.add_entry(datum,current_parents[ip]); - if(stopping_condition(new_parent)) continue; - new_parents.push_back(new_parent); + std::deque, std::shared_ptr>> secondaries; + std::function)> add_secondaries = [&](std::shared_ptr parent) { + for(size_t i=0; irecord.signature.secondary_types.size(); ++i) { + LI::dataclasses::ParticleType const & type = parent->record.signature.secondary_types[i]; + std::map>::iterator it = secondary_process_map.find(type); + if(it == secondary_process_map.end()) { + continue; + } + if(stopping_condition(parent, i)) { + continue; + } + secondaries.emplace_back( + parent, + std::make_shared(parent->record, i) + ); + } + }; + + add_secondaries(parent); + while(secondaries.size() > 0) { + for(int i = secondaries.size() - 1; i >= 0; --i) { + std::shared_ptr parent = std::get<0>(secondaries[i]); + std::shared_ptr secondary_dist = std::get<1>(secondaries[i]); + secondaries.erase(secondaries.begin() + i); + + LI::dataclasses::InteractionRecord secondary_record = SampleSecondaryProcess(*secondary_dist); + std::shared_ptr secondary_datum = tree.add_entry(secondary_record, parent); + add_secondaries(secondary_datum); } - } - current_parents = new_parents; - new_parents.clear(); } injected_events += 1; return tree; } double Injector::SecondaryGenerationProbability(std::shared_ptr const & datum) const { - return GenerationProbability(datum, secondary_process_map.at(datum->record.signature.primary_type)); + return SecondaryGenerationProbability(datum, secondary_process_map.at(datum->record.signature.primary_type)); +} + +double Injector::SecondaryGenerationProbability(std::shared_ptr const & datum, + std::shared_ptr process) const { + double probability = 1.0; + for(auto const & dist : process->GetSecondaryInjectionDistributions()) { + double prob = dist->GenerationProbability(detector_model, process->GetInteractions(), datum->record); + probability *= prob; + } + double prob = LI::injection::CrossSectionProbability(detector_model, process->GetInteractions(), datum->record); + probability *= prob; + return probability; } double Injector::GenerationProbability(LI::dataclasses::InteractionTree const & tree) const { - double probability = 1.0; - std::set>::const_iterator it = tree.tree.cbegin(); - while(it != tree.tree.cend()) { - if((*it)->depth()==0) probability *= GenerationProbability((*it)); - else probability *= SecondaryGenerationProbability((*it)); - ++it; - } - return probability; + double probability = 1.0; + std::set>::const_iterator it = tree.tree.cbegin(); + while(it != tree.tree.cend()) { + if((*it)->depth()==0) probability *= GenerationProbability((*it)); + else probability *= SecondaryGenerationProbability((*it)); + ++it; + } + return probability; } double Injector::GenerationProbability(std::shared_ptr const & datum, - std::shared_ptr process) const { + std::shared_ptr process) const { double probability = 1.0; if(!process) { // assume we are dealing with the primary process - process = primary_process; - probability *= events_to_inject; // only do this for the primary process + process = primary_process; + probability *= events_to_inject; // only do this for the primary process } - for(auto const & dist : process->GetInjectionDistributions()) { - double prob = dist->GenerationProbability(detector_model, process->GetInteractions(), *datum); + for(auto const & dist : process->GetPrimaryInjectionDistributions()) { + double prob = dist->GenerationProbability(detector_model, process->GetInteractions(), datum->record); probability *= prob; } double prob = LI::injection::CrossSectionProbability(detector_model, process->GetInteractions(), datum->record); @@ -440,13 +389,13 @@ double Injector::GenerationProbability(std::shared_ptr process) const { + std::shared_ptr process) const { double probability = 1.0; if(!process) { // assume we are dealing with the primary process - process = primary_process; - probability *= events_to_inject; // only do this for the primary process + process = primary_process; + probability *= events_to_inject; // only do this for the primary process } - for(auto const & dist : process->GetInjectionDistributions()) { + for(auto const & dist : process->GetPrimaryInjectionDistributions()) { double prob = dist->GenerationProbability(detector_model, process->GetInteractions(), record); probability *= prob; } @@ -459,7 +408,7 @@ double Injector::GenerationProbability(LI::dataclasses::InteractionRecord const std::set> Injector::DensityVariables() const { std::set> variable_sets; std::vector variables; - for(auto const & dist : primary_process->GetInjectionDistributions()) { + for(auto const & dist : primary_process->GetPrimaryInjectionDistributions()) { std::vector new_variables = dist->DensityVariables(); variables.reserve(variables.size() + new_variables.size()); variables.insert(variables.end(), new_variables.begin(), new_variables.end()); @@ -480,20 +429,20 @@ std::string Injector::Name() const { return("Injector"); } -std::pair Injector::InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple Injector::PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { if(!primary_position_distribution) { - return std::pair(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); + return std::tuple(LI::math::Vector3D(0, 0, 0), LI::math::Vector3D(0, 0, 0)); } return primary_position_distribution->InjectionBounds(detector_model, primary_process->GetInteractions(), interaction); } // Assumes there is a secondary process and position distribuiton for the provided particle type -std::pair Injector::InjectionBounds(LI::dataclasses::InteractionTreeDatum const & datum, LI::dataclasses::Particle::ParticleType const & primary_type) const { - return secondary_position_distribution_map.at(primary_type)->InjectionBounds(detector_model, secondary_process_map.at(primary_type)->GetInteractions(), datum); +std::tuple Injector::SecondaryInjectionBounds(LI::dataclasses::InteractionRecord const & record) const { + return secondary_position_distribution_map.at(record.signature.primary_type)->InjectionBounds(detector_model, secondary_process_map.at(record.signature.primary_type)->GetInteractions(), record); } -std::vector> Injector::GetInjectionDistributions() const { - return primary_process->GetInjectionDistributions(); +std::vector> Injector::GetPrimaryInjectionDistributions() const { + return primary_process->GetPrimaryInjectionDistributions(); } std::shared_ptr Injector::GetDetectorModel() const { diff --git a/projects/injection/private/Process.cxx b/projects/injection/private/Process.cxx index 8a0a490d8..798e6a54a 100644 --- a/projects/injection/private/Process.cxx +++ b/projects/injection/private/Process.cxx @@ -89,38 +89,75 @@ std::vector> const & Phys return physical_distributions; } -InjectionProcess::InjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions) : PhysicalProcess(_primary_type, _interactions) {}; +PrimaryInjectionProcess::PrimaryInjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions) : PhysicalProcess(_primary_type, _interactions) {}; -InjectionProcess::InjectionProcess(InjectionProcess const & other) : PhysicalProcess(other), injection_distributions(other.injection_distributions) {}; +PrimaryInjectionProcess::PrimaryInjectionProcess(PrimaryInjectionProcess const & other) : PhysicalProcess(other), primary_injection_distributions(other.primary_injection_distributions) {}; -InjectionProcess::InjectionProcess(InjectionProcess && other) : PhysicalProcess(other), injection_distributions(other.injection_distributions) {}; +PrimaryInjectionProcess::PrimaryInjectionProcess(PrimaryInjectionProcess && other) : PhysicalProcess(other), primary_injection_distributions(other.primary_injection_distributions) {}; -InjectionProcess & InjectionProcess::operator=(InjectionProcess const & other) { +PrimaryInjectionProcess & PrimaryInjectionProcess::operator=(PrimaryInjectionProcess const & other) { PhysicalProcess::operator=(other); - injection_distributions = other.injection_distributions; + primary_injection_distributions = other.primary_injection_distributions; return *this; }; -InjectionProcess & InjectionProcess::operator=(InjectionProcess && other) { +PrimaryInjectionProcess & PrimaryInjectionProcess::operator=(PrimaryInjectionProcess && other) { PhysicalProcess::operator=(other); - injection_distributions = other.injection_distributions; + primary_injection_distributions = other.primary_injection_distributions; return *this; }; -void InjectionProcess::AddPhysicalDistribution(std::shared_ptr dist) { - throw std::runtime_error("Cannot add a physical distribution to an InjectionProcess"); +void PrimaryInjectionProcess::AddPhysicalDistribution(std::shared_ptr dist) { + throw std::runtime_error("Cannot add a physical distribution to an PrimaryInjectionProcess"); } -void InjectionProcess::AddInjectionDistribution(std::shared_ptr dist) { - for(auto _dist: injection_distributions) { +void PrimaryInjectionProcess::AddPrimaryInjectionDistribution(std::shared_ptr dist) { + for(auto _dist: primary_injection_distributions) { if((*_dist) == (*dist)) - throw std::runtime_error("Cannot add duplicate InjectionDistributions"); + throw std::runtime_error("Cannot add duplicate PrimaryInjectionDistributions"); } - injection_distributions.push_back(dist); + primary_injection_distributions.push_back(dist); physical_distributions.push_back(std::static_pointer_cast(dist)); } -std::vector> const & InjectionProcess::GetInjectionDistributions() const { - return injection_distributions; +std::vector> const & PrimaryInjectionProcess::GetPrimaryInjectionDistributions() const { + return primary_injection_distributions; +} + +///////////////////////////////////////////// + +SecondaryInjectionProcess::SecondaryInjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions) : PhysicalProcess(_primary_type, _interactions) {}; + +SecondaryInjectionProcess::SecondaryInjectionProcess(SecondaryInjectionProcess const & other) : PhysicalProcess(other), secondary_injection_distributions(other.secondary_injection_distributions) {}; + +SecondaryInjectionProcess::SecondaryInjectionProcess(SecondaryInjectionProcess && other) : PhysicalProcess(other), secondary_injection_distributions(other.secondary_injection_distributions) {}; + +SecondaryInjectionProcess & SecondaryInjectionProcess::operator=(SecondaryInjectionProcess const & other) { + PhysicalProcess::operator=(other); + secondary_injection_distributions = other.secondary_injection_distributions; + return *this; +}; + +SecondaryInjectionProcess & SecondaryInjectionProcess::operator=(SecondaryInjectionProcess && other) { + PhysicalProcess::operator=(other); + secondary_injection_distributions = other.secondary_injection_distributions; + return *this; +}; + +void SecondaryInjectionProcess::AddPhysicalDistribution(std::shared_ptr dist) { + throw std::runtime_error("Cannot add a physical distribution to an SecondaryInjectionProcess"); +} + +void SecondaryInjectionProcess::AddSecondaryInjectionDistribution(std::shared_ptr dist) { + for(auto _dist: secondary_injection_distributions) { + if((*_dist) == (*dist)) + throw std::runtime_error("Cannot add duplicate SecondaryInjectionDistributions"); + } + physical_distributions.push_back(std::static_pointer_cast(dist)); + secondary_injection_distributions.push_back(dist); +} + +std::vector> const & SecondaryInjectionProcess::GetSecondaryInjectionDistributions() const { + return secondary_injection_distributions; } } // namespace injection diff --git a/projects/injection/private/RangedLeptonInjector.cxx b/projects/injection/private/RangedLeptonInjector.cxx index acc4c5d87..e92c2cd04 100644 --- a/projects/injection/private/RangedLeptonInjector.cxx +++ b/projects/injection/private/RangedLeptonInjector.cxx @@ -12,7 +12,7 @@ #include "LeptonInjector/injection/Process.h" #include "LeptonInjector/math/Vector3D.h" -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { @@ -26,8 +26,8 @@ RangedLeptonInjector::RangedLeptonInjector() {} RangedLeptonInjector::RangedLeptonInjector( unsigned int events_to_inject, std::shared_ptr detector_model, - std::shared_ptr primary_process, - std::vector> secondary_processes, + std::shared_ptr primary_process, + std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, @@ -40,7 +40,7 @@ RangedLeptonInjector::RangedLeptonInjector( interactions = primary_process->GetInteractions(); std::set target_types = interactions->TargetTypes(); position_distribution = std::make_shared(disk_radius, endcap_length, range_func, target_types); - primary_process->AddInjectionDistribution(position_distribution); + primary_process->AddPrimaryInjectionDistribution(position_distribution); SetPrimaryProcess(primary_process); for(auto & sec_process : secondary_processes) { AddSecondaryProcess(sec_process); @@ -48,7 +48,7 @@ RangedLeptonInjector::RangedLeptonInjector( // Otherwise uncomment below /* target_types = sec_process->GetInteractions()->TargetTypes(); - sec_process->GetInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, range_func, target_types)); + sec_process->GetPrimaryInjectionDistributions().push_back(std::make_shared(disk_radius, endcap_length, range_func, target_types)); */ } } @@ -57,7 +57,7 @@ std::string RangedLeptonInjector::Name() const { return("RangedInjector"); } -std::pair RangedLeptonInjector::InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { +std::tuple RangedLeptonInjector::PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const { return position_distribution->InjectionBounds(detector_model, interactions, interaction); } diff --git a/projects/injection/private/TreeWeighter.cxx b/projects/injection/private/TreeWeighter.cxx index 30a5b5622..3c1472033 100644 --- a/projects/injection/private/TreeWeighter.cxx +++ b/projects/injection/private/TreeWeighter.cxx @@ -43,58 +43,6 @@ namespace injection { using detector::DetectorPosition; using detector::DetectorDirection; -namespace { -template -typename std::iterator_traits::value_type accumulate(InIt begin, InIt end) { - typedef typename std::iterator_traits::value_type real; - real sum = real(0); - real running_error = real(0); - real temp; - real difference; - - for (; begin != end; ++begin) { - difference = *begin; - difference -= running_error; - temp = sum; - temp += difference; - running_error = temp; - running_error -= sum; - running_error -= difference; - sum = std::move(temp); - } - return sum; -} - -template -T accumulate(std::initializer_list list) { - return accumulate(list.begin(), list.end()); -} - -double one_minus_exp_of_negative(double x) { - if(x < 1e-1) { - return std::exp(std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0); - } else { - return 1.0 - std::exp(-x); - } -} - -double log_one_minus_exp_of_negative(double x) { - if(x < 1e-1) { - return std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0; - } else if(x > 3) { - double ex = std::exp(-x); - double ex2 = ex * ex; - double ex3 = ex2 * ex; - double ex4 = ex3 * ex; - double ex5 = ex4 * ex; - double ex6 = ex5 * ex; - return -(ex + ex2 / 2.0 + ex3 / 3.0 + ex4 / 4.0 + ex5 / 5.0 + ex6 / 6.0); - } else { - return std::log(1.0 - std::exp(-x)); - } -} -} // namespace - //--------------- // class LeptonTreeWeighter //--------------- @@ -105,18 +53,22 @@ void LeptonTreeWeighter::Initialize() { secondary_process_weighter_maps.reserve(injectors.size()); for(auto const & injector : injectors) { assert(primary_physical_process->MatchesHead(injector->GetPrimaryProcess())); - primary_process_weighters.push_back(std::make_shared(LeptonProcessWeighter(primary_physical_process, injector->GetPrimaryProcess(), detector_model))); - std::map - > injector_sec_process_weighter_map; - std::map - > injector_sec_process_map = injector->GetSecondaryProcessMap(); + primary_process_weighters.push_back(std::make_shared(PrimaryProcessWeighter(primary_physical_process, injector->GetPrimaryProcess(), detector_model))); + std::map> + injector_sec_process_weighter_map; + std::map> + injector_sec_process_map = injector->GetSecondaryProcessMap(); for(auto const & sec_phys_process : secondary_physical_processes) { try{ - std::shared_ptr sec_inj_process = injector_sec_process_map.at(sec_phys_process->GetPrimaryType()); + std::shared_ptr sec_inj_process = injector_sec_process_map.at(sec_phys_process->GetPrimaryType()); assert(sec_phys_process->MatchesHead(sec_inj_process)); // make sure cross section collection matches - injector_sec_process_weighter_map[sec_phys_process->GetPrimaryType()] = std::make_shared(LeptonProcessWeighter(sec_phys_process,sec_inj_process,detector_model)); + injector_sec_process_weighter_map[sec_phys_process->GetPrimaryType()] = + std::make_shared( + SecondaryProcessWeighter( + sec_phys_process, + sec_inj_process,detector_model + ) + ); } catch(const std::out_of_range& oor) { std::cout << "Out of Range error: " << oor.what() << '\n'; std::cout << "Initialization Incomplete: Particle " << sec_phys_process->GetPrimaryType() << " does not exist in injector\n"; @@ -144,15 +96,15 @@ double LeptonTreeWeighter::EventWeight(LI::dataclasses::InteractionTree const & double physical_probability = 1.0; double generation_probability = injectors[idx]->EventsToInject();//GenerationProbability(tree); for(auto const & datum : tree.tree) { - std::pair bounds; - if(datum->depth()==0) { - bounds = injectors[idx]->InjectionBounds(datum->record); + std::tuple bounds; + if(datum->depth() == 0) { + bounds = injectors[idx]->PrimaryInjectionBounds(datum->record); physical_probability *= primary_process_weighters[idx]->PhysicalProbability(bounds, datum->record); generation_probability *= primary_process_weighters[idx]->GenerationProbability(*datum); } else { try { - bounds = injectors[idx]->InjectionBounds(*datum, datum->record.signature.primary_type); + bounds = injectors[idx]->SecondaryInjectionBounds(datum->record); double phys_prob = secondary_process_weighter_maps[idx].at(datum->record.signature.primary_type)->PhysicalProbability(bounds, datum->record); double gen_prob = secondary_process_weighter_maps[idx].at(datum->record.signature.primary_type)->GenerationProbability(*datum); physical_probability *= phys_prob; @@ -186,176 +138,5 @@ LeptonTreeWeighter::LeptonTreeWeighter(std::vector> in Initialize(); } -//--------------- -// class LeptonProcessWeighter -//--------------- - -void LeptonProcessWeighter::Initialize() { - normalization = 1.0; - for(auto physical_dist : phys_process->GetPhysicalDistributions()) { - const LI::distributions::PhysicallyNormalizedDistribution* p = dynamic_cast(physical_dist.get()); - if(p) { - if(p->IsNormalizationSet()) { - normalization *= p->GetNormalization(); - } - } - } - unique_gen_distributions = inj_process->GetInjectionDistributions(); - unique_phys_distributions = phys_process->GetPhysicalDistributions(); - for(std::vector>::reverse_iterator gen_it = unique_gen_distributions.rbegin(); - gen_it != unique_gen_distributions.rend(); ++gen_it) { - for(std::vector>::reverse_iterator phys_it = unique_phys_distributions.rbegin(); - phys_it != unique_phys_distributions.rend(); ++phys_it) { - if((*gen_it) == (*phys_it)) { - unique_gen_distributions.erase(std::next(gen_it).base()); - unique_phys_distributions.erase(std::next(phys_it).base()); - break; - } - } - } -} - -double LeptonProcessWeighter::InteractionProbability(std::pair const & bounds, LI::dataclasses::InteractionRecord const & record) const { - LI::math::Vector3D interaction_vertex( - record.interaction_vertex[0], - record.interaction_vertex[1], - record.interaction_vertex[2]); - - LI::math::Vector3D primary_direction( - record.primary_momentum[1], - record.primary_momentum[2], - record.primary_momentum[3]); - primary_direction.normalize(); - - LI::geometry::Geometry::IntersectionList intersections = detector_model->GetIntersections(DetectorPosition(interaction_vertex), DetectorDirection(primary_direction)); - std::map>> const & cross_sections_by_target = phys_process->GetInteractions()->GetCrossSectionsByTarget(); - std::vector targets; - targets.reserve(cross_sections_by_target.size()); - std::vector total_cross_sections; - double total_decay_length = phys_process->GetInteractions()->TotalDecayLength(record); - - LI::dataclasses::InteractionRecord fake_record = record; - for(auto const & target_xs : cross_sections_by_target) { - targets.push_back(target_xs.first); - fake_record.target_mass = detector_model->GetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; - std::vector> const & xs_list = target_xs.second; - double total_xs = 0.0; - for(auto const & xs : xs_list) { - std::vector signatures = xs->GetPossibleSignaturesFromParents(record.signature.primary_type, target_xs.first); - for(auto const & signature : signatures) { - fake_record.signature = signature; - // Add total cross section - total_xs += xs->TotalCrossSection(fake_record); - } - } - total_cross_sections.push_back(total_xs); - } - - double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(bounds.second), targets, total_cross_sections, total_decay_length); - - double interaction_probability; - if(total_interaction_depth < 1e-6) { - interaction_probability = total_interaction_depth; - } else { - interaction_probability = one_minus_exp_of_negative(total_interaction_depth); - } - return interaction_probability; -} - -double LeptonProcessWeighter::NormalizedPositionProbability(std::pair const & bounds, LI::dataclasses::InteractionRecord const & record) const { - LI::math::Vector3D interaction_vertex( - record.interaction_vertex[0], - record.interaction_vertex[1], - record.interaction_vertex[2]); - - LI::math::Vector3D primary_direction( - record.primary_momentum[1], - record.primary_momentum[2], - record.primary_momentum[3]); - primary_direction.normalize(); - - LI::geometry::Geometry::IntersectionList intersections = detector_model->GetIntersections(DetectorPosition(interaction_vertex), DetectorDirection(primary_direction)); - std::map>> const & cross_sections_by_target = phys_process->GetInteractions()->GetCrossSectionsByTarget(); - - unsigned int n_targets = cross_sections_by_target.size(); - - std::vector targets; targets.reserve(n_targets); - std::vector total_cross_sections; - double total_decay_length = phys_process->GetInteractions()->TotalDecayLength(record); - LI::dataclasses::InteractionRecord fake_record = record; - for(auto const & target_xs : cross_sections_by_target) { - targets.push_back(target_xs.first); - fake_record.target_mass = detector_model->GetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; - std::vector> const & xs_list = target_xs.second; - double total_xs = 0.0; - for(auto const & xs : xs_list) { - std::vector signatures = xs->GetPossibleSignaturesFromParents(record.signature.primary_type, target_xs.first); - for(auto const & signature : signatures) { - fake_record.signature = signature; - // Add total cross section - total_xs += xs->TotalCrossSection(fake_record); - } - } - total_cross_sections.push_back(total_xs); - } - - double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(bounds.second), targets, total_cross_sections, total_decay_length); // unitless - double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); - double interaction_density = detector_model->GetInteractionDensity(intersections, DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); //units of m^-1 - - double prob_density; - if(total_interaction_depth < 1e-6) { - prob_density = interaction_density / total_interaction_depth; - } else { - prob_density = interaction_density * exp(-log_one_minus_exp_of_negative(total_interaction_depth) - traversed_interaction_depth); - } - - return prob_density; -} - -double LeptonProcessWeighter::PhysicalProbability(std::pair const & bounds, - LI::dataclasses::InteractionRecord const & record ) const { - - double physical_probability = 1.0; - double prob = InteractionProbability(bounds, record); - physical_probability *= prob; - - prob = NormalizedPositionProbability(bounds, record); - physical_probability *= prob; - - prob = LI::injection::CrossSectionProbability(detector_model, phys_process->GetInteractions(), record); - physical_probability *= prob; - - for(auto physical_dist : unique_phys_distributions) { - physical_probability *= physical_dist->GenerationProbability(detector_model, phys_process->GetInteractions(), record); - } - - return normalization * physical_probability; -} - -double LeptonProcessWeighter::GenerationProbability(LI::dataclasses::InteractionTreeDatum const & datum ) const { - double gen_probability = LI::injection::CrossSectionProbability(detector_model, phys_process->GetInteractions(), datum.record); - - for(auto gen_dist : unique_gen_distributions) { - gen_probability *= gen_dist->GenerationProbability(detector_model, phys_process->GetInteractions(), datum); - } - return gen_probability; -} - -double LeptonProcessWeighter::EventWeight(std::pair const & bounds, - LI::dataclasses::InteractionTreeDatum const & datum) const { - return PhysicalProbability(bounds,datum.record)/GenerationProbability(datum); -} - -LeptonProcessWeighter::LeptonProcessWeighter(std::shared_ptr phys_process, std::shared_ptr inj_process, std::shared_ptr detector_model) - : phys_process(phys_process) - , inj_process(inj_process) - , detector_model(detector_model) -{ - Initialize(); -} - } // namespace injection } // namespace LI diff --git a/projects/injection/private/Weighter.cxx b/projects/injection/private/Weighter.cxx index c1519f0e6..d89f85f20 100644 --- a/projects/injection/private/Weighter.cxx +++ b/projects/injection/private/Weighter.cxx @@ -87,11 +87,11 @@ namespace { //--------------- double LeptonWeighter::InteractionProbability(std::shared_ptr injector, LI::dataclasses::InteractionRecord const & record) const { - std::pair bounds = injector->InjectionBounds(record); + std::tuple bounds = injector->PrimaryInjectionBounds(record); return InteractionProbability(bounds, record); } -double LeptonWeighter::InteractionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const { +double LeptonWeighter::InteractionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D interaction_vertex( record.interaction_vertex[0], record.interaction_vertex[1], @@ -113,7 +113,6 @@ double LeptonWeighter::InteractionProbability(std::pairGetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; std::vector> const & xs_list = target_xs.second; double total_xs = 0.0; for(auto const & xs : xs_list) { @@ -127,7 +126,7 @@ double LeptonWeighter::InteractionProbability(std::pairGetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(bounds.second), targets, total_cross_sections, total_decay_length); + double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(std::get<1>(bounds)), targets, total_cross_sections, total_decay_length); double interaction_probability; if(total_interaction_depth < 1e-6) { interaction_probability = total_interaction_depth; @@ -138,11 +137,11 @@ double LeptonWeighter::InteractionProbability(std::pair injector, LI::dataclasses::InteractionRecord const & record) const { - std::pair bounds = injector->InjectionBounds(record); + std::tuple bounds = injector->PrimaryInjectionBounds(record); return UnnormalizedPositionProbability(bounds, record); } -double LeptonWeighter::UnnormalizedPositionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const { +double LeptonWeighter::UnnormalizedPositionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D interaction_vertex( record.interaction_vertex[0], record.interaction_vertex[1], @@ -166,7 +165,6 @@ double LeptonWeighter::UnnormalizedPositionProbability(std::pairGetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; std::vector> const & xs_list = target_xs.second; double total_xs = 0.0; for(auto const & xs : xs_list) { @@ -180,8 +178,8 @@ double LeptonWeighter::UnnormalizedPositionProbability(std::pairGetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(bounds.second), targets, total_cross_sections, total_decay_length); - double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); + double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(std::get<1>(bounds)), targets, total_cross_sections, total_decay_length); + double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); double interaction_density = detector_model->GetInteractionDensity(intersections, DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); double prob_density; @@ -194,7 +192,7 @@ double LeptonWeighter::UnnormalizedPositionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const { +double LeptonWeighter::NormalizedPositionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const { LI::math::Vector3D interaction_vertex( record.interaction_vertex[0], record.interaction_vertex[1], @@ -218,7 +216,6 @@ double LeptonWeighter::NormalizedPositionProbability(std::pairGetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; std::vector> const & xs_list = target_xs.second; double total_xs = 0.0; for(auto const & xs : xs_list) { @@ -232,8 +229,8 @@ double LeptonWeighter::NormalizedPositionProbability(std::pairGetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(bounds.second), targets, total_cross_sections, total_decay_length); - double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(bounds.first), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); + double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(std::get<1>(bounds)), targets, total_cross_sections, total_decay_length); + double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); double interaction_density = detector_model->GetInteractionDensity(intersections, DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); double prob_density; @@ -282,14 +279,13 @@ void LeptonWeighter::Initialize() { } std::vector>>> physical_distribution_state(injectors.size(), physical_init_state); assert(physical_distribution_state.size() == injectors.size()); - // Initialize the state for generation distributions // true ==> distribution does not cancel and is not common - std::vector>>> generation_distribution_state; + std::vector>>> generation_distribution_state; generation_distribution_state.reserve(injectors.size()); for(auto injector : injectors) { - std::vector> dists = injector->GetInjectionDistributions(); - std::vector>> dist_state; + std::vector> dists = injector->GetPrimaryInjectionDistributions(); + std::vector>> dist_state; dist_state.reserve(dists.size()); for(auto dist : dists) { dist_state.push_back(std::make_pair(true, dist)); @@ -302,14 +298,14 @@ void LeptonWeighter::Initialize() { for(unsigned int i=0; i>> & phys_dists = physical_distribution_state[i]; - std::vector>> & gen_dists = generation_distribution_state[i]; + std::vector>> & gen_dists = generation_distribution_state[i]; // Must check every pair of physical and injection distribution (unless already cancelled) for(unsigned int phys_idx=0; phys_idx> & phys_dist = phys_dists[phys_idx]; if(not phys_dist.first) // Skip if already cancelled continue; for(unsigned int gen_idx=0; gen_idx> & gen_dist = gen_dists[gen_idx]; + std::pair> & gen_dist = gen_dists[gen_idx]; if(not gen_dist.first) { // Skip if already cancelled continue; } @@ -364,9 +360,9 @@ void LeptonWeighter::Initialize() { std::vector common_generation_dist_idxs; unsigned int i=0; - std::vector>> & gen_dists_0 = generation_distribution_state[i]; + std::vector>> & gen_dists_0 = generation_distribution_state[i]; for(unsigned int gen_idx_0=0; gen_idx_0> & gen_dist_0 = gen_dists_0[gen_idx_0]; + std::pair> & gen_dist_0 = gen_dists_0[gen_idx_0]; if(not gen_dist_0.first) continue; bool is_common = true; @@ -374,9 +370,9 @@ void LeptonWeighter::Initialize() { common_idxs[i] = gen_idx_0; for(unsigned int j=i+1; j>> & gen_dists_1 = generation_distribution_state[j]; + std::vector>> & gen_dists_1 = generation_distribution_state[j]; for(unsigned int gen_idx_1=0; gen_idx_1> & gen_dist_1 = gen_dists_1[gen_idx_1]; + std::pair> & gen_dist_1 = gen_dists_1[gen_idx_1]; if(not gen_dist_1.first) continue; bool equivalent_dists = @@ -446,7 +442,7 @@ void LeptonWeighter::Initialize() { for(unsigned int injector_idx=0; injector_idx>> & phys_dists = physical_distribution_state[injector_idx]; - std::vector>> & gen_dists = generation_distribution_state[injector_idx]; + std::vector>> & gen_dists = generation_distribution_state[injector_idx]; std::vector gen_idxs; std::vector phys_idxs; @@ -530,7 +526,7 @@ double LeptonWeighter::EventWeight(LI::dataclasses::InteractionRecord const & re // From each injector we need the generation probability and the unnormalized position probability (interaction probability * position probability) for(auto injector : injectors) { double generation_probability = injector->GenerationProbability(record); - std::pair bounds = injector->InjectionBounds(record); + std::tuple bounds = injector->PrimaryInjectionBounds(record); double physical_probability = 1.0; /* @@ -622,7 +618,7 @@ double LeptonWeighter::SimplifiedEventWeight(LI::dataclasses::InteractionRecord double pos_prob = UnnormalizedPositionProbability((std::shared_ptr)injectors[i], record); prob /= pos_prob; }*/ - std::pair bounds = injectors[i]->InjectionBounds(record); + std::tuple bounds = injectors[i]->PrimaryInjectionBounds(record); double interaction_probability = InteractionProbability(bounds, record); double normalized_position_probability = NormalizedPositionProbability(bounds, record); prob /= interaction_probability; diff --git a/projects/injection/private/WeightingUtils.cxx b/projects/injection/private/WeightingUtils.cxx index b8faaecba..de00cc45c 100644 --- a/projects/injection/private/WeightingUtils.cxx +++ b/projects/injection/private/WeightingUtils.cxx @@ -71,7 +71,6 @@ double CrossSectionProbability(std::shared_ptrGetTargetMass(target); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; // Add total cross section times density to the total prob double target_prob = target_density * cross_section->TotalCrossSection(fake_record); total_prob += target_prob; diff --git a/projects/injection/private/pybindings/injection.cxx b/projects/injection/private/pybindings/injection.cxx index 3fbc45626..8206ba0ba 100644 --- a/projects/injection/private/pybindings/injection.cxx +++ b/projects/injection/private/pybindings/injection.cxx @@ -37,22 +37,28 @@ PYBIND11_MODULE(injection,m) { .def_property("primary_type", &Process::GetPrimaryType, &Process::SetPrimaryType) .def_property("interactions", &Process::GetInteractions, &Process::SetInteractions); - class_, Process>(m, "InjectionProcess") - .def(init<>()) - .def("AddInjectionDistribution",&InjectionProcess::AddInjectionDistribution) - .def("GetInjectionDistributions",&InjectionProcess::GetInjectionDistributions); - class_, Process>(m, "PhysicalProcess") .def(init<>()) .def("AddPhysicalDistribution",&PhysicalProcess::AddPhysicalDistribution) .def("GetPhysicalDistributions",&PhysicalProcess::GetPhysicalDistributions); + class_, Process>(m, "PrimaryInjectionProcess") + .def(init<>()) + .def("AddPrimaryInjectionDistribution",&PrimaryInjectionProcess::AddPrimaryInjectionDistribution) + .def("GetPrimaryInjectionDistributions",&PrimaryInjectionProcess::GetPrimaryInjectionDistributions); + + class_, Process>(m, "SecondaryInjectionProcess") + .def(init<>()) + .def("AddSecondaryInjectionDistribution",&SecondaryInjectionProcess::AddSecondaryInjectionDistribution) + .def("GetSecondaryInjectionDistributions",&SecondaryInjectionProcess::GetSecondaryInjectionDistributions); + + // Injection class_>(m, "Injector") .def(init, std::shared_ptr>()) - .def(init, std::shared_ptr, std::shared_ptr>()) - .def(init, std::shared_ptr, std::vector>, std::shared_ptr>()) + .def(init, std::shared_ptr, std::shared_ptr>()) + .def(init, std::shared_ptr, std::vector>, std::shared_ptr>()) .def("SetStoppingCondition",&Injector::SetStoppingCondition) .def("SetPrimaryProcess",&Injector::SetPrimaryProcess) .def("AddSecondaryProcess",&Injector::AddSecondaryProcess) @@ -64,38 +70,47 @@ PYBIND11_MODULE(injection,m) { .def("GenerateEvent",&Injector::GenerateEvent) .def("DensityVariables",&Injector::DensityVariables) .def("Name",&Injector::Name) - .def("GetInjectionDistributions",&Injector::GetInjectionDistributions) + .def("GetPrimaryInjectionDistributions",&Injector::GetPrimaryInjectionDistributions) .def("GetDetectorModel",&Injector::GetDetectorModel) .def("GetInteractions",&Injector::GetInteractions) .def("InjectedEvents",&Injector::InjectedEvents) .def("EventsToInject",&Injector::EventsToInject); class_, Injector>(m, "RangedLeptonInjector") - .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) + .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) .def("Name",&RangedLeptonInjector::Name); class_, Injector>(m, "DecayRangeLeptonInjector") - .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) + .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) .def("Name",&DecayRangeLeptonInjector::Name); class_, Injector>(m, "ColumnDepthLeptonInjector") - .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) + .def(init, std::shared_ptr, std::vector>, std::shared_ptr, std::shared_ptr, double, double>()) .def("Name",&ColumnDepthLeptonInjector::Name) - .def("InjectionBounds",&ColumnDepthLeptonInjector::InjectionBounds); + .def("PrimaryInjectionBounds",&ColumnDepthLeptonInjector::PrimaryInjectionBounds) + .def("SecondaryInjectionBounds",&ColumnDepthLeptonInjector::SecondaryInjectionBounds); class_, Injector>(m, "CylinderVolumeLeptonInjector") - .def(init, std::shared_ptr, std::vector>, std::shared_ptr, LI::geometry::Cylinder>()) + .def(init, std::shared_ptr, std::vector>, std::shared_ptr, LI::geometry::Cylinder>()) .def("Name",&CylinderVolumeLeptonInjector::Name); // Weighter classes - class_>(m, "LeptonProcessWeighter") - .def(init, std::shared_ptr, std::shared_ptr>()) - .def("InteractionProbability",&LeptonProcessWeighter::InteractionProbability) - .def("NormalizedPositionProbability",&LeptonProcessWeighter::NormalizedPositionProbability) - .def("PhysicalProbability",&LeptonProcessWeighter::PhysicalProbability) - .def("GenerationProbability",&LeptonProcessWeighter::GenerationProbability) - .def("EventWeight",&LeptonProcessWeighter::EventWeight); + class_>(m, "PrimaryProcessWeighter") + .def(init, std::shared_ptr, std::shared_ptr>()) + .def("InteractionProbability",&PrimaryProcessWeighter::InteractionProbability) + .def("NormalizedPositionProbability",&PrimaryProcessWeighter::NormalizedPositionProbability) + .def("PhysicalProbability",&PrimaryProcessWeighter::PhysicalProbability) + .def("GenerationProbability",&PrimaryProcessWeighter::GenerationProbability) + .def("EventWeight",&PrimaryProcessWeighter::EventWeight); + + class_>(m, "SecondaryProcessWeighter") + .def(init, std::shared_ptr, std::shared_ptr>()) + .def("InteractionProbability",&SecondaryProcessWeighter::InteractionProbability) + .def("NormalizedPositionProbability",&SecondaryProcessWeighter::NormalizedPositionProbability) + .def("PhysicalProbability",&SecondaryProcessWeighter::PhysicalProbability) + .def("GenerationProbability",&SecondaryProcessWeighter::GenerationProbability) + .def("EventWeight",&SecondaryProcessWeighter::EventWeight); class_>(m, "LeptonTreeWeighter") .def(init>, std::shared_ptr, std::shared_ptr, std::vector>>()) diff --git a/projects/injection/private/test/CCM_HNL_TEST.cxx b/projects/injection/private/test/CCM_HNL_TEST.cxx index 288663c1f..1f910edd4 100644 --- a/projects/injection/private/test/CCM_HNL_TEST.cxx +++ b/projects/injection/private/test/CCM_HNL_TEST.cxx @@ -29,9 +29,8 @@ #include "LeptonInjector/distributions/primary/direction/Cone.h" #include "LeptonInjector/distributions/primary/direction/IsotropicDirection.h" #include "LeptonInjector/distributions/primary/vertex/PointSourcePositionDistribution.h" -#include "LeptonInjector/distributions/primary/vertex/SecondaryPositionDistribution.h" #include "LeptonInjector/distributions/primary/helicity/PrimaryNeutrinoHelicityDistribution.h" -#include "LeptonInjector/distributions/target/momentum/TargetMomentumDistribution.h" +#include "LeptonInjector/distributions/secondary/vertex/SecondaryPhysicalVertexDistribution.h" #include "LeptonInjector/interactions/InteractionCollection.h" #include "LeptonInjector/interactions/CrossSection.h" @@ -178,9 +177,9 @@ TEST(Injector, Generation) // let's make the process instances // Injection processes - std::shared_ptr primary_injection_process_upper_injector = std::make_shared(); // will inject in upper tungsten target - std::shared_ptr primary_injection_process_lower_injector = std::make_shared(); // will inject in lower tungsten target - std::vector> secondary_injection_processes; // common to both injectors + std::shared_ptr primary_injection_process_upper_injector = std::make_shared(); // will inject in upper tungsten target + std::shared_ptr primary_injection_process_lower_injector = std::make_shared(); // will inject in lower tungsten target + std::vector> secondary_injection_processes; // common to both injectors // Physical processes std::shared_ptr primary_physical_process_upper_injector = std::make_shared(); // will inject in upper tungsten target std::shared_ptr primary_physical_process_lower_injector = std::make_shared(); // will inject in lower tungsten target @@ -224,8 +223,8 @@ TEST(Injector, Generation) // Primary energy distribution: pion decay-at-rest double nu_energy = 0.02965; std::shared_ptr edist = std::make_shared(nu_energy); // this creates a monoenergetic numu distribution - primary_injection_process_upper_injector->AddInjectionDistribution(edist); - primary_injection_process_lower_injector->AddInjectionDistribution(edist); + primary_injection_process_upper_injector->AddPrimaryInjectionDistribution(edist); + primary_injection_process_lower_injector->AddPrimaryInjectionDistribution(edist); primary_physical_process_upper_injector->AddPhysicalDistribution(edist); primary_physical_process_lower_injector->AddPhysicalDistribution(edist); @@ -246,22 +245,15 @@ TEST(Injector, Generation) std::shared_ptr upper_inj_ddist = std::make_shared(upper_dir,opening_angle); std::shared_ptr lower_inj_ddist = std::make_shared(lower_dir,opening_angle); std::shared_ptr phys_ddist = std::make_shared(); // truly we are isotropic - primary_injection_process_upper_injector->AddInjectionDistribution(upper_inj_ddist); - primary_injection_process_lower_injector->AddInjectionDistribution(lower_inj_ddist); + primary_injection_process_upper_injector->AddPrimaryInjectionDistribution(upper_inj_ddist); + primary_injection_process_lower_injector->AddPrimaryInjectionDistribution(lower_inj_ddist); primary_physical_process_upper_injector->AddPhysicalDistribution(phys_ddist); primary_physical_process_lower_injector->AddPhysicalDistribution(phys_ddist); - // Target momentum distribution: assume stationary for simplicity - std::shared_ptr target_momentum_distribution = std::make_shared(); - primary_injection_process_upper_injector->AddInjectionDistribution(target_momentum_distribution); - primary_injection_process_lower_injector->AddInjectionDistribution(target_momentum_distribution); - primary_physical_process_upper_injector->AddPhysicalDistribution(target_momentum_distribution); - primary_physical_process_lower_injector->AddPhysicalDistribution(target_momentum_distribution); - // Helicity distribution: this is a neutrino std::shared_ptr helicity_distribution = std::make_shared(); - primary_injection_process_upper_injector->AddInjectionDistribution(helicity_distribution); - primary_injection_process_lower_injector->AddInjectionDistribution(helicity_distribution); + primary_injection_process_upper_injector->AddPrimaryInjectionDistribution(helicity_distribution); + primary_injection_process_lower_injector->AddPrimaryInjectionDistribution(helicity_distribution); primary_physical_process_upper_injector->AddPhysicalDistribution(helicity_distribution); primary_physical_process_lower_injector->AddPhysicalDistribution(helicity_distribution); @@ -269,13 +261,13 @@ TEST(Injector, Generation) double max_dist = 25; // m std::shared_ptr upper_pos_dist = std::make_shared(upper_target_origin, max_dist, primary_interactions->TargetTypes()); std::shared_ptr lower_pos_dist = std::make_shared(lower_target_origin, max_dist, primary_interactions->TargetTypes()); - primary_injection_process_upper_injector->AddInjectionDistribution(upper_pos_dist); - primary_injection_process_lower_injector->AddInjectionDistribution(lower_pos_dist); + primary_injection_process_upper_injector->AddPrimaryInjectionDistribution(upper_pos_dist); + primary_injection_process_lower_injector->AddPrimaryInjectionDistribution(lower_pos_dist); //primary_physical_process_upper_injector->AddPhysicalDistribution(upper_pos_dist); //primary_physical_process_lower_injector->AddPhysicalDistribution(lower_pos_dist); // Secondary process - std::shared_ptr secondary_decay_inj_process = std::make_shared(); + std::shared_ptr secondary_decay_inj_process = std::make_shared(); std::shared_ptr secondary_decay_phys_process = std::make_shared(); secondary_decay_inj_process->SetPrimaryType(ParticleType::NuF4); secondary_decay_phys_process->SetPrimaryType(ParticleType::NuF4); @@ -293,8 +285,8 @@ TEST(Injector, Generation) for(auto sector : detector_model->GetSectors()) { if(sector.name=="ccm_inner_argon") fid_vol = sector.geo; } - std::shared_ptr secondary_pos_dist = std::make_shared(fid_vol); - secondary_decay_inj_process->AddInjectionDistribution(secondary_pos_dist); + std::shared_ptr secondary_pos_dist = std::make_shared(); + secondary_decay_inj_process->AddSecondaryInjectionDistribution(secondary_pos_dist); secondary_injection_processes.push_back(secondary_decay_inj_process); secondary_physical_processes.push_back(secondary_decay_phys_process); @@ -304,8 +296,8 @@ TEST(Injector, Generation) std::shared_ptr lower_injector = std::make_shared(events_to_inject, detector_model, primary_injection_process_lower_injector, secondary_injection_processes, random); // Set stopping condition - std::function)> stopping_condition = - [&] (std::shared_ptr datum) { + std::function, size_t)> stopping_condition = + [&] (std::shared_ptr datum, size_t i) { if(datum->depth() >=1) return true; return false; }; diff --git a/projects/injection/private/test/Injector_TEST.cxx b/projects/injection/private/test/Injector_TEST.cxx index cde44f24e..06e2225e5 100644 --- a/projects/injection/private/test/Injector_TEST.cxx +++ b/projects/injection/private/test/Injector_TEST.cxx @@ -156,7 +156,7 @@ bool inFiducial(std::array & int_vtx, Sphere & fidVol) { return fidVol.IsInside(pos,dir); } -double ComputeInteractionLengths(std::shared_ptr detector_model, std::shared_ptr interactions, std::pair const & bounds, InteractionRecord const & record) { +double ComputeInteractionLengths(std::shared_ptr detector_model, std::shared_ptr interactions, std::tuple const & bounds, InteractionRecord const & record) { Vector3D interaction_vertex = record.interaction_vertex; Vector3D direction( record.primary_momentum[1], @@ -172,7 +172,6 @@ double ComputeInteractionLengths(std::shared_ptr detector_m for(auto const & target_xs : cross_sections_by_target) { targets.push_back(target_xs.first); fake_record.target_mass = detector_model->GetTargetMass(target_xs.first); - fake_record.target_momentum = {fake_record.target_mass,0,0,0}; std::vector> const & xs_list = target_xs.second; double total_xs = 0.0; for(auto const & xs : xs_list) { @@ -185,7 +184,7 @@ double ComputeInteractionLengths(std::shared_ptr detector_m } total_cross_sections.push_back(total_xs); } - std::vector particle_depths = detector_model->GetParticleColumnDepth(intersections, bounds.first, bounds.second, targets); + std::vector particle_depths = detector_model->GetParticleColumnDepth(intersections, std::get<0>(bounds), std::get<1>(bounds), targets); double interaction_depth = 0.0; for(unsigned int i=0; i ddist = std::make_shared(Vector3D{0.0, 0.0, 1.0}); - // Targets should be stationary - std::shared_ptr target_momentum_distribution = std::make_shared(); - // Let us inject according to the decay distribution std::shared_ptr range_func = std::make_shared(hnl_mass, HNL_decay_width, n_decay_lengths, max_distance); @@ -314,14 +310,12 @@ TEST(Injector, Generation) std::shared_ptr helicity_distribution = std::make_shared(); // Put it all together! - //RangedLeptonInjector injector(events_to_inject, primary_type, cross_sections, detector_model, random, edist, ddist, target_momentum_distribution, range_func, disk_radius, endcap_length); - std::shared_ptr injector = std::make_shared(events_to_inject, primary_injector, cross_sections, detector_model, random, edist, ddist, target_momentum_distribution, range_func, disk_radius, endcap_length, helicity_distribution); + std::shared_ptr injector = std::make_shared(events_to_inject, primary_injector, cross_sections, detector_model, random, edist, ddist, range_func, disk_radius, endcap_length, helicity_distribution); std::vector> physical_distributions = { std::shared_ptr(tab_pdf), std::shared_ptr(flux_units), std::shared_ptr(ddist), - std::shared_ptr(target_momentum_distribution), std::shared_ptr(helicity_distribution) }; @@ -412,11 +406,6 @@ TEST(Injector, Generation) myFile << event.primary_helicity << " "; - myFile << event.target_momentum[0] << " "; - myFile << event.target_momentum[1] << " "; - myFile << event.target_momentum[2] << " "; - myFile << event.target_momentum[3] << " "; - myFile << event.target_helicity << " "; myFile << event.secondary_momenta[0][0] << " "; @@ -424,14 +413,14 @@ TEST(Injector, Generation) myFile << event.secondary_momenta[0][2] << " "; myFile << event.secondary_momenta[0][3] << " "; - myFile << event.secondary_helicity[0] << " "; + myFile << event.secondary_helicities[0] << " "; myFile << event.secondary_momenta[1][0] << " "; myFile << event.secondary_momenta[1][1] << " "; myFile << event.secondary_momenta[1][2] << " "; myFile << event.secondary_momenta[1][3] << " "; - myFile << event.secondary_helicity[1] << " "; + myFile << event.secondary_helicities[1] << " "; myFile << decay.secondary_momenta[0][0] << " "; myFile << decay.secondary_momenta[0][1] << " "; @@ -443,7 +432,7 @@ TEST(Injector, Generation) myFile << decay.secondary_momenta[1][2] << " "; myFile << decay.secondary_momenta[1][3] << " "; - myFile << decay.secondary_helicity[0] << " "; + myFile << decay.secondary_helicities[0] << " "; myFile << decay.decay_parameters[3] << " "; // decay enter myFile << decay.decay_parameters[4] << " "; // decay exit diff --git a/projects/injection/public/LeptonInjector/injection/ColumnDepthLeptonInjector.h b/projects/injection/public/LeptonInjector/injection/ColumnDepthLeptonInjector.h index bb9eb0adb..1b3f11e03 100644 --- a/projects/injection/public/LeptonInjector/injection/ColumnDepthLeptonInjector.h +++ b/projects/injection/public/LeptonInjector/injection/ColumnDepthLeptonInjector.h @@ -2,10 +2,10 @@ #ifndef LI_ColumnDepthLeptonInjector_H #define LI_ColumnDepthLeptonInjector_H +#include #include #include #include // for vector -#include #include // for uint32_t #include // for runtime_error @@ -28,8 +28,8 @@ #include "LeptonInjector/injection/Injector.h" // for Injector namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } namespace LI { namespace math { class Vector3D; } } namespace LI { namespace utilities { class LI_random; } } @@ -46,9 +46,9 @@ friend cereal::access; std::shared_ptr interactions; ColumnDepthLeptonInjector(); public: - ColumnDepthLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr depth_func, double disk_radius, double endcap_length); + ColumnDepthLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr depth_func, double disk_radius, double endcap_length); std::string Name() const override; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::tuple PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/injection/public/LeptonInjector/injection/CylinderVolumeLeptonInjector.h b/projects/injection/public/LeptonInjector/injection/CylinderVolumeLeptonInjector.h index 1eddd585c..dca2ef4aa 100644 --- a/projects/injection/public/LeptonInjector/injection/CylinderVolumeLeptonInjector.h +++ b/projects/injection/public/LeptonInjector/injection/CylinderVolumeLeptonInjector.h @@ -2,11 +2,11 @@ #ifndef LI_CylinderVolumeLeptonInjector_H #define LI_CylinderVolumeLeptonInjector_H +#include #include #include #include #include // for uint32_t -#include #include // for runtime_error #include @@ -28,8 +28,8 @@ #include "LeptonInjector/geometry/Cylinder.h" // for Cylinder #include "LeptonInjector/injection/Injector.h" // for Injector -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } namespace LI { namespace math { class Vector3D; } } // lines 40-40 namespace LI { namespace utilities { class LI_random; } } // lines 44-44 @@ -51,9 +51,9 @@ friend cereal::access; std::shared_ptr interactions; CylinderVolumeLeptonInjector(); public: - CylinderVolumeLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, LI::geometry::Cylinder cylinder); + CylinderVolumeLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, LI::geometry::Cylinder cylinder); std::string Name() const override; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::tuple PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/injection/public/LeptonInjector/injection/DecayRangeLeptonInjector.h b/projects/injection/public/LeptonInjector/injection/DecayRangeLeptonInjector.h index 73b15f1c3..c31646251 100644 --- a/projects/injection/public/LeptonInjector/injection/DecayRangeLeptonInjector.h +++ b/projects/injection/public/LeptonInjector/injection/DecayRangeLeptonInjector.h @@ -2,11 +2,11 @@ #ifndef LI_DecayRangeLeptonInjector_H #define LI_DecayRangeLeptonInjector_H +#include #include #include #include #include // for uint32_t -#include #include // for runtime_error #include @@ -28,8 +28,8 @@ #include "LeptonInjector/distributions/primary/vertex/DecayRangePositionDistribution.h" #include "LeptonInjector/injection/Injector.h" // for Injector -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } namespace LI { namespace math { class Vector3D; } } namespace LI { namespace utilities { class LI_random; } } @@ -46,9 +46,9 @@ friend cereal::access; std::shared_ptr interactions; DecayRangeLeptonInjector(); public: - DecayRangeLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, double endcap_length); + DecayRangeLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, double endcap_length); std::string Name() const override; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::tuple PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; template void save(Archive & archive, std::uint32_t const version) const { if(version == 0) { diff --git a/projects/injection/public/LeptonInjector/injection/Injector.h b/projects/injection/public/LeptonInjector/injection/Injector.h index 85372fba9..5e78985eb 100644 --- a/projects/injection/public/LeptonInjector/injection/Injector.h +++ b/projects/injection/public/LeptonInjector/injection/Injector.h @@ -4,6 +4,7 @@ #include // for map #include // for set +#include #include #include #include // for vector @@ -31,12 +32,13 @@ #include "LeptonInjector/dataclasses/Particle.h" // for Particle namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct DecayRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } namespace LI { namespace distributions { class VertexPositionDistribution; } } +namespace LI { namespace distributions { class SecondaryVertexPositionDistribution; } } namespace LI { namespace geometry { class Geometry; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } +namespace LI { namespace injection { class SecondaryInjectionProcess; } } namespace LI { namespace math { class Vector3D; } } namespace LI { namespace utilities { class LI_random; } } @@ -53,47 +55,46 @@ friend cereal::access; std::shared_ptr random; std::shared_ptr detector_model; // This funciton returns true if the given datum is the last entry to be saved in a tree - std::function)> stopping_condition; + std::function, size_t)> stopping_condition; Injector(); private: - std::shared_ptr primary_process; + std::shared_ptr primary_process; std::shared_ptr primary_position_distribution; - std::vector> secondary_processes; - std::vector> secondary_position_distributions; - std::map> secondary_process_map; - std::map> secondary_position_distribution_map; + std::vector> secondary_processes; + std::vector> secondary_position_distributions; + std::map> secondary_process_map; + std::map> secondary_position_distribution_map; public: // Constructors Injector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr random); - Injector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::shared_ptr random); - Injector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random); + Injector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::shared_ptr random); + Injector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random); - void SetStoppingCondition(std::function)> f_in) {stopping_condition = f_in;} - std::shared_ptr FindPositionDistribution(std::shared_ptr process); - void SetPrimaryProcess(std::shared_ptr primary); - std::shared_ptr GetPrimaryProcess() {return primary_process;} - std::vector> GetSecondaryProcesses() {return secondary_processes;} - std::map> GetSecondaryProcessMap() {return secondary_process_map;} - void AddSecondaryProcess(std::shared_ptr secondary); + void SetStoppingCondition(std::function, size_t)> f_in) {stopping_condition = f_in;} + std::shared_ptr FindPrimaryVertexDistribution(std::shared_ptr process); + std::shared_ptr FindSecondaryVertexDistribution(std::shared_ptr process); + void SetPrimaryProcess(std::shared_ptr primary); + std::shared_ptr GetPrimaryProcess() {return primary_process;} + std::vector> GetSecondaryProcesses() {return secondary_processes;} + std::map> GetSecondaryProcessMap() {return secondary_process_map;} + void AddSecondaryProcess(std::shared_ptr secondary); virtual LI::dataclasses::InteractionRecord NewRecord() const; // set primary type from primary process; void SetRandom(std::shared_ptr random); virtual void SampleCrossSection(LI::dataclasses::InteractionRecord & record) const; virtual void SampleCrossSection(LI::dataclasses::InteractionRecord & record, std::shared_ptr interactions) const; - virtual void SampleNeutrissimoDecay(LI::dataclasses::InteractionRecord const & interaction, LI::dataclasses::DecayRecord & decay, double width, double alpha_gen, double alpha_phys, LI::geometry::Geometry *fiducial, double buffer) const; - bool SampleSecondaryProcess(unsigned int idx, - std::shared_ptr parent, - LI::dataclasses::InteractionTreeDatum & datum); + LI::dataclasses::InteractionRecord SampleSecondaryProcess(LI::dataclasses::SecondaryDistributionRecord & secondary_record) const; LI::dataclasses::InteractionTree GenerateEvent(); virtual std::string Name() const; virtual double SecondaryGenerationProbability(std::shared_ptr const & datum) const; + virtual double SecondaryGenerationProbability(std::shared_ptr const & datum, std::shared_ptr process) const; virtual double GenerationProbability(LI::dataclasses::InteractionTree const & tree) const; - virtual double GenerationProbability(std::shared_ptr const & datum, std::shared_ptr process = NULL) const; - virtual double GenerationProbability(LI::dataclasses::InteractionRecord const & record, std::shared_ptr process = NULL) const; + virtual double GenerationProbability(std::shared_ptr const & datum, std::shared_ptr process = NULL) const; + virtual double GenerationProbability(LI::dataclasses::InteractionRecord const & record, std::shared_ptr process = NULL) const; virtual std::set> DensityVariables() const; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionTreeDatum const & datum, LI::dataclasses::Particle::ParticleType const & primary_type) const; - virtual std::vector> GetInjectionDistributions() const; + virtual std::tuple PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const; + virtual std::tuple SecondaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const; + virtual std::vector> GetPrimaryInjectionDistributions() const; virtual std::shared_ptr GetDetectorModel() const; virtual std::shared_ptr GetInteractions() const; unsigned int InjectedEvents() const; diff --git a/projects/injection/public/LeptonInjector/injection/Process.h b/projects/injection/public/LeptonInjector/injection/Process.h index 1628e4ae9..77917ccd1 100644 --- a/projects/injection/public/LeptonInjector/injection/Process.h +++ b/projects/injection/public/LeptonInjector/injection/Process.h @@ -79,27 +79,54 @@ class PhysicalProcess : public Process { }; }; -class InjectionProcess : public PhysicalProcess { +class PrimaryInjectionProcess : public PhysicalProcess { protected: - std::vector> injection_distributions; + std::vector> primary_injection_distributions; public: - InjectionProcess() = default; - InjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions); - InjectionProcess(InjectionProcess const & other); - InjectionProcess(InjectionProcess && other); - InjectionProcess & operator=(InjectionProcess const & other); - InjectionProcess & operator=(InjectionProcess && other); - virtual ~InjectionProcess() = default; + typedef distributions::PrimaryInjectionDistribution InjectionType; + PrimaryInjectionProcess() = default; + PrimaryInjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions); + PrimaryInjectionProcess(PrimaryInjectionProcess const & other); + PrimaryInjectionProcess(PrimaryInjectionProcess && other); + PrimaryInjectionProcess & operator=(PrimaryInjectionProcess const & other); + PrimaryInjectionProcess & operator=(PrimaryInjectionProcess && other); + virtual ~PrimaryInjectionProcess() = default; virtual void AddPhysicalDistribution(std::shared_ptr dist) override; - virtual void AddInjectionDistribution(std::shared_ptr dist); - std::vector> const & GetInjectionDistributions() const; + virtual void AddPrimaryInjectionDistribution(std::shared_ptr dist); + std::vector> const & GetPrimaryInjectionDistributions() const; template void serialize(Archive & archive, std::uint32_t const version) { if(version == 0) { - archive(::cereal::make_nvp("InjectionDistributions", injection_distributions)); + archive(::cereal::make_nvp("PrimaryInjectionDistributions", primary_injection_distributions)); archive(cereal::virtual_base_class(this)); } else { - throw std::runtime_error("InjectionProcess only supports version <= 0!"); + throw std::runtime_error("PrimaryInjectionProcess only supports version <= 0!"); + } + }; +}; + +class SecondaryInjectionProcess : public PhysicalProcess { +protected: + std::vector> secondary_injection_distributions; +public: + typedef distributions::SecondaryInjectionDistribution InjectionType; + SecondaryInjectionProcess() = default; + SecondaryInjectionProcess(LI::dataclasses::Particle::ParticleType _primary_type, std::shared_ptr _interactions); + SecondaryInjectionProcess(SecondaryInjectionProcess const & other); + SecondaryInjectionProcess(SecondaryInjectionProcess && other); + SecondaryInjectionProcess & operator=(SecondaryInjectionProcess const & other); + SecondaryInjectionProcess & operator=(SecondaryInjectionProcess && other); + virtual ~SecondaryInjectionProcess() = default; + virtual void AddPhysicalDistribution(std::shared_ptr dist) override; + virtual void AddSecondaryInjectionDistribution(std::shared_ptr dist); + std::vector> const & GetSecondaryInjectionDistributions() const; + template + void serialize(Archive & archive, std::uint32_t const version) { + if(version == 0) { + archive(::cereal::make_nvp("SecondaryInjectionDistributions", secondary_injection_distributions)); + archive(cereal::virtual_base_class(this)); + } else { + throw std::runtime_error("SecondaryInjectionProcess only supports version <= 0!"); } }; }; diff --git a/projects/injection/public/LeptonInjector/injection/RangedLeptonInjector.h b/projects/injection/public/LeptonInjector/injection/RangedLeptonInjector.h index 300be9381..f37cc7846 100644 --- a/projects/injection/public/LeptonInjector/injection/RangedLeptonInjector.h +++ b/projects/injection/public/LeptonInjector/injection/RangedLeptonInjector.h @@ -2,11 +2,11 @@ #ifndef LI_RangedLeptonInjector_H #define LI_RangedLeptonInjector_H +#include #include #include #include #include // for uint32_t -#include #include // for runtime_error #include @@ -26,8 +26,8 @@ #include "LeptonInjector/distributions/primary/vertex/RangePositionDistribution.h" #include "LeptonInjector/injection/Injector.h" // for Injector -namespace LI { namespace dataclasses { struct InteractionRecord; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } namespace LI { namespace math { class Vector3D; } } namespace LI { namespace utilities { class LI_random; } } @@ -44,9 +44,9 @@ friend cereal::access; std::shared_ptr interactions; RangedLeptonInjector(); public: - RangedLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, double endcap_length); + RangedLeptonInjector(unsigned int events_to_inject, std::shared_ptr detector_model, std::shared_ptr primary_process, std::vector> secondary_processes, std::shared_ptr random, std::shared_ptr range_func, double disk_radius, double endcap_length); std::string Name() const override; - virtual std::pair InjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; + virtual std::tuple PrimaryInjectionBounds(LI::dataclasses::InteractionRecord const & interaction) const override; template void save(Archive & archive, std::uint32_t const version) const { diff --git a/projects/injection/public/LeptonInjector/injection/TreeWeighter.h b/projects/injection/public/LeptonInjector/injection/TreeWeighter.h index a70bb5b3a..a3333de8c 100644 --- a/projects/injection/public/LeptonInjector/injection/TreeWeighter.h +++ b/projects/injection/public/LeptonInjector/injection/TreeWeighter.h @@ -3,9 +3,9 @@ #define LI_TreeWeighter_H #include // for map +#include #include // for shared_ptr #include // for vector -#include // for pair #include #include @@ -18,12 +18,14 @@ #include "LeptonInjector/dataclasses/InteractionTree.h" // for InteractionT... #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } -namespace LI { namespace distributions { class InjectionDistribution; } } +namespace LI { namespace distributions { class PrimaryInjectionDistribution; } } +namespace LI { namespace distributions { class SecondaryInjectionDistribution; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace injection { class Injector; } } -namespace LI { namespace injection { class InjectionProcess; } } +namespace LI { namespace injection { class PrimaryInjectionProcess; } } +namespace LI { namespace injection { class SecondaryInjectionProcess; } } namespace LI { namespace injection { class PhysicalProcess; } } namespace LI { namespace math { class Vector3D; } } @@ -31,24 +33,29 @@ namespace LI { namespace injection { // Class handling weight calculation for a single pair of injection and physical processes -class LeptonProcessWeighter { +template +class ProcessWeighter { private: std::shared_ptr phys_process; - std::shared_ptr inj_process; - std::vector> unique_gen_distributions; + std::shared_ptr inj_process; + std::vector> unique_gen_distributions; std::vector> unique_phys_distributions; std::shared_ptr detector_model; + std::vector> const & GetInjectionDistributions(); void Initialize(); double normalization; public: - double InteractionProbability(std::pair const & bounds, LI::dataclasses::InteractionRecord const & record) const; - double NormalizedPositionProbability(std::pair const & bounds, LI::dataclasses::InteractionRecord const & record) const; - double PhysicalProbability(std::pair const & bounds, LI::dataclasses::InteractionRecord const & record) const; + double InteractionProbability(std::tuple const & bounds, LI::dataclasses::InteractionRecord const & record) const; + double NormalizedPositionProbability(std::tuple const & bounds, LI::dataclasses::InteractionRecord const & record) const; + double PhysicalProbability(std::tuple const & bounds, LI::dataclasses::InteractionRecord const & record) const; double GenerationProbability(LI::dataclasses::InteractionTreeDatum const & datum) const; - double EventWeight(std::pair const & bounds, LI::dataclasses::InteractionTreeDatum const & datum) const; - LeptonProcessWeighter(std::shared_ptr phys_process, std::shared_ptr inj_process, std::shared_ptr detector_model); + double EventWeight(std::tuple const & bounds, LI::dataclasses::InteractionTreeDatum const & datum) const; + ProcessWeighter(std::shared_ptr phys_process, std::shared_ptr inj_process, std::shared_ptr detector_model); -}; // LeptonProcessWeighter +}; // ProcessWeighter + +typedef ProcessWeighter PrimaryProcessWeighter; +typedef ProcessWeighter SecondaryProcessWeighter; // Parent class for calculating event weights // Assumes there is a unique secondary physical process for each particle type @@ -61,11 +68,11 @@ class LeptonTreeWeighter { std::vector> secondary_physical_processes; // Calculated upon initialization - std::vector> primary_process_weighters; + std::vector> primary_process_weighters; std::vector< std::map< LI::dataclasses::Particle::ParticleType, - std::shared_ptr + std::shared_ptr > > secondary_process_weighter_maps; @@ -81,6 +88,8 @@ class LeptonTreeWeighter { } //namespace injection } //namespace LI +#include "TreeWeighter.tcc" + CEREAL_CLASS_VERSION(LI::injection::LeptonTreeWeighter, 0); diff --git a/projects/injection/public/LeptonInjector/injection/TreeWeighter.tcc b/projects/injection/public/LeptonInjector/injection/TreeWeighter.tcc new file mode 100644 index 000000000..8f89aee99 --- /dev/null +++ b/projects/injection/public/LeptonInjector/injection/TreeWeighter.tcc @@ -0,0 +1,261 @@ +#pragma once +#ifndef LI_TreeWeighter_TCC +#define LI_TreeWeighter_TCC +#include "LeptonInjector/injection/TreeWeighter.h" + +#include // for ite... +#include // for array +#include // for assert +#include // for exp +#include // for ini... +#include // for ope... +#include // for set +#include // for out... +#include "LeptonInjector/interactions/CrossSection.h" // for Cro... +#include "LeptonInjector/interactions/InteractionCollection.h" // for Cro... +#include "LeptonInjector/dataclasses/InteractionRecord.h" // for Int... +#include "LeptonInjector/dataclasses/InteractionSignature.h" // for Int... +#include "LeptonInjector/detector/DetectorModel.h" // for Ear... +#include "LeptonInjector/detector/Coordinates.h" +#include "LeptonInjector/distributions/Distributions.h" // for Inj... +#include "LeptonInjector/geometry/Geometry.h" // for Geo... +#include "LeptonInjector/injection/Injector.h" // for Inj... +#include "LeptonInjector/injection/Process.h" // for Phy... +#include "LeptonInjector/injection/WeightingUtils.h" // for Cro... +#include "LeptonInjector/math/Vector3D.h" // for Vec... + +#include +#include +#include +#include + +#include "LeptonInjector/injection/Injector.h" +#include "LeptonInjector/interactions/CrossSection.h" +#include "LeptonInjector/dataclasses/InteractionSignature.h" + +namespace LI { +namespace injection { + +double one_minus_exp_of_negative(double x) { + if(x < 1e-1) { + return std::exp(std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0); + } else { + return 1.0 - std::exp(-x); + } +} + +double log_one_minus_exp_of_negative(double x) { + if(x < 1e-1) { + return std::log(x) - x/2.0 + x*x/24.0 - x*x*x*x/2880.0; + } else if(x > 3) { + double ex = std::exp(-x); + double ex2 = ex * ex; + double ex3 = ex2 * ex; + double ex4 = ex3 * ex; + double ex5 = ex4 * ex; + double ex6 = ex5 * ex; + return -(ex + ex2 / 2.0 + ex3 / 3.0 + ex4 / 4.0 + ex5 / 5.0 + ex6 / 6.0); + } else { + return std::log(1.0 - std::exp(-x)); + } +} + +//--------------- +// class ProcessWeighter +//--------------- + +template +void ProcessWeighter::Initialize() { + normalization = 1.0; + for(auto physical_dist : phys_process->GetPhysicalDistributions()) { + const LI::distributions::PhysicallyNormalizedDistribution* p = dynamic_cast(physical_dist.get()); + if(p) { + if(p->IsNormalizationSet()) { + normalization *= p->GetNormalization(); + } + } + } + unique_gen_distributions = GetInjectionDistributions(); + unique_phys_distributions = phys_process->GetPhysicalDistributions(); + for(typename std::vector>::reverse_iterator gen_it = unique_gen_distributions.rbegin(); + gen_it != unique_gen_distributions.rend(); ++gen_it) { + for(std::vector>::reverse_iterator phys_it = unique_phys_distributions.rbegin(); + phys_it != unique_phys_distributions.rend(); ++phys_it) { + if((*gen_it) == (*phys_it)) { + unique_gen_distributions.erase(std::next(gen_it).base()); + unique_phys_distributions.erase(std::next(phys_it).base()); + break; + } + } + } +} + +template +double ProcessWeighter::InteractionProbability(std::tuple const & bounds, LI::dataclasses::InteractionRecord const & record) const { + using LI::detector::DetectorPosition; + using LI::detector::DetectorDirection; + LI::math::Vector3D interaction_vertex( + record.interaction_vertex[0], + record.interaction_vertex[1], + record.interaction_vertex[2]); + + LI::math::Vector3D primary_direction( + record.primary_momentum[1], + record.primary_momentum[2], + record.primary_momentum[3]); + primary_direction.normalize(); + + LI::geometry::Geometry::IntersectionList intersections = detector_model->GetIntersections(DetectorPosition(interaction_vertex), DetectorDirection(primary_direction)); + std::map>> const & cross_sections_by_target = phys_process->GetInteractions()->GetCrossSectionsByTarget(); + std::vector targets; + targets.reserve(cross_sections_by_target.size()); + std::vector total_cross_sections; + double total_decay_length = phys_process->GetInteractions()->TotalDecayLength(record); + + LI::dataclasses::InteractionRecord fake_record = record; + for(auto const & target_xs : cross_sections_by_target) { + targets.push_back(target_xs.first); + fake_record.target_mass = detector_model->GetTargetMass(target_xs.first); + std::vector> const & xs_list = target_xs.second; + double total_xs = 0.0; + for(auto const & xs : xs_list) { + std::vector signatures = xs->GetPossibleSignaturesFromParents(record.signature.primary_type, target_xs.first); + for(auto const & signature : signatures) { + fake_record.signature = signature; + // Add total cross section + total_xs += xs->TotalCrossSection(fake_record); + } + } + total_cross_sections.push_back(total_xs); + } + + double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(std::get<1>(bounds)), targets, total_cross_sections, total_decay_length); + + double interaction_probability; + if(total_interaction_depth < 1e-6) { + interaction_probability = total_interaction_depth; + } else { + interaction_probability = one_minus_exp_of_negative(total_interaction_depth); + } + return interaction_probability; +} + +template +double ProcessWeighter::NormalizedPositionProbability(std::tuple const & bounds, LI::dataclasses::InteractionRecord const & record) const { + using LI::detector::DetectorPosition; + using LI::detector::DetectorDirection; + LI::math::Vector3D interaction_vertex( + record.interaction_vertex[0], + record.interaction_vertex[1], + record.interaction_vertex[2]); + + LI::math::Vector3D primary_direction( + record.primary_momentum[1], + record.primary_momentum[2], + record.primary_momentum[3]); + primary_direction.normalize(); + + LI::geometry::Geometry::IntersectionList intersections = detector_model->GetIntersections(DetectorPosition(interaction_vertex), DetectorDirection(primary_direction)); + std::map>> const & cross_sections_by_target = phys_process->GetInteractions()->GetCrossSectionsByTarget(); + + unsigned int n_targets = cross_sections_by_target.size(); + + std::vector targets; targets.reserve(n_targets); + std::vector total_cross_sections; + double total_decay_length = phys_process->GetInteractions()->TotalDecayLength(record); + LI::dataclasses::InteractionRecord fake_record = record; + for(auto const & target_xs : cross_sections_by_target) { + targets.push_back(target_xs.first); + fake_record.target_mass = detector_model->GetTargetMass(target_xs.first); + std::vector> const & xs_list = target_xs.second; + double total_xs = 0.0; + for(auto const & xs : xs_list) { + std::vector signatures = xs->GetPossibleSignaturesFromParents(record.signature.primary_type, target_xs.first); + for(auto const & signature : signatures) { + fake_record.signature = signature; + // Add total cross section + total_xs += xs->TotalCrossSection(fake_record); + } + } + total_cross_sections.push_back(total_xs); + } + + double total_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(std::get<1>(bounds)), targets, total_cross_sections, total_decay_length); // unitless + double traversed_interaction_depth = detector_model->GetInteractionDepthInCGS(intersections, DetectorPosition(std::get<0>(bounds)), DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); + double interaction_density = detector_model->GetInteractionDensity(intersections, DetectorPosition(interaction_vertex), targets, total_cross_sections, total_decay_length); //units of m^-1 + + double prob_density; + if(total_interaction_depth < 1e-6) { + prob_density = interaction_density / total_interaction_depth; + } else { + prob_density = interaction_density * exp(-log_one_minus_exp_of_negative(total_interaction_depth) - traversed_interaction_depth); + } + + return prob_density; +} + +template +double ProcessWeighter::PhysicalProbability(std::tuple const & bounds, + LI::dataclasses::InteractionRecord const & record ) const { + + double physical_probability = 1.0; + double prob = InteractionProbability(bounds, record); + physical_probability *= prob; + + prob = NormalizedPositionProbability(bounds, record); + physical_probability *= prob; + + prob = LI::injection::CrossSectionProbability(detector_model, phys_process->GetInteractions(), record); + physical_probability *= prob; + + for(auto physical_dist : unique_phys_distributions) { + physical_probability *= physical_dist->GenerationProbability(detector_model, phys_process->GetInteractions(), record); + } + + return normalization * physical_probability; +} + +template +double ProcessWeighter::GenerationProbability(LI::dataclasses::InteractionTreeDatum const & datum ) const { + double gen_probability = LI::injection::CrossSectionProbability(detector_model, phys_process->GetInteractions(), datum.record); + + for(auto gen_dist : unique_gen_distributions) { + gen_probability *= gen_dist->GenerationProbability(detector_model, phys_process->GetInteractions(), datum.record); + } + return gen_probability; +} + +template +double ProcessWeighter::EventWeight(std::tuple const & bounds, + LI::dataclasses::InteractionTreeDatum const & datum) const { + return PhysicalProbability(bounds,datum.record)/GenerationProbability(datum); +} + +template +ProcessWeighter::ProcessWeighter(std::shared_ptr phys_process, std::shared_ptr inj_process, std::shared_ptr detector_model) + : phys_process(phys_process) + , inj_process(inj_process) + , detector_model(detector_model) +{ + Initialize(); +} + +//template +//std::vector> const & ProcessWeighter::GetInjectionDistributions() { +// return unique_gen_distributions; +//} + +template<> +std::vector> const & PrimaryProcessWeighter::GetInjectionDistributions() { + return inj_process->GetPrimaryInjectionDistributions(); +} + +template<> +std::vector> const & SecondaryProcessWeighter::GetInjectionDistributions() { + return inj_process->GetSecondaryInjectionDistributions(); +} + +} // namespace injection +} // namespace LI + +#endif // LI_TreeWeighter_TCC diff --git a/projects/injection/public/LeptonInjector/injection/Weighter.h b/projects/injection/public/LeptonInjector/injection/Weighter.h index 076af28a0..cbcfdf9be 100644 --- a/projects/injection/public/LeptonInjector/injection/Weighter.h +++ b/projects/injection/public/LeptonInjector/injection/Weighter.h @@ -5,7 +5,6 @@ #include // for tuple #include // for shared_ptr #include // for vector -#include // for pair #include #include @@ -16,7 +15,7 @@ #include namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { namespace distributions { class WeightableDistribution; } } namespace LI { namespace injection { class Injector; } } @@ -50,10 +49,10 @@ class LeptonWeighter { //TODO Think about the relationship between interaction probability and the positional distribution. Check that the math works out //TODO Add versions of these functions that take precomputed intersections double InteractionProbability(std::shared_ptr injector, LI::dataclasses::InteractionRecord const & record) const; - double InteractionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const; + double InteractionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const; double UnnormalizedPositionProbability(std::shared_ptr injector, LI::dataclasses::InteractionRecord const & record) const; - double UnnormalizedPositionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const; - double NormalizedPositionProbability(std::pair bounds, LI::dataclasses::InteractionRecord const & record) const; + double UnnormalizedPositionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const; + double NormalizedPositionProbability(std::tuple bounds, LI::dataclasses::InteractionRecord const & record) const; //TODO Add a function to check that we have the right match up of variables between generator and physical distribution //TODO Figure out a way to check that physical and generation probabilities match, and ignore those when weighting LeptonWeighter(std::vector> injectors, std::shared_ptr detector_model, std::shared_ptr interactions, std::vector> physical_distributions); diff --git a/projects/injection/public/LeptonInjector/injection/WeightingUtils.h b/projects/injection/public/LeptonInjector/injection/WeightingUtils.h index abd21f38e..db928adf7 100644 --- a/projects/injection/public/LeptonInjector/injection/WeightingUtils.h +++ b/projects/injection/public/LeptonInjector/injection/WeightingUtils.h @@ -5,7 +5,7 @@ #include // for shared_ptr namespace LI { namespace interactions { class InteractionCollection; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace detector { class DetectorModel; } } namespace LI { diff --git a/projects/interactions/private/CrossSection.cxx b/projects/interactions/private/CrossSection.cxx index 9b94fc552..5d3447586 100644 --- a/projects/interactions/private/CrossSection.cxx +++ b/projects/interactions/private/CrossSection.cxx @@ -1,10 +1,28 @@ #include "LeptonInjector/interactions/CrossSection.h" +#include "LeptonInjector/dataclasses/InteractionRecord.h" namespace LI { namespace interactions { CrossSection::CrossSection() {} +void CrossSection::SampleFinalState(dataclasses::InteractionRecord & record, std::shared_ptr rand) const { + LI::dataclasses::CrossSectionDistributionRecord csdr(record); + this->SampleFinalState(csdr, rand); + csdr.Finalize(record); +} + +double CrossSection::TotalCrossSectionAllFinalStates(LI::dataclasses::InteractionRecord const & record) const { + std::vector signatures = this->GetPossibleSignaturesFromParents(record.signature.primary_type, record.signature.target_type); + LI::dataclasses::InteractionRecord fake_record = record; + double total_cross_section = 0; + for(auto signature : signatures) { + fake_record.signature = signature; + total_cross_section += this->TotalCrossSection(record); + } + return total_cross_section; +} + bool CrossSection::operator==(CrossSection const & other) const { if(this == &other) return true; diff --git a/projects/interactions/private/DISFromSpline.cxx b/projects/interactions/private/DISFromSpline.cxx index bc393cb15..7d69d1ca4 100644 --- a/projects/interactions/private/DISFromSpline.cxx +++ b/projects/interactions/private/DISFromSpline.cxx @@ -21,6 +21,7 @@ #include "LeptonInjector/dataclasses/InteractionRecord.h" // for Interactio... #include "LeptonInjector/dataclasses/Particle.h" // for Particle #include "LeptonInjector/utilities/Random.h" // for LI_random +#include "LeptonInjector/utilities/Constants.h" // for electronMass namespace LI { namespace interactions { @@ -152,6 +153,32 @@ void DISFromSpline::LoadFromMemory(std::vector & differential_data, std::v total_cross_section_.read_fits_mem(total_data.data(), total_data.size()); } +double DISFromSpline::GetLeptonMass(LI::dataclasses::Particle::ParticleType lepton_type) { + int32_t lepton_number = std::abs(static_cast(lepton_type)); + double lepton_mass; + switch(lepton_number) { + case 11: + lepton_mass = LI::utilities::Constants::electronMass; + break; + case 13: + lepton_mass = LI::utilities::Constants::muonMass; + break; + case 15: + lepton_mass = LI::utilities::Constants::tauMass; + break; + case 12: + lepton_mass = 0; + case 14: + lepton_mass = 0; + case 16: + lepton_mass = 0; + break; + default: + throw std::runtime_error("Unknown lepton type!"); + } + return lepton_mass; +} + void DISFromSpline::ReadParamsFromSplineTable() { // returns true if successfully read target mass bool mass_good = differential_cross_section_.read_key("TARGETMASS", target_mass_); @@ -248,15 +275,8 @@ void DISFromSpline::InitializeSignatures() { double DISFromSpline::TotalCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + primary_energy = interaction.primary_momentum[0]; // if we are below threshold, return 0 if(primary_energy < InteractionThreshold(interaction)) return 0; @@ -284,28 +304,11 @@ double DISFromSpline::TotalCrossSection(LI::dataclasses::Particle::ParticleType return unit * std::pow(10.0, log_xs); } -// No implementation for DIS yet, just use non-target function -double DISFromSpline::TotalCrossSection(LI::dataclasses::Particle::ParticleType primary_type, double primary_energy, LI::dataclasses::Particle::ParticleType target_type) const { - return DISFromSpline::TotalCrossSection(primary_type,primary_energy); -} - - double DISFromSpline::DifferentialCrossSection(dataclasses::InteractionRecord const & interaction) const { rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), interaction.target_mass); double primary_energy; - rk::P4 p1_lab; - rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + primary_energy = interaction.primary_momentum[0]; assert(interaction.signature.secondary_types.size() == 2); unsigned int lepton_index = (isLepton(interaction.signature.secondary_types[0])) ? 0 : 1; unsigned int other_index = 1 - lepton_index; @@ -320,7 +323,7 @@ double DISFromSpline::DifferentialCrossSection(dataclasses::InteractionRecord co double Q2 = -q.dot(q); double y = 1.0 - p2.dot(p3) / p2.dot(p1); double x = Q2 / (2.0 * p2.dot(q)); - double lepton_mass = particleMass(interaction.signature.secondary_types[lepton_index]); + double lepton_mass = GetLeptonMass(interaction.signature.secondary_types[lepton_index]); return DifferentialCrossSection(primary_energy, x, y, lepton_mass, Q2); } @@ -364,42 +367,34 @@ double DISFromSpline::InteractionThreshold(dataclasses::InteractionRecord const return 0; } -void DISFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction, std::shared_ptr random) const { +void DISFromSpline::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { // Uses Metropolis-Hastings Algorithm! // useful for cases where we don't know the supremum of our distribution, and the distribution is multi-dimensional if (differential_cross_section_.get_ndim() != 3) { throw std::runtime_error("I expected 3 dimensions in the cross section spline, but got " + std::to_string(differential_cross_section_.get_ndim()) +". Maybe your fits file doesn't have the right 'INTERACTION' key?"); } - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p1(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), record.target_mass); // we assume that: // the target is stationary so its energy is just its mass // the incoming neutrino is massless, so its kinetic energy is its total energy - // double s = target_mass_ * tinteraction.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; + // double s = target_mass_ * trecord.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; // double s = std::pow(rk::invMass(p1, p2), 2); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p2_lab = p2; - primary_energy = p1_lab.e(); - } else { - // Rest frame of p2 will be our "lab" frame - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + p1_lab = p1; + p2_lab = p2; + primary_energy = p1_lab.e(); - unsigned int lepton_index = (isLepton(interaction.signature.secondary_types[0])) ? 0 : 1; + unsigned int lepton_index = (isLepton(record.signature.secondary_types[0])) ? 0 : 1; unsigned int other_index = 1 - lepton_index; - double m = particleMass(interaction.signature.secondary_types[lepton_index]); + double m = GetLeptonMass(record.signature.secondary_types[lepton_index]); - double m1 = interaction.primary_mass; + double m1 = record.primary_mass; double m3 = m; double E1_lab = p1_lab.e(); double E2_lab = p2_lab.e(); @@ -517,10 +512,10 @@ void DISFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction double final_x = pow(10., kin_vars[1]); double final_y = pow(10., kin_vars[2]); - interaction.interaction_parameters.resize(3); - interaction.interaction_parameters[0] = E1_lab; - interaction.interaction_parameters[1] = final_x; - interaction.interaction_parameters[2] = final_y; + record.interaction_parameters.clear(); + record.interaction_parameters["energy"] = E1_lab; + record.interaction_parameters["bjorken_x"] = final_x; + record.interaction_parameters["bjorken_y"] = final_y; double Q2 = 2 * E1_lab * E2_lab * pow(10.0, kin_vars[1] + kin_vars[2]); double p1x_lab = std::sqrt(p1_lab.px() * p1_lab.px() + p1_lab.py() * p1_lab.py() + p1_lab.pz() * p1_lab.pz()); @@ -546,34 +541,21 @@ void DISFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction rk::P4 p3; rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } - - interaction.secondary_momenta.resize(2); - interaction.secondary_masses.resize(2); - interaction.secondary_helicity.resize(2); + p3 = p3_lab; + p4 = p4_lab; - interaction.secondary_momenta[lepton_index][0] = p3.e(); // p3_energy - interaction.secondary_momenta[lepton_index][1] = p3.px(); // p3_x - interaction.secondary_momenta[lepton_index][2] = p3.py(); // p3_y - interaction.secondary_momenta[lepton_index][3] = p3.pz(); // p3_z - interaction.secondary_masses[lepton_index] = p3.m(); + std::vector & secondaries = record.GetSecondaryParticleRecords(); + LI::dataclasses::SecondaryParticleRecord & lepton = secondaries[lepton_index]; + LI::dataclasses::SecondaryParticleRecord & other = secondaries[other_index]; - interaction.secondary_helicity[lepton_index] = interaction.primary_helicity; - interaction.secondary_momenta[other_index][0] = p4.e(); // p4_energy - interaction.secondary_momenta[other_index][1] = p4.px(); // p4_x - interaction.secondary_momenta[other_index][2] = p4.py(); // p4_y - interaction.secondary_momenta[other_index][3] = p4.pz(); // p4_z - interaction.secondary_masses[other_index] = p4.m(); + lepton.SetFourMomentum({p3.e(), p3.px(), p3.py(), p3.pz()}); + lepton.SetMass(p3.m()); + lepton.SetHelicity(record.primary_helicity); - interaction.secondary_helicity[other_index] = interaction.target_helicity; + other.SetFourMomentum({p4.e(), p4.px(), p4.py(), p4.pz()}); + other.SetMass(p4.m()); + other.SetHelicity(record.target_helicity); } double DISFromSpline::FinalStateProbability(dataclasses::InteractionRecord const & interaction) const { diff --git a/projects/interactions/private/DarkNewsCrossSection.cxx b/projects/interactions/private/DarkNewsCrossSection.cxx index 6e27794f0..420192cb7 100644 --- a/projects/interactions/private/DarkNewsCrossSection.cxx +++ b/projects/interactions/private/DarkNewsCrossSection.cxx @@ -36,39 +36,30 @@ bool DarkNewsCrossSection::equal(CrossSection const & other) const { double DarkNewsCrossSection::TotalCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; - LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + LI::dataclasses::Particle::ParticleType target_type = interaction.signature.primary_type; + std::array const & primary_momentum = interaction.primary_momentum; + double const & primary_mass = interaction.primary_mass; + rk::P4 p1(geom3::Vector3(primary_momentum[1], primary_momentum[2], primary_momentum[3]), primary_mass); + double primary_energy = primary_momentum[0]; return TotalCrossSection(primary_type, primary_energy, target_type); } double DarkNewsCrossSection::DifferentialCrossSection(dataclasses::InteractionRecord const & interaction) const { - - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - rk::P4 p3(geom3::Vector3(interaction.secondary_momenta[0][1], interaction.secondary_momenta[0][2], interaction.secondary_momenta[0][3]), interaction.secondary_masses[0]); + + std::array const & primary_momentum = interaction.primary_momentum; + double const & primary_mass = interaction.primary_mass; + std::array const & secondary_momentum = interaction.secondary_momenta[0]; + double const & secondary_mass = interaction.secondary_masses[0]; + rk::P4 p1(geom3::Vector3(primary_momentum[1], primary_momentum[2], primary_momentum[3]), primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), interaction.target_mass); + rk::P4 p3(geom3::Vector3(secondary_momentum[1], secondary_momentum[2], secondary_momentum[3]), secondary_mass); double primary_energy; rk::P4 p1_lab; rk::P4 p3_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p3_lab = p2; - primary_energy = p1_lab.e(); - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p3_lab = boost_start_to_lab * p3; - primary_energy = p1_lab.e(); - } + p1_lab = p1; + p3_lab = p2; + primary_energy = p1_lab.e(); double Q2 = -1*(std::pow(p1_lab.m(),2) + std::pow(p3_lab.m(),2) - 2.0*p1_lab.dot(p3_lab)); return DifferentialCrossSection(interaction.signature.primary_type, interaction.signature.target_type, primary_energy, Q2); @@ -112,36 +103,38 @@ double DarkNewsCrossSection::Q2Max(dataclasses::InteractionRecord const & intera return 0; } -void DarkNewsCrossSection::SetUpscatteringMasses(dataclasses::InteractionRecord & interaction) const { +double DarkNewsCrossSection::TargetMass(dataclasses::ParticleType const &) const { // Should be implemented on the python side // Not pure virtual in order to allow SampleFinalState to call - throw(LI::utilities::PythonImplementationError("DarkNewsCrossSection::SetUpscatteringMasses should be implemented in Python!")); - return; + throw(LI::utilities::PythonImplementationError("DarkNewsCrossSection::TargetMass should be implemented in Python!")); + return 0; } -void DarkNewsCrossSection::SetUpscatteringHelicities(dataclasses::InteractionRecord & interaction) const { +std::vector DarkNewsCrossSection::SecondaryMasses(std::vector const & secondary_types) const { // Should be implemented on the python side // Not pure virtual in order to allow SampleFinalState to call - throw(LI::utilities::PythonImplementationError("DarkNewsCrossSection::SetUpscatteringHelicities should be implemented in Python!")); - return; + throw(LI::utilities::PythonImplementationError("DarkNewsCrossSection::SecondaryMasses should be implemented in Python!")); + return std::vector(); } +std::vector DarkNewsCrossSection::SecondaryHelicities(dataclasses::InteractionRecord const & record) const { + // Should be implemented on the python side + // Not pure virtual in order to allow SampleFinalState to call + throw(LI::utilities::PythonImplementationError("DarkNewsCrossSection::SecondaryHelicities should be implemented in Python!")); + return std::vector(); +} -void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const { +void DarkNewsCrossSection::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { // Set our upscattering masses and helicities using values from DarkNews - SetUpscatteringMasses(interaction); - SetUpscatteringHelicities(interaction); - interaction.primary_mass = 0; - interaction.target_mass = m_target; - interaction.secondary_masses.push_back(m_ups); - interaction.secondary_masses.push_back(m_target); - interaction.secondary_helicity.push_back(h_ups); - interaction.secondary_helicity.push_back(h_target); + record.SetTargetMass(TargetMass(record.target_type)); + std::vector secondary_masses = SecondaryMasses(record.signature.secondary_types); + std::vector secondary_helicities = SecondaryHelicities(record.record); + // Uses Metropolis-Hastings Algorithm // Assumes we have the differential xsec v.s. Q^2 - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p1(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), record.target_mass); // we assume that: // the target is stationary so its energy is just its mass @@ -149,26 +142,19 @@ void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & int // double s = std::pow(rk::invMass(p1, p2), 2); // define masses that we will use - double m1 = interaction.primary_mass; - double m2 = interaction.target_mass; - double m3 = interaction.secondary_masses[0]; - double m4 = interaction.secondary_masses[1]; + double m1 = record.primary_mass; + double m2 = record.target_mass; + double m3 = secondary_masses.at(0); + double m4 = secondary_masses.at(1); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p2_lab = p2; - primary_energy = p1_lab.e(); - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } - double minQ2 = Q2Min(interaction); - double maxQ2 = Q2Max(interaction); + p1_lab = p1; + p2_lab = p2; + primary_energy = p1_lab.e(); + double minQ2 = Q2Min(record.record); + double maxQ2 = Q2Max(record.record); double log_minQ2 = log10(minQ2); double log_maxQ2 = log10(maxQ2); @@ -199,8 +185,8 @@ void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & int while(std::abs(ComputeCosThetaLab(kin_vars[1]))>1) { kin_vars[1] = std::pow(10,random->Uniform(log_minQ2,log_maxQ2)); } - - test_cross_section = DifferentialCrossSection(interaction.signature.primary_type, interaction.signature.target_type, primary_energy, kin_vars[1]); + + test_cross_section = DifferentialCrossSection(record.GetPrimaryType(), record.GetTargetType(), primary_energy, kin_vars[1]); cross_section = test_cross_section; // this is the magic part. Metropolis Hastings Algorithm. @@ -210,7 +196,7 @@ void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & int for(size_t j = 0; j <= burnin; j++) { // repeat the sampling from above to get a new valid point test_kin_vars[1] = std::pow(10,random->Uniform(log_minQ2,log_maxQ2)); - test_cross_section = DifferentialCrossSection(interaction.signature.primary_type, interaction.signature.target_type, primary_energy, test_kin_vars[1]); + test_cross_section = DifferentialCrossSection(record.GetPrimaryType(), record.GetTargetType(), primary_energy, test_kin_vars[1]); double odds = (test_cross_section / cross_section); accept = (cross_section == 0 || (odds > 1.) || random->Uniform(0, 1) < odds); @@ -227,13 +213,13 @@ void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & int double final_Q2 = kin_vars[1]; // // Working in center of mass frame, assuming 2 -> 2 scattering - // double E1CM = (s + pow(interaction.primary_mass,2) - pow(interaction.target_mass,2)) / (2*sqrt(s)); + // double E1CM = (s + pow(interaction.primary_mass,2) - pow(interaction.GetTargetMass(),2)) / (2*sqrt(s)); // double E3CM = (s + pow(interaction.secondary_masses[0],2) - pow(interaction.secondary_masses[1],2)) / (2*sqrt(s)); // double P1CM = sqrt(E1CM*E1CM - pow(interaction.primary_mass,2)); // double P3CM = sqrt(E3CM*E3CM - pow(interaction.secondary_masses[0],2)); - - // double CosThetaCM = (final_Q2 - // + pow(interaction.primary_mass,2) + + // double CosThetaCM = (final_Q2 + // + pow(interaction.primary_mass,2) // + pow(interaction.secondary_masses[0],2) // - 2*E1CM*E3CM) // / (-2*P1CM*P3CM); @@ -260,32 +246,25 @@ void DarkNewsCrossSection::SampleFinalState(dataclasses::InteractionRecord & int rk::P4 p4_lab = p1_lab + p2_lab - p3_lab; // Rotate back to whatever frame the traget was in originally. - // I believe we have identified the lab frame as the target + // I believe we have identified the lab frame as the target // rest ferame in this function rk::P4 p3; rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } + p3 = p3_lab; + p4 = p4_lab; - // TODO: helicity update for secondary particles - interaction.secondary_momenta.resize(2); + std::vector & secondaries = record.GetSecondaryParticleRecords(); - interaction.secondary_momenta[0][0] = p3.e(); // p3_energy - interaction.secondary_momenta[0][1] = p3.px(); // p3_x - interaction.secondary_momenta[0][2] = p3.py(); // p3_y - interaction.secondary_momenta[0][3] = p3.pz(); // p3_z + LI::dataclasses::SecondaryParticleRecord & p3_record = secondaries[0]; + LI::dataclasses::SecondaryParticleRecord & p4_record = secondaries[1]; - interaction.secondary_momenta[1][0] = p4.e(); // p4_energy - interaction.secondary_momenta[1][1] = p4.px(); // p4_x - interaction.secondary_momenta[1][2] = p4.py(); // p4_y - interaction.secondary_momenta[1][3] = p4.pz(); // p4_z + p3_record.SetFourMomentum({p3.e(), p3.px(), p3.py(), p3.pz()}); + p3_record.SetMass(secondary_masses.at(0)); + p3_record.SetHelicity(secondary_helicities.at(0)); + p4_record.SetFourMomentum({p4.e(), p4.px(), p4.py(), p4.pz()}); + p4_record.SetMass(secondary_masses.at(1)); + p4_record.SetHelicity(secondary_helicities.at(1)); } double DarkNewsCrossSection::FinalStateProbability(dataclasses::InteractionRecord const & record) const { @@ -305,4 +284,4 @@ std::vector DarkNewsCrossSection::DensityVariables() const { } } // namespace interactions -} // namespace LI \ No newline at end of file +} // namespace LI diff --git a/projects/interactions/private/DarkNewsDecay.cxx b/projects/interactions/private/DarkNewsDecay.cxx index fdf99bad0..460fc6149 100644 --- a/projects/interactions/private/DarkNewsDecay.cxx +++ b/projects/interactions/private/DarkNewsDecay.cxx @@ -68,17 +68,15 @@ double DarkNewsDecay::FinalStateProbability(dataclasses::InteractionRecord const else return dd/td; } -dataclasses::InteractionRecord DarkNewsDecay::SampleRecordFromDarkNews(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const { +void DarkNewsDecay::SampleRecordFromDarkNews(dataclasses::CrossSectionDistributionRecord & interaction, std::shared_ptr random) const { // Should be implemented on the python side // Not pure virtual in order to allow SampleFinalState to call throw(LI::utilities::PythonImplementationError("DarkNewsDecay::SampleRecordFromDarkNews should be implemented in Python!")); - return dataclasses::InteractionRecord(); } -void DarkNewsDecay::SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const { - interaction = SampleRecordFromDarkNews(interaction,random); +void DarkNewsDecay::SampleFinalState(dataclasses::CrossSectionDistributionRecord & interaction, std::shared_ptr random) const { + SampleRecordFromDarkNews(interaction, random); } - } // namespace interactions -} // namespace LI \ No newline at end of file +} // namespace LI diff --git a/projects/interactions/private/Decay.cxx b/projects/interactions/private/Decay.cxx index f96556671..198ee1191 100644 --- a/projects/interactions/private/Decay.cxx +++ b/projects/interactions/private/Decay.cxx @@ -22,13 +22,17 @@ bool Decay::operator==(Decay const & other) const { double Decay::TotalDecayLength(dataclasses::InteractionRecord const & interaction) const { double tau = 1./TotalDecayWidth(interaction); // in inverse GeV - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); + std::array const & p4 = interaction.primary_momentum; + double const & mass = interaction.primary_mass; + rk::P4 p1(geom3::Vector3(p4[1], p4[2], p4[3]), mass); return p1.beta() * p1.gamma() * tau * LI::utilities::Constants::hbarc; } double Decay::TotalDecayLengthForFinalState(dataclasses::InteractionRecord const & interaction) const { double tau = 1./TotalDecayWidthForFinalState(interaction); // in inverse GeV - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); + std::array const & p4 = interaction.primary_momentum; + double const & mass = interaction.primary_mass; + rk::P4 p1(geom3::Vector3(p4[1], p4[2], p4[3]), mass); return p1.beta() * p1.gamma() * tau * LI::utilities::Constants::hbarc; } diff --git a/projects/interactions/private/DipoleFromTable.cxx b/projects/interactions/private/DipoleFromTable.cxx index 5bfa98c59..2274bc18a 100644 --- a/projects/interactions/private/DipoleFromTable.cxx +++ b/projects/interactions/private/DipoleFromTable.cxx @@ -112,18 +112,12 @@ double DipoleFromTable::DipoleyMax(double Enu, double mHNL, double target_mass) double DipoleFromTable::TotalCrossSection(dataclasses::InteractionRecord const & interaction) const { - LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; - LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + LI::dataclasses::Particle::ParticleType const & primary_type = interaction.signature.primary_type; + LI::dataclasses::Particle::ParticleType const & target_type = interaction.signature.target_type; + std::array const & primary_momentum = interaction.primary_momentum; + double primary_mass = interaction.primary_mass; + rk::P4 p1(geom3::Vector3(primary_momentum[1], primary_momentum[2], primary_momentum[3]), primary_mass); + double const & primary_energy = primary_momentum[0]; // if we are below threshold, return 0 if(primary_energy < InteractionThreshold(interaction)) return 0; @@ -169,36 +163,33 @@ double DipoleFromTable::TotalCrossSection(LI::dataclasses::Particle::ParticleTyp double DipoleFromTable::DifferentialCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + std::array const & primary_momentum = interaction.primary_momentum; + double primary_mass = interaction.primary_mass; + double target_mass = interaction.primary_mass; + rk::P4 p1(geom3::Vector3(primary_momentum[1], primary_momentum[2], primary_momentum[3]), primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), target_mass); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } - assert(interaction.signature.secondary_types.size() == 2); - assert(interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or interaction.signature.secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuF4 or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar or interaction.signature.secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuF4Bar); - unsigned int lepton_index = (interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar) ? 0 : 1; + primary_energy = primary_momentum[0]; + p1_lab = p1; + p2_lab = p2; + std::vector const & secondary_types = interaction.signature.secondary_types; + assert(secondary_types.size() == 2); + assert(secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuF4 or secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar or secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuF4Bar); + unsigned int lepton_index = (secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar) ? 0 : 1; unsigned int other_index = 1 - lepton_index; - std::array const & mom3 = interaction.secondary_momenta[lepton_index]; - std::array const & mom4 = interaction.secondary_momenta[other_index]; - rk::P4 p3(geom3::Vector3(mom3[1], mom3[2], mom3[3]), interaction.secondary_masses[lepton_index]); - rk::P4 p4(geom3::Vector3(mom4[1], mom4[2], mom4[3]), interaction.secondary_masses[other_index]); + std::array const & mom3 = interaction.secondary_momenta.at(lepton_index); + std::array const & mom4 = interaction.secondary_momenta.at(other_index); + rk::P4 p3(geom3::Vector3(mom3[1], mom3[2], mom3[3]), interaction.secondary_masses.at(lepton_index)); + rk::P4 p4(geom3::Vector3(mom4[1], mom4[2], mom4[3]), interaction.secondary_masses.at(other_index)); double y = 1.0 - p2.dot(p3) / p2.dot(p1); double thresh = InteractionThreshold(interaction); - return DifferentialCrossSection(primary_type, primary_energy, target_type, interaction.target_mass, y, thresh); + return DifferentialCrossSection(primary_type, primary_energy, target_type, target_mass, y, thresh); } double DipoleFromTable::DifferentialCrossSection(LI::dataclasses::Particle::ParticleType primary_type, double primary_energy, LI::dataclasses::Particle::ParticleType target_type, double target_mass, double y) const { @@ -252,20 +243,24 @@ double DipoleFromTable::InteractionThreshold(dataclasses::InteractionRecord cons return hnl_mass + (hnl_mass*hnl_mass)/(2*interaction.target_mass); } -void DipoleFromTable::SampleFinalState(dataclasses::InteractionRecord& interaction, std::shared_ptr random) const { - LI::utilities::Interpolator2D const & diff_table = differential.at(interaction.signature.target_type); +void DipoleFromTable::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { + LI::utilities::Interpolator2D const & diff_table = differential.at(record.GetTargetType()); LI::utilities::Interpolator2D const & diff_table_proton = differential.at(LI::dataclasses::Particle::ParticleType::HNucleus); - int nprotons = LI::detector::MaterialModel::GetProtonCount(interaction.signature.target_type); + int nprotons = LI::detector::MaterialModel::GetProtonCount(record.GetTargetType()); // Avoid double counting for true H nuclei - if(!inelastic || interaction.signature.target_type==LI::dataclasses::Particle::ParticleType::HNucleus) { + if(!inelastic || record.signature.target_type == LI::dataclasses::Particle::ParticleType::HNucleus) { nprotons = 0; } // Uses Metropolis-Hastings Algorithm! // useful for cases where we don't know the supremum of our distribution, and the distribution is multi-dimensional - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + std::array const & primary_momentum = record.GetPrimaryMomentum(); + double primary_mass = record.GetPrimaryMass(); + double target_mass = record.GetTargetMass(); + + rk::P4 p1(geom3::Vector3(primary_momentum[1], primary_momentum[2], primary_momentum[3]), primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), target_mass); // we assume that: // the target is stationary so its energy is just its mass @@ -276,33 +271,28 @@ void DipoleFromTable::SampleFinalState(dataclasses::InteractionRecord& interacti double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p2_lab = p2; - primary_energy = p1_lab.e(); - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + p1_lab = p1; + p2_lab = p2; + primary_energy = p1_lab.e(); + + std::vector const & secondary_types = record.record.signature.secondary_types; - unsigned int lepton_index = (interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar) ? 0 : 1; + unsigned int lepton_index = (secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4 or secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuF4Bar) ? 0 : 1; unsigned int other_index = 1 - lepton_index; double m = hnl_mass; - double thresh = InteractionThreshold(interaction); + double thresh = InteractionThreshold(record.record); if(primary_energy < thresh) { throw(LI::utilities::InjectionFailure("Primary is below interaction threshold!")); } // double m2 = p2_lab | p2_lab; - double m2 = interaction.target_mass; + double m2 = target_mass; double m3 = m; double E1_lab = p1_lab.e(); double E2_lab = p2_lab.e(); - double yMin = DipoleyMin(E1_lab, GetHNLMass(), interaction.target_mass); - double yMax = DipoleyMax(E1_lab, GetHNLMass(), interaction.target_mass); + double yMin = DipoleyMin(E1_lab, GetHNLMass(), target_mass); + double yMax = DipoleyMax(E1_lab, GetHNLMass(), target_mass); assert(yMin > 0); double log_yMax = log10(yMax); double log_yMin = log10(yMin); @@ -415,9 +405,10 @@ void DipoleFromTable::SampleFinalState(dataclasses::InteractionRecord& interacti } double final_y = kin_vars[1] + 1e-16; // to account for machine epsilon when adding to O(1) numbers - interaction.interaction_parameters.resize(2); - interaction.interaction_parameters[0] = E1_lab; - interaction.interaction_parameters[1] = final_y; + std::map params; + params["energy"] = E1_lab; + params["bjorken_y"] = final_y; + record.SetInteractionParameters(params); geom3::UnitVector3 x_dir = geom3::UnitVector3::xAxis(); geom3::Vector3 p1_mom = p1_lab.momentum(); @@ -442,24 +433,8 @@ void DipoleFromTable::SampleFinalState(dataclasses::InteractionRecord& interacti rk::P4 p3; rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } - - interaction.secondary_momenta.resize(2); - interaction.secondary_masses.resize(2); - interaction.secondary_helicity.resize(2); - - interaction.secondary_momenta[lepton_index][0] = p3.e(); // p3_energy - interaction.secondary_momenta[lepton_index][1] = p3.px(); // p3_x - interaction.secondary_momenta[lepton_index][2] = p3.py(); // p3_y - interaction.secondary_momenta[lepton_index][3] = p3.pz(); // p3_z - interaction.secondary_masses[lepton_index] = p3.m(); + p3 = p3_lab; + p4 = p4_lab; double helicity_mul = 0.0; if(channel == Conserving) @@ -467,15 +442,21 @@ void DipoleFromTable::SampleFinalState(dataclasses::InteractionRecord& interacti else if(channel == Flipping) helicity_mul = -1.0; - interaction.secondary_helicity[lepton_index] = std::copysign(0.5, interaction.primary_helicity * helicity_mul); + std::vector & secondaries = record.GetSecondaryParticleRecords(); + + LI::dataclasses::SecondaryParticleRecord & lepton = secondaries[lepton_index]; + LI::dataclasses::SecondaryParticleRecord & other = secondaries[other_index]; + + assert(lepton.type == secondary_types[lepton_index]); + assert(other.type == secondary_types[other_index]); - interaction.secondary_momenta[other_index][0] = p4.e(); // p4_energy - interaction.secondary_momenta[other_index][1] = p4.px(); // p4_x - interaction.secondary_momenta[other_index][2] = p4.py(); // p4_y - interaction.secondary_momenta[other_index][3] = p4.pz(); // p4_z - interaction.secondary_masses[other_index] = p4.m(); + lepton.SetMass(p3.m()); + lepton.SetFourMomentum({p3.e(), p3.px(), p3.py(), p3.pz()}); + lepton.SetHelicity(std::copysign(0.5, record.GetPrimaryHelicity() * helicity_mul)); - interaction.secondary_helicity[other_index] = std::copysign(interaction.target_helicity, interaction.target_helicity * helicity_mul); + other.SetMass(p4.m()); + other.SetFourMomentum({p4.e(), p4.px(), p4.py(), p4.pz()}); + other.SetHelicity(std::copysign(0.5, record.GetPrimaryHelicity() * helicity_mul)); } double DipoleFromTable::FinalStateProbability(dataclasses::InteractionRecord const & interaction) const { diff --git a/projects/interactions/private/DummyCrossSection.cxx b/projects/interactions/private/DummyCrossSection.cxx index 3ea37c486..e1b91b90d 100644 --- a/projects/interactions/private/DummyCrossSection.cxx +++ b/projects/interactions/private/DummyCrossSection.cxx @@ -33,16 +33,7 @@ bool DummyCrossSection::equal(CrossSection const & other) const { double DummyCrossSection::TotalCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + double primary_energy = interaction.primary_momentum[0]; return TotalCrossSection(primary_type, primary_energy, target_type); } @@ -60,22 +51,7 @@ double DummyCrossSection::TotalCrossSection(LI::dataclasses::Particle::ParticleT double DummyCrossSection::DifferentialCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - rk::P4 p1_lab; - rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } - + double primary_energy = interaction.primary_momentum[0]; return TotalCrossSection(primary_type, primary_energy, target_type); } @@ -83,40 +59,32 @@ double DummyCrossSection::InteractionThreshold(dataclasses::InteractionRecord co return 0; } -void DummyCrossSection::SampleFinalState(dataclasses::InteractionRecord& interaction, std::shared_ptr random) const { - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); +void DummyCrossSection::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { + rk::P4 p1(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), record.target_mass); // we assume that: // the target is stationary so its energy is just its mass // the incoming neutrino is massless, so its kinetic energy is its total energy - // double s = target_mass_ * tinteraction.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; + // double s = target_mass_ * trecord.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; // double s = std::pow(rk::invMass(p1, p2), 2); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p2_lab = p2; - primary_energy = p1_lab.e(); - } else { - // Rest frame of p2 will be our "lab" frame - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + p1_lab = p1; + p2_lab = p2; + primary_energy = p1_lab.e(); double final_x = random->Uniform(0, 1); double final_y = random->Uniform(0, 1); - interaction.interaction_parameters.resize(3); - interaction.interaction_parameters[0] = primary_energy; - interaction.interaction_parameters[1] = final_x; - interaction.interaction_parameters[2] = final_y; + record.interaction_parameters.clear(); + record.interaction_parameters["energy"] = primary_energy; + record.interaction_parameters["bjorken_x"] = final_x; + record.interaction_parameters["bjorken_y"] = final_y; - double m1 = interaction.primary_mass; + double m1 = record.primary_mass; double m3 = 0; double E1_lab = p1_lab.e(); double E2_lab = p2_lab.e(); @@ -144,37 +112,23 @@ void DummyCrossSection::SampleFinalState(dataclasses::InteractionRecord& interac rk::P4 p3; rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } - - interaction.secondary_momenta.resize(2); - interaction.secondary_masses.resize(2); - interaction.secondary_helicity.resize(2); + p3 = p3_lab; + p4 = p4_lab; size_t lepton_index = 0; - size_t other_index = 0; - - interaction.secondary_momenta[lepton_index][0] = p3.e(); // p3_energy - interaction.secondary_momenta[lepton_index][1] = p3.px(); // p3_x - interaction.secondary_momenta[lepton_index][2] = p3.py(); // p3_y - interaction.secondary_momenta[lepton_index][3] = p3.pz(); // p3_z - interaction.secondary_masses[lepton_index] = p3.m(); + size_t other_index = 1; - interaction.secondary_helicity[lepton_index] = interaction.primary_helicity; + std::vector & secondaries = record.GetSecondaryParticleRecords(); + LI::dataclasses::SecondaryParticleRecord & lepton = secondaries[lepton_index]; + LI::dataclasses::SecondaryParticleRecord & other = secondaries[other_index]; - interaction.secondary_momenta[other_index][0] = p4.e(); // p4_energy - interaction.secondary_momenta[other_index][1] = p4.px(); // p4_x - interaction.secondary_momenta[other_index][2] = p4.py(); // p4_y - interaction.secondary_momenta[other_index][3] = p4.pz(); // p4_z - interaction.secondary_masses[other_index] = p4.m(); + lepton.SetFourMomentum({p3.e(), p3.px(), p3.py(), p3.pz()}); + lepton.SetMass(p3.m()); + lepton.SetHelicity(record.primary_helicity); - interaction.secondary_helicity[other_index] = interaction.target_helicity; + other.SetFourMomentum({p4.e(), p4.px(), p4.py(), p4.pz()}); + other.SetMass(p4.m()); + other.SetHelicity(record.target_helicity); } double DummyCrossSection::FinalStateProbability(dataclasses::InteractionRecord const & interaction) const { diff --git a/projects/interactions/private/ElasticScattering.cxx b/projects/interactions/private/ElasticScattering.cxx index 1bdf3f2d8..d84f3edf6 100644 --- a/projects/interactions/private/ElasticScattering.cxx +++ b/projects/interactions/private/ElasticScattering.cxx @@ -48,21 +48,9 @@ double ElasticScattering::DifferentialCrossSection(dataclasses::InteractionRecor throw std::runtime_error("Supplied primary not supported by cross section!"); } rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), interaction.target_mass); double s = std::pow(rk::invMass(p1, p2), 2); - double primary_energy; - rk::P4 p1_lab; - rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + double primary_energy = interaction.primary_momentum[0]; assert(interaction.signature.secondary_types.size() == 2); assert(interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuE or interaction.signature.secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuE or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuMu or interaction.signature.secondary_types[1] == LI::dataclasses::Particle::ParticleType::NuMu); unsigned int nu_index = (interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuE or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuMu) ? 0 : 1; @@ -110,15 +98,7 @@ double ElasticScattering::TotalCrossSection(dataclasses::InteractionRecord const LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; LI::dataclasses::Particle::ParticleType target_type = interaction.signature.target_type; rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + double primary_energy = interaction.primary_momentum[0]; // if we are below threshold, return 0 if(primary_energy < InteractionThreshold(interaction)) return 0; @@ -133,30 +113,23 @@ double ElasticScattering::TotalCrossSection(LI::dataclasses::Particle::ParticleT return LI::utilities::rombergIntegrate(integrand, 0, ymax); } -void ElasticScattering::SampleFinalState(dataclasses::InteractionRecord& interaction, std::shared_ptr random) const { +void ElasticScattering::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { // Uses Metropolis-Hastings Algorithm! // useful for cases where we don't know the supremum of our distribution, and the distribution is multi-dimensional - LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; + LI::dataclasses::Particle::ParticleType primary_type = record.signature.primary_type; - unsigned int nu_index = (interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuE or interaction.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuMu) ? 0 : 1; + unsigned int nu_index = (record.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuE or record.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::NuMu) ? 0 : 1; unsigned int electron_index = 1 - nu_index; - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p1(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), record.target_mass); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + primary_energy = record.primary_momentum[0]; + p1_lab = p1; + p2_lab = p2; double yMin = 1e-15; double yMax = 2*primary_energy / (2*primary_energy + LI::utilities::Constants::electronMass); @@ -203,8 +176,9 @@ void ElasticScattering::SampleFinalState(dataclasses::InteractionRecord& interac } double final_y = y + 1e-16; // to account for machine epsilon when adding to O(1) numbers - interaction.interaction_parameters.resize(1); - interaction.interaction_parameters[0] = final_y; + record.interaction_parameters.clear(); + record.interaction_parameters["energy"] = primary_energy; + record.interaction_parameters["bjorken_y"] = final_y; geom3::UnitVector3 x_dir = geom3::UnitVector3::xAxis(); geom3::Vector3 p1_mom = p1_lab.momentum(); @@ -229,37 +203,16 @@ void ElasticScattering::SampleFinalState(dataclasses::InteractionRecord& interac // doing something dumb, ignore outgoing neutrino rk::P4 p4_lab = p1_lab;//p2_lab + (p1_lab - p3_lab); - rk::P4 p3; - rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } - - interaction.secondary_momenta.resize(2); - interaction.secondary_masses.resize(2); - interaction.secondary_helicity.resize(2); - - interaction.secondary_momenta[electron_index][0] = p3.e(); // p3_energy - interaction.secondary_momenta[electron_index][1] = p3.px(); // p3_x - interaction.secondary_momenta[electron_index][2] = p3.py(); // p3_y - interaction.secondary_momenta[electron_index][3] = p3.pz(); // p3_z - interaction.secondary_masses[electron_index] = p3.m(); - - - interaction.secondary_helicity[electron_index] = interaction.target_helicity; + LI::dataclasses::SecondaryParticleRecord & electron = record.GetSecondaryParticleRecord(electron_index); + LI::dataclasses::SecondaryParticleRecord & neutrino = record.GetSecondaryParticleRecord(nu_index); - interaction.secondary_momenta[nu_index][0] = p4.e(); // p4_energy - interaction.secondary_momenta[nu_index][1] = p4.px(); // p4_x - interaction.secondary_momenta[nu_index][2] = p4.py(); // p4_y - interaction.secondary_momenta[nu_index][3] = p4.pz(); // p4_z - interaction.secondary_masses[nu_index] = p4.m(); + electron.SetFourMomentum({p3_lab.e(), p3_lab.px(), p3_lab.py(), p3_lab.pz()}); + electron.SetMass(p3_lab.m()); + electron.SetHelicity(record.target_helicity); - interaction.secondary_helicity[nu_index] = interaction.primary_helicity; + neutrino.SetFourMomentum({p4_lab.e(), p4_lab.px(), p4_lab.py(), p4_lab.pz()}); + neutrino.SetMass(p4_lab.m()); + neutrino.SetHelicity(record.primary_helicity); } std::vector ElasticScattering::GetPossibleTargets() const { diff --git a/projects/interactions/private/HNLDecay.cxx b/projects/interactions/private/HNLDecay.cxx index de8dd489e..81298d2e1 100644 --- a/projects/interactions/private/HNLDecay.cxx +++ b/projects/interactions/private/HNLDecay.cxx @@ -1,5 +1,7 @@ #include "LeptonInjector/interactions/HNLDecay.h" +#include + #include #include @@ -336,21 +338,21 @@ void HNLDecay::SampleFinalState(dataclasses::InteractionRecord & record, std::sh record.secondary_momenta.resize(2); record.secondary_masses.resize(2); - record.secondary_helicity.resize(2); + record.secondary_helicities.resize(2); record.secondary_momenta[gamma_index][0] = pGamma.e(); // pGamma_energy record.secondary_momenta[gamma_index][1] = pGamma.px(); // pGamma_x record.secondary_momenta[gamma_index][2] = pGamma.py(); // pGamma_y record.secondary_momenta[gamma_index][3] = pGamma.pz(); // pGamma_z record.secondary_masses[gamma_index] = pGamma.m(); - record.secondary_helicity[gamma_index] = 0; + record.secondary_helicities[gamma_index] = 0; record.secondary_momenta[nu_index][0] = pNu.e(); // pNu_energy record.secondary_momenta[nu_index][1] = pNu.px(); // pNu_x record.secondary_momenta[nu_index][2] = pNu.py(); // pNu_y record.secondary_momenta[nu_index][3] = pNu.pz(); // pNu_z record.secondary_masses[nu_index] = pNu.m(); - record.secondary_helicity[nu_index] = -1*record.primary_helicity; + record.secondary_helicities[nu_index] = -1*record.primary_helicity; } diff --git a/projects/interactions/private/HNLFromSpline.cxx b/projects/interactions/private/HNLFromSpline.cxx index ce12d3466..b38421d33 100644 --- a/projects/interactions/private/HNLFromSpline.cxx +++ b/projects/interactions/private/HNLFromSpline.cxx @@ -24,6 +24,7 @@ #include "LeptonInjector/dataclasses/InteractionRecord.h" // for Interactio... #include "LeptonInjector/dataclasses/Particle.h" // for Particle #include "LeptonInjector/utilities/Random.h" // for LI_random +#include "LeptonInjector/utilities/Constants.h" // for electronMass namespace LI { namespace interactions { @@ -137,6 +138,32 @@ void HNLFromSpline::LoadFromMemory(std::vector & differential_data, std::v total_cross_section_.read_fits_mem(total_data.data(), total_data.size()); } +double HNLFromSpline::GetLeptonMass(LI::dataclasses::Particle::ParticleType lepton_type) { + int32_t lepton_number = std::abs(static_cast(lepton_type)); + double lepton_mass; + switch(lepton_number) { + case 11: + lepton_mass = LI::utilities::Constants::electronMass; + break; + case 13: + lepton_mass = LI::utilities::Constants::muonMass; + break; + case 15: + lepton_mass = LI::utilities::Constants::tauMass; + break; + case 12: + lepton_mass = 0; + case 14: + lepton_mass = 0; + case 16: + lepton_mass = 0; + break; + default: + throw std::runtime_error("Unknown lepton type!"); + } + return lepton_mass; +} + void HNLFromSpline::ReadParamsFromSplineTable() { // returns true if successfully read target mass bool mass_good = differential_cross_section_.read_key("TARGETMASS", target_mass_); @@ -239,15 +266,8 @@ void HNLFromSpline::InitializeSignatures() { double HNLFromSpline::TotalCrossSection(dataclasses::InteractionRecord const & interaction) const { LI::dataclasses::Particle::ParticleType primary_type = interaction.signature.primary_type; rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); - double primary_energy; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - rk::P4 p1_lab = boost_start_to_lab * p1; - primary_energy = p1_lab.e(); - } + rk::P4 p2(geom3::Vector3(0, 0, 0), interaction.target_mass); + double primary_energy = interaction.primary_momentum[0]; // if we are below threshold, return 0 if(primary_energy < InteractionThreshold(interaction)) return 0; @@ -283,20 +303,13 @@ double HNLFromSpline::TotalCrossSection(LI::dataclasses::Particle::ParticleType double HNLFromSpline::DifferentialCrossSection(dataclasses::InteractionRecord const & interaction) const { rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), interaction.target_mass); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - primary_energy = interaction.primary_momentum[0]; - p1_lab = p1; - p2_lab = p2; - } else { - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + primary_energy = interaction.primary_momentum[0]; + p1_lab = p1; + p2_lab = p2; assert(interaction.signature.secondary_types.size() == 2); unsigned int lepton_index = (isLepton(interaction.signature.secondary_types[0])) ? 0 : 1; unsigned int other_index = 1 - lepton_index; @@ -311,7 +324,7 @@ double HNLFromSpline::DifferentialCrossSection(dataclasses::InteractionRecord co double Q2 = -q.dot(q); double y = 1.0 - p2.dot(p3) / p2.dot(p1); double x = Q2 / (2.0 * p2.dot(q)); - double lepton_mass = particleMass(interaction.signature.secondary_types[lepton_index]); + double lepton_mass = GetLeptonMass(interaction.signature.secondary_types[lepton_index]); return DifferentialCrossSection(primary_energy, x, y, lepton_mass); } @@ -353,42 +366,34 @@ double HNLFromSpline::InteractionThreshold(dataclasses::InteractionRecord const return 0; } -void HNLFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction, std::shared_ptr random) const { +void HNLFromSpline::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { // Uses Metropolis-Hastings Algorithm! // useful for cases where we don't know the supremum of our distribution, and the distribution is multi-dimensional if (differential_cross_section_.get_ndim() != 3) { throw std::runtime_error("I expected 3 dimensions in the cross section spline, but got " + std::to_string(differential_cross_section_.get_ndim()) +". Maybe your fits file doesn't have the right 'INTERACTION' key?"); } - rk::P4 p1(geom3::Vector3(interaction.primary_momentum[1], interaction.primary_momentum[2], interaction.primary_momentum[3]), interaction.primary_mass); - rk::P4 p2(geom3::Vector3(interaction.target_momentum[1], interaction.target_momentum[2], interaction.target_momentum[3]), interaction.target_mass); + rk::P4 p1(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); + rk::P4 p2(geom3::Vector3(0, 0, 0), record.target_mass); // we assume that: // the target is stationary so its energy is just its mass // the incoming neutrino is massless, so its kinetic energy is its total energy - // double s = target_mass_ * tinteraction.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; + // double s = target_mass_ * trecord.secondary_momentarget_mass_ + 2 * target_mass_ * primary_energy; // double s = std::pow(rk::invMass(p1, p2), 2); double primary_energy; rk::P4 p1_lab; rk::P4 p2_lab; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p1_lab = p1; - p2_lab = p2; - primary_energy = p1_lab.e(); - } else { - // Rest frame of p2 will be our "lab" frame - rk::Boost boost_start_to_lab = p2.restBoost(); - p1_lab = boost_start_to_lab * p1; - p2_lab = boost_start_to_lab * p2; - primary_energy = p1_lab.e(); - } + p1_lab = p1; + p2_lab = p2; + primary_energy = p1_lab.e(); - unsigned int lepton_index = (isLepton(interaction.signature.secondary_types[0])) ? 0 : 1; + unsigned int lepton_index = (isLepton(record.signature.secondary_types[0])) ? 0 : 1; unsigned int other_index = 1 - lepton_index; - double m = particleMass(interaction.signature.secondary_types[lepton_index]); + double m = GetLeptonMass(record.signature.secondary_types[lepton_index]); - double m1 = interaction.primary_mass; + double m1 = record.primary_mass; double m3 = m; double E1_lab = p1_lab.e(); double E2_lab = p2_lab.e(); @@ -505,10 +510,10 @@ void HNLFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction double final_x = pow(10., kin_vars[1]); double final_y = pow(10., kin_vars[2]); - interaction.interaction_parameters.resize(3); - interaction.interaction_parameters[0] = E1_lab; - interaction.interaction_parameters[1] = final_x; - interaction.interaction_parameters[2] = final_y; + record.interaction_parameters.clear(); + record.interaction_parameters["energy"] = E1_lab; + record.interaction_parameters["bjorken_x"] = final_x; + record.interaction_parameters["bjorken_y"] = final_y; double Q2 = 2 * E1_lab * E2_lab * pow(10.0, kin_vars[1] + kin_vars[2]); double p1x_lab = std::sqrt(p1_lab.px() * p1_lab.px() + p1_lab.py() * p1_lab.py() + p1_lab.pz() * p1_lab.pz()); @@ -534,34 +539,21 @@ void HNLFromSpline::SampleFinalState(dataclasses::InteractionRecord& interaction rk::P4 p3; rk::P4 p4; - if(interaction.target_momentum[1] == 0 and interaction.target_momentum[2] == 0 and interaction.target_momentum[3] == 0) { - p3 = p3_lab; - p4 = p4_lab; - } else { - rk::Boost boost_lab_to_start = p2.labBoost(); - p3 = boost_lab_to_start * p3_lab; - p4 = boost_lab_to_start * p4_lab; - } - - interaction.secondary_momenta.resize(2); - interaction.secondary_masses.resize(2); - interaction.secondary_helicity.resize(2); + p3 = p3_lab; + p4 = p4_lab; - interaction.secondary_momenta[lepton_index][0] = p3.e(); // p3_energy - interaction.secondary_momenta[lepton_index][1] = p3.px(); // p3_x - interaction.secondary_momenta[lepton_index][2] = p3.py(); // p3_y - interaction.secondary_momenta[lepton_index][3] = p3.pz(); // p3_z - interaction.secondary_masses[lepton_index] = p3.m(); + std::vector & secondaries = record.GetSecondaryParticleRecords(); + LI::dataclasses::SecondaryParticleRecord & lepton = secondaries[lepton_index]; + LI::dataclasses::SecondaryParticleRecord & other = secondaries[other_index]; - interaction.secondary_helicity[lepton_index] = interaction.primary_helicity; - interaction.secondary_momenta[other_index][0] = p4.e(); // p4_energy - interaction.secondary_momenta[other_index][1] = p4.px(); // p4_x - interaction.secondary_momenta[other_index][2] = p4.py(); // p4_y - interaction.secondary_momenta[other_index][3] = p4.pz(); // p4_z - interaction.secondary_masses[other_index] = p4.m(); + lepton.SetFourMomentum({p3.e(), p3.px(), p3.py(), p3.pz()}); + lepton.SetMass(p3.m()); + lepton.SetHelicity(record.primary_helicity); - interaction.secondary_helicity[other_index] = interaction.target_helicity; + other.SetFourMomentum({p4.e(), p4.px(), p4.py(), p4.pz()}); + other.SetMass(p4.m()); + other.SetHelicity(record.target_helicity); } double HNLFromSpline::FinalStateProbability(dataclasses::InteractionRecord const & interaction) const { diff --git a/projects/interactions/private/NeutrissimoDecay.cxx b/projects/interactions/private/NeutrissimoDecay.cxx index 119b03fd7..d521d7ef5 100644 --- a/projects/interactions/private/NeutrissimoDecay.cxx +++ b/projects/interactions/private/NeutrissimoDecay.cxx @@ -50,18 +50,19 @@ double NeutrissimoDecay::TotalDecayWidth(LI::dataclasses::Particle::ParticleType } double NeutrissimoDecay::TotalDecayWidthForFinalState(dataclasses::InteractionRecord const & record) const { - unsigned int gamma_index = (record.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; + LI::dataclasses::InteractionSignature const & signature = record.signature; + unsigned int gamma_index = (signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; unsigned int nu_index = 1 - gamma_index; double dipole_coupling_sq = 0; - if(record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuE || - record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuEBar) - dipole_coupling_sq = dipole_coupling[0]*dipole_coupling[0]; - else if(record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuMu || - record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuMuBar) - dipole_coupling_sq = dipole_coupling[1]*dipole_coupling[1]; - else if(record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuTau || - record.signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuTauBar) - dipole_coupling_sq = dipole_coupling[2]*dipole_coupling[2]; + if(signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuE || + signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuEBar) + dipole_coupling_sq = dipole_coupling[0]*dipole_coupling[0]; + else if(signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuMu || + signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuMuBar) + dipole_coupling_sq = dipole_coupling[1]*dipole_coupling[1]; + else if(signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuTau || + signature.secondary_types[nu_index]==LI::dataclasses::Particle::ParticleType::NuTauBar) + dipole_coupling_sq = dipole_coupling[2]*dipole_coupling[2]; return dipole_coupling_sq * std::pow(hnl_mass,3) / (4*LI::utilities::Constants::pi) * LI::utilities::Constants::GeV; } @@ -73,8 +74,8 @@ std::vector NeutrissimoDecay::DensityVariables() const { std::vector NeutrissimoDecay::GetPossibleSignatures() const { std::vector signatures; for(auto primary : primary_types) { - std::vector new_signatures = GetPossibleSignaturesFromParent(primary); - signatures.insert(signatures.end(),new_signatures.begin(),new_signatures.end()); + std::vector new_signatures = GetPossibleSignaturesFromParent(primary); + signatures.insert(signatures.end(),new_signatures.begin(),new_signatures.end()); } return signatures; } @@ -107,40 +108,47 @@ double NeutrissimoDecay::DifferentialDecayWidth(dataclasses::InteractionRecord c //TODO: make sure factor of 2 is correct here return DecayWidth/2.; } + + LI::dataclasses::InteractionSignature const & signature = record.signature; + LI::math::Vector3D hnl_dir = LI::math::Vector3D(record.primary_momentum[0], record.primary_momentum[1], record.primary_momentum[2]); hnl_dir.normalize(); - unsigned int gamma_index = (record.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; + unsigned int gamma_index = (signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; + std::array const & gamma_momentum = record.secondary_momenta[gamma_index]; rk::P4 pHNL(geom3::Vector3(record.primary_momentum[1], record.primary_momentum[2], record.primary_momentum[3]), record.primary_mass); - rk::P4 pGamma(geom3::Vector3(record.secondary_momenta[gamma_index][1], record.secondary_momenta[gamma_index][2], record.secondary_momenta[gamma_index][3]), record.secondary_masses[gamma_index]); + rk::P4 pGamma(geom3::Vector3(gamma_momentum[1], gamma_momentum[2], gamma_momentum[3]), record.secondary_masses[gamma_index]); rk::Boost boost_to_HNL_rest = pHNL.restBoost(); rk::P4 pGamma_HNLrest = pGamma.boost(boost_to_HNL_rest); - + LI::math::Vector3D gamma_dir = LI::math::Vector3D(pGamma_HNLrest.px(), pGamma_HNLrest.py(), pGamma_HNLrest.pz()); gamma_dir.normalize(); double CosThetaGamma = gamma_dir*hnl_dir; // scalar product - double alpha = std::copysign(1.0,record.primary_helicity); // 1 for RH, -1 for LH - alpha = (record.signature.primary_type == LI::dataclasses::Particle::ParticleType::NuF4) ? -1*alpha : alpha; + double alpha = std::copysign(1.0, record.primary_helicity); // 1 for RH, -1 for LH + alpha = (signature.primary_type == LI::dataclasses::Particle::ParticleType::NuF4) ? -1*alpha : alpha; return DecayWidth/2. * (1 + alpha*CosThetaGamma); } -void NeutrissimoDecay::SampleFinalState(dataclasses::InteractionRecord & record, std::shared_ptr random) const { - - unsigned int gamma_index = (record.signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; +void NeutrissimoDecay::SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const { + + LI::dataclasses::InteractionSignature const & signature = record.GetSignature(); + + unsigned int gamma_index = (signature.secondary_types[0] == LI::dataclasses::Particle::ParticleType::Gamma) ? 0 : 1; unsigned int nu_index = 1 - gamma_index; double CosTheta; - double alpha = std::copysign(1.0,record.primary_helicity); // 1 for RH, -1 for LH - alpha = (record.signature.primary_type == LI::dataclasses::Particle::ParticleType::NuF4) ? -1*alpha : alpha; - if(nature==ChiralNature::Majorana) { - CosTheta = random->Uniform(-1,1); + double alpha = std::copysign(1.0,record.GetPrimaryHelicity()); // 1 for RH, -1 for LH + alpha = (signature.primary_type == LI::dataclasses::Particle::ParticleType::NuF4) ? -1*alpha : alpha; + + if(nature == ChiralNature::Majorana) { + CosTheta = random->Uniform(-1,1); } else { - double X = random->Uniform(0,1); - CosTheta = (std::sqrt(1 - 2*alpha*(1 - alpha/2. - 2*X)) - 1)/alpha; + double X = random->Uniform(0,1); + CosTheta = (std::sqrt(1 - 2*alpha*(1 - alpha/2. - 2*X)) - 1)/alpha; } double SinTheta = std::sin(std::acos(CosTheta)); @@ -151,7 +159,7 @@ void NeutrissimoDecay::SampleFinalState(dataclasses::InteractionRecord & record, geom3::Vector3 pHNL_mom = pHNL.momentum(); geom3::UnitVector3 pHNL_dir = pHNL_mom.direction(); geom3::Rotation3 x_to_pHNL_rot = geom3::rotationBetween(x_dir, pHNL_dir); - + double phi = random->Uniform(0, 2.0 * M_PI); geom3::Rotation3 rand_rot(pHNL_dir, phi); @@ -162,24 +170,25 @@ void NeutrissimoDecay::SampleFinalState(dataclasses::InteractionRecord & record, rk::P4 pGamma = pGamma_HNLrest.boost(boost_to_lab); rk::P4 pNu(pHNL.momentum() - pGamma.momentum(),0); // ensures the neutrino has zero mass, avoids rounding errors - record.secondary_momenta.resize(2); - record.secondary_masses.resize(2); - record.secondary_helicity.resize(2); - - record.secondary_momenta[gamma_index][0] = pGamma.e(); // pGamma_energy - record.secondary_momenta[gamma_index][1] = pGamma.px(); // pGamma_x - record.secondary_momenta[gamma_index][2] = pGamma.py(); // pGamma_y - record.secondary_momenta[gamma_index][3] = pGamma.pz(); // pGamma_z - record.secondary_masses[gamma_index] = pGamma.m(); - record.secondary_helicity[gamma_index] = 0; - - record.secondary_momenta[nu_index][0] = pNu.e(); // pNu_energy - record.secondary_momenta[nu_index][1] = pNu.px(); // pNu_x - record.secondary_momenta[nu_index][2] = pNu.py(); // pNu_y - record.secondary_momenta[nu_index][3] = pNu.pz(); // pNu_z - record.secondary_masses[nu_index] = pNu.m(); - record.secondary_helicity[nu_index] = -1*record.primary_helicity; + LI::dataclasses::SecondaryParticleRecord & gamma = record.GetSecondaryParticleRecord(gamma_index); + LI::dataclasses::SecondaryParticleRecord & nu = record.GetSecondaryParticleRecord(nu_index); + + assert(gamma.type == LI::dataclasses::Particle::ParticleType::Gamma); + assert(nu.type == LI::dataclasses::Particle::ParticleType::NuE || + nu.type == LI::dataclasses::Particle::ParticleType::NuMu || + nu.type == LI::dataclasses::Particle::ParticleType::NuTau || + nu.type == LI::dataclasses::Particle::ParticleType::NuEBar || + nu.type == LI::dataclasses::Particle::ParticleType::NuMuBar || + nu.type == LI::dataclasses::Particle::ParticleType::NuTauBar); + + gamma.SetFourMomentum({pGamma.e(), pGamma.px(), pGamma.py(), pGamma.pz()}); + gamma.SetMass(pGamma.m()); + gamma.SetHelicity(std::copysign(1.0, record.primary_helicity)); + + nu.SetFourMomentum({pNu.e(), pNu.px(), pNu.py(), pNu.pz()}); + nu.SetMass(pNu.m()); + nu.SetHelicity(-1*record.primary_helicity); } double NeutrissimoDecay::FinalStateProbability(dataclasses::InteractionRecord const & record) const { diff --git a/projects/interactions/private/pybindings/CrossSection.h b/projects/interactions/private/pybindings/CrossSection.h index 6ecb9904d..f7b583afc 100644 --- a/projects/interactions/private/pybindings/CrossSection.h +++ b/projects/interactions/private/pybindings/CrossSection.h @@ -38,14 +38,12 @@ class PyCrossSection : public LI::interactions::CrossSection { ); } - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override { - PYBIND11_OVERRIDE_PURE( + double TotalCrossSectionAllFinalStates(LI::dataclasses::InteractionRecord const & record) const override { + PYBIND11_OVERRIDE( double, CrossSection, - TotalCrossSection, - primary, - energy, - target + TotalCrossSectionAllFinalStates, + record ); } @@ -67,7 +65,7 @@ class PyCrossSection : public LI::interactions::CrossSection { ); } - void SampleFinalState(LI::dataclasses::InteractionRecord & record, std::shared_ptr rand) const override { + void SampleFinalState(LI::dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr rand) const override { PYBIND11_OVERRIDE_PURE( void, CrossSection, @@ -150,7 +148,7 @@ void register_CrossSection(pybind11::module_ & m) { .def("TotalCrossSection", (double (CrossSection::*)(LI::dataclasses::Particle::ParticleType, double, LI::dataclasses::Particle::ParticleType) const)(&CrossSection::TotalCrossSection)) .def("DifferentialCrossSection", &CrossSection::DifferentialCrossSection) .def("InteractionThreshold", &CrossSection::InteractionThreshold) - .def("SampleFinalState", &CrossSection::SampleFinalState) + .def("SampleFinalState", (void (CrossSection::*)(LI::dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const)(&CrossSection::SampleFinalState)) .def("GetPossibleTargets", &CrossSection::GetPossibleTargets) .def("GetPossibleTargetsFromPrimary", &CrossSection::GetPossibleTargetsFromPrimary) .def("GetPossiblePrimaries", &CrossSection::GetPossiblePrimaries) diff --git a/projects/interactions/private/pybindings/DISFromSpline.h b/projects/interactions/private/pybindings/DISFromSpline.h index 01ca7990d..362cc6314 100644 --- a/projects/interactions/private/pybindings/DISFromSpline.h +++ b/projects/interactions/private/pybindings/DISFromSpline.h @@ -74,7 +74,6 @@ void register_DISFromSpline(pybind11::module_ & m) { .def(self == self) .def("TotalCrossSection",overload_cast(&DISFromSpline::TotalCrossSection, const_)) .def("TotalCrossSection",overload_cast(&DISFromSpline::TotalCrossSection, const_)) - .def("TotalCrossSection",overload_cast(&DISFromSpline::TotalCrossSection, const_)) .def("DifferentialCrossSection",overload_cast(&DISFromSpline::DifferentialCrossSection, const_)) .def("DifferentialCrossSection",overload_cast(&DISFromSpline::DifferentialCrossSection, const_)) .def("InteractionThreshold",&DISFromSpline::InteractionThreshold) diff --git a/projects/interactions/private/pybindings/DarkNewsCrossSection.h b/projects/interactions/private/pybindings/DarkNewsCrossSection.h index 8d8e35db6..e0b91e88c 100644 --- a/projects/interactions/private/pybindings/DarkNewsCrossSection.h +++ b/projects/interactions/private/pybindings/DarkNewsCrossSection.h @@ -86,16 +86,14 @@ class pyCrossSection : public CrossSection { ) } - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override { + double TotalCrossSectionAllFinalStates(LI::dataclasses::InteractionRecord const & record) const override { C_PYBIND11_OVERRIDE_PURE( self, CrossSection, double, - TotalCrossSection, - "TotalCrossSection", - primary, - energy, - target + TotalCrossSectionAllFinalStates, + "TotalCrossSectionAllFinalStates", + record ) } @@ -121,14 +119,14 @@ class pyCrossSection : public CrossSection { ) } - void SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const override { + void SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const override { C_PYBIND11_OVERRIDE_PURE( self, CrossSection, void, SampleFinalState, "SampleFinalState", - interaction, + record, random ) } @@ -215,7 +213,7 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, TotalCrossSection, "TotalCrossSection", - interaction + std::cref(interaction) ) } @@ -239,7 +237,7 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, DifferentialCrossSection, "DifferentialCrossSection", - interaction + std::cref(interaction) ) } @@ -264,7 +262,7 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, InteractionThreshold, "InteractionThreshold", - interaction + std::cref(interaction) ) } @@ -275,7 +273,7 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, Q2Min, "Q2Min", - interaction + std::cref(interaction) ) } @@ -286,40 +284,51 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, Q2Max, "Q2Max", - interaction + std::cref(interaction) ) } - void SetUpscatteringMasses(dataclasses::InteractionRecord & interaction) const override { + double TargetMass(dataclasses::ParticleType const & target_type) const override { C_PYBIND11_OVERRIDE( self, DarkNewsCrossSection, - void, - SetUpscatteringMasses, - "SetUpscatteringMasses", - interaction + double, + TargetMass, + "TargetMass", + std::cref(target_type) ) } - void SetUpscatteringHelicities(dataclasses::InteractionRecord & interaction) const override { + std::vector SecondaryMasses(std::vector const & secondary_types) const override { C_PYBIND11_OVERRIDE( self, DarkNewsCrossSection, - void, - SetUpscatteringHelicities, - "SetUpscatteringHelicities", - interaction + std::vector, + SecondaryMasses, + "SecondaryMasses", + std::cref(secondary_types) + ) + } + + std::vector SecondaryHelicities(dataclasses::InteractionRecord const & record) const override{ + C_PYBIND11_OVERRIDE( + self, + DarkNewsCrossSection, + std::vector, + SecondaryHelicities, + "SecondaryHelicities", + std::cref(record) ) } - void SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const override { + void SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const override { C_PYBIND11_OVERRIDE( self, DarkNewsCrossSection, void, SampleFinalState, "SampleFinalState", - interaction, + std::ref(record), random ) } @@ -384,7 +393,7 @@ class pyDarkNewsCrossSection : public DarkNewsCrossSection { double, FinalStateProbability, "FinalStateProbability", - record + std::cref(record) ) } @@ -415,8 +424,9 @@ void register_DarkNewsCrossSection(pybind11::module_ & m) { .def("InteractionThreshold",&DarkNewsCrossSection::InteractionThreshold) .def("Q2Min",&DarkNewsCrossSection::Q2Min) .def("Q2Max",&DarkNewsCrossSection::Q2Max) - .def("SetUpscatteringMasses",&DarkNewsCrossSection::SetUpscatteringMasses) - .def("SetUpscatteringHelicities",&DarkNewsCrossSection::SetUpscatteringHelicities) + .def("TargetMass",&DarkNewsCrossSection::TargetMass) + .def("SecondaryMasses",&DarkNewsCrossSection::SecondaryMasses) + .def("SecondaryHelicities",&DarkNewsCrossSection::SecondaryHelicities) .def("GetPossibleTargets",&DarkNewsCrossSection::GetPossibleTargets) .def("GetPossibleTargetsFromPrimary",&DarkNewsCrossSection::GetPossibleTargetsFromPrimary) .def("GetPossiblePrimaries",&DarkNewsCrossSection::GetPossiblePrimaries) @@ -469,8 +479,9 @@ void register_DarkNewsCrossSection(pybind11::module_ & m) { .def("InteractionThreshold",&DarkNewsCrossSection::InteractionThreshold) .def("Q2Min",&DarkNewsCrossSection::Q2Min) .def("Q2Max",&DarkNewsCrossSection::Q2Max) - .def("SetUpscatteringMasses",&DarkNewsCrossSection::SetUpscatteringMasses) - .def("SetUpscatteringHelicities",&DarkNewsCrossSection::SetUpscatteringHelicities) + .def("TargetMass",&DarkNewsCrossSection::TargetMass) + .def("SecondaryMasses",&DarkNewsCrossSection::SecondaryMasses) + .def("SecondaryHelicities",&DarkNewsCrossSection::SecondaryHelicities) .def("GetPossibleTargets",&DarkNewsCrossSection::GetPossibleTargets) .def("GetPossibleTargetsFromPrimary",&DarkNewsCrossSection::GetPossibleTargetsFromPrimary) .def("GetPossiblePrimaries",&DarkNewsCrossSection::GetPossiblePrimaries) diff --git a/projects/interactions/private/pybindings/DarkNewsDecay.h b/projects/interactions/private/pybindings/DarkNewsDecay.h index 87981a830..b8a19e457 100644 --- a/projects/interactions/private/pybindings/DarkNewsDecay.h +++ b/projects/interactions/private/pybindings/DarkNewsDecay.h @@ -141,14 +141,14 @@ class pyDecay : public Decay { ) } - void SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const override { + void SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const override { C_PYBIND11_OVERRIDE_PURE( self, Decay, void, SampleFinalState, "SampleFinalState", - interaction, + record, random ) } @@ -213,7 +213,7 @@ class pyDarkNewsDecay : public DarkNewsDecay { double, TotalDecayWidth, "TotalDecayWidth", - interaction + std::cref(interaction) ) } @@ -224,7 +224,7 @@ class pyDarkNewsDecay : public DarkNewsDecay { double, TotalDecayWidthForFinalState, "TotalDecayWidthForFinalState", - interaction + std::cref(interaction) ) } @@ -246,30 +246,30 @@ class pyDarkNewsDecay : public DarkNewsDecay { double, DifferentialDecayWidth, "DifferentialDecayWidth", - interaction + std::cref(interaction) ) } - dataclasses::InteractionRecord SampleRecordFromDarkNews(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const override { + void SampleRecordFromDarkNews(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const override { C_PYBIND11_OVERRIDE( self, DarkNewsDecay, - dataclasses::InteractionRecord, + void, SampleRecordFromDarkNews, "SampleRecordFromDarkNews", - interaction, + std::ref(record), random ) } - void SampleFinalState(dataclasses::InteractionRecord & interaction, std::shared_ptr random) const override { + void SampleFinalState(dataclasses::CrossSectionDistributionRecord & record, std::shared_ptr random) const override { C_PYBIND11_OVERRIDE( self, DarkNewsDecay, void, SampleFinalState, "SampleFinalState", - interaction, + std::ref(record), random ) } @@ -312,7 +312,7 @@ class pyDarkNewsDecay : public DarkNewsDecay { double, FinalStateProbability, "FinalStateProbability", - record + std::cref(record) ) } @@ -416,4 +416,4 @@ void register_DarkNewsDecay(pybind11::module_ & m) { }) ) ; -} \ No newline at end of file +} diff --git a/projects/interactions/private/test/DISFromSpline_TEST.cxx b/projects/interactions/private/test/DISFromSpline_TEST.cxx index 1f9b085b5..c6964aca8 100644 --- a/projects/interactions/private/test/DISFromSpline_TEST.cxx +++ b/projects/interactions/private/test/DISFromSpline_TEST.cxx @@ -40,7 +40,6 @@ TEST(DISFromSpline, Constructor) event.primary_momentum[0] = energy; // 10TeV double target_mass = dis_xs->GetTargetMass(); event.target_mass = target_mass; - event.target_momentum[0] = target_mass; std::shared_ptr rand = std::make_shared(); @@ -54,7 +53,9 @@ TEST(DISFromSpline, Constructor) event.primary_momentum[2] = y * energy; event.primary_momentum[3] = z * energy; - xs->SampleFinalState(event, rand); + LI::dataclasses::CrossSectionDistributionRecord xsec_record(event); + xs->SampleFinalState(xsec_record, rand); + xsec_record.Finalize(event); cereal::JSONOutputArchive output(std::cout); //output(xs); output(event); diff --git a/projects/interactions/private/test/DipoleFromTable_TEST.cxx b/projects/interactions/private/test/DipoleFromTable_TEST.cxx index fe2595357..c29fb4b60 100644 --- a/projects/interactions/private/test/DipoleFromTable_TEST.cxx +++ b/projects/interactions/private/test/DipoleFromTable_TEST.cxx @@ -53,7 +53,6 @@ TEST(DipoleFromTable, Constructor) double carbon_mass = 12000000.0; double target_mass = carbon_mass * 0.9314941 * 1e-6; event.target_mass = target_mass; - event.target_momentum[0] = target_mass; event.target_mass = target_mass; std::shared_ptr rand = std::make_shared(); @@ -78,7 +77,9 @@ TEST(DipoleFromTable, Constructor) unsigned int total_events = 10000; output(cereal::make_size_tag(static_cast(total_events))); for(unsigned int i=0; iSampleFinalState(event, rand); + LI::dataclasses::CrossSectionDistributionRecord xsec_record(event); + xs->SampleFinalState(xsec_record, rand); + xsec_record.Finalize(event); //std::cerr << event << std::endl; output(event); } diff --git a/projects/interactions/private/test/ElasticScattering_TEST.cxx b/projects/interactions/private/test/ElasticScattering_TEST.cxx index c623c22a2..645c6f208 100644 --- a/projects/interactions/private/test/ElasticScattering_TEST.cxx +++ b/projects/interactions/private/test/ElasticScattering_TEST.cxx @@ -107,9 +107,6 @@ TEST(ElasticScattering, Generation) // Choose injection direction std::shared_ptr ddist = std::make_shared(Vector3D{0.0, 0.0, 1.0}); - // Targets should be stationary - std::shared_ptr target_momentum_distribution = std::make_shared(); - // Let us inject according to column depth std::shared_ptr depth_func = std::make_shared(); @@ -117,13 +114,12 @@ TEST(ElasticScattering, Generation) std::shared_ptr helicity_distribution = std::make_shared(); // Put it all together! - std::shared_ptr injector = std::make_shared(events_to_inject, primary_injector, cross_sections, detector_model, random, edist, ddist, target_momentum_distribution, depth_func, disk_radius, endcap_length, helicity_distribution); + std::shared_ptr injector = std::make_shared(events_to_inject, primary_injector, cross_sections, detector_model, random, edist, ddist, depth_func, disk_radius, endcap_length, helicity_distribution); std::vector> physical_distributions = { std::shared_ptr(tab_pdf), std::shared_ptr(flux_units), std::shared_ptr(ddist), - std::shared_ptr(target_momentum_distribution), std::shared_ptr(helicity_distribution) }; @@ -181,11 +177,6 @@ TEST(ElasticScattering, Generation) myFile << event.primary_helicity << " "; - myFile << event.target_momentum[0] << " "; - myFile << event.target_momentum[1] << " "; - myFile << event.target_momentum[2] << " "; - myFile << event.target_momentum[3] << " "; - myFile << event.target_helicity << " "; myFile << event.secondary_momenta[0][0] << " "; @@ -193,14 +184,14 @@ TEST(ElasticScattering, Generation) myFile << event.secondary_momenta[0][2] << " "; myFile << event.secondary_momenta[0][3] << " "; - myFile << event.secondary_helicity[0] << " "; + myFile << event.secondary_helicities[0] << " "; myFile << event.secondary_momenta[1][0] << " "; myFile << event.secondary_momenta[1][1] << " "; myFile << event.secondary_momenta[1][2] << " "; myFile << event.secondary_momenta[1][3] << " "; - myFile << event.secondary_helicity[1] << " "; + myFile << event.secondary_helicities[1] << " "; myFile << simplified_weight << " "; myFile << interaction_prob << " "; diff --git a/projects/interactions/public/LeptonInjector/interactions/CrossSection.h b/projects/interactions/public/LeptonInjector/interactions/CrossSection.h index 6a1ea388e..90c1d71dd 100644 --- a/projects/interactions/public/LeptonInjector/interactions/CrossSection.h +++ b/projects/interactions/public/LeptonInjector/interactions/CrossSection.h @@ -16,7 +16,8 @@ #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -26,16 +27,17 @@ namespace interactions { class CrossSection { friend cereal::access; private: + void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const; public: CrossSection(); virtual ~CrossSection() {}; bool operator==(CrossSection const & other) const; virtual bool equal(CrossSection const & other) const = 0; virtual double TotalCrossSection(dataclasses::InteractionRecord const &) const = 0; - virtual double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const = 0; + virtual double TotalCrossSectionAllFinalStates(dataclasses::InteractionRecord const &) const; virtual double DifferentialCrossSection(dataclasses::InteractionRecord const &) const = 0; virtual double InteractionThreshold(dataclasses::InteractionRecord const &) const = 0; - virtual void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const = 0; + virtual void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const = 0; virtual std::vector GetPossibleTargets() const = 0; virtual std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const = 0; diff --git a/projects/interactions/public/LeptonInjector/interactions/DISFromSpline.h b/projects/interactions/public/LeptonInjector/interactions/DISFromSpline.h index 9d0995601..b5bc14cdf 100644 --- a/projects/interactions/public/LeptonInjector/interactions/DISFromSpline.h +++ b/projects/interactions/public/LeptonInjector/interactions/DISFromSpline.h @@ -28,7 +28,7 @@ #include "LeptonInjector/dataclasses/InteractionSignature.h" // for Interac... #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace utilities { class LI_random; } } namespace LI { @@ -67,11 +67,10 @@ friend cereal::access; double TotalCrossSection(dataclasses::InteractionRecord const &) const override; double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy) const; - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; double DifferentialCrossSection(double energy, double x, double y, double secondary_lepton_mass, double Q2=std::numeric_limits::quiet_NaN()) const; double InteractionThreshold(dataclasses::InteractionRecord const &) const override; - void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr random) const override; + void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr random) const override; std::vector GetPossibleTargets() const override; std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override; @@ -88,6 +87,8 @@ friend cereal::access; double GetTargetMass() const {return target_mass_;}; int GetInteractionType() const {return interaction_type_;}; + static double GetLeptonMass(LI::dataclasses::Particle::ParticleType lepton_type); + public: virtual std::vector DensityVariables() const override; template diff --git a/projects/interactions/public/LeptonInjector/interactions/DarkNewsCrossSection.h b/projects/interactions/public/LeptonInjector/interactions/DarkNewsCrossSection.h index 990e0dcaf..cfa98ccf5 100644 --- a/projects/interactions/public/LeptonInjector/interactions/DarkNewsCrossSection.h +++ b/projects/interactions/public/LeptonInjector/interactions/DarkNewsCrossSection.h @@ -23,7 +23,7 @@ #include "LeptonInjector/interactions/CrossSection.h" // for CrossSection #include "LeptonInjector/dataclasses/Particle.h" // for Particlev -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -47,15 +47,16 @@ friend cereal::access; virtual bool equal(CrossSection const & other) const override; virtual double TotalCrossSection(dataclasses::InteractionRecord const &) const override; - virtual double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; + virtual double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const; virtual double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; virtual double DifferentialCrossSection(LI::dataclasses::Particle::ParticleType primary, LI::dataclasses::Particle::ParticleType target, double energy, double Q2) const; virtual double InteractionThreshold(dataclasses::InteractionRecord const &) const override; virtual double Q2Min(dataclasses::InteractionRecord const &) const; virtual double Q2Max(dataclasses::InteractionRecord const &) const; - virtual void SetUpscatteringMasses(dataclasses::InteractionRecord &) const; - virtual void SetUpscatteringHelicities(dataclasses::InteractionRecord &) const; - virtual void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr random) const override; + virtual double TargetMass(dataclasses::ParticleType const &) const; + virtual std::vector SecondaryMasses(std::vector const &) const; + virtual std::vector SecondaryHelicities(dataclasses::InteractionRecord const &) const; + virtual void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr random) const override; virtual std::vector GetPossibleTargets() const override = 0; // Requires Python-side implementation virtual std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override = 0; // Requires Python-side implementation @@ -92,4 +93,4 @@ CEREAL_CLASS_VERSION(LI::interactions::DarkNewsCrossSection, 0); CEREAL_REGISTER_TYPE(LI::interactions::DarkNewsCrossSection); CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::interactions::CrossSection, LI::interactions::DarkNewsCrossSection); -#endif // LI_DarkNewsCrossSection_H \ No newline at end of file +#endif // LI_DarkNewsCrossSection_H diff --git a/projects/interactions/public/LeptonInjector/interactions/DarkNewsDecay.h b/projects/interactions/public/LeptonInjector/interactions/DarkNewsDecay.h index 47417ff66..0c7d2bfef 100644 --- a/projects/interactions/public/LeptonInjector/interactions/DarkNewsDecay.h +++ b/projects/interactions/public/LeptonInjector/interactions/DarkNewsDecay.h @@ -23,7 +23,8 @@ #include "LeptonInjector/interactions/Decay.h" // for Decay #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -44,8 +45,8 @@ friend cereal::access; virtual double TotalDecayWidth(LI::dataclasses::Particle::ParticleType primary) const override; virtual double TotalDecayWidthForFinalState(dataclasses::InteractionRecord const &) const override; virtual double DifferentialDecayWidth(dataclasses::InteractionRecord const &) const override; - virtual dataclasses::InteractionRecord SampleRecordFromDarkNews(dataclasses::InteractionRecord &, std::shared_ptr) const; - virtual void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const override; + virtual void SampleRecordFromDarkNews(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const; + virtual void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const override; virtual std::vector GetPossibleSignatures() const override = 0; // Requires python-side implementation virtual std::vector GetPossibleSignaturesFromParent(LI::dataclasses::Particle::ParticleType primary) const override = 0; // Requires python-side implementation @@ -79,4 +80,4 @@ CEREAL_CLASS_VERSION(LI::interactions::DarkNewsDecay, 0); CEREAL_REGISTER_TYPE(LI::interactions::DarkNewsDecay); CEREAL_REGISTER_POLYMORPHIC_RELATION(LI::interactions::Decay, LI::interactions::DarkNewsDecay); -#endif // LI_DarkNewsDecay_H \ No newline at end of file +#endif // LI_DarkNewsDecay_H diff --git a/projects/interactions/public/LeptonInjector/interactions/Decay.h b/projects/interactions/public/LeptonInjector/interactions/Decay.h index c5d1de34d..62fb8b07f 100644 --- a/projects/interactions/public/LeptonInjector/interactions/Decay.h +++ b/projects/interactions/public/LeptonInjector/interactions/Decay.h @@ -16,7 +16,8 @@ #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -37,7 +38,7 @@ friend cereal::access; virtual double TotalDecayLength(LI::dataclasses::InteractionRecord const & record) const; virtual double TotalDecayLengthForFinalState(LI::dataclasses::InteractionRecord const & record) const; virtual double DifferentialDecayWidth(dataclasses::InteractionRecord const &) const = 0; - virtual void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const = 0; + virtual void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const = 0; virtual std::vector GetPossibleSignatures() const = 0; virtual std::vector GetPossibleSignaturesFromParent(LI::dataclasses::Particle::ParticleType primary) const = 0; virtual double FinalStateProbability(dataclasses::InteractionRecord const & record) const = 0; diff --git a/projects/interactions/public/LeptonInjector/interactions/DipoleFromTable.h b/projects/interactions/public/LeptonInjector/interactions/DipoleFromTable.h index 1d57dafe5..9dd9c7ff3 100644 --- a/projects/interactions/public/LeptonInjector/interactions/DipoleFromTable.h +++ b/projects/interactions/public/LeptonInjector/interactions/DipoleFromTable.h @@ -23,7 +23,8 @@ #include "LeptonInjector/dataclasses/Particle.h" // for Particle #include "LeptonInjector/utilities/Interpolator.h" // for Interpolator1D -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -58,12 +59,12 @@ DipoleFromTable() {}; DipoleFromTable(double hnl_mass, double dipole_coupling, HelicityChannel channel, bool z_samp, bool in_invGeV, std::set const & primary_types) : z_samp(z_samp), in_invGeV(in_invGeV), primary_types(primary_types), hnl_mass(hnl_mass), dipole_coupling(dipole_coupling), channel(channel) {}; DipoleFromTable(double hnl_mass, double dipole_coupling, HelicityChannel channel, bool z_samp, bool in_invGeV, bool inelastic, std::set const & primary_types) : z_samp(z_samp), in_invGeV(in_invGeV), inelastic(inelastic), primary_types(primary_types), hnl_mass(hnl_mass), dipole_coupling(dipole_coupling), channel(channel) {}; double TotalCrossSection(dataclasses::InteractionRecord const &) const override; - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; + double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const; double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; double DifferentialCrossSection(LI::dataclasses::Particle::ParticleType primary_type, double primary_energy, LI::dataclasses::Particle::ParticleType target_type, double target_mass, double y) const; double DifferentialCrossSection(LI::dataclasses::Particle::ParticleType primary_type, double primary_energy, LI::dataclasses::Particle::ParticleType target_type, double target_mass, double y, double thresh) const; double InteractionThreshold(dataclasses::InteractionRecord const &) const override; - void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const override; + void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const override; std::vector GetPossibleTargets() const override; std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override; @@ -126,7 +127,6 @@ DipoleFromTable() {}; throw std::runtime_error("DipoleFromTable only supports version <= 0!"); } } - }; } // namespace interactions diff --git a/projects/interactions/public/LeptonInjector/interactions/DummyCrossSection.h b/projects/interactions/public/LeptonInjector/interactions/DummyCrossSection.h index a0ef78500..c5ca51b9a 100644 --- a/projects/interactions/public/LeptonInjector/interactions/DummyCrossSection.h +++ b/projects/interactions/public/LeptonInjector/interactions/DummyCrossSection.h @@ -21,7 +21,8 @@ #include "LeptonInjector/interactions/CrossSection.h" // for CrossSection #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -37,10 +38,10 @@ friend cereal::access; virtual bool equal(CrossSection const & other) const override; double TotalCrossSection(dataclasses::InteractionRecord const &) const override; - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; + double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const; double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; double InteractionThreshold(dataclasses::InteractionRecord const &) const override; - void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr random) const override; + void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr random) const override; std::vector GetPossibleTargets() const override; std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override; diff --git a/projects/interactions/public/LeptonInjector/interactions/ElasticScattering.h b/projects/interactions/public/LeptonInjector/interactions/ElasticScattering.h index b78f51c48..2a1dcae1e 100644 --- a/projects/interactions/public/LeptonInjector/interactions/ElasticScattering.h +++ b/projects/interactions/public/LeptonInjector/interactions/ElasticScattering.h @@ -20,7 +20,8 @@ #include "LeptonInjector/interactions/CrossSection.h" // for CrossSection #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -41,9 +42,9 @@ friend cereal::access; double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; double DifferentialCrossSection(LI::dataclasses::Particle::ParticleType primary_type, double primary_energy, double y) const; double TotalCrossSection(dataclasses::InteractionRecord const &) const override; - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; + double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const; double InteractionThreshold(dataclasses::InteractionRecord const &) const override; - void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const override; + void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const override; std::vector GetPossibleTargets() const override; std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override; diff --git a/projects/interactions/public/LeptonInjector/interactions/HNLFromSpline.h b/projects/interactions/public/LeptonInjector/interactions/HNLFromSpline.h index e11a91ba0..fe2d227ab 100644 --- a/projects/interactions/public/LeptonInjector/interactions/HNLFromSpline.h +++ b/projects/interactions/public/LeptonInjector/interactions/HNLFromSpline.h @@ -29,7 +29,7 @@ #include "LeptonInjector/dataclasses/Particle.h" // for Particle #include "photospline/detail/fitsio.h" // for splinet... -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace utilities { class LI_random; } } namespace cereal { class access; } @@ -66,11 +66,11 @@ friend cereal::access; double TotalCrossSection(dataclasses::InteractionRecord const &) const override; double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy) const; - double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const override; + double TotalCrossSection(LI::dataclasses::Particle::ParticleType primary, double energy, LI::dataclasses::Particle::ParticleType target) const; double DifferentialCrossSection(dataclasses::InteractionRecord const &) const override; double DifferentialCrossSection(double energy, double x, double y, double secondary_lepton_mass) const; double InteractionThreshold(dataclasses::InteractionRecord const &) const override; - void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr random) const override; + void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr random) const override; std::vector GetPossibleTargets() const override; std::vector GetPossibleTargetsFromPrimary(LI::dataclasses::Particle::ParticleType primary_type) const override; @@ -87,6 +87,7 @@ friend cereal::access; double GetTargetMass() const {return target_mass_;}; int GetInteractionType() const {return interaction_type_;}; + static double GetLeptonMass(LI::dataclasses::Particle::ParticleType lepton_type); public: virtual std::vector DensityVariables() const override; template diff --git a/projects/interactions/public/LeptonInjector/interactions/InteractionCollection.h b/projects/interactions/public/LeptonInjector/interactions/InteractionCollection.h index ca57cf84f..46717afa6 100644 --- a/projects/interactions/public/LeptonInjector/interactions/InteractionCollection.h +++ b/projects/interactions/public/LeptonInjector/interactions/InteractionCollection.h @@ -27,12 +27,12 @@ namespace LI { namespace interactions { class CrossSection; } } namespace LI { namespace interactions { class Decay; } } -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } namespace LI { namespace interactions { -class InteractionCollection{ +class InteractionCollection { private: LI::dataclasses::Particle::ParticleType primary_type; std::vector> cross_sections; diff --git a/projects/interactions/public/LeptonInjector/interactions/NeutrissimoDecay.h b/projects/interactions/public/LeptonInjector/interactions/NeutrissimoDecay.h index 2cac3b297..b1d790524 100644 --- a/projects/interactions/public/LeptonInjector/interactions/NeutrissimoDecay.h +++ b/projects/interactions/public/LeptonInjector/interactions/NeutrissimoDecay.h @@ -21,7 +21,8 @@ #include "LeptonInjector/interactions/Decay.h" // for Decay #include "LeptonInjector/dataclasses/Particle.h" // for Particle -namespace LI { namespace dataclasses { struct InteractionRecord; } } +namespace LI { namespace dataclasses { class InteractionRecord; } } +namespace LI { namespace dataclasses { class CrossSectionDistributionRecord; } } namespace LI { namespace dataclasses { struct InteractionSignature; } } namespace LI { namespace utilities { class LI_random; } } @@ -51,7 +52,7 @@ NeutrissimoDecay() {}; virtual double TotalDecayWidth(LI::dataclasses::Particle::ParticleType primary) const override; virtual double TotalDecayWidthForFinalState(dataclasses::InteractionRecord const &) const override; virtual double DifferentialDecayWidth(dataclasses::InteractionRecord const &) const override; - virtual void SampleFinalState(dataclasses::InteractionRecord &, std::shared_ptr) const override; + virtual void SampleFinalState(dataclasses::CrossSectionDistributionRecord &, std::shared_ptr) const override; virtual std::vector GetPossibleSignatures() const override; virtual std::vector GetPossibleSignaturesFromParent(LI::dataclasses::Particle::ParticleType primary) const override; virtual double FinalStateProbability(dataclasses::InteractionRecord const & record) const override; diff --git a/python/LIController.py b/python/LIController.py index 51540c393..355ec21d7 100644 --- a/python/LIController.py +++ b/python/LIController.py @@ -49,7 +49,7 @@ def __init__(self, events_to_inject, experiment, seed=0): self.detector_model.LoadDetectorModel(detector_model_file) # Define the primary injection and physical process - self.primary_injection_process = _injection.InjectionProcess() + self.primary_injection_process = _injection.PrimaryInjectionProcess() self.primary_physical_process = _injection.PhysicalProcess() # Define lists for the secondary injection and physical processes @@ -79,43 +79,47 @@ def SetProcesses( self.primary_injection_process.primary_type = primary_type self.primary_physical_process.primary_type = primary_type - # Add all injection distributions - for _, idist in primary_injection_distributions.items(): - self.primary_injection_process.AddInjectionDistribution(idist) - # Add all physical distributions - for _, pdist in primary_physical_distributions.items(): - self.primary_physical_process.AddPhysicalDistribution(pdist) + # Default injection distributions + if "mass" not in primary_injection_distributions.keys(): + self.primary_injection_process.AddPrimaryInjectionDistribution( + _distributions.PrimaryMass(0) + ) # Default injection distributions - if "target" not in primary_injection_distributions.keys(): - self.primary_injection_process.AddInjectionDistribution( - _distributions.TargetAtRest() + if "mass" not in primary_physical_distributions.keys(): + self.primary_physical_process.AddPhysicalDistribution( + _distributions.PrimaryMass(0) ) + + # Default injection distributions if "helicity" not in primary_injection_distributions.keys(): - self.primary_injection_process.AddInjectionDistribution( + self.primary_injection_process.AddPrimaryInjectionDistribution( _distributions.PrimaryNeutrinoHelicityDistribution() ) # Default injection distributions - if "target" not in primary_physical_distributions.keys(): - self.primary_physical_process.AddPhysicalDistribution( - _distributions.TargetAtRest() - ) if "helicity" not in primary_physical_distributions.keys(): self.primary_physical_process.AddPhysicalDistribution( _distributions.PrimaryNeutrinoHelicityDistribution() ) + # Add all injection distributions + for _, idist in primary_injection_distributions.items(): + self.primary_injection_process.AddPrimaryInjectionDistribution(idist) + # Add all physical distributions + for _, pdist in primary_physical_distributions.items(): + self.primary_physical_process.AddPhysicalDistribution(pdist) + # Loop through possible secondary interactions for i_sec, secondary_type in enumerate(secondary_types): - secondary_injection_process = _injection.InjectionProcess() + secondary_injection_process = _injection.SecondaryInjectionProcess() secondary_physical_process = _injection.PhysicalProcess() secondary_injection_process.primary_type = secondary_type secondary_physical_process.primary_type = secondary_type # Add all injection distributions for idist in secondary_injection_distributions[i_sec]: - secondary_injection_process.AddInjectionDistribution(idist) + secondary_injection_process.AddSecondaryInjectionDistribution(idist) # Add all physical distributions for pdist in secondary_physical_distributions[i_sec]: secondary_physical_process.AddPhysicalDistribution(pdist) @@ -123,12 +127,12 @@ def SetProcesses( # Add the position distribution fid_vol = self.GetFiducialVolume() if fid_vol is not None: - secondary_injection_process.AddInjectionDistribution( - _distributions.SecondaryPositionDistribution(fid_vol) + secondary_injection_process.AddSecondaryInjectionDistribution( + _distributions.SecondaryBoundedVertexDistribution(fid_vol) ) else: - secondary_injection_process.AddInjectionDistribution( - _distributions.SecondaryPositionDistribution() + secondary_injection_process.AddSecondaryInjectionDistribution( + _distributions.SecondaryPhysicalVertexDistribution() ) self.secondary_injection_processes.append(secondary_injection_process) @@ -185,19 +189,19 @@ def InputDarkNewsModel(self, primary_type, table_dir, model_kwargs): secondary_interaction_collections = [] for secondary_type, decay_list in secondary_decays.items(): # Define a sedcondary injection distribution - secondary_injection_process = _injection.InjectionProcess() + secondary_injection_process = _injection.SecondaryInjectionProcess() secondary_physical_process = _injection.PhysicalProcess() secondary_injection_process.primary_type = secondary_type secondary_physical_process.primary_type = secondary_type # Add the secondary position distribution if fid_vol is not None: - secondary_injection_process.AddInjectionDistribution( - _distributions.SecondaryPositionDistribution(fid_vol) + secondary_injection_process.AddSecondaryInjectionDistribution( + _distributions.SecondaryBoundedVertexDistribution(fid_vol) ) else: - secondary_injection_process.AddInjectionDistribution( - _distributions.SecondaryPositionDistribution() + secondary_injection_process.AddSecondaryInjectionDistribution( + _distributions.SecondaryPhysicalVertexDistribution() ) self.secondary_injection_processes.append(secondary_injection_process) @@ -288,7 +292,7 @@ def SetInteractions( def Initialize(self): # Define stopping condition # TODO: make this more general - def StoppingCondition(datum): + def StoppingCondition(datum, i): return True # Define the injector object @@ -357,10 +361,6 @@ def SaveEvents(self, filename): "primary_momentum", data=np.array(datum.record.primary_momentum, dtype=float), ) - interaction_group.create_dataset( - "target_momentum", - data=np.array(datum.record.primary_momentum, dtype=float), - ) for isec_momenta, sec_momenta in enumerate( datum.record.secondary_momenta ): diff --git a/python/LIDarkNews.py b/python/LIDarkNews.py index ccfc21138..31701af3f 100644 --- a/python/LIDarkNews.py +++ b/python/LIDarkNews.py @@ -5,6 +5,8 @@ import json import ntpath import pickle +import functools +import logging from scipy.interpolate import CloughTocher2DInterpolator, CubicSpline # LeptonInjector methods @@ -14,8 +16,14 @@ from leptoninjector import _util # DarkNews methods +import DarkNews from DarkNews import phase_space from DarkNews.ModelContainer import ModelContainer +ModelContainer_configure_logger = ModelContainer.configure_logger +@functools.wraps(ModelContainer.configure_logger) +def suppress_info(self, logger, loglevel="INFO", prettyprinter=None, logfile=None, verbose=False): + return ModelContainer_configure_logger(self, logger, loglevel="WARNING", prettyprinter=prettyprinter, logfile=logfile, verbose=verbose) +ModelContainer.configure_logger = suppress_info from DarkNews.processes import * from DarkNews.nuclear_tools import NuclearTarget from DarkNews.integrands import get_decay_momenta_from_vegas_samples @@ -490,25 +498,25 @@ def DifferentialCrossSection(self, arg1, target=None, energy=None, Q2=None): self._redefine_interpolation_objects(diff=True) return dxsec - def SetUpscatteringMasses(self, interaction): - interaction.primary_mass = 0 - interaction.target_mass = self.ups_case.MA + def TargetMass(self, target_type): + target_mass = self.ups_case.MA + return target_mass + + def SecondaryMasses(self, secondary_types): secondary_masses = [] secondary_masses.append(self.ups_case.m_ups) secondary_masses.append(self.ups_case.MA) - interaction.secondary_masses = secondary_masses - self.m_ups = self.ups_case.m_ups - self.m_target = self.ups_case.MA + return secondary_masses - def SetUpscatteringHelicities(self, interaction): + def SecondaryHelicities(self, record): secondary_helicities = [] secondary_helicities.append( - self.ups_case.h_upscattered * interaction.primary_helicity + self.ups_case.h_upscattered * record.primary_helicity ) - secondary_helicities.append(interaction.target_helicity) - interaction.secondary_helicity = secondary_helicities + secondary_helicities.append(record.target_helicity) self.h_ups = self.ups_case.m_ups self.h_target = self.ups_case.MA + return secondary_helicities def TotalCrossSection(self, arg1, energy=None, target=None): # Handle overloaded arguments @@ -521,13 +529,14 @@ def TotalCrossSection(self, arg1, energy=None, target=None): else: print("Incorrect function call to TotalCrossSection!") exit(0) - if primary != self.ups_case.nu_projectile: + if int(primary) != self.ups_case.nu_projectile: return 0 interaction = LI.dataclasses.InteractionRecord() interaction.signature.primary_type = primary interaction.signature.target_type = target interaction.primary_momentum[0] = energy if energy < self.InteractionThreshold(interaction): + print("Python: energy < self.InteractionThreshold(interaction)") return 0 # Check if we can interpolate @@ -717,7 +726,7 @@ def TotalDecayWidth(self, arg1): else: print("Incorrect function call to TotalDecayWidth!") exit(0) - if primary != self.dec_case.nu_parent: + if int(primary) != self.dec_case.nu_parent: return 0 if self.total_width is None: # Need to set the total width @@ -758,7 +767,8 @@ def TotalDecayWidthForFinalState(self, record): ) ): return 0 - return self.dec_case.total_width() + ret = self.dec_case.total_width() + return ret def DensityVariables(self): if type(self.dec_case) == FermionSinglePhotonDecay: @@ -821,6 +831,8 @@ def SampleRecordFromDarkNews(self, record, random): np.expand_dims(np.array(record.primary_momentum), 0), ) + secondaries = record.GetSecondaryParticleRecords() + if type(self.dec_case) == FermionSinglePhotonDecay: gamma_idx = 0 for secondary in record.signature.secondary_types: @@ -831,14 +843,14 @@ def SampleRecordFromDarkNews(self, record, random): print("No gamma found in the list of secondaries!") exit(0) nu_idx = 1 - gamma_idx - secondary_momenta = [] - secondary_momenta.insert( - gamma_idx, list(np.squeeze(four_momenta["P_decay_photon"])) - ) - secondary_momenta.insert( - nu_idx, list(np.squeeze(four_momenta["P_decay_N_daughter"])) - ) - record.secondary_momenta = secondary_momenta + secondaries[gamma_idx].four_momentum = np.squeeze(four_momenta["P_decay_photon"]) + secondaries[gamma_idx].mass = 0 + secondaries[nu_idx].four_momentum = np.squeeze(four_momenta["P_decay_N_daughter"]) + secondaries[nu_idx].mass = 0 + + print("P_gamma", secondaries[gamma_idx].four_momentum) + print("P_nu", secondaries[nu_idx].four_momentum) + elif type(self.dec_case) == FermionDileptonDecay: lepminus_idx = -1 lepplus_idx = -1 @@ -864,14 +876,13 @@ def SampleRecordFromDarkNews(self, record, random): print("Couldn't find two leptons and a neutrino in the final state!") exit(0) secondary_momenta = [] - secondary_momenta.insert( - lepminus_idx, list(np.squeeze(four_momenta["P_decay_ell_minus"])) + seconaries[lepminus_idx].four_momentum = ( + np.squeeze(four_momenta["P_decay_ell_minus"]) ) - secondary_momenta.insert( - lepplus_idx, list(np.squeeze(four_momenta["P_decay_ell_plus"])) + secondaries[lepplus_idx].four_momentum = ( + np.squeeze(four_momenta["P_decay_ell_plus"]) ) - secondary_momenta.insert( - nu_idx, list(np.squeeze(four_momenta["P_decay_N_daughter"])) + secondaries[nu_idx].four_momentum = ( + np.squeeze(four_momenta["P_decay_N_daughter"]) ) - record.secondary_momenta = secondary_momenta return record diff --git a/resources/Detectors/densities/CCM/CCM-v1.dat b/resources/Detectors/densities/CCM/CCM-v1.dat index 4143815b9..619e4ed02 100644 --- a/resources/Detectors/densities/CCM/CCM-v1.dat +++ b/resources/Detectors/densities/CCM/CCM-v1.dat @@ -76,4 +76,4 @@ object cylinder 23 0 -0.65 0 0 0 1.06 0 1.50 ccm_pmt_frame # Inner argon object cylinder 23 0 -0.65 0 0 0 0.96 0 1.232 ccm_inner_argon ARGON constant 1.3954 -#detector 23 0 -0.65 +detector 23 0 -0.65 diff --git a/resources/Examples/Example1/DIS_IceCube.py b/resources/Examples/Example1/DIS_IceCube.py index 879812472..302175e61 100644 --- a/resources/Examples/Example1/DIS_IceCube.py +++ b/resources/Examples/Example1/DIS_IceCube.py @@ -1,15 +1,33 @@ import os import sys import numpy as np +import functools import leptoninjector as LI from leptoninjector import _util from leptoninjector.LIController import LIController +@functools.wraps(LIController.GenerateEvents) +def GenerateEvents(self, N=None): + if N is None: + N = self.events_to_inject + count = 0 + while (self.injector.InjectedEvents() < self.events_to_inject) and (count < N): + print("Injecting Event", count, end="\r") + tree = self.injector.GenerateEvent() + self.weighter.EventWeight(tree) + self.events.append(tree) + count += 1 + #if hasattr(self, "DN_processes"): + # self.DN_processes.SaveCrossSectionTables() + return self.events + +LIController.GenerateEvents = GenerateEvents + resources_dir = _util.resource_package_dir() # Number of events to inject -events_to_inject = 1000 +events_to_inject = int(1e6) # Expeirment to run experiment = "IceCube" @@ -41,6 +59,10 @@ primary_injection_distributions = {} primary_physical_distributions = {} +mass_dist = LI.distributions.PrimaryMass(0) +primary_injection_distributions["mass"] = mass_dist +primary_physical_distributions["mass"] = mass_dist + # energy distribution edist = LI.distributions.PowerLaw(2, 1e3, 1e6) primary_injection_distributions["energy"] = edist diff --git a/resources/Examples/Example2/DipolePortal_CCM.py b/resources/Examples/Example2/DipolePortal_CCM.py index 394451850..7838c8854 100644 --- a/resources/Examples/Example2/DipolePortal_CCM.py +++ b/resources/Examples/Example2/DipolePortal_CCM.py @@ -77,7 +77,7 @@ # Position distribution: consider neutrinos from a point source max_dist = 25 lower_pos_dist = LI.distributions.PointSourcePositionDistribution( - lower_target_origin, max_dist, set(controller.GetDetectorModelTargets()[0]) + lower_target_origin - detector_origin, max_dist, set(controller.GetDetectorModelTargets()[0]) ) primary_injection_distributions["position"] = lower_pos_dist @@ -88,6 +88,12 @@ controller.Initialize() +def stop(datum, i): + secondary_type = datum.record.signature.secondary_types[i] + return secondary_type != LI.dataclasses.Particle.ParticleType.N4 + +controller.injector.SetStoppingCondition(stop) + events = controller.GenerateEvents() controller.SaveEvents( diff --git a/resources/Examples/Example2/DipolePortal_MINERvA.py b/resources/Examples/Example2/DipolePortal_MINERvA.py index 1101691d4..b83861e76 100644 --- a/resources/Examples/Example2/DipolePortal_MINERvA.py +++ b/resources/Examples/Example2/DipolePortal_MINERvA.py @@ -88,6 +88,12 @@ controller.Initialize() +def stop(datum, i): + secondary_type = datum.record.signature.secondary_types[i] + return secondary_type != LI.dataclasses.Particle.ParticleType.N4 + +controller.injector.SetStoppingCondition(stop) + events = controller.GenerateEvents() controller.SaveEvents( diff --git a/resources/Examples/Example2/DipolePortal_MiniBooNE.py b/resources/Examples/Example2/DipolePortal_MiniBooNE.py index 0eebc981a..f5cd052d4 100644 --- a/resources/Examples/Example2/DipolePortal_MiniBooNE.py +++ b/resources/Examples/Example2/DipolePortal_MiniBooNE.py @@ -88,6 +88,12 @@ controller.Initialize() +def stop(datum, i): + secondary_type = datum.record.signature.secondary_types[i] + return secondary_type != LI.dataclasses.Particle.ParticleType.N4 + +controller.injector.SetStoppingCondition(stop) + events = controller.GenerateEvents() controller.SaveEvents(