Merge branch 'develop'

This commit is contained in:
Marcel Paffrath 2017-06-27 15:30:18 +02:00
commit 795733cc5f
13 changed files with 552 additions and 286 deletions

View File

@ -41,6 +41,8 @@ from PySide.QtGui import QMainWindow, QInputDialog, QIcon, QFileDialog, \
QTreeView, QComboBox, QTabWidget, QPushButton, QGridLayout
import numpy as np
from obspy import UTCDateTime
from obspy.core.event import Magnitude
from obspy.core.util import AttribDict
try:
import pyqtgraph as pg
@ -70,6 +72,7 @@ from pylot.core.util.connection import checkurl
from pylot.core.util.dataprocessing import read_metadata, restitute_data
from pylot.core.util.utils import fnConstructor, getLogin, \
full_range
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, \
WaveformWidget, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
@ -143,6 +146,7 @@ class MainWindow(QMainWindow):
self.data = Data(self, lastEvent)
else:
self.data = Data(self)
self.data._new = False
self.autodata = Data(self)
if settings.value("user/FullName", None) is None:
@ -172,8 +176,8 @@ class MainWindow(QMainWindow):
self.setupUi()
self.filteroptions = {}
self.picks = {}
self.autopicks = {}
self.pylot_picks = {}
self.pylot_autopicks = {}
self.loc = False
def setupUi(self):
@ -311,21 +315,21 @@ class MainWindow(QMainWindow):
# self.createNewEvent,
# QKeySequence.New, newIcon,
# "Create a new event.")
self.openmanualpicksaction = self.createAction(self, "Load &manual picks ...",
self.openmanualpicksaction = self.createAction(self, "Load event ...",
self.load_data,
"Ctrl+M",
manupicksicon,
"Load manual picks for "
"Load event information for "
"the displayed event.")
self.openmanualpicksaction.setEnabled(False)
self.openmanualpicksaction.setData(None)
self.openautopicksaction = self.createAction(self, "Load &automatic picks ... ",
self.load_autopicks,
self.openautopicksaction = self.createAction(self, "Load event information &automatically ... ",
self.load_multiple_data,
"Ctrl+A",
autopicksicon,
"Load automatic picks "
"for the displayed event.")
"Load event data automatically "
"for for all events.")
self.openautopicksaction.setEnabled(False)
self.openautopicksaction.setData(None)
@ -637,22 +641,65 @@ class MainWindow(QMainWindow):
fname_dict = dict(phasfn=fn_phases, locfn=fn_loc)
self.load_data(fname_dict, type=type)
def load_data(self, fname=None, type='manual', loc=False):
def load_multiple_data(self, type='manual'):
if not self.okToContinue():
return
refresh=False
events = self.project.eventlist
fext = '.xml'
for event in events:
path = event.path
eventname = path.split('/')[-1]
filename = os.path.join(path, 'PyLoT_'+eventname+fext)
if os.path.isfile(filename):
self.load_data(filename, draw=False, event=event, overwrite=True)
refresh=True
if not refresh:
return
if self.get_current_event().pylot_picks:
self.refreshEvents()
self.setDirty(True)
def load_data(self, fname=None, type='manual', loc=False, draw=True, event=None, overwrite=False):
if not overwrite:
if not self.okToContinue():
return
if fname is None:
action = self.sender()
if isinstance(action, QAction):
fname = self.filename_from_action(action)
if not fname:
return
self.set_fname(fname, type)
data = dict(auto=self.autodata, manual=self.data)
data[type] += Data(self, evtdata=fname)
#data = dict(auto=self.autodata, manual=self.data)
if not event:
event = self.get_current_event()
data = Data(self, event)
try:
data_new = Data(self, evtdata=fname)
data += data_new
except ValueError:
qmb = QMessageBox(self, icon=QMessageBox.Question,
text='Warning: Missmatch in event identifiers {} and {}. Continue?'.format(
data_new.get_evt_data().resource_id,
data.get_evt_data().resource_id),
windowTitle='PyLoT - Load data warning')
qmb.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
qmb.setDefaultButton(QMessageBox.No)
ret = qmb.exec_()
if ret == qmb.Yes:
data_new.setNew()
data += data_new
else:
return
self.data = data
print('Loading {} picks from file {}.'.format(type, fname))
if not loc:
self.updatePicks(type=type)
if self.get_current_event().picks:
self.plotWaveformDataThread()
self.drawPicks(picktype=type)
self.draw()
self.updatePicks(type=type, event=event)
if draw:
if self.get_current_event().pylot_picks:
self.refreshEvents()
self.setDirty(True)
def add_recentfile(self, event):
@ -676,8 +723,8 @@ class MainWindow(QMainWindow):
def getWFFnames(self):
try:
evt = self.get_data().get_evt_data()
if evt.picks:
for pick in evt.picks:
if evt.pylot_picks:
for pick in evt.pylot_picks:
try:
if pick.waveform_id is not None:
fname = pick.waveform_id.getSEEDstring()
@ -728,8 +775,8 @@ class MainWindow(QMainWindow):
'''
if not eventbox:
eventbox = self.eventBox
index = eventbox.currentIndex()
return eventbox.itemData(index)
path = eventbox.currentText()
return self.project.getEventFromPath(path)
def get_current_event_path(self, eventbox=None):
'''
@ -778,7 +825,7 @@ class MainWindow(QMainWindow):
dirs = {
'database': path.split('/')[-2],
'datapath': path.split('/')[-3],
'rootpath': os.path.join(*path.split('/')[:-3])
'rootpath': '/'+os.path.join(*path.split('/')[:-3])
}
except Exception as e:
dirs = {
@ -788,6 +835,10 @@ class MainWindow(QMainWindow):
}
print('Warning: Could not automatically init folder structure. ({})'.format(e))
settings = QSettings()
settings.setValue("data/dataRoot", dirs['rootpath'])
settings.sync()
if not self.project.eventlist:
#init parameter object
self.setParameter(show=False)
@ -880,10 +931,10 @@ class MainWindow(QMainWindow):
event_path = event.path
event_npicks = 0
event_nautopicks = 0
if event.picks:
event_npicks = len(event.picks)
if event.autopicks:
event_nautopicks = len(event.autopicks)
if event.pylot_picks:
event_npicks = len(event.pylot_picks)
if event.pylot_autopicks:
event_nautopicks = len(event.pylot_autopicks)
event_ref = event.isRefEvent()
event_test = event.isTestEvent()
@ -929,7 +980,8 @@ class MainWindow(QMainWindow):
'{} unequal {}.'
.format(event.path, self.eventBox.itemText(id)))
raise ValueError(message)
eventBox.setItemData(id, event)
#not working with obspy events
#eventBox.setItemData(id, event)
eventBox.setCurrentIndex(index)
self.refreshRefTestButtons()
@ -940,7 +992,7 @@ class MainWindow(QMainWindow):
caption = "Open an event file"
fname = QFileDialog().getOpenFileName(self, caption=caption,
filter=filt,
dir=self.getRoot())
dir=self.get_current_event_path())
fname = fname[0]
else:
fname = str(action.data().toString())
@ -965,7 +1017,7 @@ class MainWindow(QMainWindow):
print('warning: {0}'.format(e))
directory = self.get_current_event_path()
eventname = self.get_current_event_name()
filename = 'picks_'+eventname
filename = 'PyLoT_'+eventname
outpath = os.path.join(directory, filename)
file_filter = "QuakeML file (*.xml);;VELEST observation file " \
"format (*.cnv);;NonLinLoc observation file (*.obs)"
@ -986,7 +1038,7 @@ class MainWindow(QMainWindow):
fbasename = self.getEventFileName()
exform = settings.value('data/exportFormat', 'QUAKEML')
try:
self.get_data().applyEVTData(self.getPicks())
self.get_data().applyEVTData(self.get_current_event(), typ='event')#getPicks())
except OverwriteError:
# msgBox = QMessageBox()
# msgBox.setText("Picks have been modified!")
@ -1056,7 +1108,7 @@ class MainWindow(QMainWindow):
return self.get_current_event().getPicks()
if type == 'auto':
return self.get_current_event().getAutopicks()
# rdict = dict(auto=self.autopicks, manual=self.picks)
# rdict = dict(auto=self.pylot_autopicks, manual=self.pylot_picks)
# return rdict[type]
def getPicksOnStation(self, station, type='manual'):
@ -1130,7 +1182,7 @@ class MainWindow(QMainWindow):
if event:
self.ref_event_button.setChecked(event.isRefEvent())
self.test_event_button.setChecked(event.isTestEvent())
self.enableRefTestButtons(bool(self.get_current_event().picks))
self.enableRefTestButtons(bool(self.get_current_event().pylot_picks))
return
self.ref_event_button.setChecked(False)
self.test_event_button.setChecked(False)
@ -1189,14 +1241,14 @@ class MainWindow(QMainWindow):
if not event:
return
# update picks saved in GUI mainwindow (to be changed in future!!) MP MP
if not event.picks:
self.picks = {}
if not event.pylot_picks:
self.pylot_picks = {}
else:
self.picks = event.picks
if not event.autopicks:
self.autopicks = {}
self.pylot_picks = event.pylot_picks
if not event.pylot_autopicks:
self.pylot_autopicks = {}
else:
self.autopicks = event.autopicks
self.pylot_autopicks = event.pylot_autopicks
# if current tab is waveformPlot-tab and the data in this tab was not yet refreshed
if self.tabs.currentIndex() == 0:
if self._eventChanged[0]:
@ -1342,12 +1394,12 @@ class MainWindow(QMainWindow):
self.openautopicksaction.setEnabled(True)
self.loadpilotevent.setEnabled(True)
event = self.get_current_event()
if event.picks:
self.picks = event.picks
if event.pylot_picks:
self.pylot_picks = event.pylot_picks
self.drawPicks(picktype='manual')
self.enableSaveManualPicksAction()
if event.autopicks:
self.autopicks = event.autopicks
if event.pylot_autopicks:
self.pylot_autopicks = event.pylot_autopicks
self.drawPicks(picktype='auto')
self.compare_action.setEnabled(True)
self.draw()
@ -1722,14 +1774,16 @@ class MainWindow(QMainWindow):
# raise Exception('FATAL: Should never occur!')
# MP MP prompt redundant because new picks have to be accepted in the first place closing PickDlg
def updatePicks(self, type='manual'):
def updatePicks(self, type='manual', event=None):
if not event:
event = self.get_current_event()
picks = picksdict_from_picks(evt=self.get_data(type).get_evt_data())
if type == 'manual':
self.get_current_event().addPicks(picks)
self.picks.update(picks)
event.addPicks(picks)
self.pylot_picks.update(picks)
elif type == 'auto':
self.get_current_event().addAutopicks(picks)
self.autopicks.update(picks)
event.addAutopicks(picks)
self.pylot_autopicks.update(picks)
self.check4Comparison()
def drawPicks(self, station=None, picktype='manual'):
@ -1766,7 +1820,7 @@ class MainWindow(QMainWindow):
for phase in stat_picks:
picks = stat_picks[phase]
if type(stat_picks[phase]) is not dict:
if type(stat_picks[phase]) is not dict and type(stat_picks[phase]) is not AttribDict:
return
colors = phase_col[phase[0].upper()]
@ -1880,8 +1934,8 @@ class MainWindow(QMainWindow):
finally:
os.remove(phasepath)
self.get_data().applyEVTData(lt.read_location(locpath), type='event')
self.get_data().applyEVTData(self.calc_magnitude(), type='event')
self.get_data().applyEVTData(lt.read_location(locpath), typ='event')
self.get_data().applyEVTData(self.calc_magnitude(), typ='event')
def init_array_tab(self):
'''
@ -1966,6 +2020,12 @@ class MainWindow(QMainWindow):
if not self.array_map:
return
# refresh with new picks here!!!
event = self.get_current_event()
if hasattr(event, 'origins'):
if event.origins:
lat = event.origins[0].latitude
lon = event.origins[0].longitude
self.array_map.eventLoc = (lat, lon)
self.array_map.refresh_drawings(self.get_current_event().getPicks())
self._eventChanged[1] = False
@ -1992,19 +2052,19 @@ class MainWindow(QMainWindow):
# changes attributes of the corresponding event
table = self.project._table
event = self.project.getEventFromPath(table[row][0].text())
if column == 3 or column == 4:
if column == 8 or column == 9:
#toggle checked states (exclusive)
item_ref = table[row][3]
item_test = table[row][4]
if column == 3 and item_ref.checkState():
item_ref = table[row][8]
item_test = table[row][9]
if column == 8 and item_ref.checkState():
item_test.setCheckState(QtCore.Qt.Unchecked)
event.setRefEvent(True)
elif column == 3 and not item_ref.checkState():
elif column == 8 and not item_ref.checkState():
event.setRefEvent(False)
elif column == 4 and item_test.checkState():
elif column == 9 and item_test.checkState():
item_ref.setCheckState(QtCore.Qt.Unchecked)
event.setTestEvent(True)
elif column == 4 and not item_test.checkState():
elif column == 9 and not item_test.checkState():
event.setTestEvent(False)
self.fill_eventbox()
elif column == 5:
@ -2020,22 +2080,35 @@ class MainWindow(QMainWindow):
# init new qtable
self.event_table = QtGui.QTableWidget()
self.event_table.setColumnCount(6)
self.event_table.setColumnCount(11)
self.event_table.setRowCount(len(eventlist))
self.event_table.setHorizontalHeaderLabels(['Event', '[N] MP',
'[N] AP', 'Tuning Set',
'Test Set', 'Notes'])
self.event_table.setHorizontalHeaderLabels(['Event',
'Time',
'Lat',
'Lon',
'Depth',
'Mag',
'[N] MP',
'[N] AP',
'Tuning Set',
'Test Set',
'Notes'])
# iterate through eventlist and generate items for table rows
self.project._table = []
for index, event in enumerate(eventlist):
event_npicks = 0
event_nautopicks = 0
if event.picks:
event_npicks = len(event.picks)
if event.autopicks:
event_nautopicks = len(event.autopicks)
if event.pylot_picks:
event_npicks = len(event.pylot_picks)
if event.pylot_autopicks:
event_nautopicks = len(event.pylot_autopicks)
item_path = QtGui.QTableWidgetItem()
item_time = QtGui.QTableWidgetItem()
item_lat = QtGui.QTableWidgetItem()
item_lon = QtGui.QTableWidgetItem()
item_depth = QtGui.QTableWidgetItem()
item_mag = QtGui.QTableWidgetItem()
item_nmp = QtGui.QTableWidgetItem(str(event_npicks))
item_nmp.setIcon(self.manupicksicon_small)
item_nap = QtGui.QTableWidgetItem(str(event_nautopicks))
@ -2047,11 +2120,23 @@ class MainWindow(QMainWindow):
item_ref.setBackground(self._colors['ref'])
item_test.setBackground(self._colors['test'])
item_path.setText(event.path)
if hasattr(event, 'origins'):
if event.origins:
origin = event.origins[0]
item_time.setText(str(origin.time).split('.')[0])
item_lon.setText(str(origin.longitude))
item_lat.setText(str(origin.latitude))
item_depth.setText(str(origin.depth))
if hasattr(event, 'magnitudes'):
if event.magnitudes:
magnitude = event.magnitudes[0]
item_mag.setText(str(magnitude.mag))
item_notes.setText(event.notes)
set_enabled(item_path, True, False)
set_enabled(item_nmp, True, False)
set_enabled(item_nap, True, False)
if event.picks:
if event.pylot_picks:
set_enabled(item_ref, True, True)
set_enabled(item_test, True, True)
else:
@ -2067,7 +2152,8 @@ class MainWindow(QMainWindow):
else:
item_test.setCheckState(QtCore.Qt.Unchecked)
column=[item_path, item_nmp, item_nap, item_ref, item_test, item_notes]
column=[item_path, item_time, item_lat, item_lon, item_depth, item_mag,
item_nmp, item_nap, item_ref, item_test, item_notes]
self.project._table.append(column)
for r_index, row in enumerate(self.project._table):
@ -2315,7 +2401,7 @@ class MainWindow(QMainWindow):
self.setDirty(True)
def setDirty(self, value):
self.saveProjectAction.setEnabled(value)
self.saveProjectAction.setEnabled(bool(self.get_current_event().picks))
self.saveProjectAsAction.setEnabled(True)
self.project.setDirty(value)
self.dirty = value
@ -2382,6 +2468,63 @@ class Project(object):
self.setDirty()
else:
print('Skipping event with path {}. Already part of project.'.format(event.path))
self.search_eventfile_info()
def read_eventfile_info(self, filename, separator=','):
'''
Try to read event information from file (:param:filename) comparing specific event datetimes.
File structure (each row): event, date, time, magnitude, latitude, longitude, depth
separated by :param:separator each.
'''
infile = open(filename, 'r')
for line in infile.readlines():
event, date, time, mag, lat, lon, depth = line.split(separator)[:7]
#skip first line
try:
month, day, year = date.split('/')
except:
continue
year = int(year)
#hardcoded, if year only consists of 2 digits (e.g. 16 instead of 2016)
if year<100:
year += 2000
datetime = '{}-{}-{}T{}'.format(year, month, day, time)
try:
datetime = UTCDateTime(datetime)
except Exception as e:
print(e, datetime, filename)
continue
for event in self.eventlist:
if not event.origins:
continue
origin = event.origins[0] #should have only one origin
if origin.time == datetime:
origin.latitude = float(lat)
origin.longitude = float(lon)
origin.depth = float(depth)
event.magnitudes.append(Magnitude(resource_id=event.resource_id,
mag=float(mag),
mag_type='M'))
def search_eventfile_info(self):
'''
Search all datapaths in rootpath for filenames with given file extension fext
and try to read event info from it
'''
datapaths = []
fext='.csv'
for event in self.eventlist:
if not event.datapath in datapaths:
datapaths.append(event.datapath)
for datapath in datapaths:
datapath = os.path.join(self.rootpath, datapath)
for filename in os.listdir(datapath):
filename = os.path.join(datapath, filename)
if os.path.isfile(filename) and filename.endswith(fext):
try:
self.read_eventfile_info(filename)
except Exception as e:
print('Failed on reading eventfile info from file {}: {}'.format(filename, e))
def getPaths(self):
'''
@ -2442,123 +2585,6 @@ class Project(object):
return project
class Event(object):
'''
Pickable class containing information on a single event.
'''
def __init__(self, path):
self.path = path
self.database = path.split('/')[-2]
self.datapath = path.split('/')[-3]
self.rootpath = os.path.join(*path.split('/')[:-3])
self.autopicks = {}
self.picks = {}
self.notes = ''
self._testEvent = False
self._refEvent = False
try:
self.get_notes()
except:
pass
def get_notes_path(self):
notesfile = os.path.join(self.path, 'notes.txt')
return notesfile
def get_notes(self):
notesfile = self.get_notes_path()
if os.path.isfile(notesfile):
with open(notesfile) as infile:
text = '[eventInfo: '+str(infile.readlines()[0].split('\n')[0])+']'
self.addNotes(text)
def addNotes(self, notes):
self.notes = str(notes)
def clearNotes(self):
self.notes = None
def isRefEvent(self):
return self._refEvent
def isTestEvent(self):
return self._testEvent
def setRefEvent(self, bool):
self._refEvent = bool
if bool: self._testEvent = False
def setTestEvent(self, bool):
self._testEvent = bool
if bool: self._refEvent = False
def addPicks(self, picks):
for station in picks:
self.picks[station] = picks[station]
def addAutopicks(self, autopicks):
for station in autopicks:
self.autopicks[station] = autopicks[station]
def setPick(self, station, pick):
if pick:
self.picks[station] = pick
def setPicks(self, picks):
self.picks = picks
def getPick(self, station):
if station in self.picks.keys():
return self.picks[station]
def getPicks(self):
return self.picks
def setAutopick(self, station, autopick):
if autopick:
self.autopicks[station] = autopick
def setAutopicks(self, autopicks):
self.autopicks = autopicks
def getAutopick(self, station):
if station in self.autopicks.keys():
return self.autopicks[station]
def getAutopicks(self):
return self.autopicks
def save(self, filename):
'''
Save PyLoT Event to a file.
Can be loaded by using event.load(filename).
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
try:
outfile = open(filename, 'wb')
cPickle.dump(self, outfile, -1)
except Exception as e:
print('Could not pickle PyLoT event. Reason: {}'.format(e))
@staticmethod
def load(filename):
'''
Load project from filename.
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
infile = open(filename, 'rb')
event = cPickle.load(infile)
print('Loaded %s' % filename)
return event
class getExistingDirectories(QFileDialog):
'''
File dialog with possibility to select multiple folders.

View File

@ -98,8 +98,8 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
exf = ['root', 'dpath', 'dbase']
if parameter.hasParam('eventID') and fnames == 'None':
dsfields['eventID'] = parameter.get('eventID')
if parameter['eventID'] is not '*' and fnames == 'None':
dsfields['eventID'] = parameter['eventID']
exf.append('eventID')
datastructure.modifyFields(**dsfields)
@ -133,13 +133,13 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
if not input_dict:
# started in production mode
datapath = datastructure.expandDataPath()
if fnames == 'None' and not parameter['eventID']:
if fnames == 'None' and parameter['eventID'] is '*':
# multiple event processing
# read each event in database
events = [events for events in glob.glob(os.path.join(datapath, '*')) if os.path.isdir(events)]
elif fnames == 'None' and parameter['eventID']:
elif fnames == 'None' and parameter['eventID'] is not '*':
# single event processing
events = glob.glob(os.path.join(datapath, parameter.get('eventID')))
events = glob.glob(os.path.join(datapath, parameter['eventID']))
else:
# autoPyLoT was initialized from GUI
events = []
@ -243,7 +243,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# get latest NLLoc-location file if several are available
nllocfile = max(glob.glob(locsearch), key=os.path.getctime)
evt = read_events(nllocfile)[0]
# calculating seismic moment Mo and moment magnitude Mw
# calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'),
parameter.get('rho'), True, \
@ -252,15 +252,29 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props)
evt = moment_mag.updated_event()
net_mw = moment_mag.net_magnitude()
print("Network moment magnitude: %4.1f" % net_mw.mag)
# calculate local (Richter) magntiude
WAscaling = parameter.get('WAscaling')
magscaling = parameter.get('magscaling')
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'), parameter.get('WAscaling'), \
True, iplot)
parameter.get('sstop'),
WAscaling, True, iplot)
for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude
evt = local_mag.updated_event()
print("Local station magnitudes scaled with:")
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
WAscaling[1],
WAscaling[2]))
evt = local_mag.updated_event(magscaling)
net_ml = local_mag.net_magnitude(magscaling)
print("Network local magnitude: %4.1f" % net_ml.mag)
print("Network local magnitude scaled with:")
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
else:
print("autoPyLoT: No NLLoc-location file available!")
print("No source parameter estimation possible!")
locflag = 9
else:
# get theoretical P-onset times from NLLoc-location file
locsearch = '%s/loc/%s.????????.??????.grid?.loc.hyp' % (nllocroot, nllocout)
@ -301,7 +315,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
nlloccounter = maxnumit
evt = read_events(nllocfile)[0]
if locflag < 2:
# calculating seismic moment Mo and moment magnitude Mw
# calculate seismic moment Mo and moment magnitude Mw
moment_mag = MomentMagnitude(corr_dat, evt, parameter.get('vp'),
parameter.get('Qp'),
parameter.get('rho'), True, \
@ -310,14 +324,25 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
for station, props in moment_mag.moment_props.items():
picks[station]['P'].update(props)
evt = moment_mag.updated_event()
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'), parameter.get('WAscaling'), \
True, iplot)
for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude
evt = local_mag.updated_event()
net_mw = moment_mag.net_magnitude()
print("Network moment magnitude: %4.1f" % net_mw.mag)
# calculate local (Richter) magntiude
WAscaling = parameter.get('WAscaling')
magscaling = parameter.get('magscaling')
local_mag = LocalMagnitude(corr_dat, evt,
parameter.get('sstop'),
WAscaling, True, iplot)
for station, amplitude in local_mag.amplitudes.items():
picks[station]['S']['Ao'] = amplitude.generic_amplitude
print("Local station magnitudes scaled with:")
print("log(Ao) + %f * log(r) + %f * r + %f" % (WAscaling[0],
WAscaling[1],
WAscaling[2]))
evt = local_mag.updated_event(magscaling)
net_ml = local_mag.net_magnitude(magscaling)
print("Network local magnitude: %4.1f" % net_ml.mag)
print("Network local magnitude scaled with:")
print("%f * Ml + %f" % (magscaling[0], magscaling[1]))
else:
print("autoPyLoT: No NLLoc-location file available! Stop iteration!")
locflag = 9
@ -328,26 +353,26 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
data.applyEVTData(picks)
if evt is not None:
data.applyEVTData(evt, 'event')
fnqml = '%s/autoPyLoT' % event
data.exportEvent(fnqml)
fnqml = '%s/PyLoT_%s' % (event, evID)
data.exportEvent(fnqml, fnext='.xml', fcheck='manual')
if locflag == 1:
# HYPO71
hypo71file = '%s/autoPyLoT_HYPO71_phases' % event
hypo71file = '%s/PyLoT_%s_HYPO71_phases' % (event, evID)
hypo71.export(picks, hypo71file, parameter)
# HYPOSAT
hyposatfile = '%s/autoPyLoT_HYPOSAT_phases' % event
hyposatfile = '%s/PyLoT_%s_HYPOSAT_phases' % (event, evID)
hyposat.export(picks, hyposatfile, parameter)
if locflag == 1:
# VELEST
velestfile = '%s/autoPyLoT_VELEST_phases.cnv' % event
velestfile = '%s/PyLoT_%s_VELEST_phases.cnv' % (event, evID)
velest.export(picks, velestfile, parameter, evt)
# hypoDD
hypoddfile = '%s/autoPyLoT_hypoDD_phases.pha' % event
hypoddfile = '%s/PyLoT_%s_hypoDD_phases.pha' % (event, evID)
hypodd.export(picks, hypoddfile, parameter, evt)
# FOCMEC
focmecfile = '%s/autoPyLoT_FOCMEC.in' % event
focmecfile = '%s/PyLoT_%s_FOCMEC.in' % (event, evID)
focmec.export(picks, focmecfile, parameter, evt)
# HASH
hashfile = '%s/autoPyLoT_HASH' % event
hashfile = '%s/PyLoT_%s_HASH' % (event, evID)
hash.export(picks, hashfile, parameter, evt)
endsplash = '''------------------------------------------\n'

View File

@ -1 +0,0 @@
f91e1-dirty

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
"""
Created autumn/winter 2015.
Revised/extended summer 2017.
:author: Ludger Küperkoch / MAGS2 EP3 working group
"""
@ -115,17 +116,24 @@ class Magnitude(object):
def calc(self):
pass
def updated_event(self):
self.event.magnitudes.append(self.net_magnitude())
def updated_event(self, magscaling=None):
self.event.magnitudes.append(self.net_magnitude(magscaling))
return self.event
def net_magnitude(self):
def net_magnitude(self, magscaling=None):
if self:
# TODO if an average Magnitude instead of the median is calculated
# StationMagnitudeContributions should be added to the returned
# Magnitude object
# mag_error => weights (magnitude error estimate from peak_to_peak, calcsourcespec?)
# weights => StationMagnitdeContribution
if magscaling is not None and str(magscaling) is not '[0.0, 0.0]':
# scaling necessary
print("Scaling network magnitude ...")
mag = ope.Magnitude(
mag=np.median([M.mag for M in self.magnitudes.values()]) *\
magscaling[0] + magscaling[1],
magnitude_type=self.type,
origin_id=self.origin_id,
station_count=len(self.magnitudes),
azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap)
else:
# no saling necessary
mag = ope.Magnitude(
mag=np.median([M.mag for M in self.magnitudes.values()]),
magnitude_type=self.type,
@ -153,7 +161,7 @@ class LocalMagnitude(Magnitude):
_amplitudes = dict()
def __init__(self, stream, event, calc_win, wascaling=None, verbosity=False, iplot=0):
def __init__(self, stream, event, calc_win, wascaling, verbosity=False, iplot=0):
super(LocalMagnitude, self).__init__(stream, event, verbosity, iplot)
self._calc_win = calc_win
@ -207,6 +215,8 @@ class LocalMagnitude(Magnitude):
th = np.arange(0, len(sqH) * dt, dt)
# get maximum peak within pick window
iwin = getsignalwin(th, t0 - stime, self.calc_win)
ii = min([iwin[len(iwin)-1], len(th)])
iwin = iwin[0:ii]
wapp = np.max(sqH[iwin])
if self.verbose:
print("Determined Wood-Anderson peak-to-peak amplitude for station {0}: {1} "
@ -257,12 +267,13 @@ class LocalMagnitude(Magnitude):
self.amplitudes = (station, amplitude)
# using standard Gutenberg-Richter relation
# or scale WA amplitude with given scaling relation
if self.wascaling == None:
if str(self.wascaling) == '[0.0, 0.0, 0.0]':
print("Calculating original Richter magnitude ...")
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
+ richter_magnitude_scaling(delta))
else:
print("Calculating scaled local magnitude ...")
a0 = a0 * 1e03 # mm to nm (see Havskov & Ottemöller, 2010)
magnitude = ope.StationMagnitude(mag=np.log10(a0) \
+ self.wascaling[0] * np.log10(delta) + self.wascaling[1]
* delta + self.wascaling[2])

View File

@ -6,11 +6,12 @@ import os
from obspy import read_events
from obspy.core import read, Stream, UTCDateTime
from obspy.io.sac import SacIOError
from obspy.core.event import Event
from obspy.core.event import Event as ObsPyEvent
from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \
picksdict_from_pilot, merge_picks
from pylot.core.util.errors import FormatError, OverwriteError
from pylot.core.util.utils import fnConstructor, full_range
from pylot.core.util.event import Event
class Data(object):
"""
@ -33,7 +34,7 @@ class Data(object):
self.comp = 'Z'
self.wfdata = Stream()
self._new = False
if isinstance(evtdata, Event):
if isinstance(evtdata, ObsPyEvent) or isinstance(evtdata, Event):
pass
elif isinstance(evtdata, dict):
evt = readPILOTEvent(**evtdata)
@ -49,7 +50,7 @@ class Data(object):
if 'Unknown format for file' in e.message:
if 'PHASES' in evtdata:
picks = picksdict_from_pilot(evtdata)
evtdata = Event()
evtdata = ObsPyEvent()
evtdata.picks = picks_from_picksdict(picks)
elif 'LOC' in evtdata:
raise NotImplementedError('PILOT location information '
@ -61,7 +62,7 @@ class Data(object):
raise e
else: # create an empty Event object
self.setNew()
evtdata = Event()
evtdata = ObsPyEvent()
evtdata.picks = []
self.evtdata = evtdata
self.wforiginal = None
@ -73,6 +74,8 @@ class Data(object):
def __add__(self, other):
assert isinstance(other, Data), "operands must be of same type 'Data'"
rs_id = self.get_evt_data().get('resource_id')
rs_id_other = other.get_evt_data().get('resource_id')
if other.isNew() and not self.isNew():
picks_to_add = other.get_evt_data().picks
old_picks = self.get_evt_data().picks
@ -84,7 +87,7 @@ class Data(object):
self.evtdata = new.get_evt_data()
elif self.isNew() and other.isNew():
pass
elif self.get_evt_data().get('id') == other.get_evt_data().get('id'):
elif rs_id == rs_id_other:
other.setNew()
return self + other
else:
@ -95,7 +98,7 @@ class Data(object):
def getPicksStr(self):
picks_str = ''
for pick in self.get_evt_data().picks:
picks_str += str(pick) + '\n'
picks_str += str(PyLoT) + '\n'
return picks_str
def getParent(self):
@ -144,12 +147,13 @@ class Data(object):
# handle forbidden filenames especially on windows systems
return fnConstructor(str(ID))
def exportEvent(self, fnout, fnext='.xml'):
def exportEvent(self, fnout, fnext='.xml', fcheck='auto'):
"""
:param fnout:
:param fnext:
:param fcheck:
:raise KeyError:
"""
from pylot.core.util.defaults import OUTPUTFORMATS
@ -161,7 +165,29 @@ class Data(object):
'supported'.format(e, fnext)
raise FormatError(errmsg)
# check for already existing xml-file
if fnext == '.xml':
if os.path.isfile(fnout + fnext):
print("xml-file already exists! Check content ...")
cat_old = read_events(fnout + fnext)
checkflag = 0
for j in range(len(cat_old.events[0].picks)):
if cat_old.events[0].picks[j].method_id.id.split('/')[1] == fcheck:
print("Found %s pick(s), append to new catalog." % fcheck)
checkflag = 1
break
if checkflag == 1:
self.get_evt_data().write(fnout + fnext, format=evtformat)
cat_new = read_events(fnout + fnext)
cat_new.append(cat_old.events[0])
cat_new.write(fnout + fnext, format=evtformat)
else:
self.get_evt_data().write(fnout + fnext, format=evtformat)
else:
self.get_evt_data().write(fnout + fnext, format=evtformat)
# try exporting event via ObsPy
else:
try:
self.get_evt_data().write(fnout + fnext, format=evtformat)
except KeyError as e:
@ -279,12 +305,12 @@ class Data(object):
def setEvtData(self, event):
self.evtdata = event
def applyEVTData(self, data, type='pick', authority_id='rub'):
def applyEVTData(self, data, typ='pick', authority_id='rub'):
"""
:param data:
:param type:
:param typ:
:param authority_id:
:raise OverwriteError:
"""
@ -326,19 +352,27 @@ class Data(object):
information on the event to the actual data
:param event:
"""
if not self.isNew():
if self.isNew():
self.setEvtData(event)
else:
# prevent overwriting original pick information
picks = copy.deepcopy(self.get_evt_data().picks)
event_old = self.get_evt_data()
print(event_old.resource_id, event.resource_id)
if not event_old.resource_id == event.resource_id:
print("WARNING: Missmatch in event resource id's: {} and {}".format(
event_old.resource_id,
event.resource_id))
picks = copy.deepcopy(event_old.picks)
event = merge_picks(event, picks)
# apply event information from location
self.get_evt_data().update(event)
event_old.update(event)
applydata = {'pick': applyPicks,
'event': applyEvent}
applydata[type](data)
applydata[typ](data)
self._new = False
class GenericDataStructure(object):

View File

@ -14,7 +14,7 @@ defaults = {'rootpath': {'type': str,
'value': ''},
'eventID': {'type': str,
'tooltip': 'event ID for single event processing',
'tooltip': 'event ID for single event processing (* for all events found in database)',
'value': ''},
'extent': {'type': str,
@ -278,12 +278,14 @@ defaults = {'rootpath': {'type': str,
'value': 1.0},
'WAscaling': {'type': (float, float, float),
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm]',
'value': (1.0, 1.0, 1.0)},
'tooltip': 'Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] \
If zeros are set, original Richter magnitude is calculated!',
'value': (0., 0., 0.)},
'magscaling': {'type': (float, float),
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]',
'value': (1.0, 1.0)}
'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \
If zeros are set, no scaling of network magnitude is applied!',
'value': (0., 0.)}
}
settings_main={

View File

@ -221,24 +221,23 @@ class PylotParameter(object):
# for key, value in self.iteritems():
# lines.append('{key}\t{value}\n'.format(key=key, value=value))
# fid_out.writelines(lines)
header = ('%This is a parameter input file for PyLoT/autoPyLoT.\n'+
'%All main and special settings regarding data handling\n'+
'%and picking are to be set here!\n'+
'%Parameters are optimized for local data sets!\n')
seperator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
'%Parameters are optimized for %{} data sets!\n'.format(self.get_main_para_names()['pick'][0]))
separator = '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'
fid_out.write(header)
self.write_section(fid_out, self.get_main_para_names()['dirs'],
'main settings', seperator)
'main settings', separator)
self.write_section(fid_out, self.get_main_para_names()['nlloc'],
'NLLoc settings', seperator)
'NLLoc settings', separator)
self.write_section(fid_out, self.get_main_para_names()['smoment'],
'parameters for seismic moment estimation', seperator)
'parameters for seismic moment estimation', separator)
self.write_section(fid_out, self.get_main_para_names()['localmag'],
'settings local magnitude', seperator)
'settings local magnitude', separator)
self.write_section(fid_out, self.get_main_para_names()['pick'],
'common settings picker', seperator)
'common settings picker', separator)
fid_out.write(('#special settings for calculating CF#\n'+
'%!!Edit the following only if you know what you are doing!!%\n'))
self.write_section(fid_out, self.get_special_para_names()['z'],
@ -250,9 +249,9 @@ class PylotParameter(object):
self.write_section(fid_out, self.get_special_para_names()['quality'],
'quality assessment', None)
def write_section(self, fid, names, title, seperator):
if seperator:
fid.write(seperator)
def write_section(self, fid, names, title, separator):
if separator:
fid.write(separator)
fid.write('#{}#\n'.format(title))
l_val = 50
l_name = 15

View File

@ -7,6 +7,7 @@ import os
import scipy.io as sio
import warnings
from obspy.core import UTCDateTime
from obspy.core.util import AttribDict
from pylot.core.io.inputs import PylotParameter
from pylot.core.io.location import create_arrival, create_event, \
@ -195,6 +196,7 @@ def picksdict_from_picks(evt):
phase = {}
station = pick.waveform_id.station_code
channel = pick.waveform_id.channel_code
network = pick.waveform_id.network_code
try:
onsets = picks[station]
except KeyError as e:
@ -215,6 +217,7 @@ def picksdict_from_picks(evt):
phase['lpp'] = lpp
phase['spe'] = spe
phase['channel'] = channel
phase['network'] = network
try:
picker = str(pick.method_id)
if picker.startswith('smi:local/'):
@ -231,7 +234,7 @@ def picks_from_picksdict(picks, creation_info=None):
picks_list = list()
for station, onsets in picks.items():
for label, phase in onsets.items():
if not isinstance(phase, dict):
if not isinstance(phase, dict) and not isinstance(phase, AttribDict):
continue
onset = phase['mpp']
try:
@ -382,12 +385,12 @@ def reassess_pilot_event(root_dir, db_dir, event_id, out_dir=None, fn_param=None
evt.picks = picks_from_picksdict(picks_dict)
# write phase information to file
if not out_dir:
fnout_prefix = os.path.join(root_dir, db_dir, event_id, '{0}.'.format(event_id))
fnout_prefix = os.path.join(root_dir, db_dir, event_id, 'PyLoT_{0}.'.format(event_id))
else:
out_dir = os.path.join(out_dir, db_dir)
if not os.path.isdir(out_dir):
os.makedirs(out_dir)
fnout_prefix = os.path.join(out_dir, '{0}.'.format(event_id))
fnout_prefix = os.path.join(out_dir, 'PyLoT_{0}.'.format(event_id))
evt.write(fnout_prefix + 'xml', format='QUAKEML')
#evt.write(fnout_prefix + 'cnv', format='VELEST')
@ -835,9 +838,10 @@ def merge_picks(event, picks):
err = pick.time_errors
phase = pick.phase_hint
station = pick.waveform_id.station_code
network = pick.waveform_id.network_code
method = pick.method_id
for p in event.picks:
if p.waveform_id.station_code == station and p.phase_hint == phase:
p.time, p.time_errors, p.method_id = time, err, method
del time, err, phase, station, method
p.time, p.time_errors, p.waveform_id.network_code, p.method_id = time, err, network, method
del time, err, phase, station, network, method
return event

View File

@ -212,6 +212,14 @@ class AICPicker(AutoPicker):
self.Data[0].data = self.Data[0].data * 1000000
# get signal window
isignal = getsignalwin(self.Tcf, self.Pick, self.TSNR[2])
ii = min([isignal[len(isignal)-1], len(self.Tcf)])
isignal = isignal[0:ii]
try:
aic[isignal]
except IndexError as e:
msg = "Time series out of bounds! {}".format(e)
print(msg)
return
# calculate SNR from CF
self.SNR = max(abs(aic[isignal] - np.mean(aic[isignal]))) / \
max(abs(aic[inoise] - np.mean(aic[inoise])))

144
pylot/core/util/event.py Normal file
View File

@ -0,0 +1,144 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from obspy import UTCDateTime
from obspy.core.event import Event as ObsPyEvent
from obspy.core.event import Origin, Magnitude, ResourceIdentifier
from pylot.core.io.phases import picks_from_picksdict
class Event(ObsPyEvent):
'''
Pickable class derived from ~obspy.core.event.Event containing information on a single event.
'''
def __init__(self, path):
self.pylot_id = path.split('/')[-1]
# initialize super class
super(Event, self).__init__(resource_id=ResourceIdentifier('smi:local/'+self.pylot_id))
self.path = path
self.database = path.split('/')[-2]
self.datapath = path.split('/')[-3]
self.rootpath = '/' + os.path.join(*path.split('/')[:-3])
self.pylot_autopicks = {}
self.pylot_picks = {}
self.notes = ''
self._testEvent = False
self._refEvent = False
self.get_notes()
def get_notes_path(self):
notesfile = os.path.join(self.path, 'notes.txt')
return notesfile
def get_notes(self):
notesfile = self.get_notes_path()
if os.path.isfile(notesfile):
with open(notesfile) as infile:
path = str(infile.readlines()[0].split('\n')[0])
text = '[eventInfo: '+path+']'
self.addNotes(text)
try:
datetime = UTCDateTime(path.split('/')[-1])
origin = Origin(resource_id=self.resource_id, time=datetime, latitude=0, longitude=0, depth=0)
self.origins.append(origin)
except:
pass
def addNotes(self, notes):
self.notes = str(notes)
def clearNotes(self):
self.notes = None
def isRefEvent(self):
return self._refEvent
def isTestEvent(self):
return self._testEvent
def setRefEvent(self, bool):
self._refEvent = bool
if bool: self._testEvent = False
def setTestEvent(self, bool):
self._testEvent = bool
if bool: self._refEvent = False
def addPicks(self, picks):
'''
add pylot picks and overwrite existing
'''
for station in picks:
self.pylot_picks[station] = picks[station]
#add ObsPy picks
self.picks = picks_from_picksdict(self.pylot_picks)
def addAutopicks(self, autopicks):
for station in autopicks:
self.pylot_autopicks[station] = autopicks[station]
def setPick(self, station, pick):
if pick:
self.pylot_picks[station] = pick
self.picks = picks_from_picksdict(self.pylot_picks)
def setPicks(self, picks):
'''
set pylot picks and delete and overwrite all existing
'''
self.pylot_picks = picks
self.picks = picks_from_picksdict(self.pylot_picks)
def getPick(self, station):
if station in self.pylot_picks.keys():
return self.pylot_picks[station]
def getPicks(self):
return self.pylot_picks
def setAutopick(self, station, autopick):
if autopick:
self.pylot_autopicks[station] = autopick
def setAutopicks(self, autopicks):
self.pylot_autopicks = autopicks
def getAutopick(self, station):
if station in self.pylot_autopicks.keys():
return self.pylot_autopicks[station]
def getAutopicks(self):
return self.pylot_autopicks
def save(self, filename):
'''
Save PyLoT Event to a file.
Can be loaded by using event.load(filename).
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
try:
outfile = open(filename, 'wb')
cPickle.dump(self, outfile, -1)
except Exception as e:
print('Could not pickle PyLoT event. Reason: {}'.format(e))
@staticmethod
def load(filename):
'''
Load project from filename.
'''
try:
import cPickle
except ImportError:
import _pickle as cPickle
infile = open(filename, 'rb')
event = cPickle.load(infile)
print('Loaded %s' % filename)
return event

View File

@ -22,6 +22,7 @@ class map_projection(QtGui.QWidget):
self.parser = parent.metadata[1]
self.picks = None
self.picks_dict = None
self.eventLoc = None
self.figure = figure
self.init_graphics()
self.init_stations()
@ -244,6 +245,10 @@ class map_projection(QtGui.QWidget):
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
zorder=10, picker=True, edgecolor='m', label='Not Picked')
self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
if self.eventLoc:
lat, lon = self.eventLoc
self.sc_event = self.basemap.scatter(lon, lat, s=100, facecolor='red',
latlon=True, zorder=11, label='Event (might be outside map region)')
def scatter_picked_stations(self):
lon = self.lon_no_nan
@ -274,8 +279,7 @@ class map_projection(QtGui.QWidget):
def refresh_drawings(self, picks=None):
self.picks_dict = picks
self.remove_drawings()
self.draw_everything()
self._refresh_drawings()
def _refresh_drawings(self):
self.remove_drawings()
@ -303,6 +307,9 @@ class map_projection(QtGui.QWidget):
if hasattr(self, 'sc_picked'):
self.sc_picked.remove()
del(self.sc_picked)
if hasattr(self, 'sc_event'):
self.sc_event.remove()
del(self.sc_event)
if hasattr(self, 'cbar'):
self.cbar.remove()
del(self.cbar)

View File

@ -1646,7 +1646,7 @@ class TuneAutopicker(QWidget):
model = self.stationBox.model()
for network, station in stations:
item = QtGui.QStandardItem(network+'.'+station)
if station in self.get_current_event().picks:
if station in self.get_current_event().pylot_picks:
item.setBackground(self.parent._colors['ref'])
model.appendRow(item)
@ -1687,8 +1687,8 @@ class TuneAutopicker(QWidget):
self.listWidget.scrollToBottom()
def get_current_event(self):
index = self.eventBox.currentIndex()
return self.eventBox.itemData(index)
path = self.eventBox.currentText()
return self.parent.project.getEventFromPath(path)
def get_current_event_name(self):
return self.eventBox.currentText().split('/')[-1]
@ -1698,13 +1698,13 @@ class TuneAutopicker(QWidget):
def get_current_event_picks(self, station):
event = self.get_current_event()
if station in event.picks.keys():
return event.picks[station]
if station in event.pylot_picks.keys():
return event.pylot_picks[station]
def get_current_event_autopicks(self, station):
event = self.get_current_event()
if event.autopicks:
return event.autopicks[station]
if event.pylot_autopicks:
return event.pylot_autopicks[station]
def get_current_station(self):
return str(self.stationBox.currentText()).split('.')[-1]
@ -1855,6 +1855,9 @@ class TuneAutopicker(QWidget):
self.init_tab_names()
def fill_eventbox(self):
project = self.parent.project
if not project:
return
# update own list
self.parent.fill_eventbox(eventBox=self.eventBox, select_events='ref')
index_start = self.parent.eventBox.currentIndex()
@ -1862,11 +1865,15 @@ class TuneAutopicker(QWidget):
if index == -1:
index += 1
nevents = self.eventBox.model().rowCount()
if self.eventBox.itemData(index).isTestEvent():
path = self.eventBox.itemText(index)
if project.getEventFromPath(path).isTestEvent():
for index in range(nevents):
if not self.eventBox.itemData(index).isTestEvent():
path = self.eventBox.itemText(index)
if project.getEventFromPath(index):
if not project.getEventFromPath(index).isTestEvent():
break
elif index == nevents - 1:
#in case all events are marked as test events and last event is reached
if index == nevents - 1:
index = -1
self.eventBox.setCurrentIndex(index)
if not index == index_start:
@ -1911,8 +1918,8 @@ class TuneAutopicker(QWidget):
self._warn('Could not execute picker:\n{}'.format(
self.ap_thread._executedError))
return
self.picks = self.ap_thread.data
if not self.picks:
self.pylot_picks = self.ap_thread.data
if not self.pylot_picks:
self._warn('No picks found. See terminal output.')
return
#renew tabs