def test_projections(self): n = 1000 points = num.zeros((n, 3)) phi = num.random.random(n) * math.pi * 2.0 theta = num.random.random(n) * math.pi / 2.0 points[:, 0] = num.cos(phi) * num.sin(theta) points[:, 1] = num.sin(phi) * num.sin(theta) points[:, 2] = num.cos(theta) for projection in ['lambert', 'stereographic', 'orthographic']: projection = 'stereographic' points2 = beachball.project(points, projection=projection) points_new = beachball.inverse_project(points2, projection=projection) assert num.all(num.abs(points - points_new) < 1e-5)
def test_projections(self): n = 1000 points = num.zeros((n, 3)) phi = num.random.random(n) * math.pi * 2.0 theta = num.random.random(n) * math.pi / 2.0 points[:, 0] = num.cos(phi) * num.sin(theta) points[:, 1] = num.sin(phi) * num.sin(theta) points[:, 2] = num.cos(theta) for projection in ['lambert', 'stereographic', 'orthographic']: projection = 'stereographic' points2 = beachball.project(points, projection=projection) points_new = beachball.inverse_project( points2, projection=projection) assert num.all(num.abs(points - points_new) < 1e-5)
def plot_directivity(engine, source, store_id, distance=300 * km, azi_begin=0., azi_end=360., dazi=1., phase_begin='first{stored:any_P}-10%', phase_end='last{stored:any_S}+50', quantity='displacement', envelope=False, component='R', fmin=0.01, fmax=0.1, hillshade=True, cmap=None, plot_mt='full', show_phases=True, show_description=True, reverse_time=False, show_nucleations=True, axes=None, nthreads=0): '''Plot the directivity and radiation characteristics of source models Synthetic seismic traces (R, T or Z) are forward-modelled at a defined radius, covering the full or partial azimuthal range and projected on a polar plot. Difference in the amplitude are enhanced by hillshading the data. :param engine: Forward modelling engine :type engine: :py:class:`~pyrocko.gf.seismosizer.Engine` :param source: Parametrized source model :type source: :py:class:`~pyrocko.gf.seismosizer.Source` :param store_id: Store ID used for forward modelling :type store_id: str :param distance: Distance in [m] :type distance: float :param azi_begin: Begin azimuth in [deg] :type azi_begin: float :param azi_end: End azimuth in [deg] :type azi_end: float :param dazi: Delta azimuth, bin size [deg] :type dazi: float :param phase_begin: Start time of the window :type phase_begin: :py:class:`~pyrocko.gf.meta.Timing` :param phase_end: End time of the window :type phase_end: :py:class:`~pyrocko.gf.meta.Timing` :param quantity: Seismogram quantity, default ``displacement`` :type quantity: str :param envelope: Plot envelop instead of seismic trace :type envelope: bool :param component: Forward modelled component, default ``R``. Choose from `RTZ` :type component: str :param fmin: Bandpass lower frequency [Hz], default ``0.01`` :type fmin: float :param fmax: Bandpass upper frequency [Hz], default ``0.1`` :type fmax: float :param hillshade: Enable hillshading, default ``True`` :type hillshade: bool :param cmap: Matplotlit colormap to use, default ``seismic``. When ``envelope`` is ``True`` the default colormap will be ``Reds``. :type cmap: str :param plot_mt: Plot a centered moment tensor, default ``full``. Choose from ``full, deviatoric, dc or False`` :type plot_mt: str, bool :param show_phases: Show annotations, default ``True`` :type show_phases: bool :param show_description: Show desciption, default ``True`` :type show_description: bool :param reverse_time: Reverse time axis. First phases arrive at the center, default ``False`` :type reverse_time: bool :param show_nucleations: Show nucleation piercing points on the moment tensor, default ``True`` :type show_nucleations: bool :param axes: Give axes to plot into :type axes: :py:class:`matplotlib.axes.Axes` :param nthreads: Number of threads used for forward modelling, default ``0`` - all available cores :type nthreads: int ''' if axes is None: fig = plt.figure() ax = fig.add_subplot(111, polar=True) else: fig = axes.figure ax = axes if envelope and cmap is None: cmap = 'Reds' elif cmap is None: cmap = 'seismic' targets, azimuths = get_azimuthal_targets(store_id, source, distance, azi_begin, azi_end, dazi, components='R', quantity=quantity) store = engine.get_store(store_id) mt = source.pyrocko_moment_tensor(store=store, target=targets[0]) resp = engine.process(source, targets, nthreads=nthreads) data, times = get_seismogram_array(resp, fmin, fmax, component=component, envelope=envelope) timing_begin = Timing(phase_begin) timing_end = Timing(phase_end) nucl_depth = source.depth nucl_distance = distance if hasattr(source, 'nucleation_x') and hasattr(source, 'nucleation_y'): try: iter(source.nucleation_x) nx = float(source.nucleation_x[0]) ny = float(source.nucleation_y[0]) except TypeError: nx = source.nucleation_x ny = source.nucleation_y nucl_distance += nx * source.length / 2. nucl_depth += ny * num.sin(source.dip * d2r) * source.width / 2. if hasattr(source, 'anchor'): anch_x, anch_y = map_anchor[source.anchor] nucl_distance -= anch_x * source.length / 2. nucl_depth -= anch_y * num.sin(source.dip * d2r) * source.width / 2. tbegin = store.t(timing_begin, (nucl_depth, nucl_distance)) tend = store.t(timing_end, (nucl_depth, nucl_distance)) tsel = num.logical_and(times >= tbegin, times <= tend) data = data[:, tsel].T times = times[tsel] duration = times[-1] - times[0] vmax = num.abs(data).max() cmw = ScalarMappable(cmap=cmap) cmw.set_array(data) cmw.set_clim(-vmax, vmax) if envelope: cmw.set_clim(0., vmax) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) strike_label = mt.strike1 if hasattr(source, 'strike'): strike_label = source.strike try: ax.set_rlabel_position(strike_label % 180.) except AttributeError: logger.warn('Old matplotlib version: cannot set label positions') def r_fmt(v, p): if v < tbegin or v > tend: return '' return '%g s' % v ax.yaxis.set_major_formatter(FuncFormatter(r_fmt)) if reverse_time: ax.set_rlim(times[0] - .3 * duration, times[-1]) else: ax.set_rlim(times[-1] + .3 * duration, times[0]) ax.grid(zorder=20) if isinstance(plot_mt, str): mt_size = .15 beachball.plot_beachball_mpl(mt, ax, beachball_type=plot_mt, size=mt_size, size_units='axes', color_t=(0.7, 0.4, 0.4), position=(.5, .5), linewidth=1.) if hasattr(source, 'nucleation_x') and hasattr(source, 'nucleation_y')\ and show_nucleations: try: iter(source.nucleation_x) nucleation_x = source.nucleation_x nucleation_y = source.nucleation_y except TypeError: nucleation_x = [source.nucleation_x] nucleation_y = [source.nucleation_y] for nx, ny in zip(nucleation_x, nucleation_y): angle = float(num.arctan2(ny, nx)) rtp = num.array([[1., angle, (90. - source.strike) * d2r]]) points = beachball.numpy_rtp2xyz(rtp) x, y = beachball.project(points, projection='lambert').T norm = num.sqrt(x**2 + y**2) x = x / norm * mt_size / 2. y = y / norm * mt_size / 2. ax.plot(x + .5, y + .5, 'x', ms=6, mew=2, mec='darkred', mfc='red', transform=ax.transAxes, zorder=10) mesh = ax.pcolormesh(azimuths * d2r, times, data, cmap=cmw.cmap, shading='gouraud', zorder=0) if hillshade: mesh.update_scalarmappable() color = mesh.get_facecolor() color = hillshade_seismogram_array(data, color, shad_lim=(.85, 1.), blend_mode='multiply') mesh.set_facecolor(color) if show_phases: _phase_begin = Timing(phase_begin) _phase_end = Timing(phase_end) for p in (_phase_begin, _phase_end): p.offset = 0. p.offset_is_slowness = False p.offset_is_percent = False tphase_first = store.t(_phase_begin, (nucl_depth, nucl_distance)) tphase_last = store.t(_phase_end, (nucl_depth, nucl_distance)) theta = num.linspace(0, 2 * num.pi, 360) tfirst = num_full_like(theta, tphase_first) tlast = num_full_like(theta, tphase_last) ax.plot(theta, tfirst, color='k', alpha=.3, lw=1.) ax.plot(theta, tlast, color='k', alpha=.3, lw=1.) ax.text(num.pi * 7 / 5, tphase_first, '|'.join(_phase_begin.phase_defs), ha='left', color='k', fontsize='small') ax.text(num.pi * 6 / 5, tphase_last, '|'.join(_phase_end.phase_defs), ha='left', color='k', fontsize='small') description = ('Component {component:s}\n' 'Distance {distance:g} km').format(component=component, distance=distance / km) if show_description: if fmin and fmax: description += '\nBandpass {fmin:g} - {fmax:g} Hz'.format( fmin=fmin, fmax=fmax) elif fmin: description += '\nHighpass {fmin:g} Hz'.format(fmin=fmin) elif fmax: description += '\nLowpass {fmax:g} Hz'.format(fmax=fmax) ax.text(-.05, -.05, description, fontsize='small', ha='left', va='bottom', transform=ax.transAxes) cbar_label = QUANTITY_LABEL[quantity] if envelope: cbar_label = 'Envelope ' + cbar_label cb = fig.colorbar(cmw, ax=ax, orientation='vertical', shrink=.8, pad=0.11) cb.set_label(cbar_label) if axes is None: plt.show() return resp
color_t=(0.3, 0.3, 0.8), projection=projection, size_units='data') for rlat, rlon in rlatlons: distance = orthodrome.distance_accurate50m(slat, slon, rlat, rlon) rays = mod.arrivals(phases=cake.PhaseDef('P'), zstart=sdepth, zstop=rdepth, distances=[distance * cake.m2d]) if not rays: continue takeoff = rays[0].takeoff_angle() azi = orthodrome.azimuth(slat, slon, rlat, rlon) # to spherical coordinates, r, theta, phi in radians rtp = num.array([[1., num.deg2rad(takeoff), num.deg2rad(90. - azi)]]) # to 3D coordinates (x, y, z) points = beachball.numpy_rtp2xyz(rtp) # project to 2D with same projection as used in beachball x, y = beachball.project(points, projection=projection).T axes.plot(x, y, '+', ms=10., mew=2.0, mec='black', mfc='none') #fig.savefig('beachball-example04.png') plt.show()
position=(0., 0.), size=2.0, color_t=(0.7, 0.4, 0.4), projection=projection, size_units='data') for rlat, rlon in rlatlons: distance = orthodrome.distance_accurate50m(slat, slon, rlat, rlon) rays = mod.arrivals( phases=cake.PhaseDef('P'), zstart=sdepth, zstop=rdepth, distances=[distance*cake.m2d]) if not rays: continue takeoff = rays[0].takeoff_angle() azi = orthodrome.azimuth(slat, slon, rlat, rlon) # to spherical coordinates, r, theta, phi in radians rtp = num.array([[1., num.deg2rad(takeoff), num.deg2rad(90.-azi)]]) # to 3D coordinates (x, y, z) points = beachball.numpy_rtp2xyz(rtp) # project to 2D with same projection as used in beachball x, y = beachball.project(points, projection=projection).T axes.plot(x, y, '+', ms=10., mew=2.0, mec='black', mfc='none') fig.savefig('beachball-example04.png')