0
# Visualization and Imaging
1
2
Seismological visualization capabilities including waveform plotting, spectrograms, focal mechanism beachballs, and array processing visualizations integrated with matplotlib. These tools provide publication-quality graphics for seismological data analysis and presentation.
3
4
## Capabilities
5
6
### Integrated Waveform Plotting
7
8
Built-in plotting methods for Trace and Stream objects with seismological conventions and customization options.
9
10
```python { .api }
11
# Trace plotting methods
12
Trace.plot(self, type: str = 'normal', starttime=None, endtime=None,
13
fig=None, ax=None, title: str = None, show: bool = True,
14
draw: bool = None, block: bool = None, **kwargs):
15
"""
16
Plot single trace waveform.
17
18
Args:
19
type: Plot type ('normal', 'dayplot', 'relative')
20
starttime: Start time for plot window (UTCDateTime or None)
21
endtime: End time for plot window (UTCDateTime or None)
22
fig: Matplotlib figure object (created if None)
23
ax: Matplotlib axes object (created if None)
24
title: Plot title (auto-generated if None)
25
show: Display plot immediately
26
draw: Force matplotlib draw
27
block: Block execution until window closed
28
**kwargs: Additional matplotlib plotting options
29
30
Matplotlib kwargs:
31
color, linewidth, linestyle, alpha, label, etc.
32
"""
33
34
# Stream plotting methods
35
Stream.plot(self, type: str = 'normal', starttime=None, endtime=None,
36
fig=None, size: tuple = (800, 250), title: str = None,
37
color: str = 'black', number_of_ticks: int = 4,
38
tick_rotation: int = 0, tick_format: str = None,
39
show: bool = True, draw: bool = None, block: bool = None,
40
equal_scale: bool = True, **kwargs):
41
"""
42
Plot multiple traces in stream.
43
44
Args:
45
type: Plot type ('normal', 'dayplot', 'section')
46
starttime: Plot window start time
47
endtime: Plot window end time
48
fig: Matplotlib figure object
49
size: Figure size in pixels (width, height)
50
title: Plot title
51
color: Trace color (single color or list)
52
number_of_ticks: Number of time axis ticks
53
tick_rotation: Rotation angle for tick labels
54
tick_format: Time tick format string
55
show: Display plot
56
draw: Force draw
57
block: Block until closed
58
equal_scale: Use same amplitude scale for all traces
59
**kwargs: Additional plotting options
60
61
Plot Types:
62
'normal': Standard time series plot
63
'dayplot': 24-hour record section plot
64
'section': Record section with distance/time axes
65
"""
66
```
67
68
### Spectrogram Visualization
69
70
Time-frequency analysis plots for investigating spectral content evolution.
71
72
```python { .api }
73
# Trace spectrogram
74
Trace.spectrogram(self, log: bool = False, outfile: str = None,
75
format: str = None, axes=None, show: bool = True,
76
title: str = None, **kwargs):
77
"""
78
Plot spectrogram of trace data.
79
80
Args:
81
log: Use logarithmic frequency scale
82
outfile: Save plot to file (format from extension)
83
format: Image format for saving
84
axes: Matplotlib axes object
85
show: Display plot
86
title: Plot title
87
**kwargs: Spectrogram parameters
88
89
Spectrogram Parameters:
90
samp_rate: Sampling rate override
91
per_lap: Window overlap percentage (0-1)
92
wlen: Window length in seconds
93
mult: Frequency scaling multiplier
94
cmap: Colormap name
95
vmin, vmax: Color scale limits
96
dbscale: Use decibel scale
97
"""
98
99
# Stream spectrogram
100
Stream.spectrogram(self, **kwargs):
101
"""
102
Plot spectrograms for all traces in stream.
103
104
Args:
105
**kwargs: Same as Trace.spectrogram()
106
107
Creates subplot for each trace in stream.
108
"""
109
```
110
111
### Beachball Plots
112
113
Focal mechanism visualization using beachball (stereonet) representations.
114
115
```python { .api }
116
# Import from obspy.imaging.beachball
117
def beachball(fm, linewidth: int = 2, facecolor: str = 'b', bgcolor: str = 'w',
118
edgecolor: str = 'k', alpha: float = 1.0, xy: tuple = (0, 0),
119
width: int = 200, size: int = 100, nofill: bool = False,
120
zorder: int = 100, outfile: str = None, format: str = None,
121
fig=None, **kwargs):
122
"""
123
Draw focal mechanism beachball.
124
125
Args:
126
fm: Focal mechanism (strike, dip, rake) or moment tensor
127
linewidth: Nodal plane line width
128
facecolor: Compressional quadrant color
129
bgcolor: Background color
130
edgecolor: Outline color
131
alpha: Transparency (0-1)
132
xy: Center position for plot
133
width: Beachball width in points
134
size: Beachball size in points
135
nofill: Draw outline only
136
zorder: Matplotlib drawing order
137
outfile: Save to file
138
format: Image format
139
fig: Matplotlib figure
140
**kwargs: Additional options
141
142
Focal Mechanism Formats:
143
[strike, dip, rake]: Single nodal plane (degrees)
144
[strike1, dip1, rake1, strike2, dip2, rake2]: Both planes
145
MomentTensor object: Full moment tensor
146
[mrr, mtt, mpp, mrt, mrp, mtp]: Moment tensor components
147
"""
148
149
def beach(fm, **kwargs):
150
"""
151
Create beachball plot (alias for beachball function).
152
153
Args:
154
fm: Focal mechanism data
155
**kwargs: Same as beachball()
156
157
Returns:
158
Matplotlib collection object
159
"""
160
```
161
162
### Advanced Visualization Tools
163
164
#### Day Plot Format
165
166
24-hour continuous recording visualization with time and spectral information.
167
168
```python { .api }
169
# Create day plot from continuous data
170
st = read('continuous_24h.mseed')
171
st.plot(type='dayplot',
172
starttime=UTCDateTime("2023-01-01T00:00:00"),
173
title="24-Hour Seismic Record",
174
color=['red', 'blue', 'green'], # Different colors per channel
175
number_of_ticks=6, # 4-hour intervals
176
tick_format='%H:%M',
177
size=(1200, 800))
178
```
179
180
#### Record Section Plots
181
182
Multi-station/multi-event plotting with distance or time alignment.
183
184
```python { .api }
185
# Record section plotting parameters for Stream.plot()
186
SECTION_PLOT_OPTIONS = {
187
'type': 'section',
188
'recordlength': 300, # Trace length in seconds
189
'recordstart': 0, # Start offset in seconds
190
'norm_method': 'trace', # Normalization ('trace', 'stream', 'global')
191
'distance_degree': True, # Use degree distances
192
'ev_coord': tuple, # Event coordinates (lat, lon)
193
'alpha': 0.8, # Transparency
194
'linewidth': 1.0 # Line width
195
}
196
```
197
198
### PPSD Visualization
199
200
Probabilistic Power Spectral Density plotting with multiple display modes.
201
202
```python { .api }
203
# PPSD plotting methods (see signal-processing.md for PPSD class)
204
PPSD.plot(self, filename: str = None, show_coverage: bool = True,
205
show_histogram: bool = True, show_percentiles: bool = False,
206
percentiles: list = [0, 25, 50, 75, 100], show_noise_models: bool = True,
207
grid: bool = True, period_lim: tuple = None, show_mean: bool = False,
208
**kwargs):
209
"""
210
Plot PPSD analysis results.
211
212
Args:
213
filename: Save plot to file
214
show_coverage: Show temporal coverage
215
show_histogram: Show probability density histogram
216
show_percentiles: Show percentile curves
217
percentiles: List of percentiles to display
218
show_noise_models: Show Peterson noise models
219
grid: Show grid lines
220
period_lim: Period axis limits (min, max)
221
show_mean: Show mean power levels
222
**kwargs: Additional plotting options
223
"""
224
225
PPSD.plot_temporal(self, starttime=None, endtime=None, filename: str = None,
226
**kwargs):
227
"""
228
Plot temporal evolution of power spectral densities.
229
230
Args:
231
starttime: Time window start
232
endtime: Time window end
233
filename: Save to file
234
**kwargs: Plotting options
235
"""
236
237
PPSD.plot_spectrogram(self, filename: str = None, clim: tuple = None, **kwargs):
238
"""
239
Plot spectrogram view of PPSD data.
240
241
Args:
242
filename: Output filename
243
clim: Color scale limits
244
**kwargs: Additional options
245
"""
246
```
247
248
## Usage Examples
249
250
### Basic Waveform Plotting
251
252
```python
253
from obspy import read, UTCDateTime
254
import matplotlib.pyplot as plt
255
256
# Read seismic data
257
st = read('seismic_data.mseed')
258
259
# Simple trace plot
260
trace = st[0]
261
trace.plot()
262
263
# Customized trace plot
264
trace.plot(color='red', linewidth=1.5,
265
title=f"Seismogram: {trace.id}",
266
starttime=trace.stats.starttime,
267
endtime=trace.stats.starttime + 300) # First 5 minutes
268
269
# Stream plot with multiple traces
270
st.plot(type='normal',
271
size=(1000, 600),
272
color=['black', 'red', 'blue'],
273
equal_scale=True,
274
title="Three-Component Seismogram")
275
```
276
277
### Spectrogram Analysis
278
279
```python
280
from obspy import read
281
import matplotlib.pyplot as plt
282
283
# Read earthquake data
284
st = read('earthquake_record.mseed')
285
trace = st.select(channel="*Z")[0] # Vertical component
286
287
# Basic spectrogram
288
trace.spectrogram(show=True)
289
290
# Advanced spectrogram with custom parameters
291
fig, ax = plt.subplots(figsize=(12, 8))
292
trace.spectrogram(
293
log=True, # Logarithmic frequency scale
294
axes=ax,
295
show=False,
296
# Spectrogram parameters
297
wlen=10.0, # 10-second windows
298
per_lap=0.9, # 90% overlap
299
mult=2.0, # Frequency multiplier
300
cmap='plasma', # Color scheme
301
vmin=-160, # Color scale minimum
302
vmax=-100, # Color scale maximum
303
dbscale=True # Decibel scale
304
)
305
ax.set_title(f"Spectrogram: {trace.id}")
306
ax.set_ylabel("Frequency (Hz)")
307
ax.set_xlabel("Time")
308
plt.show()
309
310
# Multi-channel spectrograms
311
st_3c = st.select(station="ANMO") # All components from one station
312
st_3c.spectrogram() # Creates subplot for each component
313
```
314
315
### Focal Mechanism Visualization
316
317
```python
318
from obspy.imaging.beachball import beachball, beach
319
import matplotlib.pyplot as plt
320
321
# Focal mechanism parameters (strike, dip, rake)
322
focal_mechanisms = [
323
[95, 85, 180], # Strike-slip
324
[0, 90, -90], # Normal fault
325
[45, 30, 90], # Reverse fault
326
[315, 45, 45], # Oblique
327
]
328
329
mechanism_types = ["Strike-slip", "Normal", "Reverse", "Oblique"]
330
331
fig, axes = plt.subplots(2, 2, figsize=(10, 10))
332
axes = axes.flatten()
333
334
for i, (fm, mtype) in enumerate(zip(focal_mechanisms, mechanism_types)):
335
# Create beachball on specific axes
336
ax = axes[i]
337
beachball(fm, ax=ax, size=100,
338
facecolor='red', # Compressional quadrants
339
bgcolor='white', # Background
340
edgecolor='black', # Outline
341
linewidth=2)
342
343
ax.set_title(f"{mtype}\nStrike={fm[0]}°, Dip={fm[1]}°, Rake={fm[2]}°")
344
ax.set_xlim(-1.2, 1.2)
345
ax.set_ylim(-1.2, 1.2)
346
ax.set_aspect('equal')
347
348
plt.tight_layout()
349
plt.show()
350
351
# Beachballs with moment tensor
352
from obspy.imaging.beachball import MomentTensor
353
354
# Harvard CMT solution (Mrr, Mtt, Mpp, Mrt, Mrp, Mtp)
355
mt_components = [1.0, -1.0, 0.0, 0.0, 0.0, 0.0] # Simple strike-slip
356
357
beachball(mt_components,
358
outfile='focal_mechanism.png',
359
format='PNG',
360
size=200)
361
```
362
363
### Day Plot Visualization
364
365
```python
366
from obspy import read, UTCDateTime
367
368
# Read 24-hour continuous data
369
st = read('continuous_data_24h.mseed')
370
371
# Create day plot
372
start_time = UTCDateTime("2023-01-15T00:00:00")
373
st.plot(type='dayplot',
374
starttime=start_time,
375
title="24-Hour Seismic Record - Station ANMO",
376
size=(1400, 1000),
377
color='black',
378
number_of_ticks=12, # 2-hour intervals
379
tick_format='%H:%M',
380
show_y_UTC_label=True)
381
382
# Day plot with spectrogram overlay
383
st_single = st.select(channel="BHZ") # Single channel
384
st_single.plot(type='dayplot',
385
starttime=start_time,
386
title="Vertical Component with Spectrogram",
387
show_spectrogram=True,
388
spectrogram_cmap='plasma')
389
```
390
391
### Multi-Station Record Section
392
393
```python
394
from obspy import read, UTCDateTime
395
from obspy.geodetics import gps2dist_azimuth
396
397
# Read multi-station earthquake data
398
st = read('regional_earthquake.mseed')
399
400
# Event location
401
event_lat, event_lon = 34.0, -118.0
402
event_time = UTCDateTime("2023-01-15T10:30:00")
403
404
# Calculate distances and add to trace stats
405
for trace in st:
406
# Get station coordinates (from StationXML or manual)
407
sta_lat = trace.stats.coordinates.latitude
408
sta_lon = trace.stats.coordinates.longitude
409
410
# Calculate distance
411
dist_m, az, baz = gps2dist_azimuth(event_lat, event_lon, sta_lat, sta_lon)
412
trace.stats.distance = dist_m / 1000.0 # km
413
414
# Sort by distance
415
st.sort(['distance'])
416
417
# Create record section
418
st.plot(type='section',
419
recordlength=180, # 3-minute traces
420
recordstart=-30, # Start 30s before origin
421
norm_method='trace', # Normalize each trace
422
distance_degree=False, # Use km distances
423
ev_coord=(event_lat, event_lon),
424
alpha=0.8,
425
linewidth=1.0,
426
title="Regional Earthquake Record Section")
427
```
428
429
### PPSD Noise Analysis Visualization
430
431
```python
432
from obspy import read
433
from obspy.signal import PPSD
434
from obspy.clients.fdsn import Client
435
436
# Get instrument response
437
client = Client("IRIS")
438
inventory = client.get_stations(network="IU", station="ANMO",
439
location="00", channel="BHZ",
440
level="response")
441
442
# Read continuous data
443
st = read('noise_data.mseed')
444
445
# Create PPSD analysis
446
ppsd = PPSD(st[0].stats, metadata=inventory)
447
ppsd.add(st)
448
449
# Standard PPSD plot
450
ppsd.plot(show_coverage=True,
451
show_histogram=True,
452
show_percentiles=True,
453
percentiles=[10, 50, 90],
454
show_noise_models=True,
455
filename='ppsd_analysis.png')
456
457
# Temporal evolution plot
458
ppsd.plot_temporal(filename='ppsd_temporal.png')
459
460
# Spectrogram view
461
ppsd.plot_spectrogram(filename='ppsd_spectrogram.png')
462
463
# Custom PPSD plot with multiple percentiles
464
import matplotlib.pyplot as plt
465
466
fig, ax = plt.subplots(figsize=(12, 8))
467
ppsd.plot(axes=ax, show=False,
468
show_percentiles=True,
469
percentiles=[5, 25, 50, 75, 95],
470
grid=True,
471
period_lim=(0.01, 100))
472
473
ax.set_title("Long-term Noise Analysis - Station ANMO")
474
ax.set_xlabel("Period (s)")
475
ax.set_ylabel("Power Spectral Density (dB)")
476
plt.show()
477
```
478
479
### Publication-Quality Figure Creation
480
481
```python
482
from obspy import read, UTCDateTime
483
import matplotlib.pyplot as plt
484
import matplotlib.dates as mdates
485
486
# Read high-quality data
487
st = read('publication_data.mseed')
488
trace = st[0]
489
490
# Create publication figure
491
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))
492
493
# Waveform plot
494
times = trace.times("matplotlib")
495
ax1.plot(times, trace.data, 'k-', linewidth=0.8)
496
ax1.set_ylabel('Amplitude (counts)', fontsize=12)
497
ax1.set_title(f'Seismogram: {trace.id}', fontsize=14, fontweight='bold')
498
ax1.grid(True, alpha=0.3)
499
500
# Format time axis
501
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
502
ax1.xaxis.set_major_locator(mdates.MinuteLocator(interval=2))
503
plt.setp(ax1.xaxis.get_majorticklabels(), rotation=45)
504
505
# Spectrogram
506
trace.spectrogram(axes=ax2, show=False,
507
wlen=30.0, per_lap=0.9,
508
log=True, dbscale=True,
509
cmap='viridis')
510
ax2.set_ylabel('Frequency (Hz)', fontsize=12)
511
ax2.set_xlabel('Time (UTC)', fontsize=12)
512
513
# Adjust layout and save
514
plt.tight_layout()
515
plt.savefig('publication_figure.pdf', dpi=300, bbox_inches='tight')
516
plt.savefig('publication_figure.png', dpi=300, bbox_inches='tight')
517
plt.show()
518
```
519
520
## Types
521
522
```python { .api }
523
# Plot configuration structure
524
PlotConfig = {
525
'type': str, # Plot type ('normal', 'dayplot', 'section')
526
'size': tuple[int, int], # Figure size (width, height) pixels
527
'color': str | list[str], # Colors for traces
528
'linewidth': float, # Line width
529
'title': str, # Plot title
530
'starttime': UTCDateTime, # Time window start
531
'endtime': UTCDateTime, # Time window end
532
'equal_scale': bool, # Equal amplitude scaling
533
'number_of_ticks': int, # Time axis tick count
534
'tick_format': str # Time tick format string
535
}
536
537
# Spectrogram parameters
538
SpectrogramConfig = {
539
'wlen': float, # Window length in seconds
540
'per_lap': float, # Overlap fraction (0-1)
541
'mult': float, # Frequency multiplier
542
'cmap': str, # Matplotlib colormap
543
'vmin': float, # Color scale minimum
544
'vmax': float, # Color scale maximum
545
'log': bool, # Logarithmic frequency scale
546
'dbscale': bool # Decibel amplitude scale
547
}
548
549
# Beachball styling
550
BeachballStyle = {
551
'size': int, # Beachball size in points
552
'linewidth': float, # Nodal plane line width
553
'facecolor': str, # Compressional quadrant color
554
'bgcolor': str, # Background color
555
'edgecolor': str, # Outline color
556
'alpha': float, # Transparency (0-1)
557
'nofill': bool # Outline only
558
}
559
```