PMNS matrix parameterisation conversions for neutrino oscillation analysis as described in https://arxiv.org/abs/2507.02101.
Project description
pmns-transforms
A lightweight scientific Python library to build, transform, and analyse PMNS mixing matrices across nine Tait–Bryan parameterisations that privilege specific flavour/mass symmetries.
This codebase is based on and aligned with the framework developed in Testing T2K’s Bayesian constraints with priors in alternate parameterisations (arXiv:2507.02101).
The library implements a numerically stable, vectorised API to:
- construct a PMNS matrix for any of the nine parameterisations;
- extract the mixing angles and Dirac CP phase from a PMNS matrix under a target parameterisation;
- transform parameters from one parameterisation to another (composition of the above two);
- compute the Jacobian of the parameterisation transform via central finite differences;
- compute importance weights for reweighting a uniform-in-sin²θ prior from one parameterisation to another;
- compute the Jarlskog invariant.
Parameterisation overview
- Parameterisations are identified by strings in {e, mu, tau}{1,2,3}, for example: e3 (canonical/PDG-like), mu1, tau2, etc.
- Each string indicates the “single element” index (the one equal to s13 e^{-i δ}) and thereby fixes the row/column symmetries privileged by that parameterisation (as in the paper’s promoted row–column symmetry).
- See appendix A of arXiv:2507.02101 to identify parameterisations with the corresponding row/column symmetries and their matrix form.
Conventions and ranges
- All angles are in radians.
- Angle ranges: θ12, θ23, θ13 ∈ [0, π/2]; δ ∈ (−π, π].
- Single-element convention: U_single = s13 · exp(−i δ) at the position set by the chosen parameterisation.
- Broadcasting: all public functions accept scalars or array-like inputs and broadcast them with NumPy semantics. Scalars yield 3×3 arrays; arrays yield outputs with leading (3,3) followed by the broadcast shape.
Non-identifiable regimes and NaN policy
Certain inverse mappings (matrix → angles) become singular or numerically ill-conditioned:
- When c13 ≈ 0, θ12 and θ23 are not identifiable under this chart; they are returned as NaN.
- When the denominator for cos δ (2 s12 c12 s23 c23 s13) is ill-conditioned, δ is returned as NaN.
- When sin δ ≈ 0, the sign of δ is resolved deterministically via cos δ: δ = 0 if cos δ ≥ 0, else δ = π.
This mirrors the parameterisation singularities discussed in the paper and yields stable, deterministic behaviour.
Installation
Requirements
- Python ≥ 3.8
- NumPy ≥ 1.21
Install from source
- Standard install:
pip install .
- Editable install (development):
pip install -e .
Quick start
import pmns_transforms as pmns
# Example angles (radians)
th12, th23, th13 = 0.59, 0.79, 0.15
dcp = 0.30
# 1) Build the PMNS matrix in the canonical e3 parameterisation
U = pmns.get_mixing_matrix('e3', th12, th23, th13, dcp) # shape (3, 3)
# 2) Extract angles under a different parameterisation (e.g., mu1)
# original_parameterisation informs the phase/sign convention of U
rec_th12, rec_th23, rec_th13, rec_dcp = pmns.get_parameters('mu1', U, original_parameterisation='e3')
# 3) Transform angles directly between parameterisations
new_th12, new_th23, new_th13, new_dcp = pmns.transform('e3', 'mu1', th12, th23, th13, dcp)
# 4) Compute the Jarlskog invariant (broadcasted over inputs)
Jcp = pmns.get_Jarlskog(th12, th23, th13, dcp)
# 5) Compute the 4×4 Jacobian ∂(new params)/∂(old params) via central differences
J = pmns.get_jacobian('e3', 'mu1', th12, th23, th13, dcp) # shape (4, 4)
# 6) Compute importance weights to reweight a uniform-in-sin²θ sample from e3 to mu1
# Equivalent to |det J_{sin²}| at each point; used for prior reweighting
import numpy as np
th12_arr = np.linspace(0.2, 1.3, 500)
th23_arr, th13_arr, dcp_arr = 0.80, 0.15, 0.30
weights = pmns.get_weights('e3', 'mu1', th12_arr, th23_arr, th13_arr, dcp_arr)
Vectorised example (the user constructs arrays with NumPy):
import numpy as np
import pmns_transforms as pmns
# Vectorised inputs broadcast automatically
th12 = np.linspace(0.2, 1.3, 1000)
th23 = 0.80
th13 = 0.15
dcp = np.linspace(-np.pi, np.pi, 1000)
U_all = pmns.get_mixing_matrix('e2', th12, th23, th13, dcp) # shape (3, 3, 1000)
API summary
-
get_mixing_matrix(parameterisation, th12, th23, th13, dcp) → ndarray
- Builds U under the chosen parameterisation. Returns (3,3) or (3,3,*broadcast_shape).
-
get_parameters(target_parameterisation, mixing_matrix, original_parameterisation='e3') → (th12, th23, th13, dcp)
- Extracts angles/phase under target_parameterisation, assuming mixing_matrix was built using original_parameterisation. Handles non-identifiable regimes via NaN, and sign choices as documented below.
-
transform(original_parameterisation, target_parameterisation, th12, th23, th13, dcp) → (new_th12, new_th23, new_th13, new_dcp)
- Convenience wrapper: build → extract.
-
get_jacobian(original_parameterisation, target_parameterisation, th12, th23, th13, dcp, h=1e-5) → ndarray
- Computes the 4×4 Jacobian ∂(θ12, θ23, θ13, δ)_target / ∂(θ12, θ23, θ13, δ)_orig via central finite differences. Returns shape (4, 4) for scalar inputs or (4, 4, *broadcast_shape) for arrays. Results are unreliable near c13 ≈ 0 or δ ≈ 0, ±π.
-
get_weights(original_parameterisation, target_parameterisation, th12, th23, th13, dcp, h=1e-5) → ndarray
- Returns |det J_{sin²}| at each point, where J_{sin²} is the Jacobian of (sin²θ12, sin²θ23, sin²θ13, δ)_orig → (sin²θ12, sin²θ23, sin²θ13, δ)_target. Samples drawn uniformly in sin²θ in the original parameterisation and reweighted by these values represent a uniform distribution in the target parameterisation. Values of inf or NaN indicate singular or ill-conditioned points.
-
get_Jarlskog(th12, th23, th13, dcp) → ndarray
- Computes J = s12 c12 s23 c23 s13 c13² sin δ. Returns a real array matching the broadcast shape.
Numerical notes
-
Inverse stability:
- The sine and cosine of the angles are clipped for numerical safety before square roots/acos.
- If cos(θ13) is below a small epsilon: θ12 and θ23 → NaN.
- If the denominator of the expression for cos δ is ill-conditioned: δ → NaN.
-
Shape checks: get_parameters coerces the input matrix to an ndarray and validates a leading 3×3 shape.
Example scripts
The package comes with example scripts that require matplotlib.
examples/plot_taitBryanPriors.py — reproduces figure 6 of arXiv:2507.02101. Draws samples uniform in sin²θ, treats each sample as belonging to every non-e3 parameterisation in turn, transforms to e3, and overlays the resulting 1D marginals.
- To run:
python examples/plot_taitBryanPriors.py - Output:
dists_overlaid_to_standard.png
examples/plot_reweighted_marginals.py — demonstrates get_weights. Draws samples uniform in sin²θ under e3, transforms to each of the nine parameterisations, and applies importance weights. Flat weighted histograms (blue) confirm the weights are correct; orange shows the raw unweighted distribution.
- To run:
python examples/plot_reweighted_marginals.py - Output:
figures/reweighted_marginals.png
scripts/plot_parameterisation_distributions.py — overlays the sin²θ distributions of all nine parameterisations on a single figure, without reweighting, to visualise the support of each prior.
- To run:
python scripts/plot_parameterisation_distributions.py - Output:
figures/dists_overlaid.png
Citing
If you use this package in your work, please cite following paper:
- Testing T2K’s Bayesian constraints with priors in alternate parameterisations: arXiv:2507.02101.
License
GPL-3.0-or-later. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pmns_transforms-1.1.0.tar.gz.
File metadata
- Download URL: pmns_transforms-1.1.0.tar.gz
- Upload date:
- Size: 19.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0186df3c4613413626b3590d445ea1bc8781e61a39078b6d55d3c213b9111bcc
|
|
| MD5 |
12101def6fa739d4f0c2cb3bf5bb49cb
|
|
| BLAKE2b-256 |
284f145f437299349ff33541b08695c024db4b105c3402708ecd76bf5ef73803
|
File details
Details for the file pmns_transforms-1.1.0-py3-none-any.whl.
File metadata
- Download URL: pmns_transforms-1.1.0-py3-none-any.whl
- Upload date:
- Size: 13.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b6566792d95c51fe34da6e2071aef104ef60d9f69ed4e0c77152c0fa2d7b360
|
|
| MD5 |
bebf687e57a76fa2a1f579f9c31d5fd6
|
|
| BLAKE2b-256 |
a9ba5d5f34152aa1ecf76395f24586b42c28276d237c5958c79f0c7b4fb51172
|