0
# Core Data Structures
1
2
Fundamental data objects for seismological time series, event catalogs, and station metadata. These objects provide the foundation for all ObsPy functionality with automatic format detection and seamless integration across the seismological data ecosystem.
3
4
## Capabilities
5
6
### UTCDateTime Class
7
8
UTC-based datetime handling specifically designed for seismological timestamps with microsecond precision and specialized formatting for seismological standards.
9
10
```python { .api }
11
class UTCDateTime:
12
def __init__(self, *args, **kwargs):
13
"""
14
Create UTC datetime object.
15
16
Args:
17
*args: Various input formats (string, timestamp, datetime components)
18
**kwargs: Additional parameters
19
20
Examples:
21
UTCDateTime() # Current time
22
UTCDateTime("2023-01-01T00:00:00")
23
UTCDateTime(2023, 1, 1, 0, 0, 0)
24
UTCDateTime(1672531200.0) # Unix timestamp
25
"""
26
27
def strftime(self, fmt: str) -> str:
28
"""Format datetime as string using strftime format codes."""
29
30
def strptime(cls, date_string: str, format: str) -> 'UTCDateTime':
31
"""Parse string to UTCDateTime using format codes."""
32
33
def format_fissures(self) -> str:
34
"""Format for FISSURES/DHI web services."""
35
36
def format_arclink(self) -> str:
37
"""Format for ArcLink protocol."""
38
39
def format_seedlink(self) -> str:
40
"""Format for SeedLink protocol."""
41
42
def format_seed(self) -> str:
43
"""Format for SEED standard."""
44
45
def format_iris_web_service(self) -> str:
46
"""Format for IRIS web services."""
47
48
def now(cls) -> 'UTCDateTime':
49
"""Get current UTC time."""
50
51
def utcnow(cls) -> 'UTCDateTime':
52
"""Get current UTC time (alias for now())."""
53
54
@property
55
def matplotlib_date(self) -> float:
56
"""Get matplotlib-compatible date number."""
57
58
def replace(self, **kwargs) -> 'UTCDateTime':
59
"""Return datetime with specified components replaced."""
60
61
def timetuple(self) -> tuple:
62
"""Return time tuple compatible with time module."""
63
64
def utctimetuple(self) -> tuple:
65
"""Return UTC time tuple."""
66
67
def toordinal(self) -> int:
68
"""Return proleptic Gregorian ordinal."""
69
70
def isoformat(self) -> str:
71
"""Return ISO format string."""
72
73
def isoweekday(self) -> int:
74
"""Return day of week (1=Monday, 7=Sunday)."""
75
76
def isocalendar(self) -> tuple:
77
"""Return ISO calendar tuple (year, week, weekday)."""
78
```
79
80
### Trace Class
81
82
Single seismogram trace container with data array and metadata, providing the fundamental building block for seismological time series analysis.
83
84
```python { .api }
85
class Trace:
86
def __init__(self, data=None, header=None):
87
"""
88
Create seismogram trace.
89
90
Args:
91
data: NumPy array containing seismic data
92
header: Dictionary or Stats object with metadata
93
"""
94
95
@property
96
def data(self):
97
"""NumPy array containing seismic data."""
98
99
@property
100
def stats(self) -> 'Stats':
101
"""Trace metadata (Stats object)."""
102
103
@property
104
def id(self) -> str:
105
"""Unique trace identifier (network.station.location.channel)."""
106
107
def plot(self, **kwargs):
108
"""
109
Plot trace waveform.
110
111
Args:
112
**kwargs: Matplotlib plotting options
113
"""
114
115
def spectrogram(self, **kwargs):
116
"""
117
Plot spectrogram of trace data.
118
119
Args:
120
**kwargs: Spectrogram parameters and plotting options
121
"""
122
123
def write(self, filename: str, format: str = None, **kwargs):
124
"""
125
Write trace to file.
126
127
Args:
128
filename: Output filename
129
format: Format (auto-detected if None)
130
**kwargs: Format-specific options
131
"""
132
133
def trim(self, starttime=None, endtime=None, **kwargs) -> 'Trace':
134
"""
135
Trim trace to time window.
136
137
Args:
138
starttime: Start time (UTCDateTime or None)
139
endtime: End time (UTCDateTime or None)
140
**kwargs: Additional trim options
141
142
Returns:
143
Modified trace (in-place)
144
"""
145
146
def slice(self, starttime=None, endtime=None) -> 'Trace':
147
"""
148
Return new trace with data sliced to time window.
149
150
Args:
151
starttime: Start time (UTCDateTime or None)
152
endtime: End time (UTCDateTime or None)
153
154
Returns:
155
New Trace object with sliced data
156
"""
157
158
def filter(self, type: str, **options) -> 'Trace':
159
"""
160
Apply digital filter to trace data.
161
162
Args:
163
type: Filter type ('bandpass', 'lowpass', 'highpass', etc.)
164
**options: Filter-specific parameters (frequencies, etc.)
165
166
Returns:
167
Modified trace (in-place)
168
"""
169
170
def trigger(self, type: str, **options):
171
"""
172
Apply triggering algorithm to trace data.
173
174
Args:
175
type: Trigger type ('recstalta', 'classicstalta', etc.)
176
**options: Trigger-specific parameters
177
178
Returns:
179
Trigger function or onset times
180
"""
181
182
def resample(self, sampling_rate: float, **kwargs) -> 'Trace':
183
"""
184
Resample trace to new sampling rate.
185
186
Args:
187
sampling_rate: Target sampling rate in Hz
188
**kwargs: Resampling options
189
190
Returns:
191
Modified trace (in-place)
192
"""
193
194
def decimate(self, factor: int, **kwargs) -> 'Trace':
195
"""
196
Decimate trace by integer factor.
197
198
Args:
199
factor: Decimation factor
200
**kwargs: Decimation options
201
202
Returns:
203
Modified trace (in-place)
204
"""
205
206
def simulate(self, paz_remove=None, paz_simulate=None, **kwargs) -> 'Trace':
207
"""
208
Simulate instrument response.
209
210
Args:
211
paz_remove: Poles and zeros to remove
212
paz_simulate: Poles and zeros to simulate
213
**kwargs: Simulation options
214
215
Returns:
216
Modified trace (in-place)
217
"""
218
219
def detrend(self, type: str = 'linear', **kwargs) -> 'Trace':
220
"""
221
Remove trend from trace data.
222
223
Args:
224
type: Detrend type ('linear', 'constant', 'polynomial', etc.)
225
**kwargs: Detrend-specific options
226
227
Returns:
228
Modified trace (in-place)
229
"""
230
231
def taper(self, max_percentage: float = 0.05, type: str = 'hann', **kwargs) -> 'Trace':
232
"""
233
Apply taper to trace data.
234
235
Args:
236
max_percentage: Taper length as fraction of trace
237
type: Taper type ('hann', 'cosine', etc.)
238
**kwargs: Taper options
239
240
Returns:
241
Modified trace (in-place)
242
"""
243
244
def normalize(self, norm: float = None) -> 'Trace':
245
"""
246
Normalize trace data.
247
248
Args:
249
norm: Normalization value (max absolute value if None)
250
251
Returns:
252
Modified trace (in-place)
253
"""
254
255
def differentiate(self, method: str = 'gradient') -> 'Trace':
256
"""
257
Differentiate trace data.
258
259
Args:
260
method: Differentiation method
261
262
Returns:
263
Modified trace (in-place)
264
"""
265
266
def integrate(self, method: str = 'cumtrapz') -> 'Trace':
267
"""
268
Integrate trace data.
269
270
Args:
271
method: Integration method
272
273
Returns:
274
Modified trace (in-place)
275
"""
276
277
def attach_response(self, response):
278
"""
279
Attach instrument response to trace.
280
281
Args:
282
response: Response object or filename
283
"""
284
285
def remove_response(self, **kwargs) -> 'Trace':
286
"""
287
Remove instrument response from trace data.
288
289
Args:
290
**kwargs: Response removal options
291
292
Returns:
293
Modified trace (in-place)
294
"""
295
296
def remove_sensitivity(self, **kwargs) -> 'Trace':
297
"""
298
Remove instrument sensitivity from trace data.
299
300
Args:
301
**kwargs: Sensitivity removal options
302
303
Returns:
304
Modified trace (in-place)
305
"""
306
307
def copy(self) -> 'Trace':
308
"""Return deep copy of trace."""
309
310
def split(self) -> list['Trace']:
311
"""Split trace at gaps, returning list of traces."""
312
313
def times(self, type: str = 'matplotlib') -> np.ndarray:
314
"""
315
Generate time array for trace data.
316
317
Args:
318
type: Time array type ('matplotlib', 'utcdatetime', 'timestamp')
319
320
Returns:
321
NumPy array of time values
322
"""
323
324
def max(self) -> float:
325
"""Return maximum absolute value of trace data."""
326
327
def std(self) -> float:
328
"""Return standard deviation of trace data."""
329
330
def verify(self) -> bool:
331
"""Verify trace integrity and consistency."""
332
```
333
334
### Stats Class
335
336
Metadata container for trace information extending dictionary functionality with attribute access and seismological standards compliance.
337
338
```python { .api }
339
class Stats(AttribDict):
340
def __init__(self, header=None):
341
"""
342
Create trace metadata container.
343
344
Args:
345
header: Dictionary of metadata values
346
"""
347
348
# Standard SEED metadata attributes
349
sampling_rate: float # Sampling rate in Hz
350
delta: float # Sample interval in seconds
351
npts: int # Number of data points
352
network: str # Network code (SEED standard)
353
station: str # Station code (SEED standard)
354
location: str # Location code (SEED standard)
355
channel: str # Channel code (SEED standard)
356
starttime: UTCDateTime # Start time of trace
357
endtime: UTCDateTime # End time of trace
358
calib: float # Calibration factor
359
```
360
361
### Stream Class
362
363
Collection of Trace objects with ensemble processing capabilities for multi-channel and multi-station seismological data analysis.
364
365
```python { .api }
366
class Stream:
367
def __init__(self, traces=None):
368
"""
369
Create stream from traces.
370
371
Args:
372
traces: List of Trace objects or None for empty stream
373
"""
374
375
def __len__(self) -> int:
376
"""Return number of traces in stream."""
377
378
def __getitem__(self, index) -> Trace:
379
"""Get trace by index or slice."""
380
381
def __setitem__(self, index, trace: Trace):
382
"""Set trace at index."""
383
384
def append(self, trace: Trace):
385
"""Add trace to end of stream."""
386
387
def extend(self, trace_list: list[Trace]):
388
"""Extend stream with list of traces."""
389
390
def insert(self, index: int, trace: Trace):
391
"""Insert trace at specified index."""
392
393
def remove(self, trace: Trace):
394
"""Remove trace from stream."""
395
396
def pop(self, index: int = -1) -> Trace:
397
"""Remove and return trace at index."""
398
399
def reverse(self):
400
"""Reverse order of traces in stream."""
401
402
def sort(self, keys: list[str] = ['network', 'station', 'location', 'channel', 'starttime']):
403
"""
404
Sort traces by metadata keys.
405
406
Args:
407
keys: List of metadata keys for sorting priority
408
"""
409
410
def select(self, **kwargs) -> 'Stream':
411
"""
412
Select traces matching criteria.
413
414
Args:
415
**kwargs: Selection criteria (network, station, channel, etc.)
416
417
Returns:
418
New Stream with matching traces
419
"""
420
421
def plot(self, **kwargs):
422
"""
423
Plot all traces in stream.
424
425
Args:
426
**kwargs: Plotting options
427
"""
428
429
def spectrogram(self, **kwargs):
430
"""
431
Plot spectrograms of all traces.
432
433
Args:
434
**kwargs: Spectrogram parameters
435
"""
436
437
def write(self, filename: str, format: str = None, **kwargs):
438
"""
439
Write stream to file.
440
441
Args:
442
filename: Output filename
443
format: Format (auto-detected if None)
444
**kwargs: Format-specific options
445
"""
446
447
def trim(self, starttime=None, endtime=None, **kwargs) -> 'Stream':
448
"""
449
Trim all traces to time window.
450
451
Args:
452
starttime: Start time (UTCDateTime or None)
453
endtime: End time (UTCDateTime or None)
454
**kwargs: Trim options
455
456
Returns:
457
Modified stream (in-place)
458
"""
459
460
def cutout(self, starttime, endtime) -> 'Stream':
461
"""
462
Remove time window from all traces.
463
464
Args:
465
starttime: Start time of cutout window
466
endtime: End time of cutout window
467
468
Returns:
469
Modified stream (in-place)
470
"""
471
472
def slice(self, starttime=None, endtime=None) -> 'Stream':
473
"""
474
Return new stream with traces sliced to time window.
475
476
Args:
477
starttime: Start time (UTCDateTime or None)
478
endtime: End time (UTCDateTime or None)
479
480
Returns:
481
New Stream with sliced traces
482
"""
483
484
def slide(self, window_length: float, step: float, **kwargs):
485
"""
486
Generator yielding sliding time windows.
487
488
Args:
489
window_length: Window length in seconds
490
step: Step size in seconds
491
**kwargs: Additional options
492
493
Yields:
494
Stream objects for each time window
495
"""
496
497
def merge(self, method: int = -1, interpolation_samples: int = -1, **kwargs) -> 'Stream':
498
"""
499
Merge overlapping or adjacent traces.
500
501
Args:
502
method: Merge method (-1=auto, 0=sum, 1=overlap)
503
interpolation_samples: Interpolation gap limit
504
**kwargs: Merge options
505
506
Returns:
507
Modified stream (in-place)
508
"""
509
510
def get_gaps(self) -> list:
511
"""
512
Get list of gaps between traces.
513
514
Returns:
515
List of gap information tuples
516
"""
517
518
def print_gaps(self):
519
"""Print gap information to stdout."""
520
521
def verify(self) -> bool:
522
"""Verify stream integrity and trace consistency."""
523
524
def filter(self, type: str, **options) -> 'Stream':
525
"""
526
Apply filter to all traces.
527
528
Args:
529
type: Filter type
530
**options: Filter parameters
531
532
Returns:
533
Modified stream (in-place)
534
"""
535
536
def trigger(self, type: str, **options):
537
"""
538
Apply trigger to all traces.
539
540
Args:
541
type: Trigger type
542
**options: Trigger parameters
543
544
Returns:
545
Trigger results for all traces
546
"""
547
548
def resample(self, sampling_rate: float, **kwargs) -> 'Stream':
549
"""
550
Resample all traces.
551
552
Args:
553
sampling_rate: Target sampling rate
554
**kwargs: Resampling options
555
556
Returns:
557
Modified stream (in-place)
558
"""
559
560
def decimate(self, factor: int, **kwargs) -> 'Stream':
561
"""
562
Decimate all traces.
563
564
Args:
565
factor: Decimation factor
566
**kwargs: Decimation options
567
568
Returns:
569
Modified stream (in-place)
570
"""
571
572
def simulate(self, **kwargs) -> 'Stream':
573
"""
574
Simulate instrument response for all traces.
575
576
Args:
577
**kwargs: Simulation options
578
579
Returns:
580
Modified stream (in-place)
581
"""
582
583
def detrend(self, type: str = 'linear', **kwargs) -> 'Stream':
584
"""
585
Detrend all traces.
586
587
Args:
588
type: Detrend type
589
**kwargs: Detrend options
590
591
Returns:
592
Modified stream (in-place)
593
"""
594
595
def taper(self, max_percentage: float = 0.05, **kwargs) -> 'Stream':
596
"""
597
Taper all traces.
598
599
Args:
600
max_percentage: Taper length fraction
601
**kwargs: Taper options
602
603
Returns:
604
Modified stream (in-place)
605
"""
606
607
def normalize(self, **kwargs) -> 'Stream':
608
"""
609
Normalize all traces.
610
611
Args:
612
**kwargs: Normalization options
613
614
Returns:
615
Modified stream (in-place)
616
"""
617
618
def differentiate(self, **kwargs) -> 'Stream':
619
"""
620
Differentiate all traces.
621
622
Args:
623
**kwargs: Differentiation options
624
625
Returns:
626
Modified stream (in-place)
627
"""
628
629
def integrate(self, **kwargs) -> 'Stream':
630
"""
631
Integrate all traces.
632
633
Args:
634
**kwargs: Integration options
635
636
Returns:
637
Modified stream (in-place)
638
"""
639
640
def max(self) -> float:
641
"""Return maximum absolute value across all traces."""
642
643
def std(self) -> float:
644
"""Return standard deviation across all traces."""
645
646
def rotate(self, method: str, **kwargs) -> 'Stream':
647
"""
648
Rotate coordinate components.
649
650
Args:
651
method: Rotation method ('NE->RT', 'ZNE->LQT', etc.)
652
**kwargs: Rotation parameters (back_azimuth, inclination, etc.)
653
654
Returns:
655
Modified stream (in-place)
656
"""
657
658
def attach_response(self, response):
659
"""
660
Attach instrument response to all traces.
661
662
Args:
663
response: Response object or inventory
664
"""
665
666
def remove_response(self, **kwargs) -> 'Stream':
667
"""
668
Remove instrument response from all traces.
669
670
Args:
671
**kwargs: Response removal options
672
673
Returns:
674
Modified stream (in-place)
675
"""
676
677
def remove_sensitivity(self, **kwargs) -> 'Stream':
678
"""
679
Remove sensitivity from all traces.
680
681
Args:
682
**kwargs: Sensitivity removal options
683
684
Returns:
685
Modified stream (in-place)
686
"""
687
688
def stack(self, **kwargs) -> list[Trace]:
689
"""
690
Stack traces by metadata groups.
691
692
Args:
693
**kwargs: Stacking options
694
695
Returns:
696
List of stacked traces
697
"""
698
699
def copy(self, deep: bool = True) -> 'Stream':
700
"""
701
Return copy of stream.
702
703
Args:
704
deep: Create deep copy if True
705
706
Returns:
707
Copied Stream object
708
"""
709
710
def clear(self):
711
"""Remove all traces from stream."""
712
713
def split(self) -> 'Stream':
714
"""
715
Split traces at gaps.
716
717
Returns:
718
Modified stream with split traces (in-place)
719
"""
720
```
721
722
### Universal Read Functions
723
724
Format-agnostic functions for reading seismological data files with automatic format detection and unified interfaces.
725
726
```python { .api }
727
def read(pathname_or_url, format=None, headonly=False, starttime=None,
728
endtime=None, nearest_sample=True, dtype=None, apply_calib=False,
729
check_compression=True, **kwargs) -> Stream:
730
"""
731
Read waveform files into Stream object.
732
733
Args:
734
pathname_or_url: File path, URL, or file-like object
735
format: Format hint (auto-detected if None)
736
headonly: Read metadata only, skip data
737
starttime: Start time for reading window
738
endtime: End time for reading window
739
nearest_sample: Align times to nearest sample
740
dtype: Data type for conversion
741
apply_calib: Apply calibration factor
742
check_compression: Verify compressed data integrity
743
**kwargs: Format-specific options
744
745
Returns:
746
Stream object containing traces
747
748
Supported formats: MiniSEED, SAC, GSE2, SEG-Y, WIN, CSS, SEISAN,
749
AH, WAV, GCF, RefTek, PDAS, Y, SEG-2, SH,
750
Kinemetrics, NIED, RG16, DMX, ALSEP, and others
751
"""
752
753
def read_events(pathname_or_url, format=None, **kwargs):
754
"""
755
Read earthquake event files into Catalog object.
756
757
Args:
758
pathname_or_url: File path, URL, or file-like object
759
format: Format hint (auto-detected if None)
760
**kwargs: Format-specific options
761
762
Returns:
763
Catalog object containing events
764
765
Supported formats: QuakeML, NDK, CMTSOLUTION, Nordic, NonLinLoc,
766
SC3ML, ZMAP, JSON, MCHEDR, CNV, FOCMEC,
767
HypoDD, SCARDEC, GSE2, IMS1.0, and others
768
"""
769
770
def read_inventory(pathname_or_url, format=None, **kwargs):
771
"""
772
Read station metadata files into Inventory object.
773
774
Args:
775
pathname_or_url: File path, URL, or file-like object
776
format: Format hint (auto-detected if None)
777
**kwargs: Format-specific options
778
779
Returns:
780
Inventory object containing station metadata
781
782
Supported formats: StationXML, SEED/XSEED, SACPZ, CSS,
783
Station text, SC3ML, ArcLink XML, and others
784
"""
785
```
786
787
## Usage Examples
788
789
### Basic Trace Operations
790
791
```python
792
from obspy import Trace, UTCDateTime
793
import numpy as np
794
795
# Create trace with synthetic data
796
data = np.random.randn(1000)
797
trace = Trace(data=data)
798
trace.stats.sampling_rate = 100.0
799
trace.stats.starttime = UTCDateTime("2023-01-01T00:00:00")
800
trace.stats.network = "XX"
801
trace.stats.station = "TEST"
802
trace.stats.channel = "HHZ"
803
804
# Basic processing
805
trace.detrend('linear')
806
trace.filter('bandpass', freqmin=1.0, freqmax=10.0)
807
trace.taper(0.05)
808
809
# Get trace information
810
print(f"Trace ID: {trace.id}")
811
print(f"Duration: {trace.stats.endtime - trace.stats.starttime} seconds")
812
print(f"Max amplitude: {trace.max()}")
813
```
814
815
### Stream Processing Workflow
816
817
```python
818
from obspy import read
819
820
# Read seismic data file
821
st = read('seismic_data.mseed')
822
823
# Pre-processing
824
st.detrend('linear')
825
st.taper(0.05)
826
st.filter('bandpass', freqmin=1.0, freqmax=20.0)
827
828
# Merge overlapping traces and remove gaps
829
st.merge(method=1, interpolation_samples=10)
830
831
# Select specific components
832
st_z = st.select(channel="*Z") # Vertical components
833
st_n = st.select(channel="*N") # North components
834
st_e = st.select(channel="*E") # East components
835
836
# Rotate horizontal components to radial-transverse
837
st_horizontal = st_n + st_e # Combine N and E components
838
st_horizontal.rotate('NE->RT', back_azimuth=45.0)
839
840
# Time window extraction
841
event_time = UTCDateTime("2023-01-15T10:30:00")
842
st_event = st.slice(event_time, event_time + 300) # 5-minute window
843
```
844
845
## Types
846
847
```python { .api }
848
class AttribDict(dict):
849
"""Dictionary with attribute-style access to keys."""
850
851
def __init__(self, *args, **kwargs):
852
"""Initialize with dictionary data."""
853
854
def __getattr__(self, name):
855
"""Get dictionary value as attribute."""
856
857
def __setattr__(self, name, value):
858
"""Set dictionary value as attribute."""
859
860
def __delattr__(self, name):
861
"""Delete dictionary key as attribute."""
862
```