or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-data-structures.mddata-center-clients.mdfile-format-io.mdgeodetic-calculations.mdindex.mdsignal-processing.mdtravel-time-calculations.mdvisualization-imaging.md

visualization-imaging.mddocs/

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

```