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

travel-time-calculations.mddocs/

0

# Travel Time Calculations

1

2

Seismic ray theory calculations using multiple 1D Earth models for travel times, ray paths, and pierce points. Essential for earthquake location, phase identification, and tomographic studies using the TauP toolkit integrated into ObsPy.

3

4

## Capabilities

5

6

### TauPy Model Interface

7

8

Primary interface for travel time calculations using various Earth models with comprehensive phase support.

9

10

```python { .api }

11

# Import from obspy.taup

12

class TauPyModel:

13

def __init__(self, model: str = "iasp91", verbose: bool = False, **kwargs):

14

"""

15

Initialize TauP model for travel time calculations.

16

17

Args:

18

model: Earth model name

19

verbose: Enable verbose output

20

**kwargs: Additional model options

21

22

Available Models:

23

'1066a', '1066b', 'ak135', 'ak135f', 'ak135f_no_mud', 'herrin',

24

'iasp91', 'jb', 'prem', 'pwdk', 'sp6'

25

"""

26

27

def get_travel_times(self, source_depth_in_km: float, distance_in_degree: float = None,

28

distance_in_km: float = None, phase_list: list[str] = ['p', 's'],

29

receiver_depth_in_km: float = 0.0) -> list:

30

"""

31

Calculate seismic phase travel times.

32

33

Args:

34

source_depth_in_km: Earthquake depth in kilometers

35

distance_in_degree: Epicentral distance in degrees (or use distance_in_km)

36

distance_in_km: Epicentral distance in kilometers (or use distance_in_degree)

37

phase_list: List of seismic phases to calculate

38

receiver_depth_in_km: Receiver depth in kilometers (default: surface)

39

40

Returns:

41

List of Arrival objects with travel time information

42

43

Common Phases:

44

P, S - Direct body waves

45

PP, SS - Surface reflected waves

46

PcP, ScS - Core reflected waves

47

PKP, SKS - Core transmitted waves

48

Pdiff, Sdiff - Diffracted waves

49

PmP, SmS - Moho reflected waves

50

pP, sS - Depth phases

51

"""

52

53

def get_ray_paths(self, source_depth_in_km: float, distance_in_degree: float = None,

54

distance_in_km: float = None, phase_list: list[str] = ['p', 's'],

55

receiver_depth_in_km: float = 0.0) -> list:

56

"""

57

Calculate seismic ray paths through Earth model.

58

59

Args:

60

source_depth_in_km: Source depth in km

61

distance_in_degree: Distance in degrees (or use distance_in_km)

62

distance_in_km: Distance in km (or use distance_in_degree)

63

phase_list: Seismic phases to calculate

64

receiver_depth_in_km: Receiver depth in km

65

66

Returns:

67

List of RayPath objects with ray geometry information

68

"""

69

70

def get_pierce_points(self, source_depth_in_km: float, distance_in_degree: float = None,

71

distance_in_km: float = None, phase_list: list[str] = ['p', 's'],

72

receiver_depth_in_km: float = 0.0) -> list:

73

"""

74

Calculate ray pierce points at discontinuities.

75

76

Args:

77

source_depth_in_km: Source depth in km

78

distance_in_degree: Distance in degrees (or use distance_in_km)

79

distance_in_km: Distance in km (or use distance_in_degree)

80

phase_list: Seismic phases to calculate

81

receiver_depth_in_km: Receiver depth in km

82

83

Returns:

84

List of PiercePoint objects with pierce point information

85

"""

86

87

def get_travel_times_geo(self, source_latitude: float, source_longitude: float,

88

source_depth_in_km: float, receiver_latitude: float,

89

receiver_longitude: float, phase_list: list[str] = ['p', 's'],

90

receiver_depth_in_km: float = 0.0) -> list:

91

"""

92

Calculate travel times using geographic coordinates.

93

94

Args:

95

source_latitude: Event latitude in degrees

96

source_longitude: Event longitude in degrees

97

source_depth_in_km: Event depth in km

98

receiver_latitude: Station latitude in degrees

99

receiver_longitude: Station longitude in degrees

100

phase_list: Seismic phases to calculate

101

receiver_depth_in_km: Station elevation (negative for depth) in km

102

103

Returns:

104

List of Arrival objects with travel times and ray parameters

105

"""

106

107

def get_ray_paths_geo(self, source_latitude: float, source_longitude: float,

108

source_depth_in_km: float, receiver_latitude: float,

109

receiver_longitude: float, phase_list: list[str] = ['p', 's'],

110

receiver_depth_in_km: float = 0.0) -> list:

111

"""

112

Calculate ray paths using geographic coordinates.

113

114

Args:

115

source_latitude: Event latitude

116

source_longitude: Event longitude

117

source_depth_in_km: Event depth in km

118

receiver_latitude: Station latitude

119

receiver_longitude: Station longitude

120

phase_list: Seismic phases

121

receiver_depth_in_km: Station depth in km

122

123

Returns:

124

List of RayPath objects with geographic ray paths

125

"""

126

```

127

128

### Travel Time Plotting Functions

129

130

Visualization functions for travel time curves and ray path diagrams.

131

132

```python { .api }

133

def plot_travel_times(source_depth: float, ax=None, fig=None, phase_list: list[str] = None,

134

npoints: int = 100, model: str = 'iasp91', legend: bool = True,

135

**kwargs):

136

"""

137

Plot travel time curves for seismic phases.

138

139

Args:

140

source_depth: Source depth in km

141

ax: Matplotlib axes object (created if None)

142

fig: Matplotlib figure object (created if None)

143

phase_list: Phases to plot (common phases if None)

144

npoints: Number of distance points

145

model: Earth model to use

146

legend: Show phase legend

147

**kwargs: Additional plotting options

148

149

Returns:

150

Matplotlib figure and axes objects

151

"""

152

153

def plot_ray_paths(source_depth: float, distance: float, ax=None, fig=None,

154

phase_list: list[str] = None, model: str = 'iasp91',

155

legend: bool = True, **kwargs):

156

"""

157

Plot ray paths through Earth model.

158

159

Args:

160

source_depth: Source depth in km

161

distance: Epicentral distance in degrees

162

ax: Matplotlib axes object

163

fig: Matplotlib figure object

164

phase_list: Phases to plot

165

model: Earth model

166

legend: Show legend

167

**kwargs: Plotting options

168

169

Returns:

170

Figure and axes objects

171

"""

172

```

173

174

### Result Classes

175

176

Data structures containing travel time calculation results.

177

178

```python { .api }

179

class Arrival:

180

"""Travel time calculation result for single phase."""

181

182

@property

183

def name(self) -> str:

184

"""Phase name (e.g., 'P', 'S', 'PKP')."""

185

186

@property

187

def time(self) -> float:

188

"""Travel time in seconds."""

189

190

@property

191

def distance(self) -> float:

192

"""Epicentral distance in degrees."""

193

194

@property

195

def ray_param(self) -> float:

196

"""Ray parameter in s/degree."""

197

198

@property

199

def ray_param_sec_degree(self) -> float:

200

"""Ray parameter in s/degree."""

201

202

@property

203

def takeoff_angle(self) -> float:

204

"""Takeoff angle from source in degrees."""

205

206

@property

207

def incident_angle(self) -> float:

208

"""Incident angle at receiver in degrees."""

209

210

@property

211

def purist_distance(self) -> float:

212

"""Distance for which phase is pure."""

213

214

@property

215

def purist_name(self) -> str:

216

"""Purist phase name."""

217

218

class RayPath:

219

"""Ray path through Earth model."""

220

221

@property

222

def name(self) -> str:

223

"""Phase name."""

224

225

@property

226

def time(self) -> float:

227

"""Travel time in seconds."""

228

229

@property

230

def distance(self) -> float:

231

"""Distance in degrees."""

232

233

@property

234

def ray_param(self) -> float:

235

"""Ray parameter."""

236

237

@property

238

def path(self) -> dict:

239

"""Ray path coordinates.

240

241

Returns:

242

Dictionary with 'dist' and 'depth' arrays for plotting

243

"""

244

245

class PiercePoint:

246

"""Ray pierce point at discontinuity."""

247

248

@property

249

def name(self) -> str:

250

"""Phase name."""

251

252

@property

253

def time(self) -> float:

254

"""Time to pierce point."""

255

256

@property

257

def distance(self) -> float:

258

"""Distance to pierce point."""

259

260

@property

261

def depth(self) -> float:

262

"""Depth of pierce point."""

263

```

264

265

## Usage Examples

266

267

### Basic Travel Time Calculations

268

269

```python

270

from obspy.taup import TauPyModel

271

from obspy import UTCDateTime

272

273

# Initialize model

274

model = TauPyModel(model="iasp91")

275

276

# Calculate P and S arrival times

277

arrivals = model.get_travel_times(source_depth_in_km=10.0,

278

distance_in_degree=45.0,

279

phase_list=['P', 'S'])

280

281

print("Phase Arrivals:")

282

for arrival in arrivals:

283

print(f"{arrival.name}: {arrival.time:.2f} s")

284

print(f" Takeoff angle: {arrival.takeoff_angle:.1f}°")

285

print(f" Ray parameter: {arrival.ray_param:.3f} s/°")

286

287

# Calculate more phases including core phases

288

arrivals = model.get_travel_times(source_depth_in_km=150.0,

289

distance_in_degree=85.0,

290

phase_list=['P', 'S', 'PP', 'SS', 'PKP', 'SKS'])

291

292

print(f"\nTotal arrivals found: {len(arrivals)}")

293

```

294

295

### Earthquake Location Application

296

297

```python

298

from obspy.taup import TauPyModel

299

from obspy.geodetics import gps2dist_azimuth

300

from obspy import UTCDateTime

301

302

# Event and station information

303

event_lat, event_lon = 35.0, 140.0 # Japan

304

event_depth = 10.0 # km

305

origin_time = UTCDateTime("2023-01-15T10:30:00")

306

307

stations = [

308

("Tokyo", 35.7, 139.7),

309

("Osaka", 34.7, 135.5),

310

("Sendai", 38.3, 140.9)

311

]

312

313

model = TauPyModel(model="ak135")

314

315

print("Predicted P-wave arrivals:")

316

for station_name, sta_lat, sta_lon in stations:

317

# Calculate distance and azimuth

318

dist_m, az, baz = gps2dist_azimuth(event_lat, event_lon, sta_lat, sta_lon)

319

dist_deg = dist_m / 111319.9 # Convert to degrees

320

321

# Get P-wave travel time

322

arrivals = model.get_travel_times(source_depth_in_km=event_depth,

323

distance_in_degree=dist_deg,

324

phase_list=['P'])

325

326

if arrivals:

327

p_arrival = arrivals[0]

328

predicted_time = origin_time + p_arrival.time

329

print(f"{station_name}: {predicted_time} ({p_arrival.time:.2f} s)")

330

```

331

332

### Ray Path Analysis

333

334

```python

335

from obspy.taup import TauPyModel, plot_ray_paths

336

import matplotlib.pyplot as plt

337

338

model = TauPyModel(model="prem")

339

340

# Get ray paths for different phases

341

source_depth = 600.0 # Deep earthquake

342

distance = 75.0 # Teleseismic distance

343

344

ray_paths = model.get_ray_paths(source_depth_in_km=source_depth,

345

distance_in_degree=distance,

346

phase_list=['P', 'PP', 'PKP', 'PKIKP'])

347

348

print("Ray path information:")

349

for path in ray_paths:

350

print(f"{path.name}: {path.time:.2f} s, {path.ray_param:.3f} s/°")

351

352

# Get path coordinates

353

coords = path.path

354

max_depth = max(coords['depth'])

355

print(f" Maximum depth: {max_depth:.1f} km")

356

357

# Plot ray paths

358

plot_ray_paths(source_depth, distance,

359

phase_list=['P', 'PP', 'PKP', 'PKIKP'],

360

model='prem')

361

plt.title(f"Ray Paths: {source_depth} km depth, {distance}° distance")

362

plt.show()

363

```

364

365

### Travel Time Curves

366

367

```python

368

from obspy.taup import plot_travel_times

369

import matplotlib.pyplot as plt

370

371

# Plot travel time curves for shallow earthquake

372

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

373

374

# Shallow earthquake (crustal phases important)

375

plot_travel_times(source_depth=10.0, ax=ax1,

376

phase_list=['P', 'S', 'Pg', 'Sg', 'Pn', 'Sn'],

377

model='iasp91')

378

ax1.set_title("Shallow Earthquake (10 km depth)")

379

ax1.set_xlim(0, 30) # Regional distances

380

381

# Deep earthquake (core phases visible)

382

plot_travel_times(source_depth=600.0, ax=ax2,

383

phase_list=['P', 'S', 'PP', 'SS', 'PKP', 'SKS'],

384

model='iasp91')

385

ax2.set_title("Deep Earthquake (600 km depth)")

386

ax2.set_xlim(0, 180) # Global distances

387

388

plt.tight_layout()

389

plt.show()

390

```

391

392

### Pierce Point Analysis

393

394

```python

395

from obspy.taup import TauPyModel

396

397

model = TauPyModel(model="ak135")

398

399

# Get pierce points for P wave

400

pierce_points = model.get_pierce_points(source_depth_in_km=50.0,

401

distance_in_degree=60.0,

402

phase_list=['P'])

403

404

if pierce_points:

405

p_pierce = pierce_points[0]

406

print("P-wave pierce points:")

407

408

# Pierce points are stored in path attribute

409

for i, (dist, depth) in enumerate(zip(p_pierce.pierce['dist'],

410

p_pierce.pierce['depth'])):

411

print(f"Point {i}: {dist:.2f}° distance, {depth:.1f} km depth")

412

413

# Analyze core phase pierce points

414

pierce_points = model.get_pierce_points(source_depth_in_km=100.0,

415

distance_in_degree=120.0,

416

phase_list=['PKP'])

417

418

if pierce_points:

419

pkp_pierce = pierce_points[0]

420

print(f"\nPKP phase ({pkp_pierce.name}):")

421

print(f"Time: {pkp_pierce.time:.2f} s")

422

print(f"Ray parameter: {pkp_pierce.ray_param:.3f} s/°")

423

```

424

425

### Multi-Model Comparison

426

427

```python

428

from obspy.taup import TauPyModel

429

import matplotlib.pyplot as plt

430

import numpy as np

431

432

# Compare travel times between models

433

models = ['iasp91', 'ak135', 'prem']

434

source_depth = 100.0

435

distances = np.linspace(10, 90, 9)

436

437

fig, ax = plt.subplots(figsize=(10, 6))

438

439

for model_name in models:

440

model = TauPyModel(model=model_name)

441

p_times = []

442

443

for dist in distances:

444

arrivals = model.get_travel_times(source_depth_in_km=source_depth,

445

distance_in_degree=dist,

446

phase_list=['P'])

447

if arrivals:

448

p_times.append(arrivals[0].time)

449

else:

450

p_times.append(np.nan)

451

452

ax.plot(distances, p_times, 'o-', label=f'{model_name} P-wave')

453

454

ax.set_xlabel('Distance (degrees)')

455

ax.set_ylabel('Travel Time (seconds)')

456

ax.set_title(f'P-wave Travel Times - {source_depth} km depth')

457

ax.legend()

458

ax.grid(True, alpha=0.3)

459

plt.show()

460

461

# Print model differences

462

print("P-wave time differences at 45° distance:")

463

ref_model = TauPyModel(model='iasp91')

464

ref_time = ref_model.get_travel_times(100.0, 45.0, ['P'])[0].time

465

466

for model_name in ['ak135', 'prem']:

467

test_model = TauPyModel(model=model_name)

468

test_time = test_model.get_travel_times(100.0, 45.0, ['P'])[0].time

469

diff = test_time - ref_time

470

print(f"{model_name} vs iasp91: {diff:.2f} s")

471

```

472

473

## Types

474

475

```python { .api }

476

# Earth model information

477

ModelInfo = {

478

'name': str, # Model name

479

'description': str, # Model description

480

'min_radius': float, # Minimum radius (km)

481

'max_radius': float, # Maximum radius (km)

482

'discontinuities': list[float], # Major discontinuity depths

483

'phases': list[str] # Supported seismic phases

484

}

485

486

# Travel time result structure

487

TravelTimeResult = {

488

'phase': str, # Phase name

489

'time': float, # Travel time (s)

490

'distance': float, # Distance (degrees)

491

'ray_param': float, # Ray parameter (s/degree)

492

'takeoff_angle': float, # Takeoff angle (degrees)

493

'incident_angle': float, # Incident angle (degrees)

494

'purist_distance': float, # Purist distance (degrees)

495

'purist_name': str # Purist phase name

496

}

497

```