Merge branch 'develop'

This commit is contained in:
Marcel Paffrath 2017-06-22 10:28:15 +02:00
commit 9dc472f907
5 changed files with 206 additions and 75 deletions

View File

@ -106,7 +106,9 @@ class MainWindow(QMainWindow):
self._inputs = AutoPickParameter(infile)
self._props = None
self.dirty = False
self.project = Project()
self.project.parameter = self._inputs
self.tap = None
self.paraBox = None
self.array_map = None
@ -143,8 +145,6 @@ class MainWindow(QMainWindow):
self.data = Data(self)
self.autodata = Data(self)
self.dirty = False
if settings.value("user/FullName", None) is None:
fulluser = QInputDialog.getText(self, "Enter Name:", "Full name")
settings.setValue("user/FullName", fulluser)
@ -172,7 +172,6 @@ class MainWindow(QMainWindow):
self.setupUi()
self.filteroptions = {}
self.pickDlgs = {}
self.picks = {}
self.autopicks = {}
self.loc = False
@ -362,10 +361,10 @@ class MainWindow(QMainWindow):
QCoreApplication.instance().quit,
QKeySequence.Close, quitIcon,
"Close event and quit PyLoT")
self.parameterAction = self.createAction(self, "Pick Parameter",
self.pickParameter,
self.parameterAction = self.createAction(self, "Parameter",
self.setParameter,
None, QIcon(None),
"Modify Picking Parameter")
"Modify Parameter")
self.filterAction = self.createAction(self, "&Filter ...",
self.filterWaveformData,
"Ctrl+F", filter_icon,
@ -756,7 +755,7 @@ class MainWindow(QMainWindow):
Creates and adds events by user selection of event folders to GUI.
'''
if not self.project:
self.project = Project()
self.createNewProject()
ed = getExistingDirectories(self, 'Select event directories...')
if ed.exec_():
eventlist = ed.selectedFiles()
@ -764,11 +763,55 @@ class MainWindow(QMainWindow):
eventlist = [item for item in eventlist if item.split('/')[-1].startswith('e')
and len(item.split('/')[-1].split('.')) == 3
and len(item.split('/')[-1]) == 12]
if not eventlist:
print('No events found! Expected structure for event folders: [evID.DOY.YR]')
return
else:
return
if not self.project:
print('No project found.')
return
#get path from first event in list and split them
path = eventlist[0]
try:
dirs = {
'database': path.split('/')[-2],
'datapath': path.split('/')[-3],
'rootpath': os.path.join(*path.split('/')[:-3])
}
except Exception as e:
dirs = {
'database': '',
'datapath': '',
'rootpath': ''
}
print('Warning: Could not automatically init folder structure. ({})'.format(e))
if not self.project.eventlist:
#init parameter object
self.setParameter(show=False)
#hide all parameter (show all needed parameter later)
self.paraBox.hide_parameter()
for directory in dirs.keys():
#set parameter
box = self.paraBox.boxes[directory]
self.paraBox.setValue(box, dirs[directory])
#show needed parameter in box
self.paraBox.show_parameter(directory)
dirs_box = self.paraBox.get_groupbox_exclusive('Directories')
if not dirs_box.exec_():
return
self.project.rootpath = dirs['rootpath']
else:
if hasattr(self.project, 'rootpath'):
if not self.project.rootpath == dirs['rootpath']:
QMessageBox.warning(self, "PyLoT Warning",
'Rootpath missmatch to current project!')
return
else:
self.project.rootpath = dirs['rootpath']
self.project.add_eventlist(eventlist)
self.init_events()
self.setDirty(True)
@ -1314,6 +1357,8 @@ class MainWindow(QMainWindow):
self.disconnectWFplotEvents()
if self.pg:
self.dataPlot.plotWidget.getPlotItem().clear()
self.dataPlot.plotWidget.hideAxis('bottom')
self.dataPlot.plotWidget.hideAxis('left')
else:
self.dataPlot.getAxes().cla()
self.loadlocationaction.setEnabled(False)
@ -1519,7 +1564,9 @@ class MainWindow(QMainWindow):
wfID = self.getWFID(ycoord)
if wfID is None: return
self.pickDialog(wfID)
def pickDialog(self, wfID, nextStation=False):
station = self.getStationName(wfID)
if not station:
return
@ -1530,21 +1577,23 @@ class MainWindow(QMainWindow):
station=station,
picks=self.getPicksOnStation(station, 'manual'),
autopicks=self.getPicksOnStation(station, 'auto'))
pickDlg.nextStation.setChecked(nextStation)
if pickDlg.exec_():
if not pickDlg.getPicks():
return
self.setDirty(True)
self.update_status('picks accepted ({0})'.format(station))
replot = self.addPicks(station, pickDlg.getPicks())
self.get_current_event().setPick(station, pickDlg.getPicks())
self.enableSaveManualPicksAction()
if replot:
self.plotWaveformDataThread()
self.drawPicks()
self.draw()
else:
self.drawPicks(station)
self.draw()
if pickDlg.getPicks():
self.setDirty(True)
self.update_status('picks accepted ({0})'.format(station))
replot = self.addPicks(station, pickDlg.getPicks())
self.get_current_event().setPick(station, pickDlg.getPicks())
self.enableSaveManualPicksAction()
if replot:
self.plotWaveformDataThread()
self.drawPicks()
self.draw()
else:
self.drawPicks(station)
self.draw()
if pickDlg.nextStation.isChecked():
self.pickDialog(wfID - 1, nextStation=pickDlg.nextStation.isChecked())
else:
self.update_status('picks discarded ({0})'.format(station))
if not self.get_loc_flag() and self.check4Loc():
@ -2175,28 +2224,18 @@ class MainWindow(QMainWindow):
self.data = Data(self, evtdata=event)
self.setDirty(True)
def createNewProject(self, exists=False):
def createNewProject(self):
'''
Create new project file.
'''
if not exists:
if not self.okToContinue():
return
dlg = QFileDialog()
fnm = dlg.getSaveFileName(self, 'Create a new project file...', filter='Pylot project (*.plp)')
filename = fnm[0]
if not len(fnm[0]):
return False
if not filename.split('.')[-1] == 'plp':
filename = fnm[0] + '.plp'
if not exists:
self.project = Project()
self.init_events(new=True)
self.setDirty(True)
self.project.parameter=self._inputs
self.project.save(filename)
if not self.okToContinue():
return
self.project = Project()
self.init_events(new=True)
self.setDirty(False)
self.update_status('Creating new project...', duration=1000)
self.project.parameter=self._inputs
self.saveProjectAsAction.setEnabled(True)
self.update_status('Created new project...', duration=1000)
return True
def loadProject(self, fnm=None):
@ -2225,8 +2264,26 @@ class MainWindow(QMainWindow):
return
self.init_array_tab()
def saveProjectAs(self):
self.saveProject(new=True)
def saveProjectAs(self, exists=False):
'''
Save back project to new pickle file.
'''
if not exists:
if not self.okToContinue():
return
dlg = QFileDialog()
fnm = dlg.getSaveFileName(self, 'Create a new project file...', filter='Pylot project (*.plp)')
filename = fnm[0]
if not len(fnm[0]):
return False
if not filename.split('.')[-1] == 'plp':
filename = fnm[0] + '.plp'
self.project.parameter=self._inputs
self.project.save(filename)
self.setDirty(False)
self.saveProjectAsAction.setEnabled(True)
self.update_status('Saved new project to {}'.format(filename), duration=5000)
return True
def saveProject(self, new=False):
'''
@ -2234,14 +2291,14 @@ class MainWindow(QMainWindow):
'''
if self.project and not new:
if not self.project.location:
if not self.createNewProject(exists=True):
if not self.saveProjectAs(exists=True):
self.setDirty(True)
return False
else:
self.project.parameter=self._inputs
self.project.save()
if not self.project.dirty:
print('Saved back project to file:\n{}'.format(self.project.location))
self.update_status('Saved back project to file:\n{}'.format(self.project.location), duration=5000)
self.setDirty(False)
return True
else:
@ -2249,7 +2306,7 @@ class MainWindow(QMainWindow):
qmb = QMessageBox.warning(self,'Could not save project',
'Could not save back to original file.\nChoose new file')
self.setDirty(True)
return self.createNewProject(exists=True)
return self.saveProjectAs(exists=True)
def draw(self):
self.fill_eventbox()
@ -2260,7 +2317,7 @@ class MainWindow(QMainWindow):
def setDirty(self, value):
self.saveProjectAction.setEnabled(value)
self.saveProjectAsAction.setEnabled(value)
self.saveProjectAsAction.setEnabled(True)
self.project.setDirty(value)
self.dirty = value
@ -2272,12 +2329,13 @@ class MainWindow(QMainWindow):
# self.closing.emit()
# QMainWindow.closeEvent(self, event)
def pickParameter(self):
def setParameter(self, show=True):
if not self.paraBox:
self.paraBox = AutoPickParaBox(self._inputs)
self.paraBox._apply.clicked.connect(self._setDirty)
self.paraBox._okay.clicked.connect(self._setDirty)
self.paraBox.show()
self.paraBox._okay.clicked.connect(self._setDirty)
if show:
self.paraBox.show()
def PyLoTprefs(self):
if not self._props:
@ -2303,6 +2361,7 @@ class Project(object):
def __init__(self):
self.eventlist = []
self.location = None
self.rootpath = None
self.dirty = False
self.parameter = None
self._table = None
@ -2316,6 +2375,9 @@ class Project(object):
return
for item in eventlist:
event = Event(item)
event.rootpath = self.parameter['rootpath']
event.database = self.parameter['database']
event.datapath = self.parameter['datapath']
if not event.path in self.getPaths():
self.eventlist.append(event)
self.setDirty()
@ -2387,6 +2449,9 @@ class Event(object):
'''
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 = ''

View File

@ -1 +1 @@
ab97-dirty
6feff-dirty

View File

@ -277,8 +277,12 @@ defaults = {'rootpath': {'type': str,
'tooltip': 'maximum allowed deviation from Wadati-diagram',
'value': 1.0},
'localMag': {'type': float,
'tooltip': 'maximum allowed deviation from Wadati-diagram',
'WAscaling': {'type': float,
'tooltip': 'Scaling relation of Wood-Anderson amplitude [nm]',
'value': 1.0},
'magscaling': {'type': float,
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]',
'value': 1.0}
}
@ -301,8 +305,10 @@ settings_main={
'smoment':[
'vp',
'rho',
'Qp',
'localMag'],
'Qp'],
'localmag':[
'WAscaling',
'magscaling'],
'pick':[
'extent',
'pstart',

View File

@ -140,7 +140,8 @@ class AutoPickParameter(object):
all_names += self.get_main_para_names()['dirs']
all_names += self.get_main_para_names()['nlloc']
all_names += self.get_main_para_names()['smoment']
all_names += self.get_main_para_names()['pick']
all_names += self.get_main_para_names()['localmag']
all_names += self.get_main_para_names()['pick']
all_names += self.get_special_para_names()['z']
all_names += self.get_special_para_names()['h']
all_names += self.get_special_para_names()['fm']
@ -234,6 +235,8 @@ class AutoPickParameter(object):
'NLLoc settings', seperator)
self.write_section(fid_out, self.get_main_para_names()['smoment'],
'parameters for seismic moment estimation', seperator)
self.write_section(fid_out, self.get_main_para_names()['localmag'],
'settings local magnitude', seperator)
self.write_section(fid_out, self.get_main_para_names()['pick'],
'common settings picker', seperator)
fid_out.write(('#special settings for calculating CF#\n'+

View File

@ -752,6 +752,7 @@ class PickDlg(QDialog):
self._init_autopicks = {}
self.filteroptions = FILTERDEFAULTS
self.pick_block = False
self.nextStation = QtGui.QCheckBox('Continue with next station.')
# initialize panning attributes
self.press = None
@ -845,17 +846,21 @@ class PickDlg(QDialog):
self.s_button = QPushButton('S', self)
self.p_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
self.p_button.setToolTip('Hotkey: "1"')
self.s_button.setToolTip('Hotkey: "2"')
# create accept/reject button
self.accept_button = QPushButton('&Accept Picks')
self.reject_button = QPushButton('&Reject Picks')
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
_outerlayout = QVBoxLayout()
@ -872,7 +877,9 @@ class PickDlg(QDialog):
_dialtoolbar.addAction(self.resetPicksAction)
if self._embedded:
_dialtoolbar.addWidget(self.accept_button)
_dialtoolbar.addWidget(self.reject_button)
_dialtoolbar.addWidget(self.reject_button)
else:
_dialtoolbar.addWidget(self.nextStation)
# layout the innermost widget
_innerlayout = QVBoxLayout()
@ -1724,7 +1731,6 @@ class TuneAutopicker(QWidget):
pickDlg.update_picks.connect(self.picks_from_pickdlg)
pickDlg.update_picks.connect(self.fill_eventbox)
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(self.parent.enableSaveManualPicksAction)
self.pickDlg = QtGui.QWidget()
@ -1734,7 +1740,15 @@ class TuneAutopicker(QWidget):
def picks_from_pickdlg(self, picks=None):
station = self.get_current_station()
replot = self.parent.addPicks(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):
picks = self.get_current_event_picks(self.get_current_station())
@ -1843,7 +1857,7 @@ class TuneAutopicker(QWidget):
def fill_eventbox(self):
# update own list
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
index_start = self.eventBox.currentIndex()
index_start = self.parent.eventBox.currentIndex()
index = index_start
if index == -1:
index += 1
@ -1979,7 +1993,8 @@ class AutoPickParaBox(QtGui.QWidget):
self.add_special_pick_parameters_tab()
self.params_to_gui()
self._toggle_advanced_settings()
self.resize(720, 1280)
self.resize(720, 1280)
self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
def _init_sublayouts(self):
self._main_layout = QtGui.QVBoxLayout()
@ -2107,31 +2122,31 @@ class AutoPickParaBox(QtGui.QWidget):
scrollA = QtGui.QScrollArea()
scrollA.setWidgetResizable(True)
scrollA.setWidget(widget)
widget.setLayout(layout)
self.tabs.addTab(scrollA, name)
def add_main_parameters_tab(self):
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.parameter.get_main_para_names()['nlloc'])
self.parameter.get_main_para_names()['nlloc'], 1)
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.parameter.get_main_para_names()['pick'])
self.parameter.get_main_para_names()['pick'], 4)
self.add_tab(self._main_layout, 'Main Settings')
def add_special_pick_parameters_tab(self):
self.add_to_layout(self._advanced_layout, 'Z-component',
self.parameter.get_special_para_names()['z'])
self.parameter.get_special_para_names()['z'], 0)
self.add_to_layout(self._advanced_layout, 'H-components',
self.parameter.get_special_para_names()['h'])
self.parameter.get_special_para_names()['h'], 1)
self.add_to_layout(self._advanced_layout, 'First-motion picker',
self.parameter.get_special_para_names()['fm'])
self.parameter.get_special_para_names()['fm'], 2)
self.add_to_layout(self._advanced_layout, 'Quality assessment',
self.parameter.get_special_para_names()['quality'])
self.parameter.get_special_para_names()['quality'], 3)
self.add_tab(self._advanced_layout, 'Advanced Settings')
# def gen_h_seperator(self):
@ -2145,12 +2160,37 @@ class AutoPickParaBox(QtGui.QWidget):
# font.setBold(True)
# label.setFont(font)
# return label
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):
dialog = QtGui.QDialog(self.parent())
buttonbox = QtGui.QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
self._exclusive_dialog = dialog
layout = QtGui.QVBoxLayout()
dialog.setLayout(layout)
layout.addWidget(self.groupboxes[name])
layout.addWidget(buttonbox)
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)
return dialog
def add_to_layout(self, layout, name, items):
def add_to_layout(self, layout, name, items, position):
groupbox = QtGui.QGroupBox(name)
groupbox._position = position
groupbox._parentLayout = layout
self.groupboxes[name] = groupbox
groupbox.setLayout(self.init_boxes(items))
layout.addWidget(groupbox)
layout.insertWidget(position, groupbox)
def show_groupboxes(self):
for name in self.groupboxes.keys():
@ -2174,6 +2214,16 @@ class AutoPickParaBox(QtGui.QWidget):
else:
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):
if not name:
for name in self.boxes.keys():
@ -2286,6 +2336,13 @@ class AutoPickParaBox(QtGui.QWidget):
except Exception as e:
self._warn('Could not restore defaults:\n{}'.format(e))
return
def show(self):
self.refresh()
self.show_parameter()
if hasattr(self, '_exclusive_dialog'):
self._exclusive_dialog.close()
QtGui.QWidget.show(self)
def _warn(self, message):
self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning,