Skip to content

Commit 6d9cf62

Browse files
Updates to documentation to reflect current recommended patterns
1 parent a3875b7 commit 6d9cf62

File tree

6 files changed

+82
-63
lines changed

6 files changed

+82
-63
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- `MS3Record.pack()` functionality, use `MS3Record.generate()` instead.
1515
- `MS3TraceList.pack()` functionality, use `MS3TraceList.generate()` instead.
1616

17+
### Changed
18+
- Examples updated to reflect current recommended patterns
19+
1720
### Changed
1821
- libmseed updated to v3.2.0
1922

examples/stream_stats.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ def to_dict(self):
5050
"sourceids": sourceids_copy,
5151
}
5252

53-
def update(self, record):
53+
def update(self, msr):
5454
"""Update statistics with data from a miniSEED record."""
5555
# Update global statistics
5656
self.record_count += 1
57-
self.sample_count += record.samplecnt
58-
self.bytes += record.reclen
57+
self.sample_count += msr.samplecnt
58+
self.bytes += msr.reclen
5959

6060
# Track per-sourceid statistics
61-
sid = record.sourceid
61+
sid = msr.sourceid
6262
if sid not in self.sourceids:
6363
self.sourceids[sid] = {
6464
"record_count": 0,
@@ -70,14 +70,14 @@ def update(self, record):
7070

7171
sid_stats = self.sourceids[sid]
7272
sid_stats["record_count"] += 1
73-
sid_stats["sample_count"] += record.samplecnt
74-
sid_stats["bytes"] += record.reclen
73+
sid_stats["sample_count"] += msr.samplecnt
74+
sid_stats["bytes"] += msr.reclen
7575

76-
if sid_stats["earliest"] is None or record.starttime < sid_stats["earliest"]:
77-
sid_stats["earliest"] = record.starttime
76+
if sid_stats["earliest"] is None or msr.starttime < sid_stats["earliest"]:
77+
sid_stats["earliest"] = msr.starttime
7878

79-
if sid_stats["latest"] is None or record.endtime > sid_stats["latest"]:
80-
sid_stats["latest"] = record.endtime
79+
if sid_stats["latest"] is None or msr.endtime > sid_stats["latest"]:
80+
sid_stats["latest"] = msr.endtime
8181

8282

8383
def main():
@@ -86,15 +86,15 @@ def main():
8686

8787
# Read miniSEED from stdin and accumulate stats for each record
8888
stats = StreamStats()
89-
with MS3Record.from_file(sys.stdin.fileno()) as reader:
90-
for record in reader:
91-
# Update statistics with data from the record
92-
stats.update(record)
89+
for msr in MS3Record.from_file(sys.stdin.fileno()):
90+
# Update statistics with data from the record
91+
stats.update(msr)
9392

94-
# Write raw miniSEED record to stdout
95-
sys.stdout.buffer.write(record.record)
93+
# Write raw miniSEED record to stdout
94+
sys.stdout.buffer.write(msr.record)
9695

9796
print(stats, file=sys.stderr)
9897

98+
9999
if __name__ == "__main__":
100100
main()

examples/stream_timewindow.py

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,24 @@ def process_stream(args):
2626
print("Reading miniSEED from stdin, writing to stdout", file=sys.stderr)
2727

2828
# Read miniSEED from stdin
29-
with MS3Record.from_file(sys.stdin.fileno()) as msreader:
30-
for msr in msreader:
31-
# Skip records completely outside the time window
32-
if (args.earliest and msr.endtime < args.earliest) or (
33-
args.latest and msr.starttime > args.latest
34-
):
35-
continue
36-
37-
# Trim if record overlaps with time window boundaries
38-
output_record = msr.record
39-
if (args.earliest and msr.starttime < args.earliest <= msr.endtime) or (
40-
args.latest and msr.starttime <= args.latest < msr.endtime
41-
):
42-
trimmed_record = trim_record(msr, args.earliest, args.latest)
43-
if trimmed_record:
44-
output_record = trimmed_record
45-
46-
# Write record to stdout
47-
sys.stdout.buffer.write(output_record)
48-
records_written += 1
49-
bytes_written += msr.reclen
29+
for msr in MS3Record.from_file(sys.stdin.fileno()):
30+
# Skip records completely outside the time window
31+
if (args.earliest and msr.endtime < args.earliest) or (
32+
args.latest and msr.starttime > args.latest
33+
):
34+
continue
35+
# Trim if record overlaps with time window boundaries
36+
output_record = msr.record
37+
if (args.earliest and msr.starttime < args.earliest <= msr.endtime) or (
38+
args.latest and msr.starttime <= args.latest < msr.endtime
39+
):
40+
trimmed_record = trim_record(msr, args.earliest, args.latest)
41+
if trimmed_record:
42+
output_record = trimmed_record
43+
# Write record to stdout
44+
sys.stdout.buffer.write(output_record)
45+
records_written += 1
46+
bytes_written += msr.reclen
5047

5148
print(f"Wrote {records_written} records, {bytes_written} bytes", file=sys.stderr)
5249

@@ -57,17 +54,17 @@ def trim_record(msr, earliest, latest):
5754
if msr.samplecnt == 0 and msr.samprate == 0.0:
5855
return None
5956

60-
# Re-parse the record and decode the data samples
57+
# Re-parse the single miniSEED record and decode the data samples
6158
buffer = bytearray(msr.record) # Mutable/writable buffer required
6259
with MS3Record.from_buffer(buffer, unpack_data=True) as msreader:
6360

6461
# Read/parse the single record
65-
record = msreader.read()
62+
msr_trimmed = msreader.read()
6663

67-
data_samples = record.datasamples[:]
68-
start_time = record.starttime
69-
end_time = record.endtime
70-
sample_period_ns = int(NSTMODULUS / record.samprate)
64+
data_samples = msr_trimmed.datasamples[:]
65+
start_time = msr_trimmed.starttime
66+
end_time = msr_trimmed.endtime
67+
sample_period_ns = int(NSTMODULUS / msr_trimmed.samprate)
7168

7269
# Trim early samples to the earliest time
7370
if earliest and start_time < earliest <= end_time:
@@ -90,10 +87,10 @@ def trim_record(msr, earliest, latest):
9087
return None
9188

9289
# Pack the trimmed record
93-
record.starttime = start_time
90+
msr_trimmed.starttime = start_time
9491
record_buffer = b""
95-
for packed_record in record.generate(
96-
data_samples=data_samples, sample_type=record.sampletype
92+
for packed_record in msr_trimmed.generate(
93+
data_samples=data_samples, sample_type=msr_trimmed.sampletype
9794
):
9895
record_buffer += packed_record
9996

src/pymseed/msrecord.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,8 +1264,12 @@ def to_file(
12641264
def from_file(cls, filename, **kwargs):
12651265
"""Create a record reader for miniSEED files.
12661266
1267-
This convenience method returns an MS3RecordReader that can iterate
1268-
over all records in a miniSEED file.
1267+
This convenience method returns an MS3RecordReader that can iterate over
1268+
all records in a miniSEED file.
1269+
1270+
Note that the objects returned by this iterator are only valid during
1271+
the lifetime of the iterator. Once the iterator is exhausted, the
1272+
objects are no longer valid and should not be used.
12691273
12701274
Args:
12711275
filename: Path to miniSEED file
@@ -1287,8 +1291,12 @@ def from_file(cls, filename, **kwargs):
12871291
def from_buffer(cls, buffer, **kwargs):
12881292
"""Create a record reader for miniSEED data in memory.
12891293
1290-
This convenience method returns an MS3RecordBufferReader that can iterate
1291-
over records stored in a memory buffer (bytes-like object).
1294+
This convenience method returns an MS3RecordBufferReader that can
1295+
iterate over records stored in a memory buffer (bytes-like object).
1296+
1297+
Note that the objects returned by this iterator are only valid during
1298+
the lifetime of the iterator. Once the iterator is exhausted, the
1299+
objects are no longer valid and should not be used.
12921300
12931301
Args:
12941302
buffer: Bytes-like object containing miniSEED data

src/pymseed/msrecord_buffer_reader.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class MS3RecordBufferReader:
2424
parsed sequentially from the beginning of the buffer using the underlying
2525
libmseed library.
2626
27+
Note that the objects returned by this iterator are only valid during
28+
the lifetime of the iterator. Once the iterator is exhausted, the objects
29+
are no longer valid and should not be used.
30+
2731
Args:
2832
buffer: A buffer-like object containing miniSEED records. Must support
2933
the buffer protocol (e.g., bytearray, bytes, memoryview, numpy.ndarray).
@@ -45,11 +49,10 @@ class MS3RecordBufferReader:
4549
>>> with open('examples/example_data.mseed', 'rb') as f:
4650
... buffer = f.read()
4751
48-
>>> with MS3Record.from_buffer(buffer, unpack_data=True) as reader:
49-
... total_samples = 0
50-
... for msr in reader:
51-
... total_samples += msr.numsamples
52-
... print(f"Total samples: {total_samples}")
52+
>>> total_samples = 0
53+
>>> for msr in MS3Record.from_buffer(buffer, unpack_data=True):
54+
... total_samples += msr.numsamples
55+
>>> print(f"Total samples: {total_samples}")
5356
Total samples: 12600
5457
5558
Notes:

src/pymseed/msrecord_reader.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,29 @@ class MS3RecordReader:
2121
The reader can be used as an iterator to process records sequentially, or as
2222
a context manager for automatic resource cleanup.
2323
24+
Note that the objects returned by this iterator are only valid during
25+
the lifetime of the iterator. Once the iterator is exhausted, the results
26+
are no longer valid and should not be used.
27+
2428
Args:
2529
input (Union[str, int]): File path (string) or open file descriptor (integer).
2630
If an integer, it must be a valid open file descriptor. The file or
2731
descriptor will be automatically closed when close() is called or when
2832
the object is used as a context manager.
33+
2934
unpack_data (bool, optional): Whether to decode/unpack the data samples from
3035
the records. If False, only metadata is parsed and data remains in
3136
compressed format. Defaults to False for better performance when only
3237
metadata is needed.
38+
3339
skip_not_data (bool, optional): Whether to skip non-data bytes in the input
3440
stream until a valid miniSEED record is found. Useful for reading from
3541
streams that may contain other data mixed with miniSEED records.
3642
Defaults to False.
43+
3744
validate_crc (bool, optional): If True, validate CRC checksums when present in records.
3845
miniSEED v3 records contain CRCs, but v2 records do not. Default is True.
46+
3947
verbose (int, optional): Verbosity level for for libmseed operations. Higher values
4048
produce more detailed output. 0 = no output, 1+ = increasing verbosity.
4149
Defaults to 0 (silent).
@@ -48,11 +56,10 @@ class MS3RecordReader:
4856
4957
>>> from pymseed import MS3Record
5058
51-
>>> with MS3Record.from_file('examples/example_data.mseed', unpack_data=True) as reader:
52-
... total_samples = 0
53-
... for msr in reader:
54-
... total_samples += msr.numsamples
55-
... print(f"Total samples: {total_samples}")
59+
>>> total_samples = 0
60+
>>> for msr in MS3Record.from_file('examples/example_data.mseed', unpack_data=True):
61+
... total_samples += msr.numsamples
62+
>>> print(f"Total samples: {total_samples}")
5663
Total samples: 12600
5764
5865
@@ -61,9 +68,10 @@ class MS3RecordReader:
6168
>>> import os
6269
>>> fd = os.open('examples/example_data.mseed', os.O_RDONLY)
6370
64-
>>> with MS3Record.from_file(fd, unpack_data=True) as reader:
65-
... msrs = list(reader) # Read all records
66-
... print(f"Total records: {len(msrs)}")
71+
>>> total_records = 0
72+
>>> for msr in MS3Record.from_file(fd, unpack_data=False):
73+
... total_records += 1
74+
>>> print(f"Total records: {total_records}")
6775
Total records: 107
6876
6977
Note:

0 commit comments

Comments
 (0)