Skip to content

Commit

Permalink
Move away from longdouble samples_per_second in rest of codebase.
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanvolz committed Jun 14, 2024
1 parent a4bc689 commit 128b339
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 164 deletions.
28 changes: 21 additions & 7 deletions python/digital_rf/digital_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from six.moves import urllib, zip

# local imports
from . import list_drf
from . import list_drf, util
from ._version import get_versions

try:
Expand Down Expand Up @@ -199,6 +199,10 @@ def __init__(
raise ValueError(errstr % str(sample_rate_denominator))
self._sample_rate_denominator = int(sample_rate_denominator)

self._sample_rate = util.get_samplerate_frac(
sample_rate_numerator, sample_rate_denominator
)

# have to go to uint64 before longdouble to ensure correct conversion
# from int
self._samples_per_second = np.longdouble(
Expand All @@ -214,6 +218,10 @@ def __init__(
self._fields = None # No data written yet
self._write_properties()

def get_sample_rate(self):
"""Return the sample rate in Hz as a fractions.Fraction."""
return self._sample_rate

def get_samples_per_second(self):
"""Return the sample rate in Hz as a np.longdouble."""
return self._samples_per_second
Expand Down Expand Up @@ -338,7 +346,7 @@ def _sample_group_generator(self, samples):
Digital Metadata file and takes its name from the sample index.
"""
samples_per_file = self._file_cadence_secs * self._samples_per_second
samples_per_file = self._file_cadence_secs * self._sample_rate
for file_idx, sample_group in itertools.groupby(
samples, lambda s: np.uint64(s / samples_per_file)
):
Expand Down Expand Up @@ -470,7 +478,7 @@ def __str__(self):
attr_list = (
"_subdir_cadence_secs",
"_file_cadence_secs",
"_samples_per_second",
"_sample_rate",
"_file_name",
)
for attr in attr_list:
Expand Down Expand Up @@ -585,6 +593,9 @@ def __init__(self, metadata_dir, accept_empty=True):
self._samples_per_second = np.longdouble(
np.uint64(self._sample_rate_numerator)
) / np.longdouble(np.uint64(self._sample_rate_denominator))
self._sample_rate = util.get_samplerate_frac(
self._sample_rate_numerator, self._sample_rate_denominator
)
fname = f.attrs["file_name"]
if isinstance(fname, bytes):
# for convenience and forward-compatibility with h5py>=2.9
Expand Down Expand Up @@ -712,6 +723,10 @@ def get_fields(self):
# _fields is an internal data structure, so make a copy for the user
return copy.deepcopy(self._fields)

def get_sample_rate(self):
"""Return the sample rate in Hz as a fractions.Fraction."""
return self._sample_rate

def get_sample_rate_numerator(self):
"""Return the numerator of the sample rate in Hz."""
return self._sample_rate_numerator
Expand Down Expand Up @@ -1018,9 +1033,8 @@ def _get_file_list(self, sample0, sample1):
scheme.
"""
# need to go through numpy uint64 to prevent conversion to float
start_ts = int(np.uint64(np.uint64(sample0) / self._samples_per_second))
end_ts = int(np.uint64(np.uint64(sample1) / self._samples_per_second))
start_ts, picoseconds = util.sample_to_time_floor(sample0, self._sample_rate)
end_ts, picoseconds = util.sample_to_time_floor(sample1, self._sample_rate)

# convert ts to be divisible by self._file_cadence_secs
start_ts = (start_ts // self._file_cadence_secs) * self._file_cadence_secs
Expand Down Expand Up @@ -1203,7 +1217,7 @@ def __str__(self):
attr_list = (
"_subdir_cadence_secs",
"_file_cadence_secs",
"_samples_per_second",
"_sample_rate",
"_file_name",
)
for attr in attr_list:
Expand Down
43 changes: 13 additions & 30 deletions python/digital_rf/digital_rf_hdf5.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import collections
import datetime
import fractions
import glob
import os
import re
Expand Down Expand Up @@ -972,13 +971,11 @@ def read(self, start_sample, end_sample, channel_name, sub_channel=None):
# first get the names of all possible files with data
subdir_cadence_secs = file_properties["subdir_cadence_secs"]
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
sample_rate_numerator = file_properties["sample_rate_numerator"]
sample_rate_denominator = file_properties["sample_rate_denominator"]
sample_rate = file_properties["sample_rate"]
filepaths = self._get_file_list(
start_sample,
end_sample,
sample_rate_numerator,
sample_rate_denominator,
sample_rate,
subdir_cadence_secs,
file_cadence_millisecs,
)
Expand Down Expand Up @@ -1107,14 +1104,12 @@ def get_properties(self, channel_name, sample=None):

subdir_cadence_secs = global_properties["subdir_cadence_secs"]
file_cadence_millisecs = global_properties["file_cadence_millisecs"]
sample_rate_numerator = global_properties["sample_rate_numerator"]
sample_rate_denominator = global_properties["sample_rate_denominator"]
sample_rate = global_properties["sample_rate"]

file_list = self._get_file_list(
sample,
sample,
sample_rate_numerator,
sample_rate_denominator,
sample_rate,
subdir_cadence_secs,
file_cadence_millisecs,
)
Expand Down Expand Up @@ -1310,13 +1305,11 @@ def get_continuous_blocks(self, start_sample, end_sample, channel_name):
file_properties = self.get_properties(channel_name)
subdir_cadence_secs = file_properties["subdir_cadence_secs"]
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
sample_rate_numerator = file_properties["sample_rate_numerator"]
sample_rate_denominator = file_properties["sample_rate_denominator"]
sample_rate = file_properties["sample_rate"]
filepaths = self._get_file_list(
start_sample,
end_sample,
sample_rate_numerator,
sample_rate_denominator,
sample_rate,
subdir_cadence_secs,
file_cadence_millisecs,
)
Expand Down Expand Up @@ -1356,13 +1349,11 @@ def get_last_write(self, channel_name):
file_properties = self.get_properties(channel_name)
subdir_cadence_seconds = file_properties["subdir_cadence_secs"]
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
sample_rate_numerator = file_properties["sample_rate_numerator"]
sample_rate_denominator = file_properties["sample_rate_denominator"]
sample_rate = file_properties["sample_rate"]
file_list = self._get_file_list(
last_sample - 1,
last_sample,
sample_rate_numerator,
sample_rate_denominator,
sample_rate,
subdir_cadence_seconds,
file_cadence_millisecs,
)
Expand Down Expand Up @@ -1615,8 +1606,7 @@ def read_vector_c81d(
def _get_file_list(
sample0,
sample1,
sample_rate_numerator,
sample_rate_denominator,
sample_rate,
subdir_cadence_seconds,
file_cadence_millisecs,
):
Expand All @@ -1636,11 +1626,8 @@ def _get_file_list(
Sample index for end of read (inclusive), given in the number of
samples since the epoch (time_since_epoch*sample_rate).
sample_rate_numerator : int
Numerator of sample rate in Hz.
sample_rate_denominator : int
Denominator of sample rate in Hz.
sample_rate : fractions.Fraction | first argument to ``util.get_samplerate_frac``
Sample rate in Hz.
subdir_cadence_secs : int
Number of seconds of data found in one subdir. For example, 3600
Expand All @@ -1661,13 +1648,9 @@ def _get_file_list(
if (sample1 - sample0) > 1e12:
warnstr = "Requested read size, %i samples, is very large"
warnings.warn(warnstr % (sample1 - sample0), RuntimeWarning)
start_ts, picoseconds = _py_rf_write_hdf5.get_timestamp_floor(
sample0, sample_rate_numerator, sample_rate_denominator
)
start_ts, picoseconds = util.sample_to_time_floor(sample0, sample_rate)
start_msts = start_ts * 1000 + picoseconds // 1000000000
end_ts, picoseconds = _py_rf_write_hdf5.get_timestamp_floor(
sample1, sample_rate_numerator, sample_rate_denominator
)
end_ts, picoseconds = util.sample_to_time_floor(sample1, sample_rate)
end_msts = end_ts * 1000 + picoseconds // 1000000000

# get subdirectory start and end ts
Expand Down
9 changes: 4 additions & 5 deletions python/examples/benchmark_rf_write_hdf5.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
#
# The full license is in the LICENSE file, distributed with this software.
# ----------------------------------------------------------------------------
"""Benchmark I/O of Digital RF write in different configurations.
"""Benchmark I/O of Digital RF write in different configurations."""

"""
from __future__ import absolute_import, division, print_function

import os
Expand All @@ -24,14 +23,14 @@
N_WRITES = int(1e9 // WRITE_BLOCK_SIZE)
SAMPLE_RATE_NUMERATOR = int(1e9)
SAMPLE_RATE_DENOMINATOR = 1
sample_rate = np.longdouble(np.uint64(SAMPLE_RATE_NUMERATOR)) / np.longdouble(
np.uint64(SAMPLE_RATE_DENOMINATOR)
sample_rate = digital_rf.util.get_samplerate_frac(
SAMPLE_RATE_NUMERATOR, SAMPLE_RATE_DENOMINATOR
)
subdir_cadence_secs = 3600
file_cadence_millisecs = 10

# start 2014-03-09 12:30:30 plus one sample
start_global_index = int(np.uint64(1394368230 * sample_rate)) + 1
start_global_index = digital_rf.util.time_to_sample_ceil(1394368230, sample_rate) + 1

# data to write
data_int16 = np.zeros((WRITE_BLOCK_SIZE, 2), dtype="i2")
Expand Down
8 changes: 6 additions & 2 deletions python/examples/example_read_digital_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
Assumes the example Digital Metadata write script has already been run.
"""

from __future__ import absolute_import, division, print_function

import os
import tempfile

import digital_rf
import numpy as np

metadata_dir = os.path.join(tempfile.gettempdir(), "example_metadata")
stime = 1447082580
Expand All @@ -29,7 +29,7 @@
raise

print("init okay")
start_idx = int(np.uint64(stime * dmr.get_samples_per_second()))
start_idx = digital_rf.util.time_to_sample_ceil(stime, dmr.get_sample_rate())
first_sample, last_sample = dmr.get_bounds()
print("bounds are %i to %i" % (first_sample, last_sample))

Expand All @@ -55,6 +55,10 @@
latest_meta = dmr.read_latest()
print(latest_meta)

print("test of get_sample_rate")
sr = dmr.get_sample_rate()
print(sr)

print("test of get_samples_per_second")
sps = dmr.get_samples_per_second()
print(sps)
15 changes: 8 additions & 7 deletions python/examples/example_write_digital_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
number of levels.
"""

from __future__ import absolute_import, division, print_function

import os
Expand All @@ -24,8 +25,8 @@
metadata_dir = os.path.join(tempfile.gettempdir(), "example_metadata")
subdirectory_cadence_seconds = 3600
file_cadence_seconds = 60
samples_per_second_numerator = 10
samples_per_second_denominator = 9
sample_rate_numerator = 10
sample_rate_denominator = 9
file_name = "rideout"
stime = 1447082580

Expand All @@ -36,14 +37,14 @@
metadata_dir,
subdirectory_cadence_seconds,
file_cadence_seconds,
samples_per_second_numerator,
samples_per_second_denominator,
sample_rate_numerator,
sample_rate_denominator,
file_name,
)
print("first create okay")

data_dict = {}
start_idx = int(np.uint64(stime * dmw.get_samples_per_second()))
start_idx = digital_rf.util.time_to_sample_ceil(stime, dmw.get_sample_rate())
# To save an array of data, make sure the first axis has the same length
# as the samples index
idx_arr = np.arange(70, dtype=np.int64) + start_idx
Expand Down Expand Up @@ -95,8 +96,8 @@
metadata_dir,
subdirectory_cadence_seconds,
file_cadence_seconds,
samples_per_second_numerator,
samples_per_second_denominator,
sample_rate_numerator,
sample_rate_denominator,
file_name,
)
print("second create okay")
Expand Down
7 changes: 5 additions & 2 deletions python/examples/example_write_digital_rf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Writes continuous complex short data.
"""

from __future__ import absolute_import, division, print_function

import os
Expand All @@ -26,7 +27,9 @@
# writing parameters
sample_rate_numerator = int(100) # 100 Hz sample rate - typically MUCH faster
sample_rate_denominator = 1
sample_rate = np.longdouble(sample_rate_numerator) / sample_rate_denominator
sample_rate = digital_rf.util.get_samplerate_frac(
sample_rate_numerator, sample_rate_denominator
)
dtype_str = "i2" # short int
sub_cadence_secs = (
4 # Number of seconds of data in a subdirectory - typically MUCH larger
Expand All @@ -50,7 +53,7 @@
arr_data[i]["i"] = 3 * i

# start 2014-03-09 12:30:30 plus one sample
start_global_index = int(np.uint64(1394368230 * sample_rate)) + 1
start_global_index = digital_rf.util.time_to_sample_ceil(1394368230, sample_rate) + 1

# set up top level directory
shutil.rmtree(chdir, ignore_errors=True)
Expand Down
3 changes: 2 additions & 1 deletion python/examples/sounder/prc_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
doi:10.5194/amt-9-829-2016, 2016.
"""

from __future__ import absolute_import, division, print_function

import datetime
Expand Down Expand Up @@ -224,7 +225,7 @@ def analyze_prc(
os.remove(f)

d = drf.DigitalRFReader(op.datadir)
sr = d.get_properties(op.ch)["samples_per_second"]
sr = d.get_properties(op.ch)["sample_rate"]
b = d.get_bounds(op.ch)
idx = np.array(b[0])
if os.path.isfile(datpath):
Expand Down
Loading

0 comments on commit 128b339

Please sign in to comment.