refactor: restructure data objects

This commit is contained in:
Sebastian Wehling-Benatelli 2024-07-27 13:58:06 +02:00
parent 0709fb04a5
commit 65b456b8ab
7 changed files with 129 additions and 227 deletions

View File

@ -1773,7 +1773,7 @@ class MainWindow(QMainWindow):
def getStime(self): def getStime(self):
if self.get_data(): if self.get_data():
return full_range(self.get_data().getWFData())[0] return full_range(self.get_data().get_wf_data())[0]
def addActions(self, target, actions): def addActions(self, target, actions):
for action in actions: for action in actions:
@ -1983,7 +1983,7 @@ class MainWindow(QMainWindow):
tstart = None tstart = None
tstop = None tstop = None
self.data.setWFData(self.fnames, self.data.set_wf_data(self.fnames,
self.fnames_comp, self.fnames_comp,
checkRotated=True, checkRotated=True,
metadata=self.metadata, metadata=self.metadata,
@ -2035,7 +2035,7 @@ class MainWindow(QMainWindow):
def get_npts_to_plot(self): def get_npts_to_plot(self):
if not hasattr(self.data, 'wfdata'): if not hasattr(self.data, 'wfdata'):
return 0 return 0
return sum(trace.stats.npts for trace in self.data.getWFData()) return sum(trace.stats.npts for trace in self.data.get_wf_data())
def connectWFplotEvents(self): def connectWFplotEvents(self):
''' '''
@ -2248,14 +2248,14 @@ class MainWindow(QMainWindow):
zne_text = {'Z': 'vertical', 'N': 'north-south', 'E': 'east-west'} zne_text = {'Z': 'vertical', 'N': 'north-south', 'E': 'east-west'}
comp = self.getComponent() comp = self.getComponent()
title = 'section: {0} components'.format(zne_text[comp]) title = 'section: {0} components'.format(zne_text[comp])
wfst = self.get_data().getWFData() wfst = self.get_data().get_wf_data()
wfsyn = self.get_data().getAltWFdata() wfsyn = self.get_data().getAltWFdata()
if self.filterActionP.isChecked() and filter: if self.filterActionP.isChecked() and filter:
self.filterWaveformData(plot=False, phase='P') self.filterWaveformData(plot=False, phase='P')
elif self.filterActionS.isChecked() and filter: elif self.filterActionS.isChecked() and filter:
self.filterWaveformData(plot=False, phase='S') self.filterWaveformData(plot=False, phase='S')
# wfst = self.get_data().getWFData().select(component=comp) # wfst = self.get_data().get_wf_data().select(component=comp)
# wfst += self.get_data().getWFData().select(component=alter_comp) # wfst += self.get_data().get_wf_data().select(component=alter_comp)
plotWidget = self.getPlotWidget() plotWidget = self.getPlotWidget()
self.adjustPlotHeight() self.adjustPlotHeight()
if get_bool(settings.value('large_dataset')) == True: if get_bool(settings.value('large_dataset')) == True:
@ -2270,7 +2270,7 @@ class MainWindow(QMainWindow):
def adjustPlotHeight(self): def adjustPlotHeight(self):
if self.pg: if self.pg:
return return
height_need = len(self.data.getWFData()) * self.height_factor height_need = len(self.data.get_wf_data()) * self.height_factor
plotWidget = self.getPlotWidget() plotWidget = self.getPlotWidget()
if self.tabs.widget(0).frameSize().height() < height_need: if self.tabs.widget(0).frameSize().height() < height_need:
plotWidget.setMinimumHeight(height_need) plotWidget.setMinimumHeight(height_need)
@ -2290,24 +2290,24 @@ class MainWindow(QMainWindow):
self.plotWaveformDataThread() self.plotWaveformDataThread()
def pushFilterWF(self, param_args): def pushFilterWF(self, param_args):
self.get_data().filterWFData(param_args) self.get_data().filter_wf_data(param_args)
def filterP(self): def filterP(self):
self.filterActionS.setChecked(False) self.filterActionS.setChecked(False)
if self.filterActionP.isChecked(): if self.filterActionP.isChecked():
self.filterWaveformData(phase='P') self.filterWaveformData(phase='P')
else: else:
self.resetWFData() self.reset_wf_data()
def filterS(self): def filterS(self):
self.filterActionP.setChecked(False) self.filterActionP.setChecked(False)
if self.filterActionS.isChecked(): if self.filterActionS.isChecked():
self.filterWaveformData(phase='S') self.filterWaveformData(phase='S')
else: else:
self.resetWFData() self.reset_wf_data()
def resetWFData(self): def reset_wf_data(self):
self.get_data().resetWFData() self.get_data().reset_wf_data()
self.plotWaveformDataThread() self.plotWaveformDataThread()
def filterWaveformData(self, plot=True, phase=None): def filterWaveformData(self, plot=True, phase=None):
@ -2326,11 +2326,11 @@ class MainWindow(QMainWindow):
kwargs = self.getFilterOptions()[phase].parseFilterOptions() kwargs = self.getFilterOptions()[phase].parseFilterOptions()
self.pushFilterWF(kwargs) self.pushFilterWF(kwargs)
else: else:
self.get_data().resetWFData() self.get_data().reset_wf_data()
elif self.filterActionP.isChecked() or self.filterActionS.isChecked(): elif self.filterActionP.isChecked() or self.filterActionS.isChecked():
self.adjustFilterOptions() self.adjustFilterOptions()
else: else:
self.get_data().resetWFData() self.get_data().reset_wf_data()
if plot: if plot:
self.plotWaveformDataThread(filter=False) self.plotWaveformDataThread(filter=False)
@ -2531,10 +2531,10 @@ class MainWindow(QMainWindow):
show_comp_data=self.dataPlot.comp_checkbox.isChecked()) show_comp_data=self.dataPlot.comp_checkbox.isChecked())
if self.filterActionP.isChecked(): if self.filterActionP.isChecked():
pickDlg.currentPhase = "P" pickDlg.currentPhase = "P"
pickDlg.filterWFData() pickDlg.filter_wf_data()
elif self.filterActionS.isChecked(): elif self.filterActionS.isChecked():
pickDlg.currentPhase = "S" pickDlg.currentPhase = "S"
pickDlg.filterWFData() pickDlg.filter_wf_data()
pickDlg.nextStation.setChecked(self.nextStation) pickDlg.nextStation.setChecked(self.nextStation)
pickDlg.nextStation.stateChanged.connect(self.toggle_next_station) pickDlg.nextStation.stateChanged.connect(self.toggle_next_station)
if pickDlg.exec_(): if pickDlg.exec_():
@ -3478,7 +3478,7 @@ class MainWindow(QMainWindow):
if not self.metadata: if not self.metadata:
return None return None
wf_copy = self.get_data().getWFData().copy() wf_copy = self.get_data().get_wf_data().copy()
wf_select = Stream() wf_select = Stream()
# restitute only picked traces # restitute only picked traces

View File

@ -243,7 +243,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
pylot_event = Event(eventpath) # event should be path to event directory pylot_event = Event(eventpath) # event should be path to event directory
data.setEvtData(pylot_event) data.setEvtData(pylot_event)
if fnames == 'None': if fnames == 'None':
data.setWFData(glob.glob(os.path.join(datapath, event_datapath, '*'))) data.set_wf_data(glob.glob(os.path.join(datapath, event_datapath, '*')))
# the following is necessary because within # the following is necessary because within
# multiple event processing no event ID is provided # multiple event processing no event ID is provided
# in autopylot.in # in autopylot.in
@ -258,7 +258,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
now.minute) now.minute)
parameter.setParam(eventID=eventID) parameter.setParam(eventID=eventID)
else: else:
data.setWFData(fnames) data.set_wf_data(fnames)
eventpath = events[0] eventpath = events[0]
# now = datetime.datetime.now() # now = datetime.datetime.now()
@ -268,7 +268,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even
# now.hour, # now.hour,
# now.minute) # now.minute)
parameter.setParam(eventID=eventid) parameter.setParam(eventID=eventid)
wfdat = data.getWFData() # all available streams wfdat = data.get_wf_data() # all available streams
if not station == 'all': if not station == 'all':
wfdat = wfdat.select(station=station) wfdat = wfdat.select(station=station)
if not wfdat: if not wfdat:

View File

@ -9,11 +9,13 @@ from obspy import UTCDateTime
from pylot.core.io.event import EventData from pylot.core.io.event import EventData
from pylot.core.io.waveformdata import WaveformData from pylot.core.io.waveformdata import WaveformData
from pylot.core.util.dataprocessing import Metadata
@dataclass @dataclass
class Data: class Data:
event_data: EventData = field(default_factory=EventData) event_data: EventData = field(default_factory=EventData)
waveform_data: WaveformData = field(default_factory=WaveformData) waveform_data: WaveformData = field(default_factory=WaveformData)
metadata: Metadata = field(default_factory=Metadata)
_parent: Union[None, 'QtWidgets.QWidget'] = None _parent: Union[None, 'QtWidgets.QWidget'] = None
def __init__(self, parent=None, evtdata=None): def __init__(self, parent=None, evtdata=None):
@ -52,10 +54,17 @@ class Data:
self.waveform_data.dirty = True self.waveform_data.dirty = True
def set_wf_data(self, fnames: List[str], fnames_alt: List[str] = None, check_rotated=False, metadata=None, tstart=0, tstop=0): def set_wf_data(self, fnames: List[str], fnames_alt: List[str] = None, check_rotated=False, metadata=None, tstart=0, tstop=0):
return self.waveform_data.set_wf_data(fnames, fnames_alt, check_rotated, metadata, tstart, tstop) return self.waveform_data.load_waveforms(fnames, fnames_alt, check_rotated, metadata, tstart, tstop)
def reset_wf_data(self): def reset_wf_data(self):
self.waveform_data.reset_wf_data() self.waveform_data.reset()
def get_wf_data(self):
return self.waveform_data.wfdata
def rotate_wf_data(self):
self.waveform_data.rotate_zne(self.metadata)
class GenericDataStructure(object): class GenericDataStructure(object):
""" """

13
pylot/core/io/utils.py Normal file
View File

@ -0,0 +1,13 @@
import os
from typing import List
def validate_filenames(filenames: List[str]) -> List[str]:
"""
validate a list of filenames for file abundance
:param filenames: list of possible filenames
:type filenames: List[str]
:return: list of valid filenames
:rtype: List[str]
"""
return [fn for fn in filenames if os.path.isfile(fn)]

View File

@ -1,14 +1,13 @@
import logging import logging
import os
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Union, List from typing import Union, List
import numpy as np
from obspy import Stream, read from obspy import Stream, read
from obspy.io.sac import SacIOError from obspy.io.sac import SacIOError
from obspy.signal.rotate import rotate2zne
from pylot.core.util.utils import full_range, get_stations from pylot.core.io.utils import validate_filenames
from pylot.core.util.dataprocessing import Metadata
from pylot.core.util.utils import get_stations, check_for_nan, check4rotated
@dataclass @dataclass
@ -18,26 +17,39 @@ class WaveformData:
wf_alt: Stream = field(default_factory=Stream) wf_alt: Stream = field(default_factory=Stream)
dirty: bool = False dirty: bool = False
def set_wf_data(self, fnames: List[str], fnames_alt: List[str] = None, check_rotated=False, metadata=None, tstart=0, tstop=0): def load_waveforms(self, fnames: List[str], fnames_alt: List[str] = None, check_rotated=False, metadata=None, tstart=0, tstop=0):
self.clear_data() fn_list = validate_filenames(fnames)
fnames = self.check_fname_exists(fnames) if not fn_list:
fnames_alt = self.check_fname_exists(fnames_alt) logging.warning('No valid filenames given for loading waveforms')
else:
self.clear()
self.add_waveforms(fn_list)
if fnames: if fnames_alt is None:
self.append_wf_data(fnames) pass
if fnames_alt: else:
self.append_wf_data(fnames_alt, alternative=True) alt_fn_list = validate_filenames(fnames_alt)
self.wfdata, _ = self.check_for_gaps_and_merge(self.wfdata) if not alt_fn_list:
self.check_for_nan(self.wfdata) logging.warning('No valid alternative filenames given for loading waveforms')
if check_rotated and metadata: else:
self.wfdata = self.check4rotated(self.wfdata, metadata, verbosity=0) self.add_waveforms(alt_fn_list, alternative=True)
self.trim_station_components(self.wfdata, trim_start=True, trim_end=False)
self.wforiginal = self.wfdata.copy()
self.dirty = False
return True
return False
def append_wf_data(self, fnames: List[str], alternative: bool = False): if not fn_list and not alt_fn_list:
logging.error('No filenames or alternative filenames given for loading waveforms')
return False
self.merge()
self.replace_nan()
if not check_rotated or not metadata:
pass
else:
self.rotate_zne()
self.trim_station_traces()
self.wforiginal = self.wfdata.copy()
self.dirty = False
return True
def add_waveforms(self, fnames: List[str], alternative: bool = False):
data_stream = self.wf_alt if alternative else self.wfdata data_stream = self.wf_alt if alternative else self.wfdata
warnmsg = '' warnmsg = ''
for fname in set(fnames): for fname in set(fnames):
@ -55,189 +67,57 @@ class WaveformData:
warnmsg += f'{fname}\n{se}\n' warnmsg += f'{fname}\n{se}\n'
if warnmsg: if warnmsg:
print(f'WARNING in appendWFData: unable to read waveform data\n{warnmsg}') print(f'WARNING in add_waveforms: unable to read waveform data\n{warnmsg}')
def clear_data(self): def clear(self):
self.wfdata = Stream() self.wfdata = Stream()
self.wforiginal = None self.wforiginal = None
self.wf_alt = Stream() self.wf_alt = Stream()
def reset_wf_data(self): def reset(self):
"""
Resets the waveform data to its original state.
"""
if self.wforiginal: if self.wforiginal:
self.wfdata = self.wforiginal.copy() self.wfdata = self.wforiginal.copy()
else: else:
self.wfdata = Stream() self.wfdata = Stream()
self.dirty = False self.dirty = False
def check_fname_exists(self, filenames: List[str]) -> List[str]: def merge(self):
return [fn for fn in filenames if os.path.isfile(fn)]
def check_for_gaps_and_merge(self, stream):
""" """
check for gaps in Stream and merge if gaps are found check for gaps in Stream and merge if gaps are found
:param stream: stream of seismic data
:type stream: `~obspy.core.stream.Stream`
:return: data stream, gaps returned from obspy get_gaps
:rtype: `~obspy.core.stream.Stream`
""" """
gaps = stream.get_gaps() gaps = self.wfdata.get_gaps()
if gaps: if gaps:
merged = ['{}.{}.{}.{}'.format(*gap[:4]) for gap in gaps] merged = ['{}.{}.{}.{}'.format(*gap[:4]) for gap in gaps]
stream.merge(method=1) self.wfdata.merge(method=1)
print('Merged the following stations because of gaps:') logging.info('Merged the following stations because of gaps:')
for merged_station in merged: for station in merged:
print(merged_station) logging.info(station)
return stream, gaps def replace_nan(self):
def check_for_nan(self, stream):
""" """
Replace all NaNs in data with nan_value (in place) Replace all NaNs in data with 0. (in place)
:param stream: stream of seismic data
:type stream: `~obspy.core.stream.Stream`
:param nan_value: value which all NaNs are set to
:type nan_value: float, int
:return: None
""" """
if not stream: self.wfdata = check_for_nan(self.wfdata)
return
for trace in stream:
np.nan_to_num(trace.data, copy=False, nan=0.)
def rotate_zne(self, metadata: Metadata = None):
def check4rotated(self, stream, metadata=None, verbosity=1):
""" """
Check all traces in data. If a trace is not in ZNE rotation (last symbol of channel code is numeric) and the trace Check all traces in stream for rotation. If a trace is not in ZNE rotation (last symbol of channel code is numeric) and the trace
is in the metadata with azimuth and dip, rotate it to classical ZNE orientation. is in the metadata with azimuth and dip, rotate it to classical ZNE orientation.
Rotating the traces requires them to be of the same length, so, all traces will be trimmed to a common length as a Rotating the traces requires them to be of the same length, so, all traces will be trimmed to a common length as a
side effect. side effect.
:param stream: stream object containing seismic traces
:type stream: `~obspy.core.stream.Stream`
:param metadata: tuple containing metadata type string and metadata parser object
:type metadata: (str, `~obspy.io.xseed.parser.Parser`)
:param verbosity: if 0 print no information at runtime
:type verbosity: int
:return: stream object with traditionally oriented traces (ZNE) for stations that had misaligned traces (123) before
:rtype: `~obspy.core.stream.Stream`
""" """
def rotation_required(trace_ids): self.wfdata = check4rotated(self.wfdata, metadata)
"""
Derive if any rotation is required from the orientation code of the input.
:param trace_ids: string identifier of waveform data trace def trim_station_traces(self):
:type trace_ids: List(str)
:return: boolean representing if rotation is necessary for any of the traces
:rtype: bool
"""
orientations = [trace_id[-1] for trace_id in trace_ids]
return any([orientation.isnumeric() for orientation in orientations])
def rotate_components(wfs_in, metadata=None):
"""
Rotate components if orientation code is numeric (= non traditional orientation).
Azimut and dip are fetched from metadata. To be rotated, traces of a station have to be cut to the same length.
Returns unrotated traces of no metadata is provided
:param wfs_in: stream containing seismic traces of a station
:type wfs_in: `~obspy.core.stream.Stream`
:param metadata: tuple containing metadata type string and metadata parser object
:type metadata: (str, `~obspy.io.xseed.parser.Parser`)
:return: stream object with traditionally oriented traces (ZNE)
:rtype: `~obspy.core.stream.Stream`
"""
if len(wfs_in) < 3:
print(f"Stream {wfs_in=}, has not enough components to rotate.")
return wfs_in
# check if any traces in this station need to be rotated
trace_ids = [trace.id for trace in wfs_in]
if not rotation_required(trace_ids):
logging.debug(f"Stream does not need any rotation: Traces are {trace_ids=}")
return wfs_in
# check metadata quality
t_start = full_range(wfs_in)
try:
azimuths = []
dips = []
for tr_id in trace_ids:
azimuths.append(metadata.get_coordinates(tr_id, t_start)['azimuth'])
dips.append(metadata.get_coordinates(tr_id, t_start)['dip'])
except (KeyError, TypeError) as err:
logging.error(
f"{type(err)=} occurred: {err=} Rotating not possible, not all azimuth and dip information "
f"available in metadata. Stream remains unchanged.")
return wfs_in
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
raise
# to rotate all traces must have same length, so trim them
wfs_out = self.trim_station_components(wfs_in, trim_start=True, trim_end=True)
try:
z, n, e = rotate2zne(wfs_out[0], azimuths[0], dips[0],
wfs_out[1], azimuths[1], dips[1],
wfs_out[2], azimuths[2], dips[2])
print('check4rotated: rotated trace {} to ZNE'.format(trace_ids))
# replace old data with rotated data, change the channel code to ZNE
z_index = dips.index(min(
dips)) # get z-trace index, z has minimum dip of -90 (dip is measured from 0 to -90, with -90
# being vertical)
wfs_out[z_index].data = z
wfs_out[z_index].stats.channel = wfs_out[z_index].stats.channel[0:-1] + 'Z'
del trace_ids[z_index]
for trace_id in trace_ids:
coordinates = metadata.get_coordinates(trace_id, t_start)
dip, az = coordinates['dip'], coordinates['azimuth']
trace = wfs_out.select(id=trace_id)[0]
if az > 315 or az <= 45 or 135 < az <= 225:
trace.data = n
trace.stats.channel = trace.stats.channel[0:-1] + 'N'
elif 45 < az <= 135 or 225 < az <= 315:
trace.data = e
trace.stats.channel = trace.stats.channel[0:-1] + 'E'
except ValueError as err:
print(f"{err=} Rotation failed. Stream remains unchanged.")
return wfs_in
return wfs_out
if metadata is None:
if verbosity:
msg = 'Warning: could not rotate traces since no metadata was given\nset Inventory file!'
print(msg)
return stream
stations = get_stations(stream)
for station in stations: # loop through all stations and rotate data if neccessary
wf_station = stream.select(station=station)
rotate_components(wf_station, metadata)
return stream
def trim_station_components(stream, trim_start=True, trim_end=True):
""" """
cut a stream so only the part common to all three traces is kept to avoid dealing with offsets trim data stream to common time window
:param stream: stream of seismic data
:type stream: `~obspy.core.stream.Stream`
:param trim_start: trim start of stream
:type trim_start: bool
:param trim_end: trim end of stream
:type trim_end: bool
:return: data stream
:rtype: `~obspy.core.stream.Stream`
""" """
starttime = {False: None}
endtime = {False: None}
stations = get_stations(stream) for station in get_stations(self.wfdata):
station_traces = self.wfdata.select(station=station)
print('trim_station_components: Will trim stream for trim_start: {} and for ' station_traces.trim(starttime=max([trace.stats.starttime for trace in station_traces]),
'trim_end: {}.'.format(trim_start, trim_end)) endtime=min([trace.stats.endtime for trace in station_traces]))
for station in stations:
wf_station = stream.select(station=station)
starttime[True] = max([trace.stats.starttime for trace in wf_station])
endtime[True] = min([trace.stats.endtime for trace in wf_station])
wf_station.trim(starttime=starttime[trim_start], endtime=endtime[trim_end])
return stream

View File

@ -474,8 +474,8 @@ class Array_map(QtWidgets.QWidget):
transform=ccrs.PlateCarree(), label='deleted')) transform=ccrs.PlateCarree(), label='deleted'))
def openPickDlg(self, ind): def openPickDlg(self, ind):
wfdata = self._parent.get_data().getWFData() wfdata = self._parent.get_data().get_wf_data()
wfdata_comp = self._parent.get_data().getWFDataComp() wfdata_comp = self._parent.get_data().get_wf_dataComp()
for index in ind: for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2] network, station = self._station_onpick_ids[index].split('.')[:2]
pyl_mw = self._parent pyl_mw = self._parent

View File

@ -1912,7 +1912,7 @@ class PickDlg(QDialog):
# set attribute holding data # set attribute holding data
if data is None or not data: if data is None or not data:
try: try:
data = parent.get_data().getWFData().copy() data = parent.get_data().get_wf_data().copy()
self.data = data.select(station=station) self.data = data.select(station=station)
except AttributeError as e: except AttributeError as e:
errmsg = 'You either have to put in a data or an appropriate ' \ errmsg = 'You either have to put in a data or an appropriate ' \
@ -1946,7 +1946,7 @@ class PickDlg(QDialog):
self.cur_xlim = None self.cur_xlim = None
self.cur_ylim = None self.cur_ylim = None
self.stime, self.etime = full_range(self.getWFData()) self.stime, self.etime = full_range(self.get_wf_data())
# initialize plotting widget # initialize plotting widget
self.multicompfig = PylotCanvas(parent=self, multicursor=True) self.multicompfig = PylotCanvas(parent=self, multicursor=True)
@ -1960,7 +1960,7 @@ class PickDlg(QDialog):
self.referenceChannel.addItem('-', None) self.referenceChannel.addItem('-', None)
self.scaleChannel.addItem('individual', None) self.scaleChannel.addItem('individual', None)
for trace in self.getWFData(): for trace in self.get_wf_data():
channel = trace.stats.channel channel = trace.stats.channel
self.referenceChannel.addItem(channel, trace) self.referenceChannel.addItem(channel, trace)
if not channel[-1] in ['Z', 'N', 'E', '1', '2', '3']: if not channel[-1] in ['Z', 'N', 'E', '1', '2', '3']:
@ -1979,7 +1979,7 @@ class PickDlg(QDialog):
if self.wftype is not None: if self.wftype is not None:
title += ' | ({})'.format(self.wftype) title += ' | ({})'.format(self.wftype)
self.multicompfig.plotWFData(wfdata=self.getWFData(), wfdata_compare=self.getWFDataComp(), self.multicompfig.plotWFData(wfdata=self.get_wf_data(), wfdata_compare=self.get_wf_dataComp(),
title=title) title=title)
self.multicompfig.setZoomBorders2content() self.multicompfig.setZoomBorders2content()
@ -2514,7 +2514,7 @@ class PickDlg(QDialog):
if self.autoFilterAction.isChecked(): if self.autoFilterAction.isChecked():
for filteraction in [self.filterActionP, self.filterActionS]: for filteraction in [self.filterActionP, self.filterActionS]:
filteraction.setChecked(False) filteraction.setChecked(False)
self.filterWFData() self.filter_wf_data()
self.draw() self.draw()
else: else:
self.draw() self.draw()
@ -2598,10 +2598,10 @@ class PickDlg(QDialog):
def getGlobalLimits(self, ax, axis): def getGlobalLimits(self, ax, axis):
return self.multicompfig.getGlobalLimits(ax, axis) return self.multicompfig.getGlobalLimits(ax, axis)
def getWFData(self): def get_wf_data(self):
return self.data return self.data
def getWFDataComp(self): def get_wf_dataComp(self):
if self.showCompData: if self.showCompData:
return self.data_compare return self.data_compare
else: else:
@ -2616,17 +2616,17 @@ class PickDlg(QDialog):
return tr return tr
if component == 'E' or component == 'N': if component == 'E' or component == 'N':
for trace in self.getWFData(): for trace in self.get_wf_data():
trace = selectTrace(trace, 'NE') trace = selectTrace(trace, 'NE')
if trace: if trace:
wfdata.append(trace) wfdata.append(trace)
elif component == '1' or component == '2': elif component == '1' or component == '2':
for trace in self.getWFData(): for trace in self.get_wf_data():
trace = selectTrace(trace, '12') trace = selectTrace(trace, '12')
if trace: if trace:
wfdata.append(trace) wfdata.append(trace)
else: else:
wfdata = self.getWFData().select(component=component) wfdata = self.get_wf_data().select(component=component)
return wfdata return wfdata
def getPicks(self, picktype='manual'): def getPicks(self, picktype='manual'):
@ -2729,8 +2729,8 @@ class PickDlg(QDialog):
stime = self.getStartTime() stime = self.getStartTime()
# copy wfdata for plotting # copy wfdata for plotting
wfdata = self.getWFData().copy() wfdata = self.get_wf_data().copy()
wfdata_comp = self.getWFDataComp().copy() wfdata_comp = self.get_wf_dataComp().copy()
wfdata = self.getPickPhases(wfdata, phase) wfdata = self.getPickPhases(wfdata, phase)
wfdata_comp = self.getPickPhases(wfdata_comp, phase) wfdata_comp = self.getPickPhases(wfdata_comp, phase)
for wfd in [wfdata, wfdata_comp]: for wfd in [wfdata, wfdata_comp]:
@ -2839,7 +2839,7 @@ class PickDlg(QDialog):
filteroptions = None filteroptions = None
# copy and filter data for earliest and latest possible picks # copy and filter data for earliest and latest possible picks
wfdata = self.getWFData().copy().select(channel=channel) wfdata = self.get_wf_data().copy().select(channel=channel)
if filteroptions: if filteroptions:
try: try:
wfdata.detrend('linear') wfdata.detrend('linear')
@ -2886,7 +2886,7 @@ class PickDlg(QDialog):
minFMSNR = parameter.get('minFMSNR') minFMSNR = parameter.get('minFMSNR')
quality = get_quality_class(spe, parameter.get('timeerrorsP')) quality = get_quality_class(spe, parameter.get('timeerrorsP'))
if quality <= minFMweight and snr >= minFMSNR: if quality <= minFMweight and snr >= minFMSNR:
FM = fmpicker(self.getWFData().select(channel=channel).copy(), wfdata.copy(), parameter.get('fmpickwin'), FM = fmpicker(self.get_wf_data().select(channel=channel).copy(), wfdata.copy(), parameter.get('fmpickwin'),
pick - stime_diff) pick - stime_diff)
# save pick times for actual phase # save pick times for actual phase
@ -3178,7 +3178,7 @@ class PickDlg(QDialog):
def togglePickBlocker(self): def togglePickBlocker(self):
return not self.pick_block return not self.pick_block
def filterWFData(self, phase=None): def filter_wf_data(self, phase=None):
if not phase: if not phase:
phase = self.currentPhase phase = self.currentPhase
if self.getPhaseID(phase) == 'P': if self.getPhaseID(phase) == 'P':
@ -3196,8 +3196,8 @@ class PickDlg(QDialog):
self.cur_xlim = self.multicompfig.axes[0].get_xlim() self.cur_xlim = self.multicompfig.axes[0].get_xlim()
self.cur_ylim = self.multicompfig.axes[0].get_ylim() self.cur_ylim = self.multicompfig.axes[0].get_ylim()
# self.multicompfig.updateCurrentLimits() # self.multicompfig.updateCurrentLimits()
wfdata = self.getWFData().copy() wfdata = self.get_wf_data().copy()
wfdata_comp = self.getWFDataComp().copy() wfdata_comp = self.get_wf_dataComp().copy()
title = self.getStation() title = self.getStation()
if filter: if filter:
filtoptions = None filtoptions = None
@ -3234,14 +3234,14 @@ class PickDlg(QDialog):
def filterP(self): def filterP(self):
self.filterActionS.setChecked(False) self.filterActionS.setChecked(False)
if self.filterActionP.isChecked(): if self.filterActionP.isChecked():
self.filterWFData('P') self.filter_wf_data('P')
else: else:
self.refreshPlot() self.refreshPlot()
def filterS(self): def filterS(self):
self.filterActionP.setChecked(False) self.filterActionP.setChecked(False)
if self.filterActionS.isChecked(): if self.filterActionS.isChecked():
self.filterWFData('S') self.filter_wf_data('S')
else: else:
self.refreshPlot() self.refreshPlot()
@ -3300,7 +3300,7 @@ class PickDlg(QDialog):
if self.autoFilterAction.isChecked(): if self.autoFilterAction.isChecked():
self.filterActionP.setChecked(False) self.filterActionP.setChecked(False)
self.filterActionS.setChecked(False) self.filterActionS.setChecked(False)
# data = self.getWFData().copy() # data = self.get_wf_data().copy()
# title = self.getStation() # title = self.getStation()
filter = False filter = False
phase = None phase = None
@ -3800,8 +3800,8 @@ class TuneAutopicker(QWidget):
fnames = self.station_ids[self.get_current_station_id()] fnames = self.station_ids[self.get_current_station_id()]
if not fnames == self.fnames: if not fnames == self.fnames:
self.fnames = fnames self.fnames = fnames
self.data.setWFData(fnames) self.data.set_wf_data(fnames)
wfdat = self.data.getWFData() # all available streams wfdat = self.data.get_wf_data() # all available streams
# remove possible underscores in station names # remove possible underscores in station names
# wfdat = remove_underscores(wfdat) # wfdat = remove_underscores(wfdat)
# rotate misaligned stations to ZNE # rotate misaligned stations to ZNE
@ -3906,8 +3906,8 @@ class TuneAutopicker(QWidget):
network = None network = None
location = None location = None
wfdata = self.data.getWFData() wfdata = self.data.get_wf_data()
wfdata_comp = self.data.getWFDataComp() wfdata_comp = self.data.get_wf_dataComp()
metadata = self.parent().metadata metadata = self.parent().metadata
event = self.get_current_event() event = self.get_current_event()
filteroptions = self.parent().filteroptions filteroptions = self.parent().filteroptions
@ -3962,7 +3962,7 @@ class TuneAutopicker(QWidget):
for plotitem in self._manual_pick_plots: for plotitem in self._manual_pick_plots:
self.clear_plotitem(plotitem) self.clear_plotitem(plotitem)
self._manual_pick_plots = [] self._manual_pick_plots = []
st = self.data.getWFData() st = self.data.get_wf_data()
tr = st.select(station=self.get_current_station())[0] tr = st.select(station=self.get_current_station())[0]
starttime = tr.stats.starttime starttime = tr.stats.starttime
# create two lists with figure names and subindices (for subplots) to get the correct axes # create two lists with figure names and subindices (for subplots) to get the correct axes