Skip to content

Commit 3581eff

Browse files
committed
Move away from longdouble samples_per_second in rest of codebase.
1 parent a4bc689 commit 3581eff

11 files changed

Lines changed: 100 additions & 118 deletions

python/digital_rf/digital_metadata.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from six.moves import urllib, zip
3939

4040
# local imports
41-
from . import list_drf
41+
from . import list_drf, util
4242
from ._version import get_versions
4343

4444
try:
@@ -199,6 +199,10 @@ def __init__(
199199
raise ValueError(errstr % str(sample_rate_denominator))
200200
self._sample_rate_denominator = int(sample_rate_denominator)
201201

202+
self._sample_rate = util.get_samplerate_frac(
203+
sample_rate_numerator, sample_rate_denominator
204+
)
205+
202206
# have to go to uint64 before longdouble to ensure correct conversion
203207
# from int
204208
self._samples_per_second = np.longdouble(
@@ -214,6 +218,10 @@ def __init__(
214218
self._fields = None # No data written yet
215219
self._write_properties()
216220

221+
def get_sample_rate(self):
222+
"""Return the sample rate in Hz as a fractions.Fraction."""
223+
return self._sample_rate
224+
217225
def get_samples_per_second(self):
218226
"""Return the sample rate in Hz as a np.longdouble."""
219227
return self._samples_per_second
@@ -338,7 +346,7 @@ def _sample_group_generator(self, samples):
338346
Digital Metadata file and takes its name from the sample index.
339347
340348
"""
341-
samples_per_file = self._file_cadence_secs * self._samples_per_second
349+
samples_per_file = self._file_cadence_secs * self._sample_rate
342350
for file_idx, sample_group in itertools.groupby(
343351
samples, lambda s: np.uint64(s / samples_per_file)
344352
):
@@ -470,7 +478,7 @@ def __str__(self):
470478
attr_list = (
471479
"_subdir_cadence_secs",
472480
"_file_cadence_secs",
473-
"_samples_per_second",
481+
"_sample_rate",
474482
"_file_name",
475483
)
476484
for attr in attr_list:
@@ -585,6 +593,9 @@ def __init__(self, metadata_dir, accept_empty=True):
585593
self._samples_per_second = np.longdouble(
586594
np.uint64(self._sample_rate_numerator)
587595
) / np.longdouble(np.uint64(self._sample_rate_denominator))
596+
self._sample_rate = util.get_samplerate_frac(
597+
self._sample_rate_numerator, self._sample_rate_denominator
598+
)
588599
fname = f.attrs["file_name"]
589600
if isinstance(fname, bytes):
590601
# for convenience and forward-compatibility with h5py>=2.9
@@ -712,6 +723,10 @@ def get_fields(self):
712723
# _fields is an internal data structure, so make a copy for the user
713724
return copy.deepcopy(self._fields)
714725

726+
def get_sample_rate(self):
727+
"""Return the sample rate in Hz as a fractions.Fraction."""
728+
return self._sample_rate
729+
715730
def get_sample_rate_numerator(self):
716731
"""Return the numerator of the sample rate in Hz."""
717732
return self._sample_rate_numerator
@@ -1018,9 +1033,8 @@ def _get_file_list(self, sample0, sample1):
10181033
scheme.
10191034
10201035
"""
1021-
# need to go through numpy uint64 to prevent conversion to float
1022-
start_ts = int(np.uint64(np.uint64(sample0) / self._samples_per_second))
1023-
end_ts = int(np.uint64(np.uint64(sample1) / self._samples_per_second))
1036+
start_ts, picoseconds = util.sample_to_time_floor(sample0, self._sample_rate)
1037+
end_ts, picoseconds = util.sample_to_time_floor(sample1, self._sample_rate)
10241038

10251039
# convert ts to be divisible by self._file_cadence_secs
10261040
start_ts = (start_ts // self._file_cadence_secs) * self._file_cadence_secs
@@ -1203,7 +1217,7 @@ def __str__(self):
12031217
attr_list = (
12041218
"_subdir_cadence_secs",
12051219
"_file_cadence_secs",
1206-
"_samples_per_second",
1220+
"_sample_rate",
12071221
"_file_name",
12081222
)
12091223
for attr in attr_list:

python/digital_rf/digital_rf_hdf5.py

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import collections
2222
import datetime
23-
import fractions
2423
import glob
2524
import os
2625
import re
@@ -972,13 +971,11 @@ def read(self, start_sample, end_sample, channel_name, sub_channel=None):
972971
# first get the names of all possible files with data
973972
subdir_cadence_secs = file_properties["subdir_cadence_secs"]
974973
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
975-
sample_rate_numerator = file_properties["sample_rate_numerator"]
976-
sample_rate_denominator = file_properties["sample_rate_denominator"]
974+
sample_rate = file_properties["sample_rate"]
977975
filepaths = self._get_file_list(
978976
start_sample,
979977
end_sample,
980-
sample_rate_numerator,
981-
sample_rate_denominator,
978+
sample_rate,
982979
subdir_cadence_secs,
983980
file_cadence_millisecs,
984981
)
@@ -1107,14 +1104,12 @@ def get_properties(self, channel_name, sample=None):
11071104

11081105
subdir_cadence_secs = global_properties["subdir_cadence_secs"]
11091106
file_cadence_millisecs = global_properties["file_cadence_millisecs"]
1110-
sample_rate_numerator = global_properties["sample_rate_numerator"]
1111-
sample_rate_denominator = global_properties["sample_rate_denominator"]
1107+
sample_rate = global_properties["sample_rate"]
11121108

11131109
file_list = self._get_file_list(
11141110
sample,
11151111
sample,
1116-
sample_rate_numerator,
1117-
sample_rate_denominator,
1112+
sample_rate,
11181113
subdir_cadence_secs,
11191114
file_cadence_millisecs,
11201115
)
@@ -1310,13 +1305,11 @@ def get_continuous_blocks(self, start_sample, end_sample, channel_name):
13101305
file_properties = self.get_properties(channel_name)
13111306
subdir_cadence_secs = file_properties["subdir_cadence_secs"]
13121307
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
1313-
sample_rate_numerator = file_properties["sample_rate_numerator"]
1314-
sample_rate_denominator = file_properties["sample_rate_denominator"]
1308+
sample_rate = file_properties["sample_rate"]
13151309
filepaths = self._get_file_list(
13161310
start_sample,
13171311
end_sample,
1318-
sample_rate_numerator,
1319-
sample_rate_denominator,
1312+
sample_rate,
13201313
subdir_cadence_secs,
13211314
file_cadence_millisecs,
13221315
)
@@ -1356,13 +1349,11 @@ def get_last_write(self, channel_name):
13561349
file_properties = self.get_properties(channel_name)
13571350
subdir_cadence_seconds = file_properties["subdir_cadence_secs"]
13581351
file_cadence_millisecs = file_properties["file_cadence_millisecs"]
1359-
sample_rate_numerator = file_properties["sample_rate_numerator"]
1360-
sample_rate_denominator = file_properties["sample_rate_denominator"]
1352+
sample_rate = file_properties["sample_rate"]
13611353
file_list = self._get_file_list(
13621354
last_sample - 1,
13631355
last_sample,
1364-
sample_rate_numerator,
1365-
sample_rate_denominator,
1356+
sample_rate,
13661357
subdir_cadence_seconds,
13671358
file_cadence_millisecs,
13681359
)
@@ -1615,8 +1606,7 @@ def read_vector_c81d(
16151606
def _get_file_list(
16161607
sample0,
16171608
sample1,
1618-
sample_rate_numerator,
1619-
sample_rate_denominator,
1609+
sample_rate,
16201610
subdir_cadence_seconds,
16211611
file_cadence_millisecs,
16221612
):
@@ -1636,11 +1626,8 @@ def _get_file_list(
16361626
Sample index for end of read (inclusive), given in the number of
16371627
samples since the epoch (time_since_epoch*sample_rate).
16381628
1639-
sample_rate_numerator : int
1640-
Numerator of sample rate in Hz.
1641-
1642-
sample_rate_denominator : int
1643-
Denominator of sample rate in Hz.
1629+
sample_rate : fractions.Fraction | first argument to ``util.get_samplerate_frac``
1630+
Sample rate in Hz.
16441631
16451632
subdir_cadence_secs : int
16461633
Number of seconds of data found in one subdir. For example, 3600
@@ -1661,13 +1648,9 @@ def _get_file_list(
16611648
if (sample1 - sample0) > 1e12:
16621649
warnstr = "Requested read size, %i samples, is very large"
16631650
warnings.warn(warnstr % (sample1 - sample0), RuntimeWarning)
1664-
start_ts, picoseconds = _py_rf_write_hdf5.get_timestamp_floor(
1665-
sample0, sample_rate_numerator, sample_rate_denominator
1666-
)
1651+
start_ts, picoseconds = util.sample_to_time_floor(sample0, sample_rate)
16671652
start_msts = start_ts * 1000 + picoseconds // 1000000000
1668-
end_ts, picoseconds = _py_rf_write_hdf5.get_timestamp_floor(
1669-
sample1, sample_rate_numerator, sample_rate_denominator
1670-
)
1653+
end_ts, picoseconds = util.sample_to_time_floor(sample1, sample_rate)
16711654
end_msts = end_ts * 1000 + picoseconds // 1000000000
16721655

16731656
# get subdirectory start and end ts

python/examples/example_read_digital_metadata.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
Assumes the example Digital Metadata write script has already been run.
1212
1313
"""
14+
1415
from __future__ import absolute_import, division, print_function
1516

1617
import os
1718
import tempfile
1819

1920
import digital_rf
20-
import numpy as np
2121

2222
metadata_dir = os.path.join(tempfile.gettempdir(), "example_metadata")
2323
stime = 1447082580
@@ -29,7 +29,7 @@
2929
raise
3030

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

@@ -55,6 +55,10 @@
5555
latest_meta = dmr.read_latest()
5656
print(latest_meta)
5757

58+
print("test of get_sample_rate")
59+
sr = dmr.get_sample_rate()
60+
print(sr)
61+
5862
print("test of get_samples_per_second")
5963
sps = dmr.get_samples_per_second()
6064
print(sps)

python/examples/example_write_digital_metadata.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
number of levels.
1313
1414
"""
15+
1516
from __future__ import absolute_import, division, print_function
1617

1718
import os
@@ -24,8 +25,8 @@
2425
metadata_dir = os.path.join(tempfile.gettempdir(), "example_metadata")
2526
subdirectory_cadence_seconds = 3600
2627
file_cadence_seconds = 60
27-
samples_per_second_numerator = 10
28-
samples_per_second_denominator = 9
28+
sample_rate_numerator = 10
29+
sample_rate_denominator = 9
2930
file_name = "rideout"
3031
stime = 1447082580
3132

@@ -36,14 +37,14 @@
3637
metadata_dir,
3738
subdirectory_cadence_seconds,
3839
file_cadence_seconds,
39-
samples_per_second_numerator,
40-
samples_per_second_denominator,
40+
sample_rate_numerator,
41+
sample_rate_denominator,
4142
file_name,
4243
)
4344
print("first create okay")
4445

4546
data_dict = {}
46-
start_idx = int(np.uint64(stime * dmw.get_samples_per_second()))
47+
start_idx = digital_rf.util.time_to_sample_ceil(stime, dmw.get_sample_rate())
4748
# To save an array of data, make sure the first axis has the same length
4849
# as the samples index
4950
idx_arr = np.arange(70, dtype=np.int64) + start_idx
@@ -95,8 +96,8 @@
9596
metadata_dir,
9697
subdirectory_cadence_seconds,
9798
file_cadence_seconds,
98-
samples_per_second_numerator,
99-
samples_per_second_denominator,
99+
sample_rate_numerator,
100+
sample_rate_denominator,
100101
file_name,
101102
)
102103
print("second create okay")

python/examples/sounder/prc_analyze.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
doi:10.5194/amt-9-829-2016, 2016.
1717
1818
"""
19+
1920
from __future__ import absolute_import, division, print_function
2021

2122
import datetime
@@ -224,7 +225,7 @@ def analyze_prc(
224225
os.remove(f)
225226

226227
d = drf.DigitalRFReader(op.datadir)
227-
sr = d.get_properties(op.ch)["samples_per_second"]
228+
sr = d.get_properties(op.ch)["sample_rate"]
228229
b = d.get_bounds(op.ch)
229230
idx = np.array(b[0])
230231
if os.path.isfile(datpath):

python/gr_digital_rf/digital_rf_sink.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# The full license is in the LICENSE file, distributed with this software.
88
# ----------------------------------------------------------------------------
99
"""Module defining a Digital RF Source block."""
10+
1011
from __future__ import absolute_import, division, print_function
1112

1213
import os
@@ -19,19 +20,18 @@
1920
import numpy as np
2021
import pmt
2122
import six
23+
from digital_rf import DigitalMetadataWriter, DigitalRFWriter, _py_rf_write_hdf5, util
2224
from gnuradio import gr
2325
from six.moves import zip
2426

25-
from digital_rf import DigitalMetadataWriter, DigitalRFWriter, _py_rf_write_hdf5, util
2627

27-
28-
def parse_time_pmt(val, samples_per_second):
28+
def parse_time_pmt(val, sample_rate):
2929
"""Get (sec, frac, idx) from an rx_time pmt value."""
30-
tsec = np.uint64(pmt.to_uint64(pmt.tuple_ref(val, 0)))
30+
tsec = int(np.uint64(pmt.to_uint64(pmt.tuple_ref(val, 0))))
3131
tfrac = pmt.to_double(pmt.tuple_ref(val, 1))
3232
# calculate sample index of time and floor to uint64
33-
tidx = np.uint64(tsec * samples_per_second + tfrac * samples_per_second)
34-
return int(tsec), tfrac, int(tidx)
33+
tidx = util.time_to_sample_ceil((tsec, int(tfrac * 1e12)), sample_rate)
34+
return tsec, tfrac, tidx
3535

3636

3737
def translate_rx_freq(tag):
@@ -319,12 +319,12 @@ def __init__(
319319

320320
self._work_done = False
321321

322-
self._samples_per_second = np.longdouble(
323-
np.uint64(sample_rate_numerator)
324-
) / np.longdouble(np.uint64(sample_rate_denominator))
322+
self._sample_rate = util.get_samplerate_frac(
323+
self._sample_rate_numerator, self._sample_rate_denominator
324+
)
325325

326326
if min_chunksize is None:
327-
self._min_chunksize = max(int(self._samples_per_second // 1000), 1)
327+
self._min_chunksize = max(int(self._sample_rate // 1000), 1)
328328
else:
329329
self._min_chunksize = min_chunksize
330330

@@ -346,7 +346,7 @@ def __init__(
346346

347347
# will be None if start is None or ''
348348
self._start_sample = util.parse_identifier_to_sample(
349-
start, self._samples_per_second, None
349+
start, self._sample_rate, None
350350
)
351351
if self._start_sample is None:
352352
if self._ignore_tags:
@@ -360,9 +360,8 @@ def __init__(
360360
self._next_rel_sample = 0
361361
if self._debug:
362362
tidx = self._start_sample
363-
timedelta = util.samples_to_timedelta(tidx, self._samples_per_second)
364-
tsec = int(timedelta.total_seconds() // 1)
365-
tfrac = timedelta.microseconds / 1e6
363+
tsec, picoseconds = util.sample_to_time_floor(tidx, self._sample_rate)
364+
tfrac = picoseconds / 1e12
366365
tagstr = ("|{0}|start @ sample 0: {1}+{2} ({3})\n").format(
367366
self._channel_name, tsec, tfrac, tidx
368367
)
@@ -462,7 +461,7 @@ def _read_tags(self, nsamples):
462461
# separate data into blocks to be written
463462
for tag in time_tags:
464463
offset = tag.offset
465-
tsec, tfrac, tidx = parse_time_pmt(tag.value, self._samples_per_second)
464+
tsec, tfrac, tidx = parse_time_pmt(tag.value, self._sample_rate)
466465

467466
# index into data block for this tag
468467
bidx = offset - nread

0 commit comments

Comments
 (0)