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
« 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----------
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
13str_to_mpl_color
14InvalidColorDef
16d2r = cake.d2r
17r2d = cake.r2d
19_have_registered_gcs = False
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
26 global _have_registered_gcs
28 if _have_registered_gcs:
29 return
31 from matplotlib.projections import PolarAxes, register_projection
32 from matplotlib.transforms import Bbox, IdentityTransform
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'
41 class GlobeCrossSectionTransform(PolarAxes.PolarTransform):
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
51 transform_non_affine = transform
53 def inverted(self):
54 return GlobeCrossSectionAxes.\
55 InvertedGlobeCrossSectionTransform()
57 class InvertedGlobeCrossSectionTransform(
58 PolarAxes.InvertedPolarTransform):
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
68 def inverted(self):
69 return GlobeCrossSectionAxes.GlobeCrossSectionTransform()
71 def __init__(self, *args, **kwargs):
72 PolarAxes.__init__(
73 self,
74 *args,
75 theta_offset=90.*d2r,
76 theta_direction=-1,
77 **kwargs)
79 def _set_lim_and_transforms(self):
80 PolarAxes._set_lim_and_transforms(self)
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)
92 register_projection(GlobeCrossSectionAxes)
94 _have_registered_gcs = True
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}
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
136def light(color, factor=0.2):
137 return tuple(1-(1-c)*factor for c in color)
140def dark(color, factor=0.5):
141 return tuple(c*factor for c in color)
144def to01(c):
145 return tuple(x/255. for x in c)
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)]
153shades_water = [
154 light(to01(tango_colors['skyblue1']), i*0.1) for i in range(1, 9)]
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={}):
166 if distances is not None:
167 xmin, xmax = distances.min(), distances.max()
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)
175 for ipath, path in enumerate(paths):
176 if distances is not None:
177 if path.xmax() < xmin or path.xmin() > xmax:
178 continue
180 color = path_to_color[path]
181 p, x, t = path.draft_pxt(path.endgaps(zstart, zstop))
182 if p.size == 0:
183 continue
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)
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]
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)
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))
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)
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={}):
268 path_to_color = make_path_to_color(
269 paths, coloring, avoid_same_colors, phase_colors=phase_colors)
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))
295 all_x.append(x)
297 xxx = num.sort(num.concatenate(all_x))
298 return xxx.min(), xxx[99*len(xxx)//100]
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]')
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)
319def make_path_to_color(
320 paths,
321 coloring='by_phase_definition',
322 avoid_same_colors=True,
323 phase_colors={}):
325 assert coloring in ['by_phase_definition', 'by_path']
327 path_to_color = {}
328 definition_to_color = phase_colors.copy()
329 available_colors = set()
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)
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()
346 assert color_id not in available_colors
348 definition_to_color[given_name] = colors[color_id]
350 path_to_color[path] = definition_to_color[given_name]
351 else:
352 path_to_color[path] = colors[ipath % len(colors)]
354 return path_to_color
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={}):
365 axes = getaxes(axes)
366 if aspect is not None:
367 axes.set_aspect(aspect/(d2r*cake.earthradius))
369 path_to_color = make_path_to_color(
370 paths, coloring, avoid_same_colors, phase_colors=phase_colors)
372 if rays is None:
373 rays = paths
375 labels = set()
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))
383 if not path._is_headwave:
384 p = num.linspace(pmin, pmax, 6)
385 x = None
387 else:
388 x = num.linspace(xmin, xmin*10, 6)
389 p = num.atleast_1d(pmin)
391 fanz, fanx, _ = path.zxt_path_subdivided(
392 p, path.endgaps(zstart, zstop), x_for_headwave=x)
394 else:
395 fanz, fanx, _ = ray.zxt_path_subdivided()
396 path = ray.path
398 color = path_to_color[path]
400 if coloring == 'by_phase_definition':
401 phase_label = path.phase.given_name()
403 else:
404 phase_label = path
406 for zs, xs in zip(fanz, fanx):
407 if phase_label in labels:
408 phase_label = ''
410 axes.plot(xs, zs, color=color, label=phase_label)
411 if legend:
412 labels.add(phase_label)
414 if legend:
415 axes.legend(loc=4, prop={'size': 11})
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)
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))
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
444 color = tab[ilay % len(tab)]
445 if shade:
446 axes.axhspan(
447 lay.ztop, lay.zbot, fc=color, ec=dark(color), label='abc')
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))
460def plot_source(zstart, axes=None):
461 axes = getaxes(axes)
462 axes.plot([0], [zstart], 'o', color='black', clip_on=False)
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)
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)
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)
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
507def mk_sc_classes():
508 from matplotlib.ticker import FormatStrFormatter, AutoLocator
510 class Scaled(FormatStrFormatter):
511 def __init__(self, factor):
512 FormatStrFormatter.__init__(self, '%g')
513 self._factor = factor
515 def __call__(self, v, i=0):
516 return FormatStrFormatter.__call__(self, v*self._factor, i)
518 class ScaledLocator(AutoLocator):
519 def __init__(self, factor):
520 AutoLocator.__init__(self)
521 self._factor = factor
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)]
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)]
531 return Scaled, ScaledLocator
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))
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))
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)
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
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)]))
575 a, pp, ps, ss, sp = num.array(data).T
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)
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
595 return fig, plt
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
606def my_xp_plot(
607 paths, zstart, zstop,
608 distances=None,
609 as_degrees=False,
610 phase_colors={},
611 fig=None):
613 fig, plt = setup_figure(fig)
614 axes = setup_axes(fig)
616 xmin, xmax = plot_xp(
617 paths, zstart, zstop, axes=axes, phase_colors=phase_colors)
619 if distances is not None:
620 xmin, xmax = distances.min(), distances.max()
622 axes.set_xlim(xmin, xmax)
623 labels_xp(as_degrees=as_degrees, axes=axes)
625 if plt:
626 mpl_show(plt)
629def my_xt_plot(
630 paths, zstart, zstop,
631 distances=None,
632 as_degrees=False,
633 vred=None,
634 phase_colors={},
635 fig=None):
637 fig, plt = setup_figure(fig)
638 axes = setup_axes(fig)
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)
649 if distances is not None:
650 xmin, xmax = distances.min(), distances.max()
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)
659def my_rays_plot_gcs(
660 mod, paths, rays, zstart, zstop,
661 distances=None,
662 phase_colors={},
663 fig=None):
665 globe_cross_section()
667 fig, plt = setup_figure(fig)
668 axes = fig.add_subplot(1, 1, 1, projection='globe_cross_section')
670 plot_rays(paths, rays, zstart, zstop, axes=axes, phase_colors=phase_colors)
671 plot_source(zstart, axes=axes)
673 for name in ['cmb', 'icb']:
675 try:
676 z = mod.discontinuity(name).z
678 borders = num.arange(0, 360, 0.01)
679 a = len(borders)
680 depth = num.full(a, z)
682 axes.plot(borders, depth, color='xkcd:grey', alpha=0.5)
683 axes.fill(borders, depth, color='xkcd:grey', alpha=0.1)
685 except cake.DiscontinuityNotFound:
686 pass
688 if distances is not None:
689 plot_receivers_gcs(zstop, distances, axes=axes)
691 axes.set_ylim(0., cake.earthradius)
692 axes.get_yaxis().set_visible(False)
694 if plt:
695 mpl_show(plt)
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):
707 fig, plt = setup_figure(fig)
708 axes = setup_axes(fig)
710 if paths is None:
711 paths = list(set([x.path for x in rays]))
713 plot_rays(
714 paths, rays, zstart, zstop,
715 axes=axes, aspect=aspect, phase_colors=phase_colors)
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)
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)
730 if plt:
731 mpl_show(plt)
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):
742 fig, plt = setup_figure(fig)
744 fontsize = 9
745 labelpos = mpl_margins(
746 fig, nw=1, nh=2, w=7., h=5., hspace=2., units=fontsize)
748 ax1 = fig.add_subplot(2, 1, 1)
749 labelpos(ax1, 2., 1.5)
751 ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
752 labelpos(ax2, 2., 1.5)
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)
761 if distances is None:
762 ax1.set_xlim(xmin, xmax)
764 labels_xt(axes=ax1, vred=vred, as_degrees=as_degrees)
765 ax1.set_xlabel('')
766 ax1.get_xaxis().set_tick_params(labelbottom=False)
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)
773 plot_source(zstart, axes=ax2)
774 if distances is not None:
775 plot_receivers(zstop, distances, axes=ax2)
777 labels_rays(as_degrees=as_degrees, axes=ax2)
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)
784 if plt:
785 mpl_show(plt)
788def my_model_plot(mod, fig=None):
790 fig, plt = setup_figure(fig)
791 axes = setup_axes(fig)
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)