Skip to content

Commit 82cc37e

Browse files
authored
Merge pull request #45 from jes-p/master
Add microseconds to waveform name if necessary.
2 parents c976927 + 2479bb3 commit 82cc37e

File tree

5 files changed

+108
-21
lines changed

5 files changed

+108
-21
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ language: python
22

33
python:
44
- "2.7"
5-
- "3.4"
65
- "3.5"
76
- "3.6"
87

pyasdf/asdf_data_set.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import collections
1919
import copy
20+
from distutils.version import LooseVersion
2021
import io
2122
import itertools
2223
import math
@@ -198,7 +199,7 @@ def __init__(self, filename, compression="gzip-3", shuffle=True,
198199

199200
# Deal with the file format version. `format_version` is either None
200201
# or valid (this is checked above).
201-
__most_recent_version = "1.0.1"
202+
__most_recent_version = "1.0.2"
202203
# Case 1: Already some kind of format version in the file.
203204
if "file_format_version" in self.__file.attrs:
204205
version_in_file = self.__file.attrs["file_format_version"].decode()
@@ -234,6 +235,10 @@ def __init__(self, filename, compression="gzip-3", shuffle=True,
234235
# Just a final safety check - should not be able to fail!
235236
assert self.asdf_format_version in SUPPORTED_FORMAT_VERSIONS
236237

238+
# Useful for programmatic checks.
239+
self._loose_asdf_format_version = \
240+
LooseVersion(self.asdf_format_version)
241+
237242
# Create the waveform and provenance groups if mode is not "r".
238243
if "Waveforms" not in self.__file and mode != "r":
239244
self.__file.create_group("Waveforms")
@@ -1201,6 +1206,13 @@ def __parse_waveform_input_and_validate(self, waveform):
12011206
"integers and 4 and 8 byte floating point "
12021207
"numbers." %
12031208
trace.data.dtype.name)
1209+
elif self.asdf_format_version == "1.0.2":
1210+
raise TypeError("The trace's dtype ('%s') is not allowed "
1211+
"inside ASDF 1.0.2. Allowed are little "
1212+
"and big endian 2, 4, and 8 byte signed "
1213+
"integers and 4 and 8 byte floating point "
1214+
"numbers." %
1215+
trace.data.dtype.name)
12041216
else: # pragma: no cover
12051217
raise NotImplementedError
12061218
return waveform
@@ -1294,10 +1306,19 @@ def _add_trace_write_collective_information(self, info):
12941306
ds.attrs[key] = value
12951307

12961308
def __get_waveform_ds_name(self, net, sta, loc, cha, start, end, tag):
1309+
fmt_string = "%Y-%m-%dT%H:%M:%S"
1310+
s = start.strftime(fmt_string)
1311+
e = end.strftime(fmt_string)
1312+
1313+
# Add nanoseconds if two waveforms start in the same second. Only do
1314+
# so for recent ASDF versions.
1315+
if s == e and self._loose_asdf_format_version >= LooseVersion("1.0.2"):
1316+
s += "." + "%09i" % (start._ns % int(1e9))
1317+
e += "." + "%09i" % (end._ns % int(1e9))
1318+
12971319
return "{net}.{sta}.{loc}.{cha}__{start}__{end}__{tag}".format(
12981320
net=net, sta=sta, loc=loc, cha=cha,
1299-
start=start.strftime("%Y-%m-%dT%H:%M:%S"),
1300-
end=end.strftime("%Y-%m-%dT%H:%M:%S"),
1321+
start=s, end=e,
13011322
tag=tag)
13021323

13031324
def _add_trace_get_collective_information(

pyasdf/header.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040

4141
FORMAT_NAME = "ASDF"
42-
SUPPORTED_FORMAT_VERSIONS = ("1.0.0", "1.0.1")
42+
SUPPORTED_FORMAT_VERSIONS = ("1.0.0", "1.0.1", "1.0.2")
4343

4444

4545
# Regular expression for allowed filenames within the provenance group.
@@ -55,6 +55,11 @@
5555
np.dtype("<f4"), np.dtype(">f4"),
5656
np.dtype("<f8"), np.dtype(">f8")),
5757
"1.0.1": (np.dtype("<i2"), np.dtype(">i2"),
58+
np.dtype("<i4"), np.dtype(">i4"),
59+
np.dtype("<i8"), np.dtype(">i8"),
60+
np.dtype("<f4"), np.dtype(">f4"),
61+
np.dtype("<f8"), np.dtype(">f8")),
62+
"1.0.2": (np.dtype("<i2"), np.dtype(">i2"),
5863
np.dtype("<i4"), np.dtype(">i4"),
5964
np.dtype("<i8"), np.dtype(">i8"),
6065
np.dtype("<f4"), np.dtype(">f4"),

pyasdf/tests/test_asdf_data_set.py

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def test_assert_format_and_version_number_are_written(tmpdir):
264264
# Open again and assert name and version number.
265265
with h5py.File(asdf_filename, "r") as hdf5_file:
266266
assert hdf5_file.attrs["file_format_version"].decode() \
267-
== "1.0.1"
267+
== "1.0.2"
268268
assert hdf5_file.attrs["file_format"].decode() == FORMAT_NAME
269269

270270

@@ -506,16 +506,25 @@ def test_format_version_handling(tmpdir):
506506

507507
# Create.
508508
with ASDFDataSet(filename) as ds:
509-
assert ds.asdf_format_version_in_file == "1.0.1"
510-
assert ds.asdf_format_version == "1.0.1"
509+
assert ds.asdf_format_version_in_file == "1.0.2"
510+
assert ds.asdf_format_version == "1.0.2"
511511
# Open again.
512512
with ASDFDataSet(filename) as ds:
513-
assert ds.asdf_format_version_in_file == "1.0.1"
514-
assert ds.asdf_format_version == "1.0.1"
513+
assert ds.asdf_format_version_in_file == "1.0.2"
514+
assert ds.asdf_format_version == "1.0.2"
515515

516516
os.remove(filename)
517517

518518
# Directly specify it.
519+
with ASDFDataSet(filename, format_version="1.0.2") as ds:
520+
assert ds.asdf_format_version_in_file == "1.0.2"
521+
assert ds.asdf_format_version == "1.0.2"
522+
with ASDFDataSet(filename) as ds:
523+
assert ds.asdf_format_version_in_file == "1.0.2"
524+
assert ds.asdf_format_version == "1.0.2"
525+
526+
os.remove(filename)
527+
519528
with ASDFDataSet(filename, format_version="1.0.1") as ds:
520529
assert ds.asdf_format_version_in_file == "1.0.1"
521530
assert ds.asdf_format_version == "1.0.1"
@@ -558,17 +567,17 @@ def test_format_version_handling(tmpdir):
558567
ds._ASDFDataSet__file.attrs["file_format_version"] = \
559568
ds._zeropad_ascii_string("x.x.x")
560569
assert ds.asdf_format_version_in_file == "x.x.x"
561-
assert ds.asdf_format_version == "1.0.1"
570+
assert ds.asdf_format_version == "1.0.2"
562571
with warnings.catch_warnings(record=True) as w:
563572
warnings.simplefilter("always")
564573
with ASDFDataSet(filename) as ds:
565574
assert ds.asdf_format_version_in_file == "x.x.x"
566-
assert ds.asdf_format_version == "1.0.1"
575+
assert ds.asdf_format_version == "1.0.2"
567576
assert w[0].message.args[0] == (
568577
"The file claims an ASDF version of x.x.x. This version of pyasdf "
569-
"only supports versions: 1.0.0, 1.0.1. All following write operations "
570-
"will use version 1.0.1 - other tools might not be able to read "
571-
"the files again - proceed with caution.")
578+
"only supports versions: 1.0.0, 1.0.1, 1.0.2. All following write "
579+
"operations will use version 1.0.2 - other tools might not be able to "
580+
"read the files again - proceed with caution.")
572581
# Again but force version.
573582
os.remove(filename)
574583
# Both can also differ.
@@ -583,17 +592,17 @@ def test_format_version_handling(tmpdir):
583592
assert ds.asdf_format_version == "1.0.0"
584593
assert w[0].message.args[0] == (
585594
"The file claims an ASDF version of x.x.x. This version of pyasdf "
586-
"only supports versions: 1.0.0, 1.0.1. All following write operations "
587-
"will use version 1.0.0 - other tools might not be able to read "
588-
"the files again - proceed with caution.")
595+
"only supports versions: 1.0.0, 1.0.1, 1.0.2. All following write "
596+
"operations will use version 1.0.0 - other tools might not be able to "
597+
"read the files again - proceed with caution.")
589598

590599
# Unsupported version number.
591600
os.remove(filename)
592601
with pytest.raises(ASDFValueError) as err:
593602
ASDFDataSet(filename, format_version="x.x.x")
594603
assert err.value.args[0] == (
595604
"ASDF version 'x.x.x' is not supported. Supported versions: 1.0.0, "
596-
"1.0.1")
605+
"1.0.1, 1.0.2")
597606
# No file should be created.
598607
assert not os.path.exists(filename)
599608

@@ -605,8 +614,8 @@ def test_format_version_handling(tmpdir):
605614
with warnings.catch_warnings(record=True) as w:
606615
warnings.simplefilter("always")
607616
with ASDFDataSet(filename) as ds:
608-
assert ds.asdf_format_version_in_file == "1.0.1"
609-
assert ds.asdf_format_version == "1.0.1"
617+
assert ds.asdf_format_version_in_file == "1.0.2"
618+
assert ds.asdf_format_version == "1.0.2"
610619
assert w[0].message.args[0] == (
611620
"No file format version given in file '%s'. The program will "
612621
"continue but the result is undefined." % os.path.abspath(filename))
@@ -3013,3 +3022,54 @@ def test_get_waveform_attributes(example_data_set):
30133022
'sampling_rate': 40.0,
30143023
'starttime': 1369374000000000000}
30153024
}
3025+
3026+
3027+
def test_datesets_with_less_then_1_second_length(tmpdir):
3028+
asdf_filename = os.path.join(tmpdir.strpath, "test.h5")
3029+
3030+
tr = obspy.Trace(np.linspace(0, 1, 777),
3031+
header={"network": "AA", "station": "BB", "location": "",
3032+
"channel": "000",
3033+
"starttime": obspy.UTCDateTime(38978345.3445843)})
3034+
3035+
# Don't use nano-seconds if longer than one second.
3036+
with ASDFDataSet(asdf_filename) as ds:
3037+
tr.stats.sampling_rate = 1.0
3038+
ds.add_waveforms(tr, tag="test")
3039+
dataset_name = ds.waveforms["AA.BB"].list()[0]
3040+
os.remove(asdf_filename)
3041+
3042+
assert dataset_name == \
3043+
"AA.BB..000__1971-03-28T03:19:05__1971-03-28T03:32:01__test"
3044+
3045+
# Do, if shorter than one second.
3046+
with ASDFDataSet(asdf_filename) as ds:
3047+
tr.stats.sampling_rate = 474505737
3048+
ds.add_waveforms(tr, tag="test")
3049+
dataset_name = ds.waveforms["AA.BB"].list()[0]
3050+
os.remove(asdf_filename)
3051+
3052+
assert dataset_name == (
3053+
"AA.BB..000__1971-03-28T03:19:05.344584304__"
3054+
"1971-03-28T03:19:05.344585939__test")
3055+
3056+
# Don't do it for older versions to not write invalid files.
3057+
with ASDFDataSet(asdf_filename, format_version="1.0.1") as ds:
3058+
tr.stats.sampling_rate = 474505737
3059+
ds.add_waveforms(tr, tag="test")
3060+
dataset_name = ds.waveforms["AA.BB"].list()[0]
3061+
os.remove(asdf_filename)
3062+
3063+
assert dataset_name == (
3064+
"AA.BB..000__1971-03-28T03:19:05__1971-03-28T03:19:05__test")
3065+
3066+
# Check that leading nulls are also written.
3067+
with ASDFDataSet(asdf_filename) as ds:
3068+
tr.stats.starttime = obspy.UTCDateTime(0)
3069+
ds.add_waveforms(tr, tag="test")
3070+
dataset_name = ds.waveforms["AA.BB"].list()[0]
3071+
os.remove(asdf_filename)
3072+
3073+
assert dataset_name == (
3074+
"AA.BB..000__1970-01-01T00:00:00.000000000__"
3075+
"1970-01-01T00:00:00.000001635__test")

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
::
1616
Version 0.4.x (TBD)
1717
-------------------
18+
* Support for ASDF version 1.0.2. Allows writing traces that are less than
19+
one second short (see #44, #45).
1820
* New get_waveform_attributes() method to quickly get all attributes
1921
for the waveforms of a stations (see #38, #39).
2022

0 commit comments

Comments
 (0)