Merge branch 'develop' into filterOptions

This commit is contained in:
Marcel Paffrath 2017-07-04 10:19:42 +02:00
commit 5bc9f14074
51 changed files with 98966 additions and 71340 deletions

View File

@ -41,6 +41,8 @@ from PySide.QtGui import QMainWindow, QInputDialog, QIcon, QFileDialog, \
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout
import numpy as np
from obspy import UTCDateTime
from obspy.core.event import Magnitude
from obspy.core.util import AttribDict
try:
import pyqtgraph as pg
@ -70,6 +72,7 @@ from pylot.core.util.connection import checkurl
from pylot.core.util.dataprocessing import read_metadata, restitute_data
from pylot.core.util.utils import fnConstructor, getLogin, \
full_range
from pylot.core.util.event import Event
from pylot.core.io.location import create_creation_info, create_event
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
@ -143,6 +146,7 @@ class MainWindow(QMainWindow):
self.data = Data(self, lastEvent)
else:
self.data = Data(self)
self.data._new = False
self.autodata = Data(self)
if settings.value("user/FullName", None) is None:
@ -166,14 +170,19 @@ class MainWindow(QMainWindow):
settings.setValue("data/dataRoot", dirname)
if settings.value('compclass', None) is None:
settings.setValue('compclass', SetChannelComponents())
if settings.value('output/Format', None) is None:
outformat = QInputDialog.getText(self,
"Enter output format (*.xml, *.cnv, *.obs):",
"Format")
settings.setValue("output/Format", outformat)
settings.sync()
# setup UI
self.setupUi()
self.filteroptions = {}
self.picks = {}
self.autopicks = {}
self.pylot_picks = {}
self.pylot_autopicks = {}
self.loc = False
def setupUi(self):
@ -243,25 +252,42 @@ class MainWindow(QMainWindow):
self.tabs.setCurrentIndex(0)
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
saveIcon = self.style().standardIcon(QStyle.SP_DriveHDIcon)
openIcon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
helpIcon = self.style().standardIcon(QStyle.SP_DialogHelpButton)
newIcon = self.style().standardIcon(QStyle.SP_FileIcon)
newFolderIcon = self.style().standardIcon(QStyle.SP_FileDialogNewFolder)
# create resource icons
locactionicon = QIcon()
locactionicon.addPixmap(QPixmap(':/icons/locactionicon.png'))
manupicksicon = QIcon()
manupicksicon.addPixmap(QPixmap(':/icons/manupicsicon.png'))
autopicksicon = QIcon()
autopicksicon.addPixmap(QPixmap(':/icons/autopicsicon.png'))
newIcon = QIcon()
newIcon.addPixmap(QPixmap(':/icons/newfile.png'))
addIcon = QIcon()
addIcon.addPixmap(QPixmap(':/icons/add.png'))
saveIcon = QIcon()
saveIcon.addPixmap(QPixmap(':/icons/save.png'))
saveasIcon = QIcon()
saveasIcon.addPixmap(QPixmap(':/icons/saveas.png'))
saveProjectIcon = QIcon()
saveProjectIcon.addPixmap(QPixmap(':/icons/saveproject.png'))
saveProjectAsIcon = QIcon()
saveProjectAsIcon.addPixmap(QPixmap(':/icons/saveprojectas.png'))
openIcon = QIcon()
openIcon.addPixmap(QPixmap(':/icons/openfile.png'))
openProjectIcon = QIcon()
openProjectIcon.addPixmap(QPixmap(':/icons/openproject.png'))
openLocIcon = QIcon()
openLocIcon.addPixmap(QPixmap(':/icons/openloc.png'))
openEventIcon = QIcon()
openEventIcon.addPixmap(QPixmap(':/icons/openpick.png'))
openEventsIcon = QIcon()
openEventsIcon.addPixmap(QPixmap(':/icons/openpicks.png'))
saveEventsIcon = QIcon()
saveEventsIcon.addPixmap(QPixmap(':/icons/savepicks.png'))
prefIcon = QIcon()
prefIcon.addPixmap(QPixmap(':/icons/preferences.png'))
paraIcon = QIcon()
paraIcon.addPixmap(QPixmap(':/icons/parameter.png'))
self.autopicksicon_small = QIcon()
self.autopicksicon_small.addPixmap(QPixmap(':/icons/autopicksicon_small.png'))
self.manupicksicon_small = QIcon()
self.manupicksicon_small.addPixmap(QPixmap(':/icons/manupicksicon_small.png'))
saveProjectIcon = QIcon()
saveProjectIcon.addPixmap(QPixmap(':/icons/Library-icon.png'))
loadpiloticon = QIcon()
loadpiloticon.addPixmap(QPixmap(':/icons/Matlab_PILOT_icon.png'))
p_icon = QIcon()
@ -279,7 +305,7 @@ class MainWindow(QMainWindow):
e_icon = QIcon()
e_icon.addPixmap(QPixmap(':/icons/key_E.png'))
autotune_icon = QIcon()
autotune_icon.addPixmap(QPixmap(':/icons/autopick_button.png'))
autotune_icon.addPixmap(QPixmap(':/icons/tune.png'))
autopylot_icon = QIcon()
autopylot_icon.addPixmap(QPixmap(':/icons/autopylot_button'))
locate_icon = QIcon()
@ -293,7 +319,7 @@ class MainWindow(QMainWindow):
self.openProjectAction = self.createAction(self, "&Open project ...",
self.loadProject,
QKeySequence.Open,
openIcon,
openProjectIcon,
"Load project file")
self.saveProjectAction = self.createAction(self, "&Save project ...",
self.saveProject,
@ -304,34 +330,34 @@ class MainWindow(QMainWindow):
self.saveProjectAsAction = self.createAction(self, "Save project as ...",
self.saveProjectAs,
QKeySequence.SaveAs,
saveProjectIcon,
saveProjectAsIcon,
"Save project file as...")
self.saveProjectAsAction.setEnabled(False)
# newEventAction = self.createAction(self, "&New event ...",
# self.createNewEvent,
# QKeySequence.New, newIcon,
# "Create a new event.")
self.openmanualpicksaction = self.createAction(self, "Load &manual picks ...",
self.openmanualpicksaction = self.createAction(self, "Load event ...",
self.load_data,
"Ctrl+M",
manupicksicon,
"Load manual picks for "
openEventIcon,
"Load event information for "
"the displayed event.")
self.openmanualpicksaction.setEnabled(False)
self.openmanualpicksaction.setData(None)
self.openautopicksaction = self.createAction(self, "Load &automatic picks ... ",
self.load_autopicks,
self.openautopicksaction = self.createAction(self, "Load event information &automatically ... ",
self.load_multiple_data,
"Ctrl+A",
autopicksicon,
"Load automatic picks "
"for the displayed event.")
openEventsIcon,
"Load event data automatically "
"for for all events.")
self.openautopicksaction.setEnabled(False)
self.openautopicksaction.setData(None)
self.loadlocationaction = self.createAction(self, "Load &location ...",
self.load_loc, "Ctrl+L",
locactionicon,
openLocIcon,
"Load location information on "
"the displayed event.")
self.loadlocationaction.setEnabled(False)
@ -345,17 +371,17 @@ class MainWindow(QMainWindow):
self.saveManualPicksAction = self.createAction(self, "Save &picks ...",
self.saveData, "Ctrl+P",
saveIcon, "Save event pick data.")
saveEventsIcon, "Save event pick data.")
self.disableSaveManualPicksAction()
self.addEventDataAction = self.createAction(self, "Add &events ...",
self.add_events,
"Ctrl+E", newFolderIcon,
"Ctrl+E", addIcon,
"Add event data")
prefsEventAction = self.createAction(self, "Preferences",
self.PyLoTprefs,
QKeySequence.Preferences,
QIcon(None),
prefIcon,
"Edit PyLoT app preferences.")
quitAction = self.createAction(self, "&Quit",
QCoreApplication.instance().quit,
@ -363,7 +389,7 @@ class MainWindow(QMainWindow):
"Close event and quit PyLoT")
self.parameterAction = self.createAction(self, "Parameter",
self.setParameter,
None, QIcon(None),
None, paraIcon,
"Modify Parameter")
self.filterAction = self.createAction(self, "&Filter ...",
self.filterWaveformData,
@ -373,7 +399,7 @@ class MainWindow(QMainWindow):
desired seismic phase.""", True)
filterEditAction = self.createAction(self, "&Filter parameter ...",
self.adjustFilterOptions,
"Alt+F", QIcon(None),
"Alt+F", filter_icon,
"""Adjust filter parameters.""")
self.selectPAction = self.createAction(self, "&P", self.alterPhase,
"Alt+P",
@ -422,11 +448,15 @@ class MainWindow(QMainWindow):
fileToolBar = self.addToolBar("FileTools")
fileToolActions = (self.newProjectAction, self.addEventDataAction,
self.openProjectAction, self.saveProjectAction,
self.saveProjectAsAction, self.openmanualpicksaction,
self.openautopicksaction, self.loadlocationaction,
self.loadpilotevent, self.saveManualPicksAction)
self.saveProjectAsAction)
fileToolBar.setObjectName("FileTools")
self.addActions(fileToolBar, fileToolActions)
eventToolActions = (self.openmanualpicksaction, self.openautopicksaction,
self.saveManualPicksAction, self.loadlocationaction,
self.loadpilotevent)
eventToolBar = self.addToolBar("EventTools")
eventToolBar.setObjectName("EventTools")
self.addActions(eventToolBar, eventToolActions)
# phaseToolBar = self.addToolBar("PhaseTools")
# phaseToolActions = (self.selectPAction, self.selectSAction)
@ -637,23 +667,66 @@ class MainWindow(QMainWindow):
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
self.load_data(fname_dict, type=type)
def load_data(self, fname=None, type='manual', loc=False):
def load_multiple_data(self, type='manual'):
if not self.okToContinue():
return
refresh=False
events = self.project.eventlist
fext = '.xml'
for event in events:
path = event.path
eventname = path.split('/')[-1]
filename = os.path.join(path, 'PyLoT_'+eventname+fext)
if os.path.isfile(filename):
self.load_data(filename, draw=False, event=event, overwrite=True)
refresh=True
if not refresh:
return
if self.get_current_event().pylot_picks:
self.refreshEvents()
self.setDirty(True)
def load_data(self, fname=None, type='manual', loc=False, draw=True, event=None, overwrite=False):
if not overwrite:
if not self.okToContinue():
return
if fname is None:
action = self.sender()
if isinstance(action, QAction):
fname = self.filename_from_action(action)
if not fname:
return
self.set_fname(fname, type)
data = dict(auto=self.autodata, manual=self.data)
data[type] += Data(self, evtdata=fname)
#data = dict(auto=self.autodata, manual=self.data)
if not event:
event = self.get_current_event()
data = Data(self, event)
try:
data_new = Data(self, evtdata=fname)
data += data_new
except ValueError:
qmb = QMessageBox(self, icon=QMessageBox.Question,
text='Warning: Missmatch in event identifiers {} and {}. Continue?'.format(
data_new.get_evt_data().resource_id,
data.get_evt_data().resource_id),
windowTitle='PyLoT - Load data warning')
qmb.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
qmb.setDefaultButton(QMessageBox.No)
ret = qmb.exec_()
if ret == qmb.Yes:
data_new.setNew()
data += data_new
else:
return
self.data = data
print('Loading {} picks from file {}.'.format(type, fname))
if not loc:
self.updatePicks(type=type)
if self.get_current_event().picks:
self.plotWaveformDataThread()
self.drawPicks(picktype=type)
self.draw()
self.setDirty(True)
self.updatePicks(type=type, event=event)
if draw:
if self.get_current_event().pylot_picks:
self.refreshEvents()
self.setDirty(True)
def add_recentfile(self, event):
self.recentfiles.insert(0, event)
@ -676,8 +749,8 @@ class MainWindow(QMainWindow):
def getWFFnames(self):
try:
evt = self.get_data().get_evt_data()
if evt.picks:
for pick in evt.picks:
if evt.pylot_picks:
for pick in evt.pylot_picks:
try:
if pick.waveform_id is not None:
fname = pick.waveform_id.getSEEDstring()
@ -728,8 +801,8 @@ class MainWindow(QMainWindow):
'''
if not eventbox:
eventbox = self.eventBox
index = eventbox.currentIndex()
return eventbox.itemData(index)
path = eventbox.currentText()
return self.project.getEventFromPath(path)
def get_current_event_path(self, eventbox=None):
'''
@ -778,7 +851,7 @@ class MainWindow(QMainWindow):
dirs = {
'database': path.split('/')[-2],
'datapath': path.split('/')[-3],
'rootpath': os.path.join(*path.split('/')[:-3])
'rootpath': '/'+os.path.join(*path.split('/')[:-3])
}
except Exception as e:
dirs = {
@ -788,6 +861,10 @@ class MainWindow(QMainWindow):
}
print('Warning: Could not automatically init folder structure. ({})'.format(e))
settings = QSettings()
settings.setValue("data/dataRoot", dirs['rootpath'])
settings.sync()
if not self.project.eventlist:
#init parameter object
self.setParameter(show=False)
@ -880,10 +957,10 @@ class MainWindow(QMainWindow):
event_path = event.path
event_npicks = 0
event_nautopicks = 0
if event.picks:
event_npicks = len(event.picks)
if event.autopicks:
event_nautopicks = len(event.autopicks)
if event.pylot_picks:
event_npicks = len(event.pylot_picks)
if event.pylot_autopicks:
event_nautopicks = len(event.pylot_autopicks)
event_ref = event.isRefEvent()
event_test = event.isTestEvent()
@ -929,7 +1006,8 @@ class MainWindow(QMainWindow):
'{} unequal {}.'
.format(event.path, self.eventBox.itemText(id)))
raise ValueError(message)
eventBox.setItemData(id, event)
#not working with obspy events
#eventBox.setItemData(id, event)
eventBox.setCurrentIndex(index)
self.refreshRefTestButtons()
@ -940,7 +1018,7 @@ class MainWindow(QMainWindow):
caption = "Open an event file"
fname = QFileDialog().getOpenFileName(self, caption=caption,
filter=filt,
dir=self.getRoot())
dir=self.get_current_event_path())
fname = fname[0]
else:
fname = str(action.data().toString())
@ -959,27 +1037,42 @@ class MainWindow(QMainWindow):
self.set_fname(self.get_data().getEventFileName(), type)
return self.get_fnames(type)
def saveData(self):
def saveData(self, directory=None, outformat=None):
def getSavePath(e):
def getSavePath(e, directory, outformat):
print('warning: {0}'.format(e))
directory = self.get_current_event_path()
if not directory:
dlgflag = 1
directory = self.get_current_event_path()
else:
dlgflag = 0
eventname = self.get_current_event_name()
filename = 'picks_'+eventname
filename = 'PyLoT_'+eventname
outpath = os.path.join(directory, filename)
file_filter = "QuakeML file (*.xml);;VELEST observation file " \
"format (*.cnv);;NonLinLoc observation file (*.obs)"
title = 'Save pick data ...'
fname, selected_filter = QFileDialog.getSaveFileName(self,
title,
outpath,
file_filter)
if not outformat:
outformat = settings.value('output/Format')
outformat = outformat[0:4]
else:
selected_filter = "NonLinLoc observation file (*.obs)"
fname = outpath
if outformat == '.obs':
file_filter = "NonLinLoc observation file (*.obs)"
elif outformat == '.cnv':
file_filter = "VELEST observation file format (*.cnv)"
elif outformat == '.xml':
file_filter = "QuakeML file (*.xml)"
if dlgflag == 1:
fname, selected_filter = QFileDialog.getSaveFileName(self,
title,
outpath,
file_filter)
fbasename, exform = os.path.splitext(fname)
if not exform and selected_filter or not exform in OUTPUTFORMATS:
exform = selected_filter.split('*')[1][:-1]
if not exform in OUTPUTFORMATS:
return fname, exform
return fbasename, exform
@ -987,7 +1080,7 @@ class MainWindow(QMainWindow):
fbasename = self.getEventFileName()
exform = settings.value('data/exportFormat', 'QUAKEML')
try:
self.get_data().applyEVTData(self.getPicks())
self.get_data().applyEVTData(self.get_current_event(), typ='event')#getPicks())
except OverwriteError:
# msgBox = QMessageBox()
# msgBox.setText("Picks have been modified!")
@ -1006,9 +1099,9 @@ class MainWindow(QMainWindow):
try:
self.get_data().exportEvent(fbasename, exform)
except FormatError as e:
fbasename, exform = getSavePath(e)
fbasename, exform = getSavePath(e, directory, outformat)
except AttributeError as e:
fbasename, exform = getSavePath(e)
fbasename, exform = getSavePath(e, directory, outformat)
# catch all possible cases before going on
if not fbasename:
@ -1057,7 +1150,7 @@ class MainWindow(QMainWindow):
return self.get_current_event().getPicks()
if type == 'auto':
return self.get_current_event().getAutopicks()
# rdict = dict(auto=self.autopicks, manual=self.picks)
# rdict = dict(auto=self.pylot_autopicks, manual=self.pylot_picks)
# return rdict[type]
def getPicksOnStation(self, station, type='manual'):
@ -1131,7 +1224,7 @@ class MainWindow(QMainWindow):
if event:
self.ref_event_button.setChecked(event.isRefEvent())
self.test_event_button.setChecked(event.isTestEvent())
self.enableRefTestButtons(bool(self.get_current_event().picks))
self.enableRefTestButtons(bool(self.get_current_event().pylot_picks))
return
self.ref_event_button.setChecked(False)
self.test_event_button.setChecked(False)
@ -1190,14 +1283,14 @@ class MainWindow(QMainWindow):
if not event:
return
# update picks saved in GUI mainwindow (to be changed in future!!) MP MP
if not event.picks:
self.picks = {}
if not event.pylot_picks:
self.pylot_picks = {}
else:
self.picks = event.picks
if not event.autopicks:
self.autopicks = {}
self.pylot_picks = event.pylot_picks
if not event.pylot_autopicks:
self.pylot_autopicks = {}
else:
self.autopicks = event.autopicks
self.pylot_autopicks = event.pylot_autopicks
# if current tab is waveformPlot-tab and the data in this tab was not yet refreshed
if self.tabs.currentIndex() == 0:
if self._eventChanged[0]:
@ -1343,12 +1436,13 @@ class MainWindow(QMainWindow):
self.openautopicksaction.setEnabled(True)
self.loadpilotevent.setEnabled(True)
event = self.get_current_event()
if event.picks:
self.picks = event.picks
if event.pylot_picks:
self.pylot_picks = event.pylot_picks
self.drawPicks(picktype='manual')
self.enableSaveManualPicksAction()
if event.autopicks:
self.autopicks = event.autopicks
self.locateEvent.setEnabled(True)
if event.pylot_autopicks:
self.pylot_autopicks = event.pylot_autopicks
self.drawPicks(picktype='auto')
self.compare_action.setEnabled(True)
self.draw()
@ -1506,6 +1600,11 @@ class MainWindow(QMainWindow):
if wfID in plot_dict.keys():
return plot_dict[wfID][0]
def getNetworkName(self, wfID):
plot_dict = self.getPlotWidget().getPlotDict()
if wfID in plot_dict.keys():
return plot_dict[wfID][2]
def alterPhase(self):
pass
@ -1570,13 +1669,14 @@ class MainWindow(QMainWindow):
def pickDialog(self, wfID, nextStation=False):
station = self.getStationName(wfID)
network = self.getNetworkName(wfID)
if not station:
return
self.update_status('picking on station {0}'.format(station))
data = self.get_data().getWFData()
pickDlg = PickDlg(self, parameter=self._inputs,
data=data.select(station=station),
station=station,
station=station, network=network,
picks=self.getPicksOnStation(station, 'manual'),
autopicks=self.getPicksOnStation(station, 'auto'))
pickDlg.nextStation.setChecked(nextStation)
@ -1725,14 +1825,16 @@ class MainWindow(QMainWindow):
# raise Exception('FATAL: Should never occur!')
# MP MP prompt redundant because new picks have to be accepted in the first place closing PickDlg
def updatePicks(self, type='manual'):
def updatePicks(self, type='manual', event=None):
if not event:
event = self.get_current_event()
picks = picksdict_from_picks(evt=self.get_data(type).get_evt_data())
if type == 'manual':
self.get_current_event().addPicks(picks)
self.picks.update(picks)
event.addPicks(picks)
self.pylot_picks.update(picks)
elif type == 'auto':
self.get_current_event().addAutopicks(picks)
self.autopicks.update(picks)
event.addAutopicks(picks)
self.pylot_autopicks.update(picks)
self.check4Comparison()
def drawPicks(self, station=None, picktype='manual'):
@ -1769,7 +1871,7 @@ class MainWindow(QMainWindow):
for phase in stat_picks:
picks = stat_picks[phase]
if type(stat_picks[phase]) is not dict:
if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict:
return
colors = phase_col[phase[0].upper()]
@ -1871,11 +1973,14 @@ class MainWindow(QMainWindow):
outfile = settings.value("{0}/outputFile".format(loctool),
os.path.split(os.tempnam())[-1])
phasefile = os.path.split(os.tempnam())[-1]
obsdir = os.path.join(locroot, 'obs')
self.saveData(directory=obsdir, outformat='.obs')
eventname = self.get_current_event_name()
filename = 'PyLoT_'+eventname
locpath = os.path.join(locroot, 'loc', filename)
phasefile = os.path.join(obsdir, filename + '.obs')
phasepath = os.path.join(locroot, 'obs', phasefile)
locpath = os.path.join(locroot, 'loc', outfile)
lt.export(self.getPicks(), phasepath)
lt.modify_inputs(infile, locroot, outfile, phasefile, ttt)
lt.modify_inputs(infile, locroot, filename, phasefile, ttt)
try:
lt.locate(infile)
except RuntimeError as e:
@ -1883,8 +1988,8 @@ class MainWindow(QMainWindow):
finally:
os.remove(phasepath)
self.get_data().applyEVTData(lt.read_location(locpath), type='event')
self.get_data().applyEVTData(self.calc_magnitude(), type='event')
self.get_data().applyEVTData(lt.read_location(locpath), typ='event')
#self.get_data().applyEVTData(self.calc_magnitude(), typ='event')
def init_array_tab(self):
'''
@ -1969,6 +2074,12 @@ class MainWindow(QMainWindow):
if not self.array_map:
return
# refresh with new picks here!!!
event = self.get_current_event()
if hasattr(event, 'origins'):
if event.origins:
lat = event.origins[0].latitude
lon = event.origins[0].longitude
self.array_map.eventLoc = (lat, lon)
self.array_map.refresh_drawings(self.get_current_event().getPicks())
self._eventChanged[1] = False
@ -1995,19 +2106,19 @@ class MainWindow(QMainWindow):
# changes attributes of the corresponding event
table = self.project._table
event = self.project.getEventFromPath(table[row][0].text())
if column == 3 or column == 4:
if column == 8 or column == 9:
#toggle checked states (exclusive)
item_ref = table[row][3]
item_test = table[row][4]
if column == 3 and item_ref.checkState():
item_ref = table[row][8]
item_test = table[row][9]
if column == 8 and item_ref.checkState():
item_test.setCheckState(QtCore.Qt.Unchecked)
event.setRefEvent(True)
elif column == 3 and not item_ref.checkState():
elif column == 8 and not item_ref.checkState():
event.setRefEvent(False)
elif column == 4 and item_test.checkState():
elif column == 9 and item_test.checkState():
item_ref.setCheckState(QtCore.Qt.Unchecked)
event.setTestEvent(True)
elif column == 4 and not item_test.checkState():
elif column == 9 and not item_test.checkState():
event.setTestEvent(False)
self.fill_eventbox()
elif column == 5:
@ -2023,22 +2134,35 @@ class MainWindow(QMainWindow):
# init new qtable
self.event_table = QtGui.QTableWidget()
self.event_table.setColumnCount(6)
self.event_table.setColumnCount(11)
self.event_table.setRowCount(len(eventlist))
self.event_table.setHorizontalHeaderLabels(['Event', '[N] MP',
'[N] AP', 'Tuning Set',
'Test Set', 'Notes'])
self.event_table.setHorizontalHeaderLabels(['Event',
'Time',
'Lat',
'Lon',
'Depth',
'Mag',
'[N] MP',
'[N] AP',
'Tuning Set',
'Test Set',
'Notes'])
# iterate through eventlist and generate items for table rows
self.project._table = []
for index, event in enumerate(eventlist):
event_npicks = 0
event_nautopicks = 0
if event.picks:
event_npicks = len(event.picks)
if event.autopicks:
event_nautopicks = len(event.autopicks)
if event.pylot_picks:
event_npicks = len(event.pylot_picks)
if event.pylot_autopicks:
event_nautopicks = len(event.pylot_autopicks)
item_path = QtGui.QTableWidgetItem()
item_time = QtGui.QTableWidgetItem()
item_lat = QtGui.QTableWidgetItem()
item_lon = QtGui.QTableWidgetItem()
item_depth = QtGui.QTableWidgetItem()
item_mag = QtGui.QTableWidgetItem()
item_nmp = QtGui.QTableWidgetItem(str(event_npicks))
item_nmp.setIcon(self.manupicksicon_small)
item_nap = QtGui.QTableWidgetItem(str(event_nautopicks))
@ -2050,11 +2174,23 @@ class MainWindow(QMainWindow):
item_ref.setBackground(self._colors['ref'])
item_test.setBackground(self._colors['test'])
item_path.setText(event.path)
item_notes.setText(event.notes)
if hasattr(event, 'origins'):
if event.origins:
origin = event.origins[0]
item_time.setText(str(origin.time).split('.')[0])
item_lon.setText(str(origin.longitude))
item_lat.setText(str(origin.latitude))
item_depth.setText(str(origin.depth))
if hasattr(event, 'magnitudes'):
if event.magnitudes:
magnitude = event.magnitudes[0]
item_mag.setText(str(magnitude.mag))
item_notes.setText(event.notes)
set_enabled(item_path, True, False)
set_enabled(item_nmp, True, False)
set_enabled(item_nap, True, False)
if event.picks:
if event.pylot_picks:
set_enabled(item_ref, True, True)
set_enabled(item_test, True, True)
else:
@ -2070,7 +2206,8 @@ class MainWindow(QMainWindow):
else:
item_test.setCheckState(QtCore.Qt.Unchecked)
column=[item_path, item_nmp, item_nap, item_ref, item_test, item_notes]
column=[item_path, item_time, item_lat, item_lon, item_depth, item_mag,
item_nmp, item_nap, item_ref, item_test, item_notes]
self.project._table.append(column)
for r_index, row in enumerate(self.project._table):
@ -2389,6 +2526,63 @@ class Project(object):
self.setDirty()
else:
print('Skipping event with path {}. Already part of project.'.format(event.path))
self.search_eventfile_info()
def read_eventfile_info(self, filename, separator=','):
'''
Try to read event information from file (:param:filename) comparing specific event datetimes.
File structure (each row): event, date, time, magnitude, latitude, longitude, depth
separated by :param:separator each.
'''
infile = open(filename, 'r')
for line in infile.readlines():
event, date, time, mag, lat, lon, depth = line.split(separator)[:7]
#skip first line
try:
month, day, year = date.split('/')
except:
continue
year = int(year)
#hardcoded, if year only consists of 2 digits (e.g. 16 instead of 2016)
if year<100:
year += 2000
datetime = '{}-{}-{}T{}'.format(year, month, day, time)
try:
datetime = UTCDateTime(datetime)
except Exception as e:
print(e, datetime, filename)
continue
for event in self.eventlist:
if not event.origins:
continue
origin = event.origins[0] #should have only one origin
if origin.time == datetime:
origin.latitude = float(lat)
origin.longitude = float(lon)
origin.depth = float(depth)
event.magnitudes.append(Magnitude(resource_id=event.resource_id,
mag=float(mag),
mag_type='M'))
def search_eventfile_info(self):
'''
Search all datapaths in rootpath for filenames with given file extension fext
and try to read event info from it
'''
datapaths = []
fext='.csv'
for event in self.eventlist:
if not event.datapath in datapaths:
datapaths.append(event.datapath)
for datapath in datapaths:
datapath = os.path.join(self.rootpath, datapath)
for filename in os.listdir(datapath):
filename = os.path.join(datapath, filename)
if os.path.isfile(filename) and filename.endswith(fext):
try:
self.read_eventfile_info(filename)
except Exception as e:
print('Failed on reading eventfile info from file {}: {}'.format(filename, e))
def getPaths(self):
'''
@ -2449,123 +2643,6 @@ class Project(object):
return project
class Event(object):
'''
Pickable class containing information on a single event.
'''
def __init__(self, path):
self.path = path
self.database = path.split('/')[-2]
self.datapath = path.split('/')[-3]
self.rootpath = os.path.join(*path.split('/')[:-3])
self.autopicks = {}
self.picks = {}
self.notes = ''
self._testEvent = False
self._refEvent = False
try:
self.get_notes()
except:
pass
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:
text = '[eventInfo: '+str(infile.readlines()[0].split('\n')[0])+']'
self.addNotes(text)
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):
for station in picks:
self.picks[station] = picks[station]
def addAutopicks(self, autopicks):
for station in autopicks:
self.autopicks[station] = autopicks[station]
def setPick(self, station, pick):
if pick:
self.picks[station] = pick
def setPicks(self, picks):
self.picks = picks
def getPick(self, station):
if station in self.picks.keys():
return self.picks[station]
def getPicks(self):
return self.picks
def setAutopick(self, station, autopick):
if autopick:
self.autopicks[station] = autopick
def setAutopicks(self, autopicks):
self.autopicks = autopicks
def getAutopick(self, station):
if station in self.autopicks.keys():
return self.autopicks[station]
def getAutopicks(self):
return self.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
class getExistingDirectories(QFileDialog):
'''
File dialog with possibility to select multiple folders.

View File

@ -98,8 +98,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
exf = ['root', 'dpath', 'dbase']
if parameter.hasParam('eventID') and fnames == 'None':
dsfields['eventID'] = parameter.get('eventID')
if parameter['eventID'] is not '*' and fnames == 'None':
dsfields['eventID'] = parameter['eventID']
exf.append('eventID')
datastructure.modifyFields(**dsfields)
@ -133,13 +133,13 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
if not input_dict:
# started in production mode
datapath = datastructure.expandDataPath()
if fnames == 'None' and not parameter['eventID']:
if fnames == 'None' and parameter['eventID'] is '*':
# multiple event processing
# read each event in database
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
elif fnames == 'None' and parameter['eventID']:
elif fnames == 'None' and parameter['eventID'] is not '*':
# single event processing
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
events = glob.glob(os.path.join(datapath, parameter['eventID']))
else:
# autoPyLoT was initialized from GUI
events = []
@ -243,7 +243,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# get latest NLLoc-location file if several are available
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
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'),
parameter.get('Qp'),
parameter.get('rho'), True, \
@ -252,15 +252,29 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props)
evt = moment_mag.updated_event()
net_mw = moment_mag.net_magnitude()
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'), parameter.get('WAscaling'), \
True, iplot)
parameter.get('sstop'),
WAscaling, True, iplot)
for station, amplitude in local_mag.amplitudes.items():
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:
print("autoPyLoT: No NLLoc-location file available!")
print("No source parameter estimation possible!")
locflag = 9
else:
# get theoretical P-onset times from NLLoc-location file
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
@ -301,7 +315,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
nlloccounter = maxnumit
evt = read_events(nllocfile)[0]
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'),
parameter.get('Qp'),
parameter.get('rho'), True, \
@ -310,14 +324,25 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props)
evt = moment_mag.updated_event()
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'), parameter.get('WAscaling'), \
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()
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:
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
locflag = 9
@ -328,26 +353,26 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
data.applyEVTData(picks)
if evt is not None:
data.applyEVTData(evt, 'event')
fnqml = '%s/autoPyLoT' % event
data.exportEvent(fnqml)
# HYPO71
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event
hypo71.export(picks, hypo71file, parameter)
# HYPOSAT
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event
hyposat.export(picks, hyposatfile, parameter)
fnqml = '%s/PyLoT_%s' % (event, evID)
data.exportEvent(fnqml, fnext='.xml', fcheck='manual')
if locflag == 1:
# HYPO71
hypo71file = '%s/PyLoT_%s_HYPO71_phases' % (event, evID)
hypo71.export(picks, hypo71file, parameter)
# HYPOSAT
hyposatfile = '%s/PyLoT_%s_HYPOSAT_phases' % (event, evID)
hyposat.export(picks, hyposatfile, parameter)
# VELEST
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event
velestfile = '%s/PyLoT_%s_VELEST_phases.cnv' % (event, evID)
velest.export(picks, velestfile, parameter, evt)
# hypoDD
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event
hypoddfile = '%s/PyLoT_%s_hypoDD_phases.pha' % (event, evID)
hypodd.export(picks, hypoddfile, parameter, evt)
# FOCMEC
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event
focmecfile = '%s/PyLoT_%s_FOCMEC.in' % (event, evID)
focmec.export(picks, focmecfile, parameter, evt)
# HASH
hashfile = '%s/autoPyLoT_HASH' % event
hashfile = '%s/PyLoT_%s_HASH' % (event, evID)
hash.export(picks, hashfile, parameter, evt)
endsplash = '''------------------------------------------\n'

View File

@ -1,15 +1,29 @@
<RCC>
<qresource>
<file>icons/Library-icon.png</file>
<file>icons/pylot.ico</file>
<file>icons/pylot.png</file>
<file>icons/manupicsicon.png</file>
<file>icons/autopicsicon.png</file>
<file>icons/autopylot_button.png</file>
<file>icons/newfile.png</file>
<file>icons/open.png</file>
<file>icons/openproject.png</file>
<file>icons/add.png</file>
<file>icons/save.png</file>
<file>icons/saveas.png</file>
<file>icons/saveproject.png</file>
<file>icons/saveprojectas.png</file>
<file>icons/manupicksicon_small.png</file>
<file>icons/autopicksicon_small.png</file>
<file>icons/autopick_button.png</file>
<file>icons/locactionicon.png</file>
<file>icons/tune.png</file>
<file>icons/autopylot_button.png</file>
<file>icons/pick.png</file>
<file>icons/waveform.png</file>
<file>icons/openpick.png</file>
<file>icons/openpicks.png</file>
<file>icons/openpick.png</file>
<file>icons/openpicks.png</file>
<file>icons/savepicks.png</file>
<file>icons/preferences.png</file>
<file>icons/parameter.png</file>
<file>icons/openloc.png</file>
<file>icons/compare_button.png</file>
<file>icons/locate_button.png</file>
<file>icons/Matlab_PILOT_icon.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 50 KiB

BIN
icons/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
icons/autopylot_button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
icons/newfile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
icons/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
icons/openfile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
icons/openloc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
icons/openpick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
icons/openpicks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
icons/openproject.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
icons/parameter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
icons/pick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
icons/preferences.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
icons/save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
icons/saveas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
icons/savepicks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/saveproject.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
icons/saveprojectas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
icons/tune.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
icons/waveform.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

169077
icons_rc.py

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
97ee-dirty

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
"""
Created autumn/winter 2015.
Revised/extended summer 2017.
:author: Ludger Küperkoch / MAGS2 EP3 working group
"""
@ -115,23 +116,30 @@ class Magnitude(object):
def calc(self):
pass
def updated_event(self):
self.event.magnitudes.append(self.net_magnitude())
def updated_event(self, magscaling=None):
self.event.magnitudes.append(self.net_magnitude(magscaling))
return self.event
def net_magnitude(self):
def net_magnitude(self, magscaling=None):
if self:
# TODO if an average Magnitude instead of the median is calculated
# StationMagnitudeContributions should be added to the returned
# Magnitude object
# mag_error => weights (magnitude error estimate from peak_to_peak, calcsourcespec?)
# weights => StationMagnitdeContribution
mag = ope.Magnitude(
mag=np.median([M.mag for M in self.magnitudes.values()]),
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)
if magscaling is not None and str(magscaling) is not '[0.0, 0.0]':
# scaling necessary
print("Scaling network magnitude ...")
mag = ope.Magnitude(
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=np.median([M.mag for M in self.magnitudes.values()]),
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)
return mag
return None
@ -153,7 +161,7 @@ class LocalMagnitude(Magnitude):
_amplitudes = dict()
def __init__(self, stream, event, calc_win, wascaling=None, verbosity=False, iplot=0):
def __init__(self, stream, event, calc_win, wascaling, verbosity=False, iplot=0):
super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
self._calc_win = calc_win
@ -207,6 +215,8 @@ class LocalMagnitude(Magnitude):
th = np.arange(0, len(sqH) * dt, dt)
# get maximum peak within pick window
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])
if self.verbose:
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
@ -257,12 +267,13 @@ class LocalMagnitude(Magnitude):
self.amplitudes = (station, amplitude)
# using standard Gutenberg-Richter relation
# or scale WA amplitude with given scaling relation
if self.wascaling == None:
if str(self.wascaling) == '[0.0, 0.0, 0.0]':
print("Calculating original Richter magnitude ...")
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])

View File

@ -6,11 +6,12 @@ import os
from obspy import read_events
from obspy.core import read, Stream, UTCDateTime
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, \
picksdict_from_pilot, merge_picks
from pylot.core.util.errors import FormatError, OverwriteError
from pylot.core.util.utils import fnConstructor, full_range
from pylot.core.util.event import Event
class Data(object):
"""
@ -33,7 +34,7 @@ class Data(object):
self.comp = 'Z'
self.wfdata = Stream()
self._new = False
if isinstance(evtdata, Event):
if isinstance(evtdata, ObsPyEvent) or isinstance(evtdata, Event):
pass
elif isinstance(evtdata, dict):
evt = readPILOTEvent(**evtdata)
@ -49,7 +50,7 @@ class Data(object):
if 'Unknown format for file' in e.message:
if 'PHASES' in evtdata:
picks = picksdict_from_pilot(evtdata)
evtdata = Event()
evtdata = ObsPyEvent()
evtdata.picks = picks_from_picksdict(picks)
elif 'LOC' in evtdata:
raise NotImplementedError('PILOT location information '
@ -61,7 +62,7 @@ class Data(object):
raise e
else: # create an empty Event object
self.setNew()
evtdata = Event()
evtdata = ObsPyEvent()
evtdata.picks = []
self.evtdata = evtdata
self.wforiginal = None
@ -73,6 +74,8 @@ class Data(object):
def __add__(self, other):
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():
picks_to_add = other.get_evt_data().picks
old_picks = self.get_evt_data().picks
@ -84,7 +87,7 @@ class Data(object):
self.evtdata = new.get_evt_data()
elif self.isNew() and other.isNew():
pass
elif self.get_evt_data().get('id') == other.get_evt_data().get('id'):
elif rs_id == rs_id_other:
other.setNew()
return self + other
else:
@ -95,7 +98,7 @@ class Data(object):
def getPicksStr(self):
picks_str = ''
for pick in self.get_evt_data().picks:
picks_str += str(pick) + '\n'
picks_str += str(PyLoT) + '\n'
return picks_str
def getParent(self):
@ -144,12 +147,13 @@ class Data(object):
# handle forbidden filenames especially on windows systems
return fnConstructor(str(ID))
def exportEvent(self, fnout, fnext='.xml'):
def exportEvent(self, fnout, fnext='.xml', fcheck='auto'):
"""
:param fnout:
:param fnext:
:param fcheck:
:raise KeyError:
"""
from pylot.core.util.defaults import OUTPUTFORMATS
@ -160,13 +164,71 @@ class Data(object):
errmsg = '{0}; selected file extension {1} not ' \
'supported'.format(e, fnext)
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:
self.get_evt_data().write(fnout + fnext, format=evtformat)
except KeyError as e:
raise KeyError('''{0} export format
not implemented: {1}'''.format(evtformat, e))
else:
# check for stations picked automatically as well as manually
# Prefer manual picks!
evtdata_copy = self.get_evt_data().copy()
evtdata_org = self.get_evt_data()
for i in range(len(evtdata_org.picks)):
if evtdata_org.picks[i].method_id == 'manual':
mstation = evtdata_org.picks[i].waveform_id.station_code
mstation_ext = mstation + '_'
for k in range(len(evtdata_copy.picks)):
if evtdata_copy.picks[k].waveform_id.station_code == mstation or \
evtdata_copy.picks[k].waveform_id.station_code == mstation_ext and \
evtdata_copy.picks[k].method_id == 'auto':
del evtdata_copy.picks[k]
break
lendiff = len(evtdata_org.picks) - len(evtdata_copy.picks)
if lendiff is not 0:
print("Manual as well as automatic picks available. Prefered the {} manual ones!".format(lendiff))
if fnext == '.obs':
try:
evtdata_copy.write(fnout + fnext, format=evtformat)
# write header afterwards
evid = str(evtdata_org.resource_id).split('/')[1]
header = '# EQEVENT: Label: EQ%s Loc: X 0.00 Y 0.00 Z 10.00 OT 0.00 \n' % evid
nllocfile = open(fnout + fnext)
l = nllocfile.readlines()
nllocfile.close()
l.insert(0, header)
nllocfile = open(fnout + fnext, 'w')
nllocfile.write("".join(l))
nllocfile.close()
except KeyError as e:
raise KeyError('''{0} export format
not implemented: {1}'''.format(evtformat, e))
if fnext == '.cnv':
try:
evtdata_org.write(fnout + fnext, format=evtformat)
except KeyError as e:
raise KeyError('''{0} export format
not implemented: {1}'''.format(evtformat, e))
def getComp(self):
"""
@ -279,12 +341,12 @@ class Data(object):
def setEvtData(self, 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 type:
:param typ:
:param authority_id:
:raise OverwriteError:
"""
@ -326,19 +388,27 @@ class Data(object):
information on the event to the actual data
:param event:
"""
if not self.isNew():
if self.isNew():
self.setEvtData(event)
else:
# 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)
# apply event information from location
self.get_evt_data().update(event)
event_old.update(event)
applydata = {'pick': applyPicks,
'event': applyEvent}
applydata[type](data)
applydata[typ](data)
self._new = False
class GenericDataStructure(object):

View File

@ -14,7 +14,7 @@ defaults = {'rootpath': {'type': str,
'value': ''},
'eventID': {'type': str,
'tooltip': 'event ID for single event processing',
'tooltip': 'event ID for single event processing (* for all events found in database)',
'value': ''},
'extent': {'type': str,
@ -278,12 +278,14 @@ defaults = {'rootpath': {'type': str,
'value': 1.0},
'WAscaling': {'type': (float, float, float),
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm]',
'value': (1.0, 1.0, 1.0)},
'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]',
'value': (1.0, 1.0)},
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \
If zeros are set, no scaling of network magnitude is applied!',
'value': (0., 0.)}
'minfreq': {'type': float,
'tooltip': 'Lower filter frequency',

View File

@ -222,26 +222,25 @@ class PylotParameter(object):
# for key, value in self.iteritems():
# lines.append('{key}\t{value}\n'.format(key=key, value=value))
# fid_out.writelines(lines)
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+
'%All main and special settings regarding data handling\n'+
'%and picking are to be set here!\n'+
'%Parameters are optimized for local data sets!\n')
seperator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
'%Parameters are optimized for %{} data sets!\n'.format(self.get_main_para_names()['pick'][0]))
separator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
fid_out.write(header)
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'],
'NLLoc settings', seperator)
'NLLoc settings', separator)
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', seperator)
'settings local magnitude', separator)
self.write_section(fid_out, self.get_main_para_names()['filter'],
'filter settings', seperator)
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'+
'%!!Edit the following only if you know what you are doing!!%\n'))
self.write_section(fid_out, self.get_special_para_names()['z'],
@ -253,9 +252,9 @@ class PylotParameter(object):
self.write_section(fid_out, self.get_special_para_names()['quality'],
'quality assessment', None)
def write_section(self, fid, names, title, seperator):
if seperator:
fid.write(seperator)
def write_section(self, fid, names, title, separator):
if separator:
fid.write(separator)
fid.write('#{}#\n'.format(title))
l_val = 50
l_name = 15

View File

@ -7,6 +7,7 @@ import os
import scipy.io as sio
import warnings
from obspy.core import UTCDateTime
from obspy.core.util import AttribDict
from pylot.core.io.inputs import PylotParameter
from pylot.core.io.location import create_arrival, create_event, \
@ -195,6 +196,7 @@ def picksdict_from_picks(evt):
phase = {}
station = pick.waveform_id.station_code
channel = pick.waveform_id.channel_code
network = pick.waveform_id.network_code
try:
onsets = picks[station]
except KeyError as e:
@ -215,6 +217,7 @@ def picksdict_from_picks(evt):
phase['lpp'] = lpp
phase['spe'] = spe
phase['channel'] = channel
phase['network'] = network
try:
picker = str(pick.method_id)
if picker.startswith('smi:local/'):
@ -231,7 +234,7 @@ def picks_from_picksdict(picks, creation_info=None):
picks_list = list()
for station, onsets in picks.items():
for label, phase in onsets.items():
if not isinstance(phase, dict):
if not isinstance(phase, dict) and not isinstance(phase, AttribDict):
continue
onset = phase['mpp']
try:
@ -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)
# write phase information to file
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:
out_dir = os.path.join(out_dir, db_dir)
if not os.path.isdir(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 + 'cnv', format='VELEST')
@ -835,9 +838,10 @@ def merge_picks(event, picks):
err = pick.time_errors
phase = pick.phase_hint
station = pick.waveform_id.station_code
network = pick.waveform_id.network_code
method = pick.method_id
for p in event.picks:
if p.waveform_id.station_code == station and p.phase_hint == phase:
p.time, p.time_errors, p.method_id = time, err, method
del time, err, phase, station, method
p.time, p.time_errors, p.waveform_id.network_code, p.method_id = time, err, network, method
del time, err, phase, station, network, method
return event

View File

@ -212,6 +212,14 @@ class AICPicker(AutoPicker):
self.Data[0].data = self.Data[0].data * 1000000
# get signal window
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
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
max(abs(aic[inoise] - np.mean(aic[inoise])))

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.picks = None
self.picks_dict = None
self.eventLoc = None
self.figure = figure
self.init_graphics()
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,
zorder=10, picker=True, edgecolor='m', label='Not Picked')
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):
lon = self.lon_no_nan
@ -274,8 +279,7 @@ class map_projection(QtGui.QWidget):
def refresh_drawings(self, picks=None):
self.picks_dict = picks
self.remove_drawings()
self.draw_everything()
self._refresh_drawings()
def _refresh_drawings(self):
self.remove_drawings()
@ -303,6 +307,9 @@ class map_projection(QtGui.QWidget):
if hasattr(self, 'sc_picked'):
self.sc_picked.remove()
del(self.sc_picked)
if hasattr(self, 'sc_event'):
self.sc_event.remove()
del(self.sc_event)
if hasattr(self, 'cbar'):
self.cbar.remove()
del(self.cbar)

View File

@ -12,7 +12,7 @@ import subprocess
from obspy import UTCDateTime, read
from pylot.core.io.inputs import PylotParameter
def _pickle_method(m):
if m.im_self is None:
return getattr, (m.im_class, m.im_func.func_name)

View File

@ -35,6 +35,7 @@ from PySide.QtGui import QAction, QApplication, QCheckBox, QComboBox, \
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
from PySide.QtWebKit import QWebView
from obspy import Stream, UTCDateTime
from obspy.core.util import AttribDict
from pylot.core.io.data import Data
from pylot.core.io.inputs import FilterOptions, PylotParameter
from pylot.core.pick.utils import getSNR, earllatepicker, getnoisewin, \
@ -707,7 +708,7 @@ class WaveformWidget(FigureCanvas):
self.draw()
def updateTitle(self, text):
self.getAxes().set_title(text)
self.getAxes().set_title(text, verticalalignment='bottom')
self.draw()
def updateWidget(self, xlabel, ylabel, title):
@ -724,7 +725,7 @@ class WaveformWidget(FigureCanvas):
class PickDlg(QDialog):
update_picks = QtCore.Signal(dict)
def __init__(self, parent=None, data=None, station=None, picks=None,
def __init__(self, parent=None, data=None, station=None, network=None, picks=None,
autopicks=None, rotate=False, parameter=None, embedded=False):
super(PickDlg, self).__init__(parent)
@ -732,6 +733,7 @@ class PickDlg(QDialog):
self.parameter = parameter
self._embedded = embedded
self.station = station
self.network = network
self.rotate = rotate
self.components = 'ZNE'
self.currentPhase = None
@ -806,7 +808,15 @@ class PickDlg(QDialog):
self.cidscroll = self.connectScrollEvent(self.scrollZoom)
def setupUi(self):
menuBar = QtGui.QMenuBar(self)
if not self._embedded:
exitMenu = menuBar.addMenu('File')
exitAction = QtGui.QAction('Close', self)
exitAction.triggered.connect(self.close)
exitMenu.addAction(exitAction)
self.addPickPhases(menuBar)
# create matplotlib toolbar to inherit functionality
self.figToolBar = NavigationToolbar2QT(self.getPlotWidget(), self)
self.figToolBar.hide()
@ -847,8 +857,8 @@ class PickDlg(QDialog):
self.p_button.setCheckable(True)
self.s_button.setCheckable(True)
# set button tooltips
self.p_button.setToolTip('Hotkey: "1"')
self.s_button.setToolTip('Hotkey: "2"')
# self.p_button.setToolTip('Hotkey: "1"')
# self.s_button.setToolTip('Hotkey: "2"')
# create accept/reject button
self.accept_button = QPushButton('&Accept Picks')
@ -859,8 +869,8 @@ class PickDlg(QDialog):
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'))
# self.p_button.setShortcut(QKeySequence('1'))
# self.s_button.setShortcut(QKeySequence('2'))
# layout the outermost appearance of the Pick Dialog
_outerlayout = QVBoxLayout()
@ -892,9 +902,13 @@ class PickDlg(QDialog):
# merge widgets and layouts to establish the dialog
if not self._embedded:
_innerlayout.addWidget(_buttonbox)
_outerlayout.addWidget(menuBar)
_outerlayout.addWidget(_dialtoolbar)
_outerlayout.addLayout(_innerlayout)
_outerlayout.setStretch(0, 0)
_outerlayout.setStretch(1, 0)
_outerlayout.setStretch(2, 1)
# connect widget element signals with slots (methods to the dialog
# object
self.p_button.clicked.connect(self.p_clicked)
@ -910,6 +924,60 @@ class PickDlg(QDialog):
self.setLayout(_outerlayout)
self.resize(1280, 720)
def addPickPhases(self, menuBar):
settings = QtCore.QSettings()
p_phases = settings.value('p_phases')
s_phases = settings.value('s_phases')
if p_phases:
p_phases = p_phases.split(',')
else:
p_phases = []
if s_phases:
s_phases = s_phases.split(',')
else:
s_phases = []
phases = {'P': p_phases,
'S': s_phases}
if not 'P' in phases['P'] and not 'p' in phases['P']:
phases['P'] = ['P'] + phases['P']
if not 'S' in phases['S'] and not 's' in phases['S']:
phases['S'] = ['S'] + phases['S']
picksMenu = menuBar.addMenu('Picks')
self.picksActions = {}
# dictionary points on corresponding phase_select function
phaseSelect = {'P': self.p_phase_select,
'S': self.s_phase_select}
nHotkey = 4 # max hotkeys per phase
hotkey = 1 # start hotkey
# loop over P and S (use explicit list instead of iter over dict.keys to keep order)
for phaseIndex, phaseID in enumerate(['P', 'S']):
# loop through phases in list
for index, phase in enumerate(phases[phaseID]):
# remove zeros
phase = phase.strip()
# add hotkeys
if not index >= nHotkey:
shortcut = str(hotkey)
hotkey += 1
else:
shortcut = None
# create action and add to menu
# phase name transferred using lambda function
slot = lambda phase=phase, phaseID=phaseID: phaseSelect[phaseID](phase)
picksAction = createAction(parent=self, text=phase,
slot=slot,
shortcut=shortcut)
picksMenu.addAction(picksAction)
self.picksActions[str(phase)] = picksAction # save action in dictionary
if phaseIndex == 0:
picksMenu.addSeparator()
def disconnectPressEvent(self):
widget = self.getPlotWidget()
widget.mpl_disconnect(self.cidpress)
@ -952,9 +1020,32 @@ class PickDlg(QDialog):
def enable_ar_buttons(self, bool=True):
self.accept_button.setEnabled(bool)
self.reject_button.setEnabled(bool)
def p_phase_select(self, phase):
if not self.p_button.isChecked():
self.p_button.setChecked(True)
self.p_button.setText(phase)
else:
if str(phase) == str(self.p_button.text()):
self.reset_p_button()
else:
self.p_button.setText(phase)
self.p_clicked()
def s_phase_select(self, phase):
if not self.s_button.isChecked():
self.s_button.setChecked(True)
self.s_button.setText(phase)
else:
if str(phase) == str(self.s_button.text()):
self.reset_s_button()
else:
self.s_button.setText(phase)
self.s_clicked()
def p_clicked(self):
if self.p_button.isChecked():
self.reset_s_button()
self.s_button.setEnabled(False)
self.init_p_pick()
else:
@ -962,7 +1053,8 @@ class PickDlg(QDialog):
def s_clicked(self):
if self.s_button.isChecked():
self.p_button.setEnabled(False)
self.reset_p_button()
self.p_button.setEnabled(False)
self.init_s_pick()
else:
self.leave_picking_mode()
@ -971,13 +1063,13 @@ class PickDlg(QDialog):
self.set_button_color(self.p_button, 'yellow')
self.updateCurrentLimits()
self.activatePicking()
self.currentPhase = 'P'
self.currentPhase = str(self.p_button.text())
def init_s_pick(self):
self.set_button_color(self.s_button, 'yellow')
self.updateCurrentLimits()
self.activatePicking()
self.currentPhase = 'S'
self.currentPhase = str(self.s_button.text())
def set_button_color(self, button, color = None):
if type(color) == QtGui.QColor:
@ -989,14 +1081,22 @@ class PickDlg(QDialog):
elif type(color) == str or not color:
button.setStyleSheet("background-color: {}".format(color))
def reset_p_button(self):
self.set_button_color(self.p_button)
self.p_button.setEnabled(True)
self.p_button.setChecked(False)
self.p_button.setText('P')
def reset_s_button(self):
self.set_button_color(self.s_button)
self.s_button.setEnabled(True)
self.s_button.setChecked(False)
self.s_button.setText('S')
def leave_picking_mode(self):
self.currentPhase = None
self.set_button_color(self.p_button)
self.set_button_color(self.s_button)
self.p_button.setEnabled(True)
self.s_button.setEnabled(True)
self.p_button.setChecked(False)
self.s_button.setChecked(False)
self.reset_p_button()
self.reset_s_button()
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
title=self.getStation())
self.drawAllPicks()
@ -1035,6 +1135,8 @@ class PickDlg(QDialog):
return self.components
def getStation(self):
if self.network and self.station:
return self.network+'.'+self.station
return self.station
def getPlotWidget(self):
@ -1057,7 +1159,7 @@ class PickDlg(QDialog):
return self._user
def getFilterOptions(self, phase):
options = self.filteroptions[phase]
options = self.filteroptions[phase[0]]
return FilterOptions(**options)
def getXLims(self):
@ -1132,11 +1234,10 @@ class PickDlg(QDialog):
self.disconnectMotionEvent()
self.cidpress = self.connectPressEvent(self.setPick)
print(self.currentPhase)
if self.currentPhase == 'P':
if self.currentPhase.startswith('P'):
self.set_button_color(self.p_button, 'green')
self.setIniPickP(gui_event, wfdata, trace_number)
elif self.currentPhase == 'S':
elif self.currentPhase.startswith('S'):
self.set_button_color(self.s_button, 'green')
self.setIniPickS(gui_event, wfdata)
@ -1169,7 +1270,7 @@ class PickDlg(QDialog):
# filter data and trace on which is picked prior to determination of SNR
phase = self.currentPhase
filteroptions = self.getFilterOptions(phase).parseFilterOptions()
filteroptions = self.getFilterOptions(phase[0]).parseFilterOptions()
if filteroptions:
data.filter(**filteroptions)
wfdata.filter(**filteroptions)
@ -1360,9 +1461,11 @@ class PickDlg(QDialog):
'S': ('m', 'm--', 'r-', 'rv', 'r^', 'r', 'm:')
}
if self.getPicks(picktype):
if phase is not None and type(self.getPicks(picktype)[phase]) is dict:
picks = self.getPicks(picktype)[phase]
colors = phase_col[phase[0].upper()]
if phase is not None:
if (type(self.getPicks(picktype)[phase]) is dict
or type(self.getPicks(picktype)[phase]) is AttribDict):
picks = self.getPicks(picktype)[phase]
colors = phase_col[phase[0].upper()]
elif phase is None:
for phase in self.getPicks(picktype):
self.drawPicks(phase, picktype)
@ -1387,7 +1490,8 @@ class PickDlg(QDialog):
ax.plot([mpp + spe, mpp + spe], ylims, colors[1])
ax.plot([mpp, mpp], ylims, colors[2], label='{}-Pick'.format(phase))
else:
ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase))
ax.plot([mpp, mpp], ylims, colors[6], label='{}-Pick (NO PICKERROR)'.format(phase))
ax.text(mpp, ylims[1], phase)
elif picktype == 'auto':
ax.plot(mpp, ylims[1], colors[3],
@ -1646,7 +1750,7 @@ class TuneAutopicker(QWidget):
model = self.stationBox.model()
for network, station in stations:
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'])
model.appendRow(item)
@ -1687,8 +1791,8 @@ class TuneAutopicker(QWidget):
self.listWidget.scrollToBottom()
def get_current_event(self):
index = self.eventBox.currentIndex()
return self.eventBox.itemData(index)
path = self.eventBox.currentText()
return self.parent.project.getEventFromPath(path)
def get_current_event_name(self):
return self.eventBox.currentText().split('/')[-1]
@ -1698,13 +1802,13 @@ class TuneAutopicker(QWidget):
def get_current_event_picks(self, station):
event = self.get_current_event()
if station in event.picks.keys():
return event.picks[station]
if station in event.pylot_picks.keys():
return event.pylot_picks[station]
def get_current_event_autopicks(self, station):
event = self.get_current_event()
if event.autopicks:
return event.autopicks[station]
if event.pylot_autopicks:
return event.pylot_autopicks[station]
def get_current_station(self):
return str(self.stationBox.currentText()).split('.')[-1]
@ -1855,6 +1959,9 @@ class TuneAutopicker(QWidget):
self.init_tab_names()
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')
index_start = self.parent.eventBox.currentIndex()
@ -1862,11 +1969,15 @@ class TuneAutopicker(QWidget):
if index == -1:
index += 1
nevents = self.eventBox.model().rowCount()
if self.eventBox.itemData(index).isTestEvent():
path = self.eventBox.itemText(index)
if project.getEventFromPath(path).isTestEvent():
for index in range(nevents):
if not self.eventBox.itemData(index).isTestEvent():
break
elif index == nevents - 1:
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:
@ -1911,8 +2022,8 @@ class TuneAutopicker(QWidget):
self._warn('Could not execute picker:\n{}'.format(
self.ap_thread._executedError))
return
self.picks = self.ap_thread.data
if not self.picks:
self.pylot_picks = self.ap_thread.data
if not self.pylot_picks:
self._warn('No picks found. See terminal output.')
return
#renew tabs
@ -2456,6 +2567,7 @@ class PropertiesDlg(QDialog):
elif setting.startswith('Channel N'):
component = 'N'
compclass.setCompPosition(value, component, False)
settings.sync()
@ -2547,7 +2659,7 @@ class OutputsTab(PropTab):
settings = QSettings()
curval = settings.value("output/Format", None)
eventOutputLabel = QLabel("event ouput format")
eventOutputLabel = QLabel("event/picks output format")
self.eventOutputComboBox = QComboBox()
eventoutputformats = OUTPUTFORMATS.keys()
self.eventOutputComboBox.addItems(eventoutputformats)
@ -2568,13 +2680,45 @@ class OutputsTab(PropTab):
def resetValues(self, infile):
values = {"output/Format": self.eventOutputComboBox.setCurrentIndex(1)}
return values
class PhasesTab(PropTab):
def __init__(self, parent=None):
super(PhasesTab, self).__init__(parent)
pass
self.PphasesEdit = QLineEdit()
self.SphasesEdit = QLineEdit()
PphasesLabel = QLabel("P Phases to pick")
SphasesLabel = QLabel("S Phases to pick")
settings = QSettings()
Pphases = settings.value('p_phases')
Sphases = settings.value('s_phases')
self.PphasesEdit.setText("%s" % Pphases)
self.SphasesEdit.setText("%s" % Sphases)
layout = QGridLayout()
layout.addWidget(PphasesLabel, 0, 0)
layout.addWidget(SphasesLabel, 1, 0)
layout.addWidget(self.PphasesEdit, 0, 1)
layout.addWidget(self.SphasesEdit, 1, 1)
self.setLayout(layout)
def getValues(self):
values = {'p_phases': self.PphasesEdit.text(),
's_phases': self.SphasesEdit.text()}
return values
def resetValues(self, infile=None):
Pphases = 'P, Pg, Pn, PmP, P1, P2, P3'
Sphases = 'S, Sg, Sn, SmS, S1, S2, S3'
values = {'p_phases': self.PphasesEdit.setText(Pphases),
's_phases': self.SphasesEdit.setText(Sphases)}
return values
class GraphicsTab(PropTab):
def __init__(self, parent=None):
@ -2619,7 +2763,12 @@ class GraphicsTab(PropTab):
'pyqtgraphic': self.checkbox_pg.isChecked()}
return values
def resetValues(self, infile=None):
values = {'nth_sample': self.spinbox_nth_sample.setValue(1),
'pyqtgraphic': self.checkbox_pg.setChecked(True)}
return values
class ChannelOrderTab(PropTab):
def __init__(self, parent=None, infile=None):
super(ChannelOrderTab, self).__init__(parent)