### Local installation from source Source: https://mplstereonet.readthedocs.io/en/latest/index.html Installs mplstereonet locally from the source code. ```bash python setup.py install ``` -------------------------------- ### Installation with pip Source: https://mplstereonet.readthedocs.io/en/latest/index.html Installs the mplstereonet package using pip. ```bash pip install mplstereonet ``` -------------------------------- ### Development installation Source: https://mplstereonet.readthedocs.io/en/latest/index.html Sets up a development installation of mplstereonet, reflecting local changes. ```bash python setup.py develop ``` -------------------------------- ### Parse Plunge Bearing Example Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html Example demonstrating how to parse plunge and bearing values. ```python >>> parse_plunge_bearing("30NW", 160) ... (30, 340) ``` -------------------------------- ### Basic Usage Example Source: https://mplstereonet.readthedocs.io/en/latest/index.html Demonstrates basic usage of mplstereonet by plotting a plane, pole, and rake, and showing a grid. ```python import matplotlib.pyplot as plt import mplstereonet fig = plt.figure() ax = fig.add_subplot(111, projection='stereonet') strike, dip = 315, 30 ax.plane(strike, dip, 'g-', linewidth=2) ax.pole(strike, dip, 'g^', markersize=18) ax.rake(strike, dip, -25) ax.grid() plt.show() ``` -------------------------------- ### Parsing Example Source: https://mplstereonet.readthedocs.io/en/latest/index.html Illustrates parsing structural measurements in quadrant or azimuth form using mplstereonet utilities. ```python Parse quadrant azimuth measurements "N30E" --> 30.0 "E30N" --> 60.0 "W10S" --> 260.0 "N 10 W" --> 350.0 Parse quadrant strike/dip measurements. Note that the output follows the right-hand-rule. "215/10" --> Strike: 215.0, Dip: 10.0 "215/10E" --> Strike: 35.0, Dip: 10.0 "215/10NW" --> Strike: 215.0, Dip: 10.0 "N30E/45NW" --> Strike: 210.0, Dip: 45.0 "E10N 20 N" --> Strike: 260.0, Dip: 20.0 "W30N/46.7 S" --> Strike: 120.0, Dip: 46.7 Similarly, you can parse rake measurements that don't follow the RHR. "N30E/45NW 10NE" --> Strike: 210.0, Dip: 45.0, Rake: 170.0 "210 45 30N" --> Strike: 210.0, Dip: 45.0, Rake: 150.0 "N30E/45NW raking 10SW" --> Strike: 210.0, Dip: 45.0, Rake: 10.0 ``` -------------------------------- ### Grid Line Properties Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html Example of defining line properties for the grid using keyword arguments. ```python grid(color='r', linestyle='-', linewidth=2) ``` -------------------------------- ### Fault Slip Plot Example Source: https://mplstereonet.readthedocs.io/en/latest/examples/fault_slip_plot.html Demonstrates plotting fault slip data using both the fault-and-striae and tangent lineation methods with mplstereonet. ```python import matplotlib.pyplot as plt import numpy as np import mplstereonet import parse_angelier_data def main(): # Load data from Angelier, 1979 strikes, dips, rakes = parse_angelier_data.load() params = dict(projection='stereonet', azimuth_ticks=[]) fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw=params) fault_and_striae_plot(ax1, strikes, dips, rakes) ax1.set_title('Fault-and-Striae Diagram') ax1.set_xlabel('Lineation direction plotted\nat rake location on plane') tangent_lineation_plot(ax2, strikes, dips, rakes) ax2.set_title('Tangent Lineation Diagram') ax2.set_xlabel('Lineation direction plotted\nat pole location of plane') fig.suptitle('Fault-slip data from Angelier, 1979', y=0.05) fig.tight_layout() plt.show() def fault_and_striae_plot(ax, strikes, dips, rakes): """Makes a fault-and-striae plot (a.k.a. "Ball of String") for normal faults with the given strikes, dips, and rakes.""" # Plot the planes lines = ax.plane(strikes, dips, 'k-', lw=0.5) # Calculate the position of the rake of the lineations, but don't plot yet x, y = mplstereonet.rake(strikes, dips, rakes) # Calculate the direction the arrows should point # These are all normal faults, so the arrows point away from the center # For thrusts, it would just be u, v = -x/mag, -y/mag mag = np.hypot(x, y) u, v = x / mag, y / mag # Plot the arrows at the rake locations... arrows = ax.quiver(x, y, u, v, width=1, headwidth=4, units='dots') return lines, arrows def tangent_lineation_plot(ax, strikes, dips, rakes): """Makes a tangent lineation plot for normal faults with the given strikes, dips, and rakes.""" # Calculate the position of the rake of the lineations, but don't plot yet rake_x, rake_y = mplstereonet.rake(strikes, dips, rakes) # Calculate the direction the arrows should point # These are all normal faults, so the arrows point away from the center # Because we're plotting at the pole location, however, we need to flip this # from what we plotted with the "ball of string" plot. mag = np.hypot(rake_x, rake_y) u, v = -rake_x / mag, -rake_y / mag # Calculate the position of the poles pole_x, pole_y = mplstereonet.pole(strikes, dips) # Plot the arrows centered on the pole locations... arrows = ax.quiver(pole_x, pole_y, u, v, width=1, headwidth=4, units='dots', pivot='middle') return arrows if __name__ == '__main__': main() ``` -------------------------------- ### `basic.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/basic.html As an example of basic functionality, let's plot a plane, the pole to the plane, and a rake along the plane. ```python import matplotlib.pyplot as plt import mplstereonet fig = plt.figure() ax = fig.add_subplot(111, projection='stereonet') # Measurements follow the right-hand-rule to indicate dip direction strike, dip = 315, 30 ax.plane(strike, dip, 'g-', linewidth=2) ax.pole(strike, dip, 'g^', markersize=18) ax.rake(strike, dip, -25) ax.grid() plt.show() ``` -------------------------------- ### `rotation_example.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/rotation_example.html This example demonstrates plotting a plane, its pole, and a rake along the plane using mplstereonet. It shows how to plot on both un-rotated and rotated stereonet axes. ```python import matplotlib.pyplot as plt import mplstereonet fig = plt.figure() # An un-rotated axes ax1 = fig.add_subplot(121, projection='stereonet') # Rotated 30 degrees clockwise from North ax2 = fig.add_subplot(122, projection='stereonet', rotation=30) # Measurements follow the right-hand-rule to indicate dip direction strike, dip = 315, 30 # Plot the same data on both axes for ax in [ax1, ax2]: ax.plane(strike, dip, 'g-', linewidth=2) ax.pole(strike, dip, 'g^', markersize=18) ax.rake(strike, dip, -25) ax.grid() plt.show() ``` -------------------------------- ### Density Contouring Example Source: https://mplstereonet.readthedocs.io/en/latest/index.html Shows how to create density contour plots using mplstereonet, including plotting poles and adding a color bar. ```python import matplotlib.pyplot as plt import numpy as np import mplstereonet fig, ax = mplstereonet.subplots() strike, dip = 90, 80 num = 10 strikes = strike + 10 * np.random.randn(num) dips = dip + 10 * np.random.randn(num) cax = ax.density_contourf(strikes, dips, measurement='poles') ax.pole(strikes, dips) ax.grid(True) fig.colorbar(cax) plt.show() ``` -------------------------------- ### Parsing Example Source: https://mplstereonet.readthedocs.io/en/latest/examples/parsing_example.html Demonstrates parsing of quadrant azimuth, strike/dip, and rake measurements using mplstereonet functions. It shows how to handle measurements that may not strictly follow the right-hand-rule. ```python import mplstereonet print('Parse quadrant azimuth measurements') for original in ['N30E', 'E30N', 'W10S', 'N 10 W']: azi = mplstereonet.parse_quadrant_measurement(original) print('"{}" --> {:.1f}'.format(original, azi)) print('\nParse quadrant strike/dip measurements.') print('Note that the output follows the right-hand-rule.') def parse_sd(original, seperator): strike, dip = mplstereonet.parse_strike_dip(*original.split(seperator)) print('"{}" --> Strike: {:.1f}, Dip: {:.1f}'.format(original, strike, dip)) parse_sd('215/10', '/') parse_sd('215/10E', '/') parse_sd('215/10NW', '/') parse_sd('N30E/45NW', '/') parse_sd('E10N\t20 N', '\t') parse_sd('W30N/46.7 S', '/') print("\nSimilarly, you can parse rake measurements that don't follow the RHR.") def split_rake(original, sep1=None, sep2=None): components = original.split(sep1) if len(components) == 3: return components strike, rest = components dip, rake = rest.split(sep2) return strike, dip, rake def display_rake(original, sep1, sep2=None): components = split_rake(original, sep1, sep2) strike, dip, rake = mplstereonet.parse_rake(*components) template = '"{}" --> Strike: {:.1f}, Dip: {:.1f}, Rake: {:.1f}' print(template.format(original, strike, dip, rake)) original = 'N30E/45NW 10NE' display_rake(original, '/') original = '210 45\t30N' display_rake(original, None) original = 'N30E/45NW raking 10SW' display_rake(original, '/', 'raking') ``` -------------------------------- ### Find the average strike/dip of a series of bedding measurements Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html Example showing how to find the average strike and dip from a series of bedding measurements using the fit_pole function. ```python >>> strike = [270, 65, 280, 300] >>> dip = [20, 15, 10, 5] >>> strike0, dip0 = mplstereonet.fit_pole(strike, dip) ``` -------------------------------- ### `contouring.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/contouring.html A basic example of producing a density contour plot of poles to planes. ```python import matplotlib.pyplot as plt import numpy as np import mplstereonet # Fix random seed so that output is consistent np.random.seed(1977) fig, ax = mplstereonet.subplots() # Generate a random scatter of planes around the given plane # All measurements follow the right-hand-rule to indicate dip direction strike, dip = 90, 80 num = 10 strikes = strike + 10 * np.random.randn(num) dips = dip + 10 * np.random.randn(num) # Create filled contours of the poles of the generated planes... # By default this uses a modified Kamb contouring technique with exponential # smoothing (See Vollmer, 1995) cax = ax.density_contourf(strikes, dips, measurement='poles') # Plot the poles as points on top of the contours ax.pole(strikes, dips) # Turn on a grid and add a colorbar ax.grid(True) fig.colorbar(cax) plt.show() ``` -------------------------------- ### dip_direction2strike function example Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/utilities.html Provides an example of dip_direction2strike, which converts a dip direction measurement (azimuth convention) into a strike measurement (right-hand-rule convention). ```python def dip_direction2strike(azimuth): """ Converts a planar measurment of dip direction using the dip-azimuth convention into a strike using the right-hand-rule. Parameters ---------- azimuth : number or string The dip direction of the plane in degrees. This can be either a numerical azimuth in the 0-360 range or a string representing a quadrant measurement (e.g. N30W). Returns ------- strike : number The strike of the plane in degrees following the right-hand-rule. """ azimuth = parse_azimuth(azimuth) strike = azimuth - 90 if strike < 0: strike += 360 return strike ``` -------------------------------- ### Calculate the plunge of a cylindrical fold axis Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html Example demonstrating how to calculate the plunge of a cylindrical fold axis from strike and dip measurements of bedding. ```python >>> strike = [270, 334, 270, 270] >>> dip = [20, 15, 80, 78] >>> s, d = mplstereonet.fit_girdle(strike, dip) >>> plunge, bearing = mplstereonet.pole2plunge_bearing(s, d) ``` -------------------------------- ### Plot filled density contours of a set of rake measurements. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example illustrates plotting filled density contours for rake measurements. ```python >>> strikes, dips, rakes = [120, 315, 86], [22, 85, 31], [-5, 20, 9] >>> ax.density_contourf(strikes, dips, rakes, measurement='rakes') ``` -------------------------------- ### Plot filled density contours of a set of linear orientation measurements. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example shows how to plot filled density contours for linear orientation measurements. ```python >>> plunges, bearings = [-10, 20, -30], [120, 315, 86] >>> ax.density_contourf(plunges, bearings, measurement='lines') ``` -------------------------------- ### Plot density contours of a set of rake measurements. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example illustrates plotting density contours for rake measurements, requiring strikes, dips, and rakes as input. ```python >>> strikes, dips, rakes = [120, 315, 86], [22, 85, 31], [-5, 20, 9] >>> ax.density_contour(strikes, dips, rakes, measurement='rakes') ``` -------------------------------- ### `fit_girdle_example.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/fit_girdle_example.html Illustrates fitting a plane to a “gridle” distribution using `fit_girdle`. This example simulates finding the plunge and bearing of a cylindrical fold axis from strike/dip measurements of bedding in the fold limbs. ```python import numpy as np import matplotlib.pyplot as plt import mplstereonet np.random.seed(1) # Generate a random girdle distribution from the plunge/bearing of a fold hinge # In the end, we'll have strikes and dips as measured from bedding in the fold. # *strike* and *dip* below would normally be your input. num_points = 200 real_bearing, real_plunge = 300, 5 s, d = mplstereonet.plunge_bearing2pole(real_plunge, real_bearing) lon, lat = mplstereonet.plane(s, d, segments=num_points) lon += np.random.normal(0, np.radians(15), lon.shape) lat += np.random.normal(0, np.radians(15), lat.shape) strike, dip = mplstereonet.geographic2pole(lon, lat) # Plot the raw data and contour it: fig, ax = mplstereonet.subplots() ax.density_contourf(strike, dip, cmap='gist_earth') ax.density_contour(strike, dip, colors='black') ax.pole(strike, dip, marker='.', color='black') # Fit a plane to the girdle of the distribution and display it. fit_strike, fit_dip = mplstereonet.fit_girdle(strike, dip) ax.plane(fit_strike, fit_dip, color='red', lw=2) ax.pole(fit_strike, fit_dip, marker='o', color='red', markersize=14) # Add some annotation of the result lon, lat = mplstereonet.pole(fit_strike, fit_dip) (plunge,), (bearing,) = mplstereonet.pole2plunge_bearing(fit_strike, fit_dip) template = u'P/B of Fold Axis\n{:02.0f}\u00b0/{:03.0f}\u00b0' ax.annotate(template.format(plunge, bearing), ha='center', va='bottom', xy=(lon, lat), xytext=(-50, 20), textcoords='offset points', arrowprops=dict(arrowstyle='-|>', facecolor='black')) plt.show() ``` -------------------------------- ### `fisher_stats.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/fisher_stats.html This example shows how the Fisher statistics can be computed and displayed. It includes plotting the data, calculating Fisher statistics, and displaying the mean vector and confidence cone. ```python import matplotlib.pyplot as plt import mplstereonet as mpl decl = [122.5, 130.5, 132.5, 148.5, 140.0, 133.0, 157.5, 153.0, 140.0, 147.5, 142.0, 163.5, 141.0, 156.0, 139.5, 153.5, 151.5, 147.5, 141.0, 143.5, 131.5, 147.5, 147.0, 149.0, 144.0, 139.5] incl = [55.5, 58.0, 44.0, 56.0, 63.0, 64.5, 53.0, 44.5, 61.5, 54.5, 51.0, 56.0, 59.5, 56.5, 54.0, 47.5, 61.0, 58.5, 57.0, 67.5, 62.5, 63.5, 55.5, 62.0, 53.5, 58.0] confidence = 95 fig = plt.figure() ax = fig.add_subplot(111, projection='stereonet') ax.line(incl, decl, color="black", markersize=2) vector, stats = mpl.find_fisher_stats(incl, decl, conf=confidence) template = (u"Mean Vector P/B: {plunge:0.0f}\\u00B0/{bearing:0.0f}\\u00B0\n" "Confidence: {conf}%\n" u"Fisher Angle: {fisher:0.2f}\\u00B0\n" u"R-Value {r:0.3f}\n" "K-Value: {k:0.2f}") label = template.format(plunge=vector[0], bearing=vector[1], conf=confidence, r=stats[0], fisher=stats[1], k=stats[2]) ax.line(vector[0], vector[1], color="red", label=label) ax.cone(vector[0], vector[1], stats[1], facecolor="None", edgecolor="red") ax.legend(bbox_to_anchor=(1.1, 1.1), numpoints=1) plt.show() ``` -------------------------------- ### Plot density contours of a set of linear orientation measurements. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example shows how to plot density contours for linear orientation measurements, specifying 'lines' as the measurement type. ```python >>> plunges, bearings = [-10, 20, -30], [120, 315, 86] >>> ax.density_contour(plunges, bearings, measurement='lines') ``` -------------------------------- ### Plot density contours of poles to planes with contours at [1,2,3] standard deviations. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting density contours with specified contour levels representing standard deviations. ```python >>> strikes, dips = [120, 315, 86], [22, 85, 31] >>> ax.density_contour(strikes, dips, levels=[1,2,3]) ``` -------------------------------- ### Plot filled density contours of poles to planes using a Kamb method with the density estimated on a 10x10 grid. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example shows plotting filled density contours with a specified Kamb method and grid size. ```python >>> strikes, dips = [120, 315, 86], [22, 85, 31] >>> ax.density_contourf(strikes, dips, method='kamb', gridsize=10) ``` -------------------------------- ### Find the eigenvectors as plunge/bearing and eigenvalues of the 3D covariance matrix of a series of planar measurements Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates how to use the `mplstereonet.eigenvectors` function to calculate eigenvectors and eigenvalues from strike and dip data. ```python >>> strikes = [270, 65, 280, 300] >>> dips = [20, 15, 10, 5] >>> plu, azi, vals = mplstereonet.eigenvectors(strikes, dips) ``` -------------------------------- ### Plot filled density contours of poles to planes with contours at specified standard deviations. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting filled density contours with custom contour levels defined by standard deviations. ```python >>> strikes, dips = [120, 315, 86], [22, 85, 31] >>> ax.density_contourf(strikes, dips, levels=[1,2,3]) ``` -------------------------------- ### Cross Section Plane Example Source: https://mplstereonet.readthedocs.io/en/latest/examples/cross_section_plane.html Plots two planes as great circles and poles, calculates the best fitting plane using `fit_girdle`, and visualizes the results. ```python import matplotlib.pyplot as plt import numpy as np import mplstereonet fig, ax = mplstereonet.subplots() dip_directions = [100, 200] dips = [30, 40] strikes = np.array(dip_directions) - 90 ax.pole(strikes, dips, "bo") ax.plane(strikes, dips, color='black', lw=1) fit_strike, fit_dip = mplstereonet.fit_girdle(strikes, dips) ax.plane(fit_strike, fit_dip, color='red', lw=1) ax.pole(fit_strike, fit_dip, marker='o', color='red', markersize=5) plt.show() ``` -------------------------------- ### parse_strike_dip function example Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/utilities.html Demonstrates how parse_strike_dip converts string inputs for strike and dip into numerical azimuth and dip values, following the right-hand-rule. ```python import numpy as np import re from . import stereonet_math as smath def parse_strike_dip(strike, dip): """ Parses strings of strike and dip and returns strike and dip measurements following the right-hand-rule. Dip directions are parsed, and if the measurement does not follow the right-hand-rule, the opposite end of the strike measurement is returned. Accepts either quadrant-formatted or azimuth-formatted strikes. For example, this would convert a strike of "N30E" and a dip of "45NW" to a strike of 210 and a dip of 45. Parameters ---------- strike : string A strike measurement. May be in azimuth or quadrant format. dip : string The dip angle and direction of a plane. Returns ------- azi : float Azimuth in degrees of the strike of the plane with dip direction indicated following the right-hand-rule. dip : float Dip of the plane in degrees. """ strike = parse_azimuth(strike) dip, direction = split_trailing_letters(dip) if direction is not None: expected_direc = strike + 90 if opposite_end(expected_direc, direction): strike += 180 if strike > 360: strike -= 360 return strike, dip ``` -------------------------------- ### Plot density contours of poles to the specified planes using a modified Kamb method with exponential smoothing [1]. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting density contours of poles to planes using the default exponential Kamb method. ```python >>> strikes, dips = [120, 315, 86], [22, 85, 31] >>> ax.density_contour(strikes, dips) ``` -------------------------------- ### Plot density contours of a set of “raw” longitudes and latitudes. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting density contours using raw longitude and latitude data, specifying 'radians' as the measurement type. ```python >>> lon, lat = np.radians([-40, 30, -85]), np.radians([21, -59, 45]) >>> ax.density_contour(lon, lat, measurement='radians') ``` -------------------------------- ### parse_plunge_bearing function example Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/utilities.html Shows how parse_plunge_bearing processes plunge and bearing string inputs into consistent float values, ensuring plunge angles are between 0 and 90 degrees. ```python def parse_plunge_bearing(plunge, bearing): """ Parses strings of plunge and bearing and returns a consistent plunge and bearing measurement as floats. Plunge angles returned by this function will always be between 0 and 90. If no direction letter(s) is present, the plunge is assumed to be measured from the end specified by the bearing. If a direction letter(s) is present, the bearing will be switched to the opposite (180 degrees) end if the specified direction corresponds to the opposite end specified by the bearing. Parameters ---------- plunge : string A plunge measurement. bearing : string A bearing measurement. May be in azimuth or quadrant format. Returns ------- plunge, bearing: floats The plunge and bearing following the conventions outlined above. Examples --------- >>> parse_plunge_bearing("30NW", 160) ... (30, 340) """ bearing = parse_azimuth(bearing) plunge, direction = split_trailing_letters(plunge) if direction is not None: if opposite_end(bearing, direction): bearing +=180 if plunge < 0: bearing += 180 plunge = -plunge if plunge > 90: bearing += 180 plunge = 180 - plunge if bearing > 360: bearing -= 360 return plunge, bearing ``` -------------------------------- ### Plot filled density contours of a set of “raw” longitudes and latitudes. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting filled density contours for raw longitude and latitude measurements, requiring conversion to radians. ```python >>> lon, lat = np.radians([-40, 30, -85]), np.radians([21, -59, 45]) >>> ax.density_contourf(lon, lat, measurement='radians') ``` -------------------------------- ### angular_distance examples Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_math.html Examples of calculating angular distance between linear features and planes. ```python >>> angle = angular_distance(line(30, 270), line(40, 90)) >>> np.degrees(angle) array([ 70.]) ``` ```python >>> first, second = line(30, 270), line(40, 90) >>> angle = angular_distance(first, second, bidirectional=False) >>> np.degrees(angle) array([ 110.]) ``` ```python >>> angle = angular_distance(pole(0, 10), pole(180, 10)) >>> np.degrees(angle) array([ 20.]) ``` -------------------------------- ### `scatter.py` Source: https://mplstereonet.readthedocs.io/en/latest/examples/scatter.html Example of how ax.scatter can be used to plot linear data on a stereonet varying color and/or size by other variables. This also serves as a general example of how to convert orientation data into the coordinate system that the stereonet plot uses so that generic matplotlib plotting methods may be used. ```python import numpy as np import matplotlib.pyplot as plt import mplstereonet np.random.seed(1) strikes = np.arange(0, 360, 15) dips = 45 * np.ones(strikes.size) magnitude = np.random.random(strikes.size) # Convert our strikes and dips to stereonet coordinates lons, lats = mplstereonet.pole(strikes, dips) # Now we'll plot our data and color by magnitude fig, ax = mplstereonet.subplots() sm = ax.scatter(lons, lats, c=magnitude, s=50, cmap='gist_earth') ax.grid() plt.show() ``` -------------------------------- ### Getting Azimuth Ticks Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html Retrieves the current azimuth tick locations. ```python def get_azimuth_ticks(self, minor=False): return self._polar.get_xticks(minor) ``` -------------------------------- ### Getting Azimuth Tick Labels Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html Retrieves the azimuth tick labels as a list of Text artists. ```python def get_azimuth_ticklabels(self, minor=False): """Get the azimuth tick labels as a list of Text artists.""" return self._polar.get_xticklabels(minor) ``` -------------------------------- ### Plot density contours of a set of rake measurements. Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html This example illustrates plotting density contours for rake measurements. ```python strikes, dips, rakes = [120, 315, 86], [22, 85, 31], [-5, 20, 9] ax.density_contour(strikes, dips, rakes, measurement='rakes') ``` -------------------------------- ### Plot density contours of a set of linear orientation measurements. Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html This example shows how to plot density contours for linear orientation measurements. ```python plunges, bearings = [-10, 20, -30], [120, 315, 86] ax.density_contour(plunges, bearings, measurement='lines') ``` -------------------------------- ### Plot filled density contours of poles to the specified planes using a modified Kamb method with exponential smoothing. Source: https://mplstereonet.readthedocs.io/en/latest/mplstereonet.html This example demonstrates plotting filled density contours for poles to planes using the density_contourf function with default parameters. ```python >>> strikes, dips = [120, 315, 86], [22, 85, 31] >>> ax.density_contourf(strikes, dips) ``` -------------------------------- ### K-means clustering for fault sets Source: https://mplstereonet.readthedocs.io/en/latest/examples/kmeans_example.html This code snippet demonstrates how to use the `mplstereonet.kmeans` function to find the average strike and dip of two conjugate fault sets. It loads data, plots the raw data and contours, identifies the two modes using k-means, and annotates the results on the stereonet plot. ```python import matplotlib.pyplot as plt import mplstereonet import parse_angelier_data # Load data from Angelier, 1979 strike, dip, rake = parse_angelier_data.load() # Plot the raw data and contour it: fig, ax = mplstereonet.subplots() #ax.density_contourf(strike, dip, rake, measurement='rakes', cmap='gist_earth', # sigma=1.5) ax.density_contour(strike, dip, rake, measurement='rakes', cmap='gist_earth', sigma=1.5) ax.rake(strike, dip, rake, marker='.', color='black') # Find the two modes centers = mplstereonet.kmeans(strike, dip, rake, num=2, measurement='rakes') strike_cent, dip_cent = mplstereonet.geographic2pole(*zip(*centers)) ax.pole(strike_cent, dip_cent, 'ro', ms=12) # Label the modes for (x0, y0) in centers: s, d = mplstereonet.geographic2pole(x0, y0) x, y = mplstereonet.pole(s, d) # Otherwise, we may get the antipode... if x > 0: kwargs = dict(xytext=(40, -40), ha='left') else: kwargs = dict(xytext=(-40, 40), ha='right') ax.annotate('{:03.0f}/{:03.0f}'.format(s[0], d[0]), xy=(x, y), xycoords='data', textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='angle3'), **kwargs) ax.set_title('Strike/dip of conjugate fault sets', y=1.07) plt.show() ``` -------------------------------- ### Contour Angellier Data Example Source: https://mplstereonet.readthedocs.io/en/latest/examples/contour_angelier_data.html This code snippet demonstrates how to reproduce Figure 5 from Vollmer, 1995, illustrating different density contouring methods using mplstereonet and parse_angelier_data. ```python import matplotlib.pyplot as plt import mplstereonet import parse_angelier_data def plot(ax, strike, dip, rake, **kwargs): ax.rake(strike, dip, rake, 'ko', markersize=2) ax.density_contour(strike, dip, rake, measurement='rakes', linewidths=1, cmap='jet', **kwargs) # Load data from Angelier, 1979 strike, dip, rake = parse_angelier_data.load() # Setup a subplot grid fig, axes = mplstereonet.subplots(nrows=3, ncols=4) # Hide azimuth tick labels for ax in axes.flat: ax.set_azimuth_ticks([]) contours = [range(2, 18, 2), range(1, 21, 2), range(1, 22, 2)] # "Standard" Kamb contouring with different confidence levels. for sigma, ax, contour in zip([3, 2, 1], axes[:, 0], contours): # We're reducing the gridsize to more closely match a traditional # hand-contouring grid, similar to Kamb's original work and Vollmer's # Figure 5. `gridsize=10` produces a 10x10 grid of density estimates. plot(ax, strike, dip, rake, method='kamb', sigma=sigma, levels=contour, gridsize=10) # Kamb contouring with inverse-linear smoothing (after Vollmer, 1995) for sigma, ax, contour in zip([3, 2, 1], axes[:, 1], contours): plot(ax, strike, dip, rake, method='linear_kamb', sigma=sigma, levels=contour) template = r'$E={}\sigma$ Contours: ${}\sigma,{}\sigma,\ldots$' ax.set_xlabel(template.format(sigma, *contour[:2])) # Kamb contouring with exponential smoothing (after Vollmer, 1995) for sigma, ax, contour in zip([3, 2, 1], axes[:, 2], contours): plot(ax, strike, dip, rake, method='exponential_kamb', sigma=sigma, levels=contour) # Title the different methods methods = ['Kamb', 'Linear\nSmoothing', 'Exponential\nSmoothing'] for ax, title in zip(axes[0, :], methods): ax.set_title(title) # Hide top-right axis... (Need to implement Diggle & Fisher's method) axes[0, -1].set_visible(False) # Schmidt contouring (a.k.a. 1%) plot(axes[1, -1], strike, dip, rake, method='schmidt', gridsize=25, levels=range(3, 20, 3)) axes[1, -1].set_title('Schmidt') axes[1, -1].set_xlabel(r'Contours: $3\%,6\%,\\ldots$') # Raw data. axes[-1, -1].set_azimuth_ticks([]) axes[-1, -1].rake(strike, dip, rake, 'ko', markersize=2) axes[-1, -1].set_xlabel('N={}'.format(len(strike))) plt.show() ``` -------------------------------- ### circmean Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/utilities.html None ```python def circmean(azimuths): azimuths = np.radians(azimuths) x = np.cos(azimuths) y = np.sin(azimuths) return np.degrees(np.arctan2(y.mean(), x.mean())) ``` -------------------------------- ### Plot density contours of poles to planes with contours at [1,2,3] standard deviations. Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html This example demonstrates plotting density contours with specified levels for standard deviations. ```python strikes, dips = [120, 315, 86], [22, 85, 31] ax.density_contour(strikes, dips, levels=[1,2,3]) ``` -------------------------------- ### Stereonet Explanation Source: https://mplstereonet.readthedocs.io/en/latest/examples/stereonet_explanation.html This example illustrates the difference between the internal coordinate system of longitude and latitude and the conceptual coordinate system of a lower-hemisphere stereonet. It sets up a figure with two axes, one for the stereonet projection and one for the native projection, and explains how azimuth and dip relate to longitude and latitude. ```python import matplotlib.pyplot as plt import numpy as np import mplstereonet def main(): fig, (ax1, ax2) = setup_figure() stereonet_projection_explanation(ax1) native_projection_explanation(ax2) plt.show() def setup_figure(): """Setup the figure and axes""" fig, axes = mplstereonet.subplots(ncols=2, figsize=(20,10)) for ax in axes: # Make the grid lines solid. ax.grid(ls='-') # Make the longitude grids continue all the way to the poles ax.set_longitude_grid_ends(90) return fig, axes def stereonet_projection_explanation(ax): """Example to explain azimuth and dip on a lower-hemisphere stereonet.""" ax.set_title('Dip and Azimuth', y=1.1, size=18) # Set the azimuth ticks to be just "N", "E", etc. ax.set_azimuth_ticks(range(0, 360, 10)) # Hackishly set some of the azimuth labels to North, East, etc... fmt = ax.yaxis.get_major_formatter() labels = [fmt(item) for item in ax.get_azimuth_ticks()] labels[0] = 'North' labels[9] = 'East' labels[18] = 'South' labels[27] = 'West' ax.set_azimuth_ticklabels(labels) # Unhide the xticklabels and use them for dip labels ax.xaxis.set_tick_params(label1On=True) labels = list(range(10, 100, 10)) + list(range(80, 0, -10)) ax.set_xticks(np.radians(np.arange(-80, 90, 10))) ax.set_xticklabels([fmt(np.radians(item)) for item in labels]) ax.set_xlabel('Dip or Plunge') xlabel_halo(ax) return ax def native_projection_explanation(ax): """Example showing how the "native" longitude and latitude relate to the stereonet projection.""" ax.set_title('Longitude and Latitude', size=18, y=1.1) # Hide the azimuth labels ax.set_azimuth_ticklabels([]) # Make the axis tick labels visible: ax.set_xticks(np.radians(np.arange(-80, 90, 10))) ax.tick_params(label1On=True) ax.set_xlabel('Longitude') xlabel_halo(ax) return ax def xlabel_halo(ax): """Add a white "halo" around the xlabels.""" import matplotlib.patheffects as effects for tick in ax.get_xticklabels() + [ax.xaxis.label]: tick.set_path_effects([effects.withStroke(linewidth=4, foreground='w')]) if __name__ == '__main__': main() ``` -------------------------------- ### Plot density contours of a set of "raw" longitudes and latitudes. Source: https://mplstereonet.readthedocs.io/en/latest/_modules/mplstereonet/stereonet_axes.html This example demonstrates plotting density contours for raw longitude and latitude measurements. ```python lon, lat = np.radians([-40, 30, -85]), np.radians([21, -59, 45]) ax.density_contour(lon, lat, measurement='radians') ```