def get_transfer_function(self, codes): if self.seismogram_quantity == 'displacement': return None elif self.seismogram_quantity == 'velocity': return trace.DifferentiationResponse(1) elif self.seismogram_quantity == 'acceleration': return trace.DifferentiationResponse(2) elif self.seismogram_quantity == 'counts': raise NotImplemented()
def test_dump_load(self): r = trace.FrequencyResponse() r = trace.PoleZeroResponse([0j, 0j], [1j, 2j, 1 + 3j, 1 - 3j], 1.0) r.regularize() r2 = guts.load_string(r.dump()) assert cnumeq(r.poles, r2.poles, 1e-6) assert cnumeq(r.zeros, r2.zeros, 1e-6) assert numeq(r.constant, r2.constant) r = trace.SampledResponse([0., 1., 5., 10.], [0., 1., 1., 0.]) r.regularize() r2 = guts.load_string(r.dump()) assert numeq(r.frequencies, r2.frequencies, 1e-6) assert cnumeq(r.values, r2.values, 1e-6) r = trace.IntegrationResponse(2, 5.0) r2 = guts.load_string(r.dump()) assert numeq(r.n, r2.n) assert numeq(r.gain, r2.gain, 1e-6) r = trace.DifferentiationResponse(2, 5.0) r2 = guts.load_string(r.dump()) assert numeq(r.n, r2.n) assert numeq(r.gain, r2.gain, 1e-6) r = trace.AnalogFilterResponse(a=[1.0, 2.0, 3.0], b=[2.0, 3.0]) r2 = guts.load_string(r.dump()) assert numeq(r.a, r2.a, 1e-6) assert numeq(r.b, r2.b, 1e-6)
def testIntegrationDifferentiation(self): tlen = 100. dt = 0.1 n = int(tlen / dt) f = 0.5 tfade = tlen / 10. xdata = num.arange(n) * dt ydata = num.sin(xdata * 2. * num.pi * f) a = trace.Trace(channel='A', deltat=dt, ydata=ydata) b = a.transfer(tfade, (0.0, 0.1, 2., 3.), transfer_function=trace.IntegrationResponse()) b.set_codes(channel='B') c = a.transfer(tfade, (0.0, 0.1, 2., 3.), transfer_function=trace.DifferentiationResponse()) c.set_codes(channel='C') eps = 0.001 xdata = b.get_xdata() ydata = b.get_ydata() ydata_shouldbe = -num.cos(xdata * 2 * num.pi * f) / (2. * num.pi * f) assert num.amax(num.abs(ydata-ydata_shouldbe)) < eps, \ 'integration failed' xdata = c.get_xdata() ydata = c.get_ydata() ydata_shouldbe = num.cos(xdata * 2 * num.pi * f) * (2. * num.pi * f) assert num.amax(num.abs(ydata-ydata_shouldbe)) < eps, \ 'differentiation failed'
def test_differentiation(self): dt = 0.1 dur = 10.0 n = int(round(dur / dt)) t0 = 5.0 tau = 0.25 t = num.arange(n)*dt y = num.exp(-(t-t0)**2/tau**2) a = trace.Trace(location='A', deltat=dt, ydata=y) dydt = num.exp(-(t-t0)**2/tau**2) * -2.0 / tau**2 * (t-t0) b = trace.Trace(location='B', deltat=dt, ydata=dydt) c = a.transfer( transfer_function=trace.DifferentiationResponse(), demean=False) c.set_codes(location='C') d = a.differentiate(inplace=False, order=4) d.set_codes(location='D') e = a.differentiate(inplace=False, order=2) e.set_codes(location='E') bmax = b.absmax()[1] assert numeq(b.ydata, c.ydata, 0.0001*bmax) assert numeq(b.ydata, d.ydata, 0.03*bmax) assert numeq(b.ydata, e.ydata, 0.2*bmax) # trace.snuffle([a, b, c, d, e]) c2 = c.transfer( transfer_function=trace.DifferentiationResponse(), demean=False) c2.set_codes(location='C2') c2max = c2.absmax()[1] d2 = a.differentiate(inplace=False, n=2, order=4) d2.set_codes(location='D2') e2 = a.differentiate(inplace=False, n=2, order=2) e2.set_codes(location='E2') assert numeq(c2.ydata, d2.ydata, 0.02*c2max) assert numeq(c2.ydata, e2.ydata, 0.1*c2max)
def testIntegrationDifferentiation(self): fmin = 0.1 fmax = 2.0 for tlen in [100., 1000., 10000]: for dt in [0.1, 0.05]: for f in [0.2, 0.5, 1.0]: n = int(tlen / dt) tfade = 2.0 / fmin xdata = num.arange(n) * dt ydata = num.sin(xdata * 2. * num.pi * f) a = trace.Trace(channel='A', deltat=dt, ydata=ydata) b = a.transfer( tfade, (fmin / 2., fmin, fmax, fmax * 2.), transfer_function=trace.IntegrationResponse()) b.set_codes(channel='B') c = a.transfer( tfade, (fmin / 2., fmin, fmax, fmax * 2.), transfer_function=trace.DifferentiationResponse()) c.set_codes(channel='C') eps = 0.005 xdata = b.get_xdata() ydata = b.get_ydata() ydata_shouldbe = -num.cos(xdata * 2 * num.pi * f) / ( 2. * num.pi * f) # if num.amax(num.abs(ydata-ydata_shouldbe)) > eps: # b_shouldbe = trace.Trace( # channel='B', location='integrated', # deltat=dt, ydata=ydata_shouldbe, tmin=xdata[0]) # trace.snuffle([b, b_shouldbe]) assert num.amax(num.abs(ydata-ydata_shouldbe)) < eps, \ 'integration failed' xdata = c.get_xdata() ydata = c.get_ydata() ydata_shouldbe = num.cos( xdata * 2 * num.pi * f) * (2. * num.pi * f) # if num.amax(num.abs(ydata-ydata_shouldbe)) > eps: # c_shouldbe = trace.Trace( # channel='C', location='differentiated', # deltat=dt, ydata=ydata_shouldbe, tmin=xdata[0]) # trace.snuffle([c, c_shouldbe]) assert num.amax(num.abs(ydata-ydata_shouldbe)) < eps, \ 'differentiation failed'
from pyrocko.guts import StringChoice, StringPattern, UnicodePattern, String,\ Unicode, Int, Float, List, Object, Timestamp, ValidationError, TBase from pyrocko.guts import load_xml # noqa from pyrocko import trace, model, util guts_prefix = 'pf' logger = logging.getLogger('pyrocko.fdsn.station') conversion = { ('M', 'M'): None, ('M/S', 'M'): trace.IntegrationResponse(1), ('M/S**2', 'M'): trace.IntegrationResponse(2), ('M', 'M/S'): trace.DifferentiationResponse(1), ('M/S', 'M/S'): None, ('M/S**2', 'M/S'): trace.IntegrationResponse(1), ('M', 'M/S**2'): trace.DifferentiationResponse(2), ('M/S', 'M/S**2'): trace.DifferentiationResponse(1), ('M/S**2', 'M/S**2'): None } class NoResponseInformation(Exception): pass class MultipleResponseInformation(Exception): pass
def get_response(self, obj, quantity='displacement'): if (self.responses is None or len(self.responses) == 0) \ and (self.responses_stationxml is None or len(self.responses_stationxml) == 0): raise NotFound('No response information available.') quantity_to_unit = { 'displacement': 'M', 'velocity': 'M/S', 'acceleration': 'M/S**2' } if self.is_blacklisted(obj): raise NotFound('Response is blacklisted:', self.get_nslc(obj)) if not self.is_whitelisted(obj): raise NotFound('Response is not on whitelist:', self.get_nslc(obj)) net, sta, loc, cha = self.get_nslc(obj) tmin, tmax = self.get_tmin_tmax(obj) keys_x = [(net, sta, loc, cha), (net, sta, '', cha), ('', sta, '', cha)] keys = [] for k in keys_x: if k not in keys: keys.append(k) candidates = [] for k in keys: if k in self.responses: for x in self.responses[k]: if x.tmin < tmin and (x.tmax is None or tmax < x.tmax): if quantity == 'displacement': candidates.append(x.response) elif quantity == 'velocity': candidates.append( trace.MultiplyResponse([ x.response, trace.DifferentiationResponse() ])) elif quantity == 'acceleration': candidates.append( trace.MultiplyResponse([ x.response, trace.DifferentiationResponse(2) ])) else: assert False for sx in self.responses_stationxml: try: candidates.append( sx.get_pyrocko_response( (net, sta, loc, cha), timespan=(tmin, tmax), fake_input_units=quantity_to_unit[quantity])) except (fs.NoResponseInformation, fs.MultipleResponseInformation): pass if len(candidates) == 1: return candidates[0] elif len(candidates) == 0: raise NotFound('No response found:', (net, sta, loc, cha)) else: raise NotFound('Multiple responses found:', (net, sta, loc, cha))
def evaluate(self, engine, source, targets, dataset=None, trs=None, extra_responses=[], debug=False): from ..waveform import target as base trs_processed = [] trs_orig = [] for itarget, target in enumerate(targets): if target.codes[-1] not in self.channels: continue store = engine.get_store(target.store_id) tmin = source.time + store.t(self.timing_tmin, source, target) tmax = source.time + store.t(self.timing_tmax, source, target) if self.fmin is not None and self.fmax is not None: freqlimits = [ self.fmin / 2., self.fmin, self.fmax, self.fmax * 2. ] tfade = 1. / self.fmin else: freqlimits = None tfade = 0.0 if dataset is not None: bazi = base.backazimuth_for_waveform(target.azimuth, target.codes) tr = dataset.get_waveform(target.codes, tinc_cache=1.0 / self.fmin, quantity=self.quantity, tmin=tmin, tmax=tmax, freqlimits=freqlimits, tfade=tfade, deltat=store.config.deltat, cache=True, backazimuth=bazi) else: tr = trs[itarget] tr.extend(tmin - tfade, tmax + tfade, fillmethod='repeat') tr = tr.transfer(freqlimits=freqlimits, tfade=tfade) trs_orig.append(tr) tr = tr.copy() responses = [] responses.extend(extra_responses) ndiff = \ WaveformQuantity.choices.index(self.quantity) - \ WaveformQuantity.choices.index(target.quantity) if ndiff > 0: responses.append(trace.DifferentiationResponse(ndiff)) if ndiff < 0: responses.append(trace.IntegrationResponse(-ndiff)) if self.response: responses.append(self.response) if self.named_response: responses.append(NamedResponse.map[self.named_response]) if responses: trans = trace.MultiplyResponse(responses) try: tr = tr.transfer(transfer_function=trans) except trace.TraceTooShort: raise FeatureMeasurementFailed('transfer: trace too short') if tmin is None or tmax is None: raise FeatureMeasurementFailed( 'timing determination failed (phase unavailable?)') tr.chop(tmin, tmax) tr.set_location(tr.location + '-' + self.name + '-proc') trs_processed.append(tr) markers = [] marker_candidates = [] if self.method in ['peak_component', 'peak_to_peak_component']: component_amp_maxs = [] for tr in trs_processed: y = tr.get_ydata() if self.method == 'peak_component': yabs = num.abs(y) i_at_amax = num.argmax(yabs) amax = yabs[i_at_amax] if debug: t_at_amax = tr.tmin + i_at_amax * tr.deltat mark = marker.Marker([tr.nslc_id], t_at_amax, t_at_amax, 0) marker_candidates.append(mark) component_amp_maxs.append(amax) else: i_at_amax = num.argmax(y) i_at_amin = num.argmin(y) amax = y[i_at_amax] amin = y[i_at_amin] if debug: t_at_amax = tr.tmin + i_at_amax * tr.deltat t_at_amin = tr.tmin + i_at_amin * tr.deltat ts = sorted([t_at_amax, t_at_amin]) mark = marker.Marker([tr.nslc_id], ts[0], ts[1], 0) marker_candidates.append(mark) component_amp_maxs.append(amax - amin) i_at_amax = num.argmax(component_amp_maxs) if debug: markers.append(marker_candidates[i_at_amax]) amp_max = component_amp_maxs[i_at_amax] elif self.method == 'peak_absolute_vector': trsum = None for tr in trs_processed: tr.set_ydata(tr.get_ydata()**2) if trsum is None: trsum = tr else: trsum.add(tr) trsum.set_ydata(num.sqrt(tr.get_ydata)) trsum.set_codes(channel='SUM') yabs = trsum.get_ydata() i_at_amax = num.argmax(yabs) amax = yabs[i_at_amax] t_at_amax = tr.tmin + i_at_amax * tr.deltat amp_max = amax if debug: markers.append( marker.Marker([trsum.nslc_id], t_at_amax, t_at_amax, 0)) trs_processed.append(trsum) elif self.method == 'spectral_average': component_amp_maxs = [] for tr in trs_processed: freqs, values = tr.spectrum() component_amp_maxs.append( num.mean( num.abs(values[num.logical_and(self.fmin <= freqs, freqs <= self.fmax)]))) amp_max = num.mean(component_amp_maxs) if debug: trs_out = [] for tr in trs_orig: tr_out = tr.copy() tr_out.set_location(tr_out.location + '-' + self.name) trs_out.append(tr_out) return amp_max, (trs_out + trs_processed, markers) return amp_max, None
def test_pulse(self): store_dir = self.get_pulse_store_dir() engine = gf.LocalEngine(store_dirs=[store_dir]) sources = [ gf.ExplosionSource( time=0.0, depth=depth, moment=moment) for moment in (1.0, 2.0, 3.0) for depth in [100., 200., 300.] ] targets = [ gf.Target( quantity=quantity, codes=('', 'STA', quantity, component), north_shift=500., east_shift=0.) for component in 'ZNE' for quantity in ['displacement', 'velocity', 'acceleration'] ] pulse = engine.get_store_extra(None, 'pulse') store = engine.get_store('pulse') response = engine.process(sources=sources, targets=targets) for source, target, tr in response.iter_results(): t = tr.get_xdata() dist = math.sqrt((source.depth - target.depth)**2 + source.distance_to(target)**2) data = pulse.evaluate(dist, t-source.time) phi = math.atan2((source.depth - target.depth), source.distance_to(target)) * r2d azi, bazi = source.azibazi_to(target) data *= source.get_moment(store) * math.sqrt(2./3.) if tr.channel.endswith('N'): data *= math.cos(phi*d2r) * math.cos(azi*d2r) elif tr.channel.endswith('E'): data *= math.cos(phi*d2r) * math.sin(azi*d2r) elif tr.channel.endswith('Z'): data *= math.sin(phi*d2r) tr2 = tr.copy(data=False) tr2.set_ydata(data) tr2.set_codes(location='X') if target.quantity == 'velocity': tr2 = tr2.transfer( transfer_function=trace.DifferentiationResponse(), demean=False) elif target.quantity == 'acceleration': tr2 = tr2.transfer( transfer_function=trace.DifferentiationResponse(2), demean=False) # trace.snuffle([tr, tr2]) amax = num.max(num.abs(tr.ydata)) if amax > 1e-10: # print(num.max(num.abs(tr2.ydata - tr.ydata) / amax)) assert num.all(num.abs(tr2.ydata - tr.ydata) < 0.05 * amax)
def post_process(self, engine, source, tr_syn): tr_syn = tr_syn.pyrocko_trace() nslc = self.codes config = self.misfit_config tmin_fit, tmax_fit, tfade, tfade_taper = \ self.get_taper_params(engine, source) ds = self.get_dataset() tobs, tsyn = self.get_pick_shift(engine, source) if None not in (tobs, tsyn): tobs_shift = tobs - tsyn else: tobs_shift = 0.0 tr_syn.extend(tmin_fit - tfade * 2.0, tmax_fit + tfade * 2.0, fillmethod='repeat') freqlimits = self.get_freqlimits() if config.quantity == 'displacement': syn_resp = None elif config.quantity == 'velocity': syn_resp = trace.DifferentiationResponse(1) elif config.quantity == 'acceleration': syn_resp = trace.DifferentiationResponse(2) else: GrondError('Unsupported quantity: %s' % config.quantity) tr_syn = tr_syn.transfer(freqlimits=freqlimits, tfade=tfade, transfer_function=syn_resp) tr_syn.chop(tmin_fit - 2 * tfade, tmax_fit + 2 * tfade) tmin_obs, tmax_obs = self.get_cutout_timespan(tmin_fit + tobs_shift, tmax_fit + tobs_shift, tfade) try: tr_obs = ds.get_waveform( nslc, quantity=config.quantity, tinc_cache=1.0 / (config.fmin or 0.1 * config.fmax), tmin=tmin_fit + tobs_shift - tfade, tmax=tmax_fit + tobs_shift + tfade, tfade=tfade, freqlimits=freqlimits, deltat=tr_syn.deltat, cache=True, backazimuth=self.get_backazimuth_for_waveform()) if tobs_shift != 0.0: tr_obs = tr_obs.copy() tr_obs.shift(-tobs_shift) mr = misfit(tr_obs, tr_syn, taper=trace.CosTaper(tmin_fit - tfade_taper, tmin_fit, tmax_fit, tmax_fit + tfade_taper), domain=config.domain, exponent=config.norm_exponent, flip=self.flip_norm, result_mode=self._result_mode, tautoshift_max=config.tautoshift_max, autoshift_penalty_max=config.autoshift_penalty_max, subtargets=self._piggyback_subtargets) self._piggyback_subtargets = [] mr.tobs_shift = float(tobs_shift) mr.tsyn_pick = float_or_none(tsyn) return mr except NotFound as e: logger.debug(str(e)) raise gf.SeismosizerError('No waveform data: %s' % str(e))
def post_process(response, norths, easts, stf_spec, stations=False, show=True, savedir=None, save=True, quantity="velocity"): nnorth = norths.size neast = easts.size norths2, easts2 = coords_2d(norths, easts) by_i = defaultdict(list) traces = [] for source, target, tr in response.iter_results(): tr = tr.copy() if quantity == "velocity": trans = trace.DifferentiationResponse(1) if quantity == "acceleration": trans = trace.DifferentiationResponse(2) if quantity is not "displacement": trans = trace.MultiplyResponse([trans, stf_spec]) tr = tr.transfer(transfer_function=trans) #tr.highpass(4, 0.5) #tr.lowpass(4, 4.0) tr_resamp = tr.copy() # uncomment to active resampling to get a smooth image (slow): tr_resamp.resample(tr.deltat * 0.25) by_i[int(target.codes[1])].append(tr_resamp) traces.append(tr) values = num.zeros(nnorth * neast) from pyrocko import trace as trd # if stations is True: # trd.snuffle(traces) # if stations is True: # from pyrocko import io # io.save(traces, "traces_pgv.mseed") plot_trs = [] for i in range(norths2.size): trs = by_i[i] if trs: ysum = num.sqrt(sum(tr.ydata**2 for tr in trs)) ymax = num.max(ysum) values[i] = ymax if norths2[i] == easts2[i]: plot_trs.extend(trs) values = values.reshape((norths.size, easts.size)) if save is True: path = savedir + '/shakemap.pkl' f = open(path, 'wb') pickle.dump([values, easts, norths], f) f.close() return values