Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Example: GRASP coupling data

In this example, we describe the coupling between two standard gain horn antennas. Several cases are considered.

  • Zero movement definitions (Figure 1a). The antennas are looking face-to-face.

  • One movement definition (Figure 1b). The receiving antenna is rotated around antenna boresight. The coupling is evaulated at for rotation angles between 0° (brown; just like in Figure 1a), 30° (not shown), 60° (not shown), and 90° (white).

  • Two movement definitions (Figure 1c). Firsly, the receiving antenna is rotated around the transmitting antenna (gray arrow), described by the zenith angle θ\theta\,. The coupling is evaluated at the angles θ=0,15,30,45,60,95,90\theta=0^\circ,15^\circ,30^\circ,45^\circ,60^\circ,95^\circ,90^\circ\,. For each of these position, the receiving antenna is also moved around its boresight, just like in Figure 1b. For the initial position, this is illustrated by the white antenna. For the remaining positions, the rotated antenna is not drawn.

Example setup for antenna coupling simulation with GRASP from TICRA.

Figure 1:Example setup for antenna coupling simulation with GRASP from TICRA. Three setups are illustrated, corresponding to zero (a), one (b), and two movement definitions (c).

Imports and definitions for easy plotting

# import python libraries/modules
import os
import pint # for unit conversion when plotting
import numpy as np
import matplotlib.pyplot as plt

# import functions from pycra-tools
from pycra_tools import readcut_coupling, torfile

# function docstrings are available as follows:
# print(readcut_coupling.__doc__)
# print(torfile.__doc__)

Read data from files

directory_example_simulation = '/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example'
torfilepath = os.path.join(directory_example_simulation, 'Job_01', 'Job_01.tor')
cutfilepath0 = os.path.join(directory_example_simulation, 'Job_01', 'coupling_system_rx_zero.cut')
cutfilepath1 = os.path.join(directory_example_simulation, 'Job_01', 'coupling_system_rx_one.cut')
cutfilepath2 = os.path.join(directory_example_simulation, 'Job_01', 'coupling_system_rx_two.cut')

# read files
tordict = torfile.tor2dict(torfilepath)
da0 = readcut_coupling(cutfilepath=cutfilepath0, tordict=tordict)
da1 = readcut_coupling(cutfilepath=cutfilepath1, tordict=tordict)
da2 = readcut_coupling(cutfilepath=cutfilepath2, tordict=tordict)

Inspect structure of the dataframes

print('# print(da0)')
print(da0)
print('\n\n# print(da0.name)')
print(da0.name)
print('\n\n# print(da0.freq)')
print(da0.freq)
# print(da0)
<xarray.DataArray '/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_zero.cut' (
                                                                                                                                    freq: 3)> Size: 48B
array([-0.00248305-0.16498349j,  0.21188705+0.00160079j,
       -0.01177798+0.22985868j])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
Attributes:
    file_format:          cuts
    class_name:           coupling_system
    receiver_sources:     ['rectangular_horn_rx']
    amplitude_only:       off
    movement_definition:  None
    cqlist:               off
    comment:              None


# print(da0.name)
/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_zero.cut


# print(da0.freq)
<xarray.DataArray 'freq' (freq: 3)> Size: 24B
array([3.50e+09, 5.25e+09, 7.00e+09])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
Attributes:
    long_name:  frequency
    units:      Hz
print('# print(da1)')
print(da1)
print('\n\n# print(da1.name)')
print(da1.name)
print('\n\n# print(da1.freq)')
print(da1.freq)
print('\n\n# print(da1.m1)')
print(da1.m1)
# print(da1)
<xarray.DataArray '/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_one.cut' (
                                                                                                                                   freq: 3,
                                                                                                                                   m1: 4)> Size: 192B
array([[-2.48304943e-03-1.64983493e-01j, -2.15038389e-03-1.42879896e-01j,
        -1.24152472e-03-8.24917463e-02j,  4.75757215e-17+7.21852018e-18j],
       [ 2.11887051e-01+1.60078640e-03j,  1.83499569e-01+1.38632169e-03j,
         1.05943525e-01+8.00393198e-04j,  4.69455635e-17+8.56322568e-17j],
       [-1.17779783e-02+2.29858679e-01j, -1.02000285e-02+1.99063455e-01j,
        -5.88898917e-03+1.14929340e-01j, -2.39144714e-18+3.16118334e-16j]])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
  * m1       (m1) float64 32B 0.0 30.0 60.0 90.0
Attributes:
    file_format:          cuts
    class_name:           coupling_system
    receiver_sources:     ['rectangular_horn_rx']
    amplitude_only:       off
    movement_definition:  movement_definition_rx_one
    cqlist:               off
    comment:              None


# print(da1.name)
/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_one.cut


# print(da1.freq)
<xarray.DataArray 'freq' (freq: 3)> Size: 24B
array([3.50e+09, 5.25e+09, 7.00e+09])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
Attributes:
    long_name:  frequency
    units:      Hz


# print(da1.m1)
<xarray.DataArray 'm1' (m1: 4)> Size: 32B
array([ 0., 30., 60., 90.])
Coordinates:
  * m1       (m1) float64 32B 0.0 30.0 60.0 90.0
Attributes:
    long_name:  rotation_around (z_original)
    name:       rotation_around (z_original)
    units:      deg
print('# print(da2)')
print(da2)
print('\n\n# print(da2.name)')
print(da2.name)
print('\n\n# print(da2.freq)')
print(da2.freq)
print('\n\n# print(da2.m1)')
print(da2.m1)
print('\n\n# print(da2.m2)')
print(da2.m2)
# print(da2)
<xarray.DataArray '/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_two.cut' (
                                                                                                                                   freq: 3,
                                                                                                                                   m1: 7,
                                                                                                                                   m2: 4)> Size: 1kB
array([[[-2.48304943e-03-1.64983493e-01j,
         -2.15038389e-03-1.42879896e-01j,
         -1.24152472e-03-8.24917463e-02j,
          4.75757215e-17+7.21852018e-18j],
        [ 1.48517648e-02-1.04625827e-01j,
          1.28620056e-02-9.06086240e-02j,
          7.42588238e-03-5.23129134e-02j,
          2.59070547e-17+3.01849777e-17j],
        [ 2.53641241e-02-1.60862233e-02j,
          2.19659758e-02-1.39310780e-02j,
          1.26820621e-02-8.04311164e-03j,
          1.16416316e-18+1.20087308e-17j],
        [ 1.08795627e-02+1.15407139e-02j,
          9.42197769e-03+9.99455146e-03j,
          5.43978136e-03+5.77035697e-03j,
          1.73904875e-18-6.15850079e-18j],
        [-5.16611446e-04+6.11390793e-03j,
         -4.47398636e-04+5.29479958e-03j,
         -2.58305723e-04+3.05695396e-03j,
         -8.67982156e-18-1.21707225e-17j],
...
        [ 1.39397997e-02-1.06585942e-02j,
          1.20722206e-02-9.23061338e-03j,
          6.96989984e-03-5.32929712e-03j,
         -3.25434783e-17-7.23221678e-17j],
        [-4.72514398e-03+3.13070223e-03j,
         -4.09209472e-03+2.71126767e-03j,
         -2.36257199e-03+1.56535112e-03j,
         -2.09229321e-18-1.31877321e-17j],
        [ 9.45057740e-04-1.80216342e-03j,
          8.18444011e-04-1.56071931e-03j,
          4.72528870e-04-9.01081711e-04j,
         -1.13878789e-17+1.35449776e-17j],
        [ 1.84267059e-03+5.20571432e-04j,
          1.59579954e-03+4.50828085e-04j,
          9.21335295e-04+2.60285716e-04j,
         -8.81949650e-18+2.18389998e-17j],
        [ 8.05691312e-04+6.67543953e-04j,
          6.97749143e-04+5.78110022e-04j,
          4.02845656e-04+3.33771977e-04j,
         -1.58117891e-18-1.46989433e-17j]]])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
  * m1       (m1) float64 56B 0.0 15.0 30.0 45.0 60.0 75.0 90.0
  * m2       (m2) float64 32B 0.0 30.0 60.0 90.0
Attributes:
    file_format:          cuts
    class_name:           coupling_system
    receiver_sources:     ['rectangular_horn_rx']
    amplitude_only:       off
    movement_definition:  movement_definition_rx_two
    cqlist:               off
    comment:              None


# print(da2.name)
/home/phjschmid/phdphysics/simulation/projects/pycra_tools/coupling_example/Job_01/coupling_system_rx_two.cut


# print(da2.freq)
<xarray.DataArray 'freq' (freq: 3)> Size: 24B
array([3.50e+09, 5.25e+09, 7.00e+09])
Coordinates:
  * freq     (freq) float64 24B 3.5e+09 5.25e+09 7e+09
Attributes:
    long_name:  frequency
    units:      Hz


# print(da2.m1)
<xarray.DataArray 'm1' (m1: 7)> Size: 56B
array([ 0., 15., 30., 45., 60., 75., 90.])
Coordinates:
  * m1       (m1) float64 56B 0.0 15.0 30.0 45.0 60.0 75.0 90.0
Attributes:
    long_name:  rotation_around (y_original)
    name:       rotation_around (y_original)
    units:      deg


# print(da2.m2)
<xarray.DataArray 'm2' (m2: 4)> Size: 32B
array([ 0., 30., 60., 90.])
Coordinates:
  * m2       (m2) float64 32B 0.0 30.0 60.0 90.0
Attributes:
    long_name:  rotation_around (z_new)
    name:       rotation_around (z_new)
    units:      deg

Visualize data

Let us plot the data that is stored in the three dataframes discussed above. For simplifying the comparison, let us choose the same axis for all the figures.

# chose common axis limits for all plots
ymax = (1+max(np.abs(da0).max(),np.abs(da1).max(),np.abs(da2).max())//0.05)*0.05
ylims = [0,ymax]

# prepare unit conversion tool
ureg = pint.UnitRegistry()

Zero movement defintions

# zero movement definitions (face-to-face coupling)
fig, ax = plt.subplots()
ax.plot([(freq * ureg[da1.freq.units]).to('GHz').magnitude for freq in da0.freq.values], np.abs(da0.data), marker='o')
ax.grid(True, which='major', axis='both')
ax.set_ylim(ylims)
ax.set_xlabel(f'{da0.freq.long_name} (GHz)')
ax.set_ylabel('coupling')
<Figure size 640x480 with 1 Axes>

One movement defintion

fig, ax = plt.subplots()
ax.set_xlabel(f'"{da1.m1.long_name}" ({da1.m1.units})')
ax.set_ylabel('coupling')
ax.grid(True, which='major', axis='both')
for freq in da1.freq.values:
    freqGHz = (freq * ureg[da1.freq.units]).to('GHz').magnitude
    ax.plot(da1.sel(freq=freq).m1.values, np.abs(da1.sel(freq=freq).data), marker='o', 
            label=f'{freqGHz} GHz')
ax.set_ylim(ylims)
ax.legend(title=da1.freq.long_name)
<Figure size 640x480 with 1 Axes>

Two movement defintions

freq = da2.freq.values[0]
fig, ax = plt.subplots(1,3,figsize=(6*3+2,6))
for ii,freq in enumerate(da2.freq.values):
    ax[ii].set_title(f"{(freq * ureg[da2.freq.units]).to('GHz').magnitude} GHz")
    ax[ii].set_xlabel(f'"{da2.m2.long_name}" ({da2.m2.units})')
    ax[ii].set_ylabel('coupling')
    ax[ii].grid(True, which='major', axis='both')
    for m1 in da2.m1.values:
        ax[ii].plot(da2.sel(freq=freq, m1=m1).m2.values, np.abs(da2.sel(freq=freq, m1=m1).data), marker='o',
                    label=f'{m1} {da2.m1.units}')
    ax[ii].set_ylim(ylims)
    ax[ii].legend(title=f'"{da2.m1.long_name}"')
plt.show()
<Figure size 2000x600 with 3 Axes>