Skip to content

Commit

Permalink
Merge pull request #269 from texadactyl/master
Browse files Browse the repository at this point in the history
Implement enhancement request #264
  • Loading branch information
texadactyl authored Jul 20, 2022
2 parents e7ad0a9 + 8f47cfa commit d061f99
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 18 deletions.
1 change: 1 addition & 0 deletions VERSION-HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ This file is a version history of blimpy amendments, beginning with version 2.0.
<br>
| Date | Version | Contents |
| :--: | :--: | :-- |
| 2022-07-20 | 2.1.1 | Mods to Waterfall class, an alternative to file loading (issue #264). |
| 2022-07-08 | 2.1.0 | New utility: dsamp (issue #267). |
| 2022-04-19 | 2.0.40 | Fixed blimpy to show plots when the display supports it (issue #263). |
| 2022-03-30 | 2.0.39 | examine_h5 in hdf_reader.py is loading too much data (issue #261). |
Expand Down
75 changes: 70 additions & 5 deletions blimpy/waterfall.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,73 @@
class Waterfall():
""" Class for loading and writing blimpy data (.fil, .h5) """


def __repr__(self):
return "Waterfall data: %s" % self.filename


def _init_alternate(self, header_dict, data, filename=None):

# Validate parameters.
assert filename is None
assert isinstance(header_dict, dict)
assert "nchans" in header_dict
assert "fch1" in header_dict
assert data.ndim == 3
assert data.shape[1] == 1

# Set dummy-file Waterfall object properties.
self.filename = None
self.ext = self.filename
self.file_shape = self.filename
self.file_size_bytes = 0

# The Waterfall "container":
class Container():
n_beams_in_file = 1
n_pols_in_file = 1
_d_type = np.float32
t_begin = 0
freq_axis = 2
time_axis = 0
beam_axis = 1
self.container = Container()
self.container.n_channels_in_file = header_dict["nchans"]
self.container._n_bytes = int(header_dict["nbits"] / 8) # number of bytes per digit.
if header_dict['foff'] < 0:
self.container.f_end = header_dict['fch1']
self.container.f_begin = self.container.f_end + self.container.n_channels_in_file * header_dict['foff']
else:
self.container.f_begin = header_dict['fch1']
self.container.f_end = self.container.f_begin + self.container.n_channels_in_file * header_dict['foff']
self.container.f_start = self.container.f_begin
self.container.f_stop = self.container.f_end
self.container.t_end = data.shape[0]

# Set Waterfall object properties.
self.header = header_dict
self.file_header = header_dict
self.n_ints_in_file = data.shape[0]
self.selection_shape = data.shape
self.n_channels_in_file = header_dict["nchans"]
self.freq_axis = 2
self.time_axis = 0
self.beam_axis = 1
self.stokes_axis = 4
self.logger = logger

# Attach data matrix.
self.data = data

# Attach plotting methods.
self.plot_spectrum = six.create_bound_method(plot_spectrum, self)
self.plot_waterfall = six.create_bound_method(plot_waterfall, self)
self.plot_kurtosis = six.create_bound_method(plot_kurtosis, self)
self.plot_time_series = six.create_bound_method(plot_time_series, self)
self.plot_all = six.create_bound_method(plot_all, self)
self.plot_spectrum_min_max = six.create_bound_method(plot_spectrum_min_max, self)


def __init__(self, filename=None, f_start=None, f_stop=None, t_start=None, t_stop=None,
load_data=True, max_load=None, header_dict=None, data_array=None):
""" Class for loading and plotting blimpy data.
Expand All @@ -86,7 +150,8 @@ def __init__(self, filename=None, f_start=None, f_stop=None, t_start=None, t_sto
"""

if (header_dict is not None) or (data_array is not None):
raise ValueError("Neither header_dict nor data_array is currently supported.")
self._init_alternate(header_dict, data_array, filename=filename)
return

if filename is None:
raise ValueError("Currently, a value for filename must be supplied.")
Expand Down Expand Up @@ -192,10 +257,10 @@ def info(self):
print("%16s : %32s" % ("File shape", self.file_shape))
print("--- Selection Info ---")
print("%16s : %32s" % ("Data selection shape", self.selection_shape))
if self.header['foff'] < 0:
if self.header['foff'] < 0: # descending frequency values
minfreq = self.container.f_start - self.header['foff']
maxfreq = self.container.f_stop
else:
else: # ascending frequency values
minfreq = self.container.f_start
maxfreq = self.container.f_stop - self.header['foff']
print("%16s : %32s" % ("Minimum freq (MHz)", minfreq))
Expand Down Expand Up @@ -336,11 +401,11 @@ def blank_dc(self, n_coarse_chan):

if n_coarse_chan < 1:
logger.warning('Coarse channel number < 1, unable to blank DC bin.')
return None
return

if not n_coarse_chan % int(n_coarse_chan) == 0:
logger.warning('Selection does not contain an integer number of coarse channels, unable to blank DC bin.')
return None
return

n_coarse_chan = int(n_coarse_chan)

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from setuptools import setup, find_packages

__version__ = '2.1.0'
__version__ = '2.1.1'

with open("README.md", "r") as fh:
long_description = fh.read()
Expand Down
12 changes: 0 additions & 12 deletions tests/test_waterfall.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,3 @@ def test_bug_no_filename():
with pytest.raises(ValueError):
bl.Waterfall()

def test_bug_header_dict():
print("\n===== test_bug_header")
header_dict = { "banana": "is a fruit" }
with pytest.raises(ValueError):
bl.Waterfall(voyager_h5, header_dict=header_dict)

def test_bug_data_array():
print("\n===== test_bug_data_array")
data_array = np.arange(1, 11)
with pytest.raises(ValueError):
bl.Waterfall(voyager_h5, data_array=data_array)

48 changes: 48 additions & 0 deletions tests/test_waterfall2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import numpy as np
from astropy import units as u
from astropy.coordinates import Angle
import blimpy as bl
from tests.data import voyager_h5

def test_waterfall_stream_1():

print("\n===== test_waterfall_stream_1")

source_name = "Not_Voyager_1"
src_raj = Angle("17:10:03.984 hours")
src_dej = Angle("12:10:58.8 degrees")
tstart = 57650.78209490741
tsamp = 18.253611008
f_start = 8418.457032646984
f_stop = 8421.386717353016
n_fine_chans = 20
n_tints = 8

foff = (f_stop - f_start) / float(n_fine_chans)

header = {"az_start": 0.0, "data_type": 1,
"fch1": f_start, "foff": foff,
"ibeam": 1, "machine_id": 42, "nbeams": 1, "nbits": 32,
"nchans": n_fine_chans, "nifs": 1, "rawdatafile": "nil",
"source_name": source_name, "src_raj": src_raj, "src_dej": src_dej,
"telescope_id": 42,
"tstart": tstart, "tsamp": tsamp, "zs_tart": 0.0}

data_matrix = np.zeros((n_tints, 1, n_fine_chans), dtype=np.float32)

wf = bl.Waterfall(header_dict=header, data_array=data_matrix)
print("\nwf:", wf)
wf.info()


def test_waterfall_stream_2():

print("\n===== test_waterfall_stream_2")
wf_voya1 = bl.Waterfall(voyager_h5)
wf_voya2 = bl.Waterfall(header_dict=wf_voya1.header, data_array=wf_voya1.data)
wf_voya2.info()


if __name__ == "__main__":
test_waterfall_stream_1()
test_waterfall_stream_2()

0 comments on commit d061f99

Please sign in to comment.