30 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
0c3fca9299 Re-Added local changes that had been lost due to technical problems ( no access to old machine ) 2022-10-04 11:44:31 +02:00
2d33a60421 [Bugfix] Multiple small bugfixxes keeping NLL from working in python3.+ 2022-09-15 14:31:13 +02: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
22 changed files with 110512 additions and 109343 deletions

191
PyLoT.py
View File

@@ -60,7 +60,7 @@ except ImportError:
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from pylot.core.analysis.magnitude import LocalMagnitude, MomentMagnitude
from pylot.core.analysis.magnitude import LocalMagnitude, MomentMagnitude, calcsourcespec
from pylot.core.io.data import Data
from pylot.core.io.inputs import FilterOptions, PylotParameter
from autoPyLoT import autoPyLoT
@@ -76,14 +76,15 @@ from pylot.core.util.utils import fnConstructor, getLogin, \
full_range, readFilterInformation, pick_color_plt, \
pick_linestyle_plt, identifyPhaseID, excludeQualityClasses, \
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.event import Event
from pylot.core.io.location import create_creation_info, create_event
from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
PylotCanvas, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, CanvasWidget, AutoPickWidget, \
CompareEventsWidget, ProgressBarWidget, AddMetadataWidget, SingleTextLineDialog, LogWidget
CompareEventsWidget, ProgressBarWidget, AddMetadataWidget, SingleTextLineDialog, LogWidget, PickQualitiesFromXml, \
SourceSpecWindow, ChooseWaveFormWindow, SpectrogramTab
from pylot.core.util.array_map import Array_map
from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker
@@ -116,17 +117,19 @@ class MainWindow(QMainWindow):
if not infile:
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
print('Using default input file {}'.format(infile))
if os.path.isfile(infile) == False:
infile = QFileDialog().getOpenFileName(caption='Choose PyLoT-input file')
if os.path.isfile(infile) is False:
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",
"No PyLoT-input file declared!")
sys.exit(0)
self.infile = infile[0]
else:
self.infile = infile
"No PyLoT-input file declared! Using default parameters!")
infile = None
self._inputs = PylotParameter(infile)
if not infile:
self._inputs.reset_defaults()
self.infile = infile
self._props = None
self.gain = 1.
@@ -178,6 +181,7 @@ class MainWindow(QMainWindow):
self.autodata = Data(self)
self.fnames = None
self.fnames_comp = None
self._stime = None
# track deleted picks for logging
@@ -480,7 +484,7 @@ class MainWindow(QMainWindow):
"automatic pick "
"data.", 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',
icon=qualities_icon, tip='Histogram of pick qualities')
self.qualities_action.setEnabled(False)
@@ -493,7 +497,6 @@ class MainWindow(QMainWindow):
icon=eventlist_xml_icon,
tip='Create an Eventlist from a XML File')
self.eventlist_xml_action.setEnabled(False)
printAction = self.createAction(self, "&Print event ...",
self.show_event_information, QKeySequence.Print,
print_icon,
@@ -506,6 +509,8 @@ class MainWindow(QMainWindow):
logAction = self.createAction(self, "&Show Log", self.showLogWidget,
tip="""Display Log""")
logAction.setEnabled(use_logwidget)
# create button group for component selection
componentGroup = QActionGroup(self)
@@ -695,14 +700,17 @@ class MainWindow(QMainWindow):
wf_tab = QtWidgets.QWidget(self)
array_tab = QtWidgets.QWidget(self)
events_tab = QtWidgets.QWidget(self)
spectro_tab = QtWidgets.QWidget(self)
# init main widgets layouts
self.wf_layout = QtWidgets.QVBoxLayout()
self.array_layout = QtWidgets.QVBoxLayout()
self.events_layout = QtWidgets.QVBoxLayout()
self.spectro_layout = QtWidgets.QVBoxLayout()
wf_tab.setLayout(self.wf_layout)
array_tab.setLayout(self.array_layout)
events_tab.setLayout(self.events_layout)
spectro_tab.setLayout(self.spectro_layout)
# tighten up layouts inside tabs
for layout in [self.wf_layout, self.array_layout, self.events_layout]:
@@ -713,12 +721,14 @@ class MainWindow(QMainWindow):
self.tabs.addTab(wf_tab, 'Waveform Plot')
self.tabs.addTab(array_tab, 'Array Map')
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.wf_scroll_area)
self.wf_scroll_area.setWidgetResizable(True)
self.init_array_tab()
self.init_event_table()
self.init_spectro_tab()
self.tabs.setCurrentIndex(0)
self.eventLabel = QLabel()
@@ -731,15 +741,19 @@ class MainWindow(QMainWindow):
_widget.setLayout(self._main_layout)
_widget.showFullScreen()
if use_logwidget:
self.logwidget = LogWidget(parent=None)
self.logwidget.show()
sys.stdout = self.logwidget.stdout
sys.stderr = self.logwidget.stderr
self.stdout = self.logwidget.stdout
self.stderr = self.logwidget.stderr
self.setCentralWidget(_widget)
# Need to store PickQualities Window somewhere so it doesnt disappear
self.pickQualitiesWindow = None
def init_wfWidget(self):
xlab = self.startTime.strftime('seconds since %Y/%m/%d %H:%M:%S (%Z)')
plottitle = None # "Overview: {0} components ".format(self.getComponent())
@@ -1117,16 +1131,19 @@ class MainWindow(QMainWindow):
else:
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.
'''
# TODO: add dataStructure class for obspyDMT here, this is just a workaround!
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 not eventpath:
return
return []
fnames = [os.path.join(eventpath, f) for f in os.listdir(eventpath)]
else:
raise DatastructureError('not specified')
@@ -1170,7 +1187,7 @@ class MainWindow(QMainWindow):
'''
if not self.project:
self.createNewProject()
ed = getExistingDirectories(self, 'Select event directories...')
ed = GetExistingDirectories(self, 'Select event directories...')
if ed.exec_():
eventlist = [event for event in ed.selectedFiles() if not event.endswith('EVENTS-INFO')]
basepath = eventlist[0].split(os.path.basename(eventlist[0]))[0]
@@ -1371,7 +1388,7 @@ class MainWindow(QMainWindow):
index = eventBox.currentIndex()
tv = QtWidgets.QTableView()
header = tv.horizontalHeader()
header.setResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setStretchLastSection(True)
header.hide()
tv.verticalHeader().hide()
@@ -1668,15 +1685,54 @@ class MainWindow(QMainWindow):
def pickQualities(self):
path = self.get_current_event_path()
getQualitiesfromxml(path, self._inputs.get('timeerrorsP'), self._inputs.get('timeerrorsS'), plotflag=1)
return
(_, 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.showUI()
return
# WIP JG
def eventlistXml(self):
path = self._inputs['rootpath'] + '/' + self._inputs['datapath'] + '/' + self._inputs['database']
outpath = self.project.location[:self.project.location.rfind('/')]
geteventlistfromxml(path, outpath)
return
# WIP JG
def spectogramView(self):
global test
stations = []
names = []
traces = {}
for tr in self.get_data().wfdata.traces:
if not tr.stats.station in stations:
stations.append(tr.stats.station)
names.append(tr.stats.network + '.' + tr.stats.station)
for station in stations:
traces[station] = {}
for ch in ['Z', 'N', 'E']:
for tr in self.get_data().wfdata.select(component=ch).traces:
traces[tr.stats.station][ch] = tr
names.sort()
a = self.get_current_event()
print (self.get_data().wfdata.traces[0])
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):
if not self.compareoptions:
return
@@ -1862,6 +1918,13 @@ class MainWindow(QMainWindow):
self.newWF(plot=False)
self.update_obspy_dmt()
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):
'''
@@ -1892,13 +1955,20 @@ class MainWindow(QMainWindow):
def prepareLoadWaveformData(self):
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()
basepath = eventpath.split(os.path.basename(eventpath))[0]
self.obspy_dmt = check_obspydmt_structure(basepath)
self.dataPlot.activateObspyDMToptions(self.obspy_dmt)
if self.obspy_dmt:
self.prepareObspyDMT_data(eventpath)
self.dataPlot.activateCompareOptions(True)
def loadWaveformData(self):
'''
@@ -1929,7 +1999,7 @@ class MainWindow(QMainWindow):
tstop = None
self.data.setWFData(self.fnames,
self.fnames_syn,
self.fnames_comp,
checkRotated=True,
metadata=self.metadata,
tstart=tstart,
@@ -1937,7 +2007,7 @@ class MainWindow(QMainWindow):
def prepareObspyDMT_data(self, eventpath):
qcbox_processed = self.dataPlot.qcombo_processed
qcheckb_syn = self.dataPlot.syn_checkbox
qcheckb_syn = self.dataPlot.comp_checkbox
qcbox_processed.setEnabled(False)
qcheckb_syn.setEnabled(False)
for fpath in os.listdir(eventpath):
@@ -1945,8 +2015,8 @@ class MainWindow(QMainWindow):
if 'syngine' in fpath:
eventpath_syn = os.path.join(eventpath, fpath)
qcheckb_syn.setEnabled(True)
if self.dataPlot.syn_checkbox.isChecked():
self.fnames_syn = [os.path.join(eventpath_syn, filename) for filename in os.listdir(eventpath_syn)]
if self.dataPlot.comp_checkbox.isChecked():
self.fnames_comp = [os.path.join(eventpath_syn, filename) for filename in os.listdir(eventpath_syn)]
if 'processed' in fpath:
qcbox_processed.setEnabled(True)
if qcbox_processed.isEnabled():
@@ -2119,6 +2189,7 @@ class MainWindow(QMainWindow):
self.locateEventAction.setEnabled(True)
self.qualities_action.setEnabled(True)
self.eventlist_xml_action.setEnabled(True)
if True in self.comparable.values():
self.compare_action.setEnabled(True)
self.draw()
@@ -2226,7 +2297,7 @@ class MainWindow(QMainWindow):
comp = self.getComponent()
title = 'section: {0} components'.format(zne_text[comp])
wfst = self.get_data().getWFData()
wfsyn = self.get_data().getSynWFData()
wfsyn = self.get_data().getAltWFdata()
if self.filterActionP.isChecked() and filter:
self.filterWaveformData(plot=False, phase='P')
elif self.filterActionS.isChecked() and filter:
@@ -2235,7 +2306,7 @@ class MainWindow(QMainWindow):
# wfst += self.get_data().getWFData().select(component=alter_comp)
plotWidget = self.getPlotWidget()
self.adjustPlotHeight()
if get_Bool(settings.value('large_dataset')) == True:
if get_bool(settings.value('large_dataset')):
self.plot_method = 'fast'
else:
self.plot_method = 'normal'
@@ -2538,18 +2609,21 @@ class MainWindow(QMainWindow):
print("Warning! No network, station, and location info available!")
return
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()
wftype = self.dataPlot.qcombo_processed.currentText() if self.obspy_dmt else None
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,
location=location,
picks=self.getPicksOnStation(station, 'manual'),
autopicks=self.getPicksOnStation(station, 'auto'),
metadata=self.metadata, event=event,
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():
pickDlg.currentPhase = "P"
pickDlg.filterWFData()
@@ -2861,7 +2935,9 @@ class MainWindow(QMainWindow):
self.log_deleted_picks([deleted_pick])
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:
event_path = self.get_current_event_path()
for deleted_pick in deleted_picks:
@@ -2875,7 +2951,9 @@ class MainWindow(QMainWindow):
self.deleted_picks[event_path].append(deleted_pick)
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:
deleted_picks_from_file = self.load_deleted_picks(event_path)
except Exception as e:
@@ -3071,11 +3149,13 @@ class MainWindow(QMainWindow):
lt = locateTool[loctool]
# get working directory
locroot = parameter['nllocroot']
#locroot = 'E:/NLL/src/Insheim'
if locroot is None:
self.PyLoTprefs()
self.locate_event()
ctrfile = os.path.join(locroot, 'run', parameter['ctrfile'])
#ctrfile = 'E:/NLL/src/Insheim/run/Insheim_min1d032016.in'
ttt = parameter['ttpatter']
outfile = parameter['outpatter']
eventname = self.get_current_event_name()
@@ -3086,7 +3166,7 @@ class MainWindow(QMainWindow):
phasefile = os.path.join(obsdir, filename + '.obs')
lt.modify_inputs(ctrfile, locroot, filename, phasefile, ttt)
try:
lt.locate(ctrfile)
lt.locate(ctrfile, self._inputs)
except RuntimeError as e:
print(e.message)
# finally:
@@ -3140,7 +3220,7 @@ class MainWindow(QMainWindow):
'''
if checked: pass # dummy argument for QAction trigger signal
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:
self.init_array_tab()
return
@@ -3162,6 +3242,15 @@ class MainWindow(QMainWindow):
self.tabs.setCurrentIndex(index)
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):
'''
Start modal thread to init the array_map object.
@@ -3384,7 +3473,7 @@ class MainWindow(QMainWindow):
self.event_table.setCellWidget(r_index, c_index, item)
header = self.event_table.horizontalHeader()
header.setResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setStretchLastSection(True)
self.event_table.cellChanged[int, int].connect(cell_changed)
self.event_table.cellClicked[int, int].connect(cell_clicked)
@@ -3491,7 +3580,7 @@ class MainWindow(QMainWindow):
wf_select = Stream()
# restitute only picked traces
for station in np.unique(self.getPicks('manual').keys() + self.getPicks('auto').keys()):
for station in np.unique(list(self.getPicks('manual').keys()) + list(self.getPicks('auto').keys())):
wf_select += wf_copy.select(station=station)
corr_wf = restitute_data(wf_select, self.metadata)
@@ -3670,7 +3759,7 @@ class MainWindow(QMainWindow):
filename = fnm[0] + '.plp'
self.project.parameter = self._inputs
settings = QSettings()
autosaveXML = get_Bool(settings.value('autosaveXML', True))
autosaveXML = get_bool(settings.value('autosaveXML', True))
if autosaveXML:
self.exportEvents()
if not self.project.save(filename): return False
@@ -3694,7 +3783,7 @@ class MainWindow(QMainWindow):
self.metadata.clear_inventory()
self.project.parameter = self._inputs
settings = QSettings()
autosaveXML = get_Bool(settings.value('autosaveXML', True))
autosaveXML = get_bool(settings.value('autosaveXML', True))
if autosaveXML:
self.exportEvents()
if not self.project.save(): return False
@@ -3783,7 +3872,7 @@ class MainWindow(QMainWindow):
def helpHelp(self):
if checkurl():
form = HelpForm(self,
'https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/wiki')
'https://github.com/seismology-RUB/PyLoT')
else:
form = HelpForm(self, ':/help.html')
form.show()
@@ -3963,13 +4052,13 @@ class Project(object):
return project
class getExistingDirectories(QFileDialog):
class GetExistingDirectories(QFileDialog):
'''
File dialog with possibility to select multiple folders.
'''
def __init__(self, *args):
super(getExistingDirectories, self).__init__(*args)
super(GetExistingDirectories, self).__init__(*args)
self.setOption(self.DontUseNativeDialog, True)
self.setOption(self.ReadOnly, True)
self.setFileMode(self.Directory)
@@ -3995,16 +4084,7 @@ def create_window():
return app, app_created
def main(args=None):
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
def main(project_filename=None, pylot_infile=None, reset_qsettings=False):
# create the Qt application
pylot_app, app_created = create_window()
@@ -4053,4 +4133,5 @@ if __name__ == "__main__":
parser.add_argument('--reset_qsettings', default=False, action='store_true',
help='reset qsettings (debug option)')
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
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

View File

@@ -7,4 +7,6 @@
#$ -l h_vmem=2G
#$ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

218853
icons_rc_3.py

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -144,6 +144,10 @@ class Magnitude(object):
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
else:
# no scaling necessary
# Temporary fix needs rework
if (len(self.magnitudes.keys()) == 0):
print("Error in local magnitude calculation ")
return None
mag = ope.Magnitude(
mag=np.median([M.mag for M in self.magnitudes.values()]),
magnitude_type=self.type,
@@ -414,6 +418,10 @@ class MomentMagnitude(Magnitude):
distance = degrees2kilometers(a.distance)
azimuth = a.azimuth
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,
azimuth, incidence, self.p_attenuation,
self.plot_flag, self.verbose)
@@ -432,6 +440,40 @@ class MomentMagnitude(Magnitude):
self.event.station_magnitudes.append(magnitude)
self.magnitudes = (station, magnitude)
# WIP JG
def getSourceSpec(self):
for a in self.arrivals:
if a.phase not in 'pP':
continue
# make sure calculating Mo only from reliable onsets
# NLLoc: time_weight = 0 => do not use onset!
if a.time_weight == 0:
continue
pick = a.pick_id.get_referred_object()
station = pick.waveform_id.station_code
if len(self.stream) <= 2:
print("Station:" '{0}'.format(station))
print("WARNING: No instrument corrected data available,"
" no magnitude calculation possible! Go on.")
continue
wf = self.stream.select(station=station)
if not wf:
continue
try:
scopy = wf.copy()
except AssertionError:
print("WARNING: Something's wrong with the data,"
"station {},"
"no calculation of moment magnitude possible! Go on.".format(station))
continue
onset = pick.time
distance = degrees2kilometers(a.distance)
azimuth = a.azimuth
incidence = a.takeoff_angle
w0, fc, plt = calcsourcespec(scopy, onset, self.p_velocity, distance,
azimuth, incidence, self.p_attenuation,
3, self.verbose)
return w0, fc, plt
def calcMoMw(wfstream, w0, rho, vp, delta, verbosity=False):
'''
@@ -602,7 +644,7 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
N = min(int(np.power(m, 2)), 16384)
# N = int(np.power(m, 2))
y = dt * np.fft.fft(xdat, N)
Y = abs(y[: N / 2])
Y = abs(y[: int(N / 2)])
L = (N - 1) / freq
f = np.arange(0, fny, 1 / L)
@@ -679,6 +721,8 @@ def calcsourcespec(wfstream, onset, vp, delta, azimuth, incidence,
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitude [m/Hz]')
plt.grid()
if iplot == 3:
return w0, Fc, plt
plt.show()
try:
input()

View File

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

View File

@@ -280,6 +280,7 @@ def picksdict_from_picks(evt):
infile = os.path.join(os.path.expanduser('~'), '.pylot', 'pylot.in')
print('Using default input file {}'.format(infile))
parameter = PylotParameter(infile)
pick.phase_hint = identifyPhase(pick.phase_hint)
if pick.phase_hint == 'P':
errors = parameter['timeerrorsP']
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
for key in arrivals:
# P onsets
if arrivals[key].has_key('P'):
if 'P' in arrivals[key]:
try:
fm = arrivals[key]['P']['fm']
except KeyError as e:
@@ -551,7 +552,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
ss_ms,
pweight))
# 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 = '?'
onset = arrivals[key]['S']['mpp']
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
for key in arrivals:
# 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:
Ponset = arrivals[key]['P']['mpp']
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'
% (key, pyear, pmonth, pday, phh, pmm, Pss, pstd))
# 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:
Sonset = arrivals[key]['S']['mpp']
syear = Sonset.year
@@ -768,7 +769,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
usedarrivals = chooseArrivals(arrivals)
for key in usedarrivals:
# P onsets
if usedarrivals[key].has_key('P'):
if 'P' in usedarrivals[key]:
if usedarrivals[key]['P']['weight'] < 4:
n += 1
stat = key
@@ -782,7 +783,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
else:
fid.write('%-4sP%d%6.2f\n' % (stat, Pweight, Prt))
# S onsets
if usedarrivals[key].has_key('S'):
if 'S' in usedarrivals[key]:
if usedarrivals[key]['S']['weight'] < 4:
n += 1
stat = key
@@ -828,13 +829,13 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
# prefer manual picks
usedarrivals = chooseArrivals(arrivals)
for key in usedarrivals:
if usedarrivals[key].has_key('P'):
if 'P' in usedarrivals[key]:
# P onsets
if usedarrivals[key]['P']['weight'] < 4:
Ponset = usedarrivals[key]['P']['mpp']
Prt = Ponset - stime # onset time relative to source time
fid.write('%s %6.3f 1 P\n' % (key, Prt))
if usedarrivals[key].has_key('S'):
if 'S' in usedarrivals[key]:
# S onsets
if usedarrivals[key]['S']['weight'] < 4:
Sonset = usedarrivals[key]['S']['mpp']
@@ -879,7 +880,7 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None):
# prefer manual picks
usedarrivals = chooseArrivals(arrivals)
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:
stat = key
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
# write phase lines
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:
stat = key
ccode = arrivals[key]['P']['channel']
@@ -1014,7 +1015,6 @@ def chooseArrivals(arrivals):
: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
print("=== CHOOSE ===")
if len(arrivals) > 2:
return arrivals
if arrivals['auto'] and arrivals['manual']:

View File

@@ -82,8 +82,8 @@ def locate(fnin, parameter=None):
:param fnin: external program name
:return: None
"""
exe_path = which('NLLoc', parameter)
if exe_path is None:
exe_path = os.path.join(parameter['nllocbin'], 'NLLoc')
if not os.path.isfile(exe_path):
raise NLLocError('NonLinLoc executable not found; check your '
'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, \
getSNR, fmpicker, checkPonsets, wadaticheck, get_quality_class
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):
@@ -477,7 +477,7 @@ class AutopickStation(object):
if 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
# not the required parameters
exit_taupy()
@@ -525,7 +525,7 @@ class AutopickStation(object):
: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:
# modify pstart, pstop, sstart, sstop to be around theoretical onset if taupy should be used,
# else do nothing
@@ -544,7 +544,7 @@ class AutopickStation(object):
if self.horizontal_traces_exist():
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:
self.pick_s_phase()
except MissingTraceException as mte:
@@ -936,7 +936,7 @@ class AutopickStation(object):
"minFMSNR"]:
# if SNR is high enough, try to determine first motion of onset
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)
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)
@@ -1148,7 +1148,7 @@ class AutopickStation(object):
''.format(self.s_results.weight, self.s_results.snr, self.s_results.snrdb))
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'))
else:
# determine time window for calculating CF after P onset

View File

@@ -16,10 +16,9 @@ autoregressive prediction: application ot local and regional distances, Geophys.
:author: MAGS2 EP3 working group
"""
import numpy as np
from obspy.core import Stream
from scipy import signal
from obspy.core import Stream
class CharacteristicFunction(object):
@@ -259,7 +258,7 @@ class HOScf(CharacteristicFunction):
"""
Function to calculate skewness (statistics of order 3) or kurtosis
(statistics of order 4), using one long moving window, as published
in Kueperkoch et al. (2010).
in Kueperkoch et al. (2010), or order 2, i.e. STA/LTA.
:param data: data, time series (whether seismogram or CF)
:type data: tuple
:return: HOS cf
@@ -276,28 +275,47 @@ class HOScf(CharacteristicFunction):
elif self.getOrder() == 4: # this is kurtosis
y = np.power(xnp, 4)
y1 = np.power(xnp, 2)
elif self.getOrder() == 2: # this is variance, used for STA/LTA processing
y = np.power(xnp, 2)
y1 = np.power(xnp, 2)
# Initialisation
# t2: long term moving window
ilta = int(round(self.getTime2() / self.getIncrement()))
ista = int(round((self.getTime2() / 10) / self.getIncrement())) # TODO: still hard coded!!
lta = y[0]
lta1 = y1[0]
sta = y[0]
# moving windows
LTA = np.zeros(len(xnp))
STA = np.zeros(len(xnp))
for j in range(0, len(xnp)):
if j < 4:
LTA[j] = 0
STA[j] = 0
elif j <= ista:
lta = (y[j] + lta * (j - 1)) / j
if self.getOrder() == 2:
sta = (y[j] + sta * (j - 1)) / j
# elif j < 4:
elif j <= ilta:
lta = (y[j] + lta * (j - 1)) / j
lta1 = (y1[j] + lta1 * (j - 1)) / j
if self.getOrder() == 2:
sta = (y[j] - y[j - ista]) / ista + sta
else:
lta = (y[j] - y[j - ilta]) / ilta + lta
lta1 = (y1[j] - y1[j - ilta]) / ilta + lta1
if self.getOrder() == 2:
sta = (y[j] - y[j - ista]) / ista + sta
# define LTA
if self.getOrder() == 3:
LTA[j] = lta / np.power(lta1, 1.5)
elif self.getOrder() == 4:
LTA[j] = lta / np.power(lta1, 2)
else:
LTA[j] = lta
STA[j] = sta
# remove NaN's with first not-NaN-value,
# so autopicker doesnt pick discontinuity at start of the trace
@@ -306,7 +324,10 @@ class HOScf(CharacteristicFunction):
first = ind[0]
LTA[:first] = LTA[first]
self.cf = LTA
if self.getOrder() > 2:
self.cf = LTA
else: # order 2 means STA/LTA!
self.cf = STA / LTA
self.xcf = x

View File

@@ -336,7 +336,7 @@ class AICPicker(AutoPicker):
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
self.slope /= aicsmooth[iaicmax]
except ValueError as e:
except Exception as e:
print("AICPicker: Problems with data fitting! {}".format(e))
else:

View File

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

View File

@@ -75,7 +75,6 @@ class Array_map(QtWidgets.QWidget):
self._style = None if not hasattr(parent, '_style') else parent._style
self.show()
def init_map(self):
self.init_colormap()
@@ -464,17 +463,19 @@ class Array_map(QtWidgets.QWidget):
transform=ccrs.PlateCarree(), label='deleted'))
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:
network, station = self._station_onpick_ids[index].split('.')[:2]
pyl_mw = self._parent
try:
data = data.select(station=station)
if not data:
wfdata = wfdata.select(station=station)
wfdata_comp = wfdata_comp.select(station=station)
if not wfdata:
self._warn('No data for station {}'.format(station))
return
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),
autopicks=self._parent.get_current_event().getAutopick(station),
filteroptions=self._parent.filteroptions, metadata=self.metadata,

View File

@@ -271,7 +271,7 @@ class Metadata(object):
continue
invtype, robj = self._read_metadata_file(os.path.join(path_to_inventory, fname))
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,
'data': robj}
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.)
ALTSUFFIX = ['diff', 'n', 'g', '1', '2', '3']
FILTERDEFAULTS = readDefaultFilterInformation(os.path.join(os.path.expanduser('~'),
'.pylot',
'pylot.in'))
FILTERDEFAULTS = readDefaultFilterInformation()
TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'),
'.pylot',

View File

@@ -56,7 +56,7 @@ def which(program, parameter):
nllocpath = ":" + parameter.get('nllocbin')
os.environ['PATH'] += nllocpath
except Exception as e:
print(e.message)
print(e)
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)

View File

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

View File

@@ -37,15 +37,14 @@ def getAutoFilteroptions(phase, parameter):
return filteroptions
def readDefaultFilterInformation(fname):
def readDefaultFilterInformation():
"""
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
:rtype: dict
"""
pparam = PylotParameter(fname)
pparam = PylotParameter()
pparam.reset_defaults()
return readFilterInformation(pparam)
@@ -328,7 +327,7 @@ def get_None(value):
return value
def get_Bool(value):
def get_bool(value):
"""
Convert string representations of bools to their true boolean value
:param value:
@@ -336,13 +335,14 @@ def get_Bool(value):
:return: true boolean value
:rtype: bool
"""
if value in ['True', 'true']:
if type(value) is bool:
return value
elif value in ['True', 'true']:
return True
elif value in ['False', 'false']:
return False
else:
return value
return bool(value)
def four_digits(year):
"""
@@ -1169,7 +1169,7 @@ def correct_iplot(iplot):
try:
iplot = int(iplot)
except ValueError:
if get_Bool(iplot):
if get_bool(iplot):
iplot = 2
else:
iplot = 0

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 19 11:27:35 2014
@author: sebastianw
"""
@@ -54,7 +53,7 @@ from pylot.core.util.utils import prepTimeAxis, full_range, demeanTrace, isSorte
pick_linestyle_plt, pick_color_plt, \
check4rotated, check4doubled, merge_stream, identifyPhase, \
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
from autoPyLoT import autoPyLoT
from pylot.core.util.thread import Thread
@@ -794,7 +793,7 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def connect_signals(self):
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):
self.label_layout.addWidget(self.status_label)
@@ -805,13 +804,13 @@ class WaveformWidgetPG(QtWidgets.QWidget):
# use widgets as placeholder, so that child widgets keep position when others are hidden
mid_layout = QHBoxLayout()
right_layout = QHBoxLayout()
mid_layout.addWidget(self.syn_checkbox)
mid_layout.addWidget(self.comp_checkbox)
right_layout.addWidget(self.qcombo_processed)
mid_widget.setLayout(mid_layout)
right_widget.setLayout(right_layout)
self.label_layout.addWidget(mid_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(1, 0)
self.label_layout.setStretch(2, 0)
@@ -826,7 +825,7 @@ class WaveformWidgetPG(QtWidgets.QWidget):
label = QtWidgets.QLabel()
self.perm_labels.append(label)
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('raw', 'black')
# self.perm_qcbox_right.setAlignment(2)
@@ -835,9 +834,11 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def getPlotDict(self):
return self.plotdict
def activateObspyDMToptions(self, activate):
self.syn_checkbox.setVisible(activate)
self.qcombo_processed.setVisible(activate)
def activateObspyDMToptions(self, activate: bool) -> None:
self.qcombo_processed.setEnabled(activate)
def activateCompareOptions(self, activate: bool) -> None:
self.comp_checkbox.setEnabled(activate)
def setPermText(self, number, text=None, color='black'):
if not 0 <= number < len(self.perm_labels):
@@ -861,10 +862,8 @@ class WaveformWidgetPG(QtWidgets.QWidget):
def clearPlotDict(self):
self.plotdict = dict()
def plotWFData(self, wfdata, wfsyn=None, title=None, zoomx=None, zoomy=None,
noiselevel=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, iniPick=None, verbosity=0,
method='normal', gain=1.):
def plotWFData(self, wfdata, wfsyn=None, title=None, scaleddata=False, mapping=True,
component='*', nth_sample=1, verbosity=0, method='normal', gain=1., shift_syn=0.2):
if not wfdata:
print('Nothing to plot.')
return
@@ -947,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 [])
trace.data = np.array(
[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 [])
plots.append((times, trace.data,
times_syn, trace_syn.data))
@@ -1136,12 +1135,12 @@ class PylotCanvas(FigureCanvas):
ax.set_xlim(self.cur_xlim)
ax.set_ylim(self.cur_ylim)
self.refreshPickDlgText()
ax.figure.canvas.draw()
ax.figure.canvas.draw_idle()
def panRelease(self, gui_event):
self.press = None
self.press_rel = None
self.figure.canvas.draw()
self.figure.canvas.draw_idle()
def panZoom(self, gui_event, threshold=2., factor=1.1):
if not gui_event.x and not gui_event.y:
@@ -1359,11 +1358,15 @@ class PylotCanvas(FigureCanvas):
plot_positions[channel] = plot_pos
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,
component='*', nth_sample=1, iniPick=None, verbosity=0,
plot_additional=False, additional_channel=None, scaleToChannel=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.cla()
@@ -1374,21 +1377,33 @@ class PylotCanvas(FigureCanvas):
settings = QSettings()
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 == '*':
alter_comp = compclass.getCompPosition(component)
# alter_comp = str(alter_comp[0])
st_select = wfdata.select(component=component)
st_select += wfdata.select(component=alter_comp)
plot_streams['wfdata']['data'] = wfdata.select(component=component)
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:
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:
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)
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']:
print('Warning: Unrecognized channel {}'.format(trace.stats.channel))
continue
@@ -1396,44 +1411,48 @@ class PylotCanvas(FigureCanvas):
nslc.sort()
nslc.reverse()
linecolor = (0., 0., 0., 1.) if not self.style else self.style['linecolor']['rgba_mpl']
for n, seed_id in enumerate(nslc):
network, station, location, channel = seed_id.split('.')
st = st_select.select(id=seed_id)
trace = st[0].copy()
if mapping:
n = plot_positions[trace.stats.channel]
if n > nmax:
nmax = n
if verbosity:
msg = 'plotting %s channel of station %s' % (channel, station)
print(msg)
stime = trace.stats.starttime - wfstart
time_ax = prepTimeAxis(stime, trace)
if time_ax is not None:
if scaleToChannel:
st_scale = wfdata.select(channel=scaleToChannel)
if st_scale:
tr = st_scale[0]
for wf_name, wf_dict in plot_streams.items():
st_select = wf_dict.get('data')
if not st_select:
continue
st = st_select.select(id=seed_id)
trace = st[0].copy()
if mapping:
n = plot_positions[trace.stats.channel]
if n > nmax:
nmax = n
if verbosity:
msg = 'plotting %s channel of station %s' % (channel, station)
print(msg)
stime = trace.stats.starttime - wfstart
time_ax = prepTimeAxis(stime, trace)
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.normalize(np.max(np.abs(tr.data)) * 2)
scaleddata = True
if not scaleddata:
trace.detrend('constant')
trace.normalize(np.max(np.abs(trace.data)) * 2)
trace.normalize(np.max(np.abs(trace.data)) * 2)
times = [time for index, time in enumerate(time_ax) if not index % nth_sample]
data = [datum + n for index, datum in enumerate(trace.data) if not index % nth_sample]
ax.axhline(n, color="0.5", lw=0.5)
ax.plot(times, data, color=linecolor, linewidth=0.7)
if noiselevel is not None:
for level in [-noiselevel[channel], noiselevel[channel]]:
ax.plot([time_ax[0], time_ax[-1]],
[n + level, n + level],
color=linecolor,
linestyle='dashed')
self.setPlotDict(n, seed_id)
offset = wf_dict.get('offset')
times = [time for index, time in enumerate(time_ax) if not index % nth_sample]
data = [datum + n + offset for index, datum in enumerate(trace.data) if not index % nth_sample]
ax.axhline(n, color="0.5", lw=0.5)
ax.plot(times, data, color=wf_dict.get('linecolor'), **wf_dict.get('plot_kwargs'))
if noiselevel is not None:
for level in [-noiselevel[channel], noiselevel[channel]]:
ax.plot([time_ax[0], time_ax[-1]],
[n + level, n + level],
color=wf_dict.get('linecolor'),
linestyle='dashed')
self.setPlotDict(n, seed_id)
if plot_additional and additional_channel:
compare_stream = wfdata.select(channel=additional_channel)
if compare_stream:
@@ -1660,8 +1679,8 @@ class PhaseDefaults(QtWidgets.QDialog):
class PickDlg(QDialog):
update_picks = QtCore.Signal(dict)
def __init__(self, parent=None, data=None, station=None, network=None, location=None, picks=None,
autopicks=None, rotate=False, parameter=None, embedded=False, metadata=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, show_comp_data=False,
event=None, filteroptions=None, model=None, wftype=None):
super(PickDlg, self).__init__(parent, Qt.Window)
self.orig_parent = parent
@@ -1670,6 +1689,7 @@ class PickDlg(QDialog):
# initialize attributes
self.parameter = parameter
self._embedded = embedded
self.showCompData = show_comp_data
self.station = station
self.network = network
self.location = location
@@ -1708,22 +1728,6 @@ class PickDlg(QDialog):
else:
self.filteroptions = FILTERDEFAULTS
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
if data is None or not data:
@@ -1736,6 +1740,31 @@ class PickDlg(QDialog):
raise Exception(errmsg)
else:
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())
@@ -1748,12 +1777,12 @@ class PickDlg(QDialog):
self.setupUi()
# fill compare and scale channels
self.compareChannel.addItem('-', None)
self.referenceChannel.addItem('-', None)
self.scaleChannel.addItem('individual', None)
for trace in self.getWFData():
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']:
print('Skipping unknown channel for scaling: {}'.format(channel))
continue
@@ -1770,7 +1799,7 @@ class PickDlg(QDialog):
if self.wftype is not None:
title += ' | ({})'.format(self.wftype)
self.multicompfig.plotWFData(wfdata=self.getWFData(),
self.multicompfig.plotWFData(wfdata=self.getWFData(), wfdata_compare=self.getWFDataComp(),
title=title)
self.multicompfig.setZoomBorders2content()
@@ -1787,7 +1816,7 @@ class PickDlg(QDialog):
# init expected picks using obspy Taup
try:
if self.metadata and model is not None:
if self.metadata and model != "None":
self.model = TauPyModel(model)
self.get_arrivals()
self.drawArrivals()
@@ -1877,7 +1906,7 @@ class PickDlg(QDialog):
self.sChannels.triggered.connect(self.updateChannelSettingsS)
settings = QSettings()
self.autoFilterAction.setChecked(get_Bool(settings.value('autoFilter')))
self.autoFilterAction.setChecked(get_bool(settings.value('autoFilter')))
# create other widget elements
phaseitems = [None] + list(FILTERDEFAULTS.keys())
@@ -1946,8 +1975,11 @@ class PickDlg(QDialog):
_dialtoolbar.addWidget(est_label)
_dialtoolbar.addWidget(self.plot_arrivals_button)
_dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Compare to channel: '))
_dialtoolbar.addWidget(self.compareChannel)
_dialtoolbar.addWidget(QtWidgets.QLabel('Plot reference channel: '))
_dialtoolbar.addWidget(self.referenceChannel)
_dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Compare: '))
_dialtoolbar.addWidget(self.compareCB)
_dialtoolbar.addSeparator()
_dialtoolbar.addWidget(QtWidgets.QLabel('Scaling: '))
_dialtoolbar.addWidget(self.scaleChannel)
@@ -2282,7 +2314,7 @@ class PickDlg(QDialog):
def activatePicking(self):
self.leave_rename_phase()
self.renamePhaseAction.setEnabled(False)
self.compareChannel.setEnabled(False)
self.referenceChannel.setEnabled(False)
self.scaleChannel.setEnabled(False)
phase = self.currentPhase
phaseID = self.getPhaseID(phase)
@@ -2314,7 +2346,7 @@ class PickDlg(QDialog):
self.disconnectPressEvent()
self.multicompfig.connectEvents()
self.renamePhaseAction.setEnabled(True)
self.compareChannel.setEnabled(True)
self.referenceChannel.setEnabled(True)
self.scaleChannel.setEnabled(True)
self.connect_pick_delete()
self.draw()
@@ -2356,7 +2388,7 @@ class PickDlg(QDialog):
settings = QSettings()
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]
else:
filteroptions = getAutoFilteroptions(phaseID, self.parameter)
@@ -2387,6 +2419,12 @@ class PickDlg(QDialog):
def getWFData(self):
return self.data
def getWFDataComp(self):
if self.showCompData:
return self.data_compare
else:
return Stream()
def selectWFData(self, channel):
component = channel[-1].upper()
wfdata = Stream()
@@ -2508,24 +2546,33 @@ class PickDlg(QDialog):
stime = self.getStartTime()
# copy data for plotting
data = self.getWFData().copy()
data = self.getPickPhases(data, phase)
data.normalize()
if not data:
# copy wfdata for plotting
wfdata = self.getWFData().copy()
wfdata_comp = self.getWFDataComp().copy()
wfdata = self.getPickPhases(wfdata, phase)
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',
'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()
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()
if filterphase:
filteroptions = self.getFilterOptions(filterphase).parseFilterOptions()
try:
data.detrend('linear')
data.filter(**filteroptions)
# wfdata.filter(**filteroptions)# MP MP removed filtering of original data
for wfd in [wfdata, wfdata_comp]:
if wfd:
wfd.detrend('linear')
wfd.filter(**filteroptions)
# wfdata.filter(**filteroptions)# MP MP removed filtering of original wfdata
except ValueError as e:
self.qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Icon.Information,
'Denied',
@@ -2535,8 +2582,8 @@ class PickDlg(QDialog):
snr = []
noiselevels = {}
# determine SNR and noiselevel
for trace in data.traces:
st = data.select(channel=trace.stats.channel)
for trace in wfdata.traces:
st = wfdata.select(channel=trace.stats.channel)
stime_diff = trace.stats.starttime - stime
result = getSNR(st, (noise_win, gap_win, signal_win), ini_pick - stime_diff)
snr.append(result[0])
@@ -2547,23 +2594,25 @@ class PickDlg(QDialog):
noiselevel = nfac
noiselevels[trace.stats.channel] = noiselevel
# prepare plotting of data
for trace in data:
t = prepTimeAxis(trace.stats.starttime - stime, trace)
inoise = getnoisewin(t, ini_pick, noise_win, gap_win)
trace = demeanTrace(trace, inoise)
# upscale trace data in a way that each trace is vertically zoomed to noiselevel*factor
channel = trace.stats.channel
noiselevel = noiselevels[channel]
noiseScaleFactor = self.calcNoiseScaleFactor(noiselevel, zoomfactor=5.)
trace.data *= noiseScaleFactor
noiselevels[channel] *= noiseScaleFactor
# prepare plotting of wfdata
for wfd in [wfdata, wfdata_comp]:
if wfd:
for trace in wfd:
t = prepTimeAxis(trace.stats.starttime - stime, trace)
inoise = getnoisewin(t, ini_pick, noise_win, gap_win)
trace = demeanTrace(trace, inoise)
# upscale trace wfdata in a way that each trace is vertically zoomed to noiselevel*factor
channel = trace.stats.channel
noiselevel = noiselevels[channel]
noiseScaleFactor = self.calcNoiseScaleFactor(noiselevel, zoomfactor=5.)
trace.data *= noiseScaleFactor
noiselevels[channel] *= noiseScaleFactor
mean_snr = np.mean(snr)
x_res = getResolutionWindow(mean_snr, parameter.get('extent'))
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 += ' | SNR: {}'.format(mean_snr)
@@ -2571,9 +2620,10 @@ class PickDlg(QDialog):
filtops_str = transformFilteroptions2String(filteroptions)
title += ' | Filteroptions: {}'.format(filtops_str)
plot_additional = bool(self.compareChannel.currentText())
additional_channel = self.compareChannel.currentText()
self.multicompfig.plotWFData(wfdata=data,
plot_additional = bool(self.referenceChannel.currentText())
additional_channel = self.referenceChannel.currentText()
self.multicompfig.plotWFData(wfdata=wfdata,
wfdata_compare=wfdata_comp,
title=title,
zoomx=xlims,
zoomy=ylims,
@@ -2654,7 +2704,7 @@ class PickDlg(QDialog):
minFMSNR = parameter.get('minFMSNR')
quality = get_quality_class(spe, parameter.get('timeerrorsP'))
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)
# save pick times for actual phase
@@ -2964,7 +3014,8 @@ class PickDlg(QDialog):
self.cur_xlim = self.multicompfig.axes[0].get_xlim()
self.cur_ylim = self.multicompfig.axes[0].get_ylim()
# self.multicompfig.updateCurrentLimits()
data = self.getWFData().copy()
wfdata = self.getWFData().copy()
wfdata_comp = self.getWFDataComp().copy()
title = self.getStation()
if filter:
filtoptions = None
@@ -2972,19 +3023,22 @@ class PickDlg(QDialog):
filtoptions = self.getFilterOptions(self.getPhaseID(phase), gui_filter=True).parseFilterOptions()
if filtoptions is not None:
data.detrend('linear')
data.taper(0.02, type='cosine')
data.filter(**filtoptions)
for wfd in [wfdata, wfdata_comp]:
if wfd:
wfd.detrend('linear')
wfd.taper(0.02, type='cosine')
wfd.filter(**filtoptions)
filtops_str = transformFilteroptions2String(filtoptions)
title += ' | Filteroptions: {}'.format(filtops_str)
if self.wftype is not None:
title += ' | ({})'.format(self.wftype)
plot_additional = bool(self.compareChannel.currentText())
additional_channel = self.compareChannel.currentText()
plot_additional = bool(self.referenceChannel.currentText())
additional_channel = self.referenceChannel.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(),
zoomy=self.getYLims(),
plot_additional=plot_additional,
@@ -3026,7 +3080,7 @@ class PickDlg(QDialog):
@staticmethod
def getChannelSettingsP(channel):
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)
components = ['Z']
for component in components[:]:
@@ -3041,7 +3095,7 @@ class PickDlg(QDialog):
@staticmethod
def getChannelSettingsS(channel):
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)
components = ['N', 'E']
for component in components[:]:
@@ -3057,6 +3111,9 @@ class PickDlg(QDialog):
self.resetZoom()
self.refreshPlot()
def switchCompData(self):
self.showCompData = self.compareCB.isChecked()
def refreshPlot(self):
if self.autoFilterAction.isChecked():
self.filterActionP.setChecked(False)
@@ -3161,7 +3218,6 @@ class CanvasWidget(QWidget):
class MultiEventWidget(QWidget):
start = Signal()
'''
'''
def __init__(self, options=None, parent=None, windowflag=Qt.Window):
@@ -3438,7 +3494,6 @@ class TuneAutopicker(QWidget):
update = QtCore.Signal(str)
'''
QWidget used to modifiy and test picking parameters for autopicking algorithm.
:param: parent
:type: PyLoT Mainwindow
'''
@@ -3614,14 +3669,14 @@ class TuneAutopicker(QWidget):
self.listWidget.scrollToBottom()
def get_current_event(self):
path = self.eventBox.currentText()
path = self.get_current_event_fp()
return self.parent().project.getEventFromPath(path)
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):
return self.eventBox.currentText().split('*')[0]
return self.eventBox.currentText().rstrip('*')
def get_current_event_picks(self, station):
event = self.get_current_event()
@@ -3669,11 +3724,13 @@ class TuneAutopicker(QWidget):
location = None
wfdata = self.data.getWFData()
wfdata_comp = self.data.getWFDataComp()
metadata = self.parent().metadata
event = self.get_current_event()
filteroptions = self.parent().filteroptions
wftype = self.wftype if self.obspy_dmt else ''
self.pickDlg = PickDlg(self.parent(), data=wfdata.select(station=station).copy(),
data_comp=wfdata_comp.select(station=station).copy(),
station=station, network=network,
location=location, parameter=self.parameter,
picks=self.get_current_event_picks(station),
@@ -3757,7 +3814,7 @@ class TuneAutopicker(QWidget):
self.plot_manual_pick_to_ax(ax=ax, picks=picks, phase='S',
starttime=starttime, quality=qualitySpick)
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):
mpp = picks[phase]['mpp'] - starttime
@@ -3959,10 +4016,8 @@ class PylotParaBox(QtWidgets.QWidget):
def __init__(self, parameter, parent=None, windowflag=Qt.Window):
'''
Generate Widget containing parameters for PyLoT.
:param: parameter
:type: PylotParameter (object)
'''
QtWidgets.QWidget.__init__(self, parent, windowflag)
self.parameter = parameter
@@ -5199,7 +5254,7 @@ class FilterOptionsDialog(QDialog):
'S': QtWidgets.QGroupBox('S Filter')}
settings = QSettings()
overwriteFilter = get_Bool(settings.value('useGuiFilter'))
overwriteFilter = get_bool(settings.value('useGuiFilter'))
self.overwriteFilterCheckbox = QCheckBox('Overwrite filteroptions')
self.overwriteFilterCheckbox.setToolTip('Overwrite filter settings for refined pick with GUI settings')
@@ -5561,6 +5616,251 @@ class HelpForm(QDialog):
self.pageLabel.setText(self.webBrowser.title())
class PickQualitiesFromXml(QWidget):
"""
PyLoT widget PickQualitiesFromXml is a QWidget object. It is an UI that enables the user
to create a plot showing the pick qualities in the event selected inside the QComboBox created
by this Widget. The user can also choose to select all Events.
The plot is being shown by a FigureCanvas from matlplotlib.
"""
def __init__(self, parent=None, figure=Figure(), path="", inputVar=None):
super(PickQualitiesFromXml, self).__init__(parent)
self.fig = figure
self.chooseBox = QComboBox()
self.path = path
self.inputs = inputVar
self.setupUi()
def setupUi(self):
self.setWindowTitle("Get pick qualities from xml files")
self.main_layout = QtWidgets.QVBoxLayout()
self.figureC = FigureCanvas(self.fig)
self.chooseBox = self.createComboBox()
if self.chooseBox:
self.main_layout.addWidget(self.chooseBox)
self.main_layout.addWidget(self.figureC)
self.setLayout(self.main_layout)
def showUI(self):
self.show()
# Creates a QComboBox and adds all events in the current folder as options. Also gives the option to choose all events
def createComboBox(self):
self.chooseBox.addItems(glob.glob(os.path.join(os.path.dirname(self.path) + "/*/", '*.xml')))
self.chooseBox.addItem("All")
self.chooseBox.currentIndexChanged.connect(self.selectionChanged)
self.chooseBox.setCurrentIndex(self.chooseBox.count() - 1)
return self.chooseBox
# Function that gets called when the user changes the current selection in the QComboBox. Redraws the plot with the new data
def selectionChanged(self):
self.figureC.setParent(None)
if self.chooseBox.currentIndex() == self.chooseBox.count() - 1:
(_, _, plot) = getQualitiesfromxml(self.path, self.inputs.get('timeerrorsP'),
self.inputs.get('timeerrorsS'), plotflag=1)
self.figureC = FigureCanvas(plot)
else:
(_, _, plot) = getQualitiesfromxml(self.path, self.inputs.get('timeerrorsP'),
self.inputs.get('timeerrorsS'), plotflag=1,
xmlnames=[self.chooseBox.currentText()])
self.figureC = FigureCanvas(plot)
self.figureC.draw()
self.main_layout.addWidget(self.figureC)
self.setLayout(self.main_layout)
class SourceSpecWindow(QWidget):
def __init__(self, parent=None, figure=Figure()):
super(SourceSpecWindow, self).__init__(parent)
self.main_layout = QVBoxLayout()
self.setWindowTitle("Display source spectrum from selected trace")
self.fig = figure
def setupUi(self):
self.figureC = FigureCanvas(self.fig)
self.main_layout.addWidget(self.figureC)
self.setLayout(self.main_layout)
class ChooseWaveFormWindow(QWidget):
def __init__(self, parent=None, WaveForms=[], traces=[], stream=None, chooseB=False):
super(ChooseWaveFormWindow, self).__init__(parent)
self.main_layout = QVBoxLayout()
self.setWindowTitle("Choose trace to display source spectrum")
self.wFs = WaveForms
self.chooseBoxTraces = QComboBox()
self.chooseBoxComponent = QComboBox()
self.submitButton = QPushButton(text='test')
self.chooseB = chooseB
self.verticalButton = QPushButton(text='Z')
self.northButton = QPushButton(text='N')
self.eastButton = QPushButton(text='E')
self.component = ''
self.traces = traces
self.stream = stream
self.setupUI()
self.currentSpectro = Figure()
def setupUI(self):
self.submitButton.clicked.connect(self.submit)
self.createComboBoxTraces()
self.main_layout.addWidget(self.chooseBoxTraces)
if self.chooseB:
self.createComboBoxComponent()
self.main_layout.addWidget(self.submitButton)
self.main_layout.addWidget(self.chooseBoxComponent)
else:
self.createButtonsComponent()
self.setLayout(self.main_layout)
def submit(self):
matplotlib.pyplot.close(self.currentSpectro)
t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText()
#self.currentSpectro = self.traces[
# self.chooseBoxTraces.currentText()[3:]][self.chooseBoxComponent.currentText()].spectrogram(show=False, title=t)
#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):
matplotlib.pyplot.close(self.currentSpectro)
t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText()
self.currentSpectro = self.traces[
self.chooseBoxTraces.currentText()[3:]]['N'].spectrogram(show=False, title=t)
self.currentSpectro.show()
def submitE(self):
matplotlib.pyplot.close(self.currentSpectro)
t = self.chooseBoxTraces.currentText() + " " + self.chooseBoxComponent.currentText()
self.currentSpectro = self.traces[
self.chooseBoxTraces.currentText()[3:]]['E'].spectrogram(show=False, title=t)
self.currentSpectro.show()
# Creates a QComboBox and adds all traces provided
def createComboBoxTraces(self):
if len(self.wFs) <= 0:
raise 'No traces provided'
self.chooseBoxTraces.addItems(self.wFs)
self.chooseBoxTraces.currentIndexChanged.connect(self.selectionChanged)
self.chooseBoxTraces.setCurrentIndex(0)
return self.chooseBoxTraces
def createButtonsComponent(self):
self.northButton.clicked.connect(self.submitN)
self.eastButton.clicked.connect(self.submitE)
self.verticalButton.clicked.connect(self.submitZ)
self.main_layout.addWidget(self.verticalButton)
self.main_layout.addWidget(self.northButton)
self.main_layout.addWidget(self.eastButton)
def createComboBoxComponent(self):
self.chooseBoxComponent.addItems(['Z', 'N', 'E'])
# Function that gets called when the user changes the current selection in the QComboBox.
def selectionChanged(self):
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__':
import doctest