Jones API¶
jones
¶
Jones calculus for coherent (amplitude-level) polarization analysis.
Where :class:~hyperbolic_optics.mueller.Mueller works with Stokes vectors and
4×4 real Mueller matrices (intensity level, discards absolute phase and can model
depolarization), this module works with the 2×2 complex Jones matrix and
2-component Jones vectors — the amplitude-level description that preserves phase
and is the natural tool for fully-polarized, coherent light.
A structure's reflection coefficients are already a Jones matrix,
J = [[r_pp, r_ps],
[r_sp, r_ss]] (rows = output p/s, columns = input p/s),
so :class:Jones builds it directly, applies ideal 2×2 optical components
(polarizer, wave plates, rotator) and an incident Jones vector, and exposes the
output state plus its Stokes parameters / polarization ellipse. to_mueller
bridges to the Mueller formalism (reusing :meth:Mueller._mueller_from_jones) so
the two stay consistent.
Note on cascading: ideal components (polarizers, wave plates) are
angle-independent, so they compose with a sample by simple matrix multiplication
and broadcast freely over any scenario sweep. Cascading two angle-dependent
structures is only physical when they share the conserved in-plane wavevector
kx (and frequency) — composing independent incident-angle sweeps (especially
with different prisms) is not meaningful, since kx differs point-to-point.
Classes:
-
Jones–Jones-calculus analyzer for coherent polarization (amplitude level).
Functions:
-
compose_jones–Compose optical elements in series at the Jones (amplitude) level.
Jones
¶
Jones-calculus analyzer for coherent polarization (amplitude level).
Mirrors :class:~hyperbolic_optics.mueller.Mueller but with 2×2 complex Jones
matrices and 2-vectors, preserving phase. Batched over the scenario's
presentation shape (the 2×2 component matrices broadcast against the sample's
[..., 2, 2] Jones matrix, exactly as Mueller's 4×4 components do).
Examples:
>>> structure = Structure()
>>> structure.execute(payload)
>>> jones = Jones(structure)
>>> jones.set_incident_polarization("linear", angle=0) # p-polarized
>>> jones.add_optical_component("sample")
>>> jones.add_optical_component("linear_polarizer", 90) # crossed analyzer
>>> intensity = jones.get_intensity()
Initialize from an executed structure.
Parameters:
-
structure(Structure) –A :class:
Structureon whichexecutehas run.
Methods:
-
set_incident_polarization–Set the incident Jones vector
[E_p, E_s]. -
rotator–Rotation matrix by
angledegrees in the (p, s) plane. -
linear_polarizer–Ideal linear polarizer with transmission axis at
angledegrees. -
quarter_wave_plate–Quarter-wave plate with fast axis at
angledegrees (π/2 retardance). -
half_wave_plate–Half-wave plate with fast axis at
angledegrees (π retardance). -
calculate_jones_matrix–Build the sample's 2×2 Jones matrix from its r (or t) coefficients.
-
add_optical_component–Append an optical element to the path (applied left-to-right on the beam).
-
calculate_jones_vector–Propagate the incident Jones vector through the component chain.
-
get_intensity–Output intensity
|E_p|² + |E_s|²(presentation shape). -
get_stokes_parameters–Stokes parameters of the output Jones vector.
-
get_ellipse–Polarization ellipse of the output:
azimuthψ andellipticityχ (rad). -
eigenpolarizations–Eigenpolarizations of the sample's Jones matrix (states with no conversion).
-
to_mueller–Mueller matrix of the sample, bridged from its Jones matrix.
-
ellipsometric_parameters–Generalized ellipsometric angles from the reflection coefficients.
-
find_exceptional_points–Locate exceptional points across the scenario sweep.
Source code in hyperbolic_optics/jones.py
set_incident_polarization
¶
Set the incident Jones vector [E_p, E_s].
Parameters:
-
polarization_type(str) –"linear"(angledeg, 0 = p, 90 = s),"circular"(handedness"right"/"left"), or"elliptical"(alphadeg azimuth,ellipticitydeg).
Raises:
-
ValueError–If
polarization_typeis unknown.
Source code in hyperbolic_optics/jones.py
rotator
staticmethod
¶
Rotation matrix by angle degrees in the (p, s) plane.
linear_polarizer
¶
Ideal linear polarizer with transmission axis at angle degrees.
Source code in hyperbolic_optics/jones.py
quarter_wave_plate
¶
Quarter-wave plate with fast axis at angle degrees (π/2 retardance).
Source code in hyperbolic_optics/jones.py
half_wave_plate
¶
Half-wave plate with fast axis at angle degrees (π retardance).
Source code in hyperbolic_optics/jones.py
calculate_jones_matrix
¶
Build the sample's 2×2 Jones matrix from its r (or t) coefficients.
Parameters:
-
transmission(bool, default:False) –If True, use the transmission coefficients
t_*(computing them viaStructure.calculate_transmissivityif needed) instead of the reflection coefficients.
Returns:
-
ndarray–The Jones matrix
[..., 2, 2]in the scenario's presentation shape.
Source code in hyperbolic_optics/jones.py
add_optical_component
¶
Append an optical element to the path (applied left-to-right on the beam).
Parameters:
-
component_type(str) –"sample"(the structure's reflection Jones matrix),"sample_transmission","linear_polarizer","quarter_wave_plate","half_wave_plate"or"rotator". -
*args(Any, default:()) –Angle (degrees) for the ideal components.
Raises:
-
ValueError–If
component_typeis unknown.
Source code in hyperbolic_optics/jones.py
calculate_jones_vector
¶
Propagate the incident Jones vector through the component chain.
Returns:
-
ndarray–Output Jones vector
[..., 2]=[E_p, E_s](presentation shape).
Source code in hyperbolic_optics/jones.py
get_intensity
¶
Output intensity |E_p|² + |E_s|² (presentation shape).
get_stokes_parameters
¶
Stokes parameters of the output Jones vector.
Convention (e^{-iωt}, p↔x, s↔y): S0=|Ep|²+|Es|², S1=|Ep|²−|Es|²,
S2=2Re(Ep Es*), S3=−2Im(Ep Es*) — consistent with
:meth:FieldProfile.stokes_from_field_profile and :class:Mueller.
Source code in hyperbolic_optics/jones.py
get_ellipse
¶
Polarization ellipse of the output: azimuth ψ and ellipticity χ (rad).
Source code in hyperbolic_optics/jones.py
eigenpolarizations
¶
Eigenpolarizations of the sample's Jones matrix (states with no conversion).
An eigenvector v of the Jones matrix satisfies J·v = λ·v: it reflects
(or transmits) into the same polarization state, scaled by the complex
eigenvalue λ (amplitude + phase). These are the polarization states that
undergo no polarization conversion.
Because a lossy/anisotropic reflection Jones matrix is generally
non-normal, the two eigenpolarizations are not orthogonal and can
coalesce at an exceptional point (EP), where the matrix becomes
defective (non-diagonalizable). Two EP diagnostics are returned: the
discriminant D = ((J_pp − J_ss)/2)² + J_ps·J_sp (|D| → 0 at an EP,
since λ± = tr/2 ± √D coalesce) and the eigenvector_overlap
|⟨v₀|v₁⟩| of the unit eigenvectors (→ 1 at an EP; 0 when orthogonal).
Parameters:
-
transmission(bool, default:False) –Use the transmission Jones matrix instead of reflection.
Returns:
-
dict[str, ndarray]–Dict with
eigenvalues[..., 2],eigenpolarizations -
dict[str, ndarray]–[..., 2, 2](columns are the unit eigenvectors),discriminant -
dict[str, ndarray]–[...], andeigenvector_overlap[...].
Source code in hyperbolic_optics/jones.py
to_mueller
¶
Mueller matrix of the sample, bridged from its Jones matrix.
Reuses :meth:Mueller._mueller_from_jones, so the Jones and Mueller
descriptions of the same structure are guaranteed consistent.
Source code in hyperbolic_optics/jones.py
ellipsometric_parameters
¶
Generalized ellipsometric angles from the reflection coefficients.
The standard ratio rho = r_pp / r_ss = tan(Psi)·e^{iΔ} gives Psi
(the amplitude-ratio angle, degrees, in [0, 90]) and Delta (the
phase difference, degrees, in (-180, 180]). For anisotropic samples the
cross-polarization ratios r_ps/r_ss and r_sp/r_pp are reported as
the generalized angles Psi_ps/Delta_ps and Psi_sp/Delta_sp.
Returns:
-
dict[str, ndarray]–Dict of
Psi, Delta, Psi_ps, Delta_ps, Psi_sp, Delta_sp(degrees), -
dict[str, ndarray]–each in the scenario's presentation shape.
Source code in hyperbolic_optics/jones.py
find_exceptional_points
¶
Locate exceptional points across the scenario sweep.
At an exceptional point the two eigenpolarizations of the (non-normal)
Jones matrix coalesce: the eigenvector overlap approaches 1 and the
discriminant approaches 0. This scans :meth:eigenpolarizations over the
batch and returns those indicators plus the strongest candidate.
Parameters:
-
overlap_threshold(float, default:0.99) –Eigenvector-overlap value above which a point is flagged as near an exceptional point.
Returns:
-
dict[str, ndarray]–Dict with the full
overlapanddiscriminantmaps (presentation -
dict[str, ndarray]–shape), a boolean
near_epmask, andep_index-- the (unravelled) -
dict[str, ndarray]–position of minimum
|discriminant|(the strongest EP candidate).
Source code in hyperbolic_optics/jones.py
compose_jones
¶
Compose optical elements in series at the Jones (amplitude) level.
Multiplies the 2×2 Jones matrices of the elements in beam order (the first
argument is the element the light meets first), so the returned matrix is
J_last · … · J_first. Heterogeneous scenario sweeps broadcast, so a fixed
sample composes with a swept one (and ideal components broadcast over any
sweep).
Each element is either:
- a :class:
Structure— its reflection Jones matrix[[r_pp, r_ps], [r_sp, r_ss]]is used; or - a 2×2 array — an ideal component (polarizer / wave plate / rotator) or any
precomputed Jones matrix, e.g.
Jones(s).calculate_jones_matrix(transmission=True).
Physics guard: ideal components are angle-independent and compose freely, but
two angle/frequency-dependent structures are only physical when they share the
conserved in-plane wavevector kx and frequency. This raises if two
:class:Structure elements disagree on k_x or k_0 (their sample
azimuth/thickness axes may still differ and broadcast).
Parameters:
-
*elements(Structure | ndarray, default:()) –The optical elements in beam order.
Returns:
-
ndarray–The composed Jones matrix
[..., 2, 2].
Raises:
-
ValueError–If no elements are given, or two structures have incompatible
kx/ frequency grids.
Note
Both structures must currently resolve to broadcast-compatible
presentation shapes (e.g. a scalar Simple sample with a swept one).
Composing two different multi-axis sweeps whose squeezed shapes do not
align is not yet supported (it needs canonical-axis composition).