The fatiando package has been deprecated. Please check out the new tools in the Fatiando a Terra website: www.fatiando.org

Source code for fatiando.vis.mpl

"""
Wrappers for :mod:`matplotlib` functions to facilitate plotting grids,
2D objects, etc.

This module loads all functions from :mod:`matplotlib.pyplot`, adds new
functions and overwrites some others (like :func:`~fatiando.vis.mpl.contour`,
:func:`~fatiando.vis.mpl.pcolor`, etc).

.. warning::

    This module will be **removed** in v0.6. We recommend the use of
    :mod:`matplotlib.pyplot` module directly. Some of the fatiando specific
    functions will remain.


**Grids**

* :func:`~fatiando.vis.mpl.contour`
* :func:`~fatiando.vis.mpl.contourf`
* :func:`~fatiando.vis.mpl.pcolor`

Grids are automatically reshaped and interpolated if desired or necessary.

**2D objects**

* :func:`~fatiando.vis.mpl.points`
* :func:`~fatiando.vis.mpl.paths`
* :func:`~fatiando.vis.mpl.square`
* :func:`~fatiando.vis.mpl.squaremesh`
* :func:`~fatiando.vis.mpl.polygon`
* :func:`~fatiando.vis.mpl.layers`
* :func:`~fatiando.vis.mpl.seismic_image`
* :func:`~fatiando.vis.mpl.seismic_wiggle`

**Interactive**

* :func:`~fatiando.vis.mpl.draw_polygon`
* :func:`~fatiando.vis.mpl.draw_layers`
* :func:`~fatiando.vis.mpl.pick_points`

**Basemap (map projections)**

* :func:`~fatiando.vis.mpl.basemap`
* :func:`~fatiando.vis.mpl.draw_geolines`
* :func:`~fatiando.vis.mpl.draw_countries`
* :func:`~fatiando.vis.mpl.draw_coastlines`

**Auxiliary**

* :func:`~fatiando.vis.mpl.set_area`
* :func:`~fatiando.vis.mpl.m2km`

----

"""

import warnings
import numpy
from matplotlib import pyplot, widgets
# Quick hack so that the docs can build using the mocks for readthedocs
# Ideal would be to log an error message saying that functions from pyplot
# were not imported
try:
    from matplotlib.pyplot import *
except:
    pass

import fatiando.gridder

# Dummy variable to laizy import the basemap toolkit (slow)
Basemap = None

# Tell users that this module will be removed in v0.6
warnings.warn("This module will be removed in v0.6. We recommend the use of " +
              "matplotlib.pyplot module directly. Some of the fatiando " +
              "specific functions will remain.")


[docs]def draw_polygon(area, axes, style='-', marker='o', color='k', width=2, alpha=0.5, xy2ne=False): """ Draw a polygon by clicking with the mouse. INSTRUCTIONS: * Left click to pick the edges of the polygon; * Draw edges CLOCKWISE; * Press 'e' to erase the last edge; * Right click to close the polygon; * Close the figure window to finish; Parameters: * area : list = [x1, x2, y1, y2] Borders of the area containing the polygon * axes : matplotlib Axes The figure to use for drawing the polygon. To get an Axes instace, just do:: from matplotlib import pyplot axes = pyplot.figure().add_subplot(1,1,1) You can plot things to ``axes`` before calling this function so that they'll appear on the background. * style : str Line style (as in matplotlib.pyplot.plot) * marker : str Style of the point markers (as in matplotlib.pyplot.plot) * color : str Line color (as in matplotlib.pyplot.plot) * width : float The line width (as in matplotlib.pyplot.plot) * alpha : float Transparency of the fill of the polygon. 0 for transparent, 1 for opaque (fills the polygon once done drawing) * xy2ne : True or False If True, will exchange the x and y axis so that x points north. Use this when drawing on a map viewed from above. If the y-axis of the plot is supposed to be z (depth), then use ``xy2ne=False``. Returns: * edges : list of lists List of ``[x, y]`` pairs with the edges of the polygon """ axes.set_title("Click to draw polygon. Right click when done.") if xy2ne: axes.set_xlim(area[2], area[3]) axes.set_ylim(area[0], area[1]) else: axes.set_xlim(area[0], area[1]) axes.set_ylim(area[2], area[3]) # start with an empty line line, = axes.plot([], [], marker=marker, linestyle=style, color=color, linewidth=width) tmpline, = axes.plot([], [], marker=marker, linestyle=style, color=color, linewidth=width) draw = axes.figure.canvas.draw x = [] y = [] plotx = [] ploty = [] # Hack because Python 2 doesn't like nonlocal variables that change value. # Lists it doesn't mind. picking = [True] def draw_guide(px, py): if len(x) != 0: tmpline.set_data([x[-1], px], [y[-1], py]) def move(event): if event.inaxes != axes: return 0 if picking[0]: draw_guide(event.xdata, event.ydata) draw() def pick(event): if event.inaxes != axes: return 0 if event.button == 1 and picking[0]: x.append(event.xdata) y.append(event.ydata) plotx.append(event.xdata) ploty.append(event.ydata) if event.button == 3 or event.button == 2 and picking[0]: if len(x) < 3: axes.set_title("Need at least 3 points to make a polygon") else: picking[0] = False axes.set_title("Done! You can close the window now.") plotx.append(x[0]) ploty.append(y[0]) tmpline.set_data([], []) axes.fill(plotx, ploty, color=color, alpha=alpha) line.set_data(plotx, ploty) draw() def erase(event): if event.key == 'e' and picking[0]: x.pop() y.pop() plotx.pop() ploty.pop() line.set_data(plotx, ploty) draw_guide(event.xdata, event.ydata) draw() line.figure.canvas.mpl_connect('button_press_event', pick) line.figure.canvas.mpl_connect('key_press_event', erase) line.figure.canvas.mpl_connect('motion_notify_event', move) pyplot.show() if len(x) < 3: raise ValueError("Need at least 3 points to make a polygon") if xy2ne: verts = numpy.transpose([y, x]) else: verts = numpy.transpose([x, y]) return verts
[docs]def pick_points(area, axes, marker='o', color='k', size=8, xy2ne=False): """ Get the coordinates of points by clicking with the mouse. INSTRUCTIONS: * Left click to pick the points; * Press 'e' to erase the last point picked; * Close the figure window to finish; Parameters: * area : list = [x1, x2, y1, y2] Borders of the area containing the points * axes : matplotlib Axes The figure to use for drawing the polygon. To get an Axes instace, just do:: from matplotlib import pyplot axes = pyplot.figure().add_subplot(1,1,1) You can plot things to ``axes`` before calling this function so that they'll appear on the background. * marker : str Style of the point markers (as in matplotlib.pyplot.plot) * color : str Line color (as in matplotlib.pyplot.plot) * size : float Marker size (as in matplotlib.pyplot.plot) * xy2ne : True or False If True, will exchange the x and y axis so that x points north. Use this when drawing on a map viewed from above. If the y-axis of the plot is supposed to be z (depth), then use ``xy2ne=False``. Returns: * points : list of lists List of ``[x, y]`` coordinates of the points """ axes.set_title("Click to pick points. Close window when done.") if xy2ne: axes.set_xlim(area[2], area[3]) axes.set_ylim(area[0], area[1]) else: axes.set_xlim(area[0], area[1]) axes.set_ylim(area[2], area[3]) # start with an empty set line, = axes.plot([], [], marker=marker, color=color, markersize=size) line.figure.canvas.draw() x = [] y = [] plotx = [] ploty = [] # Hack because Python 2 doesn't like nonlocal variables that change value. # Lists it doesn't mind. picking = [True] def pick(event): if event.inaxes != axes: return 0 if event.button == 1 and picking[0]: x.append(event.xdata) y.append(event.ydata) plotx.append(event.xdata) ploty.append(event.ydata) line.set_color(color) line.set_marker(marker) line.set_markersize(size) line.set_linestyle('') line.set_data(plotx, ploty) line.figure.canvas.draw() def erase(event): if event.key == 'e' and picking[0]: x.pop() y.pop() plotx.pop() ploty.pop() line.set_data(plotx, ploty) line.figure.canvas.draw() line.figure.canvas.mpl_connect('button_press_event', pick) line.figure.canvas.mpl_connect('key_press_event', erase) pyplot.show() if xy2ne: points = numpy.transpose([y, x]) else: points = numpy.transpose([x, y]) return points
[docs]def draw_layers(area, axes, style='-', marker='o', color='k', width=2): """ Draw series of horizontal layers by clicking with the mouse. The y-axis is assumed to be depth, the x-axis is the physical property of each layer. INSTRUCTIONS: * Click to make a new layer; * Press 'e' to erase the last layer; * Close the figure window to finish; Parameters: * area : list = [x1, x2, y1, y2] Borders of the area containing the polygon * axes : matplotlib Axes The figure to use for drawing the polygon. To get an Axes instace, just do:: from matplotlib import pyplot axes = pyplot.figure().add_subplot(1,1,1) You can plot things to ``axes`` before calling this function so that they'll appear on the background. * style : str Line style (as in matplotlib.pyplot.plot) * marker : str Style of the point markers (as in matplotlib.pyplot.plot) * color : str Line color (as in matplotlib.pyplot.plot) * width : float The line width (as in matplotlib.pyplot.plot) Returns: * layers : list = [thickness, values] * thickness : list The thickness of each layer, in order of increasing depth * values : list The physical property value of each layer, in the same order """ axes.set_title("Click to set a layer. Close the window when done.") axes.grid() vmin, vmax, zmin, zmax = area axes.set_xlim(vmin, vmax) axes.set_ylim(zmax, zmin) # start with an empty line line, = axes.plot([], [], marker=marker, linestyle=style, color=color, linewidth=width) midv = 0.5 * (vmax + vmin) # this is the line that moves around with the mouse tmpline, = axes.plot([midv], [zmin], marker=marker, linestyle='--', color=color, linewidth=width) # Make a proxy for drawing draw = axes.figure.canvas.draw depths = [zmin] values = [] plotv = [] plotz = [] tmpz = [zmin] # Hack because Python 2 doesn't like nonlocal variables that change value. # Lists it doesn't mind. picking = [True] def draw_guide(v, z): if len(values) == 0: tmpline.set_data([v, v], [tmpz[0], z]) else: if z > tmpz[0]: tmpline.set_data([values[-1], v, v], [tmpz[0], tmpz[0], z]) else: tmpline.set_data([values[-1], v], [tmpz[0], tmpz[0]]) def move(event): if event.inaxes != axes: return 0 v, z = event.xdata, event.ydata if picking[0]: draw_guide(v, z) draw() def pick(event): if event.inaxes != axes: return 0 if event.button == 1 and picking[0]: v, z = event.xdata, event.ydata if z > tmpz[0]: depths.append(z) values.append(v) plotz.extend([tmpz[0], z]) plotv.extend([v, v]) tmpz[0] = z line.set_data(plotv, plotz) draw() def erase(event): if picking[0] and len(values) > 0 and event.key == 'e': depths.pop() values.pop() tmpz[0] = depths[-1] plotv.pop() plotv.pop() plotz.pop() plotz.pop() line.set_data(plotv, plotz) draw_guide(event.xdata, event.ydata) draw() line.figure.canvas.mpl_connect('button_press_event', pick) line.figure.canvas.mpl_connect('key_press_event', erase) line.figure.canvas.mpl_connect('motion_notify_event', move) pyplot.show() thickness = [depths[i + 1] - depths[i] for i in xrange(len(depths) - 1)] return thickness, values
[docs]def draw_geolines(area, dlon, dlat, basemap, linewidth=1): """ Draw the parallels and meridians on a basemap plot. Parameters: * area : list ``[west, east, south, north]``, i.e., the area where the lines will be plotted * dlon, dlat : float The spacing between the lines in the longitude and latitude directions, respectively (in decimal degrees) * basemap : mpl_toolkits.basemap.Basemap The basemap used for plotting (see :func:`~fatiando.vis.mpl.basemap`) * linewidth : float The width of the lines """ west, east, south, north = area meridians = basemap.drawmeridians(numpy.arange(west, east, dlon), labels=[0, 0, 0, 1], linewidth=linewidth) parallels = basemap.drawparallels(numpy.arange(south, north, dlat), labels=[1, 0, 0, 0], linewidth=linewidth)
[docs]def draw_countries(basemap, linewidth=1, style='dashed'): """ Draw the country borders using the given basemap. Parameters: * basemap : mpl_toolkits.basemap.Basemap The basemap used for plotting (see :func:`~fatiando.vis.mpl.basemap`) * linewidth : float The width of the lines * style : str The style of the lines. Can be: 'solid', 'dashed', 'dashdot' or 'dotted' """ lines = basemap.drawcountries(linewidth=linewidth) lines.set_linestyles(style)
[docs]def draw_coastlines(basemap, linewidth=1, style='solid'): """ Draw the coastlines using the given basemap. Parameters: * basemap : mpl_toolkits.basemap.Basemap The basemap used for plotting (see :func:`~fatiando.vis.mpl.basemap`) * linewidth : float The width of the lines * style : str The style of the lines. Can be: 'solid', 'dashed', 'dashdot' or 'dotted' """ lines = basemap.drawcoastlines(linewidth=linewidth) lines.set_linestyles(style)
[docs]def basemap(area, projection, resolution='c'): """ Make a basemap to use when plotting with map projections. Uses the matplotlib basemap toolkit. Parameters: * area : list ``[west, east, south, north]``, i.e., the area of the data that is going to be plotted * projection : str The name of the projection you want to use. Choose from: * 'ortho': Orthographic * 'geos': Geostationary * 'robin': Robinson * 'cass': Cassini * 'merc': Mercator * 'poly': Polyconic * 'lcc': Lambert Conformal * 'stere': Stereographic * resolution : str The resolution for the coastlines. Can be 'c' for crude, 'l' for low, 'i' for intermediate, 'h' for high Returns: * basemap : mpl_toolkits.basemap.Basemap The basemap """ if projection not in ['ortho', 'aeqd', 'geos', 'robin', 'cass', 'merc', 'poly', 'lcc', 'stere']: raise ValueError("Unsuported projection '%s'" % (projection)) global Basemap if Basemap is None: try: from mpl_toolkits.basemap import Basemap except ImportError: raise west, east, south, north = area lon_0 = 0.5 * (east + west) lat_0 = 0.5 * (north + south) if projection == 'ortho': bm = Basemap(projection=projection, lon_0=lon_0, lat_0=lat_0, resolution=resolution) elif projection == 'geos' or projection == 'robin': bm = Basemap(projection=projection, lon_0=lon_0, resolution=resolution) elif (projection == 'cass' or projection == 'poly'): bm = Basemap(projection=projection, llcrnrlon=west, urcrnrlon=east, llcrnrlat=south, urcrnrlat=north, lat_0=lat_0, lon_0=lon_0, resolution=resolution) elif projection == 'merc': bm = Basemap(projection=projection, llcrnrlon=west, urcrnrlon=east, llcrnrlat=south, urcrnrlat=north, lat_ts=lat_0, resolution=resolution) elif projection == 'lcc': bm = Basemap(projection=projection, llcrnrlon=west, urcrnrlon=east, llcrnrlat=south, urcrnrlat=north, lat_0=lat_0, lon_0=lon_0, rsphere=(6378137.00, 6356752.3142), lat_1=lat_0, resolution=resolution) elif projection == 'stere': bm = Basemap(projection=projection, llcrnrlon=west, urcrnrlon=east, llcrnrlat=south, urcrnrlat=north, lat_0=lat_0, lon_0=lon_0, lat_ts=lat_0, resolution=resolution) return bm
[docs]def m2km(axis=None): """ Convert the x and y tick labels from meters to kilometers. Parameters: * axis : matplotlib axis instance The plot. .. tip:: Use ``fatiando.vis.gca()`` to get the current axis. Or the value returned by ``fatiando.vis.subplot`` or ``matplotlib.pyplot.subplot``. """ if axis is None: axis = pyplot.gca() axis.set_xticklabels(['%g' % (0.001 * l) for l in axis.get_xticks()]) axis.set_yticklabels(['%g' % (0.001 * l) for l in axis.get_yticks()])
[docs]def set_area(area): """ Set the area of a Matplolib plot using xlim and ylim. Parameters: * area : list = [x1, x2, y1, y2] Coordinates of the top right and bottom left corners of the area """ x1, x2, y1, y2 = area pyplot.xlim(x1, x2) pyplot.ylim(y1, y2)
[docs]def points(pts, style='.k', size=10, label=None, xy2ne=False): """ Plot a list of points. Parameters: * pts : list of lists List of [x, y] pairs with the coordinates of the points * style : str String with the color and line style (as in matplotlib.pyplot.plot) * size : int Size of the plotted points * label : str If not None, then the string that will show in the legend * xy2ne : True or False If True, will exchange the x and y axis so that the x coordinates of the polygon are north. Use this when drawing on a map viewed from above. If the y-axis of the plot is supposed to be z (depth), then use ``xy2ne=False``. Returns: * axes : ``matplitlib.axes`` The axes element of the plot """ x, y = numpy.array(pts).T if xy2ne: x, y = y, x kwargs = {} if label is not None: kwargs['label'] = label return pyplot.plot(x, y, style, markersize=size, **kwargs)
[docs]def paths(pts1, pts2, style='-k', linewidth=1, label=None): """ Plot paths between the two sets of points. Parameters: * pts1 : list of lists List of (x, y) pairs with the coordinates of the points * pts2 : list of lists List of (x, y) pairs with the coordinates of the points * style : str String with the color and line style (as in matplotlib.pyplot.plot) * linewidth : float The width of the lines representing the paths * label : str If not None, then the string that will show in the legend """ kwargs = {'linewidth': linewidth} if label is not None: kwargs['label'] = label for p1, p2 in zip(pts1, pts2): pyplot.plot([p1[0], p2[0]], [p1[1], p2[1]], style, **kwargs)
[docs]def layers(thickness, values, style='-k', z0=0., linewidth=1, label=None, **kwargs): """ Plot a series of layers and values associated to each layer. Parameters: * thickness : list The thickness of each layer in order of increasing depth * values : list The value associated with each layer in order of increasing depth * style : str String with the color and line style (as in matplotlib.pyplot.plot) * z0 : float The depth of the top of the first layer * linewidth : float Line width * label : str label associated with the square. Returns: * axes : ``matplitlib.axes`` The axes element of the plot """ if len(thickness) != len(values): raise ValueError("thickness and values must have same length") nlayers = len(thickness) interfaces = [z0 + sum(thickness[:i]) for i in xrange(nlayers + 1)] ys = [interfaces[0]] for y in interfaces[1:-1]: ys.append(y) ys.append(y) ys.append(interfaces[-1]) xs = [] for x in values: xs.append(x) xs.append(x) kwargs['linewidth'] = linewidth if label is not None: kwargs['label'] = label plot, = pyplot.plot(xs, ys, style, **kwargs) return plot
[docs]def square(area, style='-k', linewidth=1, fill=None, alpha=1., label=None, xy2ne=False): """ Plot a square. Parameters: * area : list = [x1, x2, y1, y2] Borders of the square * style : str String with the color and line style (as in matplotlib.pyplot.plot) * linewidth : float Line width * fill : str A color string used to fill the square. If None, the square is not filled * alpha : float Transparency of the fill (1 >= alpha >= 0). 0 is transparent and 1 is opaque * label : str label associated with the square. * xy2ne : True or False If True, will exchange the x and y axis so that the x coordinates of the polygon are north. Use this when drawing on a map viewed from above. If the y-axis of the plot is supposed to be z (depth), then use ``xy2ne=False``. Returns: * axes : ``matplitlib.axes`` The axes element of the plot """ x1, x2, y1, y2 = area if xy2ne: x1, x2, y1, y2 = y1, y2, x1, x2 xs = [x1, x1, x2, x2, x1] ys = [y1, y2, y2, y1, y1] kwargs = {'linewidth': linewidth} if label is not None: kwargs['label'] = label plot, = pyplot.plot(xs, ys, style, **kwargs) if fill is not None: pyplot.fill(xs, ys, color=fill, alpha=alpha) return plot
[docs]def squaremesh(mesh, prop, cmap=pyplot.cm.jet, vmin=None, vmax=None): """ Make a pseudo-color plot of a mesh of squares Parameters: * mesh : :class:`fatiando.mesher.SquareMesh` or compatible The mesh (a compatible mesh must implement the methods ``get_xs`` and ``get_ys``) * prop : str The physical property of the squares to use as the color scale. * cmap : colormap Color map to be used. (see pyplot.cm module) * vmin, vmax : float Saturation values of the colorbar. Returns: * axes : ``matplitlib.axes`` The axes element of the plot """ if prop not in mesh.props: raise ValueError("Can't plot because 'mesh' doesn't have property '%s'" % (prop)) xs = mesh.get_xs() ys = mesh.get_ys() X, Y = numpy.meshgrid(xs, ys) V = numpy.reshape(mesh.props[prop], mesh.shape) plot = pyplot.pcolor(X, Y, V, cmap=cmap, vmin=vmin, vmax=vmax, picker=True) pyplot.xlim(xs.min(), xs.max()) pyplot.ylim(ys.min(), ys.max()) return plot
[docs]def polygon(polygon, style='-k', linewidth=1, fill=None, alpha=1., label=None, xy2ne=False, linealpha=1.): """ Plot a polygon. Parameters: * polygon : :class:`fatiando.mesher.Polygon` The polygon * style : str Color and line style string (as in matplotlib.pyplot.plot) * linewidth : float Line width * fill : str A color string used to fill the polygon. If None, the polygon is not filled * alpha : float Transparency of the fill (1 >= alpha >= 0). 0 is transparent and 1 is opaque * linealpha : float Transparency of the line (1 >= alpha >= 0). 0 is transparent and 1 is opaque * label : str String with the label identifying the polygon in the legend * xy2ne : True or False If True, will exchange the x and y axis so that the x coordinates of the polygon are north. Use this when drawing on a map viewed from above. If the y-axis of the plot is supposed to be z (depth), then use ``xy2ne=False``. Returns: * lines : matplotlib Line object Line corresponding to the polygon plotted """ if xy2ne: tmpx = [y for y in polygon.y] tmpx.append(polygon.y[0]) tmpy = [x for x in polygon.x] tmpy.append(polygon.x[0]) else: tmpx = [x for x in polygon.x] tmpx.append(polygon.x[0]) tmpy = [y for y in polygon.y] tmpy.append(polygon.y[0]) kwargs = {'linewidth': linewidth, 'alpha': linealpha} if label is not None: kwargs['label'] = label line, = pyplot.plot(tmpx, tmpy, style, **kwargs) if fill is not None: pyplot.fill(tmpx, tmpy, color=fill, alpha=alpha) return line
[docs]def contour(x, y, v, shape, levels, interp=False, extrapolate=False, color='k', label=None, clabel=True, style='solid', linewidth=1.0, basemap=None): """ Make a contour plot of the data. Parameters: * x, y : array Arrays with the x and y coordinates of the grid points. If the data is on a regular grid, then assume x varies first (ie, inner loop), then y. * v : array The scalar value assigned to the grid points. * shape : tuple = (ny, nx) Shape of the regular grid. If interpolation is not False, then will use *shape* to grid the data. * levels : int or list Number of contours to use or a list with the contour values. * interp : True or False Wether or not to interpolate before trying to plot. If data is not on regular grid, set to True! * extrapolate : True or False Wether or not to extrapolate the data when interp=True * color : str Color of the contour lines. * label : str String with the label of the contour that would show in a legend. * clabel : True or False Wether or not to print the numerical value of the contour lines * style : str The style of the contour lines. Can be ``'dashed'``, ``'solid'`` or ``'mixed'`` (solid lines for positive contours and dashed for negative) * linewidth : float Width of the contour lines * basemap : mpl_toolkits.basemap.Basemap If not None, will use this basemap for plotting with a map projection (see :func:`~fatiando.vis.mpl.basemap` for creating basemaps) Returns: * levels : list List with the values of the contour levels """ if style not in ['solid', 'dashed', 'mixed']: raise ValueError("Invalid contour style %s" % (style)) if x.shape != y.shape != v.shape: raise ValueError("Input arrays x, y, and v must have same shape!") if interp: x, y, v = fatiando.gridder.interp(x, y, v, shape, extrapolate=extrapolate) X = numpy.reshape(x, shape) Y = numpy.reshape(y, shape) V = numpy.reshape(v, shape) kwargs = dict(colors=color, picker=True) if basemap is None: ct_data = pyplot.contour(X, Y, V, levels, **kwargs) pyplot.xlim(X.min(), X.max()) pyplot.ylim(Y.min(), Y.max()) else: lon, lat = basemap(X, Y) ct_data = basemap.contour(lon, lat, V, levels, **kwargs) if clabel: ct_data.clabel(fmt='%g') if label is not None: ct_data.collections[0].set_label(label) if style != 'mixed': for c in ct_data.collections: c.set_linestyle(style) for c in ct_data.collections: c.set_linewidth(linewidth) return ct_data.levels
[docs]def contourf(x, y, v, shape, levels, interp=False, extrapolate=False, vmin=None, vmax=None, cmap=pyplot.cm.jet, basemap=None): """ Make a filled contour plot of the data. Parameters: * x, y : array Arrays with the x and y coordinates of the grid points. If the data is on a regular grid, then assume x varies first (ie, inner loop), then y. * v : array The scalar value assigned to the grid points. * shape : tuple = (ny, nx) Shape of the regular grid. If interpolation is not False, then will use *shape* to grid the data. * levels : int or list Number of contours to use or a list with the contour values. * interp : True or False Wether or not to interpolate before trying to plot. If data is not on regular grid, set to True! * extrapolate : True or False Wether or not to extrapolate the data when interp=True * vmin, vmax Saturation values of the colorbar. If provided, will overwrite what is set by *levels*. * cmap : colormap Color map to be used. (see pyplot.cm module) * basemap : mpl_toolkits.basemap.Basemap If not None, will use this basemap for plotting with a map projection (see :func:`~fatiando.vis.mpl.basemap` for creating basemaps) Returns: * levels : list List with the values of the contour levels """ if x.shape != y.shape != v.shape: raise ValueError("Input arrays x, y, and v must have same shape!") if interp: x, y, v = fatiando.gridder.interp(x, y, v, shape, extrapolate=extrapolate) X = numpy.reshape(x, shape) Y = numpy.reshape(y, shape) V = numpy.reshape(v, shape) kwargs = dict(vmin=vmin, vmax=vmax, cmap=cmap, picker=True) if basemap is None: ct_data = pyplot.contourf(X, Y, V, levels, **kwargs) pyplot.xlim(X.min(), X.max()) pyplot.ylim(Y.min(), Y.max()) else: lon, lat = basemap(X, Y) ct_data = basemap.contourf(lon, lat, V, levels, **kwargs) return ct_data.levels
[docs]def pcolor(x, y, v, shape, interp=False, extrapolate=False, cmap=pyplot.cm.jet, vmin=None, vmax=None, basemap=None): """ Make a pseudo-color plot of the data. Parameters: * x, y : array Arrays with the x and y coordinates of the grid points. If the data is on a regular grid, then assume x varies first (ie, inner loop), then y. * v : array The scalar value assigned to the grid points. * shape : tuple = (ny, nx) Shape of the regular grid. If interpolation is not False, then will use *shape* to grid the data. * interp : True or False Wether or not to interpolate before trying to plot. If data is not on regular grid, set to True! * extrapolate : True or False Wether or not to extrapolate the data when interp=True * cmap : colormap Color map to be used. (see pyplot.cm module) * vmin, vmax Saturation values of the colorbar. * basemap : mpl_toolkits.basemap.Basemap If not None, will use this basemap for plotting with a map projection (see :func:`~fatiando.vis.mpl.basemap` for creating basemaps) Returns: * axes : ``matplitlib.axes`` The axes element of the plot """ if x.shape != y.shape != v.shape: raise ValueError("Input arrays x, y, and v must have same shape!") if vmin is None: vmin = v.min() if vmax is None: vmax = v.max() if interp: x, y, v = fatiando.gridder.interp(x, y, v, shape, extrapolate=extrapolate) X = numpy.reshape(x, shape) Y = numpy.reshape(y, shape) V = numpy.reshape(v, shape) if basemap is None: plot = pyplot.pcolor(X, Y, V, cmap=cmap, vmin=vmin, vmax=vmax, picker=True) pyplot.xlim(X.min(), X.max()) pyplot.ylim(Y.min(), Y.max()) else: lon, lat = basemap(X, Y) plot = basemap.pcolor(lon, lat, V, cmap=cmap, vmin=vmin, vmax=vmax, picker=True) return plot
[docs]def seismic_wiggle(section, dt=0.004, ranges=None, scale=1., color='k', normalize=False): """ Plot a seismic section (numpy 2D array matrix) as wiggles. Parameters: * section : 2D array matrix of traces (first dimension time, second dimension traces) * dt : float sample rate in seconds (default 4 ms) * ranges : (x1, x2) min and max horizontal values (default trace number) * scale : float scale factor multiplied by the section values before plotting * color : tuple of strings Color for filling the wiggle, positive and negative lobes. * normalize : True to normalizes all trace in the section using global max/min data will be in the range (-0.5, 0.5) zero centered .. warning:: Slow for more than 200 traces, in this case decimate your data or use ``seismic_image``. """ npts, ntraces = section.shape # time/traces if ntraces < 1: raise IndexError("Nothing to plot") if npts < 1: raise IndexError("Nothing to plot") t = numpy.linspace(0, dt*npts, npts) amp = 1. # normalization factor gmin = 0. # global minimum toffset = 0. # offset in time to make 0 centered if normalize: gmax = section.max() gmin = section.min() amp = (gmax-gmin) toffset = 0.5 pyplot.ylim(max(t), 0) if ranges is None: ranges = (0, ntraces) x0, x1 = ranges # horizontal increment dx = float((x1-x0)/ntraces) pyplot.xlim(x0, x1) for i, trace in enumerate(section.transpose()): tr = (((trace-gmin)/amp)-toffset)*scale*dx x = x0+i*dx # x positon for this trace pyplot.plot(x+tr, t, 'k') pyplot.fill_betweenx(t, x+tr, x, tr > 0, color=color)
[docs]def seismic_image(section, dt=0.004, ranges=None, cmap=pyplot.cm.gray, aspect=None, vmin=None, vmax=None): """ Plot a seismic section (numpy 2D array matrix) as an image. Parameters: * section : 2D array matrix of traces (first dimension time, second dimension traces) * dt : float sample rate in seconds (default 4 ms) * ranges : (x1, x2) min and max horizontal values (default trace number) * cmap : colormap color map to be used. (see pyplot.cm module) * aspect : float matplotlib imshow aspect parameter, ratio between axes * vmin, vmax : float min and max values for imshow """ npts, maxtraces = section.shape # time/traces if maxtraces < 1: raise IndexError("Nothing to plot") if npts < 1: raise IndexError("Nothing to plot") t = numpy.linspace(0, dt*npts, npts) data = section if ranges is None: ranges = (0, maxtraces) x0, x1 = ranges extent = (x0, x1, t[-1:], t[0]) if aspect is None: # guarantee a rectangular picture aspect = numpy.round((x1-x0)/numpy.max(t)) aspect -= aspect*0.2 pyplot.imshow(data, aspect=aspect, cmap=cmap, origin='upper', extent=extent, vmin=vmin, vmax=vmax)