Mueller API¶
mueller
¶
Mueller-matrix calculus for polarization analysis.
Mueller matrices are real 4×4 matrices that transform Stokes vectors,
S_out = M · S_in, and derive from a Jones matrix F via M = A · F · A⁻¹.
The :class:Mueller class builds them for anisotropic samples and ideal
components (polarizers, wave plates) and combines components in sequence.
Reference
Chipman, Lam & Young, "Polarized Light and Optical Systems" (2018)
Classes:
-
Mueller–Builds and applies Mueller matrices for a :class:
Structure's reflection.
Mueller
¶
Builds and applies Mueller matrices for a :class:Structure's reflection.
Handles arbitrary incident polarization (linear/circular/elliptical) and sequential optical components.
Attributes:
-
structure–The Structure object containing reflection coefficients
-
mueller_matrix–4×4 Mueller matrix for the sample
-
stokes_parameters–Output Stokes parameters
-
incident_stokes–Incident polarization state [S0, S1, S2, S3]
-
optical_components–List of Mueller matrices for optical elements
Examples:
Analyzing p-polarized reflection:
>>> structure = Structure()
>>> structure.execute(payload)
>>> mueller = Mueller(structure)
>>> mueller.set_incident_polarization('linear', angle=0)
>>> mueller.add_optical_component('anisotropic_sample')
>>> params = mueller.get_all_parameters()
>>> print(f"Reflectance: {params['S0']:.4f}")
>>> print(f"DOP: {params['DOP']:.4f}")
Crossed polarizer configuration:
>>> mueller = Mueller(structure)
>>> mueller.set_incident_polarization('linear', angle=0)
>>> mueller.add_optical_component('linear_polarizer', 0)
>>> mueller.add_optical_component('anisotropic_sample')
>>> mueller.add_optical_component('linear_polarizer', 90)
>>> extinction_ratio = mueller.get_reflectivity()
Converting linear to circular polarization:
>>> mueller = Mueller(structure)
>>> mueller.set_incident_polarization('linear', angle=45)
>>> mueller.add_optical_component('quarter_wave_plate', 45)
>>> mueller.add_optical_component('anisotropic_sample')
>>> stokes = mueller.get_stokes_parameters()
>>> circularity = abs(stokes['S3'] / stokes['S0'])
>>> print(f"Circular component: {circularity:.2%}")
Initialize Mueller matrix analyzer for polarization calculations.
Parameters:
-
structure(Structure) –The Structure object containing reflection coefficients
-
debug(bool, default:False) –Enable detailed debug output for troubleshooting
Example
structure = Structure() structure.execute(payload) mueller = Mueller(structure) mueller.set_incident_polarization('linear', angle=45) mueller.add_optical_component('anisotropic_sample')
Methods:
-
set_incident_polarization–Set the incident polarization state using Stokes parameters.
-
linear_polarizer–Create Mueller matrix for ideal linear polarizer.
-
quarter_wave_plate–Create Mueller matrix for quarter-wave plate (QWP).
-
half_wave_plate–Create Mueller matrix for half-wave plate (HWP).
-
calculate_mueller_matrix–Calculate Mueller matrix from reflection coefficients.
-
calculate_transmission_mueller_matrix–Mueller matrix of the transmitted light, from the t-coefficients.
-
decompose–Lu-Chipman polar decomposition of the Mueller matrix.
-
add_optical_component–Add optical component to the propagation path.
-
calculate_stokes_parameters–Calculate output Stokes parameters after all optical components.
-
get_reflectivity–Get total reflectance (S0 Stokes parameter).
-
get_degree_of_polarisation–Calculate degree of polarization (DOP).
-
get_ellipticity–Calculate ellipticity angle of polarization ellipse.
-
get_azimuth–Calculate azimuth angle of polarization ellipse major axis.
-
get_stokes_parameters–Get all four Stokes parameters.
-
get_polarisation_parameters–Get derived polarization properties.
-
get_all_parameters–Get comprehensive set of all Stokes and polarization parameters.
-
reset–Reset Mueller object to initial state.
Source code in hyperbolic_optics/mueller.py
set_incident_polarization
¶
Set the incident polarization state using Stokes parameters.
Parameters:
-
polarization_type(str) –Type of polarization ('linear', 'circular', 'elliptical')
-
**kwargs(Any, default:{}) –Additional arguments depending on type: - linear: angle (float) - polarization angle in degrees - circular: handedness (str) - 'right' or 'left' - elliptical: alpha (float) - azimuth in degrees, ellipticity (float) - ellipticity angle in degrees
Raises:
-
ValueError–If polarization_type is not recognized
Example
mueller.set_incident_polarization('linear', angle=0) # p-polarized mueller.set_incident_polarization('circular', handedness='right') mueller.set_incident_polarization('elliptical', alpha=30, ellipticity=20)
Source code in hyperbolic_optics/mueller.py
linear_polarizer
¶
Create Mueller matrix for ideal linear polarizer.
Parameters:
-
angle(float) –Polarizer transmission axis angle in degrees
Returns:
-
ndarray–4×4 Mueller matrix for linear polarizer
Note
Ideal polarizer fully transmits light along transmission axis and fully blocks light perpendicular to it.
Source code in hyperbolic_optics/mueller.py
quarter_wave_plate
¶
Create Mueller matrix for quarter-wave plate (QWP).
Parameters:
-
angle(float) –Fast axis orientation angle in degrees
Returns:
-
ndarray–4×4 Mueller matrix for QWP
Note
QWP introduces π/2 phase shift between fast and slow axes. Can convert linear to circular polarization and vice versa.
Source code in hyperbolic_optics/mueller.py
half_wave_plate
¶
Create Mueller matrix for half-wave plate (HWP).
Parameters:
-
angle(float) –Fast axis orientation angle in degrees
Returns:
-
ndarray–4×4 Mueller matrix for HWP
Note
HWP introduces π phase shift, effectively rotating linear polarization by 2θ where θ is the plate angle.
Source code in hyperbolic_optics/mueller.py
calculate_mueller_matrix
¶
Calculate Mueller matrix from reflection coefficients.
Converts the complex 2×2 Jones matrix to a real 4×4 Mueller matrix using the transformation: M = A·F·A⁻¹ where F is formed from r_pp, r_ss, r_ps, r_sp.
Note
The Mueller matrix fully describes how the sample transforms arbitrary incident polarization states to reflected states.
Source code in hyperbolic_optics/mueller.py
calculate_transmission_mueller_matrix
¶
Mueller matrix of the transmitted light, from the t-coefficients.
Builds M = A·F·A⁻¹ from t_pp, t_ps, t_sp, t_ss (computing them via
Structure.calculate_transmissivity if needed). This describes the
polarization transformation on transmission and is set as
self.mueller_matrix so the usual Stokes/DOP/ellipse helpers apply.
Important
This treats |t|² as transmitted intensity, which equals the
physical power transmittance only for a symmetric system where the
prism and substrate permittivities are equal. For transmission into a
lower-index medium (e.g. air) it breaks down in the
evanescent / total-internal-reflection regime — the impedance and
cos θ factors no longer cancel and an evanescent wave carries no real
power despite a non-zero t. Use
:meth:hyperbolic_optics.fields.FieldProfile.transmittance (Poynting
flux) for correct power transmittance in the general case; this Mueller
matrix is for the polarization transformation of a transmitting,
index-matched stack.
Source code in hyperbolic_optics/mueller.py
decompose
¶
Lu-Chipman polar decomposition of the Mueller matrix.
Factorizes the (normalized) Mueller matrix as M = M_Δ · M_R · M_D
(depolarizer · retarder · diattenuator; Lu & Chipman, J. Opt. Soc. Am. A
13, 1106 (1996)) and extracts the physical polarization metrics. Uses
self.mueller_matrix (computed via :meth:calculate_mueller_matrix if
needed), batched over the scenario presentation shape.
Returns:
-
dict[str, ndarray]–Dict with scalar-field metrics
diattenuation,polarizance, -
dict[str, ndarray]–retardance(radians),depolarization(0 = none, 1 = total) and -
dict[str, ndarray]–transmittance(theM₀₀factor), plus the normalized component -
dict[str, ndarray]–matrices
diattenuator,retarder,depolarizer([..., 4, 4]).
Source code in hyperbolic_optics/mueller.py
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | |
add_optical_component
¶
Add optical component to the propagation path.
Parameters:
-
component_type(str) –Type of component ('anisotropic_sample', 'linear_polarizer', 'quarter_wave_plate', 'half_wave_plate')
-
*args(Any, default:()) –Component-specific parameters (e.g., angle for polarizers)
Raises:
-
ValueError–If component type is not recognized or anisotropic sample is added more than once
Example
mueller.add_optical_component('linear_polarizer', 0) mueller.add_optical_component('anisotropic_sample') mueller.add_optical_component('linear_polarizer', 90)
Source code in hyperbolic_optics/mueller.py
calculate_stokes_parameters
¶
Calculate output Stokes parameters after all optical components.
Propagates the incident Stokes vector through all added optical components by sequential Mueller matrix multiplication.
Returns:
-
ndarray–Output Stokes vector [S0, S1, S2, S3] with shape matching scenario
Note
S0 = total intensity (reflectance) S1 = horizontal vs vertical linear polarization S2 = +45° vs -45° linear polarization S3 = right vs left circular polarization
Source code in hyperbolic_optics/mueller.py
get_reflectivity
¶
Get total reflectance (S0 Stokes parameter).
Returns:
-
ndarray–Reflectance array with shape matching scenario type
Note
Automatically calculates Stokes parameters if not already computed.
Source code in hyperbolic_optics/mueller.py
get_degree_of_polarisation
¶
Calculate degree of polarization (DOP).
Returns:
-
ndarray–DOP array with values clipped to [0, 1]
Note
DOP = √(S1² + S2² + S3²) / S0 DOP = 1: fully polarized DOP = 0: unpolarized (random) 0 < DOP < 1: partially polarized
Source code in hyperbolic_optics/mueller.py
get_ellipticity
¶
Calculate ellipticity angle of polarization ellipse.
Returns:
-
ndarray–Ellipticity angle in radians (-π/4 to π/4)
Note
Ellipticity = 0: linear polarization Ellipticity = ±π/4: circular polarization Intermediate values: elliptical polarization
Source code in hyperbolic_optics/mueller.py
get_azimuth
¶
Calculate azimuth angle of polarization ellipse major axis.
Returns:
-
ndarray–Azimuth angle in radians
Note
Defines orientation of the polarization ellipse in the plane perpendicular to propagation direction.
Source code in hyperbolic_optics/mueller.py
get_stokes_parameters
¶
Get all four Stokes parameters.
Returns:
-
dict[str, ndarray]–Dictionary with keys 'S0', 'S1', 'S2', 'S3' containing parameter arrays
Note
Automatically calculates if not already computed.
Source code in hyperbolic_optics/mueller.py
get_polarisation_parameters
¶
Get derived polarization properties.
Returns:
-
dict[str, ndarray]–Dictionary with 'DOP', 'Ellipticity', 'Azimuth' arrays
Source code in hyperbolic_optics/mueller.py
get_all_parameters
¶
Get comprehensive set of all Stokes and polarization parameters.
Returns:
-
dict[str, ndarray]–Dictionary containing S0, S1, S2, S3, DOP, Ellipticity, Azimuth
Example
params = mueller.get_all_parameters() print(f"Reflectance: {params['S0'].mean():.3f}") print(f"Average DOP: {params['DOP'].mean():.3f}")
Source code in hyperbolic_optics/mueller.py
reset
¶
Reset Mueller object to initial state.
Clears all calculated matrices, Stokes parameters, optical components, and resets incident polarization to unpolarized state.
Note
Call this before setting up a new calculation sequence.