def test_spectrum(): freq = np.logspace(-2, 2, 101) moment = spectrum.moment_from_magnitude(6.7) mod = spectrum.model((moment, 150), freq, 10, kappa=0.035) np.testing.assert_allclose(mod[0], 0.21764373, atol=1e-5) np.testing.assert_allclose(mod[50], 113.5025146, atol=1e-5) np.testing.assert_allclose(mod[-1], 0.0032295, atol=1e-5)
def summary_plots(st, directory, origin): """Stream summary plot. Args: st (gmprocess.stationtrace.StationStream): Stream of data. directory (str): Directory for saving plots. origin (ScalarEvent): Flattened subclass of Obspy Event. """ mpl.rcParams['font.size'] = 8 # Check if directory exists, and if not, create it. if not os.path.exists(directory): os.makedirs(directory) # Setup figure for stream nrows = 4 ntrace = min(len(st), 3) fig = plt.figure(figsize=(3.9 * ntrace, 10)) gs = fig.add_gridspec(nrows, ntrace, height_ratios=[1, 1, 2, 2]) ax = [plt.subplot(g) for g in gs] stream_id = st.get_id() logging.debug('stream_id: %s' % stream_id) logging.debug('passed: %s' % st.passed) if st.passed: plt.suptitle("M%s %s | %s (passed)" % (origin.magnitude, origin.id, stream_id), x=0.5, y=1.02) else: plt.suptitle("M%s %s | %s (failed)" % (origin.magnitude, origin.id, stream_id), color='red', x=0.5, y=1.02) # Compute velocity st_vel = st.copy() st_vel = st_vel.integrate() # process channels in preferred sort order (i.e., HN1, HN2, HNZ) channels = [tr.stats.channel for tr in st] if len(channels) < 3: channelidx = np.argsort(channels).tolist() else: channelidx = range(3) for j in channelidx: tr = st[channelidx.index(j)] # Break if j>3 becasue we can't on a page. if j > 2: logging.warning('Only plotting first 3 traces in stream.') break # --------------------------------------------------------------------- # Get trace info if tr.hasCached('snr'): snr_dict = tr.getCached('snr') else: snr_dict = None if tr.hasCached('signal_spectrum'): signal_dict = tr.getCached('signal_spectrum') else: signal_dict = None if tr.hasCached('noise_spectrum'): noise_dict = tr.getCached('noise_spectrum') else: noise_dict = None if tr.hasCached('smooth_signal_spectrum'): smooth_signal_dict = tr.getCached('smooth_signal_spectrum') else: smooth_signal_dict = None if tr.hasCached('smooth_noise_spectrum'): smooth_noise_dict = tr.getCached('smooth_noise_spectrum') else: smooth_noise_dict = None if tr.hasParameter('snr_conf'): snr_conf = tr.getParameter('snr_conf') else: snr_conf = None trace_failed = tr.hasParameter('failure') if trace_failed: failure_reason = tr.getParameter('failure')['reason'] else: failure_reason = '' # Note that the theoretical spectra will only be available for # horizontal channels if tr.hasParameter('fit_spectra'): fit_spectra_dict = tr.getParameter('fit_spectra') else: fit_spectra_dict = None # --------------------------------------------------------------------- # Compute model spectra if fit_spectra_dict is not None: model_spec = spectrum.model( (fit_spectra_dict['moment'], fit_spectra_dict['stress_drop']), freq=np.array(smooth_signal_dict['freq']), dist=fit_spectra_dict['epi_dist'], kappa=fit_spectra_dict['kappa']) # --------------------------------------------------------------------- # Acceleration time series plot if trace_failed: trace_status = " (failed)" trace_title = tr.get_id() + trace_status ax[j].set_title(trace_title, color="red") else: trace_status = " (passed)" trace_title = tr.get_id() + trace_status ax[j].set_title(trace_title) dtimes = np.linspace(0, tr.stats.endtime - tr.stats.starttime, tr.stats.npts) ax[j].plot(dtimes, tr.data, 'k', linewidth=0.5) # Show signal split as vertical dashed line if tr.hasParameter('signal_split'): split_dict = tr.getParameter('signal_split') sptime = UTCDateTime(split_dict['split_time']) dsec = sptime - tr.stats.starttime ax[j].axvline(dsec, color='red', linestyle='dashed') ax[j].set_xlabel('Time (s)') ax[j].set_ylabel('Acceleration (cm/s/s)') # --------------------------------------------------------------------- # Velocity time series plot tr_vel = st_vel[j] dtimes = np.linspace(0, tr_vel.stats.endtime - tr_vel.stats.starttime, tr_vel.stats.npts) ax[j + ntrace].plot(dtimes, tr_vel.data, 'k', linewidth=0.5) # Show signal split as vertical dashed line if tr.hasParameter('signal_split'): split_dict = tr.getParameter('signal_split') sptime = UTCDateTime(split_dict['split_time']) dsec = sptime - tr.stats.starttime ax[j + ntrace].axvline(dsec, color='red', linestyle='dashed') ax[j + ntrace].set_xlabel('Time (s)') ax[j + ntrace].set_ylabel('Velocity (cm/s)') # --------------------------------------------------------------------- # Spectral plot # Raw signal spec if signal_dict is not None: ax[j + 2 * ntrace].loglog(signal_dict['freq'], signal_dict['spec'], color='lightblue') # Smoothed signal spec if smooth_signal_dict is not None: ax[j + 2 * ntrace].loglog(smooth_signal_dict['freq'], smooth_signal_dict['spec'], color='blue', label='Signal') # Raw noise spec if noise_dict is not None: ax[j + 2 * ntrace].loglog(noise_dict['freq'], noise_dict['spec'], color='salmon') # Smoothed noise spec if smooth_noise_dict is not None: ax[j + 2 * ntrace].loglog(smooth_noise_dict['freq'], smooth_noise_dict['spec'], color='red', label='Noise') if fit_spectra_dict is not None: # Model spec ax[j + 2 * ntrace].loglog(smooth_signal_dict['freq'], model_spec, color='black', linestyle='dashed') # Corner frequency ax[j + 2 * ntrace].axvline(fit_spectra_dict['f0'], color='black', linestyle='dashed') ax[j + 2 * ntrace].set_xlabel('Frequency (Hz)') ax[j + 2 * ntrace].set_ylabel('Amplitude (cm/s)') # --------------------------------------------------------------------- # Signal-to-noise ratio plot if 'corner_frequencies' in tr.getParameterKeys(): hp = tr.getParameter('corner_frequencies')['highpass'] lp = tr.getParameter('corner_frequencies')['lowpass'] ax[j + 3 * ntrace].axvline(hp, color='black', linestyle='--', label='Highpass') ax[j + 3 * ntrace].axvline(lp, color='black', linestyle='--', label='Lowpass') if snr_conf is not None: ax[j + 3 * ntrace].axhline(snr_conf['threshold'], color='0.75', linestyle='-', linewidth=2) ax[j + 3 * ntrace].axvline(snr_conf['max_freq'], color='0.75', linewidth=2, linestyle='-') ax[j + 3 * ntrace].axvline(snr_conf['min_freq'], color='0.75', linewidth=2, linestyle='-') if snr_dict is not None: ax[j + 3 * ntrace].loglog(snr_dict['freq'], snr_dict['snr'], label='SNR') ax[j + 3 * ntrace].set_ylabel('SNR') ax[j + 3 * ntrace].set_xlabel('Frequency (Hz)') stream_id = st.get_id() # Do not save files if running tests file_name = None if 'CALLED_FROM_PYTEST' not in os.environ: plt.subplots_adjust(left=0.05, right=0.97, hspace=0.25, wspace=0.2, top=0.97) file_name = os.path.join(directory, origin.id + '_' + stream_id + '.png') plt.savefig(fname=file_name) plt.close('all') return file_name
def summary_plots(st, directory, origin): """Stream summary plot. Args: st (gmprocess.stationtrace.StationStream): Stream of data. directory (str): Directory for saving plots. origin (ScalarEvent): Flattened subclass of Obspy Event. """ mpl.rcParams['font.size'] = 8 # Check if directory exists, and if not, create it. if not os.path.exists(directory): os.makedirs(directory) # Setup figure for stream nrows = 4 ntrace = min(len(st), 3) fig = plt.figure(figsize=(3.8 * ntrace, 10)) gs = fig.add_gridspec(nrows, ntrace, height_ratios=[1, 1, 2, 2]) ax = [plt.subplot(g) for g in gs] stream_id = st.get_id() logging.debug('stream_id: %s' % stream_id) logging.debug('passed: %s' % st.passed) if st.passed: plt.suptitle("M%s %s | %s (passed)" % (origin.magnitude, origin.id, stream_id), x=0.5, y=1.02) else: plt.suptitle("M%s %s | %s (failed)" % (origin.magnitude, origin.id, stream_id), color='red', x=0.5, y=1.02) # Compute velocity st_vel = st.copy() st_vel = st_vel.integrate() # process channels in preferred sort order (i.e., HN1, HN2, HNZ) channels = [tr.stats.channel for tr in st] if len(channels) < 3: channelidx = np.argsort(channels).tolist() else: channelidx = range(3) for j in channelidx: tr = st[channelidx.index(j)] # Break if j>3 becasue we can't on a page. if j > 2: logging.warning('Only plotting first 3 traces in stream.') break # --------------------------------------------------------------------- # Get trace info if tr.hasParameter('snr'): snr_dict = tr.getParameter('snr') else: snr_dict = None if tr.hasParameter('signal_spectrum'): signal_dict = tr.getParameter('signal_spectrum') else: signal_dict = None if tr.hasParameter('noise_spectrum'): noise_dict = tr.getParameter('noise_spectrum') else: noise_dict = None if tr.hasParameter('smooth_signal_spectrum'): smooth_signal_dict = tr.getParameter('smooth_signal_spectrum') else: smooth_signal_dict = None if tr.hasParameter('smooth_noise_spectrum'): smooth_noise_dict = tr.getParameter('smooth_noise_spectrum') else: smooth_noise_dict = None if tr.hasParameter('snr_conf'): snr_conf = tr.getParameter('snr_conf') else: snr_conf = None trace_failed = tr.hasParameter('failure') if trace_failed: failure_reason = tr.getParameter('failure')['reason'] else: failure_reason = '' # Note that the theoretical spectra will only be available for # horizontal channels if tr.hasParameter('fit_spectra'): fit_spectra_dict = tr.getParameter('fit_spectra') else: fit_spectra_dict = None # --------------------------------------------------------------------- # Compute model spectra if fit_spectra_dict is not None: model_spec = spectrum.model( freq=np.array(smooth_signal_dict['freq']), dist=fit_spectra_dict['epi_dist'], kappa=fit_spectra_dict['kappa'], magnitude=fit_spectra_dict['magnitude'], stress_drop=fit_spectra_dict['stress_drop'] ) # --------------------------------------------------------------------- # Acceleration time series plot if trace_failed: trace_status = " (failed)" trace_title = tr.get_id() + trace_status ax[j].set_title(trace_title, color="red") else: trace_status = " (passed)" trace_title = tr.get_id() + trace_status ax[j].set_title(trace_title) dtimes = tr.times('utcdatetime') - tr.times('utcdatetime')[0] ax[j].plot(dtimes, tr.data, 'k', linewidth=0.5) # Show signal split as vertical dashed line if tr.hasParameter('signal_split'): split_dict = tr.getParameter('signal_split') dsec = split_dict['split_time'] - tr.times('utcdatetime')[0] ax[j].axvline(dsec, color='red', linestyle='dashed') ax[j].set_xlabel('Time (s)') ax[j].set_ylabel('Acceleration (cm/s/s)') # --------------------------------------------------------------------- # Velocity time series plot tr_vel = st_vel[j] dtimes = tr_vel.times('utcdatetime') - tr_vel.times('utcdatetime')[0] ax[j + ntrace].plot(dtimes, tr_vel.data, 'k', linewidth=0.5) # Show signal split as vertical dashed line if tr.hasParameter('signal_split'): split_dict = tr.getParameter('signal_split') dsec = split_dict['split_time'] - tr.times('utcdatetime')[0] ax[j + ntrace].axvline(dsec, color='red', linestyle='dashed') ax[j + ntrace].set_xlabel('Time (s)') ax[j + ntrace].set_ylabel('Velocity (cm/s)') # --------------------------------------------------------------------- # Spectral plot # Raw signal spec if signal_dict is not None: ax[j + 2 * ntrace].loglog(signal_dict['freq'], signal_dict['spec'], color='lightblue') # Smoothed signal spec if smooth_signal_dict is not None: ax[j + 2 * ntrace].loglog(smooth_signal_dict['freq'], smooth_signal_dict['spec'], color='blue', label='Signal') # Raw noise spec if noise_dict is not None: ax[j + 2 * ntrace].loglog(noise_dict['freq'], noise_dict['spec'], color='salmon') # Smoothed noise spec if smooth_noise_dict is not None: ax[j + 2 * ntrace].loglog(smooth_noise_dict['freq'], smooth_noise_dict['spec'], color='red', label='Noise') if fit_spectra_dict is not None: # Model spec ax[j + 2 * ntrace].loglog(smooth_signal_dict['freq'], model_spec, color='black', linestyle='dashed') # Corner frequency ax[j + 2 * ntrace].axvline(fit_spectra_dict['f0'], color='black', linestyle='dashed') ax[j + 2 * ntrace].set_xlabel('Frequency (Hz)') ax[j + 2 * ntrace].set_ylabel('Amplitude (cm/s)') # --------------------------------------------------------------------- # Signal-to-noise ratio plot if 'corner_frequencies' in tr.getParameterKeys(): hp = tr.getParameter('corner_frequencies')['highpass'] lp = tr.getParameter('corner_frequencies')['lowpass'] ax[j + 3 * ntrace].axvline(hp, color='black', linestyle='--', label='Highpass') ax[j + 3 * ntrace].axvline(lp, color='black', linestyle='--', label='Lowpass') if snr_conf is not None: ax[j + 3 * ntrace].axhline(snr_conf['threshold'], color='0.75', linestyle='-', linewidth=2) ax[j + 3 * ntrace].axvline(snr_conf['max_freq'], color='0.75', linewidth=2, linestyle='-') ax[j + 3 * ntrace].axvline(snr_conf['min_freq'], color='0.75', linewidth=2, linestyle='-') if snr_dict is not None: ax[j + 3 * ntrace].loglog(snr_dict['freq'], snr_dict['snr'], label='SNR') ax[j + 3 * ntrace].set_ylabel('SNR') ax[j + 3 * ntrace].set_xlabel('Frequency (Hz)') stream_id = st.get_id() # Do not save files if running tests if 'CALLED_FROM_PYTEST' not in os.environ: plt.subplots_adjust(hspace=0.35, wspace=0.35, top=0.97) file_name = os.path.join( directory, origin.id + '_' + stream_id + '.png') plt.savefig(fname=file_name, bbox_inches='tight') plt.close('all') return st
def test_spectrum(): freq = np.logspace(-2, 2, 101) mod = spectrum.model(freq, 10, kappa=0.035, magnitude=6.7) np.testing.assert_allclose(mod[0], 0.21764373, atol=1e-5) np.testing.assert_allclose(mod[50], 113.5025146, atol=1e-5) np.testing.assert_allclose(mod[-1], 0.0032295, atol=1e-5)