Skip to content

Commit 8615942

Browse files
committed
Simplify RFI support
1 parent 25e70bb commit 8615942

1 file changed

Lines changed: 36 additions & 77 deletions

File tree

  • processing_components/simulation

‎processing_components/simulation/rfi.py‎

Lines changed: 36 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from processing_library.util.array_functions import average_chunks2
2424
from processing_library.util.coordinate_support import xyz_to_uvw, skycoord_to_lmn
25+
from processing_components.visibility.base import simulate_point
2526

2627
def simulate_DTV(frequency, times, power=50e3, timevariable=False, frequency_variable=False):
2728
""" Calculate DTV sqrt(power) as a function of time and frequency
@@ -58,23 +59,6 @@ def simulate_DTV(frequency, times, power=50e3, timevariable=False, frequency_var
5859
return signal
5960

6061

61-
def add_noise(visibility, bandwidth, int_time):
62-
"""Determine noise rms per visibility
63-
64-
:returns: visibility with noise added
65-
"""
66-
# The specified sensitivity (effective area / T_sys) is roughly 610 m ^ 2 / K in the range 160 - 200MHz
67-
# sigma_vis = 2 k T_sys / (area * sqrt(tb)) = 2 k 512 / (610 * sqrt(tb)
68-
sens = 610
69-
k_b = 1.38064852e-23
70-
bt = bandwidth * int_time
71-
sigma = 2 * 1e26 * k_b / ((sens / 512) * (numpy.sqrt(bt)))
72-
print("RMS noise per sample = %g Jy" % sigma)
73-
sshape = visibility.shape
74-
visibility += numpy.random.normal(0.0, sigma, sshape) + 1j * numpy.random.normal(0.0, sigma, sshape)
75-
return visibility
76-
77-
7862
def create_propagators(config, interferer, frequency, attenuation=1e-9):
7963
""" Create a set of propagators
8064
@@ -96,62 +80,29 @@ def create_propagators(config, interferer, frequency, attenuation=1e-9):
9680
def calculate_rfi_at_station(propagators, emitter):
9781
""" Calculate the rfi at each station
9882
99-
:param propagators:
100-
:param emitter:
101-
:return: Complex array [nants, ntimes, nchannels]
83+
:param propagators: [nstations, nchannels]
84+
:param emitter: [ntimes, nchannels]
85+
:return: Complex array [nstations, ntimes, nchannels]
10286
"""
103-
rfi_at_station = emitter[numpy.newaxis, :, :] * propagators[:, numpy.newaxis, :]
87+
rfi_at_station = emitter[:, numpy.newaxis, ...] * propagators[numpy.newaxis, ...]
10488
rfi_at_station[numpy.abs(rfi_at_station)<1e-15] = 0.
10589
return rfi_at_station
10690

107-
108-
def calculate_station_fringe_rotation(ants_xyz, times, frequency, phasecentre, pole):
109-
"""Calculate fringe rotation vectors
110-
111-
:param ants_xyz:
112-
:param times:
113-
:param frequency:
114-
:param phasecentre:
115-
:param pole:
116-
:return: phasor, uvw
117-
"""
118-
119-
uvw = xyz_to_uvw(ants_xyz, times, phasecentre.dec.rad)
120-
nants, _ = uvw.shape
121-
ntimes = len(times)
122-
uvw = uvw.reshape([nants, 3, ntimes])
123-
uvw = numpy.transpose(uvw, [0, 2, 1])
124-
125-
l, m, n = skycoord_to_lmn(phasecentre, pole)
126-
s = numpy.array([l, m, numpy.sqrt(1 - l ** 2 - m ** 2) - 1.0])
127-
delay = numpy.dot(uvw, s)
128-
nchan = len(frequency)
129-
phase = numpy.zeros([nants, ntimes, nchan])
130-
for ant in range(nants):
131-
for chan in range(nchan):
132-
phase[ant, :, chan] = delay[ant] * frequency[chan] / constants.c.value
133-
phase[...] -= phase[0, :, :][numpy.newaxis,...]
134-
return numpy.exp(-2.0 * numpy.pi * 1j * phase), uvw
135-
136-
137-
def calculate_station_correlation_rfi(fringe_rotation, rfi_at_station):
138-
""" Form the correlation from the rfi at the station and the fringe rotation
91+
def calculate_station_correlation_rfi(rfi_at_station):
92+
""" Form the correlation from the rfi at the station
13993
140-
:param fringe_rotation:
14194
:param rfi_at_station:
14295
:return: Correlation(nant, nants, ntimes, nchan] in Jy
14396
"""
144-
phased_rotated_rfi_at_station = fringe_rotation * rfi_at_station
145-
nants, ntimes, nchan = fringe_rotation.shape
146-
correlation = numpy.zeros([nants, nants, ntimes, nchan], dtype='complex')
97+
ntimes, nants, nchan = rfi_at_station.shape
98+
correlation = numpy.zeros([ntimes, nants, nants, nchan], dtype='complex')
14799

148-
# We only phaserotate one station in an interferometer
149-
for time in range(ntimes):
100+
for itime in range(ntimes):
150101
for chan in range(nchan):
151-
correlation[..., time, chan] = numpy.outer(rfi_at_station[..., time, chan],
152-
numpy.conjugate(phased_rotated_rfi_at_station[..., time, chan]))
102+
correlation[itime, ..., chan] = numpy.outer(rfi_at_station[itime, :, chan],
103+
numpy.conjugate(rfi_at_station[itime, :, chan]))
153104

154-
return correlation * 1e26
105+
return correlation[..., numpy.newaxis] * 1e26
155106

156107

157108
def calculate_averaged_correlation(correlation, channel_width, time_width):
@@ -166,8 +117,7 @@ def calculate_averaged_correlation(correlation, channel_width, time_width):
166117
return average_chunks2(correlation, wts, (channel_width, time_width))[0]
167118

168119

169-
def simulate_rfi_block(config, times, frequency, phasecentre, emitter_location, emitter_power=5e4,
170-
attenuation=1.0):
120+
def simulate_rfi_block(bvis, emitter_location, emitter_power=5e4, attenuation=1.0):
171121
""" Simulate RFI block
172122
173123
:param config: ARL telescope Configuration
@@ -179,26 +129,35 @@ def simulate_rfi_block(config, times, frequency, phasecentre, emitter_location,
179129
:param attenuation: Attenuation to be applied to signal
180130
:return:
181131
"""
132+
182133
# Calculate the power spectral density of the DTV station: Watts/Hz
183-
emitter = simulate_DTV(frequency, times, power=emitter_power, timevariable=False)
134+
emitter = simulate_DTV(bvis.frequency, bvis.time, power=emitter_power, timevariable=False)
184135

185136
# Calculate the propagators for signals from Perth to the stations in low
186137
# These are fixed in time but vary with frequency. The ad hoc attenuation
187138
# is set to produce signal roughly equal to noise at LOW
188-
propagators = create_propagators(config, emitter_location, frequency=frequency,
139+
propagators = create_propagators(bvis.configuration, emitter_location, frequency=bvis.frequency,
189140
attenuation=attenuation)
190141
# Now calculate the RFI at the stations, based on the emitter and the propagators
191142
rfi_at_station = calculate_rfi_at_station(propagators, emitter)
192-
193-
# Station fringe rotation: shape [nants, ntimes, nchan] complex phasor to be applied to
194-
# reference to the pole.
143+
144+
# Calculate the rfi correlation using the fringe rotation and the rfi at the station
145+
# [ntimes, nants, nants, nchan, npol]
146+
bvis.data['vis'][...] = calculate_station_correlation_rfi(rfi_at_station)
147+
148+
ntimes, nant, _, nchan, npol = bvis.vis.shape
149+
195150
pole = SkyCoord(ra=+0.0 * u.deg, dec=-90.0 * u.deg, frame='icrs', equinox='J2000')
196-
ha = times * numpy.pi / 43200.0
197151

198-
fringe_rotation, uvw = calculate_station_fringe_rotation(config.xyz, ha, frequency, phasecentre, pole)
199-
200-
# Calculate the rfi correlationm using the fringe rotation and the rfi at the station
201-
# [nants, nants, ntimes, nchan]
202-
correlation = calculate_station_correlation_rfi(fringe_rotation, rfi_at_station)
203-
204-
return correlation, uvw
152+
# Calculate phasor needed to shift from the phasecentre to the pole
153+
l, m, n = skycoord_to_lmn(pole, bvis.phasecentre)
154+
k = numpy.array(bvis.frequency) / constants.c.to('m s^-1').value
155+
uvw = bvis.uvw[..., numpy.newaxis] * k
156+
phasor = numpy.ones([ntimes, nant, nant, nchan, npol], dtype='complex')
157+
for chan in range(nchan):
158+
phasor[:, :, :, chan, :] = simulate_point(uvw[..., chan], l, m)[..., numpy.newaxis]
159+
160+
# Now fill this into the BlockVisibility
161+
bvis.data['vis'] = bvis.data['vis'] * phasor
162+
163+
return bvis

0 commit comments

Comments
 (0)