Merge branch 'develop' of ariadne.geophysik.ruhr-uni-bochum.de:/data/git/pylot into develop

This commit is contained in:
marcel 2017-06-28 09:27:21 +02:00
commit b140dd4f53
15 changed files with 1324 additions and 488 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,9 +16,9 @@ import pylot.core.loc.focmec as focmec
import pylot.core.loc.hash as hash import pylot.core.loc.hash as hash
import pylot.core.loc.nll as nll import pylot.core.loc.nll as nll
#from PySide.QtGui import QWidget, QInputDialog #from PySide.QtGui import QWidget, QInputDialog
from pylot.core.analysis.magnitude import MomentMagnitude, RichterMagnitude from pylot.core.analysis.magnitude import MomentMagnitude, LocalMagnitude
from pylot.core.io.data import Data from pylot.core.io.data import Data
from pylot.core.io.inputs import AutoPickParameter from pylot.core.io.inputs import PylotParameter
from pylot.core.pick.autopick import autopickevent, iteratepicker from pylot.core.pick.autopick import autopickevent, iteratepicker
from pylot.core.util.dataprocessing import restitute_data, read_metadata, \ from pylot.core.util.dataprocessing import restitute_data, read_metadata, \
remove_underscores remove_underscores
@ -35,7 +35,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
:param inputfile: path to the input file containing all parameter :param inputfile: path to the input file containing all parameter
information for automatic picking (for formatting details, see. information for automatic picking (for formatting details, see.
`~pylot.core.io.inputs.AutoPickParameter` `~pylot.core.io.inputs.PylotParameter`
:type inputfile: str :type inputfile: str
:return: :return:
@ -71,13 +71,13 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
if not parameter: if not parameter:
if inputfile: if inputfile:
parameter = AutoPickParameter(inputfile) parameter = PylotParameter(inputfile)
iplot = parameter['iplot'] iplot = parameter['iplot']
else: else:
print('No parameters set and no input file given. Choose either of both.') print('No parameters set and no input file given. Choose either of both.')
return return
else: else:
if not type(parameter) == AutoPickParameter: if not type(parameter) == PylotParameter:
print('Wrong input type for parameter: {}'.format(type(parameter))) print('Wrong input type for parameter: {}'.format(type(parameter)))
return return
if inputfile: if inputfile:
@ -98,8 +98,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
exf = ['root', 'dpath', 'dbase'] exf = ['root', 'dpath', 'dbase']
if parameter.hasParam('eventID') and fnames == 'None': if parameter['eventID'] is not '*' and fnames == 'None':
dsfields['eventID'] = parameter.get('eventID') dsfields['eventID'] = parameter['eventID']
exf.append('eventID') exf.append('eventID')
datastructure.modifyFields(**dsfields) datastructure.modifyFields(**dsfields)
@ -130,20 +130,34 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
print("!!No source parameter estimation possible!!") print("!!No source parameter estimation possible!!")
print(" !!! ") print(" !!! ")
if not input_dict:
# started in production mode
datapath = datastructure.expandDataPath() datapath = datastructure.expandDataPath()
if fnames == 'None' and not parameter.hasParam('eventID'): if fnames == 'None' and parameter['eventID'] is '*':
# multiple event processing # multiple event processing
# read each event in database # read each event in database
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)] events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
elif fnames == 'None' and parameter.hasParam('eventID'): elif fnames == 'None' and parameter['eventID'] is not '*':
# single event processing # single event processing
events = glob.glob(os.path.join(datapath, parameter.get('eventID'))) events = glob.glob(os.path.join(datapath, parameter['eventID']))
else: else:
# autoPyLoT was initialized from GUI # autoPyLoT was initialized from GUI
events = [] events = []
events.append(eventid) events.append(eventid)
evID = os.path.split(eventid)[-1] evID = os.path.split(eventid)[-1]
locflag = 2 locflag = 2
else:
# started in tune mode
datapath = os.path.join(parameter['rootpath'],
parameter['datapath'])
events = []
events.append(os.path.join(datapath,
parameter['database'],
parameter['eventID']))
if not events:
print('autoPyLoT: No events given. Return!')
return
for event in events: for event in events:
if fnames == 'None': if fnames == 'None':
@ -229,7 +243,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# get latest NLLoc-location file if several are available # get latest NLLoc-location file if several are available
nllocfile = max(glob.glob(locsearch), key=os.path.getctime) nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
evt = read_events(nllocfile)[0] evt = read_events(nllocfile)[0]
# calculating seismic moment Mo and moment magnitude Mw # calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'), moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'), parameter.get('Qp'),
parameter.get('rho'), True, \ parameter.get('rho'), True, \
@ -238,15 +252,29 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items(): for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props) picks[station]['P'].update(props)
evt = moment_mag.updated_event() evt = moment_mag.updated_event()
local_mag = RichterMagnitude(corr_dat, evt, net_mw = moment_mag.net_magnitude()
parameter.get('sstop'), True,\ print("Network moment magnitude: %4.1f" % net_mw.mag)
iplot) # calculate local (Richter) magntiude
WAscaling = parameter.get('WAscaling')
magscaling = parameter.get('magscaling')
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'),
WAscaling, True, iplot)
for station, amplitude in local_mag.amplitudes.items(): for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude picks[station]['S']['Ao'] = amplitude.generic_amplitude
evt = local_mag.updated_event() print("Local station magnitudes scaled with:")
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
WAscaling[1],
WAscaling[2]))
evt = local_mag.updated_event(magscaling)
net_ml = local_mag.net_magnitude(magscaling)
print("Network local magnitude: %4.1f" % net_ml.mag)
print("Network local magnitude scaled with:")
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
else: else:
print("autoPyLoT: No NLLoc-location file available!") print("autoPyLoT: No NLLoc-location file available!")
print("No source parameter estimation possible!") print("No source parameter estimation possible!")
locflag = 9
else: else:
# get theoretical P-onset times from NLLoc-location file # get theoretical P-onset times from NLLoc-location file
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout) locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
@ -287,7 +315,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
nlloccounter = maxnumit nlloccounter = maxnumit
evt = read_events(nllocfile)[0] evt = read_events(nllocfile)[0]
if locflag < 2: if locflag < 2:
# calculating seismic moment Mo and moment magnitude Mw # calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'), moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'), parameter.get('Qp'),
parameter.get('rho'), True, \ parameter.get('rho'), True, \
@ -296,14 +324,25 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items(): for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props) picks[station]['P'].update(props)
evt = moment_mag.updated_event() evt = moment_mag.updated_event()
local_mag = RichterMagnitude(corr_dat, evt,
parameter.get('sstop'), True, \
iplot)
for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude
evt = local_mag.updated_event()
net_mw = moment_mag.net_magnitude() net_mw = moment_mag.net_magnitude()
print("Network moment magnitude: %4.1f" % net_mw.mag) print("Network moment magnitude: %4.1f" % net_mw.mag)
# calculate local (Richter) magntiude
WAscaling = parameter.get('WAscaling')
magscaling = parameter.get('magscaling')
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'),
WAscaling, True, iplot)
for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude
print("Local station magnitudes scaled with:")
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
WAscaling[1],
WAscaling[2]))
evt = local_mag.updated_event(magscaling)
net_ml = local_mag.net_magnitude(magscaling)
print("Network local magnitude: %4.1f" % net_ml.mag)
print("Network local magnitude scaled with:")
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
else: else:
print("autoPyLoT: No NLLoc-location file available! Stop iteration!") print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
locflag = 9 locflag = 9
@ -314,26 +353,26 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
data.applyEVTData(picks) data.applyEVTData(picks)
if evt is not None: if evt is not None:
data.applyEVTData(evt, 'event') data.applyEVTData(evt, 'event')
fnqml = '%s/autoPyLoT' % event fnqml = '%s/PyLoT_%s' % (event, evID)
data.exportEvent(fnqml) data.exportEvent(fnqml, fnext='.xml', fcheck='manual')
if locflag == 1:
# HYPO71 # HYPO71
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event hypo71file = '%s/PyLoT_%s_HYPO71_phases' % (event, evID)
hypo71.export(picks, hypo71file, parameter) hypo71.export(picks, hypo71file, parameter)
# HYPOSAT # HYPOSAT
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event hyposatfile = '%s/PyLoT_%s_HYPOSAT_phases' % (event, evID)
hyposat.export(picks, hyposatfile, parameter) hyposat.export(picks, hyposatfile, parameter)
if locflag == 1:
# VELEST # VELEST
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event velestfile = '%s/PyLoT_%s_VELEST_phases.cnv' % (event, evID)
velest.export(picks, velestfile, parameter, evt) velest.export(picks, velestfile, parameter, evt)
# hypoDD # hypoDD
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event hypoddfile = '%s/PyLoT_%s_hypoDD_phases.pha' % (event, evID)
hypodd.export(picks, hypoddfile, parameter, evt) hypodd.export(picks, hypoddfile, parameter, evt)
# FOCMEC # FOCMEC
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event focmecfile = '%s/PyLoT_%s_FOCMEC.in' % (event, evID)
focmec.export(picks, focmecfile, parameter, evt) focmec.export(picks, focmecfile, parameter, evt)
# HASH # HASH
hashfile = '%s/autoPyLoT_HASH' % event hashfile = '%s/PyLoT_%s_HASH' % (event, evID)
hash.export(picks, hashfile, parameter, evt) hash.export(picks, hashfile, parameter, evt)
endsplash = '''------------------------------------------\n' endsplash = '''------------------------------------------\n'
@ -385,9 +424,5 @@ if __name__ == "__main__":
cla = parser.parse_args() cla = parser.parse_args()
try: picks = autoPyLoT(inputfile=str(cla.inputfile), fnames=str(cla.fnames),
picks, mainFig = autoPyLoT(inputfile=str(cla.inputfile), fnames=str(cla.fnames),
eventid=str(cla.eventid), savepath=str(cla.spath)) eventid=str(cla.eventid), savepath=str(cla.spath))
except ValueError:
print("autoPyLoT was running in production mode.")

View File

@ -1 +0,0 @@
0af79-dirty

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Created autumn/winter 2015. Created autumn/winter 2015.
Revised/extended summer 2017.
:author: Ludger Küperkoch / MAGS2 EP3 working group :author: Ludger Küperkoch / MAGS2 EP3 working group
""" """
@ -17,10 +18,17 @@ from pylot.core.pick.utils import getsignalwin, crossings_nonzero_all, \
from pylot.core.util.utils import common_range, fit_curve from pylot.core.util.utils import common_range, fit_curve
def richter_magnitude_scaling(delta): def richter_magnitude_scaling(delta):
relation = np.loadtxt(os.path.join(os.path.expanduser('~'), distance = np.array([0, 10, 20, 25, 30, 35,40, 45, 50, 60, 70, 75, 85, 90, 100, 110,
'.pylot', 'richter_scaling.data')) 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 230, 240, 250,
260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380,
390, 400, 430, 470, 510, 560, 600, 700, 800, 900, 1000])
richter_scaling = np.array([1.4, 1.5, 1.7, 1.9, 2.1, 2.3, 2.4, 2.5, 2.6, 2.8, 2.8, 2.9,
2.9, 3.0, 3.1, 3.1, 3.2, 3.2, 3.3, 3.3, 3.4, 3.4, 3.5, 3.5,
3.6, 3.7, 3.7, 3.8, 3.8, 3.9, 3.9, 4.0, 4.0, 4.1, 4.2, 4.2,
4.2, 4.2, 4.3, 4.3, 4.3, 4.4, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9,
5.1, 5.2, 5.4, 5.5, 5.7])
# prepare spline interpolation to calculate return value # prepare spline interpolation to calculate return value
func, params = fit_curve(relation[:, 0], relation[:, 1]) func, params = fit_curve(distance, richter_scaling)
return func(delta, params) return func(delta, params)
@ -31,10 +39,10 @@ class Magnitude(object):
def __init__(self, stream, event, verbosity=False, iplot=0): def __init__(self, stream, event, verbosity=False, iplot=0):
self._type = "M" self._type = "M"
self._stream = stream
self._plot_flag = iplot self._plot_flag = iplot
self._verbosity = verbosity self._verbosity = verbosity
self._event = event self._event = event
self._stream = stream
self._magnitudes = dict() self._magnitudes = dict()
def __str__(self): def __str__(self):
@ -108,17 +116,24 @@ class Magnitude(object):
def calc(self): def calc(self):
pass pass
def updated_event(self): def updated_event(self, magscaling=None):
self.event.magnitudes.append(self.net_magnitude()) self.event.magnitudes.append(self.net_magnitude(magscaling))
return self.event return self.event
def net_magnitude(self): def net_magnitude(self, magscaling=None):
if self: if self:
# TODO if an average Magnitude instead of the median is calculated if magscaling is not None and str(magscaling) is not '[0.0, 0.0]':
# StationMagnitudeContributions should be added to the returned # scaling necessary
# Magnitude object print("Scaling network magnitude ...")
# mag_error => weights (magnitude error estimate from peak_to_peak, calcsourcespec?) mag = ope.Magnitude(
# weights => StationMagnitdeContribution mag=np.median([M.mag for M in self.magnitudes.values()]) *\
magscaling[0] + magscaling[1],
magnitude_type=self.type,
origin_id=self.origin_id,
station_count=len(self.magnitudes),
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
else:
# no saling necessary
mag = ope.Magnitude( mag = ope.Magnitude(
mag=np.median([M.mag for M in self.magnitudes.values()]), mag=np.median([M.mag for M in self.magnitudes.values()]),
magnitude_type=self.type, magnitude_type=self.type,
@ -129,7 +144,7 @@ class Magnitude(object):
return None return None
class RichterMagnitude(Magnitude): class LocalMagnitude(Magnitude):
""" """
Method to derive peak-to-peak amplitude as seen on a Wood-Anderson- Method to derive peak-to-peak amplitude as seen on a Wood-Anderson-
seismograph. Has to be derived from instrument corrected traces! seismograph. Has to be derived from instrument corrected traces!
@ -146,10 +161,11 @@ class RichterMagnitude(Magnitude):
_amplitudes = dict() _amplitudes = dict()
def __init__(self, stream, event, calc_win, verbosity=False, iplot=0): def __init__(self, stream, event, calc_win, wascaling, verbosity=False, iplot=0):
super(RichterMagnitude, self).__init__(stream, event, verbosity, iplot) super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
self._calc_win = calc_win self._calc_win = calc_win
self._wascaling = wascaling
self._type = 'ML' self._type = 'ML'
self.calc() self.calc()
@ -161,6 +177,10 @@ class RichterMagnitude(Magnitude):
def calc_win(self, value): def calc_win(self, value):
self._calc_win = value self._calc_win = value
@property
def wascaling(self):
return self._wascaling
@property @property
def amplitudes(self): def amplitudes(self):
return self._amplitudes return self._amplitudes
@ -195,6 +215,8 @@ class RichterMagnitude(Magnitude):
th = np.arange(0, len(sqH) * dt, dt) th = np.arange(0, len(sqH) * dt, dt)
# get maximum peak within pick window # get maximum peak within pick window
iwin = getsignalwin(th, t0 - stime, self.calc_win) iwin = getsignalwin(th, t0 - stime, self.calc_win)
ii = min([iwin[len(iwin)-1], len(th)])
iwin = iwin[0:ii]
wapp = np.max(sqH[iwin]) wapp = np.max(sqH[iwin])
if self.verbose: if self.verbose:
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} " print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
@ -244,10 +266,17 @@ class RichterMagnitude(Magnitude):
self.event.amplitudes.append(amplitude) self.event.amplitudes.append(amplitude)
self.amplitudes = (station, amplitude) self.amplitudes = (station, amplitude)
# using standard Gutenberg-Richter relation # using standard Gutenberg-Richter relation
# TODO make the ML calculation more flexible by allowing # or scale WA amplitude with given scaling relation
# use of custom relation functions if str(self.wascaling) == '[0.0, 0.0, 0.0]':
magnitude = ope.StationMagnitude( print("Calculating original Richter magnitude ...")
mag=np.log10(a0) + richter_magnitude_scaling(delta)) magnitude = ope.StationMagnitude(mag=np.log10(a0) \
+ richter_magnitude_scaling(delta))
else:
print("Calculating scaled local magnitude ...")
a0 = a0 * 1e03 # mm to nm (see Havskov & Ottemöller, 2010)
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
+ self.wascaling[0] * np.log10(delta) + self.wascaling[1]
* delta + self.wascaling[2])
magnitude.origin_id = self.origin_id magnitude.origin_id = self.origin_id
magnitude.waveform_id = pick.waveform_id magnitude.waveform_id = pick.waveform_id
magnitude.amplitude_id = amplitude.resource_id magnitude.amplitude_id = amplitude.resource_id

View File

@ -6,11 +6,12 @@ import os
from obspy import read_events from obspy import read_events
from obspy.core import read, Stream, UTCDateTime from obspy.core import read, Stream, UTCDateTime
from obspy.io.sac import SacIOError from obspy.io.sac import SacIOError
from obspy.core.event import Event from obspy.core.event import Event as ObsPyEvent
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \ from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
picksdict_from_pilot, merge_picks picksdict_from_pilot, merge_picks
from pylot.core.util.errors import FormatError, OverwriteError from pylot.core.util.errors import FormatError, OverwriteError
from pylot.core.util.utils import fnConstructor, full_range from pylot.core.util.utils import fnConstructor, full_range
from pylot.core.util.event import Event
class Data(object): class Data(object):
""" """
@ -33,7 +34,7 @@ class Data(object):
self.comp = 'Z' self.comp = 'Z'
self.wfdata = Stream() self.wfdata = Stream()
self._new = False self._new = False
if isinstance(evtdata, Event): if isinstance(evtdata, ObsPyEvent) or isinstance(evtdata, Event):
pass pass
elif isinstance(evtdata, dict): elif isinstance(evtdata, dict):
evt = readPILOTEvent(**evtdata) evt = readPILOTEvent(**evtdata)
@ -49,7 +50,7 @@ class Data(object):
if 'Unknown format for file' in e.message: if 'Unknown format for file' in e.message:
if 'PHASES' in evtdata: if 'PHASES' in evtdata:
picks = picksdict_from_pilot(evtdata) picks = picksdict_from_pilot(evtdata)
evtdata = Event() evtdata = ObsPyEvent()
evtdata.picks = picks_from_picksdict(picks) evtdata.picks = picks_from_picksdict(picks)
elif 'LOC' in evtdata: elif 'LOC' in evtdata:
raise NotImplementedError('PILOT location information ' raise NotImplementedError('PILOT location information '
@ -61,7 +62,7 @@ class Data(object):
raise e raise e
else: # create an empty Event object else: # create an empty Event object
self.setNew() self.setNew()
evtdata = Event() evtdata = ObsPyEvent()
evtdata.picks = [] evtdata.picks = []
self.evtdata = evtdata self.evtdata = evtdata
self.wforiginal = None self.wforiginal = None
@ -73,6 +74,8 @@ class Data(object):
def __add__(self, other): def __add__(self, other):
assert isinstance(other, Data), "operands must be of same type 'Data'" assert isinstance(other, Data), "operands must be of same type 'Data'"
rs_id = self.get_evt_data().get('resource_id')
rs_id_other = other.get_evt_data().get('resource_id')
if other.isNew() and not self.isNew(): if other.isNew() and not self.isNew():
picks_to_add = other.get_evt_data().picks picks_to_add = other.get_evt_data().picks
old_picks = self.get_evt_data().picks old_picks = self.get_evt_data().picks
@ -84,7 +87,7 @@ class Data(object):
self.evtdata = new.get_evt_data() self.evtdata = new.get_evt_data()
elif self.isNew() and other.isNew(): elif self.isNew() and other.isNew():
pass pass
elif self.get_evt_data().get('id') == other.get_evt_data().get('id'): elif rs_id == rs_id_other:
other.setNew() other.setNew()
return self + other return self + other
else: else:
@ -95,7 +98,7 @@ class Data(object):
def getPicksStr(self): def getPicksStr(self):
picks_str = '' picks_str = ''
for pick in self.get_evt_data().picks: for pick in self.get_evt_data().picks:
picks_str += str(pick) + '\n' picks_str += str(PyLoT) + '\n'
return picks_str return picks_str
def getParent(self): def getParent(self):
@ -144,12 +147,13 @@ class Data(object):
# handle forbidden filenames especially on windows systems # handle forbidden filenames especially on windows systems
return fnConstructor(str(ID)) return fnConstructor(str(ID))
def exportEvent(self, fnout, fnext='.xml'): def exportEvent(self, fnout, fnext='.xml', fcheck='auto'):
""" """
:param fnout: :param fnout:
:param fnext: :param fnext:
:param fcheck:
:raise KeyError: :raise KeyError:
""" """
from pylot.core.util.defaults import OUTPUTFORMATS from pylot.core.util.defaults import OUTPUTFORMATS
@ -161,7 +165,29 @@ class Data(object):
'supported'.format(e, fnext) 'supported'.format(e, fnext)
raise FormatError(errmsg) raise FormatError(errmsg)
# check for already existing xml-file
if fnext == '.xml':
if os.path.isfile(fnout + fnext):
print("xml-file already exists! Check content ...")
cat_old = read_events(fnout + fnext)
checkflag = 0
for j in range(len(cat_old.events[0].picks)):
if cat_old.events[0].picks[j].method_id.id.split('/')[1] == fcheck:
print("Found %s pick(s), append to new catalog." % fcheck)
checkflag = 1
break
if checkflag == 1:
self.get_evt_data().write(fnout + fnext, format=evtformat)
cat_new = read_events(fnout + fnext)
cat_new.append(cat_old.events[0])
cat_new.write(fnout + fnext, format=evtformat)
else:
self.get_evt_data().write(fnout + fnext, format=evtformat)
else:
self.get_evt_data().write(fnout + fnext, format=evtformat)
# try exporting event via ObsPy # try exporting event via ObsPy
else:
try: try:
self.get_evt_data().write(fnout + fnext, format=evtformat) self.get_evt_data().write(fnout + fnext, format=evtformat)
except KeyError as e: except KeyError as e:
@ -279,12 +305,12 @@ class Data(object):
def setEvtData(self, event): def setEvtData(self, event):
self.evtdata = event self.evtdata = event
def applyEVTData(self, data, type='pick', authority_id='rub'): def applyEVTData(self, data, typ='pick', authority_id='rub'):
""" """
:param data: :param data:
:param type: :param typ:
:param authority_id: :param authority_id:
:raise OverwriteError: :raise OverwriteError:
""" """
@ -326,19 +352,27 @@ class Data(object):
information on the event to the actual data information on the event to the actual data
:param event: :param event:
""" """
if not self.isNew(): if self.isNew():
self.setEvtData(event) self.setEvtData(event)
else: else:
# prevent overwriting original pick information # prevent overwriting original pick information
picks = copy.deepcopy(self.get_evt_data().picks) event_old = self.get_evt_data()
print(event_old.resource_id, event.resource_id)
if not event_old.resource_id == event.resource_id:
print("WARNING: Missmatch in event resource id's: {} and {}".format(
event_old.resource_id,
event.resource_id))
picks = copy.deepcopy(event_old.picks)
event = merge_picks(event, picks) event = merge_picks(event, picks)
# apply event information from location # apply event information from location
self.get_evt_data().update(event) event_old.update(event)
applydata = {'pick': applyPicks, applydata = {'pick': applyPicks,
'event': applyEvent} 'event': applyEvent}
applydata[type](data) applydata[typ](data)
self._new = False
class GenericDataStructure(object): class GenericDataStructure(object):

View File

@ -14,7 +14,7 @@ defaults = {'rootpath': {'type': str,
'value': ''}, 'value': ''},
'eventID': {'type': str, 'eventID': {'type': str,
'tooltip': 'event ID for single event processing', 'tooltip': 'event ID for single event processing (* for all events found in database)',
'value': ''}, 'value': ''},
'extent': {'type': str, 'extent': {'type': str,
@ -275,7 +275,17 @@ defaults = {'rootpath': {'type': str,
'wdttolerance': {'type': float, 'wdttolerance': {'type': float,
'tooltip': 'maximum allowed deviation from Wadati-diagram', 'tooltip': 'maximum allowed deviation from Wadati-diagram',
'value': 1.0} 'value': 1.0},
'WAscaling': {'type': (float, float, float),
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] \
If zeros are set, original Richter magnitude is calculated!',
'value': (0., 0., 0.)},
'magscaling': {'type': (float, float),
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \
If zeros are set, no scaling of network magnitude is applied!',
'value': (0., 0.)}
} }
settings_main={ settings_main={
@ -298,6 +308,9 @@ settings_main={
'vp', 'vp',
'rho', 'rho',
'Qp'], 'Qp'],
'localmag':[
'WAscaling',
'magscaling'],
'pick':[ 'pick':[
'extent', 'extent',
'pstart', 'pstart',

View File

@ -4,9 +4,9 @@
from pylot.core.util.errors import ParameterError from pylot.core.util.errors import ParameterError
import default_parameters import default_parameters
class AutoPickParameter(object): class PylotParameter(object):
''' '''
AutoPickParameters is a parameter type object capable to read and/or write PylotParameter is a parameter type object capable to read and/or write
parameter ASCII. parameter ASCII.
:param fn str: Filename of the input file :param fn str: Filename of the input file
@ -78,7 +78,7 @@ class AutoPickParameter(object):
# String representation of the object # String representation of the object
def __repr__(self): def __repr__(self):
return "AutoPickParameter('%s')" % self.__filename return "PylotParameter('%s')" % self.__filename
# Boolean test # Boolean test
def __nonzero__(self): def __nonzero__(self):
@ -140,6 +140,7 @@ class AutoPickParameter(object):
all_names += self.get_main_para_names()['dirs'] all_names += self.get_main_para_names()['dirs']
all_names += self.get_main_para_names()['nlloc'] all_names += self.get_main_para_names()['nlloc']
all_names += self.get_main_para_names()['smoment'] all_names += self.get_main_para_names()['smoment']
all_names += self.get_main_para_names()['localmag']
all_names += self.get_main_para_names()['pick'] all_names += self.get_main_para_names()['pick']
all_names += self.get_special_para_names()['z'] all_names += self.get_special_para_names()['z']
all_names += self.get_special_para_names()['h'] all_names += self.get_special_para_names()['h']
@ -220,22 +221,23 @@ class AutoPickParameter(object):
# for key, value in self.iteritems(): # for key, value in self.iteritems():
# lines.append('{key}\t{value}\n'.format(key=key, value=value)) # lines.append('{key}\t{value}\n'.format(key=key, value=value))
# fid_out.writelines(lines) # fid_out.writelines(lines)
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+ header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+
'%All main and special settings regarding data handling\n'+ '%All main and special settings regarding data handling\n'+
'%and picking are to be set here!\n'+ '%and picking are to be set here!\n'+
'%Parameters are optimized for local data sets!\n') '%Parameters are optimized for %{} data sets!\n'.format(self.get_main_para_names()['pick'][0]))
seperator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n' separator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
fid_out.write(header) fid_out.write(header)
self.write_section(fid_out, self.get_main_para_names()['dirs'], self.write_section(fid_out, self.get_main_para_names()['dirs'],
'main settings', seperator) 'main settings', separator)
self.write_section(fid_out, self.get_main_para_names()['nlloc'], self.write_section(fid_out, self.get_main_para_names()['nlloc'],
'NLLoc settings', seperator) 'NLLoc settings', separator)
self.write_section(fid_out, self.get_main_para_names()['smoment'], self.write_section(fid_out, self.get_main_para_names()['smoment'],
'parameters for seismic moment estimation', seperator) 'parameters for seismic moment estimation', separator)
self.write_section(fid_out, self.get_main_para_names()['localmag'],
'settings local magnitude', separator)
self.write_section(fid_out, self.get_main_para_names()['pick'], self.write_section(fid_out, self.get_main_para_names()['pick'],
'common settings picker', seperator) 'common settings picker', separator)
fid_out.write(('#special settings for calculating CF#\n'+ fid_out.write(('#special settings for calculating CF#\n'+
'%!!Edit the following only if you know what you are doing!!%\n')) '%!!Edit the following only if you know what you are doing!!%\n'))
self.write_section(fid_out, self.get_special_para_names()['z'], self.write_section(fid_out, self.get_special_para_names()['z'],
@ -247,9 +249,9 @@ class AutoPickParameter(object):
self.write_section(fid_out, self.get_special_para_names()['quality'], self.write_section(fid_out, self.get_special_para_names()['quality'],
'quality assessment', None) 'quality assessment', None)
def write_section(self, fid, names, title, seperator): def write_section(self, fid, names, title, separator):
if seperator: if separator:
fid.write(seperator) fid.write(separator)
fid.write('#{}#\n'.format(title)) fid.write('#{}#\n'.format(title))
l_val = 50 l_val = 50
l_name = 15 l_name = 15

View File

@ -7,8 +7,9 @@ import os
import scipy.io as sio import scipy.io as sio
import warnings import warnings
from obspy.core import UTCDateTime from obspy.core import UTCDateTime
from obspy.core.util import AttribDict
from pylot.core.io.inputs import AutoPickParameter from pylot.core.io.inputs import PylotParameter
from pylot.core.io.location import create_arrival, create_event, \ from pylot.core.io.location import create_arrival, create_event, \
create_magnitude, create_origin, create_pick create_magnitude, create_origin, create_pick
from pylot.core.pick.utils import select_for_phase from pylot.core.pick.utils import select_for_phase
@ -116,7 +117,7 @@ def picksdict_from_pilot(fn):
picks = dict() picks = dict()
phases_pilot = sio.loadmat(fn) phases_pilot = sio.loadmat(fn)
stations = stations_from_pilot(phases_pilot['stat']) stations = stations_from_pilot(phases_pilot['stat'])
params = AutoPickParameter(TIMEERROR_DEFAULTS) params = PylotParameter(TIMEERROR_DEFAULTS)
timeerrors = dict(P=params.get('timeerrorsP'), timeerrors = dict(P=params.get('timeerrorsP'),
S=params.get('timeerrorsS')) S=params.get('timeerrorsS'))
for n, station in enumerate(stations): for n, station in enumerate(stations):
@ -195,6 +196,7 @@ def picksdict_from_picks(evt):
phase = {} phase = {}
station = pick.waveform_id.station_code station = pick.waveform_id.station_code
channel = pick.waveform_id.channel_code channel = pick.waveform_id.channel_code
network = pick.waveform_id.network_code
try: try:
onsets = picks[station] onsets = picks[station]
except KeyError as e: except KeyError as e:
@ -215,6 +217,7 @@ def picksdict_from_picks(evt):
phase['lpp'] = lpp phase['lpp'] = lpp
phase['spe'] = spe phase['spe'] = spe
phase['channel'] = channel phase['channel'] = channel
phase['network'] = network
try: try:
picker = str(pick.method_id) picker = str(pick.method_id)
if picker.startswith('smi:local/'): if picker.startswith('smi:local/'):
@ -231,7 +234,7 @@ def picks_from_picksdict(picks, creation_info=None):
picks_list = list() picks_list = list()
for station, onsets in picks.items(): for station, onsets in picks.items():
for label, phase in onsets.items(): for label, phase in onsets.items():
if not isinstance(phase, dict): if not isinstance(phase, dict) and not isinstance(phase, AttribDict):
continue continue
onset = phase['mpp'] onset = phase['mpp']
try: try:
@ -295,14 +298,14 @@ def reassess_pilot_db(root_dir, db_dir, out_dir=None, fn_param=None, verbosity=0
def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None, verbosity=0): def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None, verbosity=0):
from obspy import read from obspy import read
from pylot.core.io.inputs import AutoPickParameter from pylot.core.io.inputs import PylotParameter
from pylot.core.pick.utils import earllatepicker from pylot.core.pick.utils import earllatepicker
if fn_param is None: if fn_param is None:
import pylot.core.util.defaults as defaults import pylot.core.util.defaults as defaults
fn_param = defaults.AUTOMATIC_DEFAULTS fn_param = defaults.AUTOMATIC_DEFAULTS
default = AutoPickParameter(fn_param, verbosity) default = PylotParameter(fn_param, verbosity)
search_base = os.path.join(root_dir, db_dir, event_id) search_base = os.path.join(root_dir, db_dir, event_id)
phases_file = glob.glob(os.path.join(search_base, 'PHASES.mat')) phases_file = glob.glob(os.path.join(search_base, 'PHASES.mat'))
@ -382,12 +385,12 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
evt.picks = picks_from_picksdict(picks_dict) evt.picks = picks_from_picksdict(picks_dict)
# write phase information to file # write phase information to file
if not out_dir: if not out_dir:
fnout_prefix = os.path.join(root_dir, db_dir, event_id, '{0}.'.format(event_id)) fnout_prefix = os.path.join(root_dir, db_dir, event_id, 'PyLoT_{0}.'.format(event_id))
else: else:
out_dir = os.path.join(out_dir, db_dir) out_dir = os.path.join(out_dir, db_dir)
if not os.path.isdir(out_dir): if not os.path.isdir(out_dir):
os.makedirs(out_dir) os.makedirs(out_dir)
fnout_prefix = os.path.join(out_dir, '{0}.'.format(event_id)) fnout_prefix = os.path.join(out_dir, 'PyLoT_{0}.'.format(event_id))
evt.write(fnout_prefix + 'xml', format='QUAKEML') evt.write(fnout_prefix + 'xml', format='QUAKEML')
#evt.write(fnout_prefix + 'cnv', format='VELEST') #evt.write(fnout_prefix + 'cnv', format='VELEST')
@ -835,9 +838,10 @@ def merge_picks(event, picks):
err = pick.time_errors err = pick.time_errors
phase = pick.phase_hint phase = pick.phase_hint
station = pick.waveform_id.station_code station = pick.waveform_id.station_code
network = pick.waveform_id.network_code
method = pick.method_id method = pick.method_id
for p in event.picks: for p in event.picks:
if p.waveform_id.station_code == station and p.phase_hint == phase: if p.waveform_id.station_code == station and p.phase_hint == phase:
p.time, p.time_errors, p.method_id = time, err, method p.time, p.time_errors, p.waveform_id.network_code, p.method_id = time, err, network, method
del time, err, phase, station, method del time, err, phase, station, network, method
return event return event

View File

@ -11,7 +11,7 @@ function conglomerate utils.
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from pylot.core.io.inputs import AutoPickParameter from pylot.core.io.inputs import PylotParameter
from pylot.core.pick.picker import AICPicker, PragPicker from pylot.core.pick.picker import AICPicker, PragPicker
from pylot.core.pick.charfuns import CharacteristicFunction from pylot.core.pick.charfuns import CharacteristicFunction
from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf from pylot.core.pick.charfuns import HOScf, AICcf, ARZcf, ARHcf, AR3Ccf
@ -81,7 +81,7 @@ def autopickstation(wfstream, pickparam, verbose=False, iplot=0, fig_dict=None):
:param pickparam: container of picking parameters from input file, :param pickparam: container of picking parameters from input file,
usually autoPyLoT.in usually autoPyLoT.in
:type pickparam: AutoPickParameter :type pickparam: PylotParameter
:param verbose: :param verbose:
:type verbose: bool :type verbose: bool

View File

@ -212,6 +212,14 @@ class AICPicker(AutoPicker):
self.Data[0].data = self.Data[0].data * 1000000 self.Data[0].data = self.Data[0].data * 1000000
# get signal window # get signal window
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2]) isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
ii = min([isignal[len(isignal)-1], len(self.Tcf)])
isignal = isignal[0:ii]
try:
aic[isignal]
except IndexError as e:
msg = "Time series out of bounds! {}".format(e)
print(msg)
return
# calculate SNR from CF # calculate SNR from CF
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \ self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
max(abs(aic[inoise] - np.mean(aic[inoise]))) max(abs(aic[inoise] - np.mean(aic[inoise])))
@ -223,9 +231,15 @@ class AICPicker(AutoPicker):
# find maximum within slope determination window # find maximum within slope determination window
# 'cause slope should be calculated up to first local minimum only! # 'cause slope should be calculated up to first local minimum only!
imax = np.argmax(self.Data[0].data[islope]) imax = np.argmax(self.Data[0].data[islope])
iislope = islope[0][0:imax]
if len(iislope) <= 2:
# calculate slope from initial onset to maximum of AIC function
print("AICPicker: Not enough data samples left for slope calculation!")
print("Calculating slope from initial onset to maximum of AIC function ...")
imax = np.argmax(aicsmooth[islope])
if imax == 0: if imax == 0:
print('AICPicker: Maximum for slope determination right at the beginning of the window!') print("AICPicker: Maximum for slope determination right at the beginning of the window!")
print('Choose longer slope determination window!') print("Choose longer slope determination window!")
if self.iplot > 1: if self.iplot > 1:
if not self.fig: if not self.fig:
fig = plt.figure() #self.iplot) ### WHY? MP MP fig = plt.figure() #self.iplot) ### WHY? MP MP
@ -233,18 +247,13 @@ class AICPicker(AutoPicker):
fig = self.fig fig = self.fig
ax = fig.add_subplot(111) ax = fig.add_subplot(111)
x = self.Data[0].data x = self.Data[0].data
ax.plot(self.Tcf, x / max(x), 'k', legend='(HOS-/AR-) Data') ax.plot(self.Tcf, x / max(x), 'k', label='(HOS-/AR-) Data')
ax.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r', legend='Smoothed AIC-CF') ax.plot(self.Tcf, aicsmooth / max(aicsmooth), 'r', label='Smoothed AIC-CF')
ax.legend() ax.legend()
ax.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime) ax.set_xlabel('Time [s] since %s' % self.Data[0].stats.starttime)
ax.set_yticks([]) ax.set_yticks([])
ax.set_title(self.Data[0].stats.station) ax.set_title(self.Data[0].stats.station)
return return
iislope = islope[0][0:imax]
if len(iislope) <= 3:
# calculate slope from initial onset to maximum of AIC function
imax = np.argmax(aicsmooth[islope])
iislope = islope[0][0:imax] iislope = islope[0][0:imax]
dataslope = self.Data[0].data[iislope] dataslope = self.Data[0].data[iislope]
# calculate slope as polynomal fit of order 1 # calculate slope as polynomal fit of order 1

144
pylot/core/util/event.py Normal file
View File

@ -0,0 +1,144 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from obspy import UTCDateTime
from obspy.core.event import Event as ObsPyEvent
from obspy.core.event import Origin, Magnitude, ResourceIdentifier
from pylot.core.io.phases import picks_from_picksdict
class Event(ObsPyEvent):
'''
Pickable class derived from ~obspy.core.event.Event containing information on a single event.
'''
def __init__(self, path):
self.pylot_id = path.split('/')[-1]
# initialize super class
super(Event, self).__init__(resource_id=ResourceIdentifier('smi:local/'+self.pylot_id))
self.path = path
self.database = path.split('/')[-2]
self.datapath = path.split('/')[-3]
self.rootpath = '/' + os.path.join(*path.split('/')[:-3])
self.pylot_autopicks = {}
self.pylot_picks = {}
self.notes = ''
self._testEvent = False
self._refEvent = False
self.get_notes()
def get_notes_path(self):
notesfile = os.path.join(self.path, 'notes.txt')
return notesfile
def get_notes(self):
notesfile = self.get_notes_path()
if os.path.isfile(notesfile):
with open(notesfile) as infile:
path = str(infile.readlines()[0].split('\n')[0])
text = '[eventInfo: '+path+']'
self.addNotes(text)
try:
datetime = UTCDateTime(path.split('/')[-1])
origin = Origin(resource_id=self.resource_id, time=datetime, latitude=0, longitude=0, depth=0)
self.origins.append(origin)
except:
pass
def addNotes(self, notes):
self.notes = str(notes)
def clearNotes(self):
self.notes = None
def isRefEvent(self):
return self._refEvent
def isTestEvent(self):
return self._testEvent
def setRefEvent(self, bool):
self._refEvent = bool
if bool: self._testEvent = False
def setTestEvent(self, bool):
self._testEvent = bool
if bool: self._refEvent = False
def addPicks(self, picks):
'''
add pylot picks and overwrite existing
'''
for station in picks:
self.pylot_picks[station] = picks[station]
#add ObsPy picks
self.picks = picks_from_picksdict(self.pylot_picks)
def addAutopicks(self, autopicks):
for station in autopicks:
self.pylot_autopicks[station] = autopicks[station]
def setPick(self, station, pick):
if pick:
self.pylot_picks[station] = pick
self.picks = picks_from_picksdict(self.pylot_picks)
def setPicks(self, picks):
'''
set pylot picks and delete and overwrite all existing
'''
self.pylot_picks = picks
self.picks = picks_from_picksdict(self.pylot_picks)
def getPick(self, station):
if station in self.pylot_picks.keys():
return self.pylot_picks[station]
def getPicks(self):
return self.pylot_picks
def setAutopick(self, station, autopick):
if autopick:
self.pylot_autopicks[station] = autopick
def setAutopicks(self, autopicks):
self.pylot_autopicks = autopicks
def getAutopick(self, station):
if station in self.pylot_autopicks.keys():
return self.pylot_autopicks[station]
def getAutopicks(self):
return self.pylot_autopicks
def save(self, filename):
'''
Save PyLoT Event to a file.
Can be loaded by using event.load(filename).
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
try:
outfile = open(filename, 'wb')
cPickle.dump(self, outfile, -1)
except Exception as e:
print('Could not pickle PyLoT event. Reason: {}'.format(e))
@staticmethod
def load(filename):
'''
Load project from filename.
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
infile = open(filename, 'rb')
event = cPickle.load(infile)
print('Loaded %s' % filename)
return event

View File

@ -22,6 +22,7 @@ class map_projection(QtGui.QWidget):
self.parser = parent.metadata[1] self.parser = parent.metadata[1]
self.picks = None self.picks = None
self.picks_dict = None self.picks_dict = None
self.eventLoc = None
self.figure = figure self.figure = figure
self.init_graphics() self.init_graphics()
self.init_stations() self.init_stations()
@ -244,6 +245,10 @@ class map_projection(QtGui.QWidget):
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True, self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
zorder=10, picker=True, edgecolor='m', label='Not Picked') zorder=10, picker=True, edgecolor='m', label='Not Picked')
self.cid = self.canvas.mpl_connect('pick_event', self.onpick) self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
if self.eventLoc:
lat, lon = self.eventLoc
self.sc_event = self.basemap.scatter(lon, lat, s=100, facecolor='red',
latlon=True, zorder=11, label='Event (might be outside map region)')
def scatter_picked_stations(self): def scatter_picked_stations(self):
lon = self.lon_no_nan lon = self.lon_no_nan
@ -274,8 +279,7 @@ class map_projection(QtGui.QWidget):
def refresh_drawings(self, picks=None): def refresh_drawings(self, picks=None):
self.picks_dict = picks self.picks_dict = picks
self.remove_drawings() self._refresh_drawings()
self.draw_everything()
def _refresh_drawings(self): def _refresh_drawings(self):
self.remove_drawings() self.remove_drawings()
@ -303,6 +307,9 @@ class map_projection(QtGui.QWidget):
if hasattr(self, 'sc_picked'): if hasattr(self, 'sc_picked'):
self.sc_picked.remove() self.sc_picked.remove()
del(self.sc_picked) del(self.sc_picked)
if hasattr(self, 'sc_event'):
self.sc_event.remove()
del(self.sc_event)
if hasattr(self, 'cbar'): if hasattr(self, 'cbar'):
self.cbar.remove() self.cbar.remove()
del(self.cbar) del(self.cbar)

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys, os
from PySide.QtCore import QThread, Signal, Qt from PySide.QtCore import QThread, Signal, Qt
from PySide.QtGui import QDialog, QProgressBar, QLabel, QHBoxLayout from PySide.QtGui import QDialog, QProgressBar, QLabel, QHBoxLayout
@ -64,7 +64,9 @@ class Thread(QThread):
except Exception as e: except Exception as e:
self._executed = False self._executed = False
self._executedError = e self._executedError = e
print(e) exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print('Exception: {}, file: {}, line: {}'.format(exc_type, fname, exc_tb.tb_lineno))
sys.stdout = sys.__stdout__ sys.stdout = sys.__stdout__
def __del__(self): def __del__(self):

View File

@ -10,7 +10,7 @@ import re
import warnings import warnings
import subprocess import subprocess
from obspy import UTCDateTime, read from obspy import UTCDateTime, read
from pylot.core.io.inputs import AutoPickParameter from pylot.core.io.inputs import PylotParameter
def _pickle_method(m): def _pickle_method(m):
@ -497,7 +497,7 @@ def which(program, infile=None):
bpath = os.path.join(os.path.expanduser('~'), '.pylot', infile) bpath = os.path.join(os.path.expanduser('~'), '.pylot', infile)
if os.path.exists(bpath): if os.path.exists(bpath):
nllocpath = ":" + AutoPickParameter(bpath).get('nllocbin') nllocpath = ":" + PylotParameter(bpath).get('nllocbin')
os.environ['PATH'] += nllocpath os.environ['PATH'] += nllocpath
except ImportError as e: except ImportError as e:
print(e.message) print(e.message)

View File

@ -12,6 +12,11 @@ import copy
import datetime import datetime
import numpy as np import numpy as np
try:
import pyqtgraph as pg
except:
pg = None
from matplotlib.figure import Figure from matplotlib.figure import Figure
from pylot.core.util.utils import find_horizontals from pylot.core.util.utils import find_horizontals
@ -31,7 +36,7 @@ from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
from PySide.QtWebKit import QWebView from PySide.QtWebKit import QWebView
from obspy import Stream, UTCDateTime from obspy import Stream, UTCDateTime
from pylot.core.io.data import Data from pylot.core.io.data import Data
from pylot.core.io.inputs import FilterOptions, AutoPickParameter from pylot.core.io.inputs import FilterOptions, PylotParameter
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \ from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
getResolutionWindow getResolutionWindow
from pylot.core.pick.compare import Comparison from pylot.core.pick.compare import Comparison
@ -42,6 +47,12 @@ from autoPyLoT import autoPyLoT
from pylot.core.util.thread import Thread from pylot.core.util.thread import Thread
import icons_rc import icons_rc
if pg:
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
pg.setConfigOptions(antialias=True)
#pg.setConfigOption('leftButtonPan', False)
def getDataType(parent): def getDataType(parent):
type = QInputDialog().getItem(parent, "Select phases type", "Type:", type = QInputDialog().getItem(parent, "Select phases type", "Type:",
["manual", "automatic"]) ["manual", "automatic"])
@ -393,6 +404,174 @@ class PlotWidget(FigureCanvas):
return self._parent return self._parent
class WaveformWidgetPG(QtGui.QWidget):
def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'):
QtGui.QWidget.__init__(self, parent)#, 1)
self.setParent(parent)
self._parent = parent
# attribute plotdict is a dictionary connecting position and a name
self.plotdict = dict()
# create plot
self.main_layout = QtGui.QVBoxLayout()
self.label = QtGui.QLabel()
self.setLayout(self.main_layout)
self.plotWidget = pg.PlotWidget(title=title, autoDownsample=True)
self.main_layout.addWidget(self.plotWidget)
self.main_layout.addWidget(self.label)
self.plotWidget.showGrid(x=False, y=True, alpha=0.2)
self.plotWidget.hideAxis('bottom')
self.plotWidget.hideAxis('left')
self.reinitMoveProxy()
self._proxy = pg.SignalProxy(self.plotWidget.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
def reinitMoveProxy(self):
self.vLine = pg.InfiniteLine(angle=90, movable=False)
self.hLine = pg.InfiniteLine(angle=0, movable=False)
self.plotWidget.addItem(self.vLine, ignoreBounds=True)
self.plotWidget.addItem(self.hLine, ignoreBounds=True)
def mouseMoved(self, evt):
pos = evt[0] ## using signal proxy turns original arguments into a tuple
if self.plotWidget.sceneBoundingRect().contains(pos):
mousePoint = self.plotWidget.getPlotItem().vb.mapSceneToView(pos)
x, y, = (mousePoint.x(), mousePoint.y())
#if x > 0:# and index < len(data1):
wfID = self._parent.getWFID(y)
station = self._parent.getStationName(wfID)
if self._parent.get_current_event():
self.label.setText("station = {}, t = {} [s]".format(station, x))
self.vLine.setPos(mousePoint.x())
self.hLine.setPos(mousePoint.y())
def getPlotDict(self):
return self.plotdict
def setPlotDict(self, key, value):
self.plotdict[key] = value
def clearPlotDict(self):
self.plotdict = dict()
def getParent(self):
return self._parent
def setParent(self, parent):
self._parent = parent
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None,
noiselevel=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, iniPick=None):
self.title = title
self.clearPlotDict()
wfstart, wfend = full_range(wfdata)
nmax = 0
settings = QSettings()
compclass = settings.value('compclass')
if not compclass:
print('Warning: No settings for channel components found. Using default')
compclass = SetChannelComponents()
if not component == '*':
alter_comp = compclass.getCompPosition(component)
#alter_comp = str(alter_comp[0])
st_select = wfdata.select(component=component)
st_select += wfdata.select(component=alter_comp)
else:
st_select = wfdata
# list containing tuples of network, station, channel (for sorting)
nsc = []
for trace in st_select:
nsc.append((trace.stats.network, trace.stats.station, trace.stats.channel))
nsc.sort()
nsc.reverse()
plots = []
try:
self.plotWidget.getPlotItem().vb.setLimits(xMin=float(0),
xMax=float(wfend-wfstart),
yMin=-0.5,
yMax=len(nsc)+0.5)
except:
print('Warning: Could not set zoom limits')
for n, (network, station, channel) in enumerate(nsc):
st = st_select.select(network=network, station=station, channel=channel)
trace = st[0]
if mapping:
comp = channel[-1]
n = compclass.getPlotPosition(str(comp))
#n = n[0]
if n > nmax:
nmax = n
msg = 'plotting %s channel of station %s' % (channel, station)
print(msg)
stime = trace.stats.starttime - wfstart
time_ax = prepTimeAxis(stime, trace)
if time_ax is not None:
if not scaleddata:
trace.detrend('constant')
trace.normalize(np.max(np.abs(trace.data)) * 2)
times = [time for index, time in enumerate(time_ax) if not index%nth_sample]
data = [datum + n for index, datum in enumerate(trace.data) if not index%nth_sample]
plots.append((times, data))
self.setPlotDict(n, (station, channel, network))
self.xlabel = 'seconds since {0}'.format(wfstart)
self.ylabel = ''
self.setXLims([0, wfend - wfstart])
self.setYLims([-0.5, nmax + 0.5])
return plots
# def getAxes(self):
# return self.axes
# def getXLims(self):
# return self.getAxes().get_xlim()
# def getYLims(self):
# return self.getAxes().get_ylim()
def setXLims(self, lims):
vb = self.plotWidget.getPlotItem().getViewBox()
vb.setXRange(float(lims[0]), float(lims[1]), padding=0)
def setYLims(self, lims):
vb = self.plotWidget.getPlotItem().getViewBox()
vb.setYRange(float(lims[0]), float(lims[1]), padding=0)
def setYTickLabels(self, pos, labels):
ticks = zip(pos, labels)
minorTicks = [(0, 0) for item in labels]
# leftAx.tickLength = 5
# leftAx.orientation = 'right'
self.getAxItem('left').setTicks([ticks, minorTicks])
def updateXLabel(self, text):
self.getAxItem('bottom').setLabel(text)
self.draw()
def updateYLabel(self, text):
self.getAxItem('left').setLabel(text)
self.draw()
def getAxItem(self, position):
return self.plotWidget.getPlotItem().axes[position]['item']
def updateTitle(self, text):
self.plotWidget.getPlotItem().setTitle(text)
self.draw()
def updateWidget(self):#, xlabel, ylabel, title):
self.updateXLabel(self.xlabel)
self.updateYLabel(self.ylabel)
self.updateTitle(self.title)
def draw(self):
pass
class WaveformWidget(FigureCanvas): class WaveformWidget(FigureCanvas):
def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'): def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'):
@ -446,18 +625,20 @@ class WaveformWidget(FigureCanvas):
alter_comp = compclass.getCompPosition(component) alter_comp = compclass.getCompPosition(component)
#alter_comp = str(alter_comp[0]) #alter_comp = str(alter_comp[0])
wfdata = wfdata.select(component=component) st_select = wfdata.select(component=component)
wfdata += wfdata.select(component=alter_comp) st_select += wfdata.select(component=alter_comp)
else:
st_select = wfdata
# list containing tuples of network, station, channel (for sorting) # list containing tuples of network, station, channel (for sorting)
nsc = [] nsc = []
for trace in wfdata: for trace in st_select:
nsc.append((trace.stats.network, trace.stats.station, trace.stats.channel)) nsc.append((trace.stats.network, trace.stats.station, trace.stats.channel))
nsc.sort() nsc.sort()
nsc.reverse() nsc.reverse()
for n, (network, station, channel) in enumerate(nsc): for n, (network, station, channel) in enumerate(nsc):
st = wfdata.select(network=network, station=station, channel=channel) st = st_select.select(network=network, station=station, channel=channel)
trace = st[0] trace = st[0]
if mapping: if mapping:
comp = channel[-1] comp = channel[-1]
@ -571,6 +752,7 @@ class PickDlg(QDialog):
self._init_autopicks = {} self._init_autopicks = {}
self.filteroptions = FILTERDEFAULTS self.filteroptions = FILTERDEFAULTS
self.pick_block = False self.pick_block = False
self.nextStation = QtGui.QCheckBox('Continue with next station.')
# initialize panning attributes # initialize panning attributes
self.press = None self.press = None
@ -664,9 +846,6 @@ class PickDlg(QDialog):
self.s_button = QPushButton('S', self) self.s_button = QPushButton('S', self)
self.p_button.setCheckable(True) self.p_button.setCheckable(True)
self.s_button.setCheckable(True) self.s_button.setCheckable(True)
# button shortcuts (1 for P-button, 2 for S-button)
self.p_button.setShortcut(QKeySequence('1'))
self.s_button.setShortcut(QKeySequence('2'))
# set button tooltips # set button tooltips
self.p_button.setToolTip('Hotkey: "1"') self.p_button.setToolTip('Hotkey: "1"')
self.s_button.setToolTip('Hotkey: "2"') self.s_button.setToolTip('Hotkey: "2"')
@ -676,6 +855,13 @@ class PickDlg(QDialog):
self.reject_button = QPushButton('&Reject Picks') self.reject_button = QPushButton('&Reject Picks')
self.disable_ar_buttons() self.disable_ar_buttons()
# add hotkeys
self._shortcut_space = QtGui.QShortcut(QtGui.QKeySequence(' '), self)
self._shortcut_space.activated.connect(self.accept_button.clicked)
# button shortcuts (1 for P-button, 2 for S-button)
self.p_button.setShortcut(QKeySequence('1'))
self.s_button.setShortcut(QKeySequence('2'))
# layout the outermost appearance of the Pick Dialog # layout the outermost appearance of the Pick Dialog
_outerlayout = QVBoxLayout() _outerlayout = QVBoxLayout()
_dialtoolbar = QToolBar() _dialtoolbar = QToolBar()
@ -692,6 +878,8 @@ class PickDlg(QDialog):
if self._embedded: if self._embedded:
_dialtoolbar.addWidget(self.accept_button) _dialtoolbar.addWidget(self.accept_button)
_dialtoolbar.addWidget(self.reject_button) _dialtoolbar.addWidget(self.reject_button)
else:
_dialtoolbar.addWidget(self.nextStation)
# layout the innermost widget # layout the innermost widget
_innerlayout = QVBoxLayout() _innerlayout = QVBoxLayout()
@ -1429,7 +1617,6 @@ class TuneAutopicker(QWidget):
self.eventBox = self.parent.createEventBox() self.eventBox = self.parent.createEventBox()
self.eventBox.setMaxVisibleItems(20) self.eventBox.setMaxVisibleItems(20)
self.fill_eventbox() self.fill_eventbox()
self.eventBox.setCurrentIndex(0)
self.trace_layout.addWidget(self.eventBox) self.trace_layout.addWidget(self.eventBox)
def init_stationlist(self): def init_stationlist(self):
@ -1459,7 +1646,7 @@ class TuneAutopicker(QWidget):
model = self.stationBox.model() model = self.stationBox.model()
for network, station in stations: for network, station in stations:
item = QtGui.QStandardItem(network+'.'+station) item = QtGui.QStandardItem(network+'.'+station)
if station in self.get_current_event().picks: if station in self.get_current_event().pylot_picks:
item.setBackground(self.parent._colors['ref']) item.setBackground(self.parent._colors['ref'])
model.appendRow(item) model.appendRow(item)
@ -1475,7 +1662,7 @@ class TuneAutopicker(QWidget):
self.stb_names = ['aicARHfig', 'refSpick', 'el_S1pick', 'el_S2pick'] self.stb_names = ['aicARHfig', 'refSpick', 'el_S1pick', 'el_S2pick']
def add_parameters(self): def add_parameters(self):
self.paraBox = AutoPickParaBox(self.parameter) self.paraBox = PylotParaBox(self.parameter)
self.paraBox.set_tune_mode(True) self.paraBox.set_tune_mode(True)
self.update_eventID() self.update_eventID()
self.parameter_layout.addWidget(self.paraBox) self.parameter_layout.addWidget(self.paraBox)
@ -1500,8 +1687,8 @@ class TuneAutopicker(QWidget):
self.listWidget.scrollToBottom() self.listWidget.scrollToBottom()
def get_current_event(self): def get_current_event(self):
index = self.eventBox.currentIndex() path = self.eventBox.currentText()
return self.eventBox.itemData(index) return self.parent.project.getEventFromPath(path)
def get_current_event_name(self): def get_current_event_name(self):
return self.eventBox.currentText().split('/')[-1] return self.eventBox.currentText().split('/')[-1]
@ -1511,13 +1698,13 @@ class TuneAutopicker(QWidget):
def get_current_event_picks(self, station): def get_current_event_picks(self, station):
event = self.get_current_event() event = self.get_current_event()
if station in event.picks.keys(): if station in event.pylot_picks.keys():
return event.picks[station] return event.pylot_picks[station]
def get_current_event_autopicks(self, station): def get_current_event_autopicks(self, station):
event = self.get_current_event() event = self.get_current_event()
if event.autopicks: if event.pylot_autopicks:
return event.autopicks[station] return event.pylot_autopicks[station]
def get_current_station(self): def get_current_station(self):
return str(self.stationBox.currentText()).split('.')[-1] return str(self.stationBox.currentText()).split('.')[-1]
@ -1531,6 +1718,9 @@ class TuneAutopicker(QWidget):
return widget return widget
def gen_pick_dlg(self): def gen_pick_dlg(self):
if not self.get_current_event():
self.pickDlg = None
return
station = self.get_current_station() station = self.get_current_station()
data = self.data.getWFData() data = self.data.getWFData()
pickDlg = PickDlg(self, data=data.select(station=station), pickDlg = PickDlg(self, data=data.select(station=station),
@ -1541,7 +1731,6 @@ class TuneAutopicker(QWidget):
pickDlg.update_picks.connect(self.picks_from_pickdlg) pickDlg.update_picks.connect(self.picks_from_pickdlg)
pickDlg.update_picks.connect(self.fill_eventbox) pickDlg.update_picks.connect(self.fill_eventbox)
pickDlg.update_picks.connect(self.fill_stationbox) pickDlg.update_picks.connect(self.fill_stationbox)
pickDlg.update_picks.connect(self.parent.drawPicks)
pickDlg.update_picks.connect(lambda: self.parent.setDirty(True)) pickDlg.update_picks.connect(lambda: self.parent.setDirty(True))
pickDlg.update_picks.connect(self.parent.enableSaveManualPicksAction) pickDlg.update_picks.connect(self.parent.enableSaveManualPicksAction)
self.pickDlg = QtGui.QWidget() self.pickDlg = QtGui.QWidget()
@ -1551,7 +1740,15 @@ class TuneAutopicker(QWidget):
def picks_from_pickdlg(self, picks=None): def picks_from_pickdlg(self, picks=None):
station = self.get_current_station() station = self.get_current_station()
replot = self.parent.addPicks(station, picks)
self.get_current_event().setPick(station, picks) self.get_current_event().setPick(station, picks)
if self.get_current_event() == self.parent.get_current_event():
if replot:
self.parent.plotWaveformDataThread()
self.parent.drawPicks()
else:
self.parent.drawPicks(station)
self.parent.draw()
def plot_manual_picks_to_figs(self): def plot_manual_picks_to_figs(self):
picks = self.get_current_event_picks(self.get_current_station()) picks = self.get_current_event_picks(self.get_current_station())
@ -1619,7 +1816,7 @@ class TuneAutopicker(QWidget):
id1 = self.figure_tabs.insertTab(1, self.overview, 'Overview') id1 = self.figure_tabs.insertTab(1, self.overview, 'Overview')
id2 = self.figure_tabs.insertTab(2, self.p_tabs, 'P') id2 = self.figure_tabs.insertTab(2, self.p_tabs, 'P')
id3 = self.figure_tabs.insertTab(3, self.s_tabs, 'S') id3 = self.figure_tabs.insertTab(3, self.s_tabs, 'S')
if picked: if picked and self.get_current_event():
self.fill_p_tabs(canvas_dict) self.fill_p_tabs(canvas_dict)
self.fill_s_tabs(canvas_dict) self.fill_s_tabs(canvas_dict)
self.toggle_autopickTabs(bool(self.fig_dict['mainFig'].axes)) self.toggle_autopickTabs(bool(self.fig_dict['mainFig'].axes))
@ -1658,7 +1855,30 @@ class TuneAutopicker(QWidget):
self.init_tab_names() self.init_tab_names()
def fill_eventbox(self): def fill_eventbox(self):
project = self.parent.project
if not project:
return
# update own list
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref') self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
index_start = self.parent.eventBox.currentIndex()
index = index_start
if index == -1:
index += 1
nevents = self.eventBox.model().rowCount()
path = self.eventBox.itemText(index)
if project.getEventFromPath(path).isTestEvent():
for index in range(nevents):
path = self.eventBox.itemText(index)
if project.getEventFromPath(index):
if not project.getEventFromPath(index).isTestEvent():
break
#in case all events are marked as test events and last event is reached
if index == nevents - 1:
index = -1
self.eventBox.setCurrentIndex(index)
if not index == index_start:
self.eventBox.activated.emit(index)
# update parent
self.parent.fill_eventbox() self.parent.fill_eventbox()
def update_eventID(self): def update_eventID(self):
@ -1698,8 +1918,8 @@ class TuneAutopicker(QWidget):
self._warn('Could not execute picker:\n{}'.format( self._warn('Could not execute picker:\n{}'.format(
self.ap_thread._executedError)) self.ap_thread._executedError))
return return
self.picks = self.ap_thread.data self.pylot_picks = self.ap_thread.data
if not self.picks: if not self.pylot_picks:
self._warn('No picks found. See terminal output.') self._warn('No picks found. See terminal output.')
return return
#renew tabs #renew tabs
@ -1729,6 +1949,7 @@ class TuneAutopicker(QWidget):
def clear_all(self): def clear_all(self):
if hasattr(self, 'pickDlg'): if hasattr(self, 'pickDlg'):
if self.pickDlg:
self.pickDlg.setParent(None) self.pickDlg.setParent(None)
del(self.pickDlg) del(self.pickDlg)
if hasattr(self, 'overview'): if hasattr(self, 'overview'):
@ -1754,13 +1975,13 @@ class TuneAutopicker(QWidget):
self.qmb.show() self.qmb.show()
class AutoPickParaBox(QtGui.QWidget): class PylotParaBox(QtGui.QWidget):
def __init__(self, parameter, parent=None): def __init__(self, parameter, parent=None):
''' '''
Generate Widget containing parameters for automatic picking algorithm. Generate Widget containing parameters for automatic picking algorithm.
:param: parameter :param: parameter
:type: AutoPickParameter (object) :type: PylotParameter (object)
''' '''
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
@ -1773,6 +1994,7 @@ class AutoPickParaBox(QtGui.QWidget):
self.labels = {} self.labels = {}
self.boxes = {} self.boxes = {}
self.groupboxes = {} self.groupboxes = {}
self._exclusive_widgets = []
self._init_sublayouts() self._init_sublayouts()
self.setLayout(self.layout) self.setLayout(self.layout)
self.add_main_parameters_tab() self.add_main_parameters_tab()
@ -1780,6 +2002,7 @@ class AutoPickParaBox(QtGui.QWidget):
self.params_to_gui() self.params_to_gui()
self._toggle_advanced_settings() self._toggle_advanced_settings()
self.resize(720, 1280) self.resize(720, 1280)
self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
def _init_sublayouts(self): def _init_sublayouts(self):
self._main_layout = QtGui.QVBoxLayout() self._main_layout = QtGui.QVBoxLayout()
@ -1819,7 +2042,7 @@ class AutoPickParaBox(QtGui.QWidget):
def _create_advanced_cb(self): def _create_advanced_cb(self):
self._advanced_cb = QtGui.QCheckBox('Enable Advanced Settings') self._advanced_cb = QtGui.QCheckBox('Enable Advanced Settings')
self._advanced_layout.addWidget(self._advanced_cb) self._advanced_layout.insertWidget(0, self._advanced_cb)
self._advanced_cb.toggled.connect(self._toggle_advanced_settings) self._advanced_cb.toggled.connect(self._toggle_advanced_settings)
def _toggle_advanced_settings(self): def _toggle_advanced_settings(self):
@ -1907,31 +2130,31 @@ class AutoPickParaBox(QtGui.QWidget):
scrollA = QtGui.QScrollArea() scrollA = QtGui.QScrollArea()
scrollA.setWidgetResizable(True) scrollA.setWidgetResizable(True)
scrollA.setWidget(widget) scrollA.setWidget(widget)
widget.setLayout(layout) widget.setLayout(layout)
self.tabs.addTab(scrollA, name) self.tabs.addTab(scrollA, name)
def add_main_parameters_tab(self): def add_main_parameters_tab(self):
self.add_to_layout(self._main_layout, 'Directories', self.add_to_layout(self._main_layout, 'Directories',
self.parameter.get_main_para_names()['dirs']) self.parameter.get_main_para_names()['dirs'], 0)
self.add_to_layout(self._main_layout, 'NLLoc', self.add_to_layout(self._main_layout, 'NLLoc',
self.parameter.get_main_para_names()['nlloc']) self.parameter.get_main_para_names()['nlloc'], 1)
self.add_to_layout(self._main_layout, 'Seismic Moment', self.add_to_layout(self._main_layout, 'Seismic Moment',
self.parameter.get_main_para_names()['smoment']) self.parameter.get_main_para_names()['smoment'], 2)
self.add_to_layout(self._main_layout, 'Local Magnitude',
self.parameter.get_main_para_names()['localmag'], 3)
self.add_to_layout(self._main_layout, 'Common Settings Characteristic Function', self.add_to_layout(self._main_layout, 'Common Settings Characteristic Function',
self.parameter.get_main_para_names()['pick']) self.parameter.get_main_para_names()['pick'], 4)
self.add_tab(self._main_layout, 'Main Settings') self.add_tab(self._main_layout, 'Main Settings')
def add_special_pick_parameters_tab(self): def add_special_pick_parameters_tab(self):
self.add_to_layout(self._advanced_layout, 'Z-component', self.add_to_layout(self._advanced_layout, 'Z-component',
self.parameter.get_special_para_names()['z']) self.parameter.get_special_para_names()['z'], 1)
self.add_to_layout(self._advanced_layout, 'H-components', self.add_to_layout(self._advanced_layout, 'H-components',
self.parameter.get_special_para_names()['h']) self.parameter.get_special_para_names()['h'], 2)
self.add_to_layout(self._advanced_layout, 'First-motion picker', self.add_to_layout(self._advanced_layout, 'First-motion picker',
self.parameter.get_special_para_names()['fm']) self.parameter.get_special_para_names()['fm'], 3)
self.add_to_layout(self._advanced_layout, 'Quality assessment', self.add_to_layout(self._advanced_layout, 'Quality assessment',
self.parameter.get_special_para_names()['quality']) self.parameter.get_special_para_names()['quality'], 4)
self.add_tab(self._advanced_layout, 'Advanced Settings') self.add_tab(self._advanced_layout, 'Advanced Settings')
# def gen_h_seperator(self): # def gen_h_seperator(self):
@ -1946,11 +2169,45 @@ class AutoPickParaBox(QtGui.QWidget):
# label.setFont(font) # label.setFont(font)
# return label # return label
def add_to_layout(self, layout, name, items): def refresh(self):
for groupbox in self.groupboxes.values():
layout = groupbox._parentLayout
position = groupbox._position
layout.insertWidget(position, groupbox)
def get_groupbox_exclusive(self, name):
widget = QtGui.QWidget(self, 1)
layout = QtGui.QVBoxLayout()
widget.setLayout(layout)
layout.addWidget(self.groupboxes[name])
self._exclusive_widgets.append(widget)
return widget
def get_groupbox_dialog(self, name):
widget = self.get_groupbox_exclusive(name)
dialog = QtGui.QDialog(self.parent())
layout = QtGui.QVBoxLayout()
dialog.setLayout(layout)
buttonbox = QtGui.QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
buttonbox.accepted.connect(dialog.accept)
buttonbox.accepted.connect(self.refresh)
buttonbox.accepted.connect(self.params_from_gui)
buttonbox.rejected.connect(dialog.reject)
buttonbox.rejected.connect(self.refresh)
buttonbox.rejected.connect(self.params_to_gui)
layout.addWidget(widget)
layout.addWidget(buttonbox)
self._exclusive_dialog = dialog
return dialog
def add_to_layout(self, layout, name, items, position):
groupbox = QtGui.QGroupBox(name) groupbox = QtGui.QGroupBox(name)
groupbox._position = position
groupbox._parentLayout = layout
self.groupboxes[name] = groupbox self.groupboxes[name] = groupbox
groupbox.setLayout(self.init_boxes(items)) groupbox.setLayout(self.init_boxes(items))
layout.addWidget(groupbox) layout.insertWidget(position, groupbox)
def show_groupboxes(self): def show_groupboxes(self):
for name in self.groupboxes.keys(): for name in self.groupboxes.keys():
@ -1974,6 +2231,16 @@ class AutoPickParaBox(QtGui.QWidget):
else: else:
print('Groupbox {} not part of object.'.format(name)) print('Groupbox {} not part of object.'.format(name))
def show_file_buttons(self):
self.saveButton.show()
self.loadButton.show()
self.defaultsButton.show()
def hide_file_buttons(self):
self.saveButton.hide()
self.loadButton.hide()
self.defaultsButton.hide()
def show_parameter(self, name=None): def show_parameter(self, name=None):
if not name: if not name:
for name in self.boxes.keys(): for name in self.boxes.keys():
@ -2028,6 +2295,8 @@ class AutoPickParaBox(QtGui.QWidget):
if type(box) == QtGui.QLineEdit: if type(box) == QtGui.QLineEdit:
box.setText(str(value)) box.setText(str(value))
elif type(box) == QtGui.QSpinBox or type(box) == QtGui.QDoubleSpinBox: elif type(box) == QtGui.QSpinBox or type(box) == QtGui.QDoubleSpinBox:
if not value:
value = 0.
box.setValue(value) box.setValue(value)
elif type(box) == QtGui.QCheckBox: elif type(box) == QtGui.QCheckBox:
if value == 'True': if value == 'True':
@ -2085,6 +2354,14 @@ class AutoPickParaBox(QtGui.QWidget):
self._warn('Could not restore defaults:\n{}'.format(e)) self._warn('Could not restore defaults:\n{}'.format(e))
return return
def show(self):
self.refresh()
self.show_parameter()
if hasattr(self, '_exclusive_dialog'):
self._exclusive_dialog.close()
self._exclusive_widgets = []
QtGui.QWidget.show(self)
def _warn(self, message): def _warn(self, message):
self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning, self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning,
'Warning', message) 'Warning', message)
@ -2197,6 +2474,7 @@ class PropTab(QWidget):
def resetValues(self, infile=None): def resetValues(self, infile=None):
return None return None
class InputsTab(PropTab): class InputsTab(PropTab):
def __init__(self, parent, infile=None): def __init__(self, parent, infile=None):
super(InputsTab, self).__init__(parent) super(InputsTab, self).__init__(parent)
@ -2250,7 +2528,7 @@ class InputsTab(PropTab):
return values return values
def resetValues(self, infile): def resetValues(self, infile):
para = AutoPickParameter(infile) para = PylotParameter(infile)
datstruct = para.get('datastructure') datstruct = para.get('datastructure')
if datstruct == 'SeisComp': if datstruct == 'SeisComp':
index = 0 index = 0
@ -2307,6 +2585,7 @@ class GraphicsTab(PropTab):
def __init__(self, parent=None): def __init__(self, parent=None):
super(GraphicsTab, self).__init__(parent) super(GraphicsTab, self).__init__(parent)
self.init_layout() self.init_layout()
self.add_pg_cb()
self.add_nth_sample() self.add_nth_sample()
self.setLayout(self.main_layout) self.setLayout(self.main_layout)
@ -2321,15 +2600,28 @@ class GraphicsTab(PropTab):
self.spinbox_nth_sample = QtGui.QSpinBox() self.spinbox_nth_sample = QtGui.QSpinBox()
label = QLabel('nth sample') label = QLabel('nth sample')
label.setToolTip('Plot every nth sample (to speed up plotting)')
self.spinbox_nth_sample.setMinimum(1) self.spinbox_nth_sample.setMinimum(1)
self.spinbox_nth_sample.setMaximum(10e3) self.spinbox_nth_sample.setMaximum(10e3)
self.spinbox_nth_sample.setValue(int(nth_sample)) self.spinbox_nth_sample.setValue(int(nth_sample))
label.setToolTip('Plot every nth sample (to speed up plotting)') self.main_layout.addWidget(label, 1, 0)
self.main_layout.addWidget(self.spinbox_nth_sample, 1, 1)
def add_pg_cb(self):
text = {True: 'Use pyqtgraphic library for plotting',
False: 'Cannot use library: pyqtgraphic not found on system'}
label = QLabel('PyQt graphic')
label.setToolTip(text[bool(pg)])
label.setEnabled(bool(pg))
self.checkbox_pg = QtGui.QCheckBox()
self.checkbox_pg.setEnabled(bool(pg))
self.checkbox_pg.setChecked(bool(pg))
self.main_layout.addWidget(label, 0, 0) self.main_layout.addWidget(label, 0, 0)
self.main_layout.addWidget(self.spinbox_nth_sample, 0, 1) self.main_layout.addWidget(self.checkbox_pg, 0, 1)
def getValues(self): def getValues(self):
values = {'nth_sample': self.spinbox_nth_sample.value()} values = {'nth_sample': self.spinbox_nth_sample.value(),
'pyqtgraphic': self.checkbox_pg.isChecked()}
return values return values
@ -2492,7 +2784,7 @@ class LocalisationTab(PropTab):
return values return values
def resetValues(self, infile): def resetValues(self, infile):
para = AutoPickParameter(infile) para = PylotParameter(infile)
nllocroot = para.get('nllocroot') nllocroot = para.get('nllocroot')
nllocbin = para.get('nllocbin') nllocbin = para.get('nllocbin')
loctool = self.locToolComboBox.setCurrentIndex(3) loctool = self.locToolComboBox.setCurrentIndex(3)