Coverage for /usr/local/lib/python3.13/dist-packages/pyrocko/plot/cake_plot.py: 68%

413 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2025-12-04 10:41 +0000

1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6import math 

7import numpy as num 

8from pyrocko import cake 

9from pyrocko.util import mpl_show 

10from . import mpl_init, mpl_color as str_to_mpl_color, InvalidColorDef, \ 

11 mpl_margins 

12 

13str_to_mpl_color 

14InvalidColorDef 

15 

16d2r = cake.d2r 

17r2d = cake.r2d 

18 

19_have_registered_gcs = False 

20 

21 

22def globe_cross_section(): 

23 # modified from http://stackoverflow.com/questions/2417794/ 

24 # how-to-make-the-angles-in-a-matplotlib-polar-plot-go-clockwise-with-0-at-the-top 

25 

26 global _have_registered_gcs 

27 

28 if _have_registered_gcs: 

29 return 

30 

31 from matplotlib.projections import PolarAxes, register_projection 

32 from matplotlib.transforms import Bbox, IdentityTransform 

33 

34 class GlobeCrossSectionAxes(PolarAxes): 

35 ''' 

36 A variant of PolarAxes where theta starts pointing north and goes 

37 clockwise and the radial axis is reversed. 

38 ''' 

39 name = 'globe_cross_section' 

40 

41 class GlobeCrossSectionTransform(PolarAxes.PolarTransform): 

42 

43 def transform(self, tr): 

44 xy = num.zeros(tr.shape) 

45 t = tr[:, 0]*d2r 

46 r = cake.earthradius - tr[:, 1] 

47 xy[:, 0] = r * num.sin(t) 

48 xy[:, 1] = r * num.cos(t) 

49 return xy 

50 

51 transform_non_affine = transform 

52 

53 def inverted(self): 

54 return GlobeCrossSectionAxes.\ 

55 InvertedGlobeCrossSectionTransform() 

56 

57 class InvertedGlobeCrossSectionTransform( 

58 PolarAxes.InvertedPolarTransform): 

59 

60 def transform(self, xy): 

61 x = xy[:, 0] 

62 y = xy[:, 1] 

63 tr = num.zeros(xy.shape) 

64 tr[:, 1] = num.sqrt(x*x + y*y) 

65 tr[:, 0] = num.arctan2(y, x)*r2d 

66 return tr 

67 

68 def inverted(self): 

69 return GlobeCrossSectionAxes.GlobeCrossSectionTransform() 

70 

71 def __init__(self, *args, **kwargs): 

72 PolarAxes.__init__( 

73 self, 

74 *args, 

75 theta_offset=90.*d2r, 

76 theta_direction=-1, 

77 **kwargs) 

78 

79 def _set_lim_and_transforms(self): 

80 PolarAxes._set_lim_and_transforms(self) 

81 

82 self.transProjection = self.GlobeCrossSectionTransform() 

83 self.transData = ( 

84 self.transScale + 

85 self.transProjection + 

86 (self.transProjectionAffine + self.transAxes)) 

87 self._xaxis_transform = ( 

88 self.transProjection + 

89 self.PolarAffine(IdentityTransform(), Bbox.unit()) + 

90 self.transAxes) 

91 

92 register_projection(GlobeCrossSectionAxes) 

93 

94 _have_registered_gcs = True 

95 

96 

97tango_colors = { 

98 'butter1': (252, 233, 79), 

99 'butter2': (237, 212, 0), 

100 'butter3': (196, 160, 0), 

101 'chameleon1': (138, 226, 52), 

102 'chameleon2': (115, 210, 22), 

103 'chameleon3': (78, 154, 6), 

104 'orange1': (252, 175, 62), 

105 'orange2': (245, 121, 0), 

106 'orange3': (206, 92, 0), 

107 'skyblue1': (114, 159, 207), 

108 'skyblue2': (52, 101, 164), 

109 'skyblue3': (32, 74, 135), 

110 'plum1': (173, 127, 168), 

111 'plum2': (117, 80, 123), 

112 'plum3': (92, 53, 102), 

113 'chocolate1': (233, 185, 110), 

114 'chocolate2': (193, 125, 17), 

115 'chocolate3': (143, 89, 2), 

116 'scarletred1': (239, 41, 41), 

117 'scarletred2': (204, 0, 0), 

118 'scarletred3': (164, 0, 0), 

119 'aluminium1': (238, 238, 236), 

120 'aluminium2': (211, 215, 207), 

121 'aluminium3': (186, 189, 182), 

122 'aluminium4': (136, 138, 133), 

123 'aluminium5': (85, 87, 83), 

124 'aluminium6': (46, 52, 54) 

125} 

126 

127 

128def path2colorint(path): 

129 ''' 

130 Calculate an integer representation deduced from path's given name. 

131 ''' 

132 s = sum([ord(char) for char in path.phase.given_name()]) 

133 return s 

134 

135 

136def light(color, factor=0.2): 

137 return tuple(1-(1-c)*factor for c in color) 

138 

139 

140def dark(color, factor=0.5): 

141 return tuple(c*factor for c in color) 

142 

143 

144def to01(c): 

145 return tuple(x/255. for x in c) 

146 

147 

148colors = [to01(tango_colors[x+i]) for i in '321' for x in 

149 'scarletred chameleon skyblue chocolate orange plum'.split()] 

150shades = [light(to01(tango_colors['chocolate1']), i*0.1) for i in range(1, 9)] 

151shades2 = [light(to01(tango_colors['orange1']), i*0.1) for i in range(1, 9)] 

152 

153shades_water = [ 

154 light(to01(tango_colors['skyblue1']), i*0.1) for i in range(1, 9)] 

155 

156 

157def plot_xt( 

158 paths, zstart, zstop, 

159 axes=None, 

160 vred=None, 

161 distances=None, 

162 coloring='by_phase_definition', 

163 avoid_same_colors=True, 

164 phase_colors={}): 

165 

166 if distances is not None: 

167 xmin, xmax = distances.min(), distances.max() 

168 

169 axes = getaxes(axes) 

170 all_x = [] 

171 all_t = [] 

172 path_to_color = make_path_to_color( 

173 paths, coloring, avoid_same_colors, phase_colors=phase_colors) 

174 

175 for ipath, path in enumerate(paths): 

176 if distances is not None: 

177 if path.xmax() < xmin or path.xmin() > xmax: 

178 continue 

179 

180 color = path_to_color[path] 

181 p, x, t = path.draft_pxt(path.endgaps(zstart, zstop)) 

182 if p.size == 0: 

183 continue 

184 

185 all_x.append(x) 

186 all_t.append(t) 

187 if vred is not None: 

188 axes.plot(x, t-x/vred, linewidth=2, color=color) 

189 axes.plot([x[0]], [t[0]-x[0]/vred], 'o', color=color) 

190 axes.plot([x[-1]], [t[-1]-x[-1]/vred], 'o', color=color) 

191 axes.text( 

192 x[len(x)//2], 

193 t[len(x)//2]-x[len(x)//2]/vred, 

194 path.used_phase().used_repr(), 

195 color=color, 

196 va='center', 

197 ha='center', 

198 clip_on=True, 

199 bbox=dict( 

200 ec=color, 

201 fc=light(color), 

202 pad=8, 

203 lw=1), 

204 fontsize=10) 

205 else: 

206 axes.plot(x, t, linewidth=2, color=color) 

207 axes.plot([x[0]], [t[0]], 'o', color=color) 

208 axes.plot([x[-1]], [t[-1]], 'o', color=color) 

209 axes.text( 

210 x[len(x)//2], 

211 t[len(x)//2], 

212 path.used_phase().used_repr(), 

213 color=color, 

214 va='center', 

215 ha='center', 

216 clip_on=True, 

217 bbox=dict( 

218 ec=color, 

219 fc=light(color), 

220 pad=8, 

221 lw=1), 

222 fontsize=10) 

223 

224 all_x = num.concatenate(all_x) 

225 all_t = num.concatenate(all_t) 

226 if vred is not None: 

227 all_t -= all_x/vred 

228 xxx = num.sort(all_x) 

229 ttt = num.sort(all_t) 

230 return xxx.min(), xxx[99*len(xxx)//100], ttt.min(), ttt[99*len(ttt)//100] 

231 

232 

233def labels_xt(axes=None, vred=None, as_degrees=False): 

234 axes = getaxes(axes) 

235 if as_degrees: 

236 axes.set_xlabel('Distance [deg]') 

237 else: 

238 axes.set_xlabel('Distance [km]') 

239 xscaled(d2r*cake.earthradius/cake.km, axes) 

240 

241 if vred is None: 

242 axes.set_ylabel('Time [s]') 

243 else: 

244 if as_degrees: 

245 axes.set_ylabel('Time - Distance / %g deg/s [ s ]' % ( 

246 vred)) 

247 else: 

248 axes.set_ylabel('Time - Distance / %g km/s [ s ]' % ( 

249 d2r*vred*cake.earthradius/cake.km)) 

250 

251 

252def troffset(dx, dy, axes=None): 

253 axes = getaxes(axes) 

254 from matplotlib import transforms 

255 return axes.transData + transforms.ScaledTranslation( 

256 dx/72., dy/72., axes.gcf().dpi_scale_trans) 

257 

258 

259def plot_xp( 

260 paths, 

261 zstart, 

262 zstop, 

263 axes=None, 

264 coloring='by_phase_definition', 

265 avoid_same_colors=True, 

266 phase_colors={}): 

267 

268 path_to_color = make_path_to_color( 

269 paths, coloring, avoid_same_colors, phase_colors=phase_colors) 

270 

271 axes = getaxes(axes) 

272 all_x = [] 

273 for ipath, path in enumerate(paths): 

274 color = path_to_color[path] 

275 p, x, t = path.draft_pxt(path.endgaps(zstart, zstop)) 

276 # converting ray parameters from s/rad to s/deg 

277 p /= r2d 

278 axes.plot(x, p, linewidth=2, color=color) 

279 axes.plot(x[:1], p[:1], 'o', color=color) 

280 axes.plot(x[-1:], p[-1:], 'o', color=color) 

281 axes.text( 

282 x[len(x)//2], 

283 p[len(x)//2], 

284 path.used_phase().used_repr(), 

285 color=color, 

286 va='center', 

287 ha='center', 

288 clip_on=True, 

289 bbox=dict( 

290 ec=color, 

291 fc=light(color), 

292 pad=8, 

293 lw=1)) 

294 

295 all_x.append(x) 

296 

297 xxx = num.sort(num.concatenate(all_x)) 

298 return xxx.min(), xxx[99*len(xxx)//100] 

299 

300 

301def labels_xp(axes=None, as_degrees=False): 

302 axes = getaxes(axes) 

303 if as_degrees: 

304 axes.set_xlabel('Distance [deg]') 

305 else: 

306 axes.set_xlabel('Distance [km]') 

307 xscaled(d2r*cake.earthradius*0.001, axes) 

308 axes.set_ylabel('Ray Parameter [s/deg]') 

309 

310 

311def labels_model(axes=None): 

312 axes = getaxes(axes) 

313 axes.set_xlabel('S-wave and P-wave velocity [km/s]') 

314 xscaled(0.001, axes) 

315 axes.set_ylabel('Depth [km]') 

316 yscaled(0.001, axes) 

317 

318 

319def make_path_to_color( 

320 paths, 

321 coloring='by_phase_definition', 

322 avoid_same_colors=True, 

323 phase_colors={}): 

324 

325 assert coloring in ['by_phase_definition', 'by_path'] 

326 

327 path_to_color = {} 

328 definition_to_color = phase_colors.copy() 

329 available_colors = set() 

330 

331 for ipath, path in enumerate(paths): 

332 if coloring == 'by_phase_definition': 

333 given_name = path.phase.given_name() 

334 int_rep = path2colorint(path) 

335 color_id = int_rep % len(colors) 

336 

337 if given_name not in definition_to_color: 

338 if avoid_same_colors: 

339 if len(available_colors) == 0: 

340 available_colors = set(range(0, len(colors)-1)) 

341 if color_id in available_colors: 

342 available_colors.remove(color_id) 

343 else: 

344 color_id = available_colors.pop() 

345 

346 assert color_id not in available_colors 

347 

348 definition_to_color[given_name] = colors[color_id] 

349 

350 path_to_color[path] = definition_to_color[given_name] 

351 else: 

352 path_to_color[path] = colors[ipath % len(colors)] 

353 

354 return path_to_color 

355 

356 

357def plot_rays(paths, rays, zstart, zstop, 

358 axes=None, 

359 coloring='by_phase_definition', 

360 legend=True, 

361 avoid_same_colors=True, 

362 aspect=None, 

363 phase_colors={}): 

364 

365 axes = getaxes(axes) 

366 if aspect is not None: 

367 axes.set_aspect(aspect/(d2r*cake.earthradius)) 

368 

369 path_to_color = make_path_to_color( 

370 paths, coloring, avoid_same_colors, phase_colors=phase_colors) 

371 

372 if rays is None: 

373 rays = paths 

374 

375 labels = set() 

376 

377 for iray, ray in enumerate(rays): 

378 if isinstance(ray, cake.RayPath): 

379 path = ray 

380 pmin, pmax, xmin, xmax, tmin, tmax = path.ranges( 

381 path.endgaps(zstart, zstop)) 

382 

383 if not path._is_headwave: 

384 p = num.linspace(pmin, pmax, 6) 

385 x = None 

386 

387 else: 

388 x = num.linspace(xmin, xmin*10, 6) 

389 p = num.atleast_1d(pmin) 

390 

391 fanz, fanx, _ = path.zxt_path_subdivided( 

392 p, path.endgaps(zstart, zstop), x_for_headwave=x) 

393 

394 else: 

395 fanz, fanx, _ = ray.zxt_path_subdivided() 

396 path = ray.path 

397 

398 color = path_to_color[path] 

399 

400 if coloring == 'by_phase_definition': 

401 phase_label = path.phase.given_name() 

402 

403 else: 

404 phase_label = path 

405 

406 for zs, xs in zip(fanz, fanx): 

407 if phase_label in labels: 

408 phase_label = '' 

409 

410 axes.plot(xs, zs, color=color, label=phase_label) 

411 if legend: 

412 labels.add(phase_label) 

413 

414 if legend: 

415 axes.legend(loc=4, prop={'size': 11}) 

416 

417 

418def sketch_model(mod, axes=None, shade=True): 

419 from matplotlib import transforms 

420 axes = getaxes(axes) 

421 trans = transforms.BlendedGenericTransform(axes.transAxes, axes.transData) 

422 

423 for dis in mod.discontinuities(): 

424 color = shades[-1] 

425 axes.axhline(dis.z, color=dark(color), lw=1.5) 

426 if dis.name is not None: 

427 axes.text( 

428 0.90, dis.z, dis.name, 

429 transform=trans, 

430 va='center', 

431 ha='right', 

432 color=dark(color), 

433 bbox=dict(ec=dark(color), fc=light(color, 0.3), pad=8, lw=1)) 

434 

435 for ilay, lay in enumerate(mod.layers()): 

436 if lay.mtop.vs == 0.0 and lay.mbot.vs == 0.0: 

437 tab = shades_water 

438 else: 

439 if isinstance(lay, cake.GradientLayer): 

440 tab = shades 

441 else: 

442 tab = shades2 

443 

444 color = tab[ilay % len(tab)] 

445 if shade: 

446 axes.axhspan( 

447 lay.ztop, lay.zbot, fc=color, ec=dark(color), label='abc') 

448 

449 if lay.name is not None: 

450 axes.text( 

451 0.95, (lay.ztop + lay.zbot)*0.5, 

452 lay.name, 

453 transform=trans, 

454 va='center', 

455 ha='right', 

456 color=dark(color), 

457 bbox=dict(ec=dark(color), fc=light(color, 0.3), pad=8, lw=1)) 

458 

459 

460def plot_source(zstart, axes=None): 

461 axes = getaxes(axes) 

462 axes.plot([0], [zstart], 'o', color='black', clip_on=False) 

463 

464 

465def offset(axes, x, y): 

466 from matplotlib import transforms 

467 return axes.transData + transforms.ScaledTranslation( 

468 x/72., y/72., axes.get_figure().dpi_scale_trans) 

469 

470 

471def plot_receivers_gcs(zstop, distances, axes=None, **kwargs): 

472 if 'color' not in kwargs and 'c' not in kwargs: 

473 kwargs['color'] = 'black' 

474 if 'markersize' not in kwargs and 'ms' not in kwargs: 

475 kwargs['markersize'] = 6 

476 axes = getaxes(axes) 

477 for distance in distances: 

478 axes.plot( 

479 distance, zstop, marker=(3, 0, -distance), 

480 clip_on=False, transform=offset( 

481 axes, num.sin(distance*d2r)*3, num.cos(distance*d2r)*3), 

482 **kwargs) 

483 

484 

485def plot_receivers(zstop, distances, axes=None, **kwargs): 

486 if 'color' not in kwargs and 'c' not in kwargs: 

487 kwargs['color'] = 'black' 

488 if 'markersize' not in kwargs and 'ms' not in kwargs: 

489 kwargs['markersize'] = 6 

490 axes = getaxes(axes) 

491 for distance in distances: 

492 axes.plot( 

493 distance, zstop, marker=(3, 0, 0), 

494 clip_on=False, transform=offset( 

495 axes, 0, 3), 

496 **kwargs) 

497 

498 

499def getaxes(axes=None): 

500 from matplotlib import pyplot as plt 

501 if axes is None: 

502 return plt.gca() 

503 else: 

504 return axes 

505 

506 

507def mk_sc_classes(): 

508 from matplotlib.ticker import FormatStrFormatter, AutoLocator 

509 

510 class Scaled(FormatStrFormatter): 

511 def __init__(self, factor): 

512 FormatStrFormatter.__init__(self, '%g') 

513 self._factor = factor 

514 

515 def __call__(self, v, i=0): 

516 return FormatStrFormatter.__call__(self, v*self._factor, i) 

517 

518 class ScaledLocator(AutoLocator): 

519 def __init__(self, factor): 

520 AutoLocator.__init__(self) 

521 self._factor = factor 

522 

523 def _raw_ticks(self, vmin, vmax): 

524 return [x/self._factor for x in AutoLocator._raw_ticks( 

525 self, vmin*self._factor, vmax*self._factor)] 

526 

527 def bin_boundaries(self, vmin, vmax): 

528 return [x/self._factor for x in AutoLocator.bin_boundaries( 

529 self, vmin*self._factor, vmax*self._factor)] 

530 

531 return Scaled, ScaledLocator 

532 

533 

534def xscaled(factor, axes): 

535 Scaled, ScaledLocator = mk_sc_classes() 

536 xaxis = axes.get_xaxis() 

537 xaxis.set_major_formatter(Scaled(factor)) 

538 xaxis.set_major_locator(ScaledLocator(factor)) 

539 

540 

541def yscaled(factor, axes): 

542 Scaled, ScaledLocator = mk_sc_classes() 

543 yaxis = axes.get_yaxis() 

544 yaxis.set_major_formatter(Scaled(factor)) 

545 yaxis.set_major_locator(ScaledLocator(factor)) 

546 

547 

548def labels_rays(axes=None, as_degrees=False): 

549 axes = getaxes(axes) 

550 if as_degrees: 

551 axes.set_xlabel('Distance [deg]') 

552 else: 

553 axes.set_xlabel('Distance [km]') 

554 xscaled(d2r*cake.earthradius/cake.km, axes) 

555 axes.set_ylabel('Depth [km]') 

556 yscaled(1./cake.km, axes) 

557 

558 

559def plot_surface_efficiency(mat): 

560 from matplotlib import pyplot as plt 

561 data = [] 

562 for angle in num.linspace(0., 90., 910.): 

563 pp = math.sin(angle*d2r)/mat.vp 

564 ps = math.sin(angle*d2r)/mat.vs 

565 

566 escp = cake.psv_surface(mat, pp, energy=True) 

567 escs = cake.psv_surface(mat, ps, energy=True) 

568 data.append(( 

569 angle, 

570 escp[cake.psv_surface_ind(cake.P, cake.P)], 

571 escp[cake.psv_surface_ind(cake.P, cake.S)], 

572 escs[cake.psv_surface_ind(cake.S, cake.S)], 

573 escs[cake.psv_surface_ind(cake.S, cake.P)])) 

574 

575 a, pp, ps, ss, sp = num.array(data).T 

576 

577 plt.plot(a, pp, label='PP') 

578 plt.plot(a, ps, label='PS') 

579 plt.plot(a, ss, label='SS') 

580 plt.plot(a, sp, label='SP') 

581 plt.xlabel('Incident Angle') 

582 plt.ylabel('Energy Normalized Coefficient', position=(-2., 0.5)) 

583 plt.legend() 

584 mpl_show(plt) 

585 

586 

587def setup_figure(fig): 

588 if fig is None: 

589 from matplotlib import pyplot as plt 

590 mpl_init() 

591 fig = plt.figure() 

592 else: 

593 plt = None 

594 

595 return fig, plt 

596 

597 

598def setup_axes(fig): 

599 fontsize = 9 

600 labelpos = mpl_margins(fig, w=7., h=5., units=fontsize) 

601 axes = fig.add_subplot(1, 1, 1) 

602 labelpos(axes, 2., 1.5) 

603 return axes 

604 

605 

606def my_xp_plot( 

607 paths, zstart, zstop, 

608 distances=None, 

609 as_degrees=False, 

610 phase_colors={}, 

611 fig=None): 

612 

613 fig, plt = setup_figure(fig) 

614 axes = setup_axes(fig) 

615 

616 xmin, xmax = plot_xp( 

617 paths, zstart, zstop, axes=axes, phase_colors=phase_colors) 

618 

619 if distances is not None: 

620 xmin, xmax = distances.min(), distances.max() 

621 

622 axes.set_xlim(xmin, xmax) 

623 labels_xp(as_degrees=as_degrees, axes=axes) 

624 

625 if plt: 

626 mpl_show(plt) 

627 

628 

629def my_xt_plot( 

630 paths, zstart, zstop, 

631 distances=None, 

632 as_degrees=False, 

633 vred=None, 

634 phase_colors={}, 

635 fig=None): 

636 

637 fig, plt = setup_figure(fig) 

638 axes = setup_axes(fig) 

639 

640 xmin, xmax, ymin, ymax = plot_xt( 

641 paths, 

642 zstart, 

643 zstop, 

644 vred=vred, 

645 distances=distances, 

646 axes=axes, 

647 phase_colors=phase_colors) 

648 

649 if distances is not None: 

650 xmin, xmax = distances.min(), distances.max() 

651 

652 axes.set_xlim(xmin, xmax) 

653 axes.set_ylim(ymin, ymax) 

654 labels_xt(as_degrees=as_degrees, vred=vred, axes=axes) 

655 if plt: 

656 mpl_show(plt) 

657 

658 

659def my_rays_plot_gcs( 

660 mod, paths, rays, zstart, zstop, 

661 distances=None, 

662 phase_colors={}, 

663 fig=None): 

664 

665 globe_cross_section() 

666 

667 fig, plt = setup_figure(fig) 

668 axes = fig.add_subplot(1, 1, 1, projection='globe_cross_section') 

669 

670 plot_rays(paths, rays, zstart, zstop, axes=axes, phase_colors=phase_colors) 

671 plot_source(zstart, axes=axes) 

672 

673 for name in ['cmb', 'icb']: 

674 

675 try: 

676 z = mod.discontinuity(name).z 

677 

678 borders = num.arange(0, 360, 0.01) 

679 a = len(borders) 

680 depth = num.full(a, z) 

681 

682 axes.plot(borders, depth, color='xkcd:grey', alpha=0.5) 

683 axes.fill(borders, depth, color='xkcd:grey', alpha=0.1) 

684 

685 except cake.DiscontinuityNotFound: 

686 pass 

687 

688 if distances is not None: 

689 plot_receivers_gcs(zstop, distances, axes=axes) 

690 

691 axes.set_ylim(0., cake.earthradius) 

692 axes.get_yaxis().set_visible(False) 

693 

694 if plt: 

695 mpl_show(plt) 

696 

697 

698def my_rays_plot( 

699 mod, paths, rays, zstart, zstop, 

700 distances=None, 

701 as_degrees=False, 

702 aspect=None, 

703 shade_model=True, 

704 phase_colors={}, 

705 fig=None): 

706 

707 fig, plt = setup_figure(fig) 

708 axes = setup_axes(fig) 

709 

710 if paths is None: 

711 paths = list(set([x.path for x in rays])) 

712 

713 plot_rays( 

714 paths, rays, zstart, zstop, 

715 axes=axes, aspect=aspect, phase_colors=phase_colors) 

716 

717 xmin, xmax = axes.get_xlim() 

718 ymin, ymax = axes.get_ylim() 

719 sketch_model(mod, axes=axes, shade=shade_model) 

720 plot_source(zstart, axes=axes) 

721 if distances is not None: 

722 plot_receivers(zstop, distances, axes=axes) 

723 

724 labels_rays(as_degrees=as_degrees, axes=axes) 

725 mx = (xmax-xmin)*0.05 

726 my = (ymax-ymin)*0.05 

727 axes.set_xlim(xmin-mx, xmax+mx) 

728 axes.set_ylim(ymax+my, ymin-my) 

729 

730 if plt: 

731 mpl_show(plt) 

732 

733 

734def my_combi_plot( 

735 mod, paths, rays, zstart, zstop, 

736 distances=None, 

737 as_degrees=False, 

738 vred=None, 

739 phase_colors={}, 

740 fig=None): 

741 

742 fig, plt = setup_figure(fig) 

743 

744 fontsize = 9 

745 labelpos = mpl_margins( 

746 fig, nw=1, nh=2, w=7., h=5., hspace=2., units=fontsize) 

747 

748 ax1 = fig.add_subplot(2, 1, 1) 

749 labelpos(ax1, 2., 1.5) 

750 

751 ax2 = fig.add_subplot(2, 1, 2, sharex=ax1) 

752 labelpos(ax2, 2., 1.5) 

753 

754 xmin, xmax, ymin, ymax = plot_xt( 

755 paths, zstart, zstop, 

756 vred=vred, 

757 distances=distances, 

758 phase_colors=phase_colors, 

759 axes=ax1) 

760 

761 if distances is None: 

762 ax1.set_xlim(xmin, xmax) 

763 

764 labels_xt(axes=ax1, vred=vred, as_degrees=as_degrees) 

765 ax1.set_xlabel('') 

766 ax1.get_xaxis().set_tick_params(labelbottom=False) 

767 

768 plot_rays(paths, rays, zstart, zstop, phase_colors=phase_colors, axes=ax2) 

769 xmin, xmax = ax2.get_xlim() 

770 ymin, ymax = ax2.get_ylim() 

771 sketch_model(mod, axes=ax2) 

772 

773 plot_source(zstart, axes=ax2) 

774 if distances is not None: 

775 plot_receivers(zstop, distances, axes=ax2) 

776 

777 labels_rays(as_degrees=as_degrees, axes=ax2) 

778 

779 mx = (xmax-xmin)*0.05 

780 my = (ymax-ymin)*0.05 

781 ax2.set_xlim(xmin-mx, xmax+mx) 

782 ax2.set_ylim(ymax+my, ymin-my) 

783 

784 if plt: 

785 mpl_show(plt) 

786 

787 

788def my_model_plot(mod, fig=None): 

789 

790 fig, plt = setup_figure(fig) 

791 axes = setup_axes(fig) 

792 

793 labels_model(axes=axes) 

794 sketch_model(mod, axes=axes) 

795 z = mod.profile('z') 

796 vp = mod.profile('vp') 

797 vs = mod.profile('vs') 

798 axes.plot(vp, z, color=colors[0], lw=2.) 

799 axes.plot(vs, z, color=colors[2], lw=2.) 

800 ymin, ymax = axes.get_ylim() 

801 xmin, xmax = axes.get_xlim() 

802 xmin = 0. 

803 my = (ymax-ymin)*0.05 

804 mx = (xmax-xmin)*0.2 

805 axes.set_ylim(ymax+my, ymin-my) 

806 axes.set_xlim(xmin, xmax+mx) 

807 if plt: 

808 mpl_show(plt)