Visualization#
This guide covers the visualization capabilities including 2D/3D plots, UV-space representation, and interactive Plotly figures.
2D Matplotlib Plots#
Basic Pattern Cut#
import phased_array as pa
import numpy as np
import matplotlib.pyplot as plt
# Create array and compute pattern
geom = pa.create_rectangular_array(16, 16, dx=0.5, dy=0.5)
k = pa.wavelength_to_k(1.0)
weights = pa.steering_vector(k, geom.x, geom.y, theta0_deg=30, phi0_deg=0)
weights *= pa.taylor_taper_2d(16, 16, sidelobe_dB=-30)
# Compute principal plane cuts
theta_deg, E_plane, H_plane = pa.compute_pattern_cuts(
geom.x, geom.y, weights, k,
theta0_deg=30, phi0_deg=0
)
# Plot
pa.plot_pattern_2d(
theta_deg, E_plane,
title='E-plane Pattern Cut',
xlabel='Theta (deg)',
ylabel='Normalized Gain (dB)',
xlim=(-90, 90),
ylim=(-50, 0)
)
Polar Plot#
pa.plot_pattern_polar(
theta_deg, E_plane,
title='E-plane (Polar)'
)
Contour Plot#
Full 2D pattern as a contour plot:
theta, phi, pattern_dB = pa.compute_full_pattern(
geom.x, geom.y, weights, k
)
pa.plot_pattern_contour(
np.rad2deg(theta),
np.rad2deg(phi),
pattern_dB,
title='2D Radiation Pattern',
levels=20,
cmap='jet',
min_dB=-40
)
Comparison Plots#
Compare multiple patterns on the same axes:
patterns = {}
# Uniform illumination
w_uniform = pa.steering_vector(k, geom.x, geom.y, 30, 0)
_, E_uniform, _ = pa.compute_pattern_cuts(geom.x, geom.y, w_uniform, k)
patterns['Uniform'] = E_uniform
# Taylor taper
w_taylor = w_uniform * pa.taylor_taper_2d(16, 16, sidelobe_dB=-30)
_, E_taylor, _ = pa.compute_pattern_cuts(geom.x, geom.y, w_taylor, k)
patterns['Taylor -30 dB'] = E_taylor
# Chebyshev taper
w_cheb = w_uniform * pa.chebyshev_taper_2d(16, 16, sidelobe_dB=-30)
_, E_cheb, _ = pa.compute_pattern_cuts(geom.x, geom.y, w_cheb, k)
patterns['Chebyshev -30 dB'] = E_cheb
pa.plot_comparison_patterns(
theta_deg, patterns,
title='Taper Comparison',
xlim=(-60, 60),
ylim=(-50, 0)
)
Array Geometry Plot#
pa.plot_array_geometry(
geom.x, geom.y,
weights=weights, # Color by weight magnitude
title='16x16 Array Element Positions'
)
UV-Space Visualization#
Direction cosine (UV) space is often more intuitive for array analysis as it shows the visible region and grating lobe locations clearly.
Computing UV-Space Pattern#
u, v, pattern_uv = pa.compute_pattern_uv_space(
geom.x, geom.y, weights, k,
n_u=201, n_v=201,
u_range=(-1, 1),
v_range=(-1, 1)
)
pa.plot_pattern_uv_space(
u, v, pattern_uv,
title='UV-Space Pattern',
show_visible_region=True # Circle at u^2+v^2=1
)
The visible region (u² + v² ≤ 1) corresponds to real angles. Points outside are evanescent.
3D Plotly (Interactive)#
Plotly provides interactive 3D visualizations that can be rotated, zoomed, and explored in a web browser.
Installation#
pip install plotly
3D Radiation Pattern#
Spherical surface where radius represents gain:
fig = pa.plot_pattern_3d_plotly(
theta, phi, pattern_dB,
title='3D Radiation Pattern',
min_dB=-40,
colorscale='Jet',
surface_type='spherical'
)
fig.show()
Cartesian 3D Surface#
Theta/phi/gain as a 3D surface:
fig = pa.plot_pattern_3d_cartesian_plotly(
theta, phi, pattern_dB,
title='Pattern Surface'
)
fig.show()
UV-Space (Plotly)#
fig = pa.plot_pattern_uv_plotly(
u, v, pattern_uv,
title='UV-Space Pattern',
min_dB=-40
)
fig.show()
3D Array Geometry#
For conformal arrays:
# Create cylindrical array
geom_cyl = pa.create_cylindrical_array(16, 4, radius=3.0, height=2.0)
fig = pa.plot_array_geometry_3d_plotly(
geom_cyl,
show_normals=True, # Display element normal vectors
title='Cylindrical Array'
)
fig.show()
Animated Patterns#
Create animations showing pattern changes (e.g., scanning beam):
# List of patterns at different scan angles
scan_angles = np.arange(0, 61, 5)
patterns_list = []
titles = []
for angle in scan_angles:
w = pa.steering_vector(k, geom.x, geom.y, angle, 0)
w *= pa.taylor_taper_2d(16, 16, sidelobe_dB=-30)
_, _, pat = pa.compute_full_pattern(geom.x, geom.y, w, k)
patterns_list.append(pat)
titles.append(f'Scan: {angle} deg')
fig = pa.create_pattern_animation_plotly(
theta, phi,
patterns_list,
frame_titles=titles,
animation_speed=500 # ms per frame
)
fig.show()
Wideband Visualization#
Beam Squint Plot#
wavelength = 0.03 # 10 GHz
geom = pa.create_rectangular_array(16, 16, dx=0.5, dy=0.5, wavelength=wavelength)
fig = pa.plot_beam_squint(
geom.x, geom.y,
theta0_deg=45, phi0_deg=0,
center_frequency=10e9,
bandwidth=2e9,
steering_modes=['phase', 'ttd']
)
fig.show()
Pattern vs Frequency#
fig = pa.plot_pattern_vs_frequency_plotly(
geom.x, geom.y,
theta0_deg=30, phi0_deg=0,
center_frequency=10e9,
bandwidth=2e9,
n_freqs=11,
steering_mode='phase'
)
fig.show()
Subarray Delays#
architecture = pa.create_rectangular_subarrays(
Nx_total=32, Ny_total=32,
Nx_sub=8, Ny_sub=8,
dx=0.5, dy=0.5, wavelength=wavelength
)
fig = pa.plot_subarray_delays(
architecture,
theta0_deg=45, phi0_deg=0
)
fig.show()
Saving Figures#
Matplotlib#
fig, ax = plt.subplots()
pa.plot_pattern_2d(theta_deg, E_plane, ax=ax)
fig.savefig('pattern.png', dpi=300, bbox_inches='tight')
fig.savefig('pattern.pdf', bbox_inches='tight')
Plotly#
# HTML (interactive)
fig.write_html('pattern_3d.html')
# Static image (requires kaleido)
fig.write_image('pattern_3d.png', scale=2)
fig.write_image('pattern_3d.pdf')
# Install kaleido for static export:
# pip install kaleido
Customization#
Matplotlib Style#
# Use a built-in style
plt.style.use('seaborn-v0_8-whitegrid')
# Or customize
plt.rcParams.update({
'font.size': 12,
'axes.labelsize': 14,
'axes.titlesize': 16,
'lines.linewidth': 2,
'figure.figsize': (10, 6)
})
Plotly Theme#
import plotly.io as pio
pio.templates.default = "plotly_white"
# Or use dark theme
pio.templates.default = "plotly_dark"
Best Practices#
Use UV-space for understanding grating lobes and visible region.
Use 3D Plotly for presentations and interactive exploration.
Use contour plots for comparing patterns across the full hemisphere.
Use pattern cuts for precise numerical comparisons.
Set appropriate min_dB to focus on the sidelobe region of interest.
Export high-resolution figures for publications (300+ DPI).