def semblance(st, s, baz, winlen): ''' Returns the semblance for a seismic array, for a beam of given slowness and backazimuth. Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array s : float Magnitude of slowness vector, in s / km baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the semblance. Returns ------- semblance : NumPy array The semblance at the given slowness and backazimuth, as a time series. ''' # Check that each channel has the same number of samples, otherwise we can't construct the beam properly assert len(set([ len(tr) for tr in st ])) == 1, "Traces in stream have different lengths, cannot stack." nsta = len(st) stack = linear_stack(st, s, baz) # Taper the linear stack stack_trace = Trace(stack) stack_trace.taper(type='cosine', max_percentage=0.05) stack = stack_trace.data shifts = get_shifts(st, s, baz) # Smooth data with sliding Hann window (i.e. convolution of signal and window function) window = np.hanning(winlen) shifted_st = st.copy() for i, tr in enumerate(shifted_st): tr.data = np.roll(tr.data, shifts[i]) # Shift data in each trace by its offset tr.taper(type='cosine', max_percentage=0.05) # Taper it # Calculate the power in the beam beampower = np.convolve(stack**2, window, mode='same') # Calculate the summed power of each trace tracepower = np.convolve(np.sum([tr.data**2 for tr in shifted_st], axis=0), window, mode='same') # Calculate semblance semblance = nsta * beampower / tracepower return semblance
def semblance(st, s, baz, winlen): """ Returns the semblance for a seismic array, for a beam of given slowness and backazimuth. Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array s : float Magnitude of slowness vector, in s / km baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the semblance. Returns ------- semblance : NumPy array The semblance at the given slowness and backazimuth, as a time series. """ # Check that each channel has the same number of samples, otherwise we can't construct the beam properly assert len(set([len(tr) for tr in st])) == 1, "Traces in stream have different lengths, cannot stack." nsta = len(st) stack = linear_stack(st, s, baz) # Taper the linear stack stack_trace = Trace(stack) stack_trace.taper(type="cosine", max_percentage=0.05) stack = stack_trace.data shifts = get_shifts(st, s, baz) # Smooth data with sliding Hann window (i.e. convolution of signal and window function) window = np.hanning(winlen) shifted_st = st.copy() for i, tr in enumerate(shifted_st): tr.data = np.roll(tr.data, shifts[i]) # Shift data in each trace by its offset tr.taper(type="cosine", max_percentage=0.05) # Taper it # Calculate the power in the beam beampower = np.convolve(stack ** 2, window, mode="same") # Calculate the summed power of each trace tracepower = np.convolve(np.sum([tr.data ** 2 for tr in shifted_st], axis=0), window, mode="same") # Calculate semblance semblance = nsta * beampower / tracepower return semblance
def power_vespa(st, s, baz, winlen): ''' Returns the power vespa (i.e. the power in the linear delay-and-sum beam) for a seismic array, for a beam of given slowness and backazimuth. Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array s : float Magnitude of slowness vector, in s / km baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the power. Returns ------- power : NumPy array The power of the linear beam at the given slowness and backazimuth, as a time series. ''' amplitude = linear_stack(st, s, baz) power = np.convolve(amplitude**2, np.hanning(winlen), mode='same') return power
def power_vespa(st, s, baz, winlen): """ Returns the power vespa (i.e. the power in the linear delay-and-sum beam) for a seismic array, for a beam of given slowness and backazimuth. Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array s : float Magnitude of slowness vector, in s / km baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the power. Returns ------- power : NumPy array The power of the linear beam at the given slowness and backazimuth, as a time series. """ amplitude = linear_stack(st, s, baz) power = np.convolve(amplitude ** 2, np.hanning(winlen), mode="same") return power
def stack_vespagram(st, slowness_min, slowness_max, n_steps, baz, separation=0.5): ''' Plots a stack vespagram for a seismic array over a given slowness range, for a single backazimuth. The individual beam traces for each slowness step are plotted as a function of time (in s) and slowness (in s/km). Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array slowness_min : float Minimum magnitude of the slowness vector, in s/km slowness_max : float Maximum magnitude of the slowness vector, in s/km n_steps : int Maximum backazimuth, in degrees baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the power. separation : float Fraction of a single beam that overlaps with its neighbours. Smaller separations make a denser vespagram. ''' slowness_range = np.linspace(slowness_min, slowness_max, n_steps) vespas = [linear_stack(st, slowness, baz) for slowness in slowness_range] times = st[0].times() plt.figure(figsize=(14, 10)) # Find maximum and minimum amplitudes of the beam in order to set y-axes for beam traces. max_y = np.max(np.array(vespas)) min_y = np.min(np.array(vespas)) trace_height = 1. / (1 + (n_steps - 1) * separation) # Plot beam trace for each slowness value for i, trace in enumerate(vespas): # rect = [left, bottom, width, height] trace_bottom = ( 1 - trace_height) + (i - n_steps + 1) * separation * trace_height rect = [0, trace_bottom, 1, trace_height] ax = plt.axes(rect, axisbg=None, frameon=False) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.plot(times, trace, alpha=0.6) plt.ylim(min_y, max_y) plt.xlim(0, 350) # Create external axes to contain beam traces, and set its slowness range plt.axes([0, 0, 1, 1], axisbg='none') main_ax_slowness_max = slowness_max / (1 - 0.5 * trace_height) main_ax_slowness_min = slowness_min - 0.5 * trace_height * main_ax_slowness_max plt.ylim(main_ax_slowness_min, main_ax_slowness_max) plt.xlim(0, 350) plt.xlabel('Time (s)') plt.yticks(fontsize=14) plt.xticks(fontsize=14) plt.ylabel('Slowness (s / km)') plt.show()
def stack_vespagram(st, slowness_min, slowness_max, n_steps, baz, separation=0.5): ''' Plots a stack vespagram for a seismic array over a given slowness range, for a single backazimuth. The individual beam traces for each slowness step are plotted as a function of time (in s) and slowness (in s/km). Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array, length K = no. of stations in array slowness_min : float Minimum magnitude of the slowness vector, in s/km slowness_max : float Maximum magnitude of the slowness vector, in s/km n_steps : int Maximum backazimuth, in degrees baz : float Backazimuth of slowness vector, (i.e. angle from North back to epicentre of event) winlen : int Length of Hann window over which to calculate the power. separation : float Fraction of a single beam that overlaps with its neighbours. Smaller separations make a denser vespagram. ''' slowness_range = np.linspace(slowness_min, slowness_max, n_steps) vespas = [linear_stack(st, slowness, baz) for slowness in slowness_range] times = st[0].times() plt.figure(figsize=(14, 10)) # Find maximum and minimum amplitudes of the beam in order to set y-axes for beam traces. max_y = np.max(np.array(vespas)) min_y = np.min(np.array(vespas)) trace_height = 1. / (1 + (n_steps - 1) * separation) # Plot beam trace for each slowness value for i, trace in enumerate(vespas): # rect = [left, bottom, width, height] trace_bottom = (1 - trace_height) + (i - n_steps + 1) * separation * trace_height rect = [0, trace_bottom, 1, trace_height] ax = plt.axes(rect, axisbg=None, frameon=False) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.plot(times, trace, alpha=0.6) plt.ylim(min_y, max_y); plt.xlim(0, 350); # Create external axes to contain beam traces, and set its slowness range plt.axes([0, 0, 1, 1], axisbg='none') main_ax_slowness_max = slowness_max / (1 - 0.5 * trace_height) main_ax_slowness_min = slowness_min - 0.5 * trace_height * main_ax_slowness_max plt.ylim(main_ax_slowness_min, main_ax_slowness_max) plt.xlim(0, 350) plt.xlabel('Time (s)') plt.yticks(fontsize=14); plt.xticks(fontsize=14); plt.ylabel('Slowness (s / km)') plt.show()