Neutrino oscillations encode fundamental information about neutrino masses and mixing parameters, offering a unique window into physics beyond the Standard Model. Estimating these parameters from oscillation probability maps is, however, computationally challenging due to the maps’ high dimensionality and nonlinear dependence on the underlying physics. In this work, we introduce a data-driven framework that reformulates atmospheric neutrino oscillation parameter inference as a supervised regression task over structured oscillation maps. We propose a hierarchical transformer architecture that explicitly models the two-dimensional structure of these maps, capturing angular dependencies at fixed energies and global correlations across the energy spectrum. To improve physical consistency, the model is trained using a surrogate simulation constraint that enforces agreement between the predicted parameters and the reconstructed oscillation patterns. Furthermore, we introduce a neural network-based uncertainty quantification mechanism that produces distribution-free prediction intervals with formal coverage guarantees.
Overview of the proposed neutrino oscillation parameters estimation.The following libraries have to be installed:
To install the package, run pip install -q git+https://github.com/GiorgioMorales/NuOscParam in the terminal.
After installing the NuOscParam library, run the following script on Python (or on the terminal without the "!"):
!hf download GiorgioMorales/NuInferenceModels \
--repo-type model \
--local-dir $(python -c "import NuOscParam; import os; print(os.path.join(os.path.dirname(NuOscParam.__file__), 'Models', 'saved_models'))") \
--include "ModelType-HierarchicalTransformer/*"If, instead, you cloned the repository, download the model manually from HugginFace.
Then, copy and paste them into the src/NuOscParam/Models/saved_models/ModelType-HierarchicalTransformer folder.
In case you need to retrain the models or simply access the datasets, download them from
HugginFace.
Then, copy and paste them into the src/NuOscParam/Models/saved_models/ModelType-HierarchicalTransformer folder.
We use a simulator that generates 9 oscillation probability maps:
| Transition ↓ / Source → |
|
|
|
|---|---|---|---|
In all cases, the [theta12, theta23, theta13, delta_cp, m21, m31].
Generate Maps Using Known Oscillation Parameters
To use a exact simulator, initiate the Simulator class with the following parameters:
Parameters:
-
mode: It can take the valuesvacuum, which will use a simulator that produces$\nu$ oscillation maps in vacuum, orearth(default), which will use a simulator that produces$\nu$ oscillation maps after Earth-matter effect. -
cropR: It determines the number of rows ($\theta$ ) bins are used. Min:1, Max:120, Default: 80. -
cropC: It determines the number of columns (energy) bins are used. Min:1, Max:120, Default: 30.
from NuOscParam.utils import *
from NuOscParam.Data.DataRanges import *
from NuOscParam.Data.Simulator import Simulator
generator = Simulator(ranges=NEUTRINO_RANGES, mode='earth', device=torch.device("cuda" if torch.cuda.is_available() else "cpu"))To get the actual maps given a set of get_maps method.
The following example considers two sets of 6
import numpy as np
batch = np.array([[3.2434875e+01, 5.0723694e+01, 8.4253168e+00, 1.8559186e+02, 6.9126829e-05, 2.4357950e-03],
[33.003803, 51.50117, 8.243288, 243.95, 7.993506e-05, 0.0024312385]])
maps = generator.get_maps(batch)
# Optionally, plot maps
for i in range(len(batch)):
plot_osc_maps(maps[i, :, :, :].permute(1, 2, 0), title=f"Oscillation Maps. Sample {i+1}")Generate Random Maps
To generate random OscIterableDataset iterable class. Its parameters are the same as those from the Simulator class:
generator = iter(OscIterableDataset(ranges=NEUTRINO_RANGES, mode='earth',
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")))To generate random maps, we call the next command iterably:
X_test, Osc_params = [], []
n_samples = 3 # Generate three random sets of maps
for i in range(n_samples):
xtest, _, osc_pars, _ = next(generator) # Generate 1 sample
X_test.append(xtest)
Osc_params.append(osc_pars)
# Plot oscillation maps
plot_osc_maps(input_image = xtest[0, :, :, :].permute(1, 2, 0), title=f"Oscillation Maps. Sample {i+1}")
X_test = torch.cat(X_test, dim=0)To use our OscillationEstimator class:
from NuOscParam.OscillationEstimator import OscillationEstimator
predictor = OscillationEstimator()We use this class and the predict method to process a batch of
Parameters:
denormalize: IfTrue, the resulting oscillation parameters are given in their normal (operating) scale. IfFalse(default), they're still normalized (between 0 and 1).uncertainty: IfFalse, only the point predictions are retrieved using the trained transformers. IfTrue, the Conformal DualAQD is used in addition to produce 90% prediction intervals. See the Demo for more details.
pred_OscParams = predictor.predict(X_test, denormalize=True, uncertainty=True)The RunMCMC class implements a delayed-acceptance MCMC procedure, which, in our paper, was used as a baseline method for comparison.
While it leads to better or comparable results as our transformer-based approach, its computational cost is substantially higher.
The (optional) parameters of the RunMCMC class, which are given as part of the emcee_kwargs parameter, are:
nwalkers: The number of Goodman & Weare “walkers”. Default:36.nsteps: The number of steps to run. Default:900.burn_in: The number of “burn-in” steps. Default:250.budget_exact: The "budget" or maximum number of times the exact simulator can be executed. Default:80.
The evaluate method is then used to evaluate a given batch of oscillation maps (see Demo):
from NuOscParam.MCMC.RunMCMC import RunMCMC
executor = RunMCMC(mode="earth")
pred_OscParams = executor.evaluate(X_test)Use this Bibtex to cite this repository
@inproceedings{NuOscParam
title={Neutrino Oscillation Parameter Estimation Using Structured Hierarchical Transformers (in review)},
author={Morales, Giorgio and Lehaut, Gregory and Vacheret, Antonin and Jurie, Fr\'{e}d\'{e}ric and Fadili, Jalal},
volume={},
number={},
journal={IEEE International Joint Conference on Neural Networks (IJCNN)},
year={2026},
month={},
pages={},
DOI={},
}
