def fit_fault_set(ax, faults, split_axis=1, title='Poles to Planes'): """Given a sequence of swfaults representing a bi-modal distribution, fit a plane to each of the modes.""" vol = populations.vol faults = list(faults) numfaults = len(faults) normals = [norm for fault in faults for norm in normal_vecs(fault, vol)] numvecs = len(normals) normals = np.array(normals) strikes_dips = fit_bimodal_bidirectional(normals, split_axis=split_axis) strike, dip = smath.vector2pole(*normals.T) ax.pole(strike, dip, 'ko', markersize=2, alpha=0.5) cax = ax.density_contourf(strike, dip, sigma=3) ax.density_contour(strike, dip, linewidths=2, sigma=3) cbar = ax.figure.colorbar(cax, ax=ax) cbar.set_label('Number of standard deviations', rotation=-90) conj = [] for sd, color in zip(strikes_dips, ['r', 'g']): ax.pole(*sd, color=color) ax.plane(*sd, color=color, lw=2) conj.append(u'%0.0f\u00b0/%0.0f\u00b0' % sd) ax.set_azimuth_ticks([]) # ax.grid(True) ax.set_title(title + '\n' + ' and '.join(conj), y=1.0, va='bottom') ax.annotate('{} planes from {} faults'.format(numvecs, numfaults), xy=(0.5, 0), xytext=(0, -12), xycoords='axes fraction', textcoords='offset points', ha='center', va='top')
def fit_bimodal(normals, weights=None, k=2): """Given a set of vectors, find the resultant vector of two modes using kmeans to seperate the modes. The vectors will be weighted by "weights", if specified.""" obs = scipy.cluster.vq.whiten(normals) codebook, _ = scipy.cluster.vq.kmeans2(obs, k) mode, _ = scipy.cluster.vq.vq(obs, codebook) if weights is not None: weighted_normals = (normals.T * weights).T else: weighted_normals = normals modes = [weighted_normals[mode==i] for i in range(k)] return (smath.vector2pole(*mode.mean(axis=0)) for mode in modes)
def test_vector2pole(self): for (x, y, z), (strike, dip) in self.data: assert np.allclose(smath.vector2pole(x, y, z), [[strike], [dip]])
def test_vector2pole(self): for (x,y,z), (strike, dip) in self.data: assert np.allclose(smath.vector2pole(x,y,z), [[strike], [dip]])