Source code for mttime.imaging.beachball

# -*- coding: utf-8 -*-
# SPDX-License-Identifier: (LGPL-3.0)
# LLNL-CODE-814839
# author: Andrea Chiang (andrea@llnl.gov)
"""
Draws the beach ball diagram of a moment tensor

Source codes are adapted from :mod:`~obspy.imaging.mopad_wrapper`.

"""

import numpy as np
import matplotlib.collections as mpl_collections
from matplotlib import patches, transforms

from obspy.imaging.beachball import xy2patch
from .scripts.mopad import BeachBall
from .scripts.mopad import MomentTensor
from .scripts.mopad import epsilon


[docs]def beach(fm, linewidth=1, facecolor='0.75', bgcolor='w', edgecolor='k', alpha=1.0, xy=(0, 0), width=200, size=100, nofill=False, zorder=100, mopad_basis='NED', axes=None, show_iso=False): """ Plot beach ball based on `MoPaD <http://www.larskrieger.de/mopad/>`_ Function that returns a beach ball as a collection and can be added to an existing :class:`~matplotlib.axes.Axes`. :param fm: focal mechanism in (strike, dip, rake) or (M11,M22,M33,M12,M13,M23). The moment tensor elements are given for a coordinate system with axes pointing in three directions. :type fm: list :param linewidth: width of nodal and border lines. Default is ``0.8``. :type linewidth: float :param facecolor: color or shade of the compressive quadrants. Default is ``0.75`` (gray). :type facecolor: str :param bgcolor: background color, default is ``w`` (white). :type bgcolor: str :param edgecolor: color of nodal and border lines, default is ``b`` (black). :type edgecolor: str :param alpha: beach ball transparency, default is ``1.0`` (opaque). :type alpha: float :param xy: original position of the beach ball. Default is ``(0, 0)`` :type xy: tuple :param width: width of the beach ball (aka symbol size). Default is ``200``. :type width: float :param size: number of points interpolated to draw the curve. Default is ``100``. :type size: int :param nofill: no shading of the beach ball. Default is ``False``. :type nofill: bool :param zorder: set the zorder for the artist. Artists with lower zorder values are drawn first. Default is ``100``. :type zorder: float :param mopad_basis: moment tensor coordinate system. Default is ``"NED"``. :type mopad_basis: str :param axes: figure axis for beach ball, this is used to ensure the aspect ratio is adjusted so that the beach ball is circular on non-scaled axes. When this option is used figure cannot be saved in vector format. Default is ``None``. :type axes: :class:`~matplotlib.axes.Axes` :param show_iso: flag to display the isotropic component, default is ``False``. :type show_iso: bool :return: a collection of lines and polygons. :rtype: :class:`~matplotlib.collections.PatchCollection` .. warning:: Set ``axes=None`` if you want to save the beach ball image in vector file formats. """ # initialize beachball mt = MomentTensor(fm, system=mopad_basis) bb = BeachBall(mt, npoints=size) if show_iso: # Include the isotropic component bb._plot_isotropic_part = True bb._nodallines_in_NED_system() bb._setup_BB(unit_circle=False) # extract the coordinates and colors of the lines radius = width / 2.0 neg_nodalline = bb._nodalline_negative_final_US pos_nodalline = bb._nodalline_positive_final_US tension_colour = facecolor pressure_colour = bgcolor if nofill: tension_colour = 'none' pressure_colour = 'none' # based on mopads _setup_plot_US() function # collect patches for the selection coll = [None, None, None] coll[0] = patches.Circle(xy, radius=radius) coll[1] = xy2patch(neg_nodalline[0, :], neg_nodalline[1, :], radius, xy) coll[2] = xy2patch(pos_nodalline[0, :], pos_nodalline[1, :], radius, xy) # set the color of the three parts fc = [None, None, None] if bb._plot_clr_order > 0: fc[0] = pressure_colour fc[1] = tension_colour fc[2] = tension_colour if bb._plot_curve_in_curve != 0: fc[0] = tension_colour if bb._plot_curve_in_curve < 1: fc[1] = pressure_colour fc[2] = tension_colour else: coll = [coll[i] for i in (0, 2, 1)] fc[1] = pressure_colour fc[2] = tension_colour else: fc[0] = tension_colour fc[1] = pressure_colour fc[2] = pressure_colour if bb._plot_curve_in_curve != 0: fc[0] = pressure_colour if bb._plot_curve_in_curve < 1: fc[1] = tension_colour fc[2] = pressure_colour else: coll = [coll[i] for i in (0, 2, 1)] fc[1] = tension_colour fc[2] = pressure_colour if bb._pure_isotropic: if abs(np.trace(bb._M)) > epsilon: # use the circle as the most upper layer coll = [coll[0]] if bb._plot_clr_order < 0: fc = [tension_colour] else: fc = [pressure_colour] # transform the patches to a path collection and set # the appropriate attributes collection = mpl_collections.PatchCollection(coll, match_original=False) collection.set_facecolors(fc) # Use the given axes to maintain the aspect ratio of beachballs on figure # resize. if axes is not None: # This is what holds the aspect ratio (but breaks the positioning), and # the part that breaks when saving the image to a vector file format collection.set_transform(transforms.IdentityTransform()) # Bring the all patches to the origin (0, 0). for p in collection._paths: p.vertices -= xy # Use the offset property of the collection to position the patches collection.set_offsets(xy) collection._transOffset = axes.transData collection.set_edgecolors(edgecolor) collection.set_alpha(alpha) collection.set_linewidth(linewidth) collection.set_zorder(zorder) return collection