Mueller Matrix Examples
Scott Prahl
Feb 2026
Here are examples of Mueller matrices that can be used for propagating polarized light through a system.
Linear Polarizers
Quarter Wave Plates
Half Wave Plates
Fresnel reflection/transmission
[1]:
%config InlineBackend.figure_format = 'retina'
import sys
import numpy as np
import matplotlib.pyplot as plt
if sys.platform == "emscripten":
import micropip
await micropip.install("pypolar")
from pypolar import fresnel
from pypolar import jones
from pypolar import mueller
from pypolar import visualization as vis
Linear Polarizers
Kliger Appendix B page 285
[2]:
for theta in [0, 45, 90, -45]:
print("Mueller matrix for perfect linear polarizer at angle theta=%.1f°" % theta)
L = mueller.op_linear_polarizer(np.radians(theta))
print(np.round(L, 3))
print()
Mueller matrix for perfect linear polarizer at angle theta=0.0°
[[0.5 0.5 0. 0. ]
[0.5 0.5 0. 0. ]
[0. 0. 0. 0. ]
[0. 0. 0. 0. ]]
Mueller matrix for perfect linear polarizer at angle theta=45.0°
[[0.5 0. 0.5 0. ]
[0. 0. 0. 0. ]
[0.5 0. 0.5 0. ]
[0. 0. 0. 0. ]]
Mueller matrix for perfect linear polarizer at angle theta=90.0°
[[ 0.5 -0.5 0. 0. ]
[-0.5 0.5 -0. 0. ]
[ 0. -0. 0. 0. ]
[ 0. 0. 0. 0. ]]
Mueller matrix for perfect linear polarizer at angle theta=-45.0°
[[ 0.5 0. -0.5 0. ]
[ 0. 0. -0. 0. ]
[-0.5 -0. 0.5 0. ]
[ 0. 0. 0. 0. ]]
Quarter-Wave Plates
Kliger Appendix B, page 287
[3]:
for theta in [0, 90, 45, -45]:
print("Mueller matrix for quarter-wave plate with fast axis at angle theta=", theta)
L = mueller.op_quarter_wave_plate(np.radians(theta))
print(np.round(L, 3))
print("Should be the same as")
L = mueller.op_retarder(np.radians(theta), np.pi / 2)
print(np.round(L, 3))
print()
Mueller matrix for quarter-wave plate with fast axis at angle theta= 0
[[ 1. 0. 0. 0.]
[ 0. 1. 0. -0.]
[ 0. 0. 0. 1.]
[ 0. 0. -1. 0.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 1. 0. -0.]
[ 0. 0. 0. 1.]
[ 0. 0. -1. 0.]]
Mueller matrix for quarter-wave plate with fast axis at angle theta= 90
[[ 1. 0. 0. 0.]
[ 0. 1. -0. -0.]
[ 0. -0. 0. -1.]
[ 0. 0. 1. 0.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 1. -0. -0.]
[ 0. -0. 0. -1.]
[ 0. 0. 1. 0.]]
Mueller matrix for quarter-wave plate with fast axis at angle theta= 45
[[ 1. 0. 0. 0.]
[ 0. 0. 0. -1.]
[ 0. 0. 1. 0.]
[ 0. 1. -0. 0.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 0. 0. -1.]
[ 0. 0. 1. 0.]
[ 0. 1. -0. 0.]]
Mueller matrix for quarter-wave plate with fast axis at angle theta= -45
[[ 1. 0. 0. 0.]
[ 0. 0. -0. 1.]
[ 0. -0. 1. 0.]
[ 0. -1. -0. 0.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 0. -0. 1.]
[ 0. -0. 1. 0.]
[ 0. -1. -0. 0.]]
Half-Wave Plates
Kliger Appendix B, page 286
[4]:
for theta in [0, 90, 45, -45]:
print("Mueller matrix for half-wave plate with fast axis at angle theta=", theta)
L = mueller.op_half_wave_plate(np.radians(theta))
print(np.round(L, 3))
print("Should be the same as")
L = mueller.op_retarder(np.radians(theta), np.pi)
print(np.round(L, 3))
print()
Mueller matrix for half-wave plate with fast axis at angle theta= 0
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. -1. 0.]
[ 0. 0. 0. -1.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 1. 0. -0.]
[ 0. 0. -1. 0.]
[ 0. 0. -0. -1.]]
Mueller matrix for half-wave plate with fast axis at angle theta= 90
[[ 1. 0. 0. 0.]
[ 0. 1. -0. 0.]
[ 0. -0. -1. 0.]
[ 0. 0. 0. -1.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. 1. -0. -0.]
[ 0. -0. -1. -0.]
[ 0. 0. 0. -1.]]
Mueller matrix for half-wave plate with fast axis at angle theta= 45
[[ 1. 0. 0. 0.]
[ 0. -1. 0. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 0. -1.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. -1. 0. -0.]
[ 0. 0. 1. 0.]
[ 0. 0. -0. -1.]]
Mueller matrix for half-wave plate with fast axis at angle theta= -45
[[ 1. 0. 0. 0.]
[ 0. -1. -0. 0.]
[ 0. -0. 1. 0.]
[ 0. 0. 0. -1.]]
Should be the same as
[[ 1. 0. 0. 0.]
[ 0. -1. -0. 0.]
[ 0. -0. 1. 0.]
[ 0. -0. -0. -1.]]
Fresnel Reflection/Transmission
Note that these Mueller matrices include the change in perspective needed for the reflected beam.
Normal incidence
[5]:
MR = mueller.op_fresnel_reflection(1.5, 0)
print("M_R=")
print(MR)
M_R=
[[ 0.04 0. 0. 0. ]
[ 0. 0.04 0. 0. ]
[ 0. 0. -0.04 0. ]
[ 0. 0. 0. -0.04]]
[6]:
print(fresnel.t_per_amplitude(1.5, 0))
print(fresnel.t_par_amplitude(1.5, 0))
print(fresnel.T_per(1.5, 0))
print(fresnel.T_par(1.5, 0))
MT = mueller.op_fresnel_transmission(1.5, 0)
print("M_T=")
print(MT)
0.8
0.8
0.9600000000000002
0.9600000000000002
M_T=
[[0.64 0. 0. 0. ]
[0. 0.64 0. 0. ]
[0. 0. 0.64 0. ]
[0. 0. 0. 0.64]]
Light incident at Brewster’s angle
Brewster’s angle for a dielectric material is
and reflected field parallel to the plane of incidence becomes zero.
The special case for reflection at Brewster’s angle is
[7]:
m = 1.5
thetaB = np.arctan(m)
print("theta_B = %.3f°" % np.degrees(thetaB))
MR = mueller.op_fresnel_reflection(1.5, thetaB)
print("M_R=")
print(np.round(MR, 4))
print("Matrix at Brewster's angle should be")
const = 0.5 * np.cos(2 * thetaB) ** 2
MR = const * np.array([[1, -1, 0, 0], [-1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])
print(np.round(MR, 4))
theta_B = 56.310°
M_R=
[[ 0.074 -0.074 0. 0. ]
[-0.074 0.074 0. 0. ]
[ 0. 0. -0. 0. ]
[ 0. 0. 0. -0. ]]
Matrix at Brewster's angle should be
[[ 0.074 -0.074 0. 0. ]
[-0.074 0.074 0. 0. ]
[ 0. 0. 0. 0. ]
[ 0. 0. 0. 0. ]]
Goldstein gives the following for the Mueller matrix for transmitted light incident at Brewster’s angle
[8]:
m = 1.5
thetaB = np.arctan(m)
print("Brewster's angle is %.3f°" % (np.degrees(thetaB)))
print()
MT1 = mueller.op_fresnel_transmission(m, thetaB)
print("(direct) M_T=")
print(MT1)
print()
print("At Brewster's angle the matrix should be")
a = np.sin(2 * thetaB) ** 2 + 1
b = np.sin(2 * thetaB) ** 2 - 1
c = 2 * np.sin(2 * thetaB)
MT = 0.5 * np.array([[a, b, 0, 0], [b, a, 0, 0], [0, 0, c, 0], [0, 0, 0, c]])
print(MT)
Brewster's angle is 56.310°
(direct) M_T=
[[0.41157133 0.03287311 0. 0. ]
[0.03287311 0.41157133 0. 0. ]
[0. 0. 0.41025641 0. ]
[0. 0. 0. 0.41025641]]
At Brewster's angle the matrix should be
[[ 0.9260355 -0.0739645 0. 0. ]
[-0.0739645 0.9260355 0. 0. ]
[ 0. 0. 0.92307692 0. ]
[ 0. 0. 0. 0.92307692]]
Light incident at 45° to the surface
This is the other special case where the Fresnel formulas simplify. Goldstein 2003 gives
thus
which may be off by a minus sign in the lower two diagonal elements?
[9]:
m = 1.5
thetai = np.pi / 4
MR = mueller.op_fresnel_reflection(1.5, thetai)
print("M_R=")
print(MR)
print("Matrix at 45° angle should be")
thetar = np.arcsin(np.sin(thetai) / m)
const = (1 - np.sin(2 * thetar)) / (1 + np.sin(2 * thetar)) ** 2
a = np.sin(2 * thetar)
b = -np.cos(2 * thetar)
MR = const * np.array([[1, a, 0, 0], [a, 1, 0, 0], [0, 0, b, 0], [0, 0, 0, b]])
print(MR)
M_R=
[[ 0.05023991 -0.04177345 0. 0. ]
[-0.04177345 0.05023991 0. 0. ]
[ 0. 0. -0.02791106 0. ]
[ 0. 0. 0. -0.02791106]]
Matrix at 45° angle should be
[[ 0.05023991 0.04177345 0. 0. ]
[ 0.04177345 0.05023991 0. 0. ]
[ 0. 0. -0.02791106 0. ]
[ 0. 0. 0. -0.02791106]]
Optical isolator
[10]:
A = mueller.stokes_right_circular() # incident light
B = mueller.op_linear_polarizer(np.pi / 4) # polarizer at 45°
C = mueller.op_quarter_wave_plate(0) # QWP with fast axis horizontal
D = mueller.op_mirror() # first surface mirror
E = mueller.op_quarter_wave_plate(0) # QWP still has fast axis horizontal
F = mueller.op_linear_polarizer(-np.pi / 4) # now at -45° because travelling backwards
[11]:
# net result is no light
mueller.intensity(F @ E @ D @ C @ B @ A)
[11]:
np.float64(9.37349864163661e-34)
[12]:
F @ E @ D @ C @ B @ A
[12]:
array([ 9.37349864e-34, 5.73961255e-50, -9.37349864e-34, 0.00000000e+00])
[ ]: