[1]:
%load_ext autoreload
%autoreload 2

from radar.components import geometry
from radar.utils.calculate import convert
from radar.utils.typing.enums import FrequencyUnit
from radar.utils.typing.units import Frequency

from radar.components import Element
from radar.utils.calculate import pattern
from radar.utils.typing import (
    PhaseUnit,
    DirectionDomain,
    FigureType,
    AmplitudeDomain,
    Angle,
    AmplitudeUnit,
)

from radar.components.array import Array
import polars as pl

from radar.utils.typing.constants import DataHeader

Altering a Grid Array

And show its beam pattern

[2]:
beam_width = 30
beam_width_tuple = (
    Angle(beam_width, PhaseUnit.DEGREE),
    Angle(beam_width, PhaseUnit.DEGREE),
)

az_bound = 90
el_bound = 90
az_bound_tuple = (Angle(-az_bound, PhaseUnit.DEGREE), Angle(az_bound, PhaseUnit.DEGREE))
el_bound_tuple = (Angle(-el_bound, PhaseUnit.DEGREE), Angle(el_bound, PhaseUnit.DEGREE))


element_pattern = pattern.Isotropic()
freq = Frequency(1, FrequencyUnit.GIGAHERTZ)
antenna_element = Element(element_pattern, az_bound_tuple, el_bound_tuple, freq, 1)

cf = Frequency(1, FrequencyUnit.GIGAHERTZ)
distance = convert.cf_to_min_dist(cf)
array_geometry = geometry.Grid(21, 21, distance)

Array Element Weights

[3]:
array_geometry.plot.geometry()

Define Arrays with Different Element Amplitude Weights

Using the specificed geometry and element

Default Geometry

[4]:
arr = Array(antenna_element, array_geometry)

arr.plot.beam(
    DirectionDomain.ANGLE,
    PhaseUnit.DEGREE,
    AmplitudeDomain.AntennaFactor,
    AmplitudeUnit.DECIBEL,
    FigureType.SURFACE,
    Frequency(1, FrequencyUnit.GIGAHERTZ),
)

Convert Grid to Cross

by taking the initialised geometry and setting amplitude scaling of all non cross elements (x | y = 0) to 0

[5]:
df = array_geometry.df

grid_filter = (abs(pl.col(DataHeader.X_POS_M)) < 0.01) | (
    abs(pl.col(DataHeader.Y_POS_M)) < 0.01
)

df = df.with_columns(df.select(new_amps=pl.when(grid_filter).then(1).otherwise(0)))
df = df.drop(DataHeader.GEOM_AMP_GAIN_LIN, DataHeader.GEOM_AMP_GAIN_DB).rename(
    {"new_amps": DataHeader.GEOM_AMP_GAIN_LIN}
)

df.head()
[5]:
shape: (5, 5)
x_my_mElement Phase Shifter Phase (Degree)Element Phase Shifter Phase (Radian)Element Amplifier Gain (Linear)
f64f64i32i32i32
1.349066-1.049274000
-0.149896-0.449689000
-1.4989621.498962000
-1.199170.449689000
-1.349066-0.599585000
[6]:
array_geometry.gains = df
array_geometry.plot.geometry()
[7]:
arr = Array(antenna_element, array_geometry)

arr.plot.beam(
    DirectionDomain.ANGLE,
    PhaseUnit.DEGREE,
    AmplitudeDomain.AntennaFactor,
    AmplitudeUnit.DECIBEL,
    FigureType.SURFACE,
    Frequency(1, FrequencyUnit.GIGAHERTZ),
)

Windowing a Linear Array

Or we can show how to window a linear array

No Windowing

[8]:
# Create Antenna Element
from radar.utils.typing.enums import ArrayOrientation


beam_width = 5
beam_width_tuple = (
    Angle(beam_width, PhaseUnit.DEGREE),
    Angle(beam_width, PhaseUnit.DEGREE),
)

az_bound = 90
el_bound = 0
az_bound_tuple = (Angle(-az_bound, PhaseUnit.DEGREE), Angle(az_bound, PhaseUnit.DEGREE))
el_bound_tuple = (Angle(-el_bound, PhaseUnit.DEGREE), Angle(el_bound, PhaseUnit.DEGREE))


element_pattern = pattern.Isotropic()
freq = Frequency(1, FrequencyUnit.GIGAHERTZ)

antenna_element = Element(element_pattern, az_bound_tuple, el_bound_tuple, freq, 1)

# Define Geometry
cf = Frequency(1, FrequencyUnit.GIGAHERTZ)
distance = convert.cf_to_min_dist(cf)
array_geometry = geometry.Linear(11, ArrayOrientation.AZIMUTH, distance)

arr = Array(antenna_element, array_geometry)

arr.plot.beam(
    DirectionDomain.ANGLE,
    PhaseUnit.DEGREE,
    AmplitudeDomain.AntennaFactor,
    AmplitudeUnit.DECIBEL,
    FigureType.SLICE,
    Frequency(1, FrequencyUnit.GIGAHERTZ),
)

Windowing

Generate Window

[9]:
import numpy as np
import plotly.express as px

df = array_geometry.df
window = np.hamming(len(df))

df = df.drop(DataHeader.GEOM_AMP_GAIN_DB)
df = df.with_columns(pl.lit(window).alias(DataHeader.GEOM_AMP_GAIN_LIN))

fig = px.line(
    window,
    title="Array Beam Pattern Comparison",
    labels={"value": "Normalized Magnitude (dB)", "variable": "Window Function"},
)

fig.update_layout(
    hovermode="x unified",  # Shows all values when hovering over an angle
    template="plotly_white",
)

fig.show()

Applied Element Window

[10]:
array_geometry.gains = df
array_geometry.plot.geometry()

Applied Window Beam Pattern

[11]:
arr = Array(antenna_element, array_geometry)

arr.plot.beam(
    DirectionDomain.ANGLE,
    PhaseUnit.DEGREE,
    AmplitudeDomain.AntennaFactor,
    AmplitudeUnit.DECIBEL,
    FigureType.SLICE,
    Frequency(1, FrequencyUnit.GIGAHERTZ),
)