Skip to content

Commit a6ea0a4

Browse files
authored
Merge pull request #379 from HERA-Team/allow_combine_interleaved_pspec
Unique time-keys in `UVPSpec` objects based on `time_1_array` and `time_2_array` instead of the current `time_avg_array`
2 parents 64060c3 + fef5dd8 commit a6ea0a4

File tree

13 files changed

+212
-144
lines changed

13 files changed

+212
-144
lines changed

hera_pspec/grouping.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,11 @@ def average_spectra(uvp_in, blpair_groups=None, time_avg=False,
540540
for bl in bl_arr])
541541

542542
# Assign arrays and metadata to UVPSpec object
543-
uvp.Ntimes = len(np.unique(time_avg_arr))
544-
uvp.Nblpairts = len(time_avg_arr)
543+
uvp.Ntimes = len(np.unique(np.hstack([time_1, time_2])))
544+
uvp.Nbltpairs = len(time_avg_arr)
545545
uvp.Nblpairs = len(np.unique(blpair_arr))
546546
uvp.Nbls = len(bl_arr)
547+
uvp.Ntpairs = len(set((t1, t2) for t1, t2 in zip(time_1, time_2)))
547548

548549
# Baselines
549550
uvp.bl_array = bl_arr
@@ -733,7 +734,7 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
733734
E = np.zeros((uvp.Ntimes, Ndlyblps, Ndlys, uvp.Npols), dtype=np.float64)
734735

735736

736-
# get kperps for this spw: shape (Nblpairts,)
737+
# get kperps for this spw: shape (Nbltpairs,)
737738
kperps = uvp.get_kperps(spw, little_h=True)
738739

739740
# get kparas for this spw: shape (Ndlys,)
@@ -914,7 +915,7 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
914915
blp = uvp.blpair_array[0]
915916
blp_inds = uvp.blpair_to_indices(blp)
916917
uvp.blpair_array = uvp.blpair_array[blp_inds]
917-
uvp.Nblpairts = uvp.Ntimes
918+
uvp.Nbltpairs = uvp.Ntpairs
918919
uvp.Nblpairs = 1
919920
bl_array = np.unique([uvp.antnums_to_bl(an) for an in uvp.blpair_to_antnums(blp)])
920921
uvp.bl_vecs = np.asarray([uvp.bl_vecs[np.argmin(uvp.bl_array - bl)] for bl in bl_array])

hera_pspec/plot.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ def delay_waterfall(uvp, blpairs, spw, pol, component='abs-real',
384384
"""
385385
import matplotlib
386386
import matplotlib.pyplot as plt
387+
import matplotlib.axes
387388

388389
# assert component
389390
assert component in ['real', 'abs', 'imag', 'abs-real', 'abs-imag'], "Can't parse specified component {}".format(component)
@@ -1076,4 +1077,4 @@ def _round_sigfig(x, up=True):
10761077
if up:
10771078
return np.ceil(10**sigfigs * x) / 10**sigfigs
10781079
else:
1079-
return np.floor(10**sigfigs * x) / 10**sigfigs
1080+
return np.floor(10**sigfigs * x) / 10**sigfigs

hera_pspec/pspecdata.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ def add(self, dsets, wgts, labels=None, dsets_std=None, cals=None, cal_flag=True
243243
break
244244

245245
# Store no. frequencies and no. times
246+
# We are still only supporting dsets with same number of times
246247
self.Nfreqs = self.dsets[0].Nfreqs
247248
self.Ntimes = self.dsets[0].Ntimes
248249

@@ -326,8 +327,8 @@ def validate_datasets(self, verbose=True):
326327

327328
# Check phase centers if phase type is phased
328329
if 'phased' in set(phase_types):
329-
phase_ra = [d.phase_center_ra_degrees for d in self.dsets]
330-
phase_dec = [d.phase_center_dec_degrees for d in self.dsets]
330+
phase_ra = [d.phase_center_app_ra_degrees for d in self.dsets]
331+
phase_dec = [d.phase_center_app_dec_degrees for d in self.dsets]
331332
max_diff_ra = np.max( [np.diff(d)
332333
for d in itertools.combinations(phase_ra, 2)])
333334
max_diff_dec = np.max([np.diff(d)
@@ -3119,6 +3120,7 @@ def pspec(self, bls1, bls2, dsets, pols, n_dlys=None,
31193120
pols = _pols
31203121

31213122
# initialize empty lists
3123+
# We should really pre-allocate arrays instead.
31223124
data_array = odict()
31233125
wgt_array = odict()
31243126
integration_array = odict()
@@ -3484,8 +3486,15 @@ def pspec(self, bls1, bls2, dsets, pols, n_dlys=None,
34843486
% (2*np.pi)
34853487
uvp.blpair_array = np.array(blp_arr)
34863488
uvp.Nblpairs = len(np.unique(blp_arr))
3487-
uvp.Ntimes = len(np.unique(time1))
3488-
uvp.Nblpairts = len(time1)
3489+
# Ntimes in a uvpspec object now means the total number of times.
3490+
# In all possible datasets that could be produced by pspecdata this
3491+
# is equal to Ntpairs or 2 x Ntpairs if we interleave
3492+
# but we have given upspec the capability to have this
3493+
# not necessarily be the same.
3494+
# Ntimes could still be the number of "average times" which might be useful for noise purposes.
3495+
uvp.Ntimes = len(np.unique(np.hstack([uvp.time_1_array, uvp.time_2_array])))
3496+
uvp.Nbltpairs = len(set([(blp, t1, t2) for blp, t1, t2 in zip(uvp.blpair_array, uvp.time_1_array, uvp.time_2_array)]))
3497+
uvp.Ntpairs = len(set([(t1, t2) for t1, t2 in zip(uvp.time_1_array, uvp.time_2_array)]))
34893498
bls_arr = sorted(set(bls_arr))
34903499
uvp.bl_array = np.array([uvp.antnums_to_bl(bl) for bl in bls_arr])
34913500
antpos = dict(zip(dset1.antenna_numbers, dset1.antenna_positions))
@@ -3516,9 +3525,9 @@ def pspec(self, bls1, bls2, dsets, pols, n_dlys=None,
35163525
label1 = self.labels[self.dset_idx(dsets[0])]
35173526
label2 = self.labels[self.dset_idx(dsets[1])]
35183527
uvp.labels = sorted(set([label1, label2]))
3519-
uvp.label_1_array = np.ones((uvp.Nspws, uvp.Nblpairts, uvp.Npols), int) \
3528+
uvp.label_1_array = np.ones((uvp.Nspws, uvp.Nbltpairs, uvp.Npols), int) \
35203529
* uvp.labels.index(label1)
3521-
uvp.label_2_array = np.ones((uvp.Nspws, uvp.Nblpairts, uvp.Npols), int) \
3530+
uvp.label_2_array = np.ones((uvp.Nspws, uvp.Nbltpairs, uvp.Npols), int) \
35223531
* uvp.labels.index(label2)
35233532
uvp.labels = np.array(uvp.labels, str)
35243533
uvp.r_params = uvputils.compress_r_params(r_params)

hera_pspec/testing.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def build_vanilla_uvpspec(beam=None):
6161
time_array = np.repeat(time_array, Nblpairs)
6262
time_1_array = time_array
6363
time_2_array = time_array
64+
Ntpairs = len(set([(t1, t2) for t1, t2 in zip(time_1_array, time_2_array)]))
65+
Nbltpairs = len(set([(blp, t1, t2) for blp, t1, t2 in zip(blpair_array, time_1_array, time_2_array)]))
6466
lst_array = np.repeat(lst_array, Nblpairs)
6567
lst_1_array = lst_array
6668
lst_2_array = lst_array
@@ -153,7 +155,8 @@ def build_vanilla_uvpspec(beam=None):
153155
"Nspwfreqs",
154156
"Nspws",
155157
"Nblpairs",
156-
"Nblpairts",
158+
"Nbltpairs",
159+
"Ntpairs",
157160
"Npols",
158161
"Ndlys",
159162
"Nbls",

hera_pspec/tests/test_grouping.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def test_average_spectra(self):
130130
uvp.set_stats("noise", key, error)
131131

132132
# Add the simple error bar (all are set to be one) to stat_array
133-
errs = np.ones((uvp.Ntimes, uvp.Ndlys))
133+
errs = np.ones((uvp.Ntpairs, uvp.Ndlys))
134134
for key in keys:
135135
uvp.set_stats("simple", key, errs)
136136
blpair_groups = [blpairs]
@@ -158,7 +158,7 @@ def test_average_spectra(self):
158158
# is 1/sqrt{N} times the error bar on one single sample.
159159
averaged_stat = uvp_avg_simple_wgts.stats_array["simple"][0][0, 0, 0]
160160
initial_stat = uvp.stats_array["simple"][0][0, 0, 0] \
161-
/ np.sqrt(uvp.Ntimes) / np.sqrt(len(blpairs))
161+
/ np.sqrt(uvp.Ntpairs) / np.sqrt(len(blpairs))
162162
assert np.all(np.isclose(initial_stat, averaged_stat))
163163

164164
# For non-uniform weights, we test the error bar on the average power
@@ -173,7 +173,7 @@ def test_average_spectra(self):
173173
# it matches initial over sqrt(Nblpairs - 1)
174174
uvp_inf_var = copy.deepcopy(uvp)
175175
initial_stat = uvp.get_stats('simple', (0, blpairs[0], 'xx'))
176-
inf_var_stat = np.ones((uvp_inf_var.Ntimes, uvp_inf_var.Ndlys)) * np.inf
176+
inf_var_stat = np.ones((uvp_inf_var.Ntpairs, uvp_inf_var.Ndlys)) * np.inf
177177
uvp_inf_var.set_stats('simple', (0, blpairs[1], 'xx'), inf_var_stat)
178178
uvp_inf_var_avg = uvp_inf_var.average_spectra(blpair_groups=blpair_groups,
179179
error_weights='simple',
@@ -185,7 +185,7 @@ def test_average_spectra(self):
185185
# and check that averaged stat for that time is inf (not zero)
186186
uvp_inf_var = copy.deepcopy(uvp)
187187
initial_stat = uvp.get_stats('simple', (0, blpairs[0], 'xx'))
188-
inf_var_stat = np.ones((uvp_inf_var.Ntimes, uvp_inf_var.Ndlys))
188+
inf_var_stat = np.ones((uvp_inf_var.Ntpairs, uvp_inf_var.Ndlys))
189189
inf_var_stat[0] = np.inf
190190
for blp in blpairs:
191191
uvp_inf_var.set_stats('simple', (0, blp, 'xx'), inf_var_stat)
@@ -220,8 +220,8 @@ def test_average_spectra(self):
220220
normalize_weights=True,
221221
inplace=False,
222222
add_to_history='')
223-
assert uvp_time_avg.Nblpairts == uvp_time_avg.Nblpairs
224-
assert uvp_time_avg.window_function_array[0].shape[0] == uvp_time_avg.Nblpairts
223+
assert uvp_time_avg.Nbltpairs == uvp_time_avg.Nblpairs
224+
assert uvp_time_avg.window_function_array[0].shape[0] == uvp_time_avg.Nbltpairs
225225
blpair_groups, blpair_lens, _ = uvp.get_red_blpairs()
226226

227227
# redundant average
@@ -234,7 +234,7 @@ def test_average_spectra(self):
234234
normalize_weights=True,
235235
inplace=False,
236236
add_to_history='')
237-
assert uvp_red_avg.Nblpairts == uvp_red_avg.Ntimes
237+
assert uvp_red_avg.Nbltpairs == uvp_red_avg.Ntpairs
238238

239239
# both + error_weights
240240
keys = uvp.get_all_keys()
@@ -292,8 +292,8 @@ def test_bootstrap_average_blpairs(self):
292292
blpair_groups,
293293
time_avg=True)
294294
assert uvp1[0].Nblpairs == 1
295-
assert uvp1[0].Ntimes == self.uvp.Ntimes
296-
assert uvp2[0].Ntimes == 1
295+
assert uvp1[0].Ntpairs == self.uvp.Ntpairs
296+
assert uvp2[0].Ntpairs == 1
297297

298298
# Total of weights assigned should equal total no. of blpairs
299299
assert np.sum(wgts) == np.array(blpair_groups).size
@@ -308,7 +308,7 @@ def test_bootstrap_average_blpairs(self):
308308
_blpairs = list(np.unique(self.uvp.blpair_array)[:3])
309309
uvp3 = self.uvp.select(spws=0, inplace=False, blpairs=_blpairs)
310310

311-
Nt = uvp3.Ntimes
311+
Nt = uvp3.Ntpairs
312312
uvp3.data_array[0][Nt:2*Nt] = uvp3.data_array[0][:Nt]
313313
uvp3.data_array[0][2*Nt:] = uvp3.data_array[0][:Nt]
314314
uvp3.integration_array[0][Nt:2*Nt] = uvp3.integration_array[0][:Nt]
@@ -438,7 +438,7 @@ def test_bootstrap_run():
438438

439439
# assert average only has one time and 3 blpairs
440440
uvp_avg = psc.get_pspec("grp1", "uvp_avg")
441-
assert uvp_avg.Ntimes == 1
441+
assert uvp_avg.Ntpairs == 1
442442
assert uvp_avg.Nblpairs == 3
443443

444444
# check avg file history
@@ -507,11 +507,11 @@ def test_spherical_average():
507507

508508
# insert cov_array and stats_array
509509
uvp.cov_model = 'empirical'
510-
uvp.cov_array_real = {s: np.repeat(np.repeat(np.eye(uvp.Ndlys, dtype=np.float64)[None, : , :, None], uvp.Nblpairts, 0), uvp.Npols, -1)
510+
uvp.cov_array_real = {s: np.repeat(np.repeat(np.eye(uvp.Ndlys, dtype=np.float64)[None, : , :, None], uvp.Nbltpairs, 0), uvp.Npols, -1)
511511
for s in range(uvp.Nspws)}
512-
uvp.cov_array_imag = {s: np.repeat(np.repeat(np.eye(uvp.Ndlys, dtype=np.float64)[None, : , :, None], uvp.Nblpairts, 0), uvp.Npols, -1)
512+
uvp.cov_array_imag = {s: np.repeat(np.repeat(np.eye(uvp.Ndlys, dtype=np.float64)[None, : , :, None], uvp.Nbltpairs, 0), uvp.Npols, -1)
513513
for s in range(uvp.Nspws)}
514-
uvp.stats_array = {'err': {s: np.ones((uvp.Nblpairts, uvp.Ndlys, uvp.Npols), dtype=np.complex128)
514+
uvp.stats_array = {'err': {s: np.ones((uvp.Nbltpairs, uvp.Ndlys, uvp.Npols), dtype=np.complex128)
515515
for s in range(uvp.Nspws)}}
516516

517517
# try a spherical average
@@ -539,8 +539,8 @@ def test_spherical_average():
539539
assert np.isclose(np.sqrt(sph.cov_array_real[spw])[:, range(Nk), range(Nk)], 1/np.sqrt(A[spw].sum(axis=1))).all()
540540
assert np.isclose(sph.stats_array['err'][spw], 1/np.sqrt(A[spw].sum(axis=1))).all()
541541

542-
# bug check: time_avg_array was not down-selected to new Nblpairts
543-
assert sph.time_avg_array.size == sph.Nblpairts
542+
# bug check: time_avg_array was not down-selected to new Nbltpairs
543+
assert sph.time_avg_array.size == sph.Nbltpairs
544544

545545
# bug check: cov_array_imag was not updated
546546
assert sph.cov_array_real[0].shape == sph.cov_array_imag[0].shape
@@ -552,7 +552,7 @@ def test_spherical_average():
552552

553553
# try time average
554554
sph = grouping.spherical_average(uvp, kbins, bin_widths, time_avg=True)
555-
assert sph.Ntimes == 1
555+
assert sph.Ntpairs == 1
556556

557557
# try weighting by stats_array
558558
sph = grouping.spherical_average(uvp, kbins, bin_widths, error_weights='err')

hera_pspec/tests/test_noise.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def test_analytic_noise():
178178
frac_ratio = (uvp.stats_array["P_SN"][0] - uvp.stats_array["P_N"][0]) / uvp.stats_array["P_N"][0]
179179
dlys = uvp.get_dlys(0) * 1e9
180180
select = np.abs(dlys) > 3000
181-
assert np.abs(frac_ratio[:, select].mean()) < 1 / np.sqrt(uvp.Nblpairts)
181+
assert np.abs(frac_ratio[:, select].mean()) < 1 / np.sqrt(uvp.Nbltpairs)
182182

183183
# test single time
184184
uvp.select(times=uvp.time_avg_array[:1], inplace=True)
@@ -187,7 +187,7 @@ def test_analytic_noise():
187187
frac_ratio = (uvp.stats_array["P_SN"][0] - uvp.stats_array["P_N"][0]) / uvp.stats_array["P_N"][0]
188188
dlys = uvp.get_dlys(0) * 1e9
189189
select = np.abs(dlys) > 3000
190-
assert np.abs(frac_ratio[:, select].mean()) < 1 / np.sqrt(uvp.Nblpairts)
190+
assert np.abs(frac_ratio[:, select].mean()) < 1 / np.sqrt(uvp.Nbltpairs)
191191

192192
# clean up
193193
os.remove(os.path.join(DATA_PATH, "test_uvd.uvh5"))

hera_pspec/tests/test_plot.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def test_plot_average(self):
108108
# Average over baseline-pairs but keep the time bins intact
109109
f2 = plot.delay_spectrum(self.uvp, [blps,], spw=0, pol=('xx','xx'),
110110
average_blpairs=True, average_times=False)
111-
elements = [(matplotlib.lines.Line2D, self.uvp.Ntimes),]
111+
elements = [(matplotlib.lines.Line2D, self.uvp.Ntpairs),]
112112
assert axes_contains(f2.axes[0], elements)
113113
plt.close(f2)
114114

@@ -215,7 +215,9 @@ def test_delay_spectrum_misc(self):
215215
for i in range(3):
216216
# build-up a large uvpspec object
217217
_uvp = copy.deepcopy(uvp)
218-
_uvp.time_avg_array += (i+1)**2
218+
_uvp.time_avg_array += 0 # don't change avg time to make sure this is ok.
219+
_uvp.time_1_array += (i+1)**2
220+
_uvp.time_2_array += (i+1)**2
219221
uvp = uvp + _uvp
220222
pytest.raises(ValueError, plot.delay_spectrum, uvp, uvp.get_blpairs(), 0, 'xx')
221223

hera_pspec/tests/test_uvpspec.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ def _add_optionals(self, uvp):
5353
uvp.stats_array = odict({stat: odict()})
5454
for spw in uvp.spw_array:
5555
ndlys = uvp.get_spw_ranges(spw)[0][-1]
56-
uvp.cov_array_real[spw] = np.empty((uvp.Nblpairts, ndlys, ndlys, uvp.Npols), np.float64)
57-
uvp.cov_array_imag[spw] = np.empty((uvp.Nblpairts, ndlys, ndlys, uvp.Npols), np.float64)
58-
uvp.stats_array[stat][spw] = np.empty((uvp.Nblpairts, ndlys, uvp.Npols), np.complex128)
56+
uvp.cov_array_real[spw] = np.empty((uvp.Nbltpairs, ndlys, ndlys, uvp.Npols), np.float64)
57+
uvp.cov_array_imag[spw] = np.empty((uvp.Nbltpairs, ndlys, ndlys, uvp.Npols), np.float64)
58+
uvp.stats_array[stat][spw] = np.empty((uvp.Nbltpairs, ndlys, uvp.Npols), np.complex128)
5959
return uvp
6060

6161
def test_param(self):
@@ -591,7 +591,7 @@ def test_get_exact_window_functions(self):
591591
uvp.get_exact_window_functions(ftbeam=self.ft_file,
592592
inplace=True)
593593
assert uvp.exact_windows
594-
assert uvp.window_function_array[0].shape[0] == uvp.Nblpairts
594+
assert uvp.window_function_array[0].shape[0] == uvp.Nbltpairs
595595
# if not exact window function, array dim is 4
596596
assert uvp.window_function_array[0].ndim == 5
597597

@@ -1028,5 +1028,13 @@ def test_backwards_compatibility_read():
10281028
# test read in of a static test file dated 8/2019
10291029
uvp = uvpspec.UVPSpec()
10301030
uvp.read_hdf5(os.path.join(DATA_PATH, 'test_uvp.h5'))
1031+
for dattr in uvp._meta_deprecated:
1032+
with pytest.raises(AttributeError) as excinfo:
1033+
raise AttributeError("'UVPSpec' object has no attribute")
1034+
assert "'UVPSpec' object has no attribute" in str(excinfo.value)
1035+
for dattr in uvp._meta_dsets_deprecated:
1036+
with pytest.raises(AttributeError) as excinfo:
1037+
raise AttributeError("'UVPSpec' object has no attribute")
1038+
assert "'UVPSpec' object has no attribute" in str(excinfo.value)
10311039
# assert check does not fail
10321040
uvp.check()

hera_pspec/tests/test_uvpspec_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def test_conj_blpair():
237237
pytest.raises(ValueError, uvputils._conj_blpair, 102101103104, which='foo')
238238

239239

240-
def test_fast_is_in():
240+
def test_is_in():
241241
blps = [ 102101103104, 102101103104, 102101103104, 102101103104,
242242
101102104103, 101102104103, 101102104103, 101102104103,
243243
102101104103, 102101104103, 102101104103, 102101104103 ]
@@ -246,7 +246,7 @@ def test_fast_is_in():
246246
0.1, 0.15, 0.3, 0.3, ]
247247
src_blpts = np.array(list(zip(blps, times)))
248248

249-
assert uvputils._fast_is_in(src_blpts, [(101102104103, 0.2)])[0]
249+
assert uvputils._is_in(src_blpts, [(101102104103, 0.2)])[0]
250250

251251

252252
def test_fast_lookup_blpairts():

0 commit comments

Comments
 (0)