Commit 3a3cf435 authored by Mijian Xu's avatar Mijian Xu 😷
Browse files

ver 1.1.15

parent 15707865
import math import math
import numpy as np import numpy as np
def sind(deg): def sind(deg):
rad = math.radians(deg) rad = math.radians(deg)
return math.sin(rad) return math.sin(rad)
......
...@@ -92,18 +92,19 @@ class eq(object): ...@@ -92,18 +92,19 @@ class eq(object):
this_st = self.st.copy() this_st = self.st.copy()
this_st.filter('bandpass', freqmin=0.03, freqmax=0.5) this_st.filter('bandpass', freqmin=0.03, freqmax=0.5)
this_st.trim(this_st[0].stats.starttime+p_arr-time_b, this_st[0].stats.starttime+p_arr+time_e) this_st.trim(this_st[0].stats.starttime+p_arr-time_b, this_st[0].stats.starttime+p_arr+time_e)
bazs = np.arange(bazi-offset, bazi+offset) bazs = np.mod(np.arange(bazi-offset, bazi+offset), 360)
ampt = np.zeros_like(bazs) ampt = np.zeros_like(bazs)
for i, b in enumerate(bazs): for i, b in enumerate(bazs):
t, _ = seispy.geo.rotateSeisENtoTR(this_st[0].data, this_st[1].data, b) t, _ = seispy.geo.rotateSeisENtoTR(this_st[0].data, this_st[1].data, b)
ampt[i] = seispy.geo.rssq(t) ampt[i] = seispy.geo.rssq(t)
idx = seispy.geo.extrema(ampt, opt='min') idx = seispy.geo.extrema(ampt, opt='min')
if len(idx) == 0: if len(idx) == 0:
return np.nan corr_baz = np.nan
elif len(idx) > 1: elif len(idx) > 1:
return None corr_baz = None
else: else:
return bazs[seispy.geo.extrema(ampt, opt='min')[0]] - bazi corr_baz = bazs[idx[0]] - bazi
return corr_baz, ampt
def fix_channel_name(self): def fix_channel_name(self):
if self.st.select(channel='??1') and self.st.select(channel='??Z') and hasattr(self.st.select(channel='*1')[0].stats.sac, 'cmpaz'): if self.st.select(channel='??1') and self.st.select(channel='??Z') and hasattr(self.st.select(channel='*1')[0].stats.sac, 'cmpaz'):
...@@ -154,10 +155,18 @@ class eq(object): ...@@ -154,10 +155,18 @@ class eq(object):
st_noise = self.trim(length, 0, phase=phase, isreturn=True) st_noise = self.trim(length, 0, phase=phase, isreturn=True)
st_signal = self.trim(0, length, phase=phase, isreturn=True) st_signal = self.trim(0, length, phase=phase, isreturn=True)
try: try:
snr_R = seispy.geo.snr(st_signal[1].data, st_noise[1].data) snr_E = seispy.geo.snr(st_signal[0].data, st_noise[0].data)
except IndexError: except IndexError:
snr_R = 0 snr_E = 0
return snr_R try:
snr_N = seispy.geo.snr(st_signal[1].data, st_noise[1].data)
except IndexError:
snr_N = 0
try:
snr_Z = seispy.geo.snr(st_signal[2].data, st_noise[2].data)
except IndexError:
snr_Z = 0
return snr_E, snr_N, snr_Z
def get_time_offset(self, event_time): def get_time_offset(self, event_time):
if not isinstance(event_time, obspy.core.utcdatetime.UTCDateTime): if not isinstance(event_time, obspy.core.utcdatetime.UTCDateTime):
......
...@@ -2,36 +2,43 @@ import numpy as np ...@@ -2,36 +2,43 @@ import numpy as np
from numpy import pi, mod from numpy import pi, mod
from seispy import distaz from seispy import distaz
from scipy import interpolate from scipy import interpolate
import math
def sind(deg): def sind(deg):
rad = np.radians(deg) rad = np.radians(deg)
return np.sin(rad) return np.sin(rad)
def cosd(deg): def cosd(deg):
rad = np.radians(deg) rad = np.radians(deg)
return np.cos(rad) return np.cos(rad)
def tand(deg): def tand(deg):
rad = np.radians(deg) rad = np.radians(deg)
return np.tan(rad) return np.tan(rad)
def cotd(deg): def cotd(deg):
rad = np.radians(deg) rad = np.radians(deg)
return np.cos(rad) / np.sin(rad) return np.cos(rad) / np.sin(rad)
def asind(x): def asind(x):
rad = np.arcsin(x) rad = np.arcsin(x)
return np.degrees(rad) return np.degrees(rad)
def acosd(x): def acosd(x):
rad = np.arccos(x) rad = np.arccos(x)
return np.degrees(rad) return np.degrees(rad)
def atand(x): def atand(x):
rad = np.arctan(x) rad = np.arctan(x)
return np.degrees(rad) return np.degrees(rad)
def km2deg(km): def km2deg(km):
radius = 6371 radius = 6371
circum = 2*pi*radius circum = 2*pi*radius
...@@ -39,6 +46,7 @@ def km2deg(km): ...@@ -39,6 +46,7 @@ def km2deg(km):
deg = km / conv deg = km / conv
return deg return deg
def deg2km(deg): def deg2km(deg):
radius = 6371 radius = 6371
circum = 2*pi*radius circum = 2*pi*radius
...@@ -46,22 +54,27 @@ def deg2km(deg): ...@@ -46,22 +54,27 @@ def deg2km(deg):
km = deg * conv km = deg * conv
return km return km
def rad2deg(rad): def rad2deg(rad):
deg = rad*(360/(2*pi)) deg = rad*(360/(2*pi))
return deg return deg
def skm2sdeg(skm): def skm2sdeg(skm):
sdeg = skm * deg2km(1) sdeg = skm * deg2km(1)
return sdeg return sdeg
def sdeg2skm(sdeg): def sdeg2skm(sdeg):
skm = sdeg / deg2km(1) skm = sdeg / deg2km(1)
return skm return skm
def srad2skm(srad): def srad2skm(srad):
sdeg = srad * ((2*pi)/360) sdeg = srad * ((2*pi)/360)
return sdeg / deg2km(1) return sdeg / deg2km(1)
def skm2srad(skm): def skm2srad(skm):
sdeg = skm * deg2km(1) sdeg = skm * deg2km(1)
return rad2deg(sdeg) return rad2deg(sdeg)
...@@ -115,35 +128,41 @@ def rotateSeisENtoTR(E, N, BAZ): ...@@ -115,35 +128,41 @@ def rotateSeisENtoTR(E, N, BAZ):
T = E*cosd(angle) - N*sind(angle) T = E*cosd(angle) - N*sind(angle)
return T, R return T, R
def rssq(x): def rssq(x):
return np.sqrt(np.sum(x**2)/len(x)) return np.sqrt(np.sum(x**2)/len(x))
def snr(x, y): def snr(x, y):
spow = rssq(x)**2 spow = rssq(x)**2
npow = rssq(y)**2 npow = rssq(y)**2
return 10 * np.log10(spow / npow) if npow == 0:
return np.nan
else:
return 10 * np.log10(spow / npow)
def latlon_from(lat1, lon1, azimuth, gcarc_dist): def latlon_from(lat1, lon1, azimuth, gcarc_dist):
lat2 = asind ((sind (lat1) * cosd (gcarc_dist)) + (cosd (lat1) * sind (gcarc_dist) * cosd (azimuth))) lat2 = asind((sind(lat1) * cosd(gcarc_dist)) + (cosd(lat1) * sind(gcarc_dist) * cosd(azimuth)))
if isinstance(gcarc_dist, np.ndarray): if isinstance(gcarc_dist, np.ndarray):
lon2 = np.zeros_like(lat2) lon2 = np.zeros_like(lat2)
for n in range(len(gcarc_dist)): for n in range(len(gcarc_dist)):
if cosd (gcarc_dist[n]) >= (cosd (90 - lat1) * cosd (90 - lat2[n])): if cosd(gcarc_dist[n]) >= (cosd(90 - lat1) * cosd(90 - lat2[n])):
lon2[n] = lon1 + asind (sind (gcarc_dist[n]) * sind (azimuth) / cosd (lat2[n])) lon2[n] = lon1 + asind(sind(gcarc_dist[n]) * sind(azimuth) / cosd(lat2[n]))
else: else:
lon2[n] = lon1 + asind (sind (gcarc_dist[n]) * sind (azimuth) / cosd (lat2[n])) + 180 lon2[n] = lon1 + asind(sind(gcarc_dist[n]) * sind(azimuth) / cosd(lat2[n])) + 180
elif isinstance(azimuth, np.ndarray): elif isinstance(azimuth, np.ndarray):
lon2 = np.zeros_like(lat2) lon2 = np.zeros_like(lat2)
for n in range(len(azimuth)): for n in range(len(azimuth)):
if cosd (gcarc_dist) >= (cosd (90 - lat1) * cosd (90 - lat2[n])): if cosd(gcarc_dist) >= (cosd(90 - lat1) * cosd(90 - lat2[n])):
lon2[n] = lon1 + asind (sind (gcarc_dist) * sind (azimuth[n]) / cosd (lat2[n])) lon2[n] = lon1 + asind(sind(gcarc_dist) * sind(azimuth[n]) / cosd(lat2[n]))
else: else:
lon2[n] = lon1 + asind (sind (gcarc_dist) * sind (azimuth[n]) / cosd (lat2[n])) + 180 lon2[n] = lon1 + asind(sind(gcarc_dist) * sind(azimuth[n]) / cosd(lat2[n])) + 180
else: else:
if ( cosd (gcarc_dist) >= (cosd (90 - lat1) * cosd (90 - lat2))): if (cosd(gcarc_dist) >= (cosd(90 - lat1) * cosd(90 - lat2))):
lon2 = lon1 + asind (sind (gcarc_dist) * sind (azimuth) / cosd (lat2)) lon2 = lon1 + asind(sind(gcarc_dist) * sind(azimuth) / cosd(lat2))
else: else:
lon2 = lon1 + asind (sind (gcarc_dist) * sind (azimuth) / cosd (lat2)) + 180 lon2 = lon1 + asind(sind(gcarc_dist) * sind(azimuth) / cosd(lat2)) + 180
return lat2, lon2 return lat2, lon2
...@@ -165,6 +184,7 @@ def extrema(x, opt='max'): ...@@ -165,6 +184,7 @@ def extrema(x, opt='max'):
raise ImportError('Wrong Options!!!') raise ImportError('Wrong Options!!!')
return idx return idx
def slantstack(seis, timeaxis, rayp_range, tau_range, ref_dis, dis): def slantstack(seis, timeaxis, rayp_range, tau_range, ref_dis, dis):
EV_num = seis.shape[0] EV_num = seis.shape[0]
tmp = np.zeros([EV_num, tau_range.shape[0]]) tmp = np.zeros([EV_num, tau_range.shape[0]])
......
import numpy as np import numpy as np
def mccc(seis, dt, twin=0): def mccc(seis, dt, twin=0):
data = np.zeros([len(seis), seis[0].data.shape[0]]) data = np.zeros([len(seis), seis[0].data.shape[0]])
for i in range(len(seis)): for i in range(len(seis)):
......
import sys import sys
import os import os
import random
import matplotlib
import argparse import argparse
# matplotlib.use("Qt5Agg") # matplotlib.use("Qt5Agg")
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QKeySequence from PyQt5.QtGui import QIcon, QKeySequence
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QSizePolicy, QWidget, QDesktopWidget, \ from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, \
QPushButton, QHBoxLayout, QLineEdit, QFileDialog, QAction, QShortcut QSizePolicy, QWidget, QDesktopWidget, \
from numpy import arange, sin, pi QPushButton, QHBoxLayout, QFileDialog, \
QAction, QShortcut
from os.path import exists, dirname, join from os.path import exists, dirname, join
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from seispy.pickfigure import RFFigure from seispy.pickfigure import RFFigure
class MyMplCanvas(FigureCanvas): class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, rfpath='', width=21, height=11, dpi=100): def __init__(self, parent=None, rfpath='', width=21, height=11, dpi=100):
...@@ -63,7 +58,7 @@ class MatplotlibWidget(QMainWindow): ...@@ -63,7 +58,7 @@ class MatplotlibWidget(QMainWindow):
self._define_global_shortcuts() self._define_global_shortcuts()
self.setWindowTitle('PickRF') self.setWindowTitle('PickRF')
self.setWindowIcon(QIcon(join(dirname(__file__), 'data', 'seispy.png'))) self.setWindowIcon(QIcon(join(dirname(__file__), 'data', 'seispy.png')))
def on_click(self, event): def on_click(self, event):
self.mpl.rffig.onclick(event) self.mpl.rffig.onclick(event)
self.mpl.draw() self.mpl.draw()
...@@ -71,7 +66,7 @@ class MatplotlibWidget(QMainWindow): ...@@ -71,7 +66,7 @@ class MatplotlibWidget(QMainWindow):
def previous_connect(self): def previous_connect(self):
self.mpl.rffig.butprevious() self.mpl.rffig.butprevious()
self.mpl.draw() self.mpl.draw()
def next_connect(self): def next_connect(self):
self.mpl.rffig.butnext() self.mpl.rffig.butnext()
self.mpl.draw() self.mpl.draw()
...@@ -79,11 +74,11 @@ class MatplotlibWidget(QMainWindow): ...@@ -79,11 +74,11 @@ class MatplotlibWidget(QMainWindow):
def enlarge(self): def enlarge(self):
self.mpl.rffig.enlarge() self.mpl.rffig.enlarge()
self.mpl.draw() self.mpl.draw()
def reduce(self): def reduce(self):
self.mpl.rffig.reduce() self.mpl.rffig.reduce()
self.mpl.draw() self.mpl.draw()
def finish(self): def finish(self):
self.mpl.rffig.finish() self.mpl.rffig.finish()
QApplication.quit() QApplication.quit()
...@@ -92,8 +87,8 @@ class MatplotlibWidget(QMainWindow): ...@@ -92,8 +87,8 @@ class MatplotlibWidget(QMainWindow):
self.mpl.rffig.plot() self.mpl.rffig.plot()
def plot_save(self): def plot_save(self):
fileName_choose, filetype = QFileDialog.getSaveFileName(self, fileName_choose, filetype = QFileDialog.getSaveFileName(self,
"Save the figure", "Save the figure",
os.path.join(os.getcwd(), self.mpl.rffig.staname + 'RT_bazorder'), os.path.join(os.getcwd(), self.mpl.rffig.staname + 'RT_bazorder'),
"PDF Files (*.pdf);;Images (*.png);;All Files (*)") "PDF Files (*.pdf);;Images (*.png);;All Files (*)")
...@@ -116,8 +111,8 @@ class MatplotlibWidget(QMainWindow): ...@@ -116,8 +111,8 @@ class MatplotlibWidget(QMainWindow):
self.setGeometry(0, 0, frame_width, frame_height) self.setGeometry(0, 0, frame_width, frame_height)
self.move((screen_width / 2) - (self.frameSize().width() / 2), self.move((screen_width / 2) - (self.frameSize().width() / 2),
(screen_height / 2) - (self.frameSize().height() / 2)) (screen_height / 2) - (self.frameSize().height() / 2))
def _define_global_shortcuts(self): def _define_global_shortcuts(self):
self.key_c = QShortcut(QKeySequence('c'), self) self.key_c = QShortcut(QKeySequence('c'), self)
self.key_c.activated.connect(self.next_connect) self.key_c.activated.connect(self.next_connect)
...@@ -167,7 +162,8 @@ def main(): ...@@ -167,7 +162,8 @@ def main():
app = QApplication(sys.argv) app = QApplication(sys.argv)
ui = MatplotlibWidget(rfpath) ui = MatplotlibWidget(rfpath)
ui.show() ui.show()
sys.exit(app.exec_()) sys.exit(app.exec_())
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -26,8 +26,9 @@ def init_figure(): ...@@ -26,8 +26,9 @@ def init_figure():
return h, axr, axt, axb, axr_sum, axt_sum return h, axr, axt, axb, axr_sum, axt_sum
def read_process_data(lst): def read_process_data(lst, resamp_dt=0.1):
stadata = SACStation(lst) stadata = SACStation(lst)
stadata.resample(resamp_dt)
idx = np.argsort(stadata.bazi) idx = np.argsort(stadata.bazi)
stadata.event = stadata.event[idx] stadata.event = stadata.event[idx]
stadata.bazi = stadata.bazi[idx] stadata.bazi = stadata.bazi[idx]
......
...@@ -4,19 +4,21 @@ import obspy ...@@ -4,19 +4,21 @@ import obspy
from obspy.io.sac import SACTrace from obspy.io.sac import SACTrace
import re import re
from seispy.io import wsfetch from seispy.io import wsfetch
from os.path import dirname, join, expanduser, exists from os.path import join
from seispy.para import para from seispy.para import para
import seispy import seispy
from seispy.eq import eq from seispy.eq import eq
from seispy.setuplog import setuplog from seispy.setuplog import setuplog
import glob import glob
import numpy as np import numpy as np
from datetime import timedelta, datetime from datetime import timedelta
import pandas as pd import pandas as pd
from obspy.taup import TauPyModel from obspy.taup import TauPyModel
import configparser import configparser
import argparse import argparse
import sys import sys
from tkinter import messagebox
import matplotlib.pyplot as plt
def datestr2regex(datestr): def datestr2regex(datestr):
...@@ -164,6 +166,13 @@ def CfgModify(cfg_file, session, key, value): ...@@ -164,6 +166,13 @@ def CfgModify(cfg_file, session, key, value):
cf.write(open(cfg_file, 'w')) cf.write(open(cfg_file, 'w'))
def _plotampt(x, y, ampt):
xx, yy = np.meshgrid(x, y)
f = plt.figure(figsize=(8, 8))
plt.pcolor(xx, yy, ampt)
return f
class RF(object): class RF(object):
def __init__(self, cfg_file=None, log=None): def __init__(self, cfg_file=None, log=None):
if cfg_file is None: if cfg_file is None:
...@@ -299,15 +308,32 @@ class RF(object): ...@@ -299,15 +308,32 @@ class RF(object):
def baz_correct(self, time_b=10, time_e=20, offset=90): def baz_correct(self, time_b=10, time_e=20, offset=90):
self.logger.RFlog.info('correct back-azimuth') self.logger.RFlog.info('correct back-azimuth')
shift_all = [] shift_all = []
# ampt_all = []
for i, row in self.eqs.iterrows(): for i, row in self.eqs.iterrows():
shift_all.append(row['data'].search_baz(row['bazi'], time_b=time_b, time_e=time_e, offset=offset)) curr_baz, _ = row['data'].search_baz(row['bazi'], time_b=time_b, time_e=time_e, offset=offset)
shift_all.append(curr_baz)
# ampt_all.append(ampt)
if None in shift_all: if None in shift_all:
self.logger.RFlog.error('Range of searching bazi is too small.') self.logger.RFlog.error('Range of searching bazi is too small.')
sys.exit(1) sys.exit(1)
shift_all = np.array(shift_all) shift_all = np.array(shift_all)
# ampt_all = np.array(ampt_all)
baz_shift = np.mean(shift_all[np.where(np.logical_not(np.isnan(shift_all)))]) baz_shift = np.mean(shift_all[np.where(np.logical_not(np.isnan(shift_all)))])
self.logger.RFlog.info('Average {:.4f} deg offset in back-azimuth'.format(baz_shift)) # self._baz_confirm(offset, ampt_all)
self.eqs['bazi'] = self.eqs['bazi'] + baz_shift self.logger.RFlog.info('Average {:.1f} deg offset in back-azimuth'.format(baz_shift))
self.eqs['bazi'] = np.mod(self.eqs['bazi'] + baz_shift, 360)
# def _baz_confirm(self, offset, ampt_all):
# y = np.arange(self.eqs.shape[0])
# x = np.linspace(-offset, offset, ampt_all.shape[1])
# fig = _plotampt(x, y, ampt_all)
# if messagebox.askyesno('Back-azimuth correction',
# 'Would you like to keep this correction?'):
# fig.close()
# else:
# self.logger.RFlog.error('Manual interruption.')
# fig.close()
# sys.exit(1)
def rotate(self, method='NE->RT'): def rotate(self, method='NE->RT'):
self.logger.RFlog.info('Rotate {0} phase {1}'.format(self.para.phase, method)) self.logger.RFlog.info('Rotate {0} phase {1}'.format(self.para.phase, method))
...@@ -316,7 +342,7 @@ class RF(object): ...@@ -316,7 +342,7 @@ class RF(object):
try: try:
row['data'].rotate(row['bazi'], method=method, phase=self.para.phase) row['data'].rotate(row['bazi'], method=method, phase=self.para.phase)
except Exception as e: except Exception as e:
self.logger.RFlog.error('{}'.format(e)) self.logger.RFlog.error('{}: {}'.format(row['data'].datestr, e))
drop_idx.append(i) drop_idx.append(i)
self.eqs.drop(drop_idx, inplace=True) self.eqs.drop(drop_idx, inplace=True)
...@@ -326,8 +352,9 @@ class RF(object): ...@@ -326,8 +352,9 @@ class RF(object):
self.logger.RFlog.info('Reject data record with SNR less than {0}'.format(self.para.noisegate)) self.logger.RFlog.info('Reject data record with SNR less than {0}'.format(self.para.noisegate))
drop_lst = [] drop_lst = []
for i, row in self.eqs.iterrows(): for i, row in self.eqs.iterrows():
snr_R = row['data'].snr(length=length) snr_E, snr_N, snr_Z = row['data'].snr(length=length)
if snr_R < self.para.noisegate: if (np.nan in (snr_E, snr_N, snr_Z) or snr_E < self.para.noisegate
or snr_N < self.para.noisegate or snr_Z < self.para.noisegate):
drop_lst.append(i) drop_lst.append(i)
self.eqs.drop(drop_lst, inplace=True) self.eqs.drop(drop_lst, inplace=True)
self.logger.RFlog.info('{0} events left after SNR calculation'.format(self.eqs.shape[0])) self.logger.RFlog.info('{0} events left after SNR calculation'.format(self.eqs.shape[0]))
...@@ -381,6 +408,7 @@ class RF(object): ...@@ -381,6 +408,7 @@ class RF(object):
evla=row['evla'], evlo=row['evlo'], evdp=row['evdp'], baz=row['bazi'], evla=row['evla'], evlo=row['evlo'], evdp=row['evdp'], baz=row['bazi'],
mag=row['mag'], gcarc=row['dis'], gauss=self.para.gauss, only_r=self.para.only_r) mag=row['mag'], gcarc=row['dis'], gauss=self.para.gauss, only_r=self.para.only_r)
good_lst.append(i) good_lst.append(i)
self.logger.RFlog.info('{} PRFs are saved.'.format(len(good_lst)))
self.eqs = self.eqs.loc[good_lst] self.eqs = self.eqs.loc[good_lst]
...@@ -388,18 +416,22 @@ def prf(): ...@@ -388,18 +416,22 @@ def prf():
parser = argparse.ArgumentParser(description="Calculating RFs for single station") parser = argparse.ArgumentParser(description="Calculating RFs for single station")
parser.add_argument('cfg_file', type=str, help='Path to RF configure file') parser.add_argument('cfg_file', type=str, help='Path to RF configure file')
parser.add_argument('-l', help="use local catalog. Default is false", dest='islocal', action='store_true') parser.add_argument('-l', help="use local catalog. Default is false", dest='islocal', action='store_true')
parser.add_argument('-r', help='Reverse components: EN, E or N', default=None, type=str) parser.add_argument('-r', help='Reverse components: EN, E or N', dest='comp', default=None, type=str)
parser.add_argument('-b', help='Correct back-azimuth via minimal energy of T component', default=None, type=str)