colour.phenomena.thin_film_tmm#

colour.phenomena.thin_film_tmm(n: ArrayLike, t: ArrayLike, wavelength: ArrayLike, theta: ArrayLike = 0) tuple[TypeAliasForwardRef('NDArrayFloat'), TypeAliasForwardRef('NDArrayFloat')][source]#

Calculate thin film reflectance and transmittance using Transfer Matrix Method.

Unified function that returns both R and T in a single call, matching the approach used by Byrnes’ tmm and TMM-Fast packages. Supports outer product broadcasting and wavelength-dependent refractive index (dispersion).

Parameters:
  • n (array_like) –

    Complete refractive index stack \(n_j\) for single-layer film. Shape: (3,) or (3, wavelengths_count). The array should contain [n_incident, n_film, n_substrate].

    For example: constant n [1.0, 1.5, 1.0] (air | film | air), or dispersive n [[1.0, 1.0, 1.0], [1.52, 1.51, 1.50], [1.0, 1.0, 1.0]] for wavelength-dependent film refractive index.

  • t (array_like) –

    Film thickness \(d\) in nanometers. Can be:

    • Scalar: Single thickness value (e.g., 250) → shape (W, A, 1, 2)

    • 1D array: Multiple thickness values (e.g., [200, 250, 300]) for thickness sweeps via outer product broadcasting → shape (W, A, T, 2)

    When an array is provided, the function computes reflectance and transmittance for ALL combinations of thickness x wavelength x angle values.

  • wavelength (array_like) – Wavelength values \(\lambda\) in nanometers. Can be scalar or array.

  • theta (array_like, optional) – Incident angle \(\theta\) in degrees. Scalar or array of shape (angles_count,) for angle broadcasting. Default is 0 (normal incidence).

Returns:

(R, T) where:

  • R: Reflectance, numpy.ndarray, shape (W, A, T, 2) for [R_s, R_p]

  • T: Transmittance, numpy.ndarray, shape (W, A, T, 2) for [T_s, T_p]

where W = number of wavelengths, A = number of angles, T = number of thicknesses (the Spectroscopy Convention)

Return type:

tuple

Examples

Basic usage:

>>> R, T = thin_film_tmm([1.0, 1.5, 1.0], 250, 555)
>>> R.shape, T.shape
((1, 1, 1, 2), (1, 1, 1, 2))
>>> R[0, 0, 0]  # [R_s, R_p] at 555nm, shape (W, A, T, 2) = (1, 1, 1, 2)
...
array([ 0.1215919...,  0.1215919...])
>>> np.allclose(R + T, 1.0)  # Energy conservation
True

Multiple wavelengths:

>>> R, T = thin_film_tmm([1.0, 1.5, 1.0], 250, [400, 500, 600])
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 1 angle, 1 thickness, 2 pols)
(3, 1, 1, 2)

Thickness sweep (outer product broadcasting):

>>> R, T = thin_film_tmm([1.0, 1.5, 1.0], [200, 250, 300], [400, 500, 600])
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 1 angle, 3 thicknesses, 2 pols)
(3, 1, 3, 2)
>>> # Access via R[wl_idx, ang_idx, thick_idx, pol_idx]
>>> # R[0, 0, 0] = reflectance at λ=400nm, thickness=200nm
>>> # R[1, 0, 1] = reflectance at λ=500nm, thickness=250nm

Angle broadcasting:

>>> R, T = thin_film_tmm([1.0, 1.5, 1.0], 250, [400, 500, 600], [0, 30, 45, 60])
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 4 angles, 1 thickness, 2 pols)
(3, 4, 1, 2)
>>> # R[0, 0, 0] = reflectance at λ=400nm, θ=0°
>>> # R[1, 2, 0] = reflectance at λ=500nm, θ=45°

Dispersion: wavelength-dependent refractive index:

>>> wavelengths = [400, 500, 600]
>>> n_dispersive = [[1.0, 1.0, 1.0], [1.52, 1.51, 1.50], [1.0, 1.0, 1.0]]
>>> R, T = thin_film_tmm(n_dispersive, 250, wavelengths)
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 1 angle, 1 thickness, 2 pols)
(3, 1, 1, 2)

Notes

  • Thickness broadcasting (outer product): When t is an array with multiple values, ALL combinations of thickness x wavelength x angle are computed. For example: 3 thicknesses x 5 wavelengths x 2 angles = 30 total calculations, returned in shape (W, A, T, 2) = (5, 2, 3, 2).

    This differs from multilayer specification where thickness specifies one value per layer (e.g., [250, 150] for a 2-layer stack).

  • Spectroscopy Convention: Output arrays use wavelength-first ordering (W, A, T, 2) which is natural for spectroscopy applications where you typically iterate over wavelengths in the outer loop.

  • Dispersion support: If n is 2D, the second dimension must match the wavelength array length. Each wavelength uses its corresponding n value.

  • Energy conservation: For non-absorbing media, R + T = 1.

  • Supports complex refractive indices for absorbing materials (e.g., metals).

  • For absorbing media: R + T < 1 (absorption A = 1 - R - T).

References

[Byr16]