Source code for snf_simulations.detector
"""Functions for simulating antineutrino detectors."""
from .physics import calculate_flux_at_distance
from .spec import Spectrum
[docs]
class Detector:
"""Class representing an antineutrino detector.
Attributes:
volume: Volume of the detector in cubic meters.
proton_density: Proton density of the detector material per cubic centimeter.
name: An optional name for the detector.
"""
def __init__(
self,
volume: float,
proton_density: float,
name: str | None = None,
) -> None:
"""Initialize the Detector object."""
self.volume = volume
self.proton_density = proton_density
self.number_of_protons = (self.volume * 1e6) * self.proton_density
self.name = name
if self.volume <= 0:
msg = "Detector volume must be a positive value"
raise ValueError(msg)
if self.proton_density <= 0:
msg = "Proton density must be a positive value"
raise ValueError(msg)
def __repr__(self) -> str:
"""Return a string representation of the Detector object."""
try:
name_str = f' "{self.name}"' if self.name is not None else ""
repr_str = (
f"<Detector{name_str}: "
f"volume={self.volume:.3e} m3, "
f"proton_density={self.proton_density:.3e} protons/cm3>"
)
except AttributeError:
return "<Detector (uninitialized)>"
else:
return repr_str
[docs]
def calculate_event_rate(
self,
spec: Spectrum,
distance: float,
efficiency: float = 1,
) -> float:
"""Calculate the expected event rate in the detector for a given spectrum.
Args:
spec: Antineutrino spectrum.
distance: Distance from the source to the detector in meters.
efficiency: Detection efficiency.
Returns:
Event rate in s^-1.
"""
# The total flux is the integral of the spectrum over an energy range.
# For inverse beta decay the threshold is 1.806 MeV, so we integrate above this
# energy to get the total flux of antineutrinos that can be detected.
threshold_energy = 1806 # KeV
if spec.energy[-1] < threshold_energy:
msg = "Spectrum energy range does not cover the IBD threshold of 1.806 MeV"
raise ValueError(msg)
total_flux = spec.integrate(lower_energy=threshold_energy)
# Calculate the antineutrino flux at a given distance from the source.
flux_at_distance = calculate_flux_at_distance(total_flux, distance)
# Calculate the event rate using the flux and number of target protons.
cross_section = 1e-44 # cm^2, approximate IBD cross-section
event_rate = self.number_of_protons * flux_at_distance * cross_section
# Apply detection efficiency and return
return event_rate * efficiency