def _process(tr, tmin, tmax, taper, domain): tr_proc = _extend_extract(tr, tmin, tmax) tr_proc.taper(taper) df = None trspec_proc = None if domain == 'envelope': tr_proc = tr_proc.envelope(inplace=False) tr_proc.set_ydata(num.abs(tr_proc.get_ydata())) elif domain == 'absolute': tr_proc.set_ydata(num.abs(tr_proc.get_ydata())) elif domain in ('frequency_domain', 'log_frequency_domain'): ndata = tr_proc.ydata.size nfft = trace.nextpow2(ndata) padded = num.zeros(nfft, dtype=num.float) padded[:ndata] = tr_proc.ydata spectrum = num.fft.rfft(padded) df = 1.0 / (tr_proc.deltat * nfft) trspec_proc = TraceSpectrum(network=tr_proc.network, station=tr_proc.station, location=tr_proc.location, channel=tr_proc.channel, deltaf=df, fmin=0.0, ydata=spectrum) return tr_proc, trspec_proc
def export_wav(self, data=None, fn=None): if fn is None: fn = self.output_filename() if data is None: nslc_ids, data = self.prepare_data() data = num.asarray(data, dtype=num.float) n = trace.nextpow2(len(data))-len(data) n_frac = float(n)/(n+len(data)) if not self.fps_choice == 'keep original': fps = int(self.fps_choice) arg = int(fps*self.ttotal/num.abs(num.round(self.speed_up))) data = resample(data, arg) nnew = len(data) data = data[:-int(n_frac*nnew)] if self.speed_up<0.: data = data[::-1] data[0] = 0. self.fps = fps scaled = num.int16(data/float(num.max(num.abs(data))) * 32767) write(fn, self.fps, scaled)
def test_qseis_vs_ahfull(self): random.seed(23) vp = 5.8 * km vs = 3.46 * km mod = cake.LayeredModel.from_scanlines( cake.read_nd_model_str(''' 0. %(vp)g %(vs)g 2.6 1264. 600. 20. %(vp)g %(vs)g 2.6 1264. 600.'''.lstrip() % dict(vp=vp / km, vs=vs / km))) store_id_qseis = 'homogeneous_qseis' store_id_ahfull = 'homogeneous_ahfull' qsconf = qseis.QSeisConfig() qsconf.qseis_version = '2006a' textra = 5.0 qsconf.time_region = (gf.meta.Timing('{vel:%g}-%g' % (vp / km, textra)), gf.meta.Timing('{vel:%g}+%g' % (vs / km, textra))) qsconf.cut = (gf.meta.Timing('{vel:%g}-%g' % (vp / km, textra)), gf.meta.Timing('{vel:%g}+%g' % (vs / km, textra))) qsconf.relevel_with_fade_in = True qsconf.fade = (gf.meta.Timing('{vel:%g}-%g' % (vp / km, textra)), gf.meta.Timing('{vel:%g}-%g' % (vp / km, 0.)), gf.meta.Timing('{vel:%g}+%g' % (vs / km, 0.)), gf.meta.Timing('{vel:%g}+%g' % (vs / km, textra))) qsconf.wavelet_duration_samples = 0.001 qsconf.sw_flat_earth_transform = 0 qsconf.filter_surface_effects = 1 qsconf.wavenumber_sampling = 5. qsconf.aliasing_suppression_factor = 0.01 sample_rate = 10. config = gf.meta.ConfigTypeA( id=store_id_qseis, sample_rate=sample_rate, receiver_depth=0. * km, source_depth_min=1. * km, source_depth_max=19 * km, source_depth_delta=6. * km, distance_min=2. * km, distance_max=20 * km, distance_delta=2 * km, modelling_code_id='qseis.2006a', earthmodel_1d=mod, tabulated_phases=[ gf.meta.TPDef(id='begin', definition='p,P,p\\,P\\'), gf.meta.TPDef(id='end', definition='s,S,s\\,S\\'), ]) config.validate() store_dir_qseis = mkdtemp(prefix=store_id_qseis) self.tempdirs.append(store_dir_qseis) gf.store.Store.create_editables(store_dir_qseis, config=config, extra={'qseis': qsconf}) store = gf.store.Store(store_dir_qseis, 'r') store.make_ttt() store.close() try: qseis.build(store_dir_qseis, nworkers=1) except qseis.QSeisError as e: if str(e).find('could not start qseis') != -1: logger.warn('qseis not installed; ' 'skipping test_pyrocko_gf_vs_qseis') return else: raise config = gf.meta.ConfigTypeA( id=store_id_ahfull, sample_rate=sample_rate, receiver_depth=0. * km, source_depth_min=1. * km, source_depth_max=19 * km, source_depth_delta=6. * km, distance_min=2. * km, distance_max=20 * km, distance_delta=2 * km, modelling_code_id='ahfullgreen', earthmodel_1d=mod, tabulated_phases=[ gf.meta.TPDef(id='begin', definition='p,P,p\\,P\\'), gf.meta.TPDef(id='end', definition='s,S,s\\,S\\'), ]) config.validate() store_dir_ahfull = mkdtemp(prefix=store_id_qseis) self.tempdirs.append(store_dir_ahfull) gf.store.Store.create_editables(store_dir_ahfull, config=config) store = gf.store.Store(store_dir_ahfull, 'r') store.make_ttt() store.close() ahfullgreen.build(store_dir_ahfull, nworkers=1) sdepth = rand(config.source_depth_min, config.source_depth_max) sdepth = round( (sdepth - config.source_depth_min) / config.source_depth_delta) * config.source_depth_delta \ + config.source_depth_min source = gf.MTSource(lat=0., lon=0., depth=sdepth) source.m6 = tuple(rand(-1., 1.) for x in range(6)) for ii in range(5): azi = random.random() * 365. dist = rand(config.distance_min, config.distance_max) dist = round(dist / config.distance_delta) * config.distance_delta dnorth = dist * math.cos(azi * d2r) deast = dist * math.sin(azi * d2r) targets = [] for cha in 'rtz': target = gf.Target(quantity='displacement', codes=('', '0000', 'PG', cha), north_shift=dnorth, east_shift=deast, depth=config.receiver_depth, store_id=store_id_ahfull) dist = source.distance_to(target) azi, bazi = source.azibazi_to(target) if cha == 'r': target.azimuth = bazi + 180. target.dip = 0. elif cha == 't': target.azimuth = bazi - 90. target.dip = 0. elif cha == 'z': target.azimuth = 0. target.dip = 90. targets.append(target) runner = qseis.QSeisRunner() conf = qseis.QSeisConfigFull() conf.qseis_version = '2006a' conf.receiver_distances = [dist / km] conf.receiver_azimuths = [azi] conf.receiver_depth = config.receiver_depth / km conf.source_depth = source.depth / km distance_3d_max = math.sqrt(config.distance_max**2 + (config.source_depth_max - config.source_depth_min)**2) nsamples = trace.nextpow2( int( math.ceil(distance_3d_max / vs * 2.0 + 2. * textra) * config.sample_rate)) conf.time_start = -textra conf.time_window = (nsamples - 1) / config.sample_rate conf.time_reduction_velocity = 0.0 conf.nsamples = nsamples conf.source_mech = qseis.QSeisSourceMechMT(mnn=source.mnn, mee=source.mee, mdd=source.mdd, mne=source.mne, mnd=source.mnd, med=source.med) conf.earthmodel_1d = mod conf.sw_flat_earth_transform = 0 conf.filter_surface_effects = 1 conf.wavenumber_sampling = 10. conf.wavelet_duration_samples = 0.001 conf.aliasing_suppression_factor = 0.01 conf.validate() runner.run(conf) trs = runner.get_traces() for tr in trs: pass tr.lowpass(4, config.sample_rate / 8., demean=False) tr.highpass(4, config.sample_rate / 80.) engine = gf.LocalEngine( store_dirs=[store_dir_ahfull, store_dir_qseis]) trs2 = engine.process(source, targets).pyrocko_traces() for tr in trs2: tr.shift(config.deltat) tr.lowpass(4, config.sample_rate / 8., demean=False) tr.highpass(4, config.sample_rate / 80.) # trace.snuffle(trs+trs2) tmin = store.t('{vel:%g}' % (vp / km), source, target) - textra * 0.2 tmax = store.t('{vel:%g}' % (vs / km), source, target) + textra * 0.2 for tr in trs + trs2: tr.chop(tmin, tmax) denom = 0.0 for cha in 'rtz': t1 = g(trs, cha) t2 = g(trs2, cha) denom += num.sum(t1.ydata**2) + num.sum(t2.ydata**2) ds = [] for cha in 'rtz': t1 = g(trs, cha) t2 = g(trs2, cha) ds.append(2.0 * num.sum((t1.ydata - t2.ydata)**2) / denom) ds = num.array(ds) # if not num.all(ds < 0.05): # trace.snuffle(trs+trs2) assert num.all(ds < 0.05)
targets.append(target) runner = qseis.QSeisRunner() conf = qseis.QSeisConfigFull() conf.qseis_version = '2006a' conf.receiver_distances = [dist / km] conf.receiver_azimuths = [azi] conf.receiver_depth = config.receiver_depth / km conf.source_depth = source.depth / km distance_3d_max = math.sqrt(config.distance_max**2 + (config.source_depth_max - config.source_depth_min)**2) nsamples = trace.nextpow2( int( math.ceil(distance_3d_max / vs * 2.0 + 2. * textra) * config.sample_rate)) conf.time_start = -textra conf.time_window = (nsamples - 1) / config.sample_rate conf.time_reduction_velocity = 0.0 conf.nsamples = nsamples conf.source_mech = qseis.QSeisSourceMechMT(mnn=source.mnn, mee=source.mee, mdd=source.mdd, mne=source.mne, mnd=source.mnd, med=source.med) conf.earthmodel_1d = mod conf.sw_flat_earth_transform = 0
def make_seismogram( vp, vs, density, qp, qs, x, f, m6, quantity, deltat, stf=None, wanted_components='ned', want_far=True, want_intermediate=True, want_near=True, npad_levelling=40, out_alignment=0.): if stf is None: stf = Impulse() x = num.asarray(x, num.float) f = num.asarray(f, num.float) m6 = num.asarray(m6, num.float) r = math.sqrt(num.sum(x**2)) tp = r / vp ts = r / vs if ts <= tp: raise AhfullgreenError('unsupported material properties') tpad = stf.t_cutoff() or deltat * 10. tstart = tp - tpad - npad_levelling * deltat tstart = out_alignment + round((tstart - out_alignment) / deltat) * deltat nt = trace.nextpow2(int(math.ceil( (ts - tp + 2 * tpad + 2*npad_levelling * deltat) / deltat))) nspec = nt // 2 + 1 specs = [] for component in 'ned': if component in wanted_components: specs.append(num.zeros(nspec, dtype=num.complex)) else: specs.append(None) oc_c = { 'displacement': 1, # treated in post processing 'velocity': 1, 'acceleration': 2}[quantity] out_spec_delta = float(2.0 * math.pi / (nt*deltat)) out_spec_offset = 0.0 omega = out_spec_offset + out_spec_delta * num.arange(nspec) coeffs_stf = stf(omega/(2.*math.pi)).astype(num.complex) coeffs_stf *= num.exp(1.0j * omega * tstart) omega_max = 2.0 * math.pi * 0.5 / deltat omega_cut = omega_max * 0.75 icut = int(num.ceil((omega_cut - out_spec_offset) / out_spec_delta)) coeffs_stf[icut:] *= 0.5 + 0.5 * num.cos( math.pi * num.minimum( 1.0, (omega[icut:] - omega_cut) / (omega_max - omega_cut))) ext.add_seismogram( float(vp), float(vs), float(density), float(qp), float(qs), x, f, m6, oc_c, out_spec_delta, out_spec_offset, specs[0], specs[1], specs[2], want_far, want_intermediate, want_near) outs = [] for i, component in enumerate('ned'): if component not in wanted_components: outs.append(None) out = num.fft.irfft(coeffs_stf * specs[i], nt) out /= deltat assert out.size // 2 + 1 == specs[i].size m1 = num.mean( out[:npad_levelling] * num.linspace(1., 0., npad_levelling)) out -= m1 * 2. if quantity == 'displacement': out = num.cumsum(out) * deltat outs.append(out) outs_wanted = [] for component in wanted_components: i = 'ned'.find(component) if i != -1: outs_wanted.append(outs[i]) else: outs_wanted.append(None) return tstart, outs_wanted