def multitaper(st, number_of_tapers=None, time_bandwidth=4., sine=False): """ Output multitaper for stream st RETURNS POWER SPECTRAL DENSITY, units = input units **2 per Hz # TO DO add statistics and optional_output options :param st: obspy stream or trace containing data to plot :param number_of_tapers: Number of tapers to use, Defaults to int(2*time_bandwidth) - 1. This is maximum senseful amount. More tapers will have no great influence on the final spectrum but increase the calculation time. Use fewer tapers for a faster calculation. :param time_bandwidth_div: Smoothing amount, should be between 1 and Nsamps/2. :param sine: if True, will use sine_psd instead of multitaper, sine method should be used for sharp cutoffs or deep valleys, or small sample sizes """ from mtspec import mtspec, sine_psd st = Stream(st) # turn into a stream object in case st is a trace amps = [] freqs = [] for st1 in st: if sine is False: nfft = int(nextpow2((st1.stats.endtime - st1.stats.starttime) * st1.stats.sampling_rate)) amp, freq = mtspec(st1.data, 1./st1.stats.sampling_rate, time_bandwidth=time_bandwidth, number_of_tapers=number_of_tapers, nfft=nfft) else: st1.taper(max_percentage=0.05, type='cosine') amp, freq = sine_psd(st1.data, 1./st1.stats.sampling_rate) amps.append(amp) freqs.append(freq) return freqs, amps
def test_figure3(self): """ Recreate Figure 2 """ data = load_mtdata('PASC.dat.gz') fig = plt.figure() ax1 = fig.add_subplot(3, 1, 1) ax1.plot(data, color='black') ax1.set_xlim(0, len(data)) spec, freq = mtspec(data, 1.0, 1.5, number_of_tapers=1) ax2 = fig.add_subplot(3, 2, 3) ax2.set_yscale('log') ax2.set_xscale('log') ax2.plot(freq, spec, color='black') ax2.set_xlim(freq[0], freq[-1]) spec, freq = mtspec(data, 1.0, 4.5, number_of_tapers=5) ax3 = fig.add_subplot(3, 2, 4) ax3.set_yscale('log') ax3.set_xscale('log') ax3.plot(freq, spec, color='black') ax3.set_xlim(freq[0], freq[-1]) spec, freq = sine_psd(data, 1.0) ax4 = fig.add_subplot(3, 2, 5) ax4.set_yscale('log') ax4.set_xscale('log') ax4.plot(freq, spec, color='black') ax4.set_xlim(freq[0], freq[-1]) spec, freq = mtspec(data, 1.0, 4.5, number_of_tapers=5, quadratic=True) ax5 = fig.add_subplot(3, 2, 6) ax5.set_yscale('log') ax5.set_xscale('log') ax5.plot(freq, spec, color='black') ax5.set_xlim(freq[0], freq[-1]) outfile = os.path.join(self.outpath, 'fig3.pdf') fig.savefig(outfile) stat = os.stat(outfile) self.assertTrue(abs(stat.st_mtime - time.time()) < 3)
def test_sinePSD(self): """ Test for the sine_psd spectra. The result is compared to the output of test_recreatePaperFigures.py in the same directory. This is assumed to be correct because they are identical to the figures in the paper on the machine that created these. """ data = load_mtdata('PASC.dat.gz') # Calculate the spectra. spec, freq = sine_psd(data, 1.0) # No NaNs are supposed to be in the output. self.assertEqual(np.isnan(spec).any(), False) self.assertEqual(np.isnan(freq).any(), False) # Load the good data. datafile = os.path.join(os.path.dirname(__file__), 'data', 'sine_psd.npz') spec2 = np.load(datafile)['spec'] freq2 = np.arange(43201) * 1.15740741e-05 # Compare. np.testing.assert_almost_equal(freq, freq2) np.testing.assert_almost_equal(spec / spec, spec2 / spec, 2)
def test_sinePSDStatistics(self): """ Test for the sine_psd spectra with optional output. The result is compared to the output of test_recreatePaperFigures.py in the same directory. This is assumed to be correct because they are identical to the figures in the paper on the machine that created these. """ data = load_mtdata('PASC.dat.gz') # Calculate the spectra. spec, freq, errors, tapers = sine_psd(data, 1.0, statistics=True) # No NaNs are supposed to be in the output. self.assertEqual(np.isnan(spec).any(), False) self.assertEqual(np.isnan(freq).any(), False) self.assertEqual(np.isnan(errors).any(), False) self.assertEqual(np.isnan(tapers).any(), False) #XXX: assert for errors and tapers is missing # Load the good data. datafile = os.path.join(os.path.dirname(__file__), 'data', 'sine_psd.npz') spec2 = np.load(datafile)['spec'] freq2 = np.arange(43201) * 1.15740741e-05 # Compare #XXX really bad precision for spec (linux 64bit) np.testing.assert_almost_equal(freq, freq2) np.testing.assert_almost_equal(spec / spec, spec2 / spec, 2)
def calculateHVSR(stream, intervals, window_length, method, options, master_method, cutoff_value, smoothing=None, smoothing_count=1, smoothing_constant=40, message_function=None): """ Calculates the HVSR curve. """ # Some arithmetics. length = len(intervals) good_length = window_length // 2 + 1 # Create the matrix that will be used to store the single spectra. hvsr_matrix = np.empty((length, good_length)) # The stream that will be used. # XXX: Add option to use the raw data stream. if method == 'multitaper': if options['nfft']: good_length = options['nfft']// 2 + 1 # Create the matrix that will be used to store the single # spectra. hvsr_matrix = np.empty((length, good_length)) # Loop over each interval for _i, interval in enumerate(intervals): if message_function: message_function('Calculating HVSR %i of %i...' % \ (_i+1, length)) # Figure out which traces are vertical and which are horizontal. v = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'vertical'] h = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'horizontal'] v = stream[v[0]].data[interval[0]: interval[0] + \ window_length] h1 = stream[h[0]].data[interval[0]: interval[0] + \ window_length] h2 = stream[h[1]].data[interval[0]: interval[0] + \ window_length] # Calculate the spectra. v_spec, v_freq = mtspec(v, stream[0].stats.delta, options['time_bandwidth'], nfft=options['nfft'], number_of_tapers=options['number_of_tapers'], quadratic=options['quadratic'], adaptive=options['adaptive']) h1_spec, h1_freq = mtspec(h1, stream[0].stats.delta, options['time_bandwidth'], nfft=options['nfft'], number_of_tapers=options['number_of_tapers'], quadratic=options['quadratic'], adaptive=options['adaptive']) h2_spec, h2_freq = mtspec(h2, stream[0].stats.delta, options['time_bandwidth'], nfft=options['nfft'], number_of_tapers=options['number_of_tapers'], quadratic=options['quadratic'], adaptive=options['adaptive']) # Apply smoothing. if smoothing: if 'konno-ohmachi' in smoothing.lower(): if _i == 0: sm_matrix = calculate_smoothing_matrix(v_freq, smoothing_constant) for _j in xrange(smoothing_count): v_spec = np.dot(v_spec, sm_matrix) h1_spec = np.dot(h1_spec, sm_matrix) h2_spec = np.dot(h2_spec, sm_matrix) hv_spec = np.sqrt(h1_spec * h2_spec) / v_spec if _i == 0: good_freq = v_freq hvsr_matrix[_i, :] = hv_spec # Cut the hvsr matrix. hvsr_matrix = hvsr_matrix[0:length, :] elif method == 'sine multitaper': for _i, interval in enumerate(intervals): if message_function: message_function('Calculating HVSR %i of %i...' % \ (_i+1, length)) # Figure out which traces are vertical and which are horizontal. v = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'vertical'] h = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'horizontal'] v = stream[v[0]].data[interval[0]: interval[0] + \ window_length] h1 = stream[h[0]].data[interval[0]: interval[0] + \ window_length] h2 = stream[h[1]].data[interval[0]: interval[0] + \ window_length] # Calculate the spectra. v_spec, v_freq = sine_psd(v, stream[0].stats.delta, number_of_tapers=options['number_of_tapers'], number_of_iterations=options['number_of_iterations'], degree_of_smoothing=options['degree_of_smoothing']) h1_spec, h1_freq = sine_psd(h1, stream[0].stats.delta, number_of_tapers=options['number_of_tapers'], number_of_iterations=options['number_of_iterations'], degree_of_smoothing=options['degree_of_smoothing']) h2_spec, h2_freq = sine_psd(h2, stream[0].stats.delta, number_of_tapers=options['number_of_tapers'], number_of_iterations=options['number_of_iterations'], degree_of_smoothing=options['degree_of_smoothing']) # Apply smoothing. if smoothing: if 'konno-ohmachi' in smoothing.lower(): if _i == 0: sm_matrix = calculate_smoothing_matrix(v_freq, smoothing_constant) for _j in xrange(smoothing_count): v_spec = np.dot(v_spec, sm_matrix) h1_spec = np.dot(h1_spec, sm_matrix) h2_spec = np.dot(h2_spec, sm_matrix) hv_spec = np.sqrt(h1_spec * h2_spec) / v_spec if _i == 0: good_freq = v_freq # Store it into the matrix if it has the correct length. hvsr_matrix[_i,:] = hv_spec # Cut the hvsr matrix. hvsr_matrix = hvsr_matrix[0:length, :] # Use a single taper spectrum with different available tapers. elif method == 'single taper': for _i, interval in enumerate(intervals): if message_function: message_function('Calculating HVSR %i of %i...' % \ (_i+1, length)) v = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'vertical'] h = [_j for _j, trace in enumerate(stream) if \ trace.stats.orientation == 'horizontal'] v = stream[v[0]].data[interval[0]: interval[0] + \ window_length] h1 = stream[h[0]].data[interval[0]: interval[0] + \ window_length] h2 = stream[h[1]].data[interval[0]: interval[0] + \ window_length] # Calculate the spectra. v_spec, v_freq = single_taper_spectrum(v, stream[0].stats.delta, options['taper']) h1_spec, h1_freq = single_taper_spectrum(h1, stream[0].stats.delta, options['taper']) h2_spec, h2_freq = single_taper_spectrum(h2, stream[0].stats.delta, options['taper']) # Apply smoothing. if smoothing: if 'konno-ohmachi' in smoothing.lower(): if _i == 0: sm_matrix = calculate_smoothing_matrix(v_freq, smoothing_constant) for _j in xrange(smoothing_count): v_spec = np.dot(v_spec, sm_matrix) h1_spec = np.dot(h1_spec, sm_matrix) h2_spec = np.dot(h2_spec, sm_matrix) hv_spec = np.sqrt(h1_spec * h2_spec) / v_spec if _i == 0: good_freq = v_freq # Store it into the matrix if it has the correct length. hvsr_matrix[_i, :] = hv_spec # Cut the hvsr matrix. hvsr_matrix = hvsr_matrix[0:length, :] # Should never happen. else: msg = 'Something went wrong.' raise Exception(msg) # Copy once to be able to calculate standard deviations. original_matrix = deepcopy(hvsr_matrix) # Sort it for quantile operations. hvsr_matrix.sort(axis=0) # Only senseful for mean calculations. Omitted for the median. if cutoff_value != 0.0 and master_method != 'median': hvsr_matrix = hvsr_matrix[int(length * cutoff_value): ceil(length * (1 - cutoff_value)), :] length = len(hvsr_matrix) # Mean. if master_method == 'mean': master_curve = hvsr_matrix.mean(axis=0) # Geometric average. elif master_method == 'geometric average': master_curve = hvsr_matrix.prod(axis=0) ** (1.0 / length) # Median. elif master_method == 'median': # Use another method because interpolation might be necessary. master_curve = np.empty(len(hvsr_matrix[0, :])) error = np.empty((len(master_curve), 2)) for _i in xrange(len(master_curve)): cur_row = hvsr_matrix[:, _i] master_curve[_i] = quantile(cur_row, 50) error[_i, 0] = quantile(cur_row, 25) error[_i, 1] = quantile(cur_row, 75) # Calculate the standard deviation for the two mean methods. if master_method != 'median': error = np.empty((len(master_curve), 2)) std = (hvsr_matrix[:][:] - master_curve) ** 2 std = std.sum(axis=0) std /= float(length) std **= 0.5 error[:, 0] = master_curve - std error[:, 1] = master_curve + std return original_matrix, good_freq, length, master_curve, error
plt.subplot(323) plt.loglog(freq, spec, color='black') plt.xlim(freq[0], freq[-1]) plt.text(x=0.5, y=0.85, s="Single Taper", transform=plt.gca().transAxes, ha="center") spec, freq = mtspec(data, 1.0, 4.5, number_of_tapers=5) plt.subplot(324) plt.loglog(freq, spec, color='black') plt.xlim(freq[0], freq[-1]) plt.text(x=0.5, y=0.85, s="5 Tapers Multitaper", transform=plt.gca().transAxes, ha="center") spec, freq = sine_psd(data, 1.0) plt.subplot(325) plt.loglog(freq, spec, color='black') plt.xlim(freq[0], freq[-1]) plt.text(x=0.5, y=0.85, s="Sine Multitaper", transform=plt.gca().transAxes, ha="center") spec, freq = mtspec(data, 1.0, 4.5, number_of_tapers=5, quadratic=True) plt.subplot(326) plt.loglog(freq, spec, color='black') plt.xlim(freq[0], freq[-1]) plt.text(x=0.5, y=0.85, s="Quadratic Multitaper", transform=plt.gca().transAxes, ha="center")