Skip to content

Commit 0122345

Browse files
authored
Merge pull request #357 from HERA-Team/wf_delay
Update on the UVWindow and FTBeam modules
2 parents 5ae3d61 + c13f8b2 commit 0122345

File tree

5 files changed

+222
-113
lines changed

5 files changed

+222
-113
lines changed

hera_pspec/grouping.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -664,15 +664,20 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
664664
if isinstance(bin_widths, (float, int)):
665665
bin_widths = np.ones_like(kbins) * bin_widths
666666

667+
# copy input
668+
uvp = copy.deepcopy(uvp_in)
669+
670+
# transform kgrid to little_h units
671+
if not little_h:
672+
kbins = kbins / uvp.cosmo.h
673+
bin_widths = bin_widths / uvp.cosmo.h
674+
667675
# ensure bins don't overlap
668676
assert len(kbins) == len(bin_widths)
669677
kbin_left = kbins - bin_widths / 2
670678
kbin_right = kbins + bin_widths / 2
671679
assert np.all(kbin_left[1:] >= kbin_right[:-1] - 1e-6), "kbins must not overlap"
672680

673-
# copy input
674-
uvp = copy.deepcopy(uvp_in)
675-
676681
# perform time and cylindrical averaging upfront if requested
677682
if not uvp.exact_windows and (blpair_groups is not None or time_avg):
678683
uvp.average_spectra(blpair_groups=blpair_groups, time_avg=time_avg,
@@ -695,11 +700,6 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
695700
if store_window:
696701
window_function_array = odict()
697702

698-
# transform kgrid to little_h units
699-
if not little_h:
700-
kbins = kbins / uvp.cosmo.h
701-
bin_widths = bin_widths / uvp.cosmo.h
702-
703703
# iterate over spectral windows
704704
spw_ranges = uvp.get_spw_ranges()
705705
for spw in uvp.spw_array:
@@ -887,7 +887,7 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
887887
time_avg=time_avg,
888888
error_weights=error_weights,
889889
spw_array=spw,
890-
little_h=little_h,
890+
little_h=True,
891891
verbose=True)[spw]
892892

893893
# handle data arrays
@@ -943,9 +943,9 @@ def spherical_average(uvp_in, kbins, bin_widths, blpair_groups=None, time_avg=Fa
943943
return uvp
944944

945945
def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
946-
blpair_groups=None, blpair_lens=None, blpair_weights=None,
947-
error_weights=None, time_avg=False, spw_array=None,
948-
little_h=True, verbose=False):
946+
blpair_groups=None, blpair_lens=None, blpair_weights=None,
947+
error_weights=None, time_avg=False, spw_array=None,
948+
little_h=True, verbose=False):
949949

950950
"""
951951
Obtains exact spherical window functions from an UVPspec object,
@@ -984,8 +984,9 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
984984
Spectral window indices.
985985
986986
little_h : bool, optional
987-
If True, kgrid is in h Mpc^-1 units, otherwise just Mpc^-1 units.
988-
If False, user must ensure adopted h is consistent with uvp_in.cosmo
987+
If True, kbins is in h Mpc^-1 units, otherwise just Mpc^-1 units.
988+
The code ensures adopted h is consistent with uvp_in.cosmo. If not,
989+
it modifies the unit of kbins.
989990
990991
verbose : bool, optional
991992
If True, print progress, warnings and debugging info to stdout.
@@ -1004,6 +1005,21 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
10041005
if isinstance(bin_widths, (float, int)):
10051006
bin_widths = np.ones_like(kbins) * bin_widths
10061007

1008+
# if window functions have been computed without little h
1009+
# it is not possible to re adjust so kbins need to be in Mpc-1
1010+
# and reciprocally
1011+
if little_h != ('h^-3' in uvp_in.norm_units):
1012+
warnings.warn('Changed little_h units to make kbins consistent ' \
1013+
'with uvp.window_function_array. Might be inconsistent ' \
1014+
'with the power spectrum units.')
1015+
if little_h:
1016+
kbins *= uvp_in.cosmo.h
1017+
bin_widths *= uvp_in.cosmo.h
1018+
else:
1019+
kbins /= uvp_in.cosmo.h
1020+
bin_widths /= uvp_in.cosmo.h
1021+
little_h = 'h^-3' in uvp_in.norm_units
1022+
10071023
# ensure bins don't overlap
10081024
assert len(kbins) == len(bin_widths)
10091025
kbin_left = kbins - bin_widths / 2
@@ -1062,11 +1078,6 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
10621078
time_avg=time_avg,
10631079
inplace=True)
10641080

1065-
# transform kgrid to little_h units
1066-
if not little_h:
1067-
kbins = kbins / uvp.cosmo.h
1068-
bin_widths = bin_widths / uvp.cosmo.h
1069-
10701081
# initialize blank arrays and dicts
10711082
window_function_array = odict()
10721083

@@ -1078,7 +1089,7 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
10781089
# construct array giving the k probed by each baseline-tau pair
10791090
kperps = uvp.cosmo.bl_to_kperp(uvp.cosmo.f2z(avg_nu), little_h=little_h) * blpair_lens
10801091
kparas = uvp.cosmo.tau_to_kpara(uvp.cosmo.f2z(avg_nu), little_h=little_h) * uvp.get_dlys(spw)
1081-
kmags = np.sqrt(kperps[:, None]**2+kparas**2)
1092+
kmags = np.sqrt(kperps[:, None]**2 + kparas**2)
10821093

10831094
# setup arrays
10841095
window_function_array[spw] = np.zeros((uvp.Ntimes, Nk, Nk, uvp.Npols), dtype=np.float64)
@@ -1092,17 +1103,17 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
10921103
kpara_bins = uvp.window_function_kpara[spw][:, ip]
10931104
ktot = np.sqrt(kperp_bins[:, None]**2 + kpara_bins**2)
10941105

1095-
cyl_wf = uvp.window_function_array[spw][:, :, :, :, ip]
1106+
cyl_wf = uvp.window_function_array[spw][..., ip]
10961107
# separate baseline-time axis to iterate over times
1097-
cyl_wf = cyl_wf.reshape((uvp.Ntimes, uvp.Nblpairs, *cyl_wf.shape[1:] ))
1108+
cyl_wf = cyl_wf.reshape((uvp.Ntimes, uvp.Nblpairs, *cyl_wf.shape[1:]))
10981109

10991110
# take average for each time
11001111
for it in range(uvp.Ntimes):
11011112
wf_spherical = np.zeros((Nk, Nk))
11021113
for m1 in range(Nk):
11031114
mask1 = (kbin_left[m1] <= kmags) & (kmags < kbin_right[m1])
11041115
if np.any(mask1):
1105-
wf_temp = np.sum(cyl_wf[it, :, :, :, :]*mask1[:, :, None, None].astype(int), axis=(0, 1))/np.sum(mask1)
1116+
wf_temp = np.sum(cyl_wf[it, ...]*mask1[:, :, None, None].astype(int), axis=(0, 1))/np.sum(mask1)
11061117
if np.sum(wf_temp) > 0.:
11071118
for m2 in range(Nk):
11081119
mask2 = (kbin_left[m2] <= ktot) & (ktot < kbin_right[m2])
@@ -1113,7 +1124,7 @@ def spherical_wf_from_uvp(uvp_in, kbins, bin_widths,
11131124
where = np.sum(wf_spherical[m1,:]) != 0)
11141125
spw_window_function.append(wf_spherical)
11151126

1116-
window_function_array[spw][:, :, :, ip] = np.copy(spw_window_function)
1127+
window_function_array[spw][..., ip] = np.copy(spw_window_function)
11171128

11181129
return window_function_array
11191130

hera_pspec/tests/test_grouping.py

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ def test_spherical_average():
608608
spw_ranges=(175,195), taper='bh',verbose=False)
609609
# get exact window functions
610610
uvp.get_exact_window_functions(ftbeam_file = os.path.join(DATA_PATH, 'FT_beam_HERA_dipole_test'),
611-
spw_array=None, inplace=True, verbose=False)
611+
spw_array=None, inplace=True, verbose=False)
612612
# spherical window functions for redundant groups
613613
sph = grouping.spherical_average(uvp, kbins, bin_widths)
614614
# spherical average for input blpair groups
@@ -619,9 +619,10 @@ def test_spherical_average():
619619
def test_spherical_wf_from_uvp():
620620

621621
# parameters
622-
kbins = np.arange(0, 2.9, 0.25)
622+
dk = 0.25
623+
kbins = np.arange(0.1, 2.9, dk)
623624
Nk = len(kbins)
624-
bin_widths = 0.25
625+
print(kbins[0])
625626

626627
basename = 'FT_beam_HERA_dipole_test'
627628
# obtain uvp object
@@ -641,50 +642,68 @@ def test_spherical_wf_from_uvp():
641642
# obtain exact_windows (fiducial usage)
642643
uvp.get_exact_window_functions(ftbeam_file = os.path.join(DATA_PATH, basename),
643644
inplace=True)
644-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths)
645-
# blpair_groups=blpair_groups,
646-
# blpair_lens=blpair_lens,
647-
# blpair_weights=blpair_weights,
648-
# time_avg=time_avg,
649-
# error_weights=error_weights,
650-
# spw_array=spw,
651-
# little_h=little_h,
652-
# verbose=True)[spw]
645+
wf_array = grouping.spherical_wf_from_uvp(uvp,
646+
kbins=np.arange(0.1, 2.9, dk),
647+
bin_widths=dk,
648+
little_h='h^-3' in uvp.norm_units)
649+
653650
# test different options
654651
# little_h
655-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths, little_h=False)
652+
wf_array = grouping.spherical_wf_from_uvp(uvp,
653+
kbins = np.arange(0.1, 2.9, dk)/uvp.cosmo.h,
654+
bin_widths= dk/uvp.cosmo.h,
655+
little_h=True)
656656
# spw_array
657-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths, spw_array=0)
658-
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp, kbins, bin_widths,
659-
spw_array=2)
657+
wf_array = grouping.spherical_wf_from_uvp(uvp,
658+
kbins=np.arange(0.1, 2.9, dk),
659+
bin_widths=dk, spw_array=0,
660+
little_h='h^-3' in uvp.norm_units)
661+
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp,
662+
kbins=np.arange(0.1, 2.9, dk), bin_widths=dk,
663+
spw_array=2, little_h='h^-3' in uvp.norm_units)
660664
# blpair_groups
661665
blpair_groups, blpair_lens, _ = uvp.get_red_blpairs()
662-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths,
666+
wf_array = grouping.spherical_wf_from_uvp(uvp,
667+
kbins=np.arange(0.1, 2.9, dk),
668+
bin_widths=dk,
663669
blpair_groups=blpair_groups,
664-
blpair_lens=blpair_lens)
665-
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp, kbins, bin_widths,
666-
blpair_groups=blpair_groups[0])
670+
blpair_lens=blpair_lens,
671+
little_h='h^-3' in uvp.norm_units)
672+
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp,
673+
kbins=np.arange(0.1, 2.9, dk), bin_widths=dk,
674+
blpair_groups=blpair_groups[0], little_h='h^-3' in uvp.norm_units)
667675

668676
# raise warning or error if blpair_groups inconsistent with blpair_lens
669-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths,
677+
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins=np.arange(0.1, 2.9, dk),
678+
bin_widths=dk,
670679
blpair_groups=None,
671-
blpair_lens=blpair_lens)
672-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths,
680+
blpair_lens=blpair_lens,
681+
little_h='h^-3' in uvp.norm_units)
682+
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins=np.arange(0.1, 2.9, dk),
683+
bin_widths=dk,
673684
blpair_groups=blpair_groups,
674-
blpair_lens=None)
675-
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp, kbins, bin_widths,
676-
blpair_groups=blpair_groups, blpair_lens=[blpair_lens[0],blpair_lens[0]])
685+
blpair_lens=None,
686+
little_h='h^-3' in uvp.norm_units)
687+
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp,
688+
kbins=np.arange(0.1, 2.9, dk), bin_widths=dk,
689+
blpair_groups=blpair_groups, blpair_lens=[blpair_lens[0],blpair_lens[0]],
690+
little_h='h^-3' in uvp.norm_units)
677691
# error if overlapping bins
678-
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp, kbins, 1.0)
679-
# blpair_weights
680-
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins, bin_widths,
692+
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp,
693+
kbins=np.arange(0.1, 2.9, dk), bin_widths=1.0)
694+
# # blpair_weights
695+
wf_array = grouping.spherical_wf_from_uvp(uvp, kbins=np.arange(0.1, 2.9, dk),
696+
bin_widths=dk,
681697
blpair_groups=blpair_groups,
682698
blpair_lens=blpair_lens,
683-
blpair_weights=[[1. for item in grp] for grp in blpair_groups])
699+
little_h='h^-3' in uvp.norm_units)
700+
# blpair_weights=[[1. for item in grp] for grp in blpair_groups],
684701

685702
# raise error if uvp.exact_windows is False
686703
uvp.exact_windows = False
687-
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp, kbins, bin_widths)
704+
pytest.raises(AssertionError, grouping.spherical_wf_from_uvp, uvp,
705+
kbins=np.arange(0.1, 2.9, dk), bin_widths=dk,
706+
little_h='h^-3' in uvp.norm_units)
688707

689708

690709
if __name__ == "__main__":

hera_pspec/tests/test_uvwindow.py

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ def test_from_file(self):
125125
pytest.raises(AssertionError, uvwindow.FTBeam.from_file, spw_range=(1001, 1022),
126126
ftfile=self.ft_file)
127127

128+
def test_gaussian(self):
129+
130+
# fiducial use
131+
widths = -0.0343 * self.freq_array/1e6 + 11.30
132+
test = uvwindow.FTBeam.gaussian(freq_array=self.freq_array,
133+
widths=widths,
134+
pol=self.pol)
135+
# if widths given as unique number, this value is used for all freqs
136+
test2 = uvwindow.FTBeam.gaussian(freq_array=self.freq_array,
137+
widths=np.mean(widths),
138+
pol=self.pol)
139+
140+
# tests on freq_array consistency
141+
pytest.raises(AssertionError, uvwindow.FTBeam.gaussian,
142+
freq_array=self.freq_array[:2], pol=self.pol,
143+
widths=np.mean(widths))
144+
pytest.raises(AssertionError, uvwindow.FTBeam.gaussian,
145+
freq_array=self.freq_array, pol=self.pol,
146+
widths=widths[:10])
147+
148+
# make sure widths are given in degrees (raises warning)
149+
test = uvwindow.FTBeam.gaussian(freq_array=self.freq_array,
150+
pol=self.pol, widths=0.10)
151+
128152
def test_get_bandwidth(self):
129153

130154
test_bandwidth = uvwindow.FTBeam.get_bandwidth(self.ft_file)
@@ -431,12 +455,11 @@ def test_get_cylindrical_wf(self):
431455
return_bins='unweighted')
432456
assert np.all(cyl_wf2 == cyl_wf)
433457
assert np.all(kperp2 == kperp) # unweighted option to return_bins
434-
# warning raised if kperp_bins not linearly spaced
458+
# ValueError raised if kperp_bins not linearly spaced
435459
kperp_log = np.logspace(-2, 0, 100)
436-
_, _, _ = test.get_cylindrical_wf(bl_len,
437-
kperp_bins=kperp_log*test.kunits,
438-
kpara_bins=None,
439-
return_bins='unweighted')
460+
pytest.raises(ValueError, test.get_cylindrical_wf, bl_len,
461+
kperp_bins=kperp_log*test.kunits, kpara_bins=None,
462+
return_bins='unweighted')
440463

441464
# kpara bins
442465
_, kpara3, cyl_wf3 = test.get_cylindrical_wf(bl_len,
@@ -445,12 +468,11 @@ def test_get_cylindrical_wf(self):
445468
return_bins='unweighted')
446469
assert np.all(cyl_wf3 == cyl_wf)
447470
assert np.all(kpara == kpara3)
448-
# warning raised if kpara_bins not linearly spaced
471+
# ValueError raised if kpara_bins not linearly spaced
449472
kpara_log = np.logspace(-1, 1, 100)
450-
_, _, _ = test.get_cylindrical_wf(bl_len,
451-
kperp_bins=None,
452-
kpara_bins=kpara_log*test.kunits,
453-
return_bins='unweighted')
473+
pytest.raises(ValueError, test.get_cylindrical_wf, bl_len,
474+
kperp_bins=None, kpara_bins=kpara_log*test.kunits,
475+
return_bins='unweighted')
454476

455477
# test filling array by delay symmetry for odd number of delays
456478
ft_beam_test = uvwindow.FTBeam.from_file(ftfile=self.ft_file,
@@ -507,12 +529,11 @@ def test_cylindrical_to_spherical(self):
507529
ktot=ktot,
508530
bl_lens=bl_len)
509531

510-
# raise warning if kbins not linearly spaced
532+
# raise ValueError if kbins not linearly spaced
511533
kbins_log = np.logspace(-2, 2, 20)
512-
_, _ = test.cylindrical_to_spherical(cyl_wf=cyl_wf,
513-
kbins=kbins_log*test.kunits,
514-
ktot=ktot,
515-
bl_lens=bl_len)
534+
pytest.raises(ValueError, test.cylindrical_to_spherical, cyl_wf=cyl_wf,
535+
kbins=kbins_log*test.kunits, ktot=ktot,
536+
bl_lens=bl_len)
516537

517538
def test_get_spherical_wf(self):
518539

@@ -530,6 +551,7 @@ def test_get_spherical_wf(self):
530551
verbose=True)
531552
kperp_bins = test.get_kperp_bins(self.lens[:1])
532553
kpara_bins = test.get_kpara_bins(test.freq_array)
554+
print(np.diff(kpara_bins), np.diff(kperp_bins))
533555

534556
WF = test.get_spherical_wf(kbins=self.kbins,
535557
kperp_bins=kperp_bins,
@@ -559,18 +581,16 @@ def test_get_spherical_wf(self):
559581
step=kpara_centre)
560582
* test.kunits,
561583
bl_lens=self.lens[:1])
562-
# warning raised if kbins not linearly spaced
584+
# ValueError raised if kbins not linearly spaced
563585
kperp_log = np.logspace(-2, 0, 100)
564-
_ = test.get_spherical_wf(kbins=self.kbins,
565-
kperp_bins=kperp_log*test.kunits,
566-
bl_lens=self.lens[:1])
586+
pytest.raises(ValueError, test.get_spherical_wf, kbins=self.kbins,
587+
kperp_bins=kperp_log*test.kunits, bl_lens=self.lens[:1])
567588
kpara_log = np.logspace(-1, 1, 100)
568-
_ = test.get_spherical_wf(kbins=self.kbins,
569-
kpara_bins=kpara_log*test.kunits,
570-
bl_lens=self.lens[:1])
589+
pytest.raises(ValueError, test.get_spherical_wf, kbins=self.kbins,
590+
kpara_bins=kpara_log*test.kunits, bl_lens=self.lens[:1])
571591
kbins_log = np.logspace(-2, 2, 20)
572-
_ = test.get_spherical_wf(kbins=kbins_log*test.kunits,
573-
bl_lens=self.lens[:1])
592+
pytest.raises(ValueError, test.get_spherical_wf, kbins=kbins_log*test.kunits,
593+
bl_lens=self.lens[:1])
574594

575595

576596
def test_check_kunits(self):

0 commit comments

Comments
 (0)