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

\[\begin{split}M_R(0) = {(n-1)^2\over(n+1)^2} \left[ \begin{array}{cccc} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & -1& 0\\ 0 & 0 & 0 &-1\\ \end{array}\right] \qquad\mbox{and}\qquad M_T(0) = {4n\over(n+1)^2} \left[ \begin{array}{cccc} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1& 0\\ 0 & 0 & 0 &1\\ \end{array}\right]\end{split}\]
[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

\[\tan\theta_B = m\]

and reflected field parallel to the plane of incidence becomes zero.

The special case for reflection at Brewster’s angle is

\[\begin{split}M_R(\theta_B) = {1\over2}\cos^2 2\theta_B \left[ \begin{array}{cccc} 1 & 1 & 0 & 0\\ 1 & 1 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ \end{array}\right]\end{split}\]
[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

\[\begin{split}M_T(\theta_B) = {1\over2} \left[ \begin{array}{cccc} \sin^22\theta_B+1 & \sin^22\theta_B-1 & 0 & 0\\ \sin^22\theta_B-1 & \sin^22\theta_B+1 & 0 & 0\\ 0 & 0 & 2\sin2\theta_B& 0\\ 0 & 0 & 0 &2\sin2\theta_B\\ \end{array}\right]\end{split}\]
[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

\[\theta_r = 45^\circ\]

thus

\[\begin{split}M_R(\theta_r) = {1-\sin2\theta_r\over(1+\sin2\theta_r)^2} \left[ \begin{array}{cccc} 1 & \sin2\theta_r & 0 & 0\\ \sin2\theta_r & 1 & 0 & 0\\ 0 & 0 & -\cos2\theta_r & 0\\ 0 & 0 & 0 & -\cos2\theta_r\\ \end{array}\right]\end{split}\]

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
[ ]: