Polarization Module#

The polarization module provides functions for analyzing and manipulating antenna polarization states, including Jones vectors, Stokes parameters, axial ratio calculations, and Ludwig-3 co/cross-pol decomposition.

Jones Vectors#

Jones vectors provide a compact representation of polarization state, describing the amplitude and phase of orthogonal electric field components.

phased_array.jones_vector(Ex, Ey, phase_diff=0.0)[source]#

Create a Jones vector representing polarization state.

The Jones vector describes the amplitude and phase of the electric field components in a plane transverse to propagation.

Parameters:
  • Ex (array_like) – Amplitude of x-component (horizontal)

  • Ey (array_like) – Amplitude of y-component (vertical)

  • phase_diff (float) – Phase difference between Ey and Ex in radians

Returns:

jones – Complex Jones vector [Ex, Ey * exp(j * phase_diff)]

Return type:

ndarray

Examples

Linear horizontal polarization:

>>> import numpy as np
>>> import phased_array as pa
>>> j = pa.jones_vector(1.0, 0.0)
>>> np.allclose(j, [1, 0])
True

Right-hand circular polarization:

>>> j = pa.jones_vector(1.0, 1.0, phase_diff=-np.pi/2)
>>> ar = pa.axial_ratio(j)
>>> np.isclose(ar, 1.0, atol=1e-10)  # AR = 1 for circular
True

Left-hand circular polarization:

>>> j = pa.jones_vector(1.0, 1.0, phase_diff=np.pi/2)
>>> ar = pa.axial_ratio(j)
>>> np.isclose(ar, 1.0, atol=1e-10)
True

Stokes Parameters#

Stokes parameters provide a complete description of polarization state, including partially polarized light.

phased_array.stokes_parameters(jones)[source]#

Compute Stokes parameters from a Jones vector.

The Stokes parameters provide a complete description of the polarization state, including partially polarized light.

Parameters:

jones (ndarray) – Jones vector [Ex, Ey] (complex, shape (2,) or (2, N))

Returns:

  • S0 (float or ndarray) – Total intensity: |Ex|^2 + |Ey|^2

  • S1 (float or ndarray) – Linear horizontal-vertical: |Ex|^2 - |Ey|^2

  • S2 (float or ndarray) – Linear +45/-45: 2*Re(Ex*conj(Ey))

  • S3 (float or ndarray) – Circular right-left: 2*Im(Ex*conj(Ey))

Return type:

Tuple[float, float, float, float]

Examples

Horizontal linear polarization (S1 = S0):

>>> import numpy as np
>>> import phased_array as pa
>>> j = pa.jones_vector(1.0, 0.0)
>>> S0, S1, S2, S3 = pa.stokes_parameters(j)
>>> np.isclose(S1, S0)
True

Circular polarization (S3 = ±S0):

>>> j = pa.jones_vector(1.0, 1.0, phase_diff=-np.pi/2)  # RHCP
>>> S0, S1, S2, S3 = pa.stokes_parameters(j)
>>> np.isclose(S3, S0, atol=1e-10)  # right circular: S3 = +S0
True

Polarization Ellipse#

Functions for computing polarization ellipse parameters from Jones vectors.

phased_array.axial_ratio(jones)[source]#

Compute the axial ratio from a Jones vector.

The axial ratio is the ratio of the major to minor axes of the polarization ellipse. AR = 1 for circular, AR -> infinity for linear.

Parameters:

jones (ndarray) – Jones vector [Ex, Ey] (complex)

Returns:

ar – Axial ratio (>= 1). Returns infinity for perfect linear polarization.

Return type:

float or ndarray

Examples

Circular polarization has AR = 1:

>>> import numpy as np
>>> import phased_array as pa
>>> j_circ = pa.jones_vector(1.0, 1.0, phase_diff=np.pi/2)
>>> ar = pa.axial_ratio(j_circ)
>>> np.isclose(ar, 1.0, atol=1e-10)
True

Linear polarization has AR = infinity:

>>> j_lin = pa.jones_vector(1.0, 0.0)
>>> ar = pa.axial_ratio(j_lin)
>>> np.isinf(ar)
True
phased_array.tilt_angle(jones)[source]#

Compute the tilt angle of the polarization ellipse.

The tilt angle is the orientation of the major axis of the polarization ellipse with respect to the x-axis (horizontal).

Parameters:

jones (ndarray) – Jones vector [Ex, Ey] (complex)

Returns:

tau – Tilt angle in radians (-pi/2 to pi/2)

Return type:

float or ndarray

Examples

Horizontal polarization has tilt = 0:

>>> import numpy as np
>>> import phased_array as pa
>>> j = pa.jones_vector(1.0, 0.0)
>>> tau = pa.tilt_angle(j)
>>> np.isclose(tau, 0.0, atol=1e-10)
True

45-degree linear polarization:

>>> j = pa.jones_vector(1.0, 1.0, phase_diff=0.0)
>>> tau = pa.tilt_angle(j)
>>> np.isclose(tau, np.pi/4, atol=1e-10)
True

Polarization Loss and Discrimination#

Functions for computing polarization mismatch and cross-polarization performance.

phased_array.cross_pol_discrimination(jones_desired, jones_actual)[source]#

Compute cross-polarization discrimination (XPD).

XPD is the ratio of co-polarized to cross-polarized power, measuring polarization purity.

Parameters:
  • jones_desired (ndarray) – Desired (reference) Jones vector

  • jones_actual (ndarray) – Actual measured Jones vector

Returns:

xpd_dB – Cross-polarization discrimination in dB

Return type:

float or ndarray

Examples

Perfect match has infinite XPD:

>>> import numpy as np
>>> import phased_array as pa
>>> j_ref = pa.jones_vector(1.0, 0.0)
>>> j_act = pa.jones_vector(1.0, 0.0)
>>> xpd = pa.cross_pol_discrimination(j_ref, j_act)
>>> xpd > 50  # Very high XPD
True

Orthogonal polarizations have XPD = -infinity:

>>> j_h = pa.jones_vector(1.0, 0.0)
>>> j_v = pa.jones_vector(0.0, 1.0)
>>> xpd = pa.cross_pol_discrimination(j_h, j_v)
>>> xpd < -50  # Very low (negative) XPD
True
phased_array.polarization_loss_factor(jones_antenna, jones_incident)[source]#

Compute polarization loss factor (PLF).

The PLF is the fraction of incident power that couples to the antenna due to polarization mismatch.

Parameters:
  • jones_antenna (ndarray) – Antenna polarization (Jones vector)

  • jones_incident (ndarray) – Incident wave polarization (Jones vector)

Returns:

plf – Polarization loss factor (0 to 1)

Return type:

float or ndarray

Examples

Matched polarizations have PLF = 1:

>>> import numpy as np
>>> import phased_array as pa
>>> j_ant = pa.jones_vector(1.0, 0.0)  # H-pol antenna
>>> j_inc = pa.jones_vector(1.0, 0.0)  # H-pol wave
>>> plf = pa.polarization_loss_factor(j_ant, j_inc)
>>> np.isclose(plf, 1.0)
True

Orthogonal polarizations have PLF = 0:

>>> j_ant = pa.jones_vector(1.0, 0.0)  # H-pol antenna
>>> j_inc = pa.jones_vector(0.0, 1.0)  # V-pol wave
>>> plf = pa.polarization_loss_factor(j_ant, j_inc)
>>> np.isclose(plf, 0.0)
True

Circular antenna receiving linear has PLF = 0.5:

>>> j_circ = pa.jones_vector(1.0, 1.0, phase_diff=np.pi/2)
>>> j_lin = pa.jones_vector(1.0, 0.0)
>>> plf = pa.polarization_loss_factor(j_circ, j_lin)
>>> np.isclose(plf, 0.5)
True

Ludwig-3 Decomposition#

The Ludwig-3 definition is the most common convention for separating antenna patterns into co-polar and cross-polar components.

phased_array.ludwig3_decomposition(theta, phi, E_theta, E_phi)[source]#

Decompose field into Ludwig-3 co-polar and cross-polar components.

Ludwig-3 is the most common definition for co/cross-pol in antenna measurements. It’s based on aligning the reference polarization with the principal planes.

Parameters:
  • theta (ndarray) – Theta angles in radians

  • phi (ndarray) – Phi angles in radians

  • E_theta (ndarray) – Theta component of electric field (complex)

  • E_phi (ndarray) – Phi component of electric field (complex)

Returns:

  • E_co (ndarray) – Co-polar component (Ludwig-3)

  • E_cross (ndarray) – Cross-polar component (Ludwig-3)

Return type:

Tuple[ndarray, ndarray]

Notes

Ludwig-3 definition (for reference polarization in phi=0 plane):

E_co = E_theta * cos(phi) - E_phi * sin(phi) E_cross = E_theta * sin(phi) + E_phi * cos(phi)

Examples

At phi = 0, E_theta is co-pol:

>>> import numpy as np
>>> import phased_array as pa
>>> theta = np.array([np.pi/4])
>>> phi = np.array([0.0])
>>> E_theta = np.array([1.0 + 0j])
>>> E_phi = np.array([0.0 + 0j])
>>> E_co, E_cross = pa.ludwig3_decomposition(theta, phi, E_theta, E_phi)
>>> np.isclose(np.abs(E_co[0]), 1.0)
True
>>> np.isclose(np.abs(E_cross[0]), 0.0)
True
phased_array.co_pol_pattern(theta, phi, E_theta, E_phi, reference_pol='ludwig3')[source]#

Extract co-polar component of the radiation pattern.

Parameters:
  • theta (ndarray) – Theta angles in radians

  • phi (ndarray) – Phi angles in radians

  • E_theta (ndarray) – Theta component of electric field

  • E_phi (ndarray) – Phi component of electric field

  • reference_pol (str) – ‘ludwig3’ - Ludwig-3 definition (default) ‘theta’ - E_theta is co-pol ‘phi’ - E_phi is co-pol

Returns:

E_co – Co-polar component (complex)

Return type:

ndarray

Examples

>>> import numpy as np
>>> import phased_array as pa
>>> theta = np.linspace(0, np.pi/2, 91)
>>> phi = np.zeros_like(theta)
>>> E_theta = np.cos(theta)  # Simple pattern
>>> E_phi = np.zeros_like(theta)
>>> E_co = pa.co_pol_pattern(theta, phi, E_theta, E_phi)
>>> E_co.shape
(91,)
phased_array.cross_pol_pattern(theta, phi, E_theta, E_phi, reference_pol='ludwig3')[source]#

Extract cross-polar component of the radiation pattern.

Parameters:
  • theta (ndarray) – Theta angles in radians

  • phi (ndarray) – Phi angles in radians

  • E_theta (ndarray) – Theta component of electric field

  • E_phi (ndarray) – Phi component of electric field

  • reference_pol (str) – ‘ludwig3’ - Ludwig-3 definition (default) ‘theta’ - E_phi is cross-pol ‘phi’ - E_theta is cross-pol

Returns:

E_cross – Cross-polar component (complex)

Return type:

ndarray

Examples

>>> import numpy as np
>>> import phased_array as pa
>>> theta = np.linspace(0, np.pi/2, 91)
>>> phi = np.zeros_like(theta)
>>> E_theta = np.cos(theta)
>>> E_phi = 0.1 * np.sin(theta)  # Small cross-pol
>>> E_cross = pa.cross_pol_pattern(theta, phi, E_theta, E_phi)
>>> E_cross.shape
(91,)