Beispiel #1
0
 def cos_distance(self, strike1, dip1, strike2, dip2):
     """Angular distance betwen the poles of two planes."""
     xyz1 = sph2cart(*mplstereonet.pole(strike1, dip1))
     xyz2 = sph2cart(*mplstereonet.pole(strike2, dip2))
     r1, r2 = np.linalg.norm(xyz1), np.linalg.norm(xyz2)
     dot = np.dot(np.squeeze(xyz1), np.squeeze(xyz2)) / r1 / r2
     return np.abs(np.degrees(np.arccos(dot)))
Beispiel #2
0
 def cos_distance(self, strike1, dip1, strike2, dip2):
     """Angular distance betwen the poles of two planes."""
     xyz1 = sph2cart(*mplstereonet.pole(strike1, dip1))
     xyz2 = sph2cart(*mplstereonet.pole(strike2, dip2))
     r1, r2 = np.linalg.norm(xyz1), np.linalg.norm(xyz2)
     dot = np.dot(np.squeeze(xyz1), np.squeeze(xyz2)) / r1 / r2
     return np.abs(np.degrees(np.arccos(dot)))
def rotate_points(lon, lat, resultant_orien):
    """
    rotate the resultant vector to the north dirction (y-axis), and adjust all the pole according to the resultant vector

    :param lon: array
        original longitude
    :param lat:array
        original latitude
    :param result_v_lon: float
        lon of result vector
    :param result_v_lat: float
        lat of resultant vector
    :return:
    lon_adj: array
        adjusted lon
    lat_adj:
        adjusted lat
    """
    result_v_lon, result_v_lat = mplstereonet.pole(resultant_orien[0],
                                                   resultant_orien[1])
    lon_adj, lat_adj = mplstereonet.stereonet_math._rotate(lon * 180 / np.pi,
                                                           lat * 180 / np.pi,
                                                           -result_v_lon *
                                                           180 / np.pi,
                                                           axis='z')
    lon_adj, lat_adj = mplstereonet.stereonet_math._rotate(
        lon_adj * 180 / np.pi,
        lat_adj * 180 / np.pi,
        90 - result_v_lat * 180 / np.pi,
        axis='y')
    return lon_adj, lat_adj
Beispiel #4
0
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
Beispiel #5
0
 def compare_strikedip(self, strike1, dip1, strike2, dip2):
     """Avoids ambiguities in strike/dip convention when dip is 0 or 90."""
     convert = lambda a, b: sph2cart(*mplstereonet.pole(a, b))
     x1, y1, z1 = convert(strike1, dip1)
     x2, y2, z2 = convert(strike2, dip2)
     rtol, atol = 1e-7, 1e-7
     try:
         assert np.allclose([x1, y1, z1], [x2, y2, z2], rtol, atol)
     except AssertionError:
         # Antipode is also acceptable in this case....
         assert np.allclose([x1, y1, z1], [-x2, -y2, -z2], rtol, atol)
Beispiel #6
0
 def compare_strikedip(self, strike1, dip1, strike2, dip2):
     """Avoids ambiguities in strike/dip convention when dip is 0 or 90."""
     convert = lambda a, b: sph2cart(*mplstereonet.pole(a, b))
     x1, y1, z1 = convert(strike1, dip1)
     x2, y2, z2 = convert(strike2, dip2)
     rtol, atol = 1e-7, 1e-7
     try:
         assert np.allclose([x1, y1, z1], [x2, y2, z2], rtol, atol)
     except AssertionError:
         # Antipode is also acceptable in this case....
         assert np.allclose([x1, y1, z1], [-x2, -y2, -z2], rtol, atol)
Beispiel #7
0
 def test_fit_pole_noisy(self):
     np.random.seed(1)
     for strike in range(0, 370, 10):
         for dip in range(0, 100, 10):
             lon, lat = mplstereonet.pole(strike, dip)
             lon = lon + np.radians(np.random.normal(0, 1, 100))
             lat = lat + np.radians(np.random.normal(0, 1, 100))
             s_noisy, d_noisy = mplstereonet.geographic2pole(lon, lat)
             s, d = mplstereonet.fit_pole(s_noisy, d_noisy)
             ang_dist = self.cos_distance(strike, dip, s, d)
             assert ang_dist < 2 or (180 - ang_dist) < 2
Beispiel #8
0
 def test_fit_pole_noisy(self):
     np.random.seed(1)
     for strike in range(0, 370, 10):
         for dip in range(0, 100, 10):
             lon, lat = mplstereonet.pole(strike, dip)
             lon = lon + np.radians(np.random.normal(0, 1, 100))
             lat = lat + np.radians(np.random.normal(0, 1, 100))
             s_noisy, d_noisy = mplstereonet.geographic2pole(lon, lat)
             s, d = mplstereonet.fit_pole(s_noisy, d_noisy)
             ang_dist = self.cos_distance(strike, dip, s, d)
             assert ang_dist < 2 or (180 - ang_dist) < 2
def main():
    # Display the data with a polar grid
    ax1 = basic()
    ax1.grid(kind='polar')
    ax1.set_title('Polar overlay on a Stereonet', y=1.1)

    # Display the data with a grid centered on the pole to the plotted plane.
    ax2 = basic()
    ax2.grid(center=mplstereonet.pole(315, 30))
    ax2.set_title('Arbitrary overlay on a Stereonet', y=1.1)

    plt.show()
Beispiel #10
0
    def fitfold(self):
        strike, dip = self.get_strike_dip()
                # discards the old graph
        self.ax.hold(True)
        fit_strike,fit_dip = mplstereonet.fit_girdle(strike,dip)
        lon, lat = mplstereonet.pole(fit_strike, fit_dip)
        (plunge,), (bearing,) = mplstereonet.pole2plunge_bearing(fit_strike, fit_dip)       
        template = u'Plunge / Direction of Fold Axis\n{:02.0f}\u00b0/{:03.0f}\u00b0'
        self.ax.annotate(template.format(plunge, bearing), ha='center', va='bottom',
            xy=(lon, lat), xytext=(-50, 20), textcoords='offset points',
            arrowprops=dict(arrowstyle='-|>', facecolor='black'))

        self.ax.plane(fit_strike, fit_dip, color='red', lw=2)
        self.ax.pole(fit_strike, fit_dip, marker='o', color='red', markersize=14)
        self.canvas.draw() 
def fisher_pdf(orientation, kappa, resultant_orien):
    """
    calculate the pdf of orientation

    :param orientation:
        -arraylike (strike, dip) in degree
    :param kappa:
        -fisher constant
    :param resultant_orien:
        resultant orientation
    :return: float arraylike
    """
    lon, lat = mplstereonet.pole(orientation[0], orientation[1])
    lon_adj, lat_adj = rotate_points(lon, lat, resultant_orien)
    lat_adj = lat_adj * np.pi / 180
    f = kappa * np.sin(lat_adj) * np.exp(
        kappa * np.cos(lat_adj)) / (2 * np.pi * (np.exp(kappa) - 1))
    return f
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
Beispiel #13
0
    def fitfold(self):
        strike = []
        dip = []
        for f in self.layer.selectedFeatures():
            dip.append(f['dip']) #self.dip_combo.currentText()])
            strike.append(f['strike'])#self.strike_combo.currentText()]) 
        # discards the old graph
        self.ax.hold(True)
        fit_strike,fit_dip = mplstereonet.fit_girdle(strike,dip)
        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'
        self.ax.annotate(template.format(plunge, bearing), ha='center', va='bottom',
            xy=(lon, lat), xytext=(-50, 20), textcoords='offset points',
            arrowprops=dict(arrowstyle='-|>', facecolor='black'))

        print fit_strike, fit_dip
        self.ax.plane(fit_strike, fit_dip, color='red', lw=2)
        self.ax.pole(fit_strike, fit_dip, marker='o', color='red', markersize=14)
        self.canvas.draw() 
def rotate_points_back(lon, lat, resultant_orien):
    """
    rotate the simulated vectors back to restore them

    :param lon:
    :param lat:
    :param mean_vector_lon:
    :param mean_vector_lat:
    :return:
    """
    result_v_lon, result_v_lat = mplstereonet.pole(resultant_orien[0],
                                                   resultant_orien[1])
    lon_adj, lat_adj = mplstereonet.stereonet_math._rotate(lon * 180 / np.pi,
                                                           lat * 180 / np.pi,
                                                           result_v_lon * 180 /
                                                           np.pi,
                                                           axis='z')
    lon_adj, lat_adj = mplstereonet.stereonet_math._rotate(
        lon_adj * 180 / np.pi,
        lat_adj * 180 / np.pi,
        result_v_lat * 180 / np.pi - 90,
        axis='y')
    return lon_adj, lat_adj
Beispiel #15
0
                   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)

# Fit a girdle to the two modes
# The pole of this plane will be the plunge of the fold axis
axis_s, axis_d = mplstereonet.fit_girdle(*zip(*centers), measurement='radians')
ax.plane(axis_s, axis_d, color='green')
ax.pole(axis_s, axis_d, color='green', marker='o', ms=15)

# Now we'll find the midpoint. We could project the centers as rakes on the
# plane we just fit, but it's easier to get their mean vector instead.
mid, _ = mplstereonet.find_mean_vector(*zip(*centers), measurement='radians')
midx, midy = mplstereonet.line(*mid)

# Now let's find the axial plane by fitting another girdle to the midpoint
# and the pole of the plunge axis.
xp, yp = mplstereonet.pole(axis_s, axis_d)

x, y = [xp, midx], [yp, midy]
axial_s, axial_dip = mplstereonet.fit_girdle(x, y, measurement='radians')

ax.plane(axial_s, axial_dip, color='lightblue', lw=3)

plt.show()
Beispiel #16
0
"""
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.
"""
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()


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()
# scatter_3d(fig, p_x, p_y, p_z)
# # project rotated vectors on the sphere
# p_x, p_y, p_z = mplstereonet.stereonet2xyz(lon_adj, lat_adj)
# scatter_3d(fig, p_x, p_y, p_z)

# simulate 100 samples, and project original vectors and simulated vectors on a stereonet
sampling_strike, sampling_dip = fisher_rvs(kappa, 100, resultant_orien)
fig = plt.figure()
ax = fig.add_subplot(111, projection='stereonet')
ax.pole(strike, dip, 'g^', markersize=6)
ax.pole(sampling_strike, sampling_dip, 'r^', markersize=6)
ax.grid()
plt.show()

# simulate 100 samples, and project both simulated vectors and original vectors on a sphere
sampling_lon, sampling_lat = fisher_rvs(kappa,
                                        100,
                                        resultant_orien,
                                        form='geographic')
# calculate the lon and lat of original vectors
lon, lat = mplstereonet.pole(strike, dip)
fig = plt.figure()
fig = Axes3D(fig)
p_x, p_y, p_z = mplstereonet.stereonet2xyz(sampling_lon, sampling_lat)
scatter_3d(fig, p_x, p_y, p_z)
p_x, p_y, p_z = mplstereonet.stereonet2xyz(lon, lat)
scatter_3d(fig, p_x, p_y, p_z)

# calculate the pdf of (strike, dip)
pdf = fisher_pdf((strike, dip), kappa, resultant_orien)
Beispiel #19
0
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()
Beispiel #20
0
                   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)
Beispiel #21
0
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)

# Fit a girdle to the two modes
# The pole of this plane will be the plunge of the fold axis
axis_s, axis_d = mplstereonet.fit_girdle(*zip(*centers), measurement='radians')
ax.plane(axis_s, axis_d, color='green')
ax.pole(axis_s, axis_d, color='green', marker='o', ms=15)

# Now we'll find the midpoint. We could project the centers as rakes on the
# plane we just fit, but it's easier to get their mean vector instead.
mid, _ = mplstereonet.find_mean_vector(*zip(*centers), measurement='radians')
midx, midy = mplstereonet.line(*mid)

# Now let's find the axial plane by fitting another girdle to the midpoint
# and the pole of the plunge axis.
xp, yp = mplstereonet.pole(axis_s, axis_d)

x, y = [xp[0], midx], [yp[0], midy]
axial_s, axial_dip = mplstereonet.fit_girdle(x, y, measurement='radians')

ax.plane(axial_s, axial_dip, color='lightblue', lw=3)

plt.show()
# 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()