Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pmns_transforms-1.1.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pmns_transforms-1.1.0-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

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

Hashes for pmns_transforms-1.1.0.tar.gz
Algorithm Hash digest
SHA256 0186df3c4613413626b3590d445ea1bc8781e61a39078b6d55d3c213b9111bcc
MD5 12101def6fa739d4f0c2cb3bf5bb49cb
BLAKE2b-256 284f145f437299349ff33541b08695c024db4b105c3402708ecd76bf5ef73803

See more details on using hashes here.

File details

Details for the file pmns_transforms-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pmns_transforms-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b6566792d95c51fe34da6e2071aef104ef60d9f69ed4e0c77152c0fa2d7b360
MD5 bebf687e57a76fa2a1f579f9c31d5fd6
BLAKE2b-256 a9ba5d5f34152aa1ecf76395f24586b42c28276d237c5958c79f0c7b4fb51172

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page