Coverage for PyFHD/beam_setup/mwa.py: 0%
40 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-01 10:58 +0800
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-01 10:58 +0800
1import importlib_resources
2import numpy as np
3from numpy.typing import NDArray
4from astropy.io import fits
5from PyFHD.io.pyfhd_io import recarray_to_dict
6from scipy.io import readsav
9def dipole_mutual_coupling(
10 freq_arr: NDArray[np.floating],
11) -> NDArray[np.complexfloating]:
12 """
13 Calculate the mutual coupling for a dipole antenna at the given frequencies.
15 Parameters
16 ----------
17 freq_arr : NDArray[np.floating]
18 Array of frequencies in Hz.
20 Returns
21 -------
22 NDArray[np.complexfloating]
23 Array of mutual coupling values for the dipole antenna.
24 """
25 # Placeholder implementation, replace with actual mutual coupling calculation
26 z_matrix_file = importlib_resources.files(
27 "PyFHD.resources.instrument_config"
28 ).joinpath("mwa_ZMatrix.fits")
29 z_lna_file = importlib_resources.files(
30 "PyFHD.resources.instrument_config"
31 ).joinpath("mwa_LNA_impedance.sav")
32 n_dipole = 16
33 n_ant_pol = 2
35 # Read the Z matrix and LNA impedance from the files
36 z_matrix = fits.open(z_matrix_file)
37 z_mat_arr = np.zeros(
38 (len(z_matrix), n_ant_pol, n_dipole, n_dipole), dtype=np.complex128
39 )
40 freq_arr_z_mat = np.zeros(len(z_matrix), dtype=np.float64)
41 for ext_i in range(len(z_matrix)):
42 z_mat = z_matrix[ext_i].data
43 z_mat = z_mat[0] * (np.cos(z_mat[1]) + 1j * np.sin(z_mat[1]))
44 freq_arr_z_mat[ext_i] = z_matrix[ext_i].header["FREQ"]
45 z_mat_arr[ext_i, 0, :, :] = z_mat[n_dipole:, n_dipole:]
46 z_mat_arr[ext_i, 1, :, :] = z_mat[:n_dipole, :n_dipole]
47 z_matrix.close()
49 z_lna_dict = recarray_to_dict(readsav(z_lna_file)["lna_impedance"])
50 z_mat_return = np.zeros(
51 (n_ant_pol, freq_arr.size, n_dipole, n_dipole), dtype=np.complex128
52 )
53 z_mat_interp = np.zeros(
54 (freq_arr.size, n_ant_pol, n_dipole, n_dipole), dtype=np.complex128
55 )
56 for pol_i in range(n_ant_pol):
57 for di1 in range(n_dipole):
58 for di2 in range(n_dipole):
59 z_mat_interp[:, pol_i, di1, di2] = np.interp(
60 freq_arr_z_mat, freq_arr, z_mat_arr[:, pol_i, di1, di2]
61 )
63 zlna_arr = np.interp(z_lna_dict["z"], z_lna_dict["frequency"], freq_arr)
65 for fi in range(freq_arr.size):
66 z_lna = zlna_arr[fi] * np.identity(n_dipole)
67 z_inv_x = np.linalg.inv(z_lna + z_mat_interp[fi, 0])
68 z_inv_y = np.linalg.inv(z_lna + z_mat_interp[fi, 1])
70 # normalize to a zenith pointing, where voltage=Exp(icomp*2.*!Pi*Delay*frequency) and delay=0 so voltage=1.
72 norm_test_x = n_dipole / np.abs(np.sum(z_inv_x))
73 norm_test_y = n_dipole / np.abs(np.sum(z_inv_y))
74 z_inv_x *= norm_test_x
75 z_inv_y *= norm_test_y
77 z_mat_return[0, fi] = z_inv_x
78 z_mat_return[1, fi] = z_inv_y
80 return z_mat_return