Initial commit
Base modular structure (phase space, Fermi function) Initial .gitignore
This commit is contained in:
+177
@@ -0,0 +1,177 @@
|
|||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🐍 Python
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
**pycache**/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🧪 Virtual environments
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🧠 Type checking / linting
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.mypy_cache/
|
||||||
|
.pytest_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
.pyre/
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 📓 Jupyter / IPython
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.ipynb_checkpoints/
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 📊 Data / outputs (customize!)
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# Ignore generated spectra, fits, etc.
|
||||||
|
|
||||||
|
data/
|
||||||
|
outputs/
|
||||||
|
results/
|
||||||
|
*.npy
|
||||||
|
*.npz
|
||||||
|
*.h5
|
||||||
|
*.hdf5
|
||||||
|
*.pkl
|
||||||
|
|
||||||
|
# But keep small example data if needed
|
||||||
|
|
||||||
|
# !data/example/
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🖼️ Plots
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
*.png
|
||||||
|
*.jpg
|
||||||
|
*.jpeg
|
||||||
|
*.pdf
|
||||||
|
*.svg
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🧾 Logs
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# ⚙️ IDEs / Editors
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🐧 OS / Filesystem
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🧮 Build / C / Fortran (for future physics libs)
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
*.o
|
||||||
|
*.out
|
||||||
|
*.a
|
||||||
|
*.mod
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🧵 HPC / SLURM
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
slurm-*.out
|
||||||
|
*.sbatch
|
||||||
|
*.srun
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 🔐 Secrets / configs
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# 📦 Misc
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
coverage.xml
|
||||||
|
htmlcov/
|
||||||
|
.cache/
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# beta_spectrum/__init__.py
|
||||||
|
|
||||||
|
from .constants import ALPHA
|
||||||
|
from .units import T_to_W, W_to_T
|
||||||
|
|
||||||
|
from .components.phase_space import PhaseSpace
|
||||||
|
from .components.fermi import FermiFunction
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"ALPHA",
|
||||||
|
"T_to_W",
|
||||||
|
"W_to_T",
|
||||||
|
"PhaseSpace",
|
||||||
|
"FermiFunction",
|
||||||
|
]
|
||||||
|
|
||||||
|
__version__ = "0.1.0"
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# base.py
|
||||||
|
from __future__ import annotations
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
ArrayLike = np.ndarray
|
||||||
|
|
||||||
|
|
||||||
|
class SpectrumComponent(ABC):
|
||||||
|
"""
|
||||||
|
Base class for multiplicative components of beta-spectrum
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __call__(self, W: ArrayLike) -> ArrayLike:
|
||||||
|
"""
|
||||||
|
Evaluate component at total energy W (in m_e units)
|
||||||
|
"""
|
||||||
|
pass
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# components/fermi.py
|
||||||
|
import numpy as np
|
||||||
|
from scipy.special import loggamma
|
||||||
|
|
||||||
|
from ..base import SpectrumComponent
|
||||||
|
from ..constants import ALPHA
|
||||||
|
from ..utils import nuclear_radius
|
||||||
|
|
||||||
|
|
||||||
|
class FermiFunction(SpectrumComponent):
|
||||||
|
def __init__(self, Z: int, A: int):
|
||||||
|
self.Z = Z
|
||||||
|
self.A = A
|
||||||
|
self.alphaZ = ALPHA * Z
|
||||||
|
self.gamma = np.sqrt(1.0 - self.alphaZ**2)
|
||||||
|
self.R = nuclear_radius(A)
|
||||||
|
|
||||||
|
def __call__(self, W: np.ndarray) -> np.ndarray:
|
||||||
|
p = np.sqrt(W**2 - 1.0)
|
||||||
|
|
||||||
|
# Avoid division by zero
|
||||||
|
p = np.where(p == 0, 1e-30, p)
|
||||||
|
|
||||||
|
eta = self.alphaZ * W / p
|
||||||
|
|
||||||
|
# --- log components ---
|
||||||
|
|
||||||
|
# log prefactor
|
||||||
|
log_prefactor = np.log(2 * (1 + self.gamma))
|
||||||
|
|
||||||
|
# log power term
|
||||||
|
log_power = -2 * (1 - self.gamma) * np.log(2 * p * self.R)
|
||||||
|
|
||||||
|
# log gamma ratio
|
||||||
|
z = self.gamma + 1j * eta
|
||||||
|
log_gamma_complex = loggamma(z)
|
||||||
|
log_gamma_abs_sq = 2 * np.real(log_gamma_complex)
|
||||||
|
|
||||||
|
log_gamma_denom = 2 * loggamma(2 * self.gamma + 1).real
|
||||||
|
|
||||||
|
# log exponential
|
||||||
|
log_exp = np.pi * eta
|
||||||
|
|
||||||
|
logF = (
|
||||||
|
log_prefactor
|
||||||
|
+ log_power
|
||||||
|
+ log_gamma_abs_sq
|
||||||
|
- log_gamma_denom
|
||||||
|
+ log_exp
|
||||||
|
)
|
||||||
|
|
||||||
|
return np.exp(logF)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from beta_spectrum.constants import ALPHA
|
||||||
|
from beta_spectrum.base import SpectrumComponent
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# components/phase_space.py
|
||||||
|
import numpy as np
|
||||||
|
from ..base import SpectrumComponent
|
||||||
|
|
||||||
|
|
||||||
|
class PhaseSpace(SpectrumComponent):
|
||||||
|
def __init__(self, W0: float, m_nu: float = 0.0):
|
||||||
|
self.W0 = W0
|
||||||
|
self.m_nu = m_nu
|
||||||
|
|
||||||
|
def __call__(self, W: np.ndarray) -> np.ndarray:
|
||||||
|
p = np.sqrt(W**2 - 1.0)
|
||||||
|
Wv = self.W0 - W
|
||||||
|
|
||||||
|
# neutrino mass generalization
|
||||||
|
if self.m_nu == 0:
|
||||||
|
return p * W * Wv**2
|
||||||
|
else:
|
||||||
|
return p * W * Wv * np.sqrt(Wv**2 - self.m_nu**2)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# constants.py
|
||||||
|
ALPHA = 1 / 137.035999084 # fine-structure constant
|
||||||
|
HBAR_C_MEV_FM = 197.3269804 # MeV * fm
|
||||||
|
ME_MEV = 0.510998950 # MeV
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# spectrum.py
|
||||||
|
import numpy as np
|
||||||
|
from typing import List
|
||||||
|
from .base import SpectrumComponent
|
||||||
|
|
||||||
|
|
||||||
|
class BetaSpectrum:
|
||||||
|
def __init__(self, components: List[SpectrumComponent]):
|
||||||
|
self.components = components
|
||||||
|
|
||||||
|
def __call__(self, W: np.ndarray) -> np.ndarray:
|
||||||
|
result = np.ones_like(W)
|
||||||
|
|
||||||
|
for comp in self.components:
|
||||||
|
result *= comp(W)
|
||||||
|
|
||||||
|
return result
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# units.py
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
ME_KEV = 510.99895000 # keV electron mass
|
||||||
|
|
||||||
|
|
||||||
|
def W_to_T(W: float | np.ndarray) -> np.ndarray:
|
||||||
|
return (W - 1.0) * ME_KEV
|
||||||
|
|
||||||
|
|
||||||
|
def T_to_W(T_keV: float | np.ndarray) -> np.ndarray:
|
||||||
|
return T_keV / ME_KEV + 1.0
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# utils.py
|
||||||
|
from .constants import HBAR_C_MEV_FM, ME_MEV
|
||||||
|
|
||||||
|
|
||||||
|
def nuclear_radius(A: float) -> float:
|
||||||
|
r0_fm = 1.2 # fm
|
||||||
|
R_fm = r0_fm * A ** (1 / 3)
|
||||||
|
|
||||||
|
return R_fm / (HBAR_C_MEV_FM / ME_MEV)
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=61.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "beta-spectrum"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "High-precision beta spectrum calculation for nuclear physics"
|
||||||
|
authors = [
|
||||||
|
{ name = "Your Name" }
|
||||||
|
]
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
"numpy",
|
||||||
|
"scipy",
|
||||||
|
"matplotlib"
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["."]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest",
|
||||||
|
"black",
|
||||||
|
"ruff",
|
||||||
|
"mypy"
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
python_version = "3.10"
|
||||||
|
strict = true
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 88
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 88
|
||||||
Reference in New Issue
Block a user