def test_offset_back_to_rake(self): for strike, dip, rake in self.data: # Displace the line perpendicular to the plane... line = smath.sph2cart(*smath.rake(strike, dip, rake)) norm = smath.sph2cart(*smath.pole(strike, dip)) line = np.array(line) + 0.5 * np.array(norm) # Project the "displaced" line back onto the plane... lon, lat = smath.cart2sph(*line) plunge, bearing = smath.geographic2plunge_bearing(lon, lat) newrake = smath.project_onto_plane(strike, dip, plunge, bearing) assert np.allclose(rake, newrake)
def __init__(self, strike, dip, rake, *angular_errors, **kwargs): _trans_arr = N.array([-1, -1, 1]) def vec(latlon): lat, lon = latlon _ = M.sph2cart(lat, lon) val = N.array(_).flatten() val = N.roll(val,-1) return val * _trans_arr normal_error = kwargs.pop('normal_error',1) self.__strike = strike self.__dip = dip self.__angular_errors = angular_errors self.__rake = rake errors = N.radians(angular_errors)/2 pole = M.pole(strike, dip) # Uncertain why we have to do this to get a normal vector # but it has something to do with the stereonet coordinate # system relative to the normal self.normal = vec(pole) ll = M.rake(strike, dip, rake) max_angle = vec(ll) min_angle = N.cross(self.normal, max_angle) # These axes have the correct length but need to be # rotated into the correct reference frame. ax = N.vstack((min_angle, max_angle, self.normal)) # Apply right-hand rule #ax[0:],ax[1:] #T = N.eye(3) #T[:-1,:-1] = rotate_2D(N.radians(rake)) T = transform(ax[0],max_angle) self.axes = ax if self.axes[-1,-1] < 0: self.axes *= -1 lengths = normal_error/N.tan(errors[::-1]) self.hyperbolic_axes = N.array(list(lengths)+[normal_error]) self.covariance_matrix = N.diag(self.hyperbolic_axes)
def test_roundtrip(self): for strike in range(0, 370, 10): for dip in range(0, 100, 10): lon, lat = smath.pole(strike, dip) lon2, lat2 = smath.antipode(*smath.antipode(lon, lat)) compare_lonlat(lon, lat, lon2, lat2)
def test_geographic2pole(self): for (strike, dip) in self.strike_dip: lon, lat = smath.pole(strike, dip) assert np.allclose(smath.geographic2pole(lon, lat), [[strike], [dip]])
def stereoplot( Dip, DipDirection, FrictionAngle, figsize, ): """ Plot histograms with best fit probability density functions :param list Dip: list containing Dip angles :param list DipDirection: list containing Dip Directions :param tuple(float,float) figsize: figure size width,height """ # Figure settings plt.rcParams.update({'font.size': 12}) matplotlib.style.use('seaborn-whitegrid') fig = plt.figure(figsize=figsize, dpi=100, facecolor='w', edgecolor='k') ax = fig.add_subplot(111, projection='stereonet') # Convert dip to strike strikes = [dipdir2strike(x) for x in DipDirection] colours = ['r', 'g', 'b'] i = 0 # Set what the pole markers look like for x, y in zip(strikes, Dip): ax.pole(x, y, color=colours[i], marker='D', markersize=10, alpha=1, zorder=5) ax.plane(x, y, color=colours[i], linewidth=2) ax.rake(x, y, 90, color=colours[i], marker='o', markersize=10, alpha=1, zorder=5) i = i + 1 # Plane intersections plunge, bearing = plane_intersection([strikes[0], strikes[0], strikes[1]], [Dip[0], Dip[0], Dip[1]], [strikes[1], strikes[2], strikes[2]], [Dip[1], Dip[2], Dip[2]]) plunge = [x for x in plunge] bearing = [x for x in bearing] ax.line(plunge, bearing, color='k', marker='o', markersize='10') # Convert plane intersections as poles (strike/dip) int_strike, int_dip = plunge_bearing2pole(plunge, bearing) int_strike = [x for x in int_strike] int_dip = [x - 0.001 for x in int_dip] joint_strikes = [x + 180 for x in strikes] joint_dips = [90 - x for x in Dip] point_strikes = joint_strikes + int_strike point_dips = joint_dips + int_dip real_dips = Dip + plunge # Wedge Shaded area intersects = [[0, 1], [0, 2], [1, 2]] j_inside_strikes = [] j_inside_dips = [] for joint, intersect in enumerate(intersects): j_plane = plane(strikes[joint], Dip[joint]) j_plane = np.vstack((j_plane[0].T, j_plane[1].T)) j_plane_poles = geographic2pole(j_plane[0], j_plane[1]) int1 = int_strike[intersect[0]] int2 = int_strike[intersect[1]] int_diff = int1 - int2 if int_diff >= -180 and int_diff < 0 or int_diff > 180: ints_ordered = [int1, int2] elif int_diff <= 180 and int_diff > 0 or int_diff < -180: ints_ordered = [int2, int1] j_inside_strike = [] j_inside_dip = [] for i, x in enumerate(j_plane_poles[0]): if ang_between(x, ints_ordered[0], ints_ordered[1]): j_inside_strike.append(j_plane_poles[0][i]) j_inside_dip.append(j_plane_poles[1][i]) j_inside_strikes.append(j_inside_strike) j_inside_dips.append(j_inside_dip) #ax.pole(j_inside_strike, j_inside_dip, color=colours[joint]) j_inside_strikes = j_inside_strikes[0] + j_inside_strikes[ 1] + j_inside_strikes[2] j_inside_dips = j_inside_dips[0] + j_inside_dips[1] + j_inside_dips[2] # Friction circle ax.cone(90, 0, 90 - FrictionAngle, alpha=0.1, color='r', zorder=1, bidirectional=False) # Stereonet overlay settings ax.set_azimuth_ticks([0, 90, 180, 270], labels=['N', 'E', 'S', 'W']) ax.grid(True, kind='polar') plt.tight_layout() # Shaded Area shaded_area = pole(j_inside_strikes, j_inside_dips) shaded_area_x = [x for x in shaded_area[0]] shaded_area_y = [x for x in shaded_area[1]] shaded_area_stack = np.vstack((shaded_area_x, shaded_area_y)).T edges = alpha_shape(shaded_area_stack, alpha=1, only_outer=True) edges_joined = stitch_boundaries(edges) edges_joined_x = [] edges_joined_y = [] for i, j in edges_joined[0]: edges_joined_x.append(shaded_area_x[i]) edges_joined_y.append(shaded_area_y[i]) polygon = np.vstack((edges_joined_x, edges_joined_y)).T ax.fill(edges_joined_x, edges_joined_y, 'k', alpha=0.3) Joints = ['1', '2', '3', '1/2', '1/3', '2/3'] Stability = "Stable" Mode = 'N/A' if point_inside_polygon(0, 0, polygon): Stability = 'Unstable' Mode = 'Falling' else: poles_ext = pole(point_strikes, [d + 1 for d in point_dips]) poles_ext = np.vstack((poles_ext[0], poles_ext[1])).T max_slide = 0 for i in range(0, 6): if point_inside_polygon( poles_ext[i][0], poles_ext[i][1], polygon ) and real_dips[i] >= FrictionAngle and real_dips[i] > max_slide: Stability = 'Unstable' max_slide = real_dips[i] Mode = "Sliding on Joint {0}".format(Joints[i]) # Table in top plot table_data = [["Friction Angle", "{0}°".format(FrictionAngle)], ["Joints", "Dip / Dip Direction"], [ "1", "{0}°/{1:0=3d}°".format(int(round(Dip[0])), int(round(DipDirection[0]))) ], [ "2", "{0}°/{1:0=3d}°".format(int(round(Dip[1])), int(round(DipDirection[1]))) ], [ "3", "{0}°/{1:0=3d}°".format(int(round(Dip[2])), int(round(DipDirection[2]))) ], ["Intersections", "Trend / Plunge"], [ "1/2", "{0}°/{1:0=3d}°".format(int(round(plunge[0])), int(round(bearing[0]))) ], [ "1/3", "{0}°/{1:0=3d}°".format(int(round(plunge[1])), int(round(bearing[1]))) ], [ "2/3", "{0}°/{1:0=3d}°".format(int(round(plunge[2])), int(round(bearing[2]))) ], ["Stability", Stability], ["Mode", Mode]] table = ax.table(cellText=table_data, bbox=[1.1, 0.3, 0.4, 0.35], cellLoc='center', loc='right', colWidths=[0.2, 0.2 ]) # , loc='top right')#, colWidths = [0.4]*2) for (row, col), cell in table.get_celld().items(): if (row == 0 or row == 1 or row == 5 or row == 9 or row == 10): cell.set_text_props(fontproperties=FontProperties(weight='bold')) if (row == 2): cell.set_text_props(color='r') if (row == 3): cell.set_text_props(color='g') if (row == 4): cell.set_text_props(color='b') return fig, ax