Compare commits

...

5 Commits

7 changed files with 137 additions and 17 deletions

View File

@ -76,7 +76,7 @@ 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, get_pylot_eventfile_with_extension
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
@ -84,7 +84,7 @@ 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, PickQualitiesFromXml, \
SourceSpecWindow, ChooseWaveFormWindow, SpectrogramTab
SourceSpecWindow, ChooseWaveFormWindow, SpectrogramTab, SearchFileByExtensionDialog
from pylot.core.util.array_map import Array_map
from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker
@ -1006,16 +1006,15 @@ class MainWindow(QMainWindow):
return
refresh = False
events = self.project.eventlist
sld = SingleTextLineDialog(label='Specify file extension: ', default_text='.xml')
sld = SearchFileByExtensionDialog(label='Specify file extension: ', default_text='.xml',
events=events)
if not sld.exec_():
return
fext = sld.lineEdit.text()
# fext = '.xml'
for event in events:
path = event.path
eventname = path.split('/')[-1] # or event.pylot_id
filename = os.path.join(path, 'PyLoT_' + eventname + fext)
if os.path.isfile(filename):
filename = get_pylot_eventfile_with_extension(event, fext)
if filename:
self.load_data(filename, draw=False, event=event, overwrite=True)
refresh = True
if not refresh:
@ -1887,6 +1886,7 @@ class MainWindow(QMainWindow):
# which will read in data input twice. Therefore current tab is changed to 0
# in loadProject before calling this function.
self.fill_eventbox()
#print(f'{self.get_current_event()=}')
plotted = False
if self.tabs.currentIndex() == 2:
self.init_event_table()
@ -1921,7 +1921,6 @@ class MainWindow(QMainWindow):
self.spectro_layout.addWidget(newSpectroWidget)
self.spectroWidget = newSpectroWidget
def newWF(self, event=None, plot=True):
'''
Load new data and plot if necessary.
@ -1972,6 +1971,8 @@ class MainWindow(QMainWindow):
# ans = False
settings = QSettings()
# process application events to wait for event items to appear in event box
QApplication.processEvents()
curr_event = self.get_current_event()
if not curr_event:
print('Could not find current event. Try reload?')
@ -3633,7 +3634,7 @@ class MainWindow(QMainWindow):
return True
return False
def update_status(self, message, duration=5000):
def update_status(self, message, duration=10000):
self.statusBar().showMessage(message, duration)
if self.get_data() is not None:
if not self.get_current_event() or not self.project.location:

View File

@ -13,6 +13,7 @@ import obspy
from PySide2 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from pylot.core.util.utils import identifyPhaseID
from scipy.interpolate import griddata
from pylot.core.pick.utils import get_quality_class
@ -279,9 +280,12 @@ class Array_map(QtWidgets.QWidget):
self.canvas.axes.figure.canvas.draw_idle()
def onpick(self, event):
btn_msg = {1: ' in selection. Aborted', 2: ' to delete a pick on. Aborted', 3: ' to display info.'}
ind = event.ind
button = event.mouseevent.button
if ind == []:
msg_reason = None
if len(ind) > 1:
self._parent.update_status(f'Found more than one station {btn_msg.get(button)}')
return
if button == 1:
self.openPickDlg(ind)
@ -384,7 +388,14 @@ class Array_map(QtWidgets.QWidget):
try:
station_name = st_id.split('.')[-1]
# current_picks_dict: auto or manual
pick = self.current_picks_dict()[station_name][phase]
station_picks = self.current_picks_dict().get(station_name)
if not station_picks:
continue
for phase_hint, pick in station_picks.items():
if identifyPhaseID(phase_hint) == phase:
break
else:
continue
if pick['picker'] == 'auto':
if not pick['spe']:
continue

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import glob
import logging
import os
import sys
@ -189,7 +190,11 @@ class Metadata(object):
metadata = self.get_metadata(seed_id, time)
if not metadata:
return
try:
return metadata['data'].get_coordinates(seed_id, time)
# no specific exception defined in obspy inventory
except Exception as e:
logging.warning(f'Could not get metadata for {seed_id}')
def get_all_coordinates(self):
def stat_info_from_parser(parser):

View File

@ -42,7 +42,7 @@ def main(project_file_path, manual=False, auto=True, file_format='png', f_ext=''
for item in input_list:
array_map_worker(item)
else:
pool = multiprocessing.Pool(ncores)
pool = multiprocessing.Pool(ncores, maxtasksperchild=1000)
pool.map(array_map_worker, input_list)
pool.close()
pool.join()

View File

@ -160,7 +160,7 @@ class MultiThread(QThread):
try:
if not self.ncores:
self.ncores = multiprocessing.cpu_count()
pool = multiprocessing.Pool(self.ncores)
pool = multiprocessing.Pool(self.ncores, maxtasksperchild=1000)
self.data = pool.map_async(self.func, self.args, callback=self.emitDone)
# self.data = pool.apply_async(self.func, self.shotlist, callback=self.emitDone) #emit each time returned
pool.close()

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import hashlib
import logging
import os
import platform
import re
@ -119,7 +120,7 @@ def gen_Pool(ncores=0):
print('gen_Pool: Generated multiprocessing Pool with {} cores\n'.format(ncores))
pool = multiprocessing.Pool(ncores)
pool = multiprocessing.Pool(ncores, maxtasksperchild=100)
return pool
@ -899,6 +900,18 @@ def check_for_nan(data, nan_value=0.):
np.nan_to_num(trace.data, copy=False, nan=nan_value)
def get_pylot_eventfile_with_extension(event, fext):
if hasattr(event, 'path'):
eventpath = event.path
else:
logging.warning('No attribute path found for event.')
return
eventname = eventpath.split('/')[-1] # or event.pylot_id
filename = os.path.join(eventpath, 'PyLoT_' + eventname + fext)
if os.path.isfile(filename):
return filename
def get_stations(data):
"""
Get list of all station names in data stream

View File

@ -36,7 +36,7 @@ from PySide2.QtWidgets import QAction, QApplication, QCheckBox, QComboBox, \
QGridLayout, QLabel, QLineEdit, QMessageBox, \
QTabWidget, QToolBar, QVBoxLayout, QHBoxLayout, QWidget, \
QPushButton, QFileDialog, QInputDialog
from PySide2.QtCore import QSettings, Qt, QUrl, Signal
from PySide2.QtCore import QSettings, Qt, QUrl, Signal, QTimer
from PySide2.QtWebEngineWidgets import QWebEngineView as QWebView
from obspy import Stream, Trace, UTCDateTime
from obspy.core.util import AttribDict
@ -54,7 +54,7 @@ from pylot.core.util.utils import prepTimeAxis, full_range, demeanTrace, isSorte
check4rotated, check4doubled, check_for_gaps_and_merge, check_for_nan, identifyPhase, \
loopIdentifyPhase, trim_station_components, transformFilteroptions2String, \
identifyPhaseID, get_bool, get_None, pick_color, getAutoFilteroptions, SetChannelComponents, \
station_id_remove_channel
station_id_remove_channel, get_pylot_eventfile_with_extension
from autoPyLoT import autoPyLoT
from pylot.core.util.thread import Thread
from pylot.core.util.dataprocessing import Metadata
@ -1568,6 +1568,96 @@ class PylotCanvas(FigureCanvas):
self.draw()
class SearchFileByExtensionDialog(QtWidgets.QDialog):
def __init__(self, parent=None, label='Text: ', default_text='.xml', events=None):
super(SearchFileByExtensionDialog, self).__init__(parent)
self.events = events
self.filepaths = []
self.default_text = default_text
self.label = label
self.setButtons()
self.setupUi()
self.connectSignals()
self.showPaths()
self.refresh_timer = QTimer(self)
self.refresh_timer.timeout.connect(self.showPaths)
self.refresh_timer.start(10000)
self.resize(800, 450)
def setupUi(self):
self.main_layout = QtWidgets.QVBoxLayout()
self.header_layout = QtWidgets.QHBoxLayout()
#
self.setLayout(self.main_layout)
# widgets inside the dialog
self.textLabel = QtWidgets.QLabel(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.default_text)
# optional search button, currently disabled. List refreshed when text changes
self.searchButton = QtWidgets.QPushButton('Search')
self.searchButton.setVisible(False)
self.tableWidget = QtWidgets.QTableWidget()
tableWidget = self.tableWidget
tableWidget.setColumnCount(2)
tableWidget.setRowCount(len(self.events))
tableWidget.setHorizontalHeaderLabels(('Filename', 'Last modified'))
tableWidget.setEditTriggers(tableWidget.NoEditTriggers)
tableWidget.setSortingEnabled(True)
header = tableWidget.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setStretchLastSection(True)
self.statusText = QtWidgets.QLabel()
self.header_layout.addWidget(self.textLabel)
self.header_layout.addWidget(self.lineEdit)
self.header_layout.addWidget(self.searchButton)
self.main_layout.addLayout(self.header_layout)
self.main_layout.addWidget(self.tableWidget)
self.main_layout.addWidget(self.statusText)
self.main_layout.addWidget(self._buttonbox)
def showPaths(self):
self.filepaths = []
fext = self.lineEdit.text()
self.tableWidget.clearContents()
for index, event in enumerate(self.events):
filename = get_pylot_eventfile_with_extension(event, fext)
if filename:
self.filepaths.append(filename)
ts = int(os.path.getmtime(filename))
# create QTableWidgetItems of filepath and last modification time
fname_item = QtWidgets.QTableWidgetItem(f'{filename}')
ts_item = QtWidgets.QTableWidgetItem(f'{datetime.datetime.fromtimestamp(ts)}')
self.tableWidget.setItem(index, 0, fname_item)
self.tableWidget.setItem(index, 1, ts_item)
# TODO: Idea -> only refresh if table contents changed. Use selection to load only a subset of files
if len(self.filepaths) > 0:
status_text = f'Found {len(self.filepaths)} eventfiles. Do you want to load them?'
else:
status_text = 'Did not find any files for specified file mask.'
self.statusText.setText(status_text)
def setButtons(self):
self._buttonbox = QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
def connectSignals(self):
self._buttonbox.accepted.connect(self.accept)
self._buttonbox.rejected.connect(self.reject)
self.lineEdit.textChanged.connect(self.showPaths)
self.searchButton.clicked.connect(self.showPaths)
class SingleTextLineDialog(QtWidgets.QDialog):
def __init__(self, parent=None, label='Text: ', default_text='.xml'):
super(SingleTextLineDialog, self).__init__(parent)