Co- & Cross-Polarization Analysis –
MATLAB Code
This document contains ready-to-run MATLAB scripts and functions to analyze co- and
cross-polarization.
Given the electric-field spherical components E_theta and E_phi (complex phasors) versus
angle, you can:
• Project fields onto any receive polarization (linear at arbitrary tilt, RHCP/LHCP) to obtain
co- and cross-polar components
• Compute XPD (Cross-Polar Discrimination) and XPR (Cross-Polarization Ratio)
• Convert between spherical (θ,φ), slant-linear, and circular bases
• Estimate axial ratio (AR), polarization mismatch loss (PML), and plot patterns in dB
Conventions (IEEE, wave traveling in +r): E_RHCP = (E_theta + j E_phi)/√2, E_LHCP =
(E_theta − j E_phi)/√2.
Demo Script
% =====================================================
% demo_cocross.m — Co-/Cross-Polarization Analysis
% =====================================================
clear; clc; close all;
% ---------- Synthetic example field (axially-directed beam) ----------
% We construct a RHCP-dominant beam with a chosen axial ratio.
f0 = 10e9;
lambda = physconst('LightSpeed')/f0;
theta = linspace(0,180,721); % degrees
phi = 0; % single cut at phi=0 for demo
AR_dB_target = 3; % desired axial ratio (boresight)
AR_lin = 10^(AR_dB_target/20);
% Beam shape (choose n for directivity); taper to avoid log(0)
n = 12;
A = (cosd(theta)).^n; A(theta>90) = 0;
A = A + 1e-6; % small floor to avoid -Inf dB
% Set circular components: ER dominant, EL leakage set by AR
ER = A; % RHCP
EL = A./AR_lin; % LHCP leakage (same phase for simplicity)
% Convert to spherical components using IEEE convention:
% ER = (Eθ + j Eφ)/√2, EL = (Eθ − j Eφ)/√2 =>
% Eθ = (ER + EL)/√2, Eφ = -j*(ER - EL)/√2
Etheta = (ER + EL)/sqrt(2);
Ephi = -1j*(ER - EL)/sqrt(2);
% ---------- Choose a receive polarization and compute co/cross
----------
% Options: 'RHCP', 'LHCP', or linear with tilt psi (deg) in local (θ,φ)
plane.
u_rx = pol_unit_circ('RHCP'); % receive polarization unit
vector
% u_rx = pol_unit_linear(0); % 0° => θ-polarized (vertical in
cut)
% u_rx = pol_unit_linear(45); % slant 45°
[Eco, Ecx] = project_co_cross(Etheta, Ephi, u_rx);
XPD_dB = 20*log10(abs(Eco)./max(abs(Ecx), 1e-12));
% ---------- Normalize and plot patterns ----------
Eco_dB = 20*log10(abs(Eco)/max(abs(Eco)));
Ecx_dB = 20*log10(abs(Ecx)/max(abs(Eco)));
figure; plot(theta, Eco_dB, theta, Ecx_dB, '--'); grid on;
xlabel('\theta (deg)'); ylabel('Normalized Level (dB)');
legend('Co-pol','Cross-pol','Location','best');
title('Co/Cross Patterns (normalized to Co-pol peak)');
figure; plot(theta, XPD_dB); grid on;
xlabel('\theta (deg)'); ylabel('XPD (dB)');
title('Cross-Polar Discrimination vs \theta');
% ---------- Basis conversions & metrics at boresight ----------
[ER_est, EL_est] = sph_to_circ(Etheta, Ephi);
AR_bore = axial_ratio_from_circ(ER_est(1), EL_est(1));
fprintf('Axial Ratio at boresight: %.2f dB\n', 20*log10(AR_bore));
% XPR in circular basis (field-intrinsic, independent of RX): |ER|^2/|
EL|^2
XPR_dB = 10*log10( (abs(ER_est).^2 + 1e-24) ./ (abs(EL_est).^2 + 1e-
24) );
figure; plot(theta, XPR_dB); grid on;
xlabel('\theta (deg)'); ylabel('XPR (dB)'); title('Cross-Polarization
Ratio (circular basis)');
% ---------- Polarization mismatch loss example ----------
% Define an assumed TX polarization from boresight field:
e_bore = [Etheta(1); Ephi(1)];
p_tx = e_bore / norm(e_bore);
PML_dB = pol_mismatch_loss_dB(p_tx, u_rx);
fprintf('Polarization Mismatch Loss (boresight) vs selected RX: %.2f dB\
n', PML_dB);
Co-/Cross-Polar Projection
function [Eco, Ecx] = project_co_cross(Etheta, Ephi, u_rx)
% project_co_cross - Project field onto co- and cross-polar components.
% Inputs:
% Etheta, Ephi : field components vs angle (same size), complex
% u_rx : 2x1 unit vector defining receive polarization in
(θ,φ) basis
% Output:
% Eco, Ecx : co- and cross-polar components (same size as inputs)
%
% Co-pol is the projection onto u_rx; Cross-pol is onto the orthogonal
unit
% vector in the polarization space (local transverse plane).
%
% Orthonormal complement construction: for u = [u1; u2],
% u_perp = [-conj(u2); conj(u1)], then normalize.
assert(numel(u_rx)==2,'u_rx must be 2x1 polarization vector');
u = u_rx(:);
u = u / norm(u + 1e-24);
u_perp = [-conj(u(2)); conj(u(1))];
u_perp = u_perp / norm(u_perp + 1e-24);
E = [Etheta(:).'; Ephi(:).']; % 2 x N
Eco = sum(conj(u).*E, 1).'; % co-pol scalar vs angle
Ecx = sum(conj(u_perp).*E, 1).';% cross-pol scalar vs angle
% reshape to original size
Eco = reshape(Eco, size(Etheta));
Ecx = reshape(Ecx, size(Ephi));
end
Linear Polarization Unit Vector
function u = pol_unit_linear(psi_deg)
% pol_unit_linear - Unit polarization vector for linear tilt psi (deg)
% In local (θ,φ) plane: psi=0° -> pure θ-pol, psi=90° -> pure φ-pol.
psi = deg2rad(psi_deg);
u = [cos(psi); sin(psi)];
u = u / norm(u);
end
Circular Polarization Unit Vectors
function u = pol_unit_circ(hand)
% pol_unit_circ - Unit polarization vector for circular polarization
% hand: 'RHCP' or 'LHCP' (IEEE, wave toward +r)
% RHCP basis vector e_R = (1/√2)[1; j], LHCP e_L = (1/√2)[1; -j]
if strcmpi(hand,'RHCP')
u = (1/sqrt(2))*[1; 1j];
elseif strcmpi(hand,'LHCP')
u = (1/sqrt(2))*[1; -1j];
else
error('hand must be RHCP or LHCP');
end
end
Conversion: Spherical -> Circular
function [ER, EL] = sph_to_circ(Etheta, Ephi)
% sph_to_circ - Convert spherical (Eθ,Eφ) to circular (ER,EL)
ER = (Etheta + 1j*Ephi)/sqrt(2);
EL = (Etheta - 1j*Ephi)/sqrt(2);
end
Conversion: Circular -> Spherical
function [Etheta, Ephi] = circ_to_sph(ER, EL)
% circ_to_sph - Convert circular (ER,EL) to spherical (Eθ,Eφ)
Etheta = (ER + EL)/sqrt(2);
Ephi = -1j*(ER - EL)/sqrt(2);
end
Axial Ratio from Circular Components
function AR_lin = axial_ratio_from_circ(ER, EL)
% axial_ratio_from_circ - Axial ratio (linear) from circular components
% AR = (|ER| + |EL|)/(| |ER| - |EL| |); AR>=1
num = abs(ER) + abs(EL);
den = abs(abs(ER) - abs(EL)) + eps;
AR_lin = num ./ den;
end
Polarization Mismatch Loss
function PML_dB = pol_mismatch_loss_dB(p_tx, p_rx)
% pol_mismatch_loss_dB - Polarization mismatch loss between TX and RX
% Loss factor = 1 - |p_rx^H p_tx|^2 (power not captured)
% Mismatch loss (dB) = -10*log10(|p_rx^H p_tx|^2)
p_tx = p_tx(:)/norm(p_tx + 1e-24);
p_rx = p_rx(:)/norm(p_rx + 1e-24);
k = abs(p_rx' * p_tx)^2;
PML_dB = -10*log10(k + 1e-24);
end
Linear Basis Pair Helper
function [u_co, u_cross] = linear_basis_pair(psi_deg)
% linear_basis_pair - Orthonormal pair of linear polarizations at tilt
psi
u_co = pol_unit_linear(psi_deg);
u_cross = pol_unit_linear(psi_deg + 90);
end
Usage Notes
• Replace the synthetic ER/EL (or Eθ/Eφ) in the demo with your simulated/measured
fields.
• For full 2D patterns, loop over φ and store Eco/Ecx in matrices for contour plots.
• XPD (dB) here is 20·log10(|Eco|/|Ecx|) for a selected receive polarization; XPR (dB) is
10·log10(|ER|^2/|EL|^2).
• Conventions follow IEEE (observer looking in +r). If your simulator uses different circular
definitions, swap j signs accordingly.
• Ensure fields are referenced to the same phase center and normalization before
comparison.