pypolar.fresnel

Useful functions for calculating light interaction at planar boundaries.

The underlying assumptions are that there a two semi-infinite media with a planar interface. For convenience, assume the light is incident from the top. The upper medium is characterized by a purely real index of refraction n_i which has a default value of 1. The lower medium is characterized by a complex index of refraction m = n - n * kappa * 1j. Note that pypolar assumes the sign of the imaginary part of the index of refraction is negative.

The Fresnel equations assume that the electric field has been decomposed into fields relative to the plane of incidence (a plane defined by the incoming light direction and the normal to the surface).

The incidence angle is measured from the normal to the surface and is measured in radians.

To Do::
  • Make sure routines work for arrays of m or of theta_i

  • fail for positive imaginary refractive indices

  • fail for out-of-range angles to catch degrees/radians error

Scott Prahl Apr 2021

pypolar.fresnel.R_par(m, theta_i, n_i=1, deg=False)[source]

Reflected fraction of parallel-polarized optical power by an interface.

The reflected fraction of incident power (or flux) assuming that the electric field of the incident light is polarized parallel (p) to the plane of incidence (transverse magnetic or TM electric field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

reflected fraction of parallel-polarized irradiance [-]

pypolar.fresnel.R_per(m, theta_i, n_i=1, deg=False)[source]

Return the fraction of perpendicular-polarized optical power reflectedby an interface.

The fraction of the incident power (or flux) reflected at the interface between two semi-infinite media. The incident light is assumed to be polarized perpendicular (s, or senkrecht) to the plane of incidence (transverse electric or TE field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

reflected fraction of perpendicular-polarized irradiance [-]

pypolar.fresnel.R_unpolarized(m, theta_i, n_i=1, deg=False)[source]

Fraction of unpolarized light that is reflected.

Calculate reflection fraction of incident power (or flux) assuming that the incident light is unpolarized

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

fraction of unpolarized irradiance reflected [-]

pypolar.fresnel.T_par(m, theta_i, n_i=1, deg=False)[source]

Return the transmitted fraction of parallel-polarized optical power through an interface.

The transmitted fraction of incident power (or flux) assuming that the electric field of the incident light is polarized parallel (p) to the plane of incidence (transverse magnetic or TM electric field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

transmitted fraction of parallel-polarized irradiance [-]

pypolar.fresnel.T_per(m, theta_i, n_i=1, deg=False)[source]

Return the transmitted fraction of perpendicular-polarized optical power through an interface.

The transmitted fraction of the incident power (or flux) through the interface between two semi-infinite media. The incident light is assumed to be polarized perpendicular (s, or senkrecht) to the plane of incidence (transverse electric or TE field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

transmitted fraction of perpendicular-polarized irradiance [-]

pypolar.fresnel.T_unpolarized(m, theta_i, n_i=1, deg=False)[source]

Fraction of unpolarized light that is transmitted.

Calculate transmitted fraction of incident power (or flux) assuming that the incident light is unpolarized

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

fraction of unpolarized irradiance transmitted [-]

pypolar.fresnel.brewster(m, n_i=1, deg=False)[source]

Brewster’s angle for an interface.

Parameters:
  • m – complex index of refraction of medium [-]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

Brewster’s angle from normal to surface [radians/degrees]

pypolar.fresnel.critical(m, n_i=1, deg=False)[source]

Critical angle for total internal reflection at interface.

Parameters:
  • m – complex index of refraction of medium [-]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

critical angle from normal to surface [radians/degrees]

pypolar.fresnel.r_par_amplitude(m, theta_i, n_i=1, deg=False)[source]

Reflected fraction of parallel-polarized field at an interface.

This is the fraction of the incident electric field reflected at the interface between two semi-infinite media. The incident field is assumed to be polarized parallel (p) to the plane of incidence (transverse magnetic or TM field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

reflected fraction of parallel field [-]

pypolar.fresnel.r_per_amplitude(m, theta_i, n_i=1, deg=False)[source]

Reflected fraction of perpendicular-polarized field at an interface.

This is the fraction of the incident electric field reflected at the interface between two semi-infinite media. The incident field is assumed to be polarized perpendicular (s, or senkrecht) to the plane of incidence (transverse electric or TE field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

reflected fraction of perpendicular field [-]

pypolar.fresnel.t_par_amplitude(m, theta_i, n_i=1, deg=False)[source]

Find the transmitted fraction of parallel-polarized field through an interface.

This is the fraction of the incident electric field transmitted through the interface between two semi-infinite media. The incident field is assumed to be polarized parallel (p) to the plane of incidence (transverse magnetic or TM field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

transmitted fraction of parallel field [-]

pypolar.fresnel.t_per_amplitude(m, theta_i, n_i=1, deg=False)[source]

Return the transmitted fraction of perpendicular-polarized field through an interface.

This is the fraction of the incident electric field transmitted through the interface between two semi-infinite media. The incident field is assumed to be polarized perpendicular (s, or senkrecht) to the plane of incidence (transverse electric or TE field).

The index of refraction for medium of the incoming field defaults to 1, but can be set any real value. The medium of the outgoing field is characterized by an index of refraction that may be complex.

Parameters:
  • m – complex index of refraction of medium [-]

  • theta_i – incidence angle from normal [radians/degrees]

  • n_i – real refractive index of incident medium [-]

  • deg – theta_i is in degrees [True/False]

Returns:

transmitted fraction of perpendicular field [-]

pypolar.sym_fresnel

Useful basic routines for managing symbolic Fresnel reflection.

To Do
  • tests and documentation

Scott Prahl Apr 2019

pypolar.sym_fresnel.R_par(m, theta_i)[source]

Fraction of parallel-polarized light that is reflected (R_p).

Calculate reflected fraction of incident power (or flux) assuming that the E-field of the incident light is parallel to the plane of incidence

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

reflected power [-]

pypolar.sym_fresnel.R_per(m, theta_i)[source]

Fraction of perpendicular-polarized light that is reflected (R_s).

Calculate reflected fraction of incident power (or flux) assuming that the E-field of the incident light is perpendicular to the plane of incidence

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

reflected irradiance [-]

pypolar.sym_fresnel.R_unpolarized(m, theta_i)[source]

Fraction of unpolarized light that is reflected.

Calculate reflection fraction of incident power (or flux) assuming that the incident light is unpolarized

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

reflected irradiance [-]

pypolar.sym_fresnel.T_par(m, theta_i)[source]

Fraction of parallel-polarized light that is transmitted (T_p).

Calculate transmitted fraction of incident power (or flux) assuming that the E-field of the incident light is parallel to the plane of incidence

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

transmitted irradiance [-]

pypolar.sym_fresnel.T_per(m, theta_i)[source]

Fraction of perpendicular-polarized light that is transmitted (T_s).

Calculate transmitted fraction of incident power (or flux) assuming that the E-field of the incident light is perpendicular to the plane of incidence

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

transmitted field amplitude [-]

pypolar.sym_fresnel.T_unpolarized(m, theta_i)[source]

Fraction of unpolarized light that is transmitted.

Calculate transmitted fraction of incident power (or flux) assuming that the incident light is unpolarized

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

reflected irradiance [-]

pypolar.sym_fresnel.ellipsometry_index(rho, theta_i)[source]

Calculate the index of refraction for an isotropic sample.

Parameters:
  • rho – r_par_amplitude/r_per_amplitude [-]

  • theta_i – incidence angle from normal [radians]

Returns:

complex index of refraction [-]

pypolar.sym_fresnel.ellipsometry_rho(m, theta_i)[source]

Calculate the ellipsometer parameter rho.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

ellipsometer parameter rho [-]

pypolar.sym_fresnel.r_par_amplitude(m, theta_i)[source]

Calculate the reflected amplitude for parallel polarized light.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – angle from normal to surface [radians]

Returns:

reflected fraction of parallel field [-]

pypolar.sym_fresnel.r_per_amplitude(m, theta_i)[source]

Calculate the reflected amplitude for perpendicular polarized light.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

reflected fraction of perpendicular field [-]

pypolar.sym_fresnel.t_par_amplitude(m, theta_i)[source]

Calculate the transmitted amplitude for parallel polarized light.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

transmitted fraction of parallel field [-]

pypolar.sym_fresnel.t_per_amplitude(m, theta_i)[source]

Calculate the transmitted amplitude for perpendicular polarized light.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians]

Returns:

transmitted fraction of perpendicular field [-]

pypolar.jones

Useful routines for managing polarization with the Jones calculus.

The routines are broken into four broad categories: creating Jones vectors, creating Jones Matrices, interpreting Jones Vectors, and converting to the Mueller / Stokes matrix calculus.

Creating Jones vectors for specific polarization states:

* field_linear(angle)
* field_left_circular()
* field_right_circular()
* field_horizontal()
* field_vertical()
* field_ellipsometry(tanpsi, Delta)
* field_elliptical(azimuth, elliptic_angle)

Creating Jones Matrices for polarizing elements:

* op_linear_polarizer(angle)
* op_retarder(fast_axis_angle, retardance)
* op_attenuator(optical_density)
* op_mirror()
* op_rotation(angle)
* op_quarter_wave_plate(fast_axis_angle)
* op_half_wave_plate(fast_axis_angle)
* op_fresnel_reflection(index_of_refraction, angle)
* op_fresnel_transmission(index_of_refraction, angle)

Interpreting the polarization state:

* use_alternate_convention(boolean)
* interpret(jones_vector)
* intensity(jones_vector)
* phase(jones_vector)
* ellipse_azimuth(jones_vector)
* ellipse_axes(jones_vector)
* ellipticity(jones_vector)
* ellipticity_angle(jones_vector)
* amplitude_ratio(jones_vector)
* amplitude_ratio_angle(jones_vector)
* polarization_variable(jones_vector)

Converting to Mueller formalism:

* jones_op_to_mueller_op(jones_matrix)
* jones_to_stokes(jones_vector)
To Do::
  • modify interpret() when phase difference differs by more than 2pi

  • improve interpret() to give angle for elliptical polarization

  • test everything with non - unity amplitudes

  • finish normalize

pypolar.jones.amplitude_ratio(J)[source]

Return the ratio of electric fields.

This is the amplitude of the vibrations along x measured relative to the amplitude along y.

pypolar.jones.amplitude_ratio_angle(J)[source]

Return the ratio of electric fields.

The tangent of this angle is the ratio of electric fields in the y and x directions.

pypolar.jones.ellipse_axes(J)[source]

Return the semi - major and semi - minor radii of the ellipse.

Twice these values will be the semi - major or semi - minor diameters.

pypolar.jones.ellipse_azimuth(J)[source]

Return the angle between the major semi - axis and the x - axis.

The polarization ellipse is rotated by this angle (called the azimuth) relative to the laboratory frame.

pypolar.jones.ellipticity(J)[source]

Return the ellipticity of the polarization ellipse.

This is the ratio of semi - minor to semi - major radii. The ellipticity is a measure of the fatness of the ellipse. The ellipticity can be defined to always be positive. However negative values can be used to indicate left - handed polarization. Thus the ellipticity will range from -1 to 0 to 1 as light moves from LCP to Linear Polarization to RCP.

pypolar.jones.ellipticity_angle(J)[source]

Return the ellipticity angle of the polarization ellipse.

The tangent of this angle is the ratio of semi - minor:semi - major radii. It is between -pi / 4 ≤ angle ≤ pi / 4. Positive values are for right–handed ellipticity. Negative values for left - handed ellipticity.

pypolar.jones.field_ellipsometry(tanpsi, Delta)[source]

Jones vector for using ellipometer parameters.

This creates a Jones vector for the specific set of ellipsometry parameters tanpsi and Delta. See Fujiwara table 3.1 for example

Parameters:
  • tanpsi – abs(E_x / E_y) [-]

  • Delta – angle(E_x) - angle(E_y) [radians]

Returns:

Jones vector with specified characteristics

pypolar.jones.field_elliptical(azimuth, elliptic_angle, phi_x=0, E_0=1)[source]

Jones vector for elliptically polarized light.

Uses Azzam’s equation 1.75

Parameters:
  • azimuth – tilt angle of ellipse from x - axis [radians]

  • ellipticity_angle – arctan(minor - axis / major - axis) [radians]

  • phi_x – phase for E field in x - direction [radians]

  • E_0 – amplitude of field

Returns:

Jones vector with specified characteristics

pypolar.jones.field_horizontal()[source]

Jones Vector for horizontal polarized light.

pypolar.jones.field_left_circular()[source]

Jones Vector for left circular polarized light.

pypolar.jones.field_linear(theta)[source]

Jones vector for linear polarized light at angle theta from horizontal plane.

pypolar.jones.field_right_circular()[source]

Jones Vector for right circular polarized light.

pypolar.jones.field_vertical()[source]

Jones Vector for vertical polarized light.

pypolar.jones.intensity(J)[source]

Return the intensity.

pypolar.jones.interpret(J)[source]

Interpret a Jones vector.

arg:

J: A Jones vector (2x1) which may have complex entries

Examples

interpret([1, -1j]) –> “Right circular polarization”

interpret([0.5, 0.5]) –>

“Linear polarization at 45.000000 degrees CCW from x - axis”

interpret( np.array([exp(-1j * pi), exp(-1j * pi / 3)]) ) –>

“Left elliptical polarization, rotated with respect to the axes”

pypolar.jones.jones_op_to_mueller_op(JJ)[source]

Convert a complex 2x2 Jones matrix to a real 4x4 Mueller matrix.

Hauge, Muller, and Smith, “Conventions and Formulas for Using the Mueller- Stokes Calculus in Ellipsometry,” Surface Science, 96, 81 - 107 (1980) :Parameters: J – Jones matrix

Returns:

equivalent 4x4 Mueller matrix

pypolar.jones.jones_to_stokes(J)[source]

Convert Jones vector to Stokes vector.

Parameters:

J – Jones vector

Returns:

Stokes vector

pypolar.jones.op_attenuator(t)[source]

Jones matrix operator for an isotropic optical attenuator.

The transmittance t=I / I_0 is the fraction of light getting through the attenuator or absorber.

Parameters:

t – fraction of intensity getting through attenuator [—]

pypolar.jones.op_fresnel_reflection(m, theta)[source]

Jones matrix operator for Fresnel reflection at angle theta.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

2x2 matrix of the Fresnel transmission operator [-]

pypolar.jones.op_fresnel_transmission(m, theta)[source]

Jones matrix operator for Fresnel transmission at angle theta.

* THIS IS ALMOST CERTAINLY WRONG *

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

2x2 Fresnel transmission operator [-]

pypolar.jones.op_half_wave_plate(theta)[source]

Jones matrix operator for a rotated half - wave plate.

The half wave plate has been rotated around a normal to the surface of the plate.

Parameters:

theta – angle from fast - axis to horizontal plane [radians]

Returns:

2x2 matrix of the half - wave plate operator [-]

pypolar.jones.op_linear_polarizer(theta)[source]

Jones matrix operator for a rotated linear polarizer.

The polarizer has been rotated around a normal to its surface.

Parameters:

theta – rotation angle measured from the horizontal plane [radians]

pypolar.jones.op_mirror()[source]

Jones matrix operator for a perfect mirror.

pypolar.jones.op_quarter_wave_plate(theta)[source]

Jones matrix operator for an rotated quarter - wave plate.

The QWP had been rotated around a normal to its surface.

Parameters:

theta – angle from fast - axis to horizontal plane [radians]

Returns:

2x2 matrix of the quarter - wave plate operator [-]

pypolar.jones.op_retarder(theta, delta)[source]

Jones matrix operator for an rotated optical retarder.

The retarder has been rotated around a normal to its surface.

Parameters:
  • theta – rotation angle between fast - axis and the horizontal plane [radians]

  • delta – phase delay introduced between fast and slow - axes [radians]

pypolar.jones.op_rotation(theta)[source]

Jones matrix operator to rotate light around the optical axis.

Parameters:

theta – angle of rotation around optical axis [radians]

Returns:

2x2 matrix of the rotation operator [-]

pypolar.jones.phase(J)[source]

Return the phase.

pypolar.jones.polarization_variable(J)[source]

Return the complex polarization variable, chi.

This reduces the Jones vector to a single complex number and is useful when the amplitude and absolute - phase are of secondary interest. These are eliminated and chi is representative of the polarization state in the complex plane.

pypolar.jones.use_alternate_convention(state)[source]

Change sign convention used for Jones calculus.

Read the documentation about the different conventions possible.

The default convention is to assume the wave function is represented by exp(j*(omega * t-k * z)) and that the perspective when viewing a sectional pattern is to look back along the optical axis towards the source. This is the most commonly used convention, but there are noteable exceptions (Wikipedia, Fowler, and Hecht (sometimes).

Call this function once at the beginning and everything should be just fine.

pypolar.sym_jones

Useful routines for symbolic manipulation of Jones vectors and matrices.

Creating Jones vectors for specific polarization states:

* field_linear(angle)
* field_left_circular()
* field_right_circular()
* field_horizontal()
* field_vertical()
* field_ellipsometry(tanpsi, Delta)
* field_elliptical(azimuth, elliptic_angle)

Creating Jones Matrices for polarizing elements:

* op_linear_polarizer(angle)
* op_retarder(fast_axis_angle, retardance)
* op_attenuator(optical_density)
* op_mirror()
* op_rotation(angle)
* op_quarter_wave_plate(fast_axis_angle)
* op_half_wave_plate(fast_axis_angle)
* op_fresnel_reflection(index_of_refraction, angle)
* op_fresnel_transmission(index_of_refraction, angle)

Interpreting the polarization state:

* use_alternate_convention(boolean)
* interpret(jones_vector)
* intensity(jones_vector)
* phase(jones_vector)
* ellipse_azimuth(jones_vector)
* ellipse_axes(jones_vector)
* ellipticity(jones_vector)
* ellipticity_angle(jones_vector)
* amplitude_ratio(jones_vector)
* amplitude_ratio_angle(jones_vector)
* polarization_variable(jones_vector)

Converting to Mueller formalism:

* jones_op_to_mueller_op(jones_matrix)
* jones_to_stokes(jones_vector)
pypolar.sym_jones.field_horizontal()[source]

Jones Vector for horizontal polarized light.

pypolar.sym_jones.field_left_circular()[source]

Jones Vector for left circular polarized light.

pypolar.sym_jones.field_linear(theta)[source]

Jones vector for linear polarized light at angle theta from horizontal plane.

pypolar.sym_jones.field_right_circular()[source]

Jones Vector for right circular polarized light.

pypolar.sym_jones.field_vertical()[source]

Jones Vector for vertical polarized light.

pypolar.sym_jones.intensity(J)[source]

Return the intensity.

pypolar.sym_jones.op_attenuator(t)[source]

Jones matrix operator for an optical attenuator.

Parameters:

t – fraction of intensity passing through attenuator [—]

pypolar.sym_jones.op_fresnel_reflection(m, theta)[source]

Jones matrix operator for Fresnel reflection at angle.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

2x2 matrix of the Fresnel transmission operator [-]

pypolar.sym_jones.op_fresnel_transmission(m, theta)[source]

Jones matrix operator for Fresnel transmission at angle theta.

* THIS IS ALMOST CERTAINLY WRONG *

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

2x2 Fresnel transmission operator [-]

pypolar.sym_jones.op_half_wave_plate(theta)[source]

Jones matrix operator for a rotated half-wave plate.

The HWP is rotated about a normal to its surface.

Parameters:

theta – angle from fast-axis to horizontal plane [radians]

Returns:

2x2 matrix of the half-wave plate operator [-]

pypolar.sym_jones.op_linear_polarizer(theta)[source]

Jones matrix operator for a rotated linear polarizer.

The polarizer is rotated around a normal to its surface.

Parameters:

theta – rotation angle measured from the horizontal plane [radians]

pypolar.sym_jones.op_mirror()[source]

Jones matrix operator for a perfect mirror.

pypolar.sym_jones.op_quarter_wave_plate(theta)[source]

Jones matrix operator for a rotated quarter-wave plate.

The QWP is rotated about a normal to its surface.

Parameters:

theta – angle from fast-axis to horizontal plane [radians]

Returns:

2x2 matrix of the quarter-wave plate operator [-]

pypolar.sym_jones.op_retarder(theta, delta)[source]

Jones matrix operator for a rotated optical retarder.

The retarder is rotated around a normal to its surface.

Parameters:
  • theta – rotation angle between fast-axis and the horizontal plane [radians]

  • delta – phase delay introduced between fast and slow-axes [radians]

pypolar.sym_jones.op_rotation(theta)[source]

Jones matrix operator to rotate light around the optical axis.

Parameters:

theta – angle of rotation about optical axis [radians]

Returns:

2x2 matrix of the rotation operator [-]

pypolar.sym_jones.phase(J)[source]

Return the phase.

pypolar.mueller

Useful basic routines for managing polarization with the Stokes / Mueller calculus.

The routines are broken up into four groups: (1) creating Stokes vectors, (2) creating Mueller matrix operators, (3) interpretation, and (4) conversion.

Functions to create Stokes vectors:

stokes_linear(angle)
stokes_left_circular()
stokes_right_circular()
stokes_horizontal()
stokes_vertical()
stokes_unpolarized()
stokes_elliptical(DOP, azimuth, ellipticity)
stokes_ellipsometry(tanpsi, Delta)

Functions to create Mueller matrix operators:

op_linear_polarizer(angle)
op_retarder(fast_axis_angle, phase_delay)
op_attenuator(optical_density)
op_mirror()
op_rotation(angle)
op_quarter_wave_plate(fast_axis_angle)
op_half_wave_plate(fast_axis_angle)
op_fresnel_reflection(index_of_refraction, incidence_angle)
op_fresnel_transmission(index_of_refraction, incidence_angle)

Functions to interpret Stokes vectors:

intensity(stokes_vector)
degree_of_polarization(stokes_vector)
ellipse_orientation(stokes_vector)
ellipse_ellipticity(stokes_vector)
ellipse_axes(stokes_vector)
interpret(stokes_vector)

Functions to convert:

stokes_to_jones(stokes_vector)
mueller_to_jones(mueller_matrix)
pypolar.mueller.degree_of_polarization(S)[source]

Return the degree of polarization.

pypolar.mueller.ellipse_axes(S)[source]

Return the semi-major and semi-minor axes of the polarization ellipse.

pypolar.mueller.ellipse_ellipticity(S)[source]

Return the ellipticity of the polarization ellipse.

This parameter is often represented by Chi.

pypolar.mueller.ellipse_orientation(S)[source]

Return the angle between the major semi-axis and the x-axis.

The polarization ellipse is rotated by an angle from the laboratory frame. This is that angle: often represented by psi.

pypolar.mueller.intensity(S)[source]

Return the intensity.

pypolar.mueller.interpret(S)[source]

Interpret a Stokes vector.

Parameters S : A Stokes vector

Examples

interpret([1, 0, 0, 0]) –> “Unpolarized Light”

pypolar.mueller.mueller_to_jones(M)[source]

Convert a Mueller matrix to a Jones matrix.

Theocaris, Matrix Theory of Photoelasticity, eqns 4.70-4.76, 1979

Inputs:

M : a 4x4 Mueller matrix

Returns:

the corresponding 2x2 Jones matrix

pypolar.mueller.op_attenuator(t)[source]

Mueller matrix operator for an optical attenuator.

Parameters:

t – fraction of light getting through attenuator [—]

pypolar.mueller.op_fresnel_reflection(m, theta)[source]

Mueller matrix operator for Fresnel reflection at angle theta.

These are based on Collett, Mueller-Stokes Matrix Formulation of Fresnel equation, Am. J Phys., 39, 1971.

The changes in direction and detector orientation are included in the Mueller matrix. See Clark, Stellar Polarimetry, Appendix A.

Still needs sign testing for angles above Brewster’s angle.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

4x4 Fresnel reflection Mueller matrix [-]

pypolar.mueller.op_fresnel_transmission(m, theta)[source]

Mueller matrix operator for Fresnel transmission at angle theta.

These are based on Collett, Mueller-Stokes Matrix Formulation of Fresnel equation, Am. J Phys., 39, 1971.

Still needs sign testing for angles above Brewster’s angle.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

4x4 Fresnel transmission operator [-]

pypolar.mueller.op_half_wave_plate(theta)[source]

Mueller matrix for a rotated half-wave plate.

Parameters:

theta – rotation angle between fast-axis and the horizontal plane [radians]

Returns:

a Mueller matrix operator for the rotated half-wave plate.

pypolar.mueller.op_linear_polarizer(theta)[source]

Mueller matrix operator for a rotated linear polarizer.

The polarizer is rotated around a normal to its surface.

Parameters:

theta – rotation angle measured from the horizontal plane [radians]

pypolar.mueller.op_mirror()[source]

Mueller matrix operator for a perfect mirror.

pypolar.mueller.op_quarter_wave_plate(theta)[source]

Mueller matrix operator for an quarter-wave plate.

Parameters:

theta – rotation angle between fast-axis and the horizontal plane [radians]

Returns:

a Mueller matrix operator for the rotated quarter-wave plate.

pypolar.mueller.op_retarder(theta, delta)[source]

Mueller matrix operator for an rotated optical retarder.

The retarder is rotated around a normal to its surface.

Parameters:
  • theta – rotation angle between fast-axis and the horizontal plane [radians]

  • delta – phase delay introduced between fast and slow-axes [radians]

pypolar.mueller.op_rotation(theta)[source]

Mueller matrix operator to rotate light around the optical axis.

Parameters:

theta – rotation angle [radians]

pypolar.mueller.stokes_ellipsometry(tanpsi, Delta)[source]

Stokes vector using ellipsometer parameters.

This creates a Stokes vector for the specific set of ellipsometry parameters tanpsi and Delta. See Fujiwara table 3.1 for example.

Parameters:
  • tanpsi – abs(E_x / E_y) [-]

  • Delta – angle(E_x) - angle(E_y) [radians]

Returns:

normalized Stokes vector with specified properties

pypolar.mueller.stokes_elliptical(DOP, azimuth, ellipticity)[source]

Stokes vector for partially polarized elliptically polarized light.

Parameters:
  • DOP – degree of polarization [-]

  • azimuth – tilt of ellipse relative to horizontal [radians]

  • ellipticity – ratio of minor to major axes [-]

Returns:

normalized Stokes vector with specified properties

pypolar.mueller.stokes_horizontal()[source]

Stokes vector for horizontal polarized light.

pypolar.mueller.stokes_left_circular()[source]

Stokes vector for left circular polarized light.

pypolar.mueller.stokes_linear(theta)[source]

Stokes vector for light polarized at angle theta from the horizontal plane.

pypolar.mueller.stokes_right_circular()[source]

Stokes vector for right circular polarized light.

pypolar.mueller.stokes_to_jones(S)[source]

Convert a (list of) Stokes vector(s) to a (list of) Jones vector(s).

The sign convention for the Jones vector can be set by calling pypolar.jones.use_alternate_convention(True). The default is to assume that the field is represented by exp(j * omega * t-k * z).

Inputs:

S : a single Stokes vector (4,) or list of Stokes vectors (n,4)

Returns:

a Jones vector (2,) or list of Jones vectors (n,2)

pypolar.mueller.stokes_unpolarized()[source]

Stokes vector for vertical polarized light.

pypolar.mueller.stokes_vertical()[source]

Stokes vector for vertical polarized light.

pypolar.sym_mueller

Symbolic manipulation of polarization using the Stokes/Mueller calculus.

The routines are broken up into four groups: (1) creating Stokes vectors, (2) creating Mueller matrix operators, (3) interpretation, and (4) conversion.

Functions to create Stokes vectors:

stokes_linear(angle)
stokes_left_circular()
stokes_right_circular()
stokes_horizontal()
stokes_vertical()
stokes_unpolarized()
stokes_elliptical(DOP, azimuth, ellipticity)
stokes_ellipsometry(tanpsi, Delta)

Functions to create Mueller matrix operators:

op_linear_polarizer(angle)
op_retarder(fast_axis_angle, phase_delay)
op_attenuator(optical_density)
op_mirror()
op_rotation(angle)
op_quarter_wave_plate(fast_axis_angle)
op_half_wave_plate(fast_axis_angle)
op_fresnel_reflection(index_of_refraction, incidence_angle)
op_fresnel_transmission(index_of_refraction, incidence_angle)

Functions to interpret Stokes vectors:

intensity(stokes_vector)
degree_of_polarization(stokes_vector)
ellipse_orientation(stokes_vector)
ellipse_ellipticity(stokes_vector)
ellipse_axes(stokes_vector)

Functions to convert:

stokes_to_jones(stokes_vector)
mueller_to_jones(mueller_matrix)
pypolar.sym_mueller.degree_of_polarization(S)[source]

Return the degree of polarization.

pypolar.sym_mueller.ellipse_axes(S)[source]

Return the semi-major and semi-minor axes.

These are the axes of the polarization ellipse.

pypolar.sym_mueller.ellipse_ellipticity(S)[source]

Return ellipticity of the polarization ellipse.

The ellipticity of the polarization ellipse (often represented by chi)

pypolar.sym_mueller.ellipse_orientation(S)[source]

Return orientation of the polarization ellipse.

The orientation is the angle between the major semi-axis and the x-axis of the polarization ellipse (often represented by psi).

pypolar.sym_mueller.intensity(S)[source]

Return the intensity.

pypolar.sym_mueller.mueller_to_jones(M)[source]

Convert a Mueller matrix to a Jones matrix.

Theocaris, Matrix Theory of Photoelasticity, eqns 4.70-4.76, 1979

Parameters:

M – a 4x4 Mueller matrix

Returns:

the corresponding 2x2 Jones matrix

pypolar.sym_mueller.op_attenuator(t)[source]

Mueller matrix operator for an optical attenuator.

Parameters:

t – fraction of light getting through attenuator [—]

pypolar.sym_mueller.op_fresnel_reflection(m, theta)[source]

Mueller matrix operator for Fresnel reflection.

Convert from the Jones operator to ensure that phase change are handled properly.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

4x4 Fresnel reflection operator [-]

pypolar.sym_mueller.op_fresnel_transmission(m, theta)[source]

Mueller matrix operator for Fresnel transmission.

Unclear if phase changes are handled properly. See Collett, “Mueller-Stokes Matrix Formulation of Fresnel’s Equations,” Am. J. Phys. 39, 517 (1971).

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from normal to surface [radians]

Returns:

4x4 Fresnel transmission operator [-]

pypolar.sym_mueller.op_half_wave_plate(theta)[source]

Mueller matrix operator for rotated half-wave plate.

The HWP is rotated about a normal to its surface.

Parameters:

theta – rotation angle between fast-axis and the horizontal plane [radians]

pypolar.sym_mueller.op_linear_polarizer(theta)[source]

Mueller matrix operator for a rotated linear polarizer.

The polarizer is rotated about a normal to its surface.

Parameters:

theta – rotation angle measured from the horizontal plane [radians]

pypolar.sym_mueller.op_mirror()[source]

Mueller matrix operator for a perfect mirror.

pypolar.sym_mueller.op_quarter_wave_plate(theta)[source]

Mueller matrix operator for a rotated quarter-wave plate.

The QWP is rotated about a normal to its surface.

Parameters:

theta – rotation angle between fast-axis and the horizontal plane [radians]

pypolar.sym_mueller.op_retarder(theta, delta)[source]

Mueller matrix operator for a rotated optical retarder.

The retarder is rotated about a normal to its surface.

Parameters:
  • theta – rotation angle between fast-axis and the horizontal plane [radians]

  • delta – phase delay introduced between fast and slow-axes [radians]

pypolar.sym_mueller.op_rotation(theta)[source]

Mueller matrix operator to rotate light about the optical axis.

Parameters:

theta – rotation angle [radians]

pypolar.sym_mueller.stokes_horizontal()[source]

Stokes vector for horizontal polarized light.

pypolar.sym_mueller.stokes_left_circular()[source]

Stokes vector for left circular polarized light.

pypolar.sym_mueller.stokes_linear(theta)[source]

Stokes vector for linear polarized light at angle.

Parameters:
  • m – complex index of refraction [-]

  • theta – angle from horizontal plane [radians]

pypolar.sym_mueller.stokes_right_circular()[source]

Stokes vector for right circular polarized light.

pypolar.sym_mueller.stokes_to_jones(S)[source]

Convert a Stokes vector to a Jones vector.

This conversion loses some of the information in the Stokes vector because the unpolarized fraction is lost. Furthermore, since the Jones vector can differ by an arbitrary phase, the phase is chosen to make the horizontal component real.

Parameters:

S – a Stokes vector

Returns:

a corresponding Jones vector

pypolar.sym_mueller.stokes_unpolarized()[source]

Stokes vector for unpolarized light.

pypolar.sym_mueller.stokes_vertical()[source]

Stokes vector for vertical polarized light.

pypolar.visualization

A set of basic routines for visualizing polarization.

Functions for drawing the polarization ellipse (sectional pattern):

draw_jones_ellipse(J)
draw_stokes_ellipse(S)

Functions for drawing 2D and 3D representations:

draw_jones_field(J)
draw_stokes_field(S)

Functions for drawing an animated 2D and 3D representations:

draw_jones_animated(J)
draw_stokes_animated(S)
Functions for drawing a Poincaré representation::

draw_empty_sphere() draw_jones_poincare(J) draw_stokes_poincare(S) join_jones_poincare(J) join_stokes_poincare(S)

Example: Poincaré sphere plot of a Jones vector:

J = pypolar.jones.field_linear(np.pi / 6)
pypolar.visualization.draw_jones_poincare(J)

Example: Poincaré sphere plot of two Stokes vectors:

S1 = pypolar.mueller.stokes_left_circular()
S2 = pypolar.mueller.stokes_linear(np.radians(15))

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')
pypolar.visualization.draw_empty_sphere(ax)
pypolar.visualization.draw_stokes_poincare(S1, ax, label='  S1')
pypolar.visualization.draw_stokes_poincare(S2, ax, label='  S2')
pypolar.visualization.join_stokes_poincare(S1, S2, ax, lw=2, ls=':', color='orange')
pypolar.visualization.draw_empty_sphere(ax=None)[source]

Plot an empty Poincare sphere.

Parameters:

ax – pyplot axis

pypolar.visualization.draw_jones_animated(J, nframes=64)[source]

Animate 3D and 2D representations of the polarization field.

Parameters:

J – Jones vector

pypolar.visualization.draw_jones_ellipse(J, simple=False)[source]

Draw a 2D sectional pattern for a Jones vector.

Parameters:
  • J – Jones vector

  • simple – if True then just draw a simple ellipse plot

pypolar.visualization.draw_jones_field(J, offset=0)[source]

Draw 3D and 2D representations of the polarization field.

Parameters:
  • J – Jones vector

  • offset – starting point

pypolar.visualization.draw_jones_poincare(J, ax=None, label=None, **kwargs)[source]

Plot single point on Poincaré sphere.

pypolar.visualization.draw_stokes_animated(S)[source]

Draw animated 2D and 3D representations of the polarization.

Parameters:

S – Stokes vector

pypolar.visualization.draw_stokes_ellipse(S)[source]

Draw a 2D and 3D representation of the polarization.

Parameters:

S – Stokes vector

pypolar.visualization.draw_stokes_field(S, offset=0)[source]

Draw a 2D and 3D representation of the polarization.

Parameters:
  • S – Stokes vector

  • offset – starting point

pypolar.visualization.draw_stokes_poincare(S, ax=None, label=None, **kwargs)[source]

Plot single point on Poincaré sphere.

pypolar.visualization.join_jones_poincare(J1, J2, ax=None, **kwargs)[source]

Plot arc joining two Jones vectors on Poincaré sphere.

pypolar.visualization.join_stokes_poincare(S1, S2, ax=None, **kwargs)[source]

Plot arc joining two Stokes vectors on Poincaré sphere.

pypolar.ellipsometry

Useful functions for ellipsometry.

Scott Prahl Apr 2021

pypolar.ellipsometry.RAE_from_rho(phi, rho, P, average=1, noise=0, deg=False)[source]

Create normalized rotating ellipsometer signal for sample.

See eqn 4.19 and eqn 4.23 in Fujiwara 2007

Generate the expected reading at each analyzer angle in an ellipsometer with a sample characterized by a material with an ellipsometer parameter rho = tan(psi)exp(j * Delta)

This is a classic source::polarizer::QWP::sample::analyzer::detector arrangement. The QWP is oriented at +45° if present.

Note that the default returned array is normalized between 0 and 1. therefore the noise should be scaled accordingly.

Parameters:
  • phi – array of analyzer angles from 0 to 2pi [radians / degrees]

  • rho – ellipsometer parameter for surface [complex]

  • P – angle of polarizer [radians / degrees]

  • average – average value of signal over 2pi [AU]

  • noise – std dev of normal noise distribution [AU]

  • deg – phi and P are in degrees [True / False]

Returns:

Array of ellipsometer readings for each angle phi [-]

pypolar.ellipsometry.find_fourier(phi, signal, deg=False)[source]

Calculate first few Fourier series coefficients.

Fit the signal to the function

I_ave * ( 1 + alpha * cos(2 * phi) + beta * sin(2 * phi) )

Parameters:
  • phi – array of analyzer angles [radians / degrees]

  • signal – array of ellipsometer intensities [AU]

  • deg – phi is in degrees [True / False]

Returns:

I_ave, alpha, beta

pypolar.ellipsometry.m_from_rho(rho, theta_i, deg=False)[source]

Calculate the index of refraction for an isotropic sample.

rho = r_par_amplitude / r_per_amplitude or

rho = tan(psi)*exp(j * Delta)

Formula from McCrackin “Measurement of the thickness and refractive index of very thin films and the optical properties of surfaces by ellipsometry”, Journal of Research of the National Bureau of Standards, (1963).

Parameters:
  • rho – complex reflectance ratio [-]

  • theta_i – incidence angle from normal [radians / degrees]

  • deg – theta_i is in degrees [True / False]

Returns:

complex index of refraction [-]

pypolar.ellipsometry.m_from_rotating_analyzer_data(phi, signal, theta_i, P, QWP=False, deg=False)[source]

Recover m from rotating analyzer data.

Parameters:
  • phi – array of analyzer angles [radians / degrees]

  • signal – array of ellipsometer intensities [AU]

  • theta_i – incidence angle from normal [radians / degrees]

  • P – incident polarization azimuthal angle [radians / degrees]

  • QWP – True if QWP is present

  • deg – phi, theta_i, and P are in degrees [True / False]

Returns:

complex index of refraction [-]

pypolar.ellipsometry.m_from_tanpsi_and_Delta(tanpsi, Delta, theta_i, deg=False)[source]

Return the index of refraction for observed Delta, tanpsi, and theta_i.

Parameters:
  • tanpsi – abs() of ratio of field amplitudes [-]

  • Delta – phase change caused by reflection [-]

  • theta_i – incidence angle from normal [radians / degrees]

  • deg – theta_i and Delta are in degrees [True / False]

Returns:

complex index of refraction [-]

pypolar.ellipsometry.null_angles(m, theta_i, deg=False)[source]

Generate expected ellipsometer angles for all zones.

The various null angles fall into four sets called zones, two with the fast - axis of the quarter wave plate set 45° (2 & 4) and two with the fast - axis of the quarter wave plate set to -45° (1 & 3). In each zone there are four combinations of polarizer and analyzer angles that have a null reading (because rotation of a linear polarizer by 180° should give the same result.

Table 1 from McCrackin “Measurement of the thickness and refractive index of very thin films and the optical properties of surfaces by ellipsometry”, Journal of Research of the National Bureau of Standards, (1963).

All angles returned fall between 0 and 2pi.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians / degrees]

  • deg – theta_i in degrees, return null angles in degrees? [True / False]

Returns:

dictionary with null angles [(P1, A1), (P2, A2), (P3, A3), (P4, A4)] for each zone

pypolar.ellipsometry.null_angles_report(m, theta_i, deg=False)[source]

Create a report showing null angles for sample.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians / degrees]

  • deg – theta_i is in degrees [True / False]

Returns:

string containing a report listing null angles for each zone.

pypolar.ellipsometry.rho_from_PSA(phi, signal, P, deg=False)[source]

Recover rho from polarizer / sample / rotating analyzer system.

Based on equation 4.24 in Fujiwara 2005. Note that the PSA arrangement allows 0<=psi<=90° and 0<=Delta<=180°.

In this system the measurement error increases when Delta is near zero or 180°. Since this corresponds to linearly polarized light and would be exactly what would be measured for dielectric samples.

Parameters:
  • phi – array of analyzer angles [radians / degrees]

  • signal – array of ellipsometer intensities [AU]

  • P – incident polarization azimuthal angle [radians / degrees]

  • deg – phi and P are in degrees [True / False]

Returns:

rho = tan(psi)*exp(1j * Delta) [-]

pypolar.ellipsometry.rho_from_m(m, theta_i, deg=False)[source]

Calculate the complex ratio of reflection amplitudes.

This assumes that the material is flat and isotropic (e.g., no surface film). It also assumes that the parallel (or perpendicular) field remains entirely parallel (or perpendicular) and is fully characterized by Fresnel reflection.

Parameters:
  • m – complex index of refraction [-]

  • theta_i – incidence angle from normal [radians / degrees]

  • deg – theta_i is in degrees [True / False]

Returns:

complex ellipsometer parameter rho [-]

pypolar.ellipsometry.rho_from_rotating_analyzer_data(phi, signal, P, QWP=False, deg=False)[source]

Recover rho from rotating analyzer data.

Based on equation 3.297 from Azzam (should be fixed to work with any P value)

Parameters:
  • phi – array of analyzer angles [radians / degrees]

  • signal – array of ellipsometer intensities [AU]

  • P – incident polarization azimuthal angle [radians / degrees]

  • QWP – True if QWP is present

  • deg – phi and P are in degrees [True / False]

Returns:

rho = tan(psi)*exp(1j * Delta) [-] fit: array of fitted data

pypolar.ellipsometry.rho_from_tanpsi_Delta(tanpsi, Delta, deg=False)[source]

Calculate the index of refraction for an isotropic sample.

Formula from McCrackin “Measurement of the thickness and refractive index of very thin films and the optical properties of surfaces by ellipsometry”, Journal of Research of the National Bureau of Standards, (1963).

Parameters:
  • tanpsi – tan(psi) or abs(rpar / rperp) [-]

  • Delta – phase change caused by reflection [radians / degrees]

  • deg – Delta is in degrees [True / False]

Returns:

complex ellipsometer parameter rho [-]

pypolar.ellipsometry.rho_from_zone_2_null_angles(P, A, deg=False)[source]

Recover rho from Null ellipsometer measurements in zone 2.

Parameters:
  • P – polarizer angle for null reading [radians / degrees]

  • A – analyzer angle for null reading [radians / degrees]

  • deg – P and A are in degrees [True / False]

Returns:

complex ellipsometer parameter rho [-]

pypolar.ellipsometry.rho_from_zone_4_null_angles(P, A, deg=False)[source]

Recover rho from Null ellipsometer measurements in zone 4.

Parameters:
  • P – polarizer angle for null reading in zone 4 [radians / degrees]

  • A – analyzer angle for null reading in zone 4 [radians / degrees]

  • deg – P and A are in degrees [True / False]

Returns:

complex ellipsometer parameter rho [-]

pypolar.ellipsometry.rotating_analyzer_signal(phi, IDC, IS, IC, noise=0, deg=False)[source]

Create theoretical rotating ellipsometer signal.

In theory the rotating analyzer ellipsometer generates a sinusoidal signal with an offset. This function does that and allows the optional addition of normally distributed noise.

Parameters:
  • phi array of analyzer angles [radians / degrees]

  • IDC – DC amplitude of signal [-]

  • IS – sin(2 * phi) amplitude coefficient [-]

  • IC – cos(2 * phi) amplitude coefficient [-]

  • noise – std dev of normal noise distribution [-]

  • deg – phi is in degrees [True / False]

Returns:

Array of ellipsometer readings for each angle phi [-]

pypolar.ellipsometry.rotating_analyzer_signal_from_m(phi, m, theta_i, P, average=1, noise=0, deg=False)[source]

Create rotating ellipsometer signal for sample with known index.

Parameters:
  • phi – array of analyzer angles from 0 to 2pi [radians / degrees]

  • m – complex index of refraction of sample [-]

  • theta_i – angle of incidence (from normal) [radians / degrees]

  • P – angle of incident polarized light [radians / degrees]

  • average – average value of signal over 2pi [AU]

  • noise – std dev of normal noise distribution [-]

  • deg – phi, theta_i and P ar in degrees [True / False]

Returns:

Array of ellipsometer readings for each angle phi [-]

pypolar.ellipsometry.rotating_analyzer_signal_from_rho(phi, rho, P, QWP=False, average=1, noise=0, deg=False)[source]

Create normalized rotating ellipsometer signal for sample.

Generate the expected reading at each analyzer angle in an ellipsometer with a sample characterized by a material with an ellipsometer parameter rho = tan(psi)exp(j * Delta)

This is a classic source::polarizer::QWP::sample::analyzer::detector arrangement. The QWP is oriented at +45° if present.

Note that the default returned array is normalized between 0 and 1. therefore the noise should be scaled accordingly.

Parameters:
  • phi – array of analyzer angles from 0 to 2pi [radians / degrees]

  • rho – ellipsometer parameter for surface [complex]

  • P – angle of polarizer [radians / degrees]

  • QWP – True if QWP is present

  • average – average value of signal over 2pi [AU]

  • noise – std dev of normal noise distribution [AU]

  • deg – phi and P are in degrees [True / False]

Returns:

Array of ellipsometer readings for each angle phi [-]

pypolar.ellipsometry.tanpsi_Delta_from_rho(rho, deg=False)[source]

Extract ellipsometer parameters from rho.

rho = r_par_amplitude / r_per_amplitude or

rho = tan(psi)*exp(j * Delta)

Formula from Fujiwara 2007 eqn 4.6 and correspond to the case when the complex refractive index is negative (m = n - k * 1j)

Parameters:
  • rho – complex reflectance ratio [-]

  • deg – return Delta in degrees? [True / False]

Returns:

tanpsi – tan(psi) or abs(r_p / r_s) [-] Delta: phase change caused by reflection [radians / degrees]

pypolar.gaerter

Simple interface to Gaerter 116A Ellipsometer.

This is intended to be used with the computer connected to an Arduino controller that interfaces with the Gaerter ellipsometer.

Scott Prahl Apr 2020

pypolar.gaertner.avg_reflectance(conn, num_samples=10)[source]

Collect multiple samples and return the sum of all of them.

Returns:

an array of 72 integers

pypolar.gaertner.connect_to_ellipsometer(usb_serial_port_id)[source]

Establish a serial connection with the ellipsometer.

Parameters:

usb_serial_port_id – name of serial port

Returns

Serial connection object

pypolar.gaertner.current_serial_ports()[source]

Return a string listing all current serial port names.

pypolar.gaertner.get_reflectance(conn)[source]

Obtain one analyzer revolution worth of reflectance values.

Trigger the Arduino attached to the ellipsometer and obtain readings at each of 72 analyzer orientations.

The idea is pretty simple. Just send a byte to the Arduino and it will send 144=72 * 2 bytes back. :returns: an array of 72 integers

pypolar.gaertner.read_data_with_name(filename)[source]

Read a text file into an array.

This does the opposite of save_data_with_time_stamp() or save_data_with_name() The data is read and returned in a 72 element array.

pypolar.gaertner.save_data_with_name(signal, basename, theta_i, P, QWP=False)[source]

Save signal to file with ellipsometer setting in the filename.

Creates a filename based on the settings and saves the array signal to it.

Parameters:
  • signal – array of ellipsometer readings

  • basename – string starting filename

  • theta_i – angle of incidence [radians]

  • P – polarizer angle [radians]

  • QWP – True if QWP is present

Returns:

filename of the file created

pypolar.gaertner.save_data_with_time_stamp(signal)[source]

Save signal in time-stamped file.

Creates a filename using the current time.

Parameters:

signal – array of ellipsometer readings

Returns:

filename of the file created