Zjednodušený automatický picker

pro teleseismickou P vlnu

In [1]:
%pylab inline
from __future__ import print_function
import matplotlib.pylab as plt
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = 12, 8
import warnings
warnings.filterwarnings("ignore")
Populating the interactive namespace from numpy and matplotlib

Budeme potřebovat:

  • stažení seznamu s eventy
  • stažení staničních metadat
  • stažení seismických signálů
  • odstranění přístrojové odezvy
  • TauP
  • trigger
  • xcorrel

Načtení funkcí a modulů, clienty si pro lepší přehlednost přejmenujeme:

In [2]:
from obspy.clients.fdsn import Client as Client_FDSN
from obspy.clients.syngine import Client as Client_Syngine
from obspy.clients.fdsn.mass_downloader import RectangularDomain, Restrictions, MassDownloader
from obspy import UTCDateTime, read_inventory, read
from obspy.taup import TauPyModel
from obspy.geodetics.base import calc_vincenty_inverse, kilometer2degrees
from obspy.signal.trigger import recursive_sta_lta, plot_trigger, trigger_onset
from obspy.signal.cross_correlation import xcorr_pick_correction
from obspy.imaging.cm import pqlx
import numpy as np
import os, glob, shutil

Vstupní parametry

In [3]:
# oblast se stanicema
lon1 = 11; lon2 = 15
lat1 = 48.5; lat2 = 51
# časové období pro eventy
t1 = UTCDateTime('2015-01-01')
t2 = UTCDateTime('2016-01-01')
# rádius pro eventy (ve stupních)
rad1 = 20; rad2 = 100
# minimální magnitudo
minmagn = 5.0
# preferovaná frekvence signálů (v Hz)
sample_rate = 100
# simulační filtr WWSSN-SP
paz_wwssn_sp =     {'poles': [-3.367788+3.731514j, -3.367788-3.731514j,
                              -7.037168+4.545562j, -7.037168-4.545562j],
                    'zeros': [0j, 0j],
                    'gain': 70.18386,
                    'sensitivity': 1.}
# trigger
sta = 1   # v sec
lta = 10  # v sec
trig1 = 4
trig2 = 3

# inicializace TAUP
model = TauPyModel(model="iasp91")

Budem potřebovat pomocné funkce pro sesazení signálů a pro vykreslování:

In [4]:
def median_picked(st, key, offset):
    tr_mean = st[0].copy()
    for i,tr in enumerate(st):
        tr1 = tr.copy().trim(tr.stats[key]+offset[0], tr.stats[key]+offset[1])
        tr1_data = tr1.data / np.linalg.norm(tr1.data)
        if i == 0:
            signals = tr1.data / np.linalg.norm(tr1.data)
        else:
            signals = np.vstack((signals, tr1.data / np.linalg.norm(tr1.data)))
    tr_mean.data = np.median(signals, axis=0)
    # rekursivní sta-lta trigger
    df = tr_mean.stats.sampling_rate
    cft = recursive_sta_lta(tr_mean.data, int(sta * df), int(lta * df))
    t_teor_offs = trigger_onset(cft, trig1, trig2)[0][0] / df
    tr_mean.stats.t_correl = tr_mean.stats.starttime + t_teor_offs
    return tr_mean

def plot_all_picked(st, key, offset, show_mean=True):
    fig = plt.figure(figsize=(16,5))
    ax = fig.add_subplot(111)
    for i,tr in enumerate(st):
        tr1 = tr.copy().trim(tr.stats[key]+offset[0], tr.stats[key]+offset[1])
        tm1 = tr1.times()
        tr1_data = tr1.data / np.linalg.norm(tr1.data)
        ax.plot(tm1, tr1_data)
    if show_mean:
        tr_mean =  median_picked(st, key, offset)
        ax.plot(tm1, tr_mean.data, 'k-')
    ax.set_xlim((0, max(tm1)))
    ax.set_title("Sorted: " + key)
    return

def kresli_residua(st, baz, ax=None):

    _lat, _lon, _prel, _stats = [],[],[],[]
    for tr in st:
        if tr.stats.station in ['AAE21']: continue
        _lat.append(tr.stats.latitude)
        _lon.append(tr.stats.longitude)
        _prel.append(tr.stats.t_correl - tr.stats.t_teor)
        _stats.append(tr.stats.station)
        # korekce
        if tr.stats.station in ['HKWD']:
            _prel[-1] -= 1.
    numcols, numrows = 100, 100
    xi = np.linspace(np.amin(_lon), np.amax(_lon), numcols)
    yi = np.linspace(np.amin(_lat), np.amax(_lat), numrows)
    xi, yi = np.meshgrid(xi, yi)
    zi = griddata(_lon, _lat, _prel, xi, yi, interp='linear')
    if not ax:
        fig = plt.figure(figsize=(15,10))
        ax = fig.add_subplot(111)
    im = ax.contourf(xi, yi, zi, 20, cmap=pqlx)
    ax.scatter(_lon, _lat, c=_prel, s=50, vmin=zi.min(), vmax=zi.max(), marker='v', edgecolors='k', 
               linewidths=1, cmap=pqlx)
    offs = 0.03
    for i,stat in enumerate(_stats):
        ax.text(_lon[i]+offs, _lat[i]+offs, stat)
    ax.set_aspect('equal')
    plt.colorbar(im, ax=ax)
    # arrow
    x1,x2 = ax.get_xlim()
    y1,y2 = ax.get_ylim()
    x0 = x1 + 0.9*(x2-x1)
    y0 = y1 + 0.9*(y2-y1)
    d = (x2-x1) / 7
    phi = (baz - 180) * np.pi/180
    ax.arrow(x0, y0, d*np.sin(phi), d*np.cos(phi), width=0.02, head_width=0.1, length_includes_head=True, color='r')
    plt.draw()

Seznam eventů

In [5]:
# referenční bod (střed oblasti)
lat0 = 0.5 * (lat1 + lat2)
lon0 = 0.5 * (lon1 + lon2)

# eventy z finálního ISC katalogu
client = Client_FDSN('ISC')
catalog = client.get_events(starttime=t1, endtime=t2,
                latitude=lat0, longitude=lon0, minradius=rad1, maxradius=rad2,
                minmagnitude=minmagn, orderby="time-asc", contributor="ISC")

# vykreslení
plt.rcParams['figure.figsize'] = 12, 8
catalog.plot(),
Out[5]:
(<matplotlib.figure.Figure at 0xe27add8>,)

Pro zjednodušení vybereme jen jeden event:

In [6]:
# for event in catalog:  # normálně by byl cyklus přes všechny eventy
event = catalog.filter("time > 2015-08-06T09:00", "time < 2015-08-06T09:30")[0]
print(event.__str__().split('\n')[0])

# vezmi nejlépe určené ohnisko u daného eventu
origin = event.preferred_origin() or event.origins[0]
print(origin.__str__().split('quality')[0])
Event:	2015-08-06T09:22:28.920000Z | +36.457, +140.637 | 5.31 mb
Origin
	        resource_id: ResourceIdentifier(id="smi:ISC/origid=609802003")
	               time: UTCDateTime(2015, 8, 6, 9, 22, 28, 920000) [uncertainty=0.34]
	          longitude: 140.6373
	           latitude: 36.4569
	              depth: 56372.0
	            

Stažení staničních signálů a metadat

za pomoci MassDownloader

In [7]:
# !!!(stahování chvíli trvá, takže nejdřív spustit a pak vysvětlovat)

# stahovaný úsek: start = origin_time, délka = 30 min
starttime = origin.time
endtime = starttime + 30*60

# oblast
domain = RectangularDomain(minlatitude=lat1, maxlatitude=lat2, minlongitude=lon1, maxlongitude=lon2)

# restrikce
restrict = Restrictions(
    starttime=starttime, endtime=endtime,
    sanitize=True,   # pouze stanice s metadatama
    minimum_length=0.8,
    reject_channels_with_gaps=True,
    minimum_interstation_distance_in_m=1000,
    exclude_networks = ["Z3"],   # jsou na heslo
    channel_priorities=["HHZ", "BHZ", "EHZ", "SHZ"],
    location_priorities=["", "00", "01"])

# kam uložit mseedy a stationxml
mseed_storage = origin.time.strftime("%Y%m%d%H%M%S")
stationxml_storage = mseed_storage

# stahování dat a metadat
mdl = MassDownloader()  
mdl.download(domain, restrict, download_chunk_size_in_mb=50, threads_per_client=3, 
             mseed_storage=mseed_storage, stationxml_storage=stationxml_storage),
[2018-11-14 13:39:49,157] - obspy.clients.fdsn.mass_downloader - INFO: Initializing FDSN client(s) for BGR, EMSC, ETH, GEONET, GFZ, ICGC, INGV, IPGP, ISC, KOERI, LMU, NCEDC, NIEP, NOA, RESIF, SCEDC, TEXNET, USGS, USP, ORFEUS, IRIS.
[2018-11-14 13:39:49,306] - obspy.clients.fdsn.mass_downloader - INFO: Cannot use client 'ISC' as it does not have 'dataselect' and/or 'station' services.
[2018-11-14 13:39:50,710] - obspy.clients.fdsn.mass_downloader - INFO: Cannot use client 'EMSC' as it does not have 'dataselect' and/or 'station' services.
[2018-11-14 13:39:50,733] - obspy.clients.fdsn.mass_downloader - WARNING: Failed to initialize client 'ORFEUS'.
[2018-11-14 13:39:50,835] - obspy.clients.fdsn.mass_downloader - INFO: Cannot use client 'USGS' as it does not have 'dataselect' and/or 'station' services.
[2018-11-14 13:39:54,469] - obspy.clients.fdsn.mass_downloader - INFO: Successfully initialized 17 client(s): BGR, ETH, GEONET, GFZ, ICGC, INGV, IPGP, KOERI, LMU, NCEDC, NIEP, NOA, RESIF, SCEDC, TEXNET, USP, IRIS.
[2018-11-14 13:39:54,471] - obspy.clients.fdsn.mass_downloader - INFO: Total acquired or preexisting stations: 0
[2018-11-14 13:39:54,474] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Requesting unreliable availability.
[2018-11-14 13:39:58,739] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully requested availability (4.26 seconds)
[2018-11-14 13:39:59,002] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Found 62 stations (62 channels).
[2018-11-14 13:39:59,009] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Will attempt to download data from 62 stations.
[2018-11-14 13:39:59,073] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Status for 62 time intervals/channels before downloading: NEEDS_DOWNLOADING
[2018-11-14 13:40:17,769] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully downloaded 10 channels (of 12)
[2018-11-14 13:40:56,243] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully downloaded 49 channels (of 50)
[2018-11-14 13:40:56,256] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Launching basic QC checks...
[2018-11-14 13:40:56,571] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Downloaded 10.7 MB [190.97 KB/sec] of data, 0.0 MB of which were discarded afterwards.
[2018-11-14 13:40:56,575] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Status for 3 time intervals/channels after downloading: DOWNLOAD_FAILED
[2018-11-14 13:40:56,575] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Status for 59 time intervals/channels after downloading: DOWNLOADED
[2018-11-14 13:40:56,862] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully downloaded '20150806092228\GR.GEB5.xml'.
[2018-11-14 13:40:56,872] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully downloaded '20150806092228\GR.GRA1.xml'.
[2018-11-14 13:40:57,132] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Successfully downloaded '20150806092228\TH.ZEU.xml'.
...
...
...
[2018-11-14 13:42:16,431] - obspy.clients.fdsn.mass_downloader - INFO: ============================== Final report
[2018-11-14 13:42:16,436] - obspy.clients.fdsn.mass_downloader - INFO: 0 MiniSEED files [0.0 MB] already existed.
[2018-11-14 13:42:16,437] - obspy.clients.fdsn.mass_downloader - INFO: 0 StationXML files [0.0 MB] already existed.
[2018-11-14 13:42:16,441] - obspy.clients.fdsn.mass_downloader - INFO: Client 'GFZ' - Acquired 4 MiniSEED files [0.6 MB].
[2018-11-14 13:42:16,444] - obspy.clients.fdsn.mass_downloader - INFO: Client 'GFZ' - Acquired 4 StationXML files [0.0 MB].
[2018-11-14 13:42:16,444] - obspy.clients.fdsn.mass_downloader - INFO: Client 'TEXNET' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,447] - obspy.clients.fdsn.mass_downloader - INFO: Client 'TEXNET' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,447] - obspy.clients.fdsn.mass_downloader - INFO: Client 'RESIF' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,448] - obspy.clients.fdsn.mass_downloader - INFO: Client 'RESIF' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,451] - obspy.clients.fdsn.mass_downloader - INFO: Client 'IPGP' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,453] - obspy.clients.fdsn.mass_downloader - INFO: Client 'IPGP' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,457] - obspy.clients.fdsn.mass_downloader - INFO: Client 'GEONET' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,467] - obspy.clients.fdsn.mass_downloader - INFO: Client 'GEONET' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,470] - obspy.clients.fdsn.mass_downloader - INFO: Client 'IRIS' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,473] - obspy.clients.fdsn.mass_downloader - INFO: Client 'IRIS' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,476] - obspy.clients.fdsn.mass_downloader - INFO: Client 'SCEDC' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,479] - obspy.clients.fdsn.mass_downloader - INFO: Client 'SCEDC' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,482] - obspy.clients.fdsn.mass_downloader - INFO: Client 'ICGC' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,483] - obspy.clients.fdsn.mass_downloader - INFO: Client 'ICGC' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,489] - obspy.clients.fdsn.mass_downloader - INFO: Client 'LMU' - Acquired 8 MiniSEED files [3.5 MB].
[2018-11-14 13:42:16,490] - obspy.clients.fdsn.mass_downloader - INFO: Client 'LMU' - Acquired 8 StationXML files [0.1 MB].
[2018-11-14 13:42:16,493] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NOA' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,496] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NOA' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,497] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NIEP' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,500] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NIEP' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,503] - obspy.clients.fdsn.mass_downloader - INFO: Client 'KOERI' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,506] - obspy.clients.fdsn.mass_downloader - INFO: Client 'KOERI' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,523] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Acquired 45 MiniSEED files [8.7 MB].
[2018-11-14 13:42:16,526] - obspy.clients.fdsn.mass_downloader - INFO: Client 'BGR' - Acquired 45 StationXML files [0.1 MB].
[2018-11-14 13:42:16,529] - obspy.clients.fdsn.mass_downloader - INFO: Client 'USP' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,532] - obspy.clients.fdsn.mass_downloader - INFO: Client 'USP' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,542] - obspy.clients.fdsn.mass_downloader - INFO: Client 'ETH' - Acquired 23 MiniSEED files [7.0 MB].
[2018-11-14 13:42:16,545] - obspy.clients.fdsn.mass_downloader - INFO: Client 'ETH' - Acquired 23 StationXML files [0.3 MB].
[2018-11-14 13:42:16,546] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NCEDC' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,551] - obspy.clients.fdsn.mass_downloader - INFO: Client 'NCEDC' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,553] - obspy.clients.fdsn.mass_downloader - INFO: Client 'INGV' - Acquired 0 MiniSEED files [0.0 MB].
[2018-11-14 13:42:16,556] - obspy.clients.fdsn.mass_downloader - INFO: Client 'INGV' - Acquired 0 StationXML files [0.0 MB].
[2018-11-14 13:42:16,559] - obspy.clients.fdsn.mass_downloader - INFO: Downloaded 20.4 MB in total.
Out[7]:
({u'BGR': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x7d04048>,
  u'ETH': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x126d0470>,
  u'GEONET': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0xc0c3358>,
  u'GFZ': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x126f1278>,
  u'ICGC': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0xe37ac50>,
  u'INGV': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124bd080>,
  u'IPGP': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124bdfd0>,
  u'IRIS': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x12496ef0>,
  u'KOERI': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124aecf8>,
  u'LMU': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124ae828>,
  u'NCEDC': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0xe37ad30>,
  u'NIEP': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124bd048>,
  u'NOA': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0xe3132b0>,
  u'RESIF': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x12496e80>,
  u'SCEDC': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x12496ac8>,
  u'TEXNET': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x124966d8>,
  u'USP': <obspy.clients.fdsn.mass_downloader.download_helpers.ClientDownloadHelper at 0x12496b38>},)

Protože nám v EIDĚ zmršili metadata, zkopírujeme si naši verzi:

In [8]:
for f in glob.glob(os.path.join('DLESS_XT_CZ', '*.xml')):
    shutil.copy(f, stationxml_storage)

Načtení signálů a metadat, připnutí přístrojových odezev

In [9]:
# staniční metadata
files = sorted(glob.glob(os.path.join(stationxml_storage, "*.xml")))
inv = read_inventory(files[0])
for f in files[1:]:
    inv += read_inventory(f)
inv.plot(projection='local', color_per_network=True),

# signály
st = read(os.path.join(mseed_storage, "*.mseed"))
print(len(st))

# přiřaď odezvu a lokaci
st.attach_response(inv)
for tr in st:
    coor = inv.get_coordinates(tr.id, datetime=tr.stats.starttime)
    tr.stats.latitude = coor['latitude']
    tr.stats.longitude = coor['longitude']
    tr.stats.elevation = coor['elevation']
80

Předpříprava signálů

Výřez signálů kolem začátku teoretické P vlny

In [10]:
for tr in st:
    # teoretická P vlna
    [dist_m, az, baz] = calc_vincenty_inverse(origin.latitude, origin.longitude, 
                                              tr.stats.latitude, tr.stats.longitude)
    dist = kilometer2degrees(dist_m/1000.)
    P_arrival = model.get_travel_times(source_depth_in_km=origin.depth/1000., 
                                       distance_in_degree=dist, phase_list=['ttp+'])[0]
    tr.stats.t_teor = origin.time + P_arrival.time
    tr.trim(tr.stats.t_teor-300, tr.stats.t_teor+300)
# průměrný backazimuth
[dist_m, az, baz0] = calc_vincenty_inverse(origin.latitude, origin.longitude, lat0, lon0)
dist0 = kilometer2degrees(dist_m/1000.)

Odstranění přístrojové odezvy a simulace WWSSN-SP

In [11]:
st.detrend('linear')
st.remove_response(pre_filt=[0.1, 0.5, 2, 4], water_level=1e6, output="DISP")
st.simulate(paz_remove=None, paz_simulate=paz_wwssn_sp)
for tr in st:
    tr.trim(tr.stats.t_teor-60, tr.stats.t_teor+60)
st.detrend('linear')
st.filter('bandpass', freqmin=0.2, freqmax=5., corners=2, zerophase=True)
Out[11]:
80 Trace(s) in Stream:

BW.MANZ..EHZ | 2015-08-06T09:33:45.755000Z - 2015-08-06T09:35:45.755000Z | 200.0 Hz, 24001 samples
...
(78 other traces)
...
XT.AAE24..HHZ | 2015-08-06T09:33:49.020000Z - 2015-08-06T09:35:49.020000Z | 100.0 Hz, 12001 samples

[Use "print(Stream.__str__(extended=True))" to print all Traces]

Přeškálování na 100 Hz

In [12]:
for tr in st:
    if tr.stats.sampling_rate != sample_rate:
        if tr.stats.sampling_rate % sample_rate == 0.:
            factor = int(round(tr.stats.sampling_rate / sample_rate))
            tr.decimate(factor)
        else:
            tr.interpolate(sample_rate)

1. Sesazení signálů podle teoretického picku

Průměr přes všechny stopy sesazené podle teoretického picku:

In [13]:
tr_mean = median_picked(st, 't_teor', (-10,10))
plot_all_picked(st, 't_teor', (-10,10))

Trigger na průměrnou stopu, odhalí případný větší offset všech signálů od teoretického picku:

In [14]:
# rekursivní sta-lta trigger
df = tr_mean.stats.sampling_rate
cft = recursive_sta_lta(tr_mean.data, int(sta * df), int(lta * df))
t_teor_offs = trigger_onset(cft, trig1, trig2)[0][0] / df - 10
print(t_teor_offs)
plot_trigger(tr_mean, cft, trig1, trig2)

for tr in st:
    tr.stats.t_teor += t_teor_offs
tr_mean.stats.t_teor = tr_mean.stats.starttime + 10 + t_teor_offs
0.0

2. Sesazení signálů podle korelace s průměrným signálem

In [15]:
for tr in st:
    dt, coeff = xcorr_pick_correction(tr_mean.stats.t_teor, tr_mean, tr.stats.t_teor, tr, 0.5, 2., 1., plot=False)
    tr.stats.t_correl = tr.stats.t_teor + dt
    
# nové sesazení
tr_mean = median_picked(st, 't_correl', (-10,10))
plot_all_picked(st, 't_correl', (-10,10))

3. Poslední sesazení signálů podle korelace s průměrným signálem

tentokrát hledáme vlnu až 5 sec daleko od teoretického picku

In [16]:
for tr in st:
    dt, coeff = xcorr_pick_correction(tr_mean.stats.t_correl, tr_mean, tr.stats.t_correl, tr, 0.5, 2., 5., plot=False)
    tr.stats.t_correl += dt
    tr.stats.correl = coeff
    
# nové sesazení
tr_mean = median_picked(st, 't_correl', (-10,10))
plot_all_picked(st, 't_correl', (-10,10))

VÝPIS: stanice ...... korelace ................ P_theo ................... P_correl-P_theo

In [17]:
for tr in st:
    print("{:<15s} {:3.0f}%   {} {:6.2f}".format(tr.id, 100.*tr.stats.correl, 
                                tr.stats.t_teor, tr.stats.t_correl - tr.stats.t_teor))
BW.MANZ..EHZ     90%   2015-08-06T09:34:45.756974Z  -0.01
BW.MGBB..EHZ     90%   2015-08-06T09:34:45.587237Z   0.20
BW.MKON..EHZ     90%   2015-08-06T09:34:45.359719Z   0.13
BW.MROB..EHZ     91%   2015-08-06T09:34:45.218126Z  -0.00
BW.MSBB..EHZ     84%   2015-08-06T09:34:45.862709Z  -0.12
BW.MZEK..EHZ     89%   2015-08-06T09:34:46.193005Z   0.04
BW.ROTZ..EHZ     87%   2015-08-06T09:34:46.426408Z   0.37
BW.VIEL..EHZ     93%   2015-08-06T09:34:44.966860Z   0.03
CZ.KHC..HHZ      96%   2015-08-06T09:34:45.985835Z   0.15
CZ.NKC..HHZ      92%   2015-08-06T09:34:44.041529Z   0.10
CZ.PRU..HHZ      93%   2015-08-06T09:34:40.447164Z   0.17
CZ.PVCC..HHZ     82%   2015-08-06T09:34:38.234067Z   0.34
GR.BRG..HHZ      84%   2015-08-06T09:34:38.218304Z  -0.13
GR.GEC2..HHZ     96%   2015-08-06T09:34:46.847763Z  -0.25
GR.GEC5..SHZ     95%   2015-08-06T09:34:46.921960Z  -0.28
GR.GEC6..SHZ     95%   2015-08-06T09:34:46.903861Z  -0.31
GR.GED1..SHZ     96%   2015-08-06T09:34:46.789819Z  -0.25
GR.GED2..SHZ     95%   2015-08-06T09:34:46.827093Z  -0.29
GR.GED4..SHZ     94%   2015-08-06T09:34:46.922038Z  -0.30
GR.GED5..SHZ     92%   2015-08-06T09:34:46.975004Z  -0.25
GR.GED6..SHZ     93%   2015-08-06T09:34:46.959541Z  -0.29
GR.GED8..SHZ     96%   2015-08-06T09:34:46.840864Z  -0.30
GR.GED9..SHZ     97%   2015-08-06T09:34:46.806532Z  -0.27
GR.GRA1..HHZ     90%   2015-08-06T09:34:48.806978Z   0.37
GR.GRA2..HHZ     94%   2015-08-06T09:34:48.666035Z   0.34
GR.GRA3..HHZ     86%   2015-08-06T09:34:48.321725Z   0.35
GR.GRA4..HHZ     89%   2015-08-06T09:34:48.865814Z   0.17
GR.GRB1..HHZ     88%   2015-08-06T09:34:49.107245Z   0.12
GR.GRB2..HHZ     91%   2015-08-06T09:34:49.550190Z   0.00
GR.GRB3..HHZ     96%   2015-08-06T09:34:48.972166Z   0.22
GR.GRB4..HHZ     94%   2015-08-06T09:34:48.989170Z   0.14
GR.GRB5..HHZ     80%   2015-08-06T09:34:50.169163Z  -0.02
GR.GRC1..HHZ     88%   2015-08-06T09:34:50.959645Z  -0.13
GR.GRC2..HHZ     90%   2015-08-06T09:34:51.779111Z  -0.29
GR.GRC3..HHZ     93%   2015-08-06T09:34:51.245030Z  -0.16
GR.GRC4..HHZ     89%   2015-08-06T09:34:50.588516Z  -0.09
GR.MOX..HHZ      94%   2015-08-06T09:34:44.132868Z  -0.12
GR.WET..HHZ      93%   2015-08-06T09:34:47.457548Z   0.22
SX.GUNZ..HHZ     93%   2015-08-06T09:34:43.764713Z   0.06
SX.MULD..HHZ     84%   2015-08-06T09:34:43.416238Z  -0.02
SX.ROHR..HHZ     93%   2015-08-06T09:34:44.317064Z   0.09
SX.SCHF..HHZ     92%   2015-08-06T09:34:42.347289Z   0.06
SX.TRIB..HHZ     94%   2015-08-06T09:34:44.224373Z  -0.06
SX.WERD..HHZ     89%   2015-08-06T09:34:43.476565Z  -0.01
SX.WERN..HHZ     92%   2015-08-06T09:34:43.976304Z   0.16
TH.ABG1..HHZ     92%   2015-08-06T09:34:40.804685Z  -0.21
TH.ANNA..HHZ     95%   2015-08-06T09:34:40.999266Z  -0.17
TH.GRZ1..HHZ     94%   2015-08-06T09:34:42.681625Z   0.02
TH.HKWD..HHZ     92%   2015-08-06T09:34:42.016992Z   1.02
TH.HWTS..HHZ     92%   2015-08-06T09:34:44.651536Z  -0.13
TH.LEIB1..HHZ    94%   2015-08-06T09:34:45.290117Z  -0.21
TH.MLFH..HHZ     96%   2015-08-06T09:34:42.574219Z  -0.05
TH.MODW..HHZ     86%   2015-08-06T09:34:41.134709Z  -0.20
TH.PLN..HHZ      86%   2015-08-06T09:34:43.644043Z  -0.01
TH.TAUT..HHZ     88%   2015-08-06T09:34:42.573628Z  -0.05
TH.WESF..HHZ     95%   2015-08-06T09:34:45.414581Z  -0.14
TH.ZEU..HHZ      95%   2015-08-06T09:34:43.275503Z  -0.03
XT.AAE01..HHZ    94%   2015-08-06T09:34:40.416796Z   0.18
XT.AAE02..HHZ    97%   2015-08-06T09:34:41.194967Z   0.13
XT.AAE03..HHZ    65%   2015-08-06T09:34:41.131135Z   0.17
XT.AAE04..HHZ    92%   2015-08-06T09:34:41.808585Z   0.09
XT.AAE05..HHZ    95%   2015-08-06T09:34:41.977756Z   0.27
XT.AAE07..HHZ    87%   2015-08-06T09:34:42.579871Z   0.05
XT.AAE08..HHZ    92%   2015-08-06T09:34:43.322219Z   0.00
XT.AAE09..HHZ    93%   2015-08-06T09:34:43.334481Z   0.04
XT.AAE10..HHZ    95%   2015-08-06T09:34:44.044880Z  -0.07
XT.AAE11..HHZ    88%   2015-08-06T09:34:43.954142Z   0.11
XT.AAE12..HHZ    74%   2015-08-06T09:34:44.797277Z   0.19
XT.AAE13..HHZ    88%   2015-08-06T09:34:44.678686Z  -0.03
XT.AAE14..HHZ    88%   2015-08-06T09:34:45.470134Z   0.17
XT.AAE15..HHZ    94%   2015-08-06T09:34:45.419368Z   0.20
XT.AAE16..HHZ    95%   2015-08-06T09:34:46.245034Z   0.26
XT.AAE17..HHZ    97%   2015-08-06T09:34:46.197641Z   0.18
XT.AAE18..HHZ    91%   2015-08-06T09:34:46.909540Z   0.22
XT.AAE19..HHZ    88%   2015-08-06T09:34:46.828284Z   0.05
XT.AAE20..HHZ    94%   2015-08-06T09:34:47.556199Z  -0.14
XT.AAE21..HHZ    73%   2015-08-06T09:34:47.629122Z   1.07
XT.AAE22..HHZ    96%   2015-08-06T09:34:48.309788Z  -0.14
XT.AAE23..HHZ    88%   2015-08-06T09:34:48.248686Z  -0.26
XT.AAE24..HHZ    90%   2015-08-06T09:34:49.023342Z  -0.17

Vykreslíme jen signály s horší korelací:

In [18]:
fig = plt.figure(figsize=(16,5))
ax = fig.add_subplot(111)
for tr in st:
    if tr.stats.correl < 0.8:
        tr1 = tr.copy().trim(tr.stats.t_correl-10, tr.stats.t_correl+10)
        tm1 = tr1.times()
        tr1_data = tr1.data / np.linalg.norm(tr1.data)
        ax.plot(tm1, tr1_data, label="{}   {:4.2f}".format(tr1.id, tr1.stats.correl))
tm1 = tr_mean.times()
ax.plot(tm1, tr_mean.data, 'k-', label='MEAN')
ax.set_xlim((0, max(tm1)))
ax.legend(loc='upper left')
ax.set_title("Signals with worse correlations")
Out[18]:
Text(0.5,1,u'Signals with worse correlations')

Jednoduché vykreslení odchylek od teoretických časů příchodů P vln:

In [19]:
kresli_residua(st, baz0)

Syntetické seismogramy - budoucnost pikování?

Idea: místo korelací se signálem zprůmětovaným přes všechny stanice zkusit korelace se syntetickými signály napočtenými pro každou stanici zvlášť

In [20]:
client = Client_Syngine()

Syntetický signál pro KHC a dané zemětřesení:

In [21]:
st_synt = client.get_waveforms(model="ak135f_1s", network="CZ", station="KHC", units="displacement",
                          eventid="GCMT:C201508060922A", starttime="P-60", endtime="P+60")
print(st_synt)
st_synt.plot()
1 Trace(s) in Stream:
CZ.KHC.SE.BXZ | 2015-08-06T09:33:49.500000Z - 2015-08-06T09:35:49.450000Z | 20.0 Hz, 2400 samples

Použijeme stejné filtrování jako u reálných signálů:

In [22]:
st_synt.simulate(paz_remove=None, paz_simulate=paz_wwssn_sp)
st_synt.filter('bandpass', freqmin=0.2, freqmax=5., corners=2, zerophase=True)
st_synt.plot()

Porovnáme reálnou a syntetickou P vlnu:

In [23]:
st_KHC = st.select(station="KHC")
st_KHC += st_synt

t1 = UTCDateTime('2015-08-06T09:34:20')
t2 = t1 + 70

print('RELATIVNI NORMOVANI')
st_KHC.plot(equal_scale=False, starttime=t1, endtime=t2)
RELATIVNI NORMOVANI
In [24]:
print('ABSOLUTNI NORMOVANI')
st_KHC.plot(equal_scale=True, starttime=t1, endtime=t2)
ABSOLUTNI NORMOVANI