815 lines
26 KiB
Python
815 lines
26 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Wed Mar 19 11:27:35 2014
|
|
|
|
@author: sebastianw
|
|
"""
|
|
|
|
import datetime
|
|
import numpy as np
|
|
import matplotlib
|
|
|
|
matplotlib.use('Qt4Agg')
|
|
matplotlib.rcParams['backend.qt4'] = 'PySide'
|
|
|
|
from matplotlib.figure import Figure
|
|
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
|
from matplotlib.widgets import MultiCursor
|
|
from PySide.QtGui import QAction, QApplication,QComboBox, QDateTimeEdit,\
|
|
QDialog, QDialogButtonBox, QDoubleSpinBox, QGroupBox, QGridLayout,\
|
|
QIcon, QKeySequence, QLabel, QLineEdit, QMessageBox, QPixmap, QSpinBox,\
|
|
QTabWidget, QToolBar, QVBoxLayout, QWidget
|
|
from PySide.QtCore import QSettings, Qt, QUrl, Signal, Slot
|
|
from PySide.QtWebKit import QWebView
|
|
from obspy import Stream, UTCDateTime
|
|
from obspy.core.event import Pick
|
|
from pylot.core.read import FilterOptions
|
|
from pylot.core.pick.utils import getSNR
|
|
from pylot.core.util.defaults import OUTPUTFORMATS
|
|
from pylot.core.util import prepTimeAxis, getGlobalTimes
|
|
|
|
|
|
def createAction(parent, text, slot=None, shortcut=None, icon=None,
|
|
tip=None, checkable=False):
|
|
"""
|
|
:rtype : ~PySide.QtGui.QAction
|
|
"""
|
|
action = QAction(text, parent)
|
|
if icon is not None:
|
|
action.setIcon(icon)
|
|
if shortcut is not None:
|
|
action.setShortcut(shortcut)
|
|
if tip is not None:
|
|
action.setToolTip(tip)
|
|
if slot is not None:
|
|
action.triggered.connect(slot)
|
|
if checkable:
|
|
action.setCheckable(True)
|
|
return action
|
|
|
|
class MPLWidget(FigureCanvas):
|
|
|
|
def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'):
|
|
|
|
self._parent = None
|
|
self.setParent(parent)
|
|
self.figure = Figure()
|
|
# attribute plotdict is an dictionary connecting position and a name
|
|
self.plotdict = dict()
|
|
# create axes
|
|
self.axes = self.figure.add_subplot(111)
|
|
# clear axes each time plot is called
|
|
self.axes.hold(True)
|
|
# initialize super class
|
|
FigureCanvas.__init__(self, self.figure)
|
|
# add an cursor for station selection
|
|
self.multiCursor = MultiCursor(self.figure.canvas, (self.axes,), horizOn=True,
|
|
color='m', lw=1)
|
|
# update labels of the entire widget
|
|
self.updateWidget(xlabel, ylabel, title)
|
|
|
|
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):
|
|
self.axes.cla()
|
|
self.clearPlotDict()
|
|
wfstart = getGlobalTimes(wfdata)[0]
|
|
for n, trace in enumerate(wfdata):
|
|
channel = trace.stats.channel
|
|
station = trace.stats.station
|
|
msg = 'plotting %s channel of station %s' % (channel, station)
|
|
print(msg)
|
|
stime = trace.stats.starttime - wfstart
|
|
time_ax = prepTimeAxis(stime, trace)
|
|
trace.detrend()
|
|
trace.detrend('demean')
|
|
trace.normalize(trace.data.max() * 2)
|
|
self.axes.plot(time_ax, trace.data + n, 'k')
|
|
xlabel = 'seconds since {0}'.format(wfstart)
|
|
ylabel = ''
|
|
self.updateWidget(xlabel, ylabel, title)
|
|
self.setPlotDict(n, (station, channel))
|
|
self.axes.autoscale(tight=True)
|
|
if zoomx:
|
|
self.axes.set_xlim(zoomx)
|
|
if zoomy:
|
|
self.axes.set_ylim(zoomy)
|
|
self.draw()
|
|
|
|
def setYTickLabels(self, pos, labels):
|
|
self.axes.set_yticks(pos)
|
|
self.axes.set_yticklabels(labels)
|
|
self.draw()
|
|
|
|
def updateXLabel(self, text):
|
|
self.axes.set_xlabel(text)
|
|
self.draw()
|
|
|
|
|
|
def updateYLabel(self, text):
|
|
self.axes.set_ylabel(text)
|
|
self.draw()
|
|
|
|
def updateTitle(self, text):
|
|
self.axes.set_title(text)
|
|
self.draw()
|
|
|
|
def updateWidget(self, xlabel, ylabel, title):
|
|
self.updateXLabel(xlabel)
|
|
self.updateYLabel(ylabel)
|
|
self.updateTitle(title)
|
|
|
|
def insertLabel(self, pos, text):
|
|
pos = pos / max(self.axes.ylim)
|
|
axann = self.axes.annotate(text, xy=(.03, pos), xycoords='axes fraction')
|
|
axann.set_bbox(dict(facecolor='lightgrey', alpha=.6))
|
|
|
|
|
|
class multiComponentPlot(FigureCanvas):
|
|
|
|
def __init__(self, data, parent=None, components='ZNE'):
|
|
|
|
self.data = data
|
|
self._parent = parent
|
|
self.components = components
|
|
|
|
self.figure = Figure()
|
|
|
|
self.noc = len(components)
|
|
FigureCanvas.__init__(self, self.figure)
|
|
self.multiCursor = None
|
|
self.resetPlot(components, data)
|
|
|
|
def getData(self):
|
|
return self.data
|
|
|
|
def setData(self, data):
|
|
self.data = data
|
|
|
|
def getParent(self):
|
|
return self._parent
|
|
|
|
def setParent(self, parent):
|
|
self._parent = parent
|
|
|
|
def getComponents(self):
|
|
return self.components
|
|
|
|
def setComponents(self, components):
|
|
self.components = components
|
|
|
|
def getNoC(self):
|
|
return self.noc
|
|
|
|
def setNoC(self, noc):
|
|
self.noc = noc
|
|
|
|
def resetPlot(self, components=None, data=None):
|
|
|
|
# clear figure
|
|
self.figure.clf()
|
|
|
|
# delete multiCursor if existing
|
|
if self.multiCursor is not None:
|
|
self.multiCursor = None
|
|
|
|
# set new attribute values
|
|
if data is not None:
|
|
self.setData(data)
|
|
if components is not None:
|
|
self.setComponents(components)
|
|
noc = len(self.getComponents())
|
|
if self.getNoC() != noc:
|
|
self.setNoC(noc)
|
|
self.axesdict = dict()
|
|
|
|
# prepare variables for plotting
|
|
stime = getGlobalTimes(self.getData())[0]
|
|
|
|
xlabel = 'time since {0} [s]'.format(stime)
|
|
|
|
# plot individual component traces in separate subplots
|
|
for n, comp in enumerate(components):
|
|
nsub = '{0}1{1}'.format(self.noc, n+1)
|
|
if n >= 1:
|
|
subax = self.figure.add_subplot(nsub, sharex=self.axesdict[0])
|
|
else:
|
|
subax = self.figure.add_subplot(nsub)
|
|
subax.autoscale(tight=True)
|
|
subset = data.copy().select(component=comp)[0]
|
|
time_ax = prepTimeAxis(subset.stats.starttime - stime, subset)
|
|
subax.plot(time_ax, subset.data)
|
|
self.axesdict[n] = subax
|
|
self.updateYLabel(n, comp)
|
|
if n == self.noc:
|
|
self.updateXLabel(self.noc, xlabel)
|
|
else:
|
|
self.updateXLabel(n, '')
|
|
|
|
self.multiCursor = MultiCursor(self.figure.canvas,
|
|
tuple(self.axesdict.values()),
|
|
color='r', lw=1)
|
|
|
|
def updateXLabel(self, pos, text):
|
|
self.axesdict[pos].set_xlabel(text)
|
|
|
|
def updateYLabel(self, pos, text):
|
|
self.axesdict[pos].set_ylabel(text)
|
|
|
|
|
|
class PickDlg(QDialog):
|
|
|
|
def __init__(self, parent=None, data=None, station=None, rotate=False):
|
|
super(PickDlg, self).__init__(parent)
|
|
|
|
# initialize attributes
|
|
self.station = station
|
|
self.rotate = rotate
|
|
self.components = 'ZNE'
|
|
self.picks = {}
|
|
|
|
# set attribute holding data
|
|
if data is None:
|
|
try:
|
|
data = parent.getData().getWFData().copy()
|
|
self.data = data.select(station=station)
|
|
except AttributeError, e:
|
|
errmsg = 'You either have to put in a data or an appropriate ' \
|
|
'parent (PyLoT MainWindow) object: {0}'.format(e)
|
|
raise Exception(errmsg)
|
|
else:
|
|
self.data = data
|
|
|
|
# initialize plotting widget
|
|
self.multicompfig = MPLWidget(self)
|
|
|
|
# setup ui
|
|
self.setupUi()
|
|
|
|
# plot data
|
|
self.getPlotWidget().plotWFData(wfdata=self.getWFData(),
|
|
title=self.getStation())
|
|
|
|
# set plot labels
|
|
self.setPlotLabels()
|
|
|
|
# connect button press event to an action
|
|
self.cid = self.getPlotWidget().mpl_connect('button_press_event', self.setPick)
|
|
|
|
def setupUi(self):
|
|
|
|
# create icons
|
|
filter_icon = QIcon()
|
|
filter_icon.addPixmap(QPixmap(':/icons/filter.png'))
|
|
|
|
# create actions
|
|
self.filterAction = createAction(parent=self, text='Filter',
|
|
slot=self.filterWFData,
|
|
icon=filter_icon,
|
|
tip='Filter waveforms',
|
|
checkable=True)
|
|
self.selectPhase = QComboBox()
|
|
self.selectPhase.addItems(['Pn', 'Pg', 'P1', 'P2'])
|
|
|
|
# layout the outermost appearance of the Pick Dialog
|
|
_outerlayout = QVBoxLayout()
|
|
_dialtoolbar = QToolBar()
|
|
|
|
# fill toolbar with content
|
|
|
|
_dialtoolbar.addAction(self.filterAction)
|
|
_dialtoolbar.addWidget(self.selectPhase)
|
|
|
|
_innerlayout = QVBoxLayout()
|
|
|
|
_innerlayout.addWidget(self.multicompfig)
|
|
_buttonbox = QDialogButtonBox(QDialogButtonBox.Apply |
|
|
QDialogButtonBox.Ok |
|
|
QDialogButtonBox.Cancel)
|
|
|
|
_innerlayout.addWidget(_buttonbox)
|
|
|
|
_outerlayout.addWidget(_dialtoolbar)
|
|
_outerlayout.addLayout(_innerlayout)
|
|
self.setLayout(_outerlayout)
|
|
|
|
def reconnect(self, event_name, slot):
|
|
self.getPlotWidget().mpl_disconnect(self.cid)
|
|
self.cid = self.getPlotWidget().mpl_connect(event_name, slot)
|
|
|
|
def getComponents(self):
|
|
return self.components
|
|
|
|
def getStation(self):
|
|
return self.station
|
|
|
|
def getPlotWidget(self):
|
|
return self.multicompfig
|
|
|
|
def getChannelID(self, key):
|
|
return self.getPlotWidget().getPlotDict()[int(key)][1]
|
|
|
|
def getWFData(self):
|
|
return self.data
|
|
|
|
def selectWFData(self, channel):
|
|
component = channel[-1].upper()
|
|
wfdata = Stream()
|
|
def selectTrace(trace, components):
|
|
if trace.stats.channel[-1].upper() in components:
|
|
return trace
|
|
|
|
if component == 'E' or component == 'N':
|
|
for trace in self.getWFData():
|
|
trace = selectTrace(trace, 'NE')
|
|
if trace:
|
|
wfdata.append(trace)
|
|
elif component == 'Z':
|
|
wfdata = self.getWFData().select(component=component)
|
|
return wfdata
|
|
|
|
def getPicks(self):
|
|
return self.picks
|
|
|
|
def setPick(self, gui_event):
|
|
channel = self.getChannelID(round(gui_event.ydata))
|
|
wfdata = self.selectWFData(channel)
|
|
|
|
ini_pick = gui_event.xdata
|
|
|
|
# calculate the resolution window width from SNR
|
|
# SNR >= 3 -> 2 sec HRW
|
|
# 3 > SNR >= 2 -> 5 sec MRW
|
|
# 2 > SNR >= 1.5 -> 10 sec LRW
|
|
# 1.5 > SNR -> 15 sec VLRW
|
|
|
|
res_wins = {
|
|
'HRW' : 2.,
|
|
'MRW' : 5.,
|
|
'LRW' : 10.,
|
|
'VLRW' : 15.
|
|
}
|
|
|
|
result = getSNR(wfdata, (5,.5,1), ini_pick)
|
|
|
|
snr = result[0]
|
|
noiselevel = result[2] * 1.5
|
|
|
|
if snr < 1.5:
|
|
x_res = res_wins['VLRW']
|
|
elif snr < 2.:
|
|
x_res = res_wins['LRW']
|
|
elif snr < 3.:
|
|
x_res = res_wins['MRW']
|
|
else:
|
|
x_res = res_wins['HRW']
|
|
x_res /= 2
|
|
|
|
zoomx = [ini_pick - x_res, ini_pick + x_res]
|
|
zoomy = [noiselevel * 1.5, -noiselevel * 1.5]
|
|
self.getPlotWidget().plotWFData(wfdata=wfdata,
|
|
title=self.getStation() +
|
|
' picking mode',
|
|
zoomx=zoomx,
|
|
zoomy=zoomy)
|
|
|
|
self.getPlotWidget().axes.plot()
|
|
|
|
# reset labels
|
|
self.setPlotLabels()
|
|
|
|
self.reconnect('button_press_event', self.plotPick)
|
|
|
|
def plotPick(self, gui_event):
|
|
pick = gui_event.xdata
|
|
ax = self.getPlotWidget().axes
|
|
|
|
ylims = ax.get_ylim()
|
|
|
|
ax.plot([pick, pick], ylims, 'r--')
|
|
self.getPlotWidget().draw()
|
|
|
|
def filterWFData(self):
|
|
data = self.getWFData().copy().filter(type='bandpass', freqmin=.5, freqmax=15.)
|
|
title = self.getStation() + ' (filtered)'
|
|
self.getPlotWidget().plotWFData(wfdata=data, title=title)
|
|
self.setPlotLabels()
|
|
|
|
def setPlotLabels(self):
|
|
|
|
# get channel labels
|
|
pos = self.getPlotWidget().getPlotDict().keys()
|
|
labels = [self.getPlotWidget().getPlotDict()[key][1] for key in pos]
|
|
|
|
# set channel labels
|
|
self.getPlotWidget().setYTickLabels(pos, labels)
|
|
|
|
def apply(self):
|
|
if self.getPicks():
|
|
for phase, time in self.getPicks().iteritems():
|
|
ope_pick = Pick()
|
|
ope_pick.time = time
|
|
ope_pick.phase_hint = phase
|
|
print ope_pick
|
|
|
|
def reject(self):
|
|
QDialog.reject(self)
|
|
|
|
def accept(self):
|
|
self.apply()
|
|
QDialog.accept(self)
|
|
|
|
class PropertiesDlg(QDialog):
|
|
|
|
def __init__(self, parent=None):
|
|
super(PropertiesDlg, self).__init__(parent)
|
|
|
|
appName = QApplication.applicationName()
|
|
|
|
self.setWindowTitle("{0} Properties".format(appName))
|
|
|
|
self.tabWidget = QTabWidget()
|
|
self.tabWidget.addTab(InputsTab(self), "Inputs")
|
|
self.tabWidget.addTab(OutputsTab(self), "Outputs")
|
|
self.tabWidget.addTab(PhasesTab(self), "Phases")
|
|
self.tabWidget.addTab(GraphicsTab(self), "Graphics")
|
|
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok |
|
|
QDialogButtonBox.Apply |
|
|
QDialogButtonBox.Close)
|
|
|
|
layout = QVBoxLayout()
|
|
layout.addWidget(self.tabWidget)
|
|
layout.addWidget(self.buttonBox)
|
|
self.setLayout(layout)
|
|
|
|
self.buttonBox.accepted.connect(self.accept)
|
|
self.buttonBox.rejected.connect(self.reject)
|
|
self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
|
|
|
|
def accept(self, *args, **kwargs):
|
|
self.apply()
|
|
QDialog.accept(self)
|
|
|
|
def apply(self):
|
|
for widint in range(self.tabWidget.count()):
|
|
curwid = self.tabWidget.widget(widint)
|
|
values = curwid.getValues()
|
|
if values is not None: self.setValues(values)
|
|
|
|
def setValues(self, tabValues):
|
|
settings = QSettings()
|
|
for setting, value in tabValues.iteritems():
|
|
settings.setValue(setting, value)
|
|
settings.sync()
|
|
|
|
|
|
class PropTab(QWidget):
|
|
|
|
def __init__(self, parent=None):
|
|
super(PropTab, self).__init__(parent)
|
|
|
|
def getValues(self):
|
|
return None
|
|
|
|
|
|
class InputsTab(PropTab):
|
|
|
|
def __init__(self, parent):
|
|
super(InputsTab, self).__init__(parent)
|
|
|
|
settings = QSettings()
|
|
fulluser = settings.value("user/FullName")
|
|
login = settings.value("user/Login")
|
|
|
|
fullNameLabel = QLabel("Full name for user '{0}': ".format(login))
|
|
|
|
# get the full name of the actual user
|
|
self.fullNameEdit = QLineEdit()
|
|
self.fullNameEdit.setText(fulluser)
|
|
|
|
# information about data structure
|
|
dataroot = settings.value("data/dataRoot")
|
|
dataDirLabel = QLabel("data root directory: ")
|
|
self.dataDirEdit = QLineEdit()
|
|
self.dataDirEdit.setText(dataroot)
|
|
self.dataDirEdit.selectAll()
|
|
structureLabel = QLabel("data structure: ")
|
|
self.structureSelect = QComboBox()
|
|
|
|
from pylot.core.util.structure import DATASTRUCTURE
|
|
|
|
self.structureSelect.addItems(DATASTRUCTURE.keys())
|
|
|
|
layout = QGridLayout()
|
|
layout.addWidget(dataDirLabel, 0, 0)
|
|
layout.addWidget(self.dataDirEdit, 0, 1)
|
|
layout.addWidget(fullNameLabel, 1, 0)
|
|
layout.addWidget(self.fullNameEdit, 1, 1)
|
|
layout.addWidget(structureLabel, 2, 0)
|
|
layout.addWidget(self.structureSelect, 2, 1)
|
|
|
|
self.setLayout(layout)
|
|
|
|
def getValues(self):
|
|
values = {}
|
|
values["data/dataRoot"] = self.dataDirEdit.text()
|
|
values["user/FullName"] = self.fullNameEdit.text()
|
|
values["data/Structure"] = self.structureSelect.currentText()
|
|
return values
|
|
|
|
|
|
class OutputsTab(PropTab):
|
|
|
|
def __init__(self, parent=None):
|
|
super(OutputsTab, self).__init__(parent)
|
|
|
|
settings = QSettings()
|
|
curval = settings.value("output/Format", None)
|
|
|
|
eventOutputLabel = QLabel("event ouput format")
|
|
self.eventOutputComboBox = QComboBox()
|
|
eventoutputformats = OUTPUTFORMATS.keys()
|
|
self.eventOutputComboBox.addItems(eventoutputformats)
|
|
|
|
if curval is None:
|
|
ind = 0
|
|
else:
|
|
ind = self.eventOutputComboBox.findText(curval)
|
|
|
|
self.eventOutputComboBox.setCurrentIndex(ind)
|
|
layout = QGridLayout()
|
|
layout.addWidget(eventOutputLabel, 0, 0)
|
|
layout.addWidget(self.eventOutputComboBox, 0, 1)
|
|
|
|
self.setLayout(layout)
|
|
|
|
def getValues(self):
|
|
values = {}
|
|
values["output/Format"] = self.eventOutputComboBox.currentText()
|
|
return values
|
|
|
|
class PhasesTab(PropTab):
|
|
|
|
def __init__(self, parent=None):
|
|
super(PhasesTab, self).__init__(parent)
|
|
|
|
pass
|
|
|
|
|
|
class GraphicsTab(PropTab):
|
|
|
|
def __init__(self, parent=None):
|
|
super(GraphicsTab, self).__init__(parent)
|
|
|
|
pass
|
|
|
|
|
|
class NewEventDlg(QDialog):
|
|
def __init__(self, parent=None, titleString="Create a new event"):
|
|
"""
|
|
QDialog object utilized to create a new event manually.
|
|
"""
|
|
super(NewEventDlg, self).__init__()
|
|
|
|
self.setupUI()
|
|
|
|
now = datetime.datetime.now()
|
|
self.eventTimeEdit.setDateTime(now)
|
|
# event dates in the future are forbidden
|
|
self.eventTimeEdit.setMaximumDateTime(now)
|
|
|
|
self.latEdit.setText("51.0000")
|
|
self.lonEdit.setText("7.0000")
|
|
self.depEdit.setText("10.0")
|
|
|
|
self.buttonBox.accepted.connect(self.accept)
|
|
self.buttonBox.rejected.connect(self.reject)
|
|
|
|
def getValues(self):
|
|
return {'origintime' : self.eventTimeEdit.dateTime().toPython(),
|
|
'latitude' : self.latEdit.text(),
|
|
'longitude' : self.lonEdit.text(),
|
|
'depth' : self.depEdit.text()}
|
|
|
|
def setupUI(self):
|
|
|
|
# create widget objects
|
|
timeLabel = QLabel()
|
|
timeLabel.setText("Select time: ")
|
|
self.eventTimeEdit = QDateTimeEdit()
|
|
latLabel = QLabel()
|
|
latLabel.setText("Latitude: ")
|
|
self.latEdit = QLineEdit()
|
|
lonLabel = QLabel()
|
|
lonLabel.setText("Longitude: ")
|
|
self.lonEdit = QLineEdit()
|
|
depLabel = QLabel()
|
|
depLabel.setText("Depth: ")
|
|
self.depEdit = QLineEdit()
|
|
|
|
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok |
|
|
QDialogButtonBox.Cancel)
|
|
|
|
grid = QGridLayout()
|
|
grid.addWidget(timeLabel, 0, 0)
|
|
grid.addWidget(self.eventTimeEdit, 0, 1)
|
|
grid.addWidget(latLabel, 1, 0)
|
|
grid.addWidget(self.latEdit, 1, 1)
|
|
grid.addWidget(lonLabel, 2, 0)
|
|
grid.addWidget(self.lonEdit, 2, 1)
|
|
grid.addWidget(depLabel, 3, 0)
|
|
grid.addWidget(self.depEdit, 3, 1)
|
|
grid.addWidget(self.buttonBox, 4, 1)
|
|
|
|
self.setLayout(grid)
|
|
|
|
class FilterOptionsDialog(QDialog):
|
|
|
|
def __init__(self, parent=None, titleString="Filter options",
|
|
filterOptions=None):
|
|
"""
|
|
PyLoT widget FilterOptionsDialog is a QDialog object. It is an UI to
|
|
adjust parameters for filtering seismic data.
|
|
"""
|
|
super(FilterOptionsDialog, self).__init__()
|
|
|
|
if parent is not None:
|
|
self.filterOptions = parent.getFilterOptions()
|
|
elif filterOptions is not None:
|
|
self.filterOptions = FilterOptions(filterOptions)
|
|
else:
|
|
self.filterOptions = FilterOptions()
|
|
|
|
_enable = True
|
|
if self.getFilterOptions().getFilterType() is None:
|
|
_enable = False
|
|
|
|
self.freqminLabel = QLabel()
|
|
self.freqminLabel.setText("minimum:")
|
|
self.freqminSpinBox = QDoubleSpinBox()
|
|
self.freqminSpinBox.setRange(5e-7, 1e6)
|
|
self.freqminSpinBox.setDecimals(2)
|
|
self.freqminSpinBox.setSuffix(' Hz')
|
|
self.freqminSpinBox.setEnabled(_enable)
|
|
|
|
self.freqmaxLabel = QLabel()
|
|
self.freqmaxLabel.setText("maximum:")
|
|
self.freqmaxSpinBox = QDoubleSpinBox()
|
|
self.freqmaxSpinBox.setRange(5e-7, 1e6)
|
|
self.freqmaxSpinBox.setDecimals(2)
|
|
self.freqmaxSpinBox.setSuffix(' Hz')
|
|
|
|
if _enable:
|
|
self.freqminSpinBox.setValue(self.getFilterOptions().getFreq()[0])
|
|
if self.getFilterOptions().getFilterType() in ['bandpass', 'bandstop']:
|
|
self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq()[1])
|
|
else:
|
|
try:
|
|
self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq())
|
|
self.freqminSpinBox.setValue(self.getFilterOptions().getFreq())
|
|
except TypeError, e:
|
|
print e
|
|
self.freqmaxSpinBox.setValue(1.)
|
|
self.freqminSpinBox.setValue(.1)
|
|
|
|
typeOptions = [None, "bandpass", "bandstop", "lowpass", "highpass"]
|
|
|
|
self.orderLabel = QLabel()
|
|
self.orderLabel.setText("Order:")
|
|
self.orderSpinBox = QSpinBox()
|
|
self.orderSpinBox.setRange(2, 10)
|
|
self.orderSpinBox.setEnabled(_enable)
|
|
self.selectTypeLabel = QLabel()
|
|
self.selectTypeLabel.setText("Select filter type:")
|
|
self.selectTypeCombo = QComboBox()
|
|
self.selectTypeCombo.addItems(typeOptions)
|
|
self.selectTypeLayout = QVBoxLayout()
|
|
self.selectTypeLayout.addWidget(self.orderLabel)
|
|
self.selectTypeLayout.addWidget(self.orderSpinBox)
|
|
self.selectTypeLayout.addWidget(self.selectTypeLabel)
|
|
self.selectTypeLayout.addWidget(self.selectTypeCombo)
|
|
|
|
self.freqGroupBox = QGroupBox("Frequency range")
|
|
self.freqGroupLayout = QGridLayout()
|
|
self.freqGroupLayout.addWidget(self.freqminLabel, 0, 0)
|
|
self.freqGroupLayout.addWidget(self.freqminSpinBox, 0, 1)
|
|
self.freqGroupLayout.addWidget(self.freqmaxLabel, 1, 0)
|
|
self.freqGroupLayout.addWidget(self.freqmaxSpinBox, 1, 1)
|
|
self.freqGroupBox.setLayout(self.freqGroupLayout)
|
|
|
|
self.freqmaxSpinBox.setEnabled(_enable)
|
|
|
|
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
|
|
QDialogButtonBox.Cancel)
|
|
|
|
grid = QGridLayout()
|
|
grid.addWidget(self.freqGroupBox, 0, 2, 1, 2)
|
|
grid.addLayout(self.selectTypeLayout, 1, 2, 1, 2)
|
|
grid.addWidget(self.buttonBox, 2, 2, 1, 2)
|
|
|
|
self.setLayout(grid)
|
|
|
|
self.freqminSpinBox.valueChanged.connect(self.updateUi)
|
|
self.freqmaxSpinBox.valueChanged.connect(self.updateUi)
|
|
self.orderSpinBox.valueChanged.connect(self.updateUi)
|
|
self.selectTypeCombo.currentIndexChanged.connect(self.updateUi)
|
|
self.buttonBox.accepted.connect(self.accept)
|
|
self.buttonBox.rejected.connect(self.reject)
|
|
|
|
|
|
def updateUi(self):
|
|
_enable = False
|
|
if self.selectTypeCombo.currentText() not in ['bandpass', 'bandstop']:
|
|
self.freqminLabel.setText("cutoff:")
|
|
self.freqmaxSpinBox.setValue(self.freqminSpinBox.value())
|
|
else:
|
|
_enable = True
|
|
self.freqminLabel.setText("minimum:")
|
|
|
|
self.freqmaxLabel.setEnabled(_enable)
|
|
self.freqmaxSpinBox.setEnabled(_enable)
|
|
|
|
|
|
self.getFilterOptions().setFilterType(self.selectTypeCombo.currentText())
|
|
freq = []
|
|
freq.append(self.freqminSpinBox.value())
|
|
if _enable:
|
|
if self.freqminSpinBox.value() > self.freqmaxSpinBox.value():
|
|
QMessageBox.warning(self, "Value error",
|
|
"Maximum frequency must be at least the "
|
|
"same value as minimum frequency (notch)!")
|
|
self.freqmaxSpinBox.setValue(self.freqminSpinBox.value())
|
|
self.freqmaxSpinBox.selectAll()
|
|
self.freqmaxSpinBox.setFocus()
|
|
return
|
|
freq.append(self.freqmaxSpinBox.value())
|
|
self.getFilterOptions().setFreq(freq)
|
|
self.getFilterOptions().setOrder(self.orderSpinBox.value())
|
|
|
|
def getFilterOptions(self):
|
|
return self.filterOptions
|
|
|
|
def accept(self):
|
|
self.updateUi()
|
|
QDialog.accept(self)
|
|
|
|
|
|
class LoadDataDlg(QDialog):
|
|
|
|
def __init__(self, parent=None):
|
|
super(LoadDataDlg, self).__init__(parent)
|
|
|
|
pass
|
|
|
|
|
|
class HelpForm(QDialog):
|
|
|
|
def __init__(self, page=QUrl('https://ariadne.geophysik.rub.de/trac/PyLoT'), parent=None):
|
|
super(HelpForm, self).__init__(parent)
|
|
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
self.setAttribute(Qt.WA_GroupLeader)
|
|
|
|
backAction = QAction(QIcon(":/back.png"), "&Back", self)
|
|
backAction.setShortcut(QKeySequence.Back)
|
|
homeAction = QAction(QIcon(":/home.png"), "&Home", self)
|
|
homeAction.setShortcut("Home")
|
|
self.pageLabel = QLabel()
|
|
|
|
toolBar = QToolBar()
|
|
toolBar.addAction(backAction)
|
|
toolBar.addAction(homeAction)
|
|
toolBar.addWidget(self.pageLabel)
|
|
self.webBrowser = QWebView()
|
|
self.webBrowser.load(page)
|
|
|
|
layout = QVBoxLayout()
|
|
layout.addWidget(toolBar)
|
|
layout.addWidget(self.webBrowser, 1)
|
|
self.setLayout(layout)
|
|
|
|
self.connect(backAction, Signal("triggered()"),
|
|
self.webBrowser, Slot("backward()"))
|
|
self.connect(homeAction, Signal("triggered()"),
|
|
self.webBrowser, Slot("home()"))
|
|
self.connect(self.webBrowser, Signal("sourceChanged(QUrl)"),
|
|
self.updatePageTitle)
|
|
|
|
self.resize(400, 600)
|
|
self.setWindowTitle("{0} Help".format(QApplication.applicationName()))
|
|
|
|
def updatePageTitle(self):
|
|
self.pageLabel.setText(self.webBrowser.documentTitle())
|