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

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 

7 

8 

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. 

14 

15 Parameters 

16 ---------- 

17 freq_arr : NDArray[np.floating] 

18 Array of frequencies in Hz. 

19 

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 

34 

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() 

48 

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 ) 

62 

63 zlna_arr = np.interp(z_lna_dict["z"], z_lna_dict["frequency"], freq_arr) 

64 

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]) 

69 

70 # normalize to a zenith pointing, where voltage=Exp(icomp*2.*!Pi*Delay*frequency) and delay=0 so voltage=1. 

71 

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 

76 

77 z_mat_return[0, fi] = z_inv_x 

78 z_mat_return[1, fi] = z_inv_y 

79 

80 return z_mat_return