Mueller Matrices
Scott Prahl
April 2020
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]:
import numpy as np
import matplotlib.pyplot as plt
import pypolar.fresnel as fresnel
import pypolar.jones as jones
import pypolar.mueller as mueller
import pypolar.visualization as vis
np.set_printoptions(suppress=True) # print 1e-16 as zero
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(L, "\n")
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(L,"\nShould be the same as")
L = mueller.op_retarder(np.radians(theta), np.pi/2)
print(L,"\n")
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(L,"\nShould be the same as")
L = mueller.op_retarder(np.radians(theta), np.pi)
print(L,"\n")
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.96 0. 0. 0. ]
[0. 0.96 0. 0. ]
[0. 0. 0.96 0. ]
[0. 0. 0. 0.96]]
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(np.degrees(thetaB))
MR = mueller.op_fresnel_reflection(1.5,thetaB)
print('M_R=')
print(MR)
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(MR)
56.309932474020215
M_R=
[[ 0.0739645 0.0739645 0. 0. ]
[ 0.0739645 0.0739645 0. 0. ]
[ 0. 0. -0. 0. ]
[ 0. 0. 0. -0. ]]
Matrix at Brewster's angle should be
[[0.0739645 0.0739645 0. 0. ]
[0.0739645 0.0739645 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.9260355 -0.0739645 0. 0. ]
[-0.0739645 0.9260355 0. 0. ]
[ 0. 0. 0.92307692 0. ]
[ 0. 0. 0. 0.92307692]]
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]]
Example 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]:
0.0
[ ]: