Merge branch 'devFilterWidget' into develop

This commit is contained in:
Sebastian Wehling-Benatelli 2014-12-17 07:53:32 +01:00
commit e6301af2bb
9 changed files with 188 additions and 98 deletions

View File

@ -23,6 +23,7 @@ https://www.iconfinder.com/iconsets/flavour
(http://www.gnu.org/copyleft/lesser.html)
"""
import os
import sys
from PySide.QtCore import *
@ -35,8 +36,10 @@ from pylot.core.read import (Data,
from pylot.core.util import FILTERDEFAULTS
from pylot.core.util import fnConstructor
from pylot.core.util import checkurl
from pylot.core.util import layoutStationButtons
from pylot.core.util import (FilterOptionsDialog,
MPLWidget,
PropertiesDlg,
HelpForm)
@ -46,31 +49,39 @@ __version__ = _getVersionString()
class MainWindow(QMainWindow):
closing = Signal()
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
settings = QSettings()
self.recentEvents = settings.value("recentEvents", [])
self.setWindowTitle("PyLoT - do seismic processing the pythonic way")
if settings.value("user/FullName", None) is None:
fulluser = QInputDialog.getText(self, "Enter Name:", "Full name")
settings.setValue("user/FullName", fulluser)
settings.setValue("user/Login", os.getlogin())
settings.sync()
self.recentEvents = settings.value("data/recentEvents", [])
self.setWindowTitle("PyLoT - do seismic processing the python way")
self.setWindowIcon(QIcon(":/icon.ico"))
self.seismicPhase = str(settings.value("phase", "P"))
if settings.value("dataRoot", None) is None:
dirname = QFileDialog().getExistingDirectory()
settings.setValue("dataRoot", dirname)
if settings.value("data/dataRoot", None) is None:
dirname = QFileDialog().getExistingDirectory(caption = 'Choose data root ...')
settings.setValue("data/dataRoot", dirname)
settings.sync()
# initialize filter parameter
filterOptionsP = FILTERDEFAULTS['P']
filterOptionsS = FILTERDEFAULTS['S']
print filterOptionsP, "\n", filterOptionsS
# print filterOptionsP, "\n", filterOptionsS
self.filterOptionsP = FilterOptions(**filterOptionsP)
self.filterOptionsS = FilterOptions(**filterOptionsS)
# initialize data
self.data = None
self.dirty = False
self.loadData()
self.updateFilterOptions()
print self.filteroptions
# print self.filteroptions
try:
self.startTime = min([tr.stats.starttime for tr in self.data.wfdata])
except:
@ -103,7 +114,7 @@ class MainWindow(QMainWindow):
self.fileMenu.clear()
self.addActions(self.fileMenu, self.fileMenuActions[:-1])
current = self.data.evtdata.getEventID()
current = self.data.evtdata.getID()
recentEvents = []
for eventID in self.recentEvents:
fname = fnConstructor(eventID)
@ -124,13 +135,16 @@ class MainWindow(QMainWindow):
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.fileMenuActions[-1])
def loadData(self, fname=None):
if fname is None:
action = self.sender()
if isinstance(action, QAction):
if action.data() is None:
fname = QFileDialog()
filt = """Supported event formats (*.mat *.qml *.xml *.kor
*.evt)"""
caption = 'Select event to open'
fname = QFileDialog().getOpenFileName(self, caption=caption,
filter=filt)
else:
fname = unicode(action.data().toString())
if not self.okToContinue():
@ -141,7 +155,7 @@ class MainWindow(QMainWindow):
self.data = Data(evtdata=fname)
def saveData(self):
pass
return True
def getComponent(self):
return self
@ -158,13 +172,17 @@ class MainWindow(QMainWindow):
xlab = self.startTime.strftime('seconds since %d %b %Y %H:%M:%S (%Z)')
plottitle = self._getCurrentPlotType()
_widget = QWidget()
_layout = QHBoxLayout()
# create central matplotlib figure widget
self.DataPlot = MPLWidget(parent=self,
xlabel=xlab,
ylabel=None,
title=plottitle)
self.setCentralWidget(self.getDataWidget())
statsButtons = layoutStationButtons(self.getData(), self.getComponent())
_layout.addLayout(statsButtons)
_layout.addWidget(self.DataPlot)
openIcon = self.style().standardIcon(QStyle.SP_DirOpenIcon)
quitIcon = self.style().standardIcon(QStyle.SP_MediaStop)
@ -176,6 +194,9 @@ class MainWindow(QMainWindow):
saveEventAction = self.createAction("&Save event ...", self.saveData,
QKeySequence.Save, saveIcon,
"Save actual event data.")
prefsEventAction = self.createAction("Preferences", self.PyLoTprefs,
QKeySequence.Preferences, None,
"Edit PyLoT app preferences.")
quitAction = self.createAction("&Quit",
QCoreApplication.instance().quit,
QKeySequence.Close, quitIcon,
@ -201,6 +222,7 @@ class MainWindow(QMainWindow):
"Print waveform overview.")
self.fileMenu = self.menuBar().addMenu('&File')
self.fileMenuActions = (openEventAction, saveEventAction, None,
prefsEventAction, None,
quitAction)
self.fileMenu.aboutToShow.connect(self.updateFileMenu)
@ -219,14 +241,11 @@ class MainWindow(QMainWindow):
status.addPermanentWidget(self.eventLabel)
status.showMessage("Ready", 500)
# statLayout = layoutStationButtons(self.getData(), self.getComponent())
# dataLayout = self.getDataWidget()
# maingrid = QGridLayout()
# maingrid.setSpacing(10)
# maingrid.addLayout(statLayout, 0, 0)
# maingrid.addWidget(self.getDataWidget(), 0, 1)
# self.setLayout(maingrid)
statsButtons = layoutStationButtons(self.getData(), self.getComponent())
_layout.addLayout(statsButtons)
_layout.addWidget(self.DataPlot)
_widget.setLayout(_layout)
self.setCentralWidget(_widget)
def okToContinue(self):
if self.dirty:
@ -237,19 +256,29 @@ class MainWindow(QMainWindow):
pass #self.data.plotData(self.DataPlot)
def filterData(self):
pass
if self.getData():
kwargs = {}
freq = self.filteroptions.getFreq()
if len(freq) > 1:
kwargs['freqmin'] = freq[0]
kwargs['freqmax'] = freq[1]
else:
kwargs['freq'] = freq
kwargs['type'] = self.filteroptions.getFilterType()
#kwargs['order'] = self.filteroptions.getOrder()
self.data.filter(**kwargs)
def adjustFilterOptions(self):
filterOptions = None
filteroptions = None
fstring = "Filter Options ({0})".format(self.getSeismicPhase())
filterDlg = FilterOptionsDialog(titleString=fstring,
parent=self,
filterOptions=self.getFilterOptions())
if filterDlg.exec_():
filterOptions = filterDlg.getFilterOptions()
filteroptions = filterDlg.getFilterOptions()
assert isinstance(filterOptions, FilterOptions)
self.setFilterOptions(filterOptions)
assert isinstance(filteroptions, FilterOptions)
self.setFilterOptions(filteroptions)
def getFilterOptions(self):
return self.filteroptions
@ -283,12 +312,30 @@ class MainWindow(QMainWindow):
def updateStatus(self, message):
self.statusBar().showMessage(message, 5000)
if self.getData() is not None:
if not self.getData().isNew():
self.setWindowTitle("PyLoT - processing event %s[*]" % self.getData().getID())
elif self.getData().isNew():
self.setWindowTitle("PyLoT - New event [*]")
else:
self.setWindowTitle("PyLoT - seismic processing the python way[*]")
self.setWindowTitle("PyLoT - seismic processing the python way[*]")
self.setWindowModified(self.dirty)
self.statusBar().showMessage(message, 5000)
def printEvent(self):
pass
def closeEvent(self):
return self.saveData()
def closeEvent(self, event):
if self.okToContinue():
self.closing.emit()
QMainWindow.closeEvent(self, event)
def PyLoTprefs(self):
props = PropertiesDlg(self)
if props.exec_():
return
def helpHelp(self):
if checkurl():
@ -313,7 +360,7 @@ def main():
# Show main window and run the app
pylot_form.show()
sys.exit(pylot_app.exec_())
pylot_app.exec_()
if __name__ == "__main__":
main()
sys.exit(main())

View File

@ -1 +1 @@
e6ac-dirty
ef8b-dirty

View File

@ -1,5 +1,6 @@
from pylot.core.read.data import (Data,
GenericDataStructure,
SeiscompDataStructure)
from pylot.core.read.inputs import (AutoPickParameter,
FilterOptions)
from pylot.core.read.inputs import AutoPickParameter
from pylot.core.read.inputs import FilterOptions
from pylot.core.read.data import Data
from pylot.core.read.data import GenericDataStructure
from pylot.core.read.data import SeiscompDataStructure

View File

@ -27,7 +27,10 @@ class Data(object):
def __init__(self, parent=None, evtdata=None):
try:
self.wfdata = read()
if parent:
self.wfdata = read(parent.fnames)
else:
self.wfdata = read()
except IOError, e:
msg = 'An I/O error occured while loading data!'
inform = 'Variable wfdata will be empty.'
@ -44,6 +47,7 @@ class Data(object):
self.wfdata = Stream()
else:
self.wfdata = Stream()
self.newevent = False
if evtdata is not None and isinstance(evtdata, Event):
self.evtdata = evtdata
elif evtdata is not None and not evtdata.endswith('.mat'):
@ -52,17 +56,27 @@ class Data(object):
elif evtdata is not None:
cat = readMatPhases(evtdata)
else: # create an empty Event object
self.newevent = True
self.evtdata = Event()
self.orig = self.wfdata.copy()
def isNew(self):
return self.newevent
def readMatPhases(self, fname):
pass
def exportEvent(self, fnout=None, evtformat='QUAKEML'):
from pylot.core.util.defaults import OUTPUTFORMATS
if evtformat.strip() not in OUTPUTFORMATS.values():
evtformat = OUTPUTFORMATS.values()[0]
if fnout is None:
fnout = self.evtdata.getEventID()
ID = self.evtdata.getEventID()
# handle forbidden filenames especially on windows systems
fnout = fnConstructor(fnout)
fnout = fnConstructor(ID)
evtformat = evtformat.upper().strip()
@ -77,10 +91,9 @@ class Data(object):
not implemented: {1}'''.format(evtformat, e))
def plotData(self, widget):
pass #axes = widget.axes
def getEventID(self):
def getID(self):
try:
return self.evtdata.get('resource_id').id
except:
@ -123,10 +136,19 @@ class SeiscompDataStructure(object):
:type sdate, edate: str or UTCDateTime or None
'''
# Data type options
__typeOptions = {'waveform': 'D', # Waveform data
'detect': 'E', # Detection data
'log': 'L', # Log data
'timing': 'T', # Timing data
'calib': 'C', # Calibration data
'resp': 'R', # Response data
'opaque': 'O' # Opaque data
}
def __init__(self, dataType='waveform', sdate=None, edate=None, **kwargs):
# imports
from obspy.core import UTCDateTime
import numpy as np
def checkDate(date):
if not isinstance(date, UTCDateTime):
@ -140,7 +162,9 @@ class SeiscompDataStructure(object):
edate = UTCDateTime(edate)
except TypeError:
edate = UTCDateTime()
sdate = edate - np.pi*1e7/2
halfyear = UTCDateTime('1970-07-01')
sdate = UTCDateTime(edate - halfyear)
del halfyear
year = ''
if not edate.year == sdate.year:
@ -149,17 +173,7 @@ class SeiscompDataStructure(object):
year += '{0:04d},'.format(sdate.year+yr)
year = '{'+year[:-1]+'}'
else:
year = '{0:04d},'.format(sdate.year)
# Data type options
self.__typeOptions = {'waveform': 'D', # Waveform data
'detect': 'E', # Detection data
'log': 'L', # Log data
'timing': 'T', # Timing data
'calib': 'C', # Calibration data
'resp': 'R', # Response data
'opaque': 'O' # Opaque data
}
year = '{0:04d}'.format(sdate.year)
if dataType in self.__typeOptions.keys():
self.dataType = dataType
@ -177,7 +191,7 @@ class SeiscompDataStructure(object):
'NET': '??', # up to 8 characters
'STA': '????', # up to 8 characters
'CHAN': 'HH?', # up to 8 characters
'TYPE': self._getType(), # 1 character
'TYPE': self.getType(), # 1 character
'LOC': '', # up to 8 characters
'DAY': '{0:03d}'.format(sdate.julday) # 3 digits
}
@ -187,10 +201,14 @@ class SeiscompDataStructure(object):
if kwargs and isinstance(kwargs, dict):
for key, value in kwargs.iteritems():
key = str(key)
value = str(value)
if type(value) not in (str, int, float):
for n, val in enumerate(value):
value[n] = str(val)
else:
value = str(value)
try:
if key in self.__sdsFields.keys():
self.__sdsFields[key] = str(value)
if key in self.getSDSFields().keys():
self.getSDSFields()[key] = value
else:
raise KeyError('unknown SDS wildcard: %s.' % key)
except KeyError, e:
@ -200,16 +218,19 @@ class SeiscompDataStructure(object):
errmsg += '%s; desired value was: %s\n' % (e, value)
print errmsg
def _getType(self):
def getType(self):
return self.__typeOptions[self.dataType]
def getSDSFields(self):
return self.__sdsFields
def expandDataPath(self):
fullChan = '{0}.{1}'.format(self.__sdsFields['CHAN'], self._getType())
dataPath = os.path.join(self.__sdsFields['SDSdir'],
self.__sdsFields['YEAR'],
self.__sdsFields['NET'],
self.__sdsFields['STA'],
fullChan = '{0}.{1}'.format(self.getSDSFields()['CHAN'], self.getType())
dataPath = os.path.join(self.getSDSFields()['SDSdir'],
self.getSDSFields()['YEAR'],
self.getSDSFields()['NET'],
self.getSDSFields()['STA'],
fullChan,
'*{0}'.format(self.__sdsFields['DAY'])
'*{0}'.format(self.getSDSFields()['DAY'])
)
return dataPath

View File

@ -165,34 +165,34 @@ class FilterOptions(object):
'''
def __init__(self, filtertype='bandpass', freq=[2., 5.], order=3,
**kwargs):
self.setFilterType(filtertype)
self.setFreq(freq)
self.setOrder(order)
self._order = order
self._filtertype = filtertype
self._freq = freq
def __str__(self):
hrs = '''\n\tFilter parameter:\n
Type:\t\t{ftype}\n
Frequencies:\t{freq}\n
Order:\t\t{order}\n
'''.format(ftype=self.getFilterType(),
freq=self.getFreq(),
order=self.getOrder())
'''.format(ftype=self.getFilterType,
freq=self.getFreq,
order=self.getOrder)
return hrs
def getFreq(self):
return self.freq
return self.__getattribute__('_freq')
def setFreq(self, freq):
self.freq = freq
self.__setattr__('_freq', freq)
def getOrder(self):
return self.order
return self.__getattribute__('_order')
def setOrder(self, order):
self.order = order
self.__setattr__('_order', order)
def getFilterType(self):
return self.filterType
return self.__getattribute__('_filtertype')
def setFilterType(self, filtertype):
self.filterType = filtertype
self.__setattr__('_filtertype', filtertype)

View File

@ -12,3 +12,5 @@ FILTERDEFAULTS = {'P': {'filtertype': None,
'S': {'filtertype': 'bandpass',
'order': '4',
'freq': [.5, 5]}}
OUTPUTFORMATS = {'QuakeML':'QUAKEML', 'VelEst':'VELEST'}

View File

@ -21,7 +21,7 @@ def layoutStationButtons(data, comp):
stationButtons.append(QPushButton('%s'.format(stat)))
except:
for n in range(5):
stationButtons.append(QPushButton('ST%02d'.format(n)))
stationButtons.append(QPushButton('ST{0:02d}'.format(n+1)))
for button in stationButtons:
layout.addWidget(button)
return layout

View File

@ -31,12 +31,14 @@ from PySide.QtGui import (QAction,
QToolBar,
QVBoxLayout,
QWidget)
from PySide.QtCore import (Qt,
from PySide.QtCore import (QSettings,
Qt,
QUrl,
SIGNAL,
SLOT)
from PySide.QtWebKit import QWebView
from pylot.core.read import FilterOptions
from pylot.core.util.defaults import OUTPUTFORMATS
class MPLWidget(FigureCanvasQTAgg):
@ -71,17 +73,17 @@ class PropertiesDlg(QDialog):
self.setWindowTitle("{0} Properties".format(appName))
tabWidget = QTabWidget()
tabWidget.addTab(InputsTab(self), "Inputs")
tabWidget.addTab(OutputsTab(self), "Outputs")
tabWidget.addTab(PhasesTab(self), "Phases")
tabWidget.addTab(GraphicsTab(self), "Graphics")
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(tabWidget)
layout.addWidget(self.tabWidget)
layout.addWidget(self.buttonBox)
self.setLayout(layout)
@ -91,23 +93,40 @@ class PropertiesDlg(QDialog):
SIGNAL("clicked()"), self.apply)
self.connect(self.buttonBox, SIGNAL("rejected()"),
self, SLOT("reject()"))
pass
def apply(self):
pass
settings = QSettings()
for widint in range(self.tabWidget.count()):
curwid = self.tabWidget.widget(widint)
values = self.getValues(curwid)
settings.setValue()
class InputsTab(QWidget):
def __init__(self, parent=None):
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))
parent.fullNameEdit = QLineEdit()
parent.fullNameEdit.setText(fulluser)
dataroot = settings.value("data/dataRoot")
dataDirLabel = QLabel("data directory:")
dataDirEdit = QLineEdit()
parent.dataDirEdit = QLineEdit()
parent.dataDirEdit.setText(dataroot)
parent.dataDirEdit.selectAll()
layout = QGridLayout()
layout.addWidget(dataDirLabel, 0, 0)
layout.addWidget(dataDirEdit, 0, 1)
layout.addWidget(parent.dataDirEdit, 0, 1)
layout.addWidget(fullNameLabel, 1, 0)
layout.addWidget(parent.fullNameEdit, 1, 1)
self.setLayout(layout)
@ -119,7 +138,7 @@ class OutputsTab(QWidget):
eventOutputLabel = QLabel("event ouput format")
eventOutputComboBox = QComboBox()
eventoutputformats = ["QuakeML", "VelEst"]
eventoutputformats = OUTPUTFORMATS.keys()
eventOutputComboBox.addItems(eventoutputformats)
layout = QGridLayout()
@ -166,7 +185,7 @@ class FilterOptionsDialog(QDialog):
self.freqminSpinBox.setRange(5e-7, 1e6)
self.freqminSpinBox.setDecimals(2)
self.freqminSpinBox.setSuffix(' Hz')
self.freqminSpinBox.setValue(self.getFilterOptions().getFreq()[0])
self.freqminSpinBox.setValue(self.getFilterOptions().getFreq[0])
self.freqmaxLabel = QLabel()
self.freqmaxLabel.setText("maximum:")
self.freqmaxSpinBox = QDoubleSpinBox()
@ -174,7 +193,7 @@ class FilterOptionsDialog(QDialog):
self.freqmaxSpinBox.setDecimals(2)
self.freqmaxSpinBox.setSuffix(' Hz')
if self.filterOptions.filterType in ['bandpass', 'bandstop']:
self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq()[1])
self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq[1])
typeOptions = ["bandpass", "bandstop", "lowpass", "highpass"]

File diff suppressed because one or more lines are too long