28 Commits

Author SHA1 Message Date
65dbaad446 [update] adding possibility to display other waveform data (e.g. denoised/synthetic) together with genuine data for comparison 2024-03-22 17:12:04 +01:00
5b97d51517 [minor] mpl.figure.canvas.draw -> draw_idle 2024-03-22 17:12:04 +01:00
f03ace75e7 [bugfix] QWidget.show() killed figure axis dimensions creating unexpected error of fig.aspect=0 when creating colorbar inset_axes in Python 3.11 2024-03-22 17:10:04 +01:00
9c78471d20 [bugfix] header resize method renamed in QT5 2024-03-22 15:34:05 +01:00
09d2fb1022 [bugfix] pt2 of fmpicker fix, make sure to also copy stream in autoPyLoT
closes #24
2023-08-24 12:55:30 +02:00
3cae6d3a78 [bugfix] use copies of wfdata when calling fmpicker to prevent modification of actual data used inside GUI 2023-08-24 11:28:30 +02:00
2e85d083a3 [bugfix] do not call calcsourcespec if incidence angle is outside bounds (for whatever reason) 2023-08-24 11:27:30 +02:00
ba4e6cfe50 [bugfix] bin directory + /bin creates "/bin/bin". Also it is not taken care of os compatibility and also compatibility with existing code (line 86ff was useless after recent change in line 85) 2023-08-23 14:48:21 +02:00
1f16d01648 [minor] give more precise user warning if no pick channel was selected 2023-08-23 09:38:16 +02:00
3069e7d526 [minor] commented - possibly unnecessary - line of code that created an error when using old metadata Parser 2023-08-22 15:53:49 +02:00
a9aeb7aaa3 [bugfix] set simple phase hint (P or S) 2023-08-22 15:53:49 +02:00
b9adb182ad [bugfix] could not handle asterisk-marked events when opening tune-autopicker 2023-08-22 15:53:49 +02:00
a823eb2440 [workaround] using explicit Exception definition without a special handling does not make sense. Function broke on other errors in polyfit. Still might need fixes in the two lines above the "except" block(s). 2023-08-22 15:53:49 +02:00
486e3dc9c3 Merge pull request 'Disabled button in case flag is false' (#31) from disable-show-log-widget into develop
Reviewed-on: #31
2023-08-22 12:05:33 +02:00
8d356050d7 [update] corrected original authors of PILOT 2023-08-22 12:01:51 +02:00
43cab3767f [Bugfix] fixxed wrong check for taupymodel 2023-06-27 08:04:00 +02:00
a1f6c5ffca Bugfixxes, spectogram tab wip 2023-06-14 13:11:54 +02:00
e4e7afa996 Minor changes to adjust to python 3. Temporary Fix for file exporting not working properly. WIP spectrogram view. 2023-04-27 10:24:55 +02:00
0634d24814 fix: disabled button in case flag is false
The button was not disabled in case the flag variable was false. The get_Bool function was renamed and improved to also work in case in the input variable is of type int or float.

Additionally, the environment file was corrected to also work for macOS installations with ARM architecture.
2023-04-06 16:40:20 +02:00
43c2b97b3d Small changes 2023-01-24 11:45:12 +01:00
ann-christin
8d94440e77 [bugfix] logwidget always initiated 2022-11-14 14:14:59 +01:00
ann-christin
66b7dea706 [update] pylot.in no longer mandatory 2022-11-14 14:14:12 +01:00
ann-christin
ebf6d4806a [minor] reformating 2022-11-14 11:52:25 +01:00
ann-christin
207d0b3a6f [update] directly pass args from arg parser 2022-11-14 11:18:15 +01:00
ann-christin
3b3bbc29d1 Merge remote-tracking branch 'origin/develop' into develop 2022-11-14 10:30:38 +01:00
ann-christin
a8c6f4c972 [reformat] spell checking 2022-08-25 15:31:08 +02:00
ann-christin
0d91f9e3fe update github link 2022-08-25 14:03:05 +02:00
ann-christin
494d281d61 update github link 2022-08-25 14:00:37 +02:00
17 changed files with 495 additions and 270 deletions

168
PyLoT.py
View File

@@ -76,7 +76,7 @@ from pylot.core.util.utils import fnConstructor, getLogin, \
full_range, readFilterInformation, pick_color_plt, \ full_range, readFilterInformation, pick_color_plt, \
pick_linestyle_plt, identifyPhaseID, excludeQualityClasses, \ pick_linestyle_plt, identifyPhaseID, excludeQualityClasses, \
transform_colors_mpl, transform_colors_mpl_str, getAutoFilteroptions, check_all_obspy, \ transform_colors_mpl, transform_colors_mpl_str, getAutoFilteroptions, check_all_obspy, \
check_all_pylot, get_Bool, get_None check_all_pylot, get_bool, get_None
from pylot.core.util.gui import make_pen from pylot.core.util.gui import make_pen
from pylot.core.util.event import Event from pylot.core.util.event import Event
from pylot.core.io.location import create_creation_info, create_event from pylot.core.io.location import create_creation_info, create_event
@@ -84,7 +84,7 @@ from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
PylotCanvas, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \ PylotCanvas, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, CanvasWidget, AutoPickWidget, \ ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, CanvasWidget, AutoPickWidget, \
CompareEventsWidget, ProgressBarWidget, AddMetadataWidget, SingleTextLineDialog, LogWidget, PickQualitiesFromXml, \ CompareEventsWidget, ProgressBarWidget, AddMetadataWidget, SingleTextLineDialog, LogWidget, PickQualitiesFromXml, \
SourceSpecWindow, ChooseWaveFormWindow SourceSpecWindow, ChooseWaveFormWindow, SpectrogramTab
from pylot.core.util.array_map import Array_map from pylot.core.util.array_map import Array_map
from pylot.core.util.structure import DATASTRUCTURE from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker from pylot.core.util.thread import Thread, Worker
@@ -117,17 +117,19 @@ class MainWindow(QMainWindow):
if not infile: if not infile:
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in') infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
print('Using default input file {}'.format(infile)) print('Using default input file {}'.format(infile))
if os.path.isfile(infile) == False: if os.path.isfile(infile) is False:
infile = QFileDialog().getOpenFileName(caption='Choose PyLoT-input file') infile = QFileDialog().getOpenFileName(caption='Choose PyLoT-input file')[0]
if not os.path.exists(infile[0]): if not os.path.exists(infile):
QMessageBox.warning(self, "PyLoT Warning", QMessageBox.warning(self, "PyLoT Warning",
"No PyLoT-input file declared!") "No PyLoT-input file declared! Using default parameters!")
sys.exit(0) infile = None
self.infile = infile[0]
else:
self.infile = infile
self._inputs = PylotParameter(infile) self._inputs = PylotParameter(infile)
if not infile:
self._inputs.reset_defaults()
self.infile = infile
self._props = None self._props = None
self.gain = 1. self.gain = 1.
@@ -179,6 +181,7 @@ class MainWindow(QMainWindow):
self.autodata = Data(self) self.autodata = Data(self)
self.fnames = None self.fnames = None
self.fnames_comp = None
self._stime = None self._stime = None
# track deleted picks for logging # track deleted picks for logging
@@ -481,7 +484,7 @@ class MainWindow(QMainWindow):
"automatic pick " "automatic pick "
"data.", False) "data.", False)
self.compare_action.setEnabled(False) self.compare_action.setEnabled(False)
self.qualities_action = self.createAction(parent=self, text='Show pick qualitites...', self.qualities_action = self.createAction(parent=self, text='Show pick qualities...',
slot=self.pickQualities, shortcut='Alt+Q', slot=self.pickQualities, shortcut='Alt+Q',
icon=qualities_icon, tip='Histogram of pick qualities') icon=qualities_icon, tip='Histogram of pick qualities')
self.qualities_action.setEnabled(False) self.qualities_action.setEnabled(False)
@@ -494,7 +497,6 @@ class MainWindow(QMainWindow):
icon=eventlist_xml_icon, icon=eventlist_xml_icon,
tip='Create an Eventlist from a XML File') tip='Create an Eventlist from a XML File')
self.eventlist_xml_action.setEnabled(False) self.eventlist_xml_action.setEnabled(False)
printAction = self.createAction(self, "&Print event ...", printAction = self.createAction(self, "&Print event ...",
self.show_event_information, QKeySequence.Print, self.show_event_information, QKeySequence.Print,
print_icon, print_icon,
@@ -507,6 +509,8 @@ class MainWindow(QMainWindow):
logAction = self.createAction(self, "&Show Log", self.showLogWidget, logAction = self.createAction(self, "&Show Log", self.showLogWidget,
tip="""Display Log""") tip="""Display Log""")
logAction.setEnabled(use_logwidget)
# create button group for component selection # create button group for component selection
componentGroup = QActionGroup(self) componentGroup = QActionGroup(self)
@@ -696,14 +700,17 @@ class MainWindow(QMainWindow):
wf_tab = QtWidgets.QWidget(self) wf_tab = QtWidgets.QWidget(self)
array_tab = QtWidgets.QWidget(self) array_tab = QtWidgets.QWidget(self)
events_tab = QtWidgets.QWidget(self) events_tab = QtWidgets.QWidget(self)
spectro_tab = QtWidgets.QWidget(self)
# init main widgets layouts # init main widgets layouts
self.wf_layout = QtWidgets.QVBoxLayout() self.wf_layout = QtWidgets.QVBoxLayout()
self.array_layout = QtWidgets.QVBoxLayout() self.array_layout = QtWidgets.QVBoxLayout()
self.events_layout = QtWidgets.QVBoxLayout() self.events_layout = QtWidgets.QVBoxLayout()
self.spectro_layout = QtWidgets.QVBoxLayout()
wf_tab.setLayout(self.wf_layout) wf_tab.setLayout(self.wf_layout)
array_tab.setLayout(self.array_layout) array_tab.setLayout(self.array_layout)
events_tab.setLayout(self.events_layout) events_tab.setLayout(self.events_layout)
spectro_tab.setLayout(self.spectro_layout)
# tighten up layouts inside tabs # tighten up layouts inside tabs
for layout in [self.wf_layout, self.array_layout, self.events_layout]: for layout in [self.wf_layout, self.array_layout, self.events_layout]:
@@ -714,12 +721,14 @@ class MainWindow(QMainWindow):
self.tabs.addTab(wf_tab, 'Waveform Plot') self.tabs.addTab(wf_tab, 'Waveform Plot')
self.tabs.addTab(array_tab, 'Array Map') self.tabs.addTab(array_tab, 'Array Map')
self.tabs.addTab(events_tab, 'Eventlist') self.tabs.addTab(events_tab, 'Eventlist')
self.tabs.addTab(spectro_tab, 'Spectro')
self.wf_layout.addWidget(self.no_data_label) self.wf_layout.addWidget(self.no_data_label)
self.wf_layout.addWidget(self.wf_scroll_area) self.wf_layout.addWidget(self.wf_scroll_area)
self.wf_scroll_area.setWidgetResizable(True) self.wf_scroll_area.setWidgetResizable(True)
self.init_array_tab() self.init_array_tab()
self.init_event_table() self.init_event_table()
self.init_spectro_tab()
self.tabs.setCurrentIndex(0) self.tabs.setCurrentIndex(0)
self.eventLabel = QLabel() self.eventLabel = QLabel()
@@ -732,19 +741,13 @@ class MainWindow(QMainWindow):
_widget.setLayout(self._main_layout) _widget.setLayout(self._main_layout)
_widget.showFullScreen() _widget.showFullScreen()
if use_logwidget: if use_logwidget:
self.logwidget = LogWidget(parent=None) self.logwidget = LogWidget(parent=None)
self.logwidget.show() self.logwidget.show()
self.stdout = self.logwidget.stdout self.stdout = self.logwidget.stdout
self.stderr = self.logwidget.stderr self.stderr = self.logwidget.stderr
sys.stdout = self.stdout
sys.stderr = self.stderr
# Not sure why but the lines above kept messing with the Ouput even with use_logwidget disabled
sys.stdout = self.stdout
sys.stderr = self.stderr
self.setCentralWidget(_widget) self.setCentralWidget(_widget)
# Need to store PickQualities Window somewhere so it doesnt disappear # Need to store PickQualities Window somewhere so it doesnt disappear
@@ -1128,16 +1131,19 @@ class MainWindow(QMainWindow):
else: else:
return return
def getWFFnames_from_eventbox(self, eventbox=None): def getWFFnames_from_eventbox(self, eventbox: str = None, subpath: str = None) -> list:
''' '''
Return waveform filenames from event in eventbox. Return waveform filenames from event in eventbox.
''' '''
# TODO: add dataStructure class for obspyDMT here, this is just a workaround! # TODO: add dataStructure class for obspyDMT here, this is just a workaround!
eventpath = self.get_current_event_path(eventbox) eventpath = self.get_current_event_path(eventbox)
basepath = eventpath.split(os.path.basename(eventpath))[0] if subpath:
eventpath = os.path.join(eventpath, subpath)
if not os.path.isdir(eventpath):
return []
if self.dataStructure: if self.dataStructure:
if not eventpath: if not eventpath:
return return []
fnames = [os.path.join(eventpath, f) for f in os.listdir(eventpath)] fnames = [os.path.join(eventpath, f) for f in os.listdir(eventpath)]
else: else:
raise DatastructureError('not specified') raise DatastructureError('not specified')
@@ -1181,7 +1187,7 @@ class MainWindow(QMainWindow):
''' '''
if not self.project: if not self.project:
self.createNewProject() self.createNewProject()
ed = getExistingDirectories(self, 'Select event directories...') ed = GetExistingDirectories(self, 'Select event directories...')
if ed.exec_(): if ed.exec_():
eventlist = [event for event in ed.selectedFiles() if not event.endswith('EVENTS-INFO')] eventlist = [event for event in ed.selectedFiles() if not event.endswith('EVENTS-INFO')]
basepath = eventlist[0].split(os.path.basename(eventlist[0]))[0] basepath = eventlist[0].split(os.path.basename(eventlist[0]))[0]
@@ -1382,7 +1388,7 @@ class MainWindow(QMainWindow):
index = eventBox.currentIndex() index = eventBox.currentIndex()
tv = QtWidgets.QTableView() tv = QtWidgets.QTableView()
header = tv.horizontalHeader() header = tv.horizontalHeader()
header.setResizeMode(QtWidgets.QHeaderView.ResizeToContents) header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setStretchLastSection(True) header.setStretchLastSection(True)
header.hide() header.hide()
tv.verticalHeader().hide() tv.verticalHeader().hide()
@@ -1679,20 +1685,20 @@ class MainWindow(QMainWindow):
def pickQualities(self): def pickQualities(self):
path = self.get_current_event_path() path = self.get_current_event_path()
(_, _, plot) = getQualitiesfromxml(path, self._inputs.get('timeerrorsP'), self._inputs.get('timeerrorsS'),plotflag=1) (_, plot) = getQualitiesfromxml(path, self._inputs.get('timeerrorsP'), self._inputs.get('timeerrorsS'),plotflag=1)
self.pickQualitiesWindow = PickQualitiesFromXml(figure=plot, path=self.get_current_event_path(),inputVar=self._inputs) self.pickQualitiesWindow = PickQualitiesFromXml(figure=plot, path=self.get_current_event_path(),inputVar=self._inputs)
self.pickQualitiesWindow.showUI() self.pickQualitiesWindow.showUI()
return return
# WIP JG # WIP JG
def eventlistXml2(self): def eventlistXml(self):
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database'] path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
outpath = self.project.location[:self.project.location.rfind('/')] outpath = self.project.location[:self.project.location.rfind('/')]
geteventlistfromxml(path, outpath) geteventlistfromxml(path, outpath)
return return
# WIP JG # WIP JG
def eventlistXml(self): def spectogramView(self):
global test global test
stations = [] stations = []
names = [] names = []
@@ -1707,12 +1713,25 @@ class MainWindow(QMainWindow):
for tr in self.get_data().wfdata.select(component=ch).traces: for tr in self.get_data().wfdata.select(component=ch).traces:
traces[tr.stats.station][ch] = tr traces[tr.stats.station][ch] = tr
names.sort() names.sort()
a = self.get_current_event() a = self.get_current_event()
test = ChooseWaveFormWindow(WaveForms=names, traces=traces, stream=self.get_data())
#self.get_data().wfdata.spectrogram() print (self.get_data().wfdata.traces[0])
test.show()
test = SpectrogramTab(traces, self.get_data().wfdata)
height = self.tabs.widget(0).height()
width = self.tabs.widget(0).width()
self.tabs.setCurrentIndex(3)
figCanvas = test.makeSpecFig(direction=self.dispComponent, height = height, width = width, parent = self.tabs.widget)
return figCanvas
#self.spectro_layout.addWidget()
# self.get_data().wfdata.spectrogram()
# self.tabs.addTab(figCanvas, 'Spectrogram')
# self.tabs[3] = figCanvas
# self.refreshTabs()
# test.show()
def compareMulti(self): def compareMulti(self):
if not self.compareoptions: if not self.compareoptions:
@@ -1899,6 +1918,13 @@ class MainWindow(QMainWindow):
self.newWF(plot=False) self.newWF(plot=False)
self.update_obspy_dmt() self.update_obspy_dmt()
self.refresh_array_map() self.refresh_array_map()
if self.tabs.currentIndex() == 3:
if self.spectroWidget != None:
self.spectro_layout.removeWidget(self.spectroWidget)
newSpectroWidget = self.spectogramView()
self.spectro_layout.addWidget(newSpectroWidget)
self.spectroWidget = newSpectroWidget
def newWF(self, event=None, plot=True): def newWF(self, event=None, plot=True):
''' '''
@@ -1929,13 +1955,20 @@ class MainWindow(QMainWindow):
def prepareLoadWaveformData(self): def prepareLoadWaveformData(self):
self.fnames = self.getWFFnames_from_eventbox() self.fnames = self.getWFFnames_from_eventbox()
self.fnames_syn = [] self.fnames_comp = []
fnames_comp = self.getWFFnames_from_eventbox(subpath='compare')
self.dataPlot.activateCompareOptions(bool(fnames_comp))
if fnames_comp:
if self.dataPlot.comp_checkbox.isChecked():
self.fnames_comp = fnames_comp
eventpath = self.get_current_event_path() eventpath = self.get_current_event_path()
basepath = eventpath.split(os.path.basename(eventpath))[0] basepath = eventpath.split(os.path.basename(eventpath))[0]
self.obspy_dmt = check_obspydmt_structure(basepath) self.obspy_dmt = check_obspydmt_structure(basepath)
self.dataPlot.activateObspyDMToptions(self.obspy_dmt) self.dataPlot.activateObspyDMToptions(self.obspy_dmt)
if self.obspy_dmt: if self.obspy_dmt:
self.prepareObspyDMT_data(eventpath) self.prepareObspyDMT_data(eventpath)
self.dataPlot.activateCompareOptions(True)
def loadWaveformData(self): def loadWaveformData(self):
''' '''
@@ -1966,7 +1999,7 @@ class MainWindow(QMainWindow):
tstop = None tstop = None
self.data.setWFData(self.fnames, self.data.setWFData(self.fnames,
self.fnames_syn, self.fnames_comp,
checkRotated=True, checkRotated=True,
metadata=self.metadata, metadata=self.metadata,
tstart=tstart, tstart=tstart,
@@ -1974,7 +2007,7 @@ class MainWindow(QMainWindow):
def prepareObspyDMT_data(self, eventpath): def prepareObspyDMT_data(self, eventpath):
qcbox_processed = self.dataPlot.qcombo_processed qcbox_processed = self.dataPlot.qcombo_processed
qcheckb_syn = self.dataPlot.syn_checkbox qcheckb_syn = self.dataPlot.comp_checkbox
qcbox_processed.setEnabled(False) qcbox_processed.setEnabled(False)
qcheckb_syn.setEnabled(False) qcheckb_syn.setEnabled(False)
for fpath in os.listdir(eventpath): for fpath in os.listdir(eventpath):
@@ -1982,8 +2015,8 @@ class MainWindow(QMainWindow):
if 'syngine' in fpath: if 'syngine' in fpath:
eventpath_syn = os.path.join(eventpath, fpath) eventpath_syn = os.path.join(eventpath, fpath)
qcheckb_syn.setEnabled(True) qcheckb_syn.setEnabled(True)
if self.dataPlot.syn_checkbox.isChecked(): if self.dataPlot.comp_checkbox.isChecked():
self.fnames_syn = [os.path.join(eventpath_syn, filename) for filename in os.listdir(eventpath_syn)] self.fnames_comp = [os.path.join(eventpath_syn, filename) for filename in os.listdir(eventpath_syn)]
if 'processed' in fpath: if 'processed' in fpath:
qcbox_processed.setEnabled(True) qcbox_processed.setEnabled(True)
if qcbox_processed.isEnabled(): if qcbox_processed.isEnabled():
@@ -2156,6 +2189,7 @@ class MainWindow(QMainWindow):
self.locateEventAction.setEnabled(True) self.locateEventAction.setEnabled(True)
self.qualities_action.setEnabled(True) self.qualities_action.setEnabled(True)
self.eventlist_xml_action.setEnabled(True) self.eventlist_xml_action.setEnabled(True)
if True in self.comparable.values(): if True in self.comparable.values():
self.compare_action.setEnabled(True) self.compare_action.setEnabled(True)
self.draw() self.draw()
@@ -2263,7 +2297,7 @@ class MainWindow(QMainWindow):
comp = self.getComponent() comp = self.getComponent()
title = 'section: {0} components'.format(zne_text[comp]) title = 'section: {0} components'.format(zne_text[comp])
wfst = self.get_data().getWFData() wfst = self.get_data().getWFData()
wfsyn = self.get_data().getSynWFData() wfsyn = self.get_data().getAltWFdata()
if self.filterActionP.isChecked() and filter: if self.filterActionP.isChecked() and filter:
self.filterWaveformData(plot=False, phase='P') self.filterWaveformData(plot=False, phase='P')
elif self.filterActionS.isChecked() and filter: elif self.filterActionS.isChecked() and filter:
@@ -2272,7 +2306,7 @@ class MainWindow(QMainWindow):
# wfst += self.get_data().getWFData().select(component=alter_comp) # wfst += self.get_data().getWFData().select(component=alter_comp)
plotWidget = self.getPlotWidget() plotWidget = self.getPlotWidget()
self.adjustPlotHeight() self.adjustPlotHeight()
if get_Bool(settings.value('large_dataset')) == True: if get_bool(settings.value('large_dataset')):
self.plot_method = 'fast' self.plot_method = 'fast'
else: else:
self.plot_method = 'normal' self.plot_method = 'normal'
@@ -2575,18 +2609,21 @@ class MainWindow(QMainWindow):
print("Warning! No network, station, and location info available!") print("Warning! No network, station, and location info available!")
return return
self.update_status('picking on station {0}'.format(station)) self.update_status('picking on station {0}'.format(station))
data = self.get_data().getOriginalWFData().copy() wfdata = self.get_data().getOriginalWFData().copy()
wfdata_comp = self.get_data().getAltWFdata().copy()
event = self.get_current_event() event = self.get_current_event()
wftype = self.dataPlot.qcombo_processed.currentText() if self.obspy_dmt else None wftype = self.dataPlot.qcombo_processed.currentText() if self.obspy_dmt else None
pickDlg = PickDlg(self, parameter=self._inputs, pickDlg = PickDlg(self, parameter=self._inputs,
data=data.select(station=station), data=wfdata.select(station=station),
data_compare=wfdata_comp.select(station=station),
station=station, network=network, station=station, network=network,
location=location, location=location,
picks=self.getPicksOnStation(station, 'manual'), picks=self.getPicksOnStation(station, 'manual'),
autopicks=self.getPicksOnStation(station, 'auto'), autopicks=self.getPicksOnStation(station, 'auto'),
metadata=self.metadata, event=event, metadata=self.metadata, event=event,
model=self.inputs.get('taup_model'), model=self.inputs.get('taup_model'),
filteroptions=self.filteroptions, wftype=wftype) filteroptions=self.filteroptions, wftype=wftype,
show_comp_data=self.dataPlot.comp_checkbox.isChecked())
if self.filterActionP.isChecked(): if self.filterActionP.isChecked():
pickDlg.currentPhase = "P" pickDlg.currentPhase = "P"
pickDlg.filterWFData() pickDlg.filterWFData()
@@ -2898,7 +2935,9 @@ class MainWindow(QMainWindow):
self.log_deleted_picks([deleted_pick]) self.log_deleted_picks([deleted_pick])
def log_deleted_picks(self, deleted_picks, event_path=None): def log_deleted_picks(self, deleted_picks, event_path=None):
''' Log deleted picks to list self.deleted_picks ''' '''
Log deleted picks to list self.deleted_picks
'''
if not event_path: if not event_path:
event_path = self.get_current_event_path() event_path = self.get_current_event_path()
for deleted_pick in deleted_picks: for deleted_pick in deleted_picks:
@@ -2912,7 +2951,9 @@ class MainWindow(QMainWindow):
self.deleted_picks[event_path].append(deleted_pick) self.deleted_picks[event_path].append(deleted_pick)
def dump_deleted_picks(self, event_path): def dump_deleted_picks(self, event_path):
''' Save deleted picks to json file for event in event_path. Load old file before and merge''' '''
Save deleted picks to json file for event in event_path. Load old file before and merge
'''
try: try:
deleted_picks_from_file = self.load_deleted_picks(event_path) deleted_picks_from_file = self.load_deleted_picks(event_path)
except Exception as e: except Exception as e:
@@ -3125,7 +3166,7 @@ class MainWindow(QMainWindow):
phasefile = os.path.join(obsdir, filename + '.obs') phasefile = os.path.join(obsdir, filename + '.obs')
lt.modify_inputs(ctrfile, locroot, filename, phasefile, ttt) lt.modify_inputs(ctrfile, locroot, filename, phasefile, ttt)
try: try:
lt.locate(ctrfile, self.obspy_dmt) lt.locate(ctrfile, self._inputs)
except RuntimeError as e: except RuntimeError as e:
print(e.message) print(e.message)
# finally: # finally:
@@ -3179,7 +3220,7 @@ class MainWindow(QMainWindow):
''' '''
if checked: pass # dummy argument for QAction trigger signal if checked: pass # dummy argument for QAction trigger signal
self.tabs.setCurrentIndex(1) self.tabs.setCurrentIndex(1)
# if there is no metadata (invetories is an empty list), just initialize the default empty tab # if there is no metadata (inventories is an empty list), just initialize the default empty tab
if not self.metadata.inventories: if not self.metadata.inventories:
self.init_array_tab() self.init_array_tab()
return return
@@ -3201,6 +3242,15 @@ class MainWindow(QMainWindow):
self.tabs.setCurrentIndex(index) self.tabs.setCurrentIndex(index)
self.refresh_array_map() self.refresh_array_map()
def init_spectro_tab(self):
'''
Init spectrogram tab with currently selected event.
'''
self.spectroWidget = None
#self.spectro_layout.addWidget( self.spectogramView() )
pass
def array_map_thread(self): def array_map_thread(self):
''' '''
Start modal thread to init the array_map object. Start modal thread to init the array_map object.
@@ -3423,7 +3473,7 @@ class MainWindow(QMainWindow):
self.event_table.setCellWidget(r_index, c_index, item) self.event_table.setCellWidget(r_index, c_index, item)
header = self.event_table.horizontalHeader() header = self.event_table.horizontalHeader()
header.setResizeMode(QtWidgets.QHeaderView.ResizeToContents) header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setStretchLastSection(True) header.setStretchLastSection(True)
self.event_table.cellChanged[int, int].connect(cell_changed) self.event_table.cellChanged[int, int].connect(cell_changed)
self.event_table.cellClicked[int, int].connect(cell_clicked) self.event_table.cellClicked[int, int].connect(cell_clicked)
@@ -3709,7 +3759,7 @@ class MainWindow(QMainWindow):
filename = fnm[0] + '.plp' filename = fnm[0] + '.plp'
self.project.parameter = self._inputs self.project.parameter = self._inputs
settings = QSettings() settings = QSettings()
autosaveXML = get_Bool(settings.value('autosaveXML', True)) autosaveXML = get_bool(settings.value('autosaveXML', True))
if autosaveXML: if autosaveXML:
self.exportEvents() self.exportEvents()
if not self.project.save(filename): return False if not self.project.save(filename): return False
@@ -3733,7 +3783,7 @@ class MainWindow(QMainWindow):
self.metadata.clear_inventory() self.metadata.clear_inventory()
self.project.parameter = self._inputs self.project.parameter = self._inputs
settings = QSettings() settings = QSettings()
autosaveXML = get_Bool(settings.value('autosaveXML', True)) autosaveXML = get_bool(settings.value('autosaveXML', True))
if autosaveXML: if autosaveXML:
self.exportEvents() self.exportEvents()
if not self.project.save(): return False if not self.project.save(): return False
@@ -3822,7 +3872,7 @@ class MainWindow(QMainWindow):
def helpHelp(self): def helpHelp(self):
if checkurl(): if checkurl():
form = HelpForm(self, form = HelpForm(self,
'https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/wiki') 'https://github.com/seismology-RUB/PyLoT')
else: else:
form = HelpForm(self, ':/help.html') form = HelpForm(self, ':/help.html')
form.show() form.show()
@@ -4002,13 +4052,13 @@ class Project(object):
return project return project
class getExistingDirectories(QFileDialog): class GetExistingDirectories(QFileDialog):
''' '''
File dialog with possibility to select multiple folders. File dialog with possibility to select multiple folders.
''' '''
def __init__(self, *args): def __init__(self, *args):
super(getExistingDirectories, self).__init__(*args) super(GetExistingDirectories, self).__init__(*args)
self.setOption(self.DontUseNativeDialog, True) self.setOption(self.DontUseNativeDialog, True)
self.setOption(self.ReadOnly, True) self.setOption(self.ReadOnly, True)
self.setFileMode(self.Directory) self.setFileMode(self.Directory)
@@ -4034,16 +4084,7 @@ def create_window():
return app, app_created return app, app_created
def main(args=None): def main(project_filename=None, pylot_infile=None, reset_qsettings=False):
project_filename = None
# args.project_filename = 'C:/Shared/AlpArray/alparray_data/project_alparray_test.plp'
pylot_infile = None
if args:
if args.project_filename:
project_filename = args.project_filename
if args.input_filename:
pylot_infile = args.input_filename
reset_qsettings = args.reset_qsettings
# create the Qt application # create the Qt application
pylot_app, app_created = create_window() pylot_app, app_created = create_window()
@@ -4092,4 +4133,5 @@ if __name__ == "__main__":
parser.add_argument('--reset_qsettings', default=False, action='store_true', parser.add_argument('--reset_qsettings', default=False, action='store_true',
help='reset qsettings (debug option)') help='reset qsettings (debug option)')
args = parser.parse_args() args = parser.parse_args()
sys.exit(main(args)) sys.exit(main(project_filename=args.project_filename, pylot_infile=args.input_filename,
reset_qsettings=args.reset_qsettings))

View File

@@ -99,7 +99,7 @@ We hope to solve these with the next release.
## Staff ## Staff
Original author(s): L. Kueperkoch, S. Wehling-Benatelli, M. Bischoff (PILOT) Original author(s): M. Rische, S. Wehling-Benatelli, L. Kueperkoch, M. Bischoff (PILOT)
Developer(s): S. Wehling-Benatelli, M. Paffrath, L. Kueperkoch, K. Olbert, M. Bischoff, C. Wollin, M. Rische, D. Arnold, K. Cökerim, S. Zimmermann Developer(s): S. Wehling-Benatelli, M. Paffrath, L. Kueperkoch, K. Olbert, M. Bischoff, C. Wollin, M. Rische, D. Arnold, K. Cökerim, S. Zimmermann

View File

@@ -7,4 +7,6 @@
#$ -l h_vmem=2G #$ -l h_vmem=2G
#$ -l os=*stretch #$ -l os=*stretch
python ./autoPyLoT.py -i /home/marcel/.pylot/pylot_alparray_mantle_corr_stack_0.03-0.5.in -dmt processed -c $NSLOTS conda activate pylot_38
python ./autoPyLoT.py -i /home/marcel/.pylot/pylot_janis_noisy.in -c $NSLOTS

View File

@@ -8,7 +8,7 @@ dependencies:
- numpy=1.22.3 - numpy=1.22.3
- obspy=1.3.0 - obspy=1.3.0
- pyqtgraph=0.12.4 - pyqtgraph=0.12.4
- pyside2=5.13.2 - pyside2>=5.13.2
- python=3.8.12 - python=3.8.12
- qt=5.12.9 - qt>=5.12.9
- scipy=1.8.0 - scipy=1.8.0

View File

@@ -418,6 +418,10 @@ class MomentMagnitude(Magnitude):
distance = degrees2kilometers(a.distance) distance = degrees2kilometers(a.distance)
azimuth = a.azimuth azimuth = a.azimuth
incidence = a.takeoff_angle incidence = a.takeoff_angle
if not 0. <= incidence <= 360.:
if self.verbose:
print(f'WARNING: Incidence angle outside bounds - {incidence}')
return
w0, fc = calcsourcespec(scopy, onset, self.p_velocity, distance, w0, fc = calcsourcespec(scopy, onset, self.p_velocity, distance,
azimuth, incidence, self.p_attenuation, azimuth, incidence, self.p_attenuation,
self.plot_flag, self.verbose) self.plot_flag, self.verbose)

View File

@@ -260,7 +260,6 @@ class Data(object):
can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude'] can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude']
""" """
from pylot.core.util.defaults import OUTPUTFORMATS from pylot.core.util.defaults import OUTPUTFORMATS
if not type(fcheck) == list: if not type(fcheck) == list:
fcheck = [fcheck] fcheck = [fcheck]
@@ -321,35 +320,61 @@ class Data(object):
if lendiff != 0: if lendiff != 0:
print("Manual as well as automatic picks available. Prefered the {} manual ones!".format(lendiff)) print("Manual as well as automatic picks available. Prefered the {} manual ones!".format(lendiff))
no_uncertainties_p = []
no_uncertainties_s = []
if upperErrors: if upperErrors:
# check for pick uncertainties exceeding adjusted upper errors # check for pick uncertainties exceeding adjusted upper errors
# Picks with larger uncertainties will not be saved in output file! # Picks with larger uncertainties will not be saved in output file!
for j in range(len(picks)): for j in range(len(picks)):
for i in range(len(picks_copy)): for i in range(len(picks_copy)):
if picks_copy[i].phase_hint[0] == 'P': if picks_copy[i].phase_hint[0] == 'P':
if (picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[0]) or \ # Skipping pick if no upper_uncertainty is found and warning user
(picks_copy[i].time_errors['uncertainty'] is None): if picks_copy[i].time_errors['upper_uncertainty'] is None:
#print("{1} P-Pick of station {0} does not have upper_uncertainty and cant be checked".format(
# picks_copy[i].waveform_id.station_code,
# picks_copy[i].method_id))
if not picks_copy[i].waveform_id.station_code in no_uncertainties_p:
no_uncertainties_p.append(picks_copy[i].waveform_id.station_code)
continue
#print ("checking for upper_uncertainty")
if (picks_copy[i].time_errors['uncertainty'] is None) or \
(picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[0]):
print("Uncertainty exceeds or equal adjusted upper time error!") print("Uncertainty exceeds or equal adjusted upper time error!")
print("Adjusted uncertainty: {}".format(upperErrors[0])) print("Adjusted uncertainty: {}".format(upperErrors[0]))
print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty'])) print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty']))
print("{1} P-Pick of station {0} will not be saved in outputfile".format( print("{1} P-Pick of station {0} will not be saved in outputfile".format(
picks_copy[i].waveform_id.station_code, picks_copy[i].waveform_id.station_code,
picks_copy[i].method_id)) picks_copy[i].method_id))
print("#")
del picks_copy[i] del picks_copy[i]
break break
if picks_copy[i].phase_hint[0] == 'S': if picks_copy[i].phase_hint[0] == 'S':
if (picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[1]) or \
(picks_copy[i].time_errors['uncertainty'] is None): # Skipping pick if no upper_uncertainty is found and warning user
if picks_copy[i].time_errors['upper_uncertainty'] is None:
#print("{1} S-Pick of station {0} does not have upper_uncertainty and cant be checked".format(
#picks_copy[i].waveform_id.station_code,
#picks_copy[i].method_id))
if not picks_copy[i].waveform_id.station_code in no_uncertainties_s:
no_uncertainties_s.append(picks_copy[i].waveform_id.station_code)
continue
if (picks_copy[i].time_errors['uncertainty'] is None) or \
(picks_copy[i].time_errors['upper_uncertainty'] >= upperErrors[1]):
print("Uncertainty exceeds or equal adjusted upper time error!") print("Uncertainty exceeds or equal adjusted upper time error!")
print("Adjusted uncertainty: {}".format(upperErrors[1])) print("Adjusted uncertainty: {}".format(upperErrors[1]))
print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty'])) print("Pick uncertainty: {}".format(picks_copy[i].time_errors['uncertainty']))
print("{1} S-Pick of station {0} will not be saved in outputfile".format( print("{1} S-Pick of station {0} will not be saved in outputfile".format(
picks_copy[i].waveform_id.station_code, picks_copy[i].waveform_id.station_code,
picks_copy[i].method_id)) picks_copy[i].method_id))
print("#")
del picks_copy[i] del picks_copy[i]
break break
for s in no_uncertainties_p:
print("P-Pick of station {0} does not have upper_uncertainty and cant be checked".format(s))
for s in no_uncertainties_s:
print("S-Pick of station {0} does not have upper_uncertainty and cant be checked".format(s))
if fnext == '.obs': if fnext == '.obs':
try: try:
@@ -426,20 +451,25 @@ class Data(object):
data.filter(**kwargs) data.filter(**kwargs)
self.dirty = True self.dirty = True
def setWFData(self, fnames, fnames_syn=None, checkRotated=False, metadata=None, tstart=0, tstop=0): def setWFData(self, fnames, fnames_alt=None, checkRotated=False, metadata=None, tstart=0, tstop=0):
""" """
Clear current waveform data and set given waveform data Clear current waveform data and set given waveform data
:param fnames: waveform data names to append :param fnames: waveform data names to append
:param fnames_alt: alternative data to show (e.g. synthetic/processed)
:type fnames: list :type fnames: list
""" """
self.wfdata = Stream() self.wfdata = Stream()
self.wforiginal = None self.wforiginal = None
self.wfsyn = Stream() self.wf_alt = Stream()
if tstart == tstop: if tstart == tstop:
tstart = tstop = None tstart = tstop = None
self.tstart = tstart self.tstart = tstart
self.tstop = tstop self.tstop = tstop
# remove directories
fnames = [fname for fname in fnames if not os.path.isdir(fname)]
fnames_alt = [fname for fname in fnames_alt if not os.path.isdir(fname)]
# if obspy_dmt: # if obspy_dmt:
# wfdir = 'raw' # wfdir = 'raw'
# self.processed = False # self.processed = False
@@ -457,8 +487,8 @@ class Data(object):
# wffnames = fnames # wffnames = fnames
if fnames is not None: if fnames is not None:
self.appendWFData(fnames) self.appendWFData(fnames)
if fnames_syn is not None: if fnames_alt is not None:
self.appendWFData(fnames_syn, synthetic=True) self.appendWFData(fnames_alt, alternative=True)
else: else:
return False return False
@@ -478,7 +508,7 @@ class Data(object):
self.dirty = False self.dirty = False
return True return True
def appendWFData(self, fnames, synthetic=False): def appendWFData(self, fnames, alternative=False):
""" """
Read waveform data from fnames and append it to current wf data Read waveform data from fnames and append it to current wf data
:param fnames: waveform data to append :param fnames: waveform data to append
@@ -491,20 +521,20 @@ class Data(object):
if self.dirty: if self.dirty:
self.resetWFData() self.resetWFData()
real_or_syn_data = {True: self.wfsyn, orig_or_alternative_data = {True: self.wf_alt,
False: self.wfdata} False: self.wfdata}
warnmsg = '' warnmsg = ''
for fname in set(fnames): for fname in set(fnames):
try: try:
real_or_syn_data[synthetic] += read(fname, starttime=self.tstart, endtime=self.tstop) orig_or_alternative_data[alternative] += read(fname, starttime=self.tstart, endtime=self.tstop)
except TypeError: except TypeError:
try: try:
real_or_syn_data[synthetic] += read(fname, format='GSE2', starttime=self.tstart, endtime=self.tstop) orig_or_alternative_data[alternative] += read(fname, format='GSE2', starttime=self.tstart, endtime=self.tstop)
except Exception as e: except Exception as e:
try: try:
real_or_syn_data[synthetic] += read(fname, format='SEGY', starttime=self.tstart, orig_or_alternative_data[alternative] += read(fname, format='SEGY', starttime=self.tstart,
endtime=self.tstop) endtime=self.tstop)
except Exception as e: except Exception as e:
warnmsg += '{0}\n{1}\n'.format(fname, e) warnmsg += '{0}\n{1}\n'.format(fname, e)
except SacIOError as se: except SacIOError as se:
@@ -519,8 +549,8 @@ class Data(object):
def getOriginalWFData(self): def getOriginalWFData(self):
return self.wforiginal return self.wforiginal
def getSynWFData(self): def getAltWFdata(self):
return self.wfsyn return self.wf_alt
def resetWFData(self): def resetWFData(self):
""" """

View File

@@ -280,6 +280,7 @@ def picksdict_from_picks(evt):
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in') infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
print('Using default input file {}'.format(infile)) print('Using default input file {}'.format(infile))
parameter = PylotParameter(infile) parameter = PylotParameter(infile)
pick.phase_hint = identifyPhase(pick.phase_hint)
if pick.phase_hint == 'P': if pick.phase_hint == 'P':
errors = parameter['timeerrorsP'] errors = parameter['timeerrorsP']
elif pick.phase_hint == 'S': elif pick.phase_hint == 'S':
@@ -517,7 +518,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
for key in arrivals: for key in arrivals:
# P onsets # P onsets
if arrivals[key].has_key('P'): if 'P' in arrivals[key]:
try: try:
fm = arrivals[key]['P']['fm'] fm = arrivals[key]['P']['fm']
except KeyError as e: except KeyError as e:
@@ -551,7 +552,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
ss_ms, ss_ms,
pweight)) pweight))
# S onsets # S onsets
if arrivals[key].has_key('S') and arrivals[key]['S']['mpp'] is not None: if 'S' in arrivals[key] and arrivals[key]['S']['mpp'] is not None:
fm = '?' fm = '?'
onset = arrivals[key]['S']['mpp'] onset = arrivals[key]['S']['mpp']
year = onset.year year = onset.year
@@ -670,7 +671,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
for key in arrivals: for key in arrivals:
# P onsets # P onsets
if arrivals[key].has_key('P') and arrivals[key]['P']['mpp'] is not None: if 'P' in arrivals[key] and arrivals[key]['P']['mpp'] is not None:
if arrivals[key]['P']['weight'] < 4: if arrivals[key]['P']['weight'] < 4:
Ponset = arrivals[key]['P']['mpp'] Ponset = arrivals[key]['P']['mpp']
pyear = Ponset.year pyear = Ponset.year
@@ -699,7 +700,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
fid.write('%-5s P1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n' fid.write('%-5s P1 %4.0f %02d %02d %02d %02d %05.02f %5.3f -999. 0.00 -999. 0.00\n'
% (key, pyear, pmonth, pday, phh, pmm, Pss, pstd)) % (key, pyear, pmonth, pday, phh, pmm, Pss, pstd))
# S onsets # S onsets
if arrivals[key].has_key('S') and arrivals[key]['S']['mpp'] is not None: if 'S' in arrivals[key] and arrivals[key]['S']['mpp'] is not None:
if arrivals[key]['S']['weight'] < 4: if arrivals[key]['S']['weight'] < 4:
Sonset = arrivals[key]['S']['mpp'] Sonset = arrivals[key]['S']['mpp']
syear = Sonset.year syear = Sonset.year
@@ -768,7 +769,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
usedarrivals = chooseArrivals(arrivals) usedarrivals = chooseArrivals(arrivals)
for key in usedarrivals: for key in usedarrivals:
# P onsets # P onsets
if usedarrivals[key].has_key('P'): if 'P' in usedarrivals[key]:
if usedarrivals[key]['P']['weight'] < 4: if usedarrivals[key]['P']['weight'] < 4:
n += 1 n += 1
stat = key stat = key
@@ -782,7 +783,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
else: else:
fid.write('%-4sP%d%6.2f\n' % (stat, Pweight, Prt)) fid.write('%-4sP%d%6.2f\n' % (stat, Pweight, Prt))
# S onsets # S onsets
if usedarrivals[key].has_key('S'): if 'S' in usedarrivals[key]:
if usedarrivals[key]['S']['weight'] < 4: if usedarrivals[key]['S']['weight'] < 4:
n += 1 n += 1
stat = key stat = key
@@ -828,13 +829,13 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
# prefer manual picks # prefer manual picks
usedarrivals = chooseArrivals(arrivals) usedarrivals = chooseArrivals(arrivals)
for key in usedarrivals: for key in usedarrivals:
if usedarrivals[key].has_key('P'): if 'P' in usedarrivals[key]:
# P onsets # P onsets
if usedarrivals[key]['P']['weight'] < 4: if usedarrivals[key]['P']['weight'] < 4:
Ponset = usedarrivals[key]['P']['mpp'] Ponset = usedarrivals[key]['P']['mpp']
Prt = Ponset - stime # onset time relative to source time Prt = Ponset - stime # onset time relative to source time
fid.write('%s %6.3f 1 P\n' % (key, Prt)) fid.write('%s %6.3f 1 P\n' % (key, Prt))
if usedarrivals[key].has_key('S'): if 'S' in usedarrivals[key]:
# S onsets # S onsets
if usedarrivals[key]['S']['weight'] < 4: if usedarrivals[key]['S']['weight'] < 4:
Sonset = usedarrivals[key]['S']['mpp'] Sonset = usedarrivals[key]['S']['mpp']
@@ -879,7 +880,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
# prefer manual picks # prefer manual picks
usedarrivals = chooseArrivals(arrivals) usedarrivals = chooseArrivals(arrivals)
for key in usedarrivals: for key in usedarrivals:
if usedarrivals[key].has_key('P'): if 'P' in usedarrivals[key]:
if usedarrivals[key]['P']['weight'] < 4 and usedarrivals[key]['P']['fm'] is not None: if usedarrivals[key]['P']['weight'] < 4 and usedarrivals[key]['P']['fm'] is not None:
stat = key stat = key
for i in range(len(picks)): for i in range(len(picks)):
@@ -961,7 +962,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere arrivals = chooseArrivals(arrivals) # MP MP what is chooseArrivals? It is not defined anywhere
# write phase lines # write phase lines
for key in arrivals: for key in arrivals:
if arrivals[key].has_key('P'): if 'P' in arrivals[key]:
if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None: if arrivals[key]['P']['weight'] < 4 and arrivals[key]['P']['fm'] is not None:
stat = key stat = key
ccode = arrivals[key]['P']['channel'] ccode = arrivals[key]['P']['channel']
@@ -1014,7 +1015,6 @@ def chooseArrivals(arrivals):
:return: arrivals but with the manual picks prefered if possible :return: arrivals but with the manual picks prefered if possible
""" """
# If len of arrivals is greater than 2 it comes from autopicking so only autopicks are available # If len of arrivals is greater than 2 it comes from autopicking so only autopicks are available
print("=== CHOOSE ===")
if len(arrivals) > 2: if len(arrivals) > 2:
return arrivals return arrivals
if arrivals['auto'] and arrivals['manual']: if arrivals['auto'] and arrivals['manual']:

View File

@@ -82,8 +82,8 @@ def locate(fnin, parameter=None):
:param fnin: external program name :param fnin: external program name
:return: None :return: None
""" """
exe_path = parameter['nllocbin'] + '/bin/NLLoc' exe_path = os.path.join(parameter['nllocbin'], 'NLLoc')
if exe_path is None: if not os.path.isfile(exe_path):
raise NLLocError('NonLinLoc executable not found; check your ' raise NLLocError('NonLinLoc executable not found; check your '
'environment variables') 'environment variables')

View File

@@ -22,7 +22,7 @@ from pylot.core.pick.picker import AICPicker, PragPicker
from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \ from pylot.core.pick.utils import checksignallength, checkZ4S, earllatepicker, \
getSNR, fmpicker, checkPonsets, wadaticheck, get_quality_class getSNR, fmpicker, checkPonsets, wadaticheck, get_quality_class
from pylot.core.util.utils import getPatternLine, gen_Pool, \ from pylot.core.util.utils import getPatternLine, gen_Pool, \
get_Bool, identifyPhaseID, get_None, correct_iplot get_bool, identifyPhaseID, get_None, correct_iplot
def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None): def autopickevent(data, param, iplot=0, fig_dict=None, fig_dict_wadatijack=None, ncores=0, metadata=None, origin=None):
@@ -477,7 +477,7 @@ class AutopickStation(object):
if self.pickparams["sstart"] < 0: if self.pickparams["sstart"] < 0:
self.pickparams["sstart"] = 0 self.pickparams["sstart"] = 0
if get_Bool(self.pickparams["use_taup"]) is False: if get_bool(self.pickparams["use_taup"]) is False:
# correct user mistake where a relative cuttime is selected (pstart < 0) but use of taupy is disabled/ has # correct user mistake where a relative cuttime is selected (pstart < 0) but use of taupy is disabled/ has
# not the required parameters # not the required parameters
exit_taupy() exit_taupy()
@@ -525,7 +525,7 @@ class AutopickStation(object):
:rtype: dict :rtype: dict
""" """
if get_Bool(self.pickparams['use_taup']) is True and self.origin is not None: if get_bool(self.pickparams['use_taup']) is True and self.origin is not None:
try: try:
# modify pstart, pstop, sstart, sstop to be around theoretical onset if taupy should be used, # modify pstart, pstop, sstart, sstop to be around theoretical onset if taupy should be used,
# else do nothing # else do nothing
@@ -544,7 +544,7 @@ class AutopickStation(object):
if self.horizontal_traces_exist(): if self.horizontal_traces_exist():
if (self.p_results.weight is not None and self.p_results.weight < 4) or \ if (self.p_results.weight is not None and self.p_results.weight < 4) or \
get_Bool(self.pickparams.get('use_taup')): get_bool(self.pickparams.get('use_taup')):
try: try:
self.pick_s_phase() self.pick_s_phase()
except MissingTraceException as mte: except MissingTraceException as mte:
@@ -936,7 +936,7 @@ class AutopickStation(object):
"minFMSNR"]: "minFMSNR"]:
# if SNR is high enough, try to determine first motion of onset # if SNR is high enough, try to determine first motion of onset
self.set_current_figure('fm_picker') self.set_current_figure('fm_picker')
self.p_results.fm = fmpicker(self.zstream, z_copy, self.pickparams["fmpickwin"], self.p_results.mpp, self.p_results.fm = fmpicker(self.zstream.copy(), z_copy, self.pickparams["fmpickwin"], self.p_results.mpp,
self.iplot, self.current_figure, self.current_linecolor) self.iplot, self.current_figure, self.current_linecolor)
msg = "autopickstation: P-weight: {}, SNR: {}, SNR[dB]: {}, Polarity: {}" msg = "autopickstation: P-weight: {}, SNR: {}, SNR[dB]: {}, Polarity: {}"
msg = msg.format(self.p_results.weight, self.p_results.snr, self.p_results.snrdb, self.p_results.fm) msg = msg.format(self.p_results.weight, self.p_results.snr, self.p_results.snrdb, self.p_results.fm)
@@ -1148,7 +1148,7 @@ class AutopickStation(object):
''.format(self.s_results.weight, self.s_results.snr, self.s_results.snrdb)) ''.format(self.s_results.weight, self.s_results.snr, self.s_results.snrdb))
def pick_s_phase(self): def pick_s_phase(self):
if get_Bool(self.pickparams.get('use_taup')) is True: if get_bool(self.pickparams.get('use_taup')) is True:
cuttimesh = (self.pickparams.get('sstart'), self.pickparams.get('sstop')) cuttimesh = (self.pickparams.get('sstart'), self.pickparams.get('sstop'))
else: else:
# determine time window for calculating CF after P onset # determine time window for calculating CF after P onset

View File

@@ -336,7 +336,7 @@ class AICPicker(AutoPicker):
self.slope = 1 / (len(dataslope) * self.Data[0].stats.delta) * (datafit[-1] - datafit[0]) self.slope = 1 / (len(dataslope) * self.Data[0].stats.delta) * (datafit[-1] - datafit[0])
# normalize slope to maximum of cf to make it unit independent # normalize slope to maximum of cf to make it unit independent
self.slope /= aicsmooth[iaicmax] self.slope /= aicsmooth[iaicmax]
except ValueError as e: except Exception as e:
print("AICPicker: Problems with data fitting! {}".format(e)) print("AICPicker: Problems with data fitting! {}".format(e))
else: else:

View File

@@ -15,7 +15,7 @@ import numpy as np
from obspy.core import Stream, UTCDateTime from obspy.core import Stream, UTCDateTime
from scipy.signal import argrelmax from scipy.signal import argrelmax
from pylot.core.util.utils import get_Bool, get_None, SetChannelComponents from pylot.core.util.utils import get_bool, get_None, SetChannelComponents
def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None, linecolor='k'): def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None, linecolor='k'):
@@ -62,8 +62,8 @@ def earllatepicker(X, nfac, TSNR, Pick1, iplot=0, verbosity=1, fig=None, linecol
plt_flag = 0 plt_flag = 0
try: try:
iplot = int(iplot) iplot = int(iplot)
except: except ValueError:
if get_Bool(iplot): if get_bool(iplot):
iplot = 2 iplot = 2
else: else:
iplot = 0 iplot = 0
@@ -275,7 +275,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None, linecolor='k'):
try: try:
P1 = np.polyfit(xslope1, xraw[islope1], 1) P1 = np.polyfit(xslope1, xraw[islope1], 1)
datafit1 = np.polyval(P1, xslope1) datafit1 = np.polyval(P1, xslope1)
except ValueError as e: except Exception as e:
print("fmpicker: Problems with data fit! {}".format(e)) print("fmpicker: Problems with data fit! {}".format(e))
print("Skip first motion determination!") print("Skip first motion determination!")
return FM return FM
@@ -321,7 +321,7 @@ def fmpicker(Xraw, Xfilt, pickwin, Pick, iplot=0, fig=None, linecolor='k'):
try: try:
P2 = np.polyfit(xslope2, xfilt[islope2], 1) P2 = np.polyfit(xslope2, xfilt[islope2], 1)
datafit2 = np.polyval(P2, xslope2) datafit2 = np.polyval(P2, xslope2)
except ValueError as e: except Exception as e:
emsg = 'fmpicker: polyfit failed: {}'.format(e) emsg = 'fmpicker: polyfit failed: {}'.format(e)
print(emsg) print(emsg)
return FM return FM
@@ -816,7 +816,7 @@ def checksignallength(X, pick, minsiglength, pickparams, iplot=0, fig=None, line
try: try:
iplot = int(iplot) iplot = int(iplot)
except: except:
if get_Bool(iplot): if get_bool(iplot):
iplot = 2 iplot = 2
else: else:
iplot = 0 iplot = 0
@@ -1130,7 +1130,7 @@ def checkZ4S(X, pick, pickparams, iplot, fig=None, linecolor='k'):
try: try:
iplot = int(iplot) iplot = int(iplot)
except: except:
if get_Bool(iplot): if get_bool(iplot):
iplot = 2 iplot = 2
else: else:
iplot = 0 iplot = 0
@@ -1499,7 +1499,7 @@ def get_pickparams(pickparam):
first_motion_params = dict(zip(first_motion_names, fm_parameter_values)) first_motion_params = dict(zip(first_motion_names, fm_parameter_values))
signal_length_params = dict(zip(signal_length_names, sl_parameter_values)) signal_length_params = dict(zip(signal_length_names, sl_parameter_values))
p_params['use_taup'] = get_Bool(p_params['use_taup']) p_params['use_taup'] = get_bool(p_params['use_taup'])
return p_params, s_params, first_motion_params, signal_length_params return p_params, s_params, first_motion_params, signal_length_params

View File

@@ -75,7 +75,6 @@ class Array_map(QtWidgets.QWidget):
self._style = None if not hasattr(parent, '_style') else parent._style self._style = None if not hasattr(parent, '_style') else parent._style
self.show()
def init_map(self): def init_map(self):
self.init_colormap() self.init_colormap()
@@ -464,17 +463,19 @@ class Array_map(QtWidgets.QWidget):
transform=ccrs.PlateCarree(), label='deleted')) transform=ccrs.PlateCarree(), label='deleted'))
def openPickDlg(self, ind): def openPickDlg(self, ind):
data = self._parent.get_data().getWFData() wfdata = self._parent.get_data().getWFData()
wfdata_comp = self._parent.get_data().getWFDataComp()
for index in ind: for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2] network, station = self._station_onpick_ids[index].split('.')[:2]
pyl_mw = self._parent pyl_mw = self._parent
try: try:
data = data.select(station=station) wfdata = wfdata.select(station=station)
if not data: wfdata_comp = wfdata_comp.select(station=station)
if not wfdata:
self._warn('No data for station {}'.format(station)) self._warn('No data for station {}'.format(station))
return return
pickDlg = PickDlg(self._parent, parameter=self.parameter, pickDlg = PickDlg(self._parent, parameter=self.parameter,
data=data, network=network, station=station, data=wfdata.copy(), data_compare=wfdata_comp.copy(), network=network, station=station,
picks=self._parent.get_current_event().getPick(station), picks=self._parent.get_current_event().getPick(station),
autopicks=self._parent.get_current_event().getAutopick(station), autopicks=self._parent.get_current_event().getAutopick(station),
filteroptions=self._parent.filteroptions, metadata=self.metadata, filteroptions=self._parent.filteroptions, metadata=self.metadata,

View File

@@ -271,7 +271,7 @@ class Metadata(object):
continue continue
invtype, robj = self._read_metadata_file(os.path.join(path_to_inventory, fname)) invtype, robj = self._read_metadata_file(os.path.join(path_to_inventory, fname))
try: try:
robj.get_coordinates(station_seed_id) # robj.get_coordinates(station_seed_id) # TODO: Commented out, failed with Parser, is this needed?
self.inventory_files[fname] = {'invtype': invtype, self.inventory_files[fname] = {'invtype': invtype,
'data': robj} 'data': robj}
if station_seed_id in self.seed_ids.keys(): if station_seed_id in self.seed_ids.keys():

View File

@@ -26,9 +26,7 @@ elif system_name == "Windows":
# suffix for phase name if not phase identified by last letter (P, p, etc.) # suffix for phase name if not phase identified by last letter (P, p, etc.)
ALTSUFFIX = ['diff', 'n', 'g', '1', '2', '3'] ALTSUFFIX = ['diff', 'n', 'g', '1', '2', '3']
FILTERDEFAULTS = readDefaultFilterInformation(os.path.join(os.path.expanduser('~'), FILTERDEFAULTS = readDefaultFilterInformation()
'.pylot',
'pylot.in'))
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'), TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
'.pylot', '.pylot',

View File

@@ -41,7 +41,8 @@ class Thread(QThread):
exctype, value = sys.exc_info()[:2] exctype, value = sys.exc_info()[:2]
self._executedErrorInfo = '{} {} {}'. \ self._executedErrorInfo = '{} {} {}'. \
format(exctype, value, traceback.format_exc()) format(exctype, value, traceback.format_exc())
sys.stdout = self.old_stdout if self.redirect_stdout:
sys.stdout = self.old_stdout
def showProgressbar(self): def showProgressbar(self):
if self.progressText: if self.progressText:

View File

@@ -37,15 +37,14 @@ def getAutoFilteroptions(phase, parameter):
return filteroptions return filteroptions
def readDefaultFilterInformation(fname): def readDefaultFilterInformation():
""" """
Read default filter information from pylot.in file Read default filter information from pylot.in file
:param fname: path to pylot.in file
:type fname: str
:return: dictionary containing the defailt filter information :return: dictionary containing the defailt filter information
:rtype: dict :rtype: dict
""" """
pparam = PylotParameter(fname) pparam = PylotParameter()
pparam.reset_defaults()
return readFilterInformation(pparam) return readFilterInformation(pparam)
@@ -328,7 +327,7 @@ def get_None(value):
return value return value
def get_Bool(value): def get_bool(value):
""" """
Convert string representations of bools to their true boolean value Convert string representations of bools to their true boolean value
:param value: :param value:
@@ -336,13 +335,14 @@ def get_Bool(value):
:return: true boolean value :return: true boolean value
:rtype: bool :rtype: bool
""" """
if value in ['True', 'true']: if type(value) is bool:
return value
elif value in ['True', 'true']:
return True return True
elif value in ['False', 'false']: elif value in ['False', 'false']:
return False return False
else: else:
return value return bool(value)
def four_digits(year): def four_digits(year):
""" """
@@ -1169,7 +1169,7 @@ def correct_iplot(iplot):
try: try:
iplot = int(iplot) iplot = int(iplot)
except ValueError: except ValueError:
if get_Bool(iplot): if get_bool(iplot):
iplot = 2 iplot = 2
else: else:
iplot = 0 iplot = 0

View File

@@ -53,7 +53,7 @@ from pylot.core.util.utils import prepTimeAxis, full_range, demeanTrace, isSorte
pick_linestyle_plt, pick_color_plt, \ pick_linestyle_plt, pick_color_plt, \
check4rotated, check4doubled, merge_stream, identifyPhase, \ check4rotated, check4doubled, merge_stream, identifyPhase, \
loopIdentifyPhase, trim_station_components, transformFilteroptions2String, \ loopIdentifyPhase, trim_station_components, transformFilteroptions2String, \
identifyPhaseID, get_Bool, get_None, pick_color, getAutoFilteroptions, SetChannelComponents, \ identifyPhaseID, get_bool, get_None, pick_color, getAutoFilteroptions, SetChannelComponents, \
station_id_remove_channel station_id_remove_channel
from autoPyLoT import autoPyLoT from autoPyLoT import autoPyLoT
from pylot.core.util.thread import Thread from pylot.core.util.thread import Thread
@@ -793,7 +793,7 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def connect_signals(self): def connect_signals(self):
self.qcombo_processed.activated.connect(self.parent().newWF) self.qcombo_processed.activated.connect(self.parent().newWF)
self.syn_checkbox.clicked.connect(self.parent().newWF) self.comp_checkbox.clicked.connect(self.parent().newWF)
def init_labels(self): def init_labels(self):
self.label_layout.addWidget(self.status_label) self.label_layout.addWidget(self.status_label)
@@ -804,13 +804,13 @@ class WaveformWidgetPG(QtWidgets.QWidget):
# use widgets as placeholder, so that child widgets keep position when others are hidden # use widgets as placeholder, so that child widgets keep position when others are hidden
mid_layout = QHBoxLayout() mid_layout = QHBoxLayout()
right_layout = QHBoxLayout() right_layout = QHBoxLayout()
mid_layout.addWidget(self.syn_checkbox) mid_layout.addWidget(self.comp_checkbox)
right_layout.addWidget(self.qcombo_processed) right_layout.addWidget(self.qcombo_processed)
mid_widget.setLayout(mid_layout) mid_widget.setLayout(mid_layout)
right_widget.setLayout(right_layout) right_widget.setLayout(right_layout)
self.label_layout.addWidget(mid_widget) self.label_layout.addWidget(mid_widget)
self.label_layout.addWidget(right_widget) self.label_layout.addWidget(right_widget)
self.syn_checkbox.setLayoutDirection(Qt.RightToLeft) self.comp_checkbox.setLayoutDirection(Qt.RightToLeft)
self.label_layout.setStretch(0, 4) self.label_layout.setStretch(0, 4)
self.label_layout.setStretch(1, 0) self.label_layout.setStretch(1, 0)
self.label_layout.setStretch(2, 0) self.label_layout.setStretch(2, 0)
@@ -825,7 +825,7 @@ class WaveformWidgetPG(QtWidgets.QWidget):
label = QtWidgets.QLabel() label = QtWidgets.QLabel()
self.perm_labels.append(label) self.perm_labels.append(label)
self.qcombo_processed = QtWidgets.QComboBox() self.qcombo_processed = QtWidgets.QComboBox()
self.syn_checkbox = QtWidgets.QCheckBox('synthetics') self.comp_checkbox = QtWidgets.QCheckBox('Load comparison data')
self.addQCboxItem('processed', 'green') self.addQCboxItem('processed', 'green')
self.addQCboxItem('raw', 'black') self.addQCboxItem('raw', 'black')
# self.perm_qcbox_right.setAlignment(2) # self.perm_qcbox_right.setAlignment(2)
@@ -834,9 +834,11 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def getPlotDict(self): def getPlotDict(self):
return self.plotdict return self.plotdict
def activateObspyDMToptions(self, activate): def activateObspyDMToptions(self, activate: bool) -> None:
self.syn_checkbox.setVisible(activate) self.qcombo_processed.setEnabled(activate)
self.qcombo_processed.setVisible(activate)
def activateCompareOptions(self, activate: bool) -> None:
self.comp_checkbox.setEnabled(activate)
def setPermText(self, number, text=None, color='black'): def setPermText(self, number, text=None, color='black'):
if not 0 <= number < len(self.perm_labels): if not 0 <= number < len(self.perm_labels):
@@ -860,10 +862,8 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def clearPlotDict(self): def clearPlotDict(self):
self.plotdict = dict() self.plotdict = dict()
def plotWFData(self, wfdata, wfsyn=None, title=None, zoomx=None, zoomy=None, def plotWFData(self, wfdata, wfsyn=None, title=None, scaleddata=False, mapping=True,
noiselevel=None, scaleddata=False, mapping=True, component='*', nth_sample=1, verbosity=0, method='normal', gain=1., shift_syn=0.2):
component='*', nth_sample=1, iniPick=None, verbosity=0,
method='normal', gain=1.):
if not wfdata: if not wfdata:
print('Nothing to plot.') print('Nothing to plot.')
return return
@@ -946,7 +946,7 @@ class WaveformWidgetPG(QtWidgets.QWidget):
[time for index, time in enumerate(time_ax_syn) if not index % nth_sample] if st_syn else []) [time for index, time in enumerate(time_ax_syn) if not index % nth_sample] if st_syn else [])
trace.data = np.array( trace.data = np.array(
[datum * gain + n for index, datum in enumerate(trace.data) if not index % nth_sample]) [datum * gain + n for index, datum in enumerate(trace.data) if not index % nth_sample])
trace_syn.data = np.array([datum + n for index, datum in enumerate(trace_syn.data) trace_syn.data = np.array([datum + n + shift_syn for index, datum in enumerate(trace_syn.data)
if not index % nth_sample] if st_syn else []) if not index % nth_sample] if st_syn else [])
plots.append((times, trace.data, plots.append((times, trace.data,
times_syn, trace_syn.data)) times_syn, trace_syn.data))
@@ -1135,12 +1135,12 @@ class PylotCanvas(FigureCanvas):
ax.set_xlim(self.cur_xlim) ax.set_xlim(self.cur_xlim)
ax.set_ylim(self.cur_ylim) ax.set_ylim(self.cur_ylim)
self.refreshPickDlgText() self.refreshPickDlgText()
ax.figure.canvas.draw() ax.figure.canvas.draw_idle()
def panRelease(self, gui_event): def panRelease(self, gui_event):
self.press = None self.press = None
self.press_rel = None self.press_rel = None
self.figure.canvas.draw() self.figure.canvas.draw_idle()
def panZoom(self, gui_event, threshold=2., factor=1.1): def panZoom(self, gui_event, threshold=2., factor=1.1):
if not gui_event.x and not gui_event.y: if not gui_event.x and not gui_event.y:
@@ -1358,11 +1358,15 @@ class PylotCanvas(FigureCanvas):
plot_positions[channel] = plot_pos plot_positions[channel] = plot_pos
return plot_positions return plot_positions
def plotWFData(self, wfdata, title=None, zoomx=None, zoomy=None, def plotWFData(self, wfdata, wfdata_compare=None, title=None, zoomx=None, zoomy=None,
noiselevel=None, scaleddata=False, mapping=True, noiselevel=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, iniPick=None, verbosity=0, component='*', nth_sample=1, iniPick=None, verbosity=0,
plot_additional=False, additional_channel=None, scaleToChannel=None, plot_additional=False, additional_channel=None, scaleToChannel=None,
snr=None): snr=None):
def get_wf_dict(data: Stream = Stream(), linecolor = 'k', offset: float = 0., **plot_kwargs):
return dict(data=data, linecolor=linecolor, offset=offset, plot_kwargs=plot_kwargs)
ax = self.axes[0] ax = self.axes[0]
ax.cla() ax.cla()
@@ -1373,21 +1377,33 @@ class PylotCanvas(FigureCanvas):
settings = QSettings() settings = QSettings()
compclass = SetChannelComponents.from_qsettings(settings) compclass = SetChannelComponents.from_qsettings(settings)
linecolor = (0., 0., 0., 1.) if not self.style else self.style['linecolor']['rgba_mpl']
plot_streams = dict(wfdata=get_wf_dict(linecolor=linecolor, linewidth=0.7),
wfdata_comp=get_wf_dict(offset=0.1, linecolor='b', alpha=0.7, linewidth=0.5))
if not component == '*': if not component == '*':
alter_comp = compclass.getCompPosition(component) alter_comp = compclass.getCompPosition(component)
# alter_comp = str(alter_comp[0]) # alter_comp = str(alter_comp[0])
st_select = wfdata.select(component=component) plot_streams['wfdata']['data'] = wfdata.select(component=component)
st_select += wfdata.select(component=alter_comp) plot_streams['wfdata']['data'] += wfdata.select(component=alter_comp)
if wfdata_compare:
plot_streams['wfdata_comp']['data'] = wfdata_compare.select(component=component)
plot_streams['wfdata_comp']['data'] += wfdata_compare.select(component=alter_comp)
else: else:
st_select = wfdata plot_streams['wfdata']['data'] = wfdata
if wfdata_compare:
plot_streams['wfdata_comp']['data'] = wfdata_compare
st_main = plot_streams['wfdata']['data']
if mapping: if mapping:
plot_positions = self.calcPlotPositions(st_select, compclass) plot_positions = self.calcPlotPositions(st_main, compclass)
# list containing tuples of network, station, channel and plot position (for sorting) # list containing tuples of network, station, channel and plot position (for sorting)
nslc = [] nslc = []
for plot_pos, trace in enumerate(st_select): for plot_pos, trace in enumerate(st_main):
if not trace.stats.channel[-1] in ['Z', 'N', 'E', '1', '2', '3']: if not trace.stats.channel[-1] in ['Z', 'N', 'E', '1', '2', '3']:
print('Warning: Unrecognized channel {}'.format(trace.stats.channel)) print('Warning: Unrecognized channel {}'.format(trace.stats.channel))
continue continue
@@ -1395,44 +1411,48 @@ class PylotCanvas(FigureCanvas):
nslc.sort() nslc.sort()
nslc.reverse() nslc.reverse()
linecolor = (0., 0., 0., 1.) if not self.style else self.style['linecolor']['rgba_mpl']
for n, seed_id in enumerate(nslc): for n, seed_id in enumerate(nslc):
network, station, location, channel = seed_id.split('.') network, station, location, channel = seed_id.split('.')
st = st_select.select(id=seed_id) for wf_name, wf_dict in plot_streams.items():
trace = st[0].copy() st_select = wf_dict.get('data')
if mapping: if not st_select:
n = plot_positions[trace.stats.channel] continue
if n > nmax: st = st_select.select(id=seed_id)
nmax = n trace = st[0].copy()
if verbosity: if mapping:
msg = 'plotting %s channel of station %s' % (channel, station) n = plot_positions[trace.stats.channel]
print(msg) if n > nmax:
stime = trace.stats.starttime - wfstart nmax = n
time_ax = prepTimeAxis(stime, trace) if verbosity:
if time_ax is not None: msg = 'plotting %s channel of station %s' % (channel, station)
if scaleToChannel: print(msg)
st_scale = wfdata.select(channel=scaleToChannel) stime = trace.stats.starttime - wfstart
if st_scale: time_ax = prepTimeAxis(stime, trace)
tr = st_scale[0] if time_ax is not None:
if scaleToChannel:
st_scale = wfdata.select(channel=scaleToChannel)
if st_scale:
tr = st_scale[0]
trace.detrend('constant')
trace.normalize(np.max(np.abs(tr.data)) * 2)
scaleddata = True
if not scaleddata:
trace.detrend('constant') trace.detrend('constant')
trace.normalize(np.max(np.abs(tr.data)) * 2) trace.normalize(np.max(np.abs(trace.data)) * 2)
scaleddata = True
if not scaleddata:
trace.detrend('constant')
trace.normalize(np.max(np.abs(trace.data)) * 2)
times = [time for index, time in enumerate(time_ax) if not index % nth_sample] offset = wf_dict.get('offset')
data = [datum + n for index, datum in enumerate(trace.data) if not index % nth_sample]
ax.axhline(n, color="0.5", lw=0.5) times = [time for index, time in enumerate(time_ax) if not index % nth_sample]
ax.plot(times, data, color=linecolor, linewidth=0.7) data = [datum + n + offset for index, datum in enumerate(trace.data) if not index % nth_sample]
if noiselevel is not None: ax.axhline(n, color="0.5", lw=0.5)
for level in [-noiselevel[channel], noiselevel[channel]]: ax.plot(times, data, color=wf_dict.get('linecolor'), **wf_dict.get('plot_kwargs'))
ax.plot([time_ax[0], time_ax[-1]], if noiselevel is not None:
[n + level, n + level], for level in [-noiselevel[channel], noiselevel[channel]]:
color=linecolor, ax.plot([time_ax[0], time_ax[-1]],
linestyle='dashed') [n + level, n + level],
self.setPlotDict(n, seed_id) color=wf_dict.get('linecolor'),
linestyle='dashed')
self.setPlotDict(n, seed_id)
if plot_additional and additional_channel: if plot_additional and additional_channel:
compare_stream = wfdata.select(channel=additional_channel) compare_stream = wfdata.select(channel=additional_channel)
if compare_stream: if compare_stream:
@@ -1659,8 +1679,8 @@ class PhaseDefaults(QtWidgets.QDialog):
class PickDlg(QDialog): class PickDlg(QDialog):
update_picks = QtCore.Signal(dict) update_picks = QtCore.Signal(dict)
def __init__(self, parent=None, data=None, station=None, network=None, location=None, picks=None, def __init__(self, parent=None, data=None, data_compare=None, station=None, network=None, location=None, picks=None,
autopicks=None, rotate=False, parameter=None, embedded=False, metadata=None, autopicks=None, rotate=False, parameter=None, embedded=False, metadata=None, show_comp_data=False,
event=None, filteroptions=None, model=None, wftype=None): event=None, filteroptions=None, model=None, wftype=None):
super(PickDlg, self).__init__(parent, Qt.Window) super(PickDlg, self).__init__(parent, Qt.Window)
self.orig_parent = parent self.orig_parent = parent
@@ -1669,6 +1689,7 @@ class PickDlg(QDialog):
# initialize attributes # initialize attributes
self.parameter = parameter self.parameter = parameter
self._embedded = embedded self._embedded = embedded
self.showCompData = show_comp_data
self.station = station self.station = station
self.network = network self.network = network
self.location = location self.location = location
@@ -1707,22 +1728,6 @@ class PickDlg(QDialog):
else: else:
self.filteroptions = FILTERDEFAULTS self.filteroptions = FILTERDEFAULTS
self.pick_block = False self.pick_block = False
self.nextStation = QtWidgets.QCheckBox('Continue with next station ')
# comparison channel
self.compareChannel = QtWidgets.QComboBox()
self.compareChannel.activated.connect(self.resetPlot)
# scale channel
self.scaleChannel = QtWidgets.QComboBox()
self.scaleChannel.activated.connect(self.resetPlot)
# initialize panning attributes
self.press = None
self.xpress = None
self.ypress = None
self.cur_xlim = None
self.cur_ylim = None
# set attribute holding data # set attribute holding data
if data is None or not data: if data is None or not data:
@@ -1735,6 +1740,31 @@ class PickDlg(QDialog):
raise Exception(errmsg) raise Exception(errmsg)
else: else:
self.data = data self.data = data
self.data_compare = data_compare
self.nextStation = QtWidgets.QCheckBox('Continue with next station ')
# comparison channel
self.referenceChannel = QtWidgets.QComboBox()
self.referenceChannel.activated.connect(self.resetPlot)
# comparison channel
self.compareCB = QtWidgets.QCheckBox()
self.compareCB.setChecked(self.showCompData)
self.compareCB.clicked.connect(self.switchCompData)
self.compareCB.clicked.connect(self.resetPlot)
self.compareCB.setVisible(bool(self.data_compare))
# scale channel
self.scaleChannel = QtWidgets.QComboBox()
self.scaleChannel.activated.connect(self.resetPlot)
# initialize panning attributes
self.press = None
self.xpress = None
self.ypress = None
self.cur_xlim = None
self.cur_ylim = None
self.stime, self.etime = full_range(self.getWFData()) self.stime, self.etime = full_range(self.getWFData())
@@ -1747,12 +1777,12 @@ class PickDlg(QDialog):
self.setupUi() self.setupUi()
# fill compare and scale channels # fill compare and scale channels
self.compareChannel.addItem('-', None) self.referenceChannel.addItem('-', None)
self.scaleChannel.addItem('individual', None) self.scaleChannel.addItem('individual', None)
for trace in self.getWFData(): for trace in self.getWFData():
channel = trace.stats.channel channel = trace.stats.channel
self.compareChannel.addItem(channel, trace) self.referenceChannel.addItem(channel, trace)
if not channel[-1] in ['Z', 'N', 'E', '1', '2', '3']: if not channel[-1] in ['Z', 'N', 'E', '1', '2', '3']:
print('Skipping unknown channel for scaling: {}'.format(channel)) print('Skipping unknown channel for scaling: {}'.format(channel))
continue continue
@@ -1769,7 +1799,7 @@ class PickDlg(QDialog):
if self.wftype is not None: if self.wftype is not None:
title += ' | ({})'.format(self.wftype) title += ' | ({})'.format(self.wftype)
self.multicompfig.plotWFData(wfdata=self.getWFData(), self.multicompfig.plotWFData(wfdata=self.getWFData(), wfdata_compare=self.getWFDataComp(),
title=title) title=title)
self.multicompfig.setZoomBorders2content() self.multicompfig.setZoomBorders2content()
@@ -1786,7 +1816,7 @@ class PickDlg(QDialog):
# init expected picks using obspy Taup # init expected picks using obspy Taup
try: try:
if self.metadata and model is not None: if self.metadata and model != "None":
self.model = TauPyModel(model) self.model = TauPyModel(model)
self.get_arrivals() self.get_arrivals()
self.drawArrivals() self.drawArrivals()
@@ -1876,7 +1906,7 @@ class PickDlg(QDialog):
self.sChannels.triggered.connect(self.updateChannelSettingsS) self.sChannels.triggered.connect(self.updateChannelSettingsS)
settings = QSettings() settings = QSettings()
self.autoFilterAction.setChecked(get_Bool(settings.value('autoFilter'))) self.autoFilterAction.setChecked(get_bool(settings.value('autoFilter')))
# create other widget elements # create other widget elements
phaseitems = [None] + list(FILTERDEFAULTS.keys()) phaseitems = [None] + list(FILTERDEFAULTS.keys())
@@ -1945,8 +1975,11 @@ class PickDlg(QDialog):
_dialtoolbar.addWidget(est_label) _dialtoolbar.addWidget(est_label)
_dialtoolbar.addWidget(self.plot_arrivals_button) _dialtoolbar.addWidget(self.plot_arrivals_button)
_dialtoolbar.addSeparator() _dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Compare to channel: ')) _dialtoolbar.addWidget(QtWidgets.QLabel('Plot reference channel: '))
_dialtoolbar.addWidget(self.compareChannel) _dialtoolbar.addWidget(self.referenceChannel)
_dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Compare: '))
_dialtoolbar.addWidget(self.compareCB)
_dialtoolbar.addSeparator() _dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Scaling: ')) _dialtoolbar.addWidget(QtWidgets.QLabel('Scaling: '))
_dialtoolbar.addWidget(self.scaleChannel) _dialtoolbar.addWidget(self.scaleChannel)
@@ -2281,7 +2314,7 @@ class PickDlg(QDialog):
def activatePicking(self): def activatePicking(self):
self.leave_rename_phase() self.leave_rename_phase()
self.renamePhaseAction.setEnabled(False) self.renamePhaseAction.setEnabled(False)
self.compareChannel.setEnabled(False) self.referenceChannel.setEnabled(False)
self.scaleChannel.setEnabled(False) self.scaleChannel.setEnabled(False)
phase = self.currentPhase phase = self.currentPhase
phaseID = self.getPhaseID(phase) phaseID = self.getPhaseID(phase)
@@ -2313,7 +2346,7 @@ class PickDlg(QDialog):
self.disconnectPressEvent() self.disconnectPressEvent()
self.multicompfig.connectEvents() self.multicompfig.connectEvents()
self.renamePhaseAction.setEnabled(True) self.renamePhaseAction.setEnabled(True)
self.compareChannel.setEnabled(True) self.referenceChannel.setEnabled(True)
self.scaleChannel.setEnabled(True) self.scaleChannel.setEnabled(True)
self.connect_pick_delete() self.connect_pick_delete()
self.draw() self.draw()
@@ -2355,7 +2388,7 @@ class PickDlg(QDialog):
settings = QSettings() settings = QSettings()
phaseID = self.getPhaseID(phase) phaseID = self.getPhaseID(phase)
if get_Bool(settings.value('useGuiFilter')) or gui_filter: if get_bool(settings.value('useGuiFilter')) or gui_filter:
filteroptions = self.filteroptions[phaseID] filteroptions = self.filteroptions[phaseID]
else: else:
filteroptions = getAutoFilteroptions(phaseID, self.parameter) filteroptions = getAutoFilteroptions(phaseID, self.parameter)
@@ -2386,6 +2419,12 @@ class PickDlg(QDialog):
def getWFData(self): def getWFData(self):
return self.data return self.data
def getWFDataComp(self):
if self.showCompData:
return self.data_compare
else:
return Stream()
def selectWFData(self, channel): def selectWFData(self, channel):
component = channel[-1].upper() component = channel[-1].upper()
wfdata = Stream() wfdata = Stream()
@@ -2507,24 +2546,33 @@ class PickDlg(QDialog):
stime = self.getStartTime() stime = self.getStartTime()
# copy data for plotting # copy wfdata for plotting
data = self.getWFData().copy() wfdata = self.getWFData().copy()
data = self.getPickPhases(data, phase) wfdata_comp = self.getWFDataComp().copy()
data.normalize() wfdata = self.getPickPhases(wfdata, phase)
if not data: wfdata_comp = self.getPickPhases(wfdata_comp, phase)
for wfd in [wfdata, wfdata_comp]:
if wfd:
wfd.normalize()
if not wfdata:
QtWidgets.QMessageBox.warning(self, 'No channel to plot', QtWidgets.QMessageBox.warning(self, 'No channel to plot',
'No channel to plot for phase: {}.'.format(phase)) 'No channel to plot for phase: {}. '
'Make sure to select the correct channels for P and S '
'in the menu in the top panel.'.format(phase))
self.leave_picking_mode() self.leave_picking_mode()
return return
# filter data and trace on which is picked prior to determination of SNR # filter wfdata and trace on which is picked prior to determination of SNR
filterphase = self.currentFilterPhase() filterphase = self.currentFilterPhase()
if filterphase: if filterphase:
filteroptions = self.getFilterOptions(filterphase).parseFilterOptions() filteroptions = self.getFilterOptions(filterphase).parseFilterOptions()
try: try:
data.detrend('linear') for wfd in [wfdata, wfdata_comp]:
data.filter(**filteroptions) if wfd:
# wfdata.filter(**filteroptions)# MP MP removed filtering of original data wfd.detrend('linear')
wfd.filter(**filteroptions)
# wfdata.filter(**filteroptions)# MP MP removed filtering of original wfdata
except ValueError as e: except ValueError as e:
self.qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Icon.Information, self.qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Icon.Information,
'Denied', 'Denied',
@@ -2534,8 +2582,8 @@ class PickDlg(QDialog):
snr = [] snr = []
noiselevels = {} noiselevels = {}
# determine SNR and noiselevel # determine SNR and noiselevel
for trace in data.traces: for trace in wfdata.traces:
st = data.select(channel=trace.stats.channel) st = wfdata.select(channel=trace.stats.channel)
stime_diff = trace.stats.starttime - stime stime_diff = trace.stats.starttime - stime
result = getSNR(st, (noise_win, gap_win, signal_win), ini_pick - stime_diff) result = getSNR(st, (noise_win, gap_win, signal_win), ini_pick - stime_diff)
snr.append(result[0]) snr.append(result[0])
@@ -2546,23 +2594,25 @@ class PickDlg(QDialog):
noiselevel = nfac noiselevel = nfac
noiselevels[trace.stats.channel] = noiselevel noiselevels[trace.stats.channel] = noiselevel
# prepare plotting of data # prepare plotting of wfdata
for trace in data: for wfd in [wfdata, wfdata_comp]:
t = prepTimeAxis(trace.stats.starttime - stime, trace) if wfd:
inoise = getnoisewin(t, ini_pick, noise_win, gap_win) for trace in wfd:
trace = demeanTrace(trace, inoise) t = prepTimeAxis(trace.stats.starttime - stime, trace)
# upscale trace data in a way that each trace is vertically zoomed to noiselevel*factor inoise = getnoisewin(t, ini_pick, noise_win, gap_win)
channel = trace.stats.channel trace = demeanTrace(trace, inoise)
noiselevel = noiselevels[channel] # upscale trace wfdata in a way that each trace is vertically zoomed to noiselevel*factor
noiseScaleFactor = self.calcNoiseScaleFactor(noiselevel, zoomfactor=5.) channel = trace.stats.channel
trace.data *= noiseScaleFactor noiselevel = noiselevels[channel]
noiselevels[channel] *= noiseScaleFactor noiseScaleFactor = self.calcNoiseScaleFactor(noiselevel, zoomfactor=5.)
trace.data *= noiseScaleFactor
noiselevels[channel] *= noiseScaleFactor
mean_snr = np.mean(snr) mean_snr = np.mean(snr)
x_res = getResolutionWindow(mean_snr, parameter.get('extent')) x_res = getResolutionWindow(mean_snr, parameter.get('extent'))
xlims = [ini_pick - x_res, ini_pick + x_res] xlims = [ini_pick - x_res, ini_pick + x_res]
ylims = list(np.array([-.5, .5]) + [0, len(data) - 1]) ylims = list(np.array([-.5, .5]) + [0, len(wfdata) - 1])
title = self.getStation() + ' picking mode' title = self.getStation() + ' picking mode'
title += ' | SNR: {}'.format(mean_snr) title += ' | SNR: {}'.format(mean_snr)
@@ -2570,9 +2620,10 @@ class PickDlg(QDialog):
filtops_str = transformFilteroptions2String(filteroptions) filtops_str = transformFilteroptions2String(filteroptions)
title += ' | Filteroptions: {}'.format(filtops_str) title += ' | Filteroptions: {}'.format(filtops_str)
plot_additional = bool(self.compareChannel.currentText()) plot_additional = bool(self.referenceChannel.currentText())
additional_channel = self.compareChannel.currentText() additional_channel = self.referenceChannel.currentText()
self.multicompfig.plotWFData(wfdata=data, self.multicompfig.plotWFData(wfdata=wfdata,
wfdata_compare=wfdata_comp,
title=title, title=title,
zoomx=xlims, zoomx=xlims,
zoomy=ylims, zoomy=ylims,
@@ -2653,7 +2704,7 @@ class PickDlg(QDialog):
minFMSNR = parameter.get('minFMSNR') minFMSNR = parameter.get('minFMSNR')
quality = get_quality_class(spe, parameter.get('timeerrorsP')) quality = get_quality_class(spe, parameter.get('timeerrorsP'))
if quality <= minFMweight and snr >= minFMSNR: if quality <= minFMweight and snr >= minFMSNR:
FM = fmpicker(self.getWFData().select(channel=channel), wfdata, parameter.get('fmpickwin'), FM = fmpicker(self.getWFData().select(channel=channel).copy(), wfdata.copy(), parameter.get('fmpickwin'),
pick - stime_diff) pick - stime_diff)
# save pick times for actual phase # save pick times for actual phase
@@ -2963,7 +3014,8 @@ class PickDlg(QDialog):
self.cur_xlim = self.multicompfig.axes[0].get_xlim() self.cur_xlim = self.multicompfig.axes[0].get_xlim()
self.cur_ylim = self.multicompfig.axes[0].get_ylim() self.cur_ylim = self.multicompfig.axes[0].get_ylim()
# self.multicompfig.updateCurrentLimits() # self.multicompfig.updateCurrentLimits()
data = self.getWFData().copy() wfdata = self.getWFData().copy()
wfdata_comp = self.getWFDataComp().copy()
title = self.getStation() title = self.getStation()
if filter: if filter:
filtoptions = None filtoptions = None
@@ -2971,19 +3023,22 @@ class PickDlg(QDialog):
filtoptions = self.getFilterOptions(self.getPhaseID(phase), gui_filter=True).parseFilterOptions() filtoptions = self.getFilterOptions(self.getPhaseID(phase), gui_filter=True).parseFilterOptions()
if filtoptions is not None: if filtoptions is not None:
data.detrend('linear') for wfd in [wfdata, wfdata_comp]:
data.taper(0.02, type='cosine') if wfd:
data.filter(**filtoptions) wfd.detrend('linear')
wfd.taper(0.02, type='cosine')
wfd.filter(**filtoptions)
filtops_str = transformFilteroptions2String(filtoptions) filtops_str = transformFilteroptions2String(filtoptions)
title += ' | Filteroptions: {}'.format(filtops_str) title += ' | Filteroptions: {}'.format(filtops_str)
if self.wftype is not None: if self.wftype is not None:
title += ' | ({})'.format(self.wftype) title += ' | ({})'.format(self.wftype)
plot_additional = bool(self.compareChannel.currentText()) plot_additional = bool(self.referenceChannel.currentText())
additional_channel = self.compareChannel.currentText() additional_channel = self.referenceChannel.currentText()
scale_channel = self.scaleChannel.currentText() scale_channel = self.scaleChannel.currentText()
self.multicompfig.plotWFData(wfdata=data, title=title, self.multicompfig.plotWFData(wfdata=wfdata, wfdata_compare=wfdata_comp,
title=title,
zoomx=self.getXLims(), zoomx=self.getXLims(),
zoomy=self.getYLims(), zoomy=self.getYLims(),
plot_additional=plot_additional, plot_additional=plot_additional,
@@ -3025,7 +3080,7 @@ class PickDlg(QDialog):
@staticmethod @staticmethod
def getChannelSettingsP(channel): def getChannelSettingsP(channel):
settings = QSettings() settings = QSettings()
rval = get_Bool(settings.value('p_channel_{}'.format(channel))) rval = get_bool(settings.value('p_channel_{}'.format(channel)))
compclass = SetChannelComponents.from_qsettings(settings) compclass = SetChannelComponents.from_qsettings(settings)
components = ['Z'] components = ['Z']
for component in components[:]: for component in components[:]:
@@ -3040,7 +3095,7 @@ class PickDlg(QDialog):
@staticmethod @staticmethod
def getChannelSettingsS(channel): def getChannelSettingsS(channel):
settings = QSettings() settings = QSettings()
rval = get_Bool(settings.value('s_channel_{}'.format(channel))) rval = get_bool(settings.value('s_channel_{}'.format(channel)))
compclass = SetChannelComponents.from_qsettings(settings) compclass = SetChannelComponents.from_qsettings(settings)
components = ['N', 'E'] components = ['N', 'E']
for component in components[:]: for component in components[:]:
@@ -3056,6 +3111,9 @@ class PickDlg(QDialog):
self.resetZoom() self.resetZoom()
self.refreshPlot() self.refreshPlot()
def switchCompData(self):
self.showCompData = self.compareCB.isChecked()
def refreshPlot(self): def refreshPlot(self):
if self.autoFilterAction.isChecked(): if self.autoFilterAction.isChecked():
self.filterActionP.setChecked(False) self.filterActionP.setChecked(False)
@@ -3611,14 +3669,14 @@ class TuneAutopicker(QWidget):
self.listWidget.scrollToBottom() self.listWidget.scrollToBottom()
def get_current_event(self): def get_current_event(self):
path = self.eventBox.currentText() path = self.get_current_event_fp()
return self.parent().project.getEventFromPath(path) return self.parent().project.getEventFromPath(path)
def get_current_event_name(self): def get_current_event_name(self):
return self.eventBox.currentText().split('/')[-1].split('*')[0] return self.eventBox.currentText().split('/')[-1].rstrip('*')
def get_current_event_fp(self): def get_current_event_fp(self):
return self.eventBox.currentText().split('*')[0] return self.eventBox.currentText().rstrip('*')
def get_current_event_picks(self, station): def get_current_event_picks(self, station):
event = self.get_current_event() event = self.get_current_event()
@@ -3666,11 +3724,13 @@ class TuneAutopicker(QWidget):
location = None location = None
wfdata = self.data.getWFData() wfdata = self.data.getWFData()
wfdata_comp = self.data.getWFDataComp()
metadata = self.parent().metadata metadata = self.parent().metadata
event = self.get_current_event() event = self.get_current_event()
filteroptions = self.parent().filteroptions filteroptions = self.parent().filteroptions
wftype = self.wftype if self.obspy_dmt else '' wftype = self.wftype if self.obspy_dmt else ''
self.pickDlg = PickDlg(self.parent(), data=wfdata.select(station=station).copy(), self.pickDlg = PickDlg(self.parent(), data=wfdata.select(station=station).copy(),
data_comp=wfdata_comp.select(station=station).copy(),
station=station, network=network, station=station, network=network,
location=location, parameter=self.parameter, location=location, parameter=self.parameter,
picks=self.get_current_event_picks(station), picks=self.get_current_event_picks(station),
@@ -3754,7 +3814,7 @@ class TuneAutopicker(QWidget):
self.plot_manual_pick_to_ax(ax=ax, picks=picks, phase='S', self.plot_manual_pick_to_ax(ax=ax, picks=picks, phase='S',
starttime=starttime, quality=qualitySpick) starttime=starttime, quality=qualitySpick)
for canvas in self.parent().canvas_dict.values(): for canvas in self.parent().canvas_dict.values():
canvas.draw() canvas.draw_idle()
def plot_manual_pick_to_ax(self, ax, picks, phase, starttime, quality): def plot_manual_pick_to_ax(self, ax, picks, phase, starttime, quality):
mpp = picks[phase]['mpp'] - starttime mpp = picks[phase]['mpp'] - starttime
@@ -5194,7 +5254,7 @@ class FilterOptionsDialog(QDialog):
'S': QtWidgets.QGroupBox('S Filter')} 'S': QtWidgets.QGroupBox('S Filter')}
settings = QSettings() settings = QSettings()
overwriteFilter = get_Bool(settings.value('useGuiFilter')) overwriteFilter = get_bool(settings.value('useGuiFilter'))
self.overwriteFilterCheckbox = QCheckBox('Overwrite filteroptions') self.overwriteFilterCheckbox = QCheckBox('Overwrite filteroptions')
self.overwriteFilterCheckbox.setToolTip('Overwrite filter settings for refined pick with GUI settings') self.overwriteFilterCheckbox.setToolTip('Overwrite filter settings for refined pick with GUI settings')
@@ -5663,9 +5723,23 @@ class ChooseWaveFormWindow(QWidget):
def submit(self): def submit(self):
matplotlib.pyplot.close(self.currentSpectro) matplotlib.pyplot.close(self.currentSpectro)
t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText() t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText()
self.currentSpectro = self.traces[ #self.currentSpectro = self.traces[
self.chooseBoxTraces.currentText()[3:]][self.chooseBoxComponent.currentText()].spectrogram(show=False, title=t) # self.chooseBoxTraces.currentText()[3:]][self.chooseBoxComponent.currentText()].spectrogram(show=False, title=t)
self.currentSpectro.show() #self.currentSpectro.show()
applyFFT()
def applyFFT(self, trace):
tra = self.traces[self.chooseBoxTraces.currentText()[3:]]['Z']
transformed = abs(np.fft.rfft(tra.data))
print ( transformed )
matplotlib.pyplot.plot ( transformed )
matplotlib.pyplot.show()
def applyFFTs(self, tra):
transformed = abs(np.fft.rfft(tra.data))
print ( transformed )
matplotlib.pyplot.plot ( transformed )
matplotlib.pyplot.show()
def submitN(self): def submitN(self):
matplotlib.pyplot.close(self.currentSpectro) matplotlib.pyplot.close(self.currentSpectro)
@@ -5681,13 +5755,6 @@ class ChooseWaveFormWindow(QWidget):
self.chooseBoxTraces.currentText()[3:]]['E'].spectrogram(show=False, title=t) self.chooseBoxTraces.currentText()[3:]]['E'].spectrogram(show=False, title=t)
self.currentSpectro.show() self.currentSpectro.show()
def submitZ(self):
matplotlib.pyplot.close(self.currentSpectro)
t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText()
self.currentSpectro = self.traces[
self.chooseBoxTraces.currentText()[3:]]['Z'].spectrogram(show=False, title=t)
self.currentSpectro.show()
# Creates a QComboBox and adds all traces provided # Creates a QComboBox and adds all traces provided
def createComboBoxTraces(self): def createComboBoxTraces(self):
if len(self.wFs) <= 0: if len(self.wFs) <= 0:
@@ -5714,6 +5781,86 @@ class ChooseWaveFormWindow(QWidget):
pass pass
class SpectrogramTab(QWidget):
def __init__(self, traces, wfdata, parent=None):
super(SpectrogramTab, self).__init__(parent)
self.setupUi()
self.traces = traces
self.wfdata = wfdata
def setupUi(self):
pass
def makeSpecFig(self, direction = 'Z', height = 0, width = 0, parent = None):
i = 0
grams = []
figure, axis = matplotlib.pyplot.subplots(len(self.traces), sharex=True)
start, end = full_range(self.wfdata)
if height != 0 and width != 0:
figure.figsize = (width, height)
figure.set_figwidth = width
figure.set_figheight = height
#figure.tight_layout()
for t in self.traces:
tra = self.traces[t][direction]
#print(start, end)
# Set Title
if i == 0:
if direction == 'Z':
figure.suptitle("section: vertical components")
elif direction == 'E':
figure.suptitle("section: east-west components")
elif direction == 'N':
figure.suptitle("section: north-south components")
axis[i].vlines(0, axis[i].get_ylim()[0], axis[i].get_ylim()[1],
colors='m', linestyles='dashed',
linewidth=2)
# Different axis settings for visual improvements
# axis[i].set_xlim(left=0, right=end - start)
# axis[i].spines['top'].set_visible(False)
# axis[i].spines['right'].set_visible(False)
# # axis[i].spines['left'].set_visible(False)
# axis[i].tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
# if not (len(self.traces) == i - 1):
# axis[i].spines['bottom'].set_visible(False)
# axis[i].set_yticks([])
# axis[i].set_ylabel(t, loc='center', rotation='horizontal')
#ax.axhline(n, color="0.5", lw=0.5)
grams.append(tra.spectrogram(show=False, axes=axis[i]))
i+=1
#figure.setXLims([0, end - start])
figure.set_tight_layout(True)
fC = FigureCanvas(figure)
return fC
#for t in self.traces:
# tra = self.traces[t]['Z']
# transformed = abs(np.fft.rfft(tra.data))
# axis[i].plot(transformed, label=t)
# # axis[i].tick_params(labelbottom=False)
# axis[i].spines['top'].set_visible(False)
# axis[i].spines['right'].set_visible(False)
# axis[i].spines['left'].set_visible(False)
# if not (len(self.traces) == i - 1):
# axis[i].spines['bottom'].set_visible(False)
# axis[i].set_yticks([])
# axis[i].set_ylabel(t, loc='center', rotation='horizontal')
# # axis[i].axis('off')
# i += 1
# # self.applyFFTs(t)
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest