Source code for neunorm.utils.constants

"""
Physical constants for neutron TOF calculations.

All fundamental physical constants sourced from scipy.constants (CODATA 2018).
NO hardcoded values for standard physics quantities - always use scipy.

Detector-specific and facility-specific constants are documented with sources.
"""

import scipy.constants as const

# =============================================================================
# Fundamental Physical Constants (from scipy.constants)
# =============================================================================

M_N = const.m_n  # Neutron mass (kg): 1.67492749804e-27
"""Neutron mass in kg. Source: scipy.constants.m_n (CODATA 2018)"""

H = const.h  # Planck constant (J·s): 6.62607015e-34
"""Planck constant in J·s. Source: scipy.constants.h (exact, 2019 SI definition)"""

E_CHARGE = const.e  # Elementary charge (C): 1.602176634e-19
"""Elementary charge in Coulombs. Source: scipy.constants.e (exact, 2019 SI definition)"""

# =============================================================================
# Derived Constants (computed from scipy.constants for full precision)
# =============================================================================

H_OVER_MN = const.h / const.m_n  # m·s
"""
h / m_n ratio for wavelength conversion.

Used in: λ = (h/m_n) * (t/L)
Value: ~3.956034e-7 m·s
Computed from scipy.constants for full precision (no rounding).
"""

DE_BROGLIE_EV_ANGSQ = (const.h**2 / (2 * const.m_n * const.e)) * 1e20  # eV·Å²
"""
de Broglie constant for wavelength-energy conversion.

Used in: E(eV) = DE_BROGLIE_EV_ANGSQ / λ²(Å)
Value: ~0.0818 eV·Å²
Computed from scipy.constants with unit conversion (m² → Ų).

Derivation:
E = h² / (2·m_n·λ²)     [SI units: J = (J·s)² / (kg·m²)]
E(eV) = E(J) / e        [Convert J to eV]
With λ in Å: multiply by 1e20 (since 1 Å = 1e-10 m, so 1 Ų = 1e-20 m²)
"""

# =============================================================================
# Detector-Specific Constants (NOT in scipy.constants)
# =============================================================================

TPX3_CLOCK_NS = 25.0  # nanoseconds
"""
Timepix3 detector time resolution.

Source:
- Timepix3 Manual, Section 3.2, Medipix Collaboration (2014)
- URL: https://medipix.web.cern.ch/
- Technical specification: 1.5625 ns × 16 (clock divider) = 25 ns

Last verified: 2025-11-17
Precision: Exact (clock specification from manufacturer)
"""

TPX4_CLOCK_NS = 0.195  # nanoseconds
"""
Timepix4 detector time resolution (improved from TPX3).

Source:
- Timepix4 Specifications, Medipix Collaboration (2023)
- URL: https://medipix.web.cern.ch/

Last verified: 2025-11-17
Note: TPX4 not yet deployed at VENUS as of 2025-11-17
"""

# =============================================================================
# Facility-Specific Constants
# =============================================================================

VENUS_FLIGHT_PATH_M = 25.0  # meters
"""
Default VENUS beamline L2 distance (moderator to detector).

Source:
- VENUS beamline design documents, Spallation Neutron Source, ORNL
- URL: https://neutrons.ornl.gov/venus
- Contact: Instrument scientists for precise measurements

Last verified: 2025-11-17

Important Notes:
- Actual flight path varies by detector position and sample position
- Always verify with beamline staff for high-precision measurements
- Typical range: 24.5 - 25.5 m depending on detector mount
"""

MARS_FLIGHT_PATH_M = None  # Not applicable (continuous beam, no TOF)
"""
MARS beamline uses continuous neutron beam (HFIR reactor).

No pulsed source → no time-of-flight capability → flight path concept not applicable.
For MARS normalization, use traditional flat-field correction only.
"""

# =============================================================================
# Unit Conversion Helpers
# =============================================================================


[docs] def ev_to_joule(energy_ev: float) -> float: """ Convert electron volts to Joules. Uses scipy.constants.e (elementary charge). Parameters ---------- energy_ev : float Energy in electron volts Returns ------- float Energy in Joules """ return energy_ev * E_CHARGE
[docs] def joule_to_ev(energy_j: float) -> float: """ Convert Joules to electron volts. Uses scipy.constants.e (elementary charge). Parameters ---------- energy_j : float Energy in Joules Returns ------- float Energy in electron volts """ return energy_j / E_CHARGE
[docs] def angstrom_to_meter(wavelength_a: float) -> float: """ Convert Angstrom to meters. Parameters ---------- wavelength_a : float Wavelength in Angstrom Returns ------- float Wavelength in meters Notes ----- Conversion factor: 1 Å = 1e-10 m (exact, SI definition) """ return wavelength_a * 1e-10
[docs] def meter_to_angstrom(wavelength_m: float) -> float: """ Convert meters to Angstrom. Parameters ---------- wavelength_m : float Wavelength in meters Returns ------- float Wavelength in Angstrom Notes ----- Conversion factor: 1 m = 1e10 Å (exact, SI definition) """ return wavelength_m * 1e10