From cd612def81613e0b416c0b7f5c7729d1b7ad7b2a Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Wed, 31 May 2017 16:25:46 +0200 Subject: [PATCH 01/10] WIP: working on saving filter options as part of project --- QtPyLoT.py | 16 +++++++++++----- pylot/RELEASE-VERSION | 2 +- pylot/core/util/widgets.py | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index bbb264b9..78d5d2d7 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1314,7 +1314,7 @@ class MainWindow(QMainWindow): self.adjustFilterOptions() else: self.get_data().resetWFData() - self.plotWaveformData() + self.plotWaveformDataThread() self.drawPicks() self.draw() @@ -1328,11 +1328,11 @@ class MainWindow(QMainWindow): if self.filterAction.isChecked(): kwargs = self.getFilterOptions().parseFilterOptions() self.pushFilterWF(kwargs) - self.plotWaveformData() + self.plotWaveformDataThread() def getFilterOptions(self): try: - return self.filteroptions[self.getSeismicPhase()] + return self.project.filteroptions[self.getSeismicPhase()] except AttributeError as e: print(e) return FilterOptions(None, None, None) @@ -1341,10 +1341,12 @@ class MainWindow(QMainWindow): return self.filteroptions def setFilterOptions(self, filterOptions, seismicPhase=None): + if not self.project: + return if seismicPhase is None: - self.getFilters()[self.getSeismicPhase()] = filterOptions + self.project.filteroptions[self.getSeismicPhase()] = filterOptions else: - self.getFilters()[seismicPhase] = filterOptions + self.project.filteroptions[seismicPhase] = filterOptions def updateFilterOptions(self): try: @@ -2147,6 +2149,10 @@ class Project(object): def __init__(self): self.eventlist = [] self.location = None + self.filteroptions = { + 'P': FilterOptions(), + 'S': FilterOptions() + } self.dirty = False self._table = None diff --git a/pylot/RELEASE-VERSION b/pylot/RELEASE-VERSION index d06fb391..4fcc02b2 100644 --- a/pylot/RELEASE-VERSION +++ b/pylot/RELEASE-VERSION @@ -1 +1 @@ -02a5-dirty +62fa-dirty diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 4c9e7860..e7173464 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2399,7 +2399,7 @@ class FilterOptionsDialog(QDialog): """ super(FilterOptionsDialog, self).__init__() - if parent is not None and parent.getFilterOptions(): + if parent is not None and parent.getFilters(): self.filterOptions = parent.getFilterOptions() elif filterOptions is not None: self.filterOptions = FilterOptions(filterOptions) From ca1d3dca3821ccf41298afe2fc4657ca517afc05 Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Thu, 22 Jun 2017 12:01:22 +0200 Subject: [PATCH 02/10] [add] filter parameters added to default parameters --- pylot/RELEASE-VERSION | 2 +- pylot/core/io/default_parameters.py | 25 +++++++++++++++++++++++-- pylot/core/io/inputs.py | 5 ++++- pylot/core/util/widgets.py | 4 +++- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/pylot/RELEASE-VERSION b/pylot/RELEASE-VERSION index 6bf29797..d2392439 100644 --- a/pylot/RELEASE-VERSION +++ b/pylot/RELEASE-VERSION @@ -1 +1 @@ -f91e1-dirty +97ee-dirty diff --git a/pylot/core/io/default_parameters.py b/pylot/core/io/default_parameters.py index 93d55ae4..c936436b 100644 --- a/pylot/core/io/default_parameters.py +++ b/pylot/core/io/default_parameters.py @@ -282,8 +282,24 @@ defaults = {'rootpath': {'type': str, 'value': (1.0, 1.0, 1.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]', + 'value': (1.0, 1.0)}, + + 'minfreq': {'type': float, + 'tooltip': 'Lower filter frequency', + 'value': 1.0}, + + 'maxfreq': {'type': float, + 'tooltip': 'Upper filter frequency', + 'value': 10.0}, + + 'filter_order': {'type': int, + 'tooltip': 'filter order', + 'value': 2}, + + 'filter_type': {'type': str, + 'tooltip': 'filter type (bandpass, bandstop, lowpass, highpass)', + 'value': None} } settings_main={ @@ -309,6 +325,11 @@ settings_main={ 'localmag':[ 'WAscaling', 'magscaling'], + 'filter':[ + 'minfreq', + 'maxfreq', + 'filter_order', + 'filter_type'], 'pick':[ 'extent', 'pstart', diff --git a/pylot/core/io/inputs.py b/pylot/core/io/inputs.py index 3653b828..26e2e233 100644 --- a/pylot/core/io/inputs.py +++ b/pylot/core/io/inputs.py @@ -141,7 +141,8 @@ class PylotParameter(object): all_names += self.get_main_para_names()['nlloc'] all_names += self.get_main_para_names()['smoment'] all_names += self.get_main_para_names()['localmag'] - all_names += self.get_main_para_names()['pick'] + all_names += self.get_main_para_names()['pick'] + all_names += self.get_main_para_names()['filter'] all_names += self.get_special_para_names()['z'] all_names += self.get_special_para_names()['h'] all_names += self.get_special_para_names()['fm'] @@ -237,6 +238,8 @@ class PylotParameter(object): 'parameters for seismic moment estimation', seperator) self.write_section(fid_out, self.get_main_para_names()['localmag'], 'settings local magnitude', seperator) + self.write_section(fid_out, self.get_main_para_names()['filter'], + 'filter settings', seperator) self.write_section(fid_out, self.get_main_para_names()['pick'], 'common settings picker', seperator) fid_out.write(('#special settings for calculating CF#\n'+ diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 29cabb60..7765b2b3 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2135,8 +2135,10 @@ class PylotParaBox(QtGui.QWidget): self.parameter.get_main_para_names()['smoment'], 2) self.add_to_layout(self._main_layout, 'Local Magnitude', self.parameter.get_main_para_names()['localmag'], 3) + self.add_to_layout(self._main_layout, 'Filter Settings', + self.parameter.get_main_para_names()['filter'], 4) self.add_to_layout(self._main_layout, 'Common Settings Characteristic Function', - self.parameter.get_main_para_names()['pick'], 4) + self.parameter.get_main_para_names()['pick'], 5) self.add_tab(self._main_layout, 'Main Settings') def add_special_pick_parameters_tab(self): From 1b3c29c47ee03a5dd416de709205df800a5e6d1c Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Tue, 4 Jul 2017 10:31:23 +0200 Subject: [PATCH 03/10] [bugfix] missing comma in dictionary definition, also corrected misspelling --- pylot/core/io/default_parameters.py | 12 ++++++------ pylot/core/io/inputs.py | 2 +- pylot/core/util/widgets.py | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pylot/core/io/default_parameters.py b/pylot/core/io/default_parameters.py index cd078812..9285f1e9 100644 --- a/pylot/core/io/default_parameters.py +++ b/pylot/core/io/default_parameters.py @@ -278,14 +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] \ - If zeros are set, original Richter magnitude is calculated!', - 'value': (0., 0., 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]. \ - If zeros are set, no scaling of network magnitude is applied!', - 'value': (0., 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.)}, 'minfreq': {'type': float, 'tooltip': 'Lower filter frequency', diff --git a/pylot/core/io/inputs.py b/pylot/core/io/inputs.py index a4628188..aad56f78 100644 --- a/pylot/core/io/inputs.py +++ b/pylot/core/io/inputs.py @@ -238,7 +238,7 @@ class PylotParameter(object): self.write_section(fid_out, self.get_main_para_names()['localmag'], 'settings local magnitude', separator) self.write_section(fid_out, self.get_main_para_names()['filter'], - 'filter settings', seperator) + 'filter settings', separator) self.write_section(fid_out, self.get_main_para_names()['pick'], 'common settings picker', separator) fid_out.write(('#special settings for calculating CF#\n'+ diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 1cdf7ba4..00950147 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2263,10 +2263,10 @@ class PylotParaBox(QtGui.QWidget): self.parameter.get_special_para_names()['quality'], 4) self.add_tab(self._advanced_layout, 'Advanced Settings') - # def gen_h_seperator(self): - # seperator = QtGui.QFrame() - # seperator.setFrameShape(QtGui.QFrame.HLine) - # return seperator + # def gen_h_separator(self): + # separator = QtGui.QFrame() + # separator.setFrameShape(QtGui.QFrame.HLine) + # return separator # def gen_headline(self, text): # label=QtGui.QLabel(text) From 097222a43dbccc2eafb69d2d8b24d7e37486c1ab Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Tue, 4 Jul 2017 14:39:10 +0200 Subject: [PATCH 04/10] [add] namestrings for default parameters, filteroptions connected to parameters (WIP) [change] layout of pylotparabox --- QtPyLoT.py | 18 ++- pylot/core/io/default_parameters.py | 241 ++++++++++++++++++---------- pylot/core/io/inputs.py | 5 +- pylot/core/util/widgets.py | 36 +++-- 4 files changed, 202 insertions(+), 98 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 2750ff23..576a4f77 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1569,7 +1569,18 @@ class MainWindow(QMainWindow): self.project.filteroptions[self.getSeismicPhase()] = filterOptions else: self.project.filteroptions[seismicPhase] = filterOptions + self._inputs.setParamKV('minfreq', float(filterOptions.getFreq()[0])) + self._inputs.setParamKV('maxfreq', float(filterOptions.getFreq()[1])) + self._inputs.setParamKV('filter_order', int(filterOptions.getOrder())) + self._inputs.setParamKV('filter_type', str(filterOptions.getFilterType())) + def filterOptionsFromParameter(self): + if not self.project: + return + self.project.filteroptions.setFreq([self._inputs['minfreq'], self._inputs['axfreq']]) + self.project.filteroptions.setOrder(self._inputs['filter_order']) + self.project.filteroptions.setFilterType(self._inputs['filter_type']) + def updateFilterOptions(self): try: settings = QSettings() @@ -2394,6 +2405,9 @@ class MainWindow(QMainWindow): if hasattr(self.project, 'parameter'): if self.project.parameter: self._inputs = self.project.parameter + if not hasattr(self.project, 'filteroptions'): + self.project.filteroptions = {'P': FilterOptions(), + 'S': FilterOptions()} self.tabs.setCurrentIndex(0) # implemented to prevent double-loading of waveform data self.init_events(new=True) self.setDirty(False) @@ -2473,9 +2487,11 @@ class MainWindow(QMainWindow): self.paraBox = PylotParaBox(self._inputs) self.paraBox._apply.clicked.connect(self._setDirty) self.paraBox._okay.clicked.connect(self._setDirty) + self.paraBox._apply.clicked.connect(self.filterOptionsFromParameter) + self.paraBox._okay.clicked.connect(self.filterOptionsFromParameter) if show: self.paraBox.show() - + def PyLoTprefs(self): if not self._props: self._props = PropertiesDlg(self, infile=self.infile) diff --git a/pylot/core/io/default_parameters.py b/pylot/core/io/default_parameters.py index 9285f1e9..adf150fc 100644 --- a/pylot/core/io/default_parameters.py +++ b/pylot/core/io/default_parameters.py @@ -3,305 +3,380 @@ defaults = {'rootpath': {'type': str, 'tooltip': 'project path', - 'value': ''}, + 'value': '', + 'namestring': 'Root path'}, 'datapath': {'type': str, 'tooltip': 'data path', - 'value': ''}, + 'value': '', + 'namestring': 'Data path'}, 'database': {'type': str, 'tooltip': 'name of data base', - 'value': ''}, + 'value': '', + 'namestring': 'Database path'}, 'eventID': {'type': str, 'tooltip': 'event ID for single event processing (* for all events found in database)', - 'value': ''}, + 'value': '', + 'namestring': 'Event ID'}, 'extent': {'type': str, 'tooltip': 'extent of array ("local", "regional" or "global")', - 'value': 'local'}, + 'value': 'local', + 'namestring': 'Array extent'}, 'invdir': {'type': str, 'tooltip': 'full path to inventory or dataless-seed file', - 'value': ''}, + 'value': '', + 'namestring': 'Inversion dir'}, 'datastructure': {'type': str, 'tooltip': 'choose data structure', - 'value': 'PILOT'}, + 'value': 'PILOT', + 'namestring': 'Datastructure'}, 'apverbose': {'type': bool, 'tooltip': "choose 'True' or 'False' for terminal output", - 'value': True}, + 'value': True, + 'namestring': 'App. verbosity'}, 'nllocbin': {'type': str, 'tooltip': 'path to NLLoc executable', - 'value': ''}, + 'value': '', + 'namestring': 'NLLoc bin path'}, 'nllocroot': {'type': str, 'tooltip': 'root of NLLoc-processing directory', - 'value': ''}, + 'value': '', + 'namestring': 'NLLoc root path'}, 'phasefile': {'type': str, 'tooltip': 'name of autoPyLoT-output phase file for NLLoc', - 'value': 'AUTOPHASES.obs'}, + 'value': 'AUTOPHASES.obs', + 'namestring': 'Phase filename'}, 'ctrfile': {'type': str, 'tooltip': 'name of autoPyLoT-output control file for NLLoc', - 'value': 'Insheim_min1d2015_auto.in'}, + 'value': 'Insheim_min1d2015_auto.in', + 'namestring': 'Control filename'}, 'ttpatter': {'type': str, 'tooltip': 'pattern of NLLoc ttimes from grid', - 'value': 'ttime'}, + 'value': 'ttime', + 'namestring': 'Traveltime pattern'}, 'outpatter': {'type': str, 'tooltip': 'pattern of NLLoc-output file', - 'value': 'AUTOLOC_nlloc'}, + 'value': 'AUTOLOC_nlloc', + 'namestring': 'NLLoc output pattern'}, 'vp': {'type': float, 'tooltip': 'average P-wave velocity', - 'value': 3530.}, + 'value': 3530., + 'namestring': 'P-velocity'}, 'rho': {'type': float, 'tooltip': 'average rock density [kg/m^3]', - 'value': 2500.}, + 'value': 2500., + 'namestring': 'Density'}, 'Qp': {'type': (float, float), 'tooltip': 'quality factor for P waves (Qp*f^a); list(Qp, a)', - 'value': (300., 0.8)}, + 'value': (300., 0.8), + 'namestring': ('Quality factor', 'Qp1', 'Qp2')}, 'pstart': {'type': float, 'tooltip': 'start time [s] for calculating CF for P-picking', - 'value': 15.0}, + 'value': 15.0, + 'namestring': 'P start'}, 'pstop': {'type': float, 'tooltip': 'end time [s] for calculating CF for P-picking', - 'value': 60.0}, + 'value': 60.0, + 'namestring': 'P stop'}, 'sstart': {'type': float, 'tooltip': 'start time [s] relative to P-onset for calculating CF for S-picking', - 'value': -1.0}, + 'value': -1.0, + 'namestring': 'S start'}, 'sstop': {'type': float, 'tooltip': 'end time [s] after P-onset for calculating CF for S-picking', - 'value': 10.0}, + 'value': 10.0, + 'namestring': 'S stop'}, 'bpz1': {'type': (float, float), 'tooltip': 'lower/upper corner freq. of first band pass filter Z-comp. [Hz]', - 'value': (2, 20)}, + 'value': (2, 20), + 'namestring': ('Z-bandpass 1', 'Lower', 'Upper')}, 'bpz2': {'type': (float, float), 'tooltip': 'lower/upper corner freq. of second band pass filter Z-comp. [Hz]', - 'value': (2, 30)}, + 'value': (2, 30), + 'namestring': ('Z-bandpass 2', '', '')}, 'bph1': {'type': (float, float), 'tooltip': 'lower/upper corner freq. of first band pass filter H-comp. [Hz]', - 'value': (2, 15)}, + 'value': (2, 15), + 'namestring': ('H-bandpass 1', 'Lower', 'Upper')}, 'bph2': {'type': (float, float), 'tooltip': 'lower/upper corner freq. of second band pass filter z-comp. [Hz]', - 'value': (2, 20)}, + 'value': (2, 20), + 'namestring': ('H-bandpass 2', '', '')}, 'algoP': {'type': str, 'tooltip': 'choose algorithm for P-onset determination (HOS, ARZ, or AR3)', - 'value': 'HOS'}, + 'value': 'HOS', + 'namestring': 'P algorithm'}, 'tlta': {'type': float, 'tooltip': 'for HOS-/AR-AIC-picker, length of LTA window [s]', - 'value': 7.0}, + 'value': 7.0, + 'namestring': 'LTA window'}, 'hosorder': {'type': int, 'tooltip': 'for HOS-picker, order of Higher Order Statistics', - 'value': 4}, + 'value': 4, + 'namestring': 'HOS order'}, 'Parorder': {'type': int, 'tooltip': 'for AR-picker, order of AR process of Z-component', - 'value': 2}, + 'value': 2, + 'namestring': 'AR order P'}, 'tdet1z': {'type': float, 'tooltip': 'for AR-picker, length of AR determination window [s] for Z-component, 1st pick', - 'value': 1.2}, + 'value': 1.2, + 'namestring': 'AR det. window Z 1'}, 'tpred1z': {'type': float, 'tooltip': 'for AR-picker, length of AR prediction window [s] for Z-component, 1st pick', - 'value': 0.4}, + 'value': 0.4, + 'namestring': 'AR pred. window Z 1'}, 'tdet2z': {'type': float, 'tooltip': 'for AR-picker, length of AR determination window [s] for Z-component, 2nd pick', - 'value': 0.6}, + 'value': 0.6, + 'namestring': 'AR det. window Z 2'}, 'tpred2z': {'type': float, 'tooltip': 'for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick', - 'value': 0.2}, + 'value': 0.2, + 'namestring': 'AR pred. window Z 2'}, 'addnoise': {'type': float, 'tooltip': 'add noise to seismogram for stable AR prediction', - 'value': 0.001}, + 'value': 0.001, + 'namestring': 'Add noise'}, 'tsnrz': {'type': (float, float, float, float), 'tooltip': 'for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]', - 'value': (3, 0.1, 0.5, 1.0)}, + 'value': (3, 0.1, 0.5, 1.0), + 'namestring': ('SNR windows P', 'Noise', 'Safety', 'Signal', 'Slope')}, 'pickwinP': {'type': float, 'tooltip': 'for initial AIC pick, length of P-pick window [s]', - 'value': 3.0}, + 'value': 3.0, + 'namestring': 'AIC window P'}, 'Precalcwin': {'type': float, 'tooltip': 'for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick)', - 'value': 6.0}, + 'value': 6.0, + 'namestring': 'Recal. window P'}, 'aictsmooth': {'type': float, 'tooltip': 'for HOS/AR, take average of samples for smoothing of AIC-function [s]', - 'value': 0.2}, + 'value': 0.2, + 'namestring': 'AIC smooth P'}, 'tsmoothP': {'type': float, 'tooltip': 'for HOS/AR, take average of samples for smoothing CF [s]', - 'value': 0.1}, + 'value': 0.1, + 'namestring': 'CF smooth P'}, 'ausP': {'type': float, 'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (P)', - 'value': 0.001}, + 'value': 0.001, + 'namestring': 'Artificial uplift P'}, 'nfacP': {'type': float, 'tooltip': 'for HOS/AR, noise factor for noise level determination (P)', - 'value': 1.3}, + 'value': 1.3, + 'namestring': 'Noise factor P'}, 'algoS': {'type': str, 'tooltip': 'choose algorithm for S-onset determination (ARH or AR3)', - 'value': 'ARH'}, + 'value': 'ARH', + 'namestring': 'S algorithm'}, 'tdet1h': {'type': float, 'tooltip': 'for HOS/AR, length of AR-determination window [s], H-components, 1st pick', - 'value': 0.8}, + 'value': 0.8, + 'namestring': 'AR det. window H 1'}, 'tpred1h': {'type': float, 'tooltip': 'for HOS/AR, length of AR-prediction window [s], H-components, 1st pick', - 'value': 0.4}, + 'value': 0.4, + 'namestring': 'AR pred. window H 1'}, 'tdet2h': {'type': float, 'tooltip': 'for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick', - 'value': 0.6}, + 'value': 0.6, + 'namestring': 'AR det. window H 2'}, 'tpred2h': {'type': float, 'tooltip': 'for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick', - 'value': 0.3}, + 'value': 0.3, + 'namestring': 'AR pred. window H 2'}, 'Sarorder': {'type': int, 'tooltip': 'for AR-picker, order of AR process of H-components', - 'value': 4}, + 'value': 4, + 'namestring': 'AR order S'}, 'Srecalcwin': {'type': float, 'tooltip': 'for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)', - 'value': 5.0}, + 'value': 5.0, + 'namestring': 'Recal. window S'}, 'pickwinS': {'type': float, 'tooltip': 'for initial AIC pick, length of S-pick window [s]', - 'value': 3.0}, + 'value': 3.0, + 'namestring': 'AIC window S'}, 'tsnrh': {'type': (float, float, float, float), 'tooltip': 'for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s]', - 'value': (2, 0.2, 1.5, 0.5)}, + 'value': (2, 0.2, 1.5, 0.5), + 'namestring': ('SNR windows S', 'Noise', 'Safety', 'Signal', 'Slope')}, 'aictsmoothS': {'type': float, 'tooltip': 'for AIC-picker, take average of samples for smoothing of AIC-function [s]', - 'value': 0.5}, + 'value': 0.5, + 'namestring': 'AIC smooth S'}, 'tsmoothS': {'type': float, 'tooltip': 'for AR-picker, take average of samples for smoothing CF [s] (S)', - 'value': 0.7}, + 'value': 0.7, + 'namestring': 'CF smooth S'}, 'ausS': {'type': float, 'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (S)', - 'value': 0.9}, + 'value': 0.9, + 'namestring': 'Artificial uplift S'}, 'nfacS': {'type': float, 'tooltip': 'for AR-picker, noise factor for noise level determination (S)', - 'value': 1.5}, + 'value': 1.5, + 'namestring': 'Noise factor S'}, 'minfmweight': {'type': int, 'tooltip': 'minimum required P weight for first-motion determination', - 'value': 1}, + 'value': 1, + 'namestring': 'Min. P weight'}, 'minFMSNR': {'type': float, 'tooltip': 'miniumum required SNR for first-motion determination', - 'value': 2.}, + 'value': 2., + 'namestring': 'Min SNR'}, 'fmpickwin': {'type': float, 'tooltip': 'pick window around P onset for calculating zero crossings', - 'value': 0.2}, + 'value': 0.2, + 'namestring': 'Zero crossings window'}, 'timeerrorsP': {'type': (float, float, float, float), 'tooltip': 'discrete time errors [s] corresponding to picking weights [0 1 2 3] for P', - 'value': (0.01, 0.02, 0.04, 0.08)}, + 'value': (0.01, 0.02, 0.04, 0.08), + 'namestring': ('Time errors P', '0', '1', '2', '3')}, 'timeerrorsS': {'type': (float, float, float, float), 'tooltip': 'discrete time errors [s] corresponding to picking weights [0 1 2 3] for S', - 'value': (0.04, 0.08, 0.16, 0.32)}, + 'value': (0.04, 0.08, 0.16, 0.32), + 'namestring': ('Time errors S', '0', '1', '2', '3')}, 'minAICPslope': {'type': float, 'tooltip': 'below this slope [counts/s] the initial P pick is rejected', - 'value': 0.8}, + 'value': 0.8, + 'namestring': 'Min. slope P'}, 'minAICPSNR': {'type': float, 'tooltip': 'below this SNR the initial P pick is rejected', - 'value': 1.1}, + 'value': 1.1, + 'namestring': 'Min. SNR P'}, 'minAICSslope': {'type': float, 'tooltip': 'below this slope [counts/s] the initial S pick is rejected', - 'value': 1.}, + 'value': 1., + 'namestring': 'Min. slope S'}, 'minAICSSNR': {'type': float, 'tooltip': 'below this SNR the initial S pick is rejected', - 'value': 1.5}, + 'value': 1.5, + 'namestring': 'Min. SNR S'}, 'minsiglength': {'type': float, 'tooltip': 'length of signal part for which amplitudes must exceed noiselevel [s]', - 'value': 1.}, + 'value': 1., + 'namestring': 'Min. signal length'}, 'noisefactor': {'type': float, 'tooltip': 'noiselevel*noisefactor=threshold', - 'value': 1.0}, + 'value': 1.0, + 'namestring': 'Noise factor'}, 'minpercent': {'type': float, 'tooltip': 'required percentage of amplitudes exceeding threshold', - 'value': 10.}, + 'value': 10., + 'namestring': 'Min amplitude [%]'}, 'zfac': {'type': float, 'tooltip': 'P-amplitude must exceed at least zfac times RMS-S amplitude', - 'value': 1.5}, + 'value': 1.5, + 'namestring': 'Z factor'}, 'mdttolerance': {'type': float, 'tooltip': 'maximum allowed deviation of P picks from median [s]', - 'value': 6.0}, + 'value': 6.0, + 'namestring': 'Median tolerance'}, 'wdttolerance': {'type': float, 'tooltip': 'maximum allowed deviation from Wadati-diagram', - 'value': 1.0}, + 'value': 1.0, + 'namestring': 'Wadati tolerance'}, 'WAscaling': {'type': (float, float, float), '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.)}, + 'value': (0., 0., 0.), + 'namestring': ('Wood-Anderson scaling', '', '', '')}, 'magscaling': {'type': (float, float), 'tooltip': 'Scaling relation for derived local magnitude [a*Ml+b]. \ If zeros are set, no scaling of network magnitude is applied!', - 'value': (0., 0.)}, + 'value': (0., 0.), + 'namestring': ('Local mag. scaling', '', '')}, - 'minfreq': {'type': float, - 'tooltip': 'Lower filter frequency', - 'value': 1.0}, + 'minfreq': {'type': (float, float), + 'tooltip': 'Lower filter frequency [P, S]', + 'value': (1.0, 1.0), + 'namestring': ('Lower freq.', 'P', 'S')}, - 'maxfreq': {'type': float, - 'tooltip': 'Upper filter frequency', - 'value': 10.0}, + 'maxfreq': {'type': (float, float), + 'tooltip': 'Upper filter frequency [P, S]', + 'value': (10.0, 10.0), + 'namestring': ('Upper freq.', '', '')}, - 'filter_order': {'type': int, - 'tooltip': 'filter order', - 'value': 2}, + 'filter_order': {'type': (int, int), + 'tooltip': 'filter order [P, S]', + 'value': (2, 2), + 'namestring': ('Order', '', '')}, - 'filter_type': {'type': str, - 'tooltip': 'filter type (bandpass, bandstop, lowpass, highpass)', - 'value': None} + 'filter_type': {'type': (str, str), + 'tooltip': 'filter type (bandpass, bandstop, lowpass, highpass) [P, S]', + 'value': ('bandpass' , 'bandpass'), + 'namestring': ('Type', '', '')} } settings_main={ diff --git a/pylot/core/io/inputs.py b/pylot/core/io/inputs.py index aad56f78..95317e05 100644 --- a/pylot/core/io/inputs.py +++ b/pylot/core/io/inputs.py @@ -209,7 +209,10 @@ class PylotParameter(object): vallist = value.strip().split(' ') val = [] for val0 in vallist: - val0 = float(val0) + try: + val0 = float(val0) + except: + pass val.append(val0) else: val = str(value.strip()) diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 00950147..6d1d4806 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2082,7 +2082,7 @@ class TuneAutopicker(QWidget): class PylotParaBox(QtGui.QWidget): def __init__(self, parameter, parent=None): ''' - Generate Widget containing parameters for automatic picking algorithm. + Generate Widget containing parameters for PyLoT. :param: parameter :type: PylotParameter (object) @@ -2183,8 +2183,6 @@ class PylotParaBox(QtGui.QWidget): grid = QtGui.QGridLayout() for index1, name in enumerate(parameter_names): - text = name + ' [?]' - label = QtGui.QLabel(text) default_item = self.parameter.get_defaults()[name] tooltip = default_item['tooltip'] tooltip += ' | type: {}'.format(default_item['type']) @@ -2192,14 +2190,19 @@ class PylotParaBox(QtGui.QWidget): typ = default_item['type'] box = self.create_box(typ, tooltip) self.boxes[name] = box + namestring = default_item['namestring'] elif type(default_item['type']) == tuple: boxes = [] values = self.parameter[name] for index2, val in enumerate(values): typ = default_item['type'][index2] boxes.append(self.create_box(typ, tooltip)) - box = self.create_multi_box(boxes) + headline = default_item['namestring'][1:] + box, lower = self.create_multi_box(boxes, headline) self.boxes[name] = boxes + namestring = default_item['namestring'][0] + text = namestring + ' [?]' + label = QtGui.QLabel(text) self.labels[name] = label label.setToolTip(tooltip) grid.addWidget(label, index1, 1) @@ -2211,8 +2214,8 @@ class PylotParaBox(QtGui.QWidget): box = QtGui.QLineEdit() elif typ == float: box = QtGui.QDoubleSpinBox() - box.setDecimals(5) - box.setRange(-10e5, 10e5) + box.setDecimals(4) + box.setRange(-10e4, 10e4) elif typ == int: box = QtGui.QSpinBox() elif typ == bool: @@ -2221,13 +2224,20 @@ class PylotParaBox(QtGui.QWidget): raise TypeError('Unrecognized type {}'.format(typ)) return box - def create_multi_box(self, boxes): + def create_multi_box(self, boxes, headline=None): box = QtGui.QWidget() - hl = QtGui.QVBoxLayout() - for b in boxes: - hl.addWidget(b) - box.setLayout(hl) - return box + gl = QtGui.QGridLayout() + row = 0 + if headline: + for index, item in enumerate(headline): + if not item: + continue + gl.addWidget(QtGui.QLabel(item), 0, index, 4) + row = 1 + for index, b in enumerate(boxes): + gl.addWidget(b, row, index) + box.setLayout(gl) + return box, row def add_tab(self, layout, name): widget = QtGui.QWidget() @@ -2467,7 +2477,7 @@ class PylotParaBox(QtGui.QWidget): self._exclusive_dialog.close() self._exclusive_widgets = [] QtGui.QWidget.show(self) - + def _warn(self, message): self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning, 'Warning', message) From dbc38385b53acb0a95b8e3f82d574641344fc08d Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Tue, 4 Jul 2017 16:37:05 +0200 Subject: [PATCH 05/10] [add] semi working version of filterOption dialog, WIP --- QtPyLoT.py | 67 +++++++++++++++++++++----------------- pylot/core/util/widgets.py | 65 ++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 44 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 576a4f77..566dda13 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -180,7 +180,8 @@ class MainWindow(QMainWindow): # setup UI self.setupUi() - self.filteroptions = {} + self.filteroptions = {'P': FilterOptions(), + 'S': FilterOptions()} self.pylot_picks = {} self.pylot_autopicks = {} self.loc = False @@ -1541,7 +1542,7 @@ class MainWindow(QMainWindow): self.draw() def adjustFilterOptions(self): - fstring = "Filter Options ({0})".format(self.getSeismicPhase()) + fstring = "Filter Options" filterDlg = FilterOptionsDialog(titleString=fstring, parent=self) if filterDlg.exec_(): @@ -1553,33 +1554,46 @@ class MainWindow(QMainWindow): self.plotWaveformDataThread() def getFilterOptions(self): - try: - return self.project.filteroptions[self.getSeismicPhase()] - except AttributeError as e: - print(e) - return FilterOptions(None, None, None) + return self.filteroptions + # try: + # return self.filteroptions[self.getSeismicPhase()] + # except AttributeError as e: + # print(e) + # return FilterOptions(None, None, None) def getFilters(self): return self.filteroptions - def setFilterOptions(self, filterOptions, seismicPhase=None): - if not self.project: - return - if seismicPhase is None: - self.project.filteroptions[self.getSeismicPhase()] = filterOptions - else: - self.project.filteroptions[seismicPhase] = filterOptions - self._inputs.setParamKV('minfreq', float(filterOptions.getFreq()[0])) - self._inputs.setParamKV('maxfreq', float(filterOptions.getFreq()[1])) - self._inputs.setParamKV('filter_order', int(filterOptions.getOrder())) - self._inputs.setParamKV('filter_type', str(filterOptions.getFilterType())) + def setFilterOptions(self, filterOptions):#, seismicPhase=None): + # if seismicPhase is None: + # self.getFilterOptions()[self.getSeismicPhase()] = filterOptions + # else: + # self.getFilterOptions()[seismicPhase] = filterOptions + self.filterOptions = filterOptions + filterP = filterOptions['P'] + filterS = filterOptions['S'] + minP, maxP = filterP.getFreq() + minS, maxS = filterS.getFreq() + self._inputs.setParamKV('minfreq', (minP, minS)) + self._inputs.setParamKV('maxfreq', (maxP, maxS)) + self._inputs.setParamKV('filter_order', (filterP.getOrder(), filterS.getOrder())) + self._inputs.setParamKV('filter_type', (filterP.getFilterType(), filterS.getFilterType())) def filterOptionsFromParameter(self): - if not self.project: - return - self.project.filteroptions.setFreq([self._inputs['minfreq'], self._inputs['axfreq']]) - self.project.filteroptions.setOrder(self._inputs['filter_order']) - self.project.filteroptions.setFilterType(self._inputs['filter_type']) + minP, minS = self._inputs['minfreq'] + maxP, maxS = self._inputs['maxfreq'] + orderP, orderS = self._inputs['filter_order'] + typeP, typeS = self._inputs['filter_type'] + + filterP = self.getFilterOptions()['P'] + filterP.setFreq([minP, maxP]) + filterP.setOrder(orderP) + filterP.setFilterType(typeP) + + filterS = self.getFilterOptions()['S'] + filterS.setFreq([minS, maxS]) + filterS.setOrder(orderS) + filterS.setFilterType(typeS) def updateFilterOptions(self): try: @@ -2405,9 +2419,6 @@ class MainWindow(QMainWindow): if hasattr(self.project, 'parameter'): if self.project.parameter: self._inputs = self.project.parameter - if not hasattr(self.project, 'filteroptions'): - self.project.filteroptions = {'P': FilterOptions(), - 'S': FilterOptions()} self.tabs.setCurrentIndex(0) # implemented to prevent double-loading of waveform data self.init_events(new=True) self.setDirty(False) @@ -2517,10 +2528,6 @@ class Project(object): self.eventlist = [] self.location = None self.rootpath = None - self.filteroptions = { - 'P': FilterOptions(), - 'S': FilterOptions() - } self.dirty = False self.parameter = None self._table = None diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 6d1d4806..0be38ce2 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -3013,13 +3013,60 @@ class FilterOptionsDialog(QDialog): adjust parameters for filtering seismic data. """ super(FilterOptionsDialog, self).__init__() - if parent is not None and parent.getFilters(): - self.filterOptions = parent.getFilterOptions() + self.filterOptions = parent.getFilters() elif filterOptions is not None: - self.filterOptions = FilterOptions(filterOptions) + self.filterOptions = filterOptions else: - self.filterOptions = FilterOptions() + self.filterOptions = {'P': FilterOptions(), + 'S': FilterOptions()} + + self.setWindowTitle(titleString) + self.filterOptionWidgets = {'P': FilterOptionsWidget(self.filterOptions['P']), + 'S': FilterOptionsWidget(self.filterOptions['S'])} + self.setupUI() + self.connectButtons() + + def setupUI(self): + self.main_layout = QtGui.QVBoxLayout() + self.filter_layout = QtGui.QHBoxLayout() + self.groupBoxes = {'P': QtGui.QGroupBox('P Filter'), + 'S': QtGui.QGroupBox('S Filter')} + + self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | + QDialogButtonBox.Cancel) + + for key in ['P', 'S']: + groupbox = self.groupBoxes[key] + box_layout = QtGui.QVBoxLayout() + groupbox.setLayout(box_layout) + + self.filter_layout.addWidget(groupbox) + box_layout.addWidget(self.filterOptionWidgets[key]) + + self.main_layout.addLayout(self.filter_layout) + self.main_layout.addWidget(self.buttonBox) + self.setLayout(self.main_layout) + + def connectButtons(self): + self.buttonBox.accepted.connect(self.accept) + self.buttonBox.rejected.connect(self.reject) + + def accept(self): + for foWidget in self.filterOptionWidgets.values(): + foWidget.updateUi() + QDialog.accept(self) + + def getFilterOptions(self): + filteroptions = {'P': self.filterOptionWidgets['P'].getFilterOptions(), + 'S': self.filterOptionWidgets['S'].getFilterOptions()} + return filteroptions + + +class FilterOptionsWidget(QWidget): + def __init__(self, filterOptions): + super(FilterOptionsWidget, self).__init__() + self.filterOptions = filterOptions _enable = True if self.getFilterOptions().getFilterType() is None: @@ -3083,13 +3130,9 @@ class FilterOptionsDialog(QDialog): self.freqmaxSpinBox.setEnabled(_enable) - self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | - QDialogButtonBox.Cancel) - grid = QGridLayout() grid.addWidget(self.freqGroupBox, 0, 2, 1, 2) grid.addLayout(self.selectTypeLayout, 1, 2, 1, 2) - grid.addWidget(self.buttonBox, 2, 2, 1, 2) self.setLayout(grid) @@ -3097,8 +3140,6 @@ class FilterOptionsDialog(QDialog): self.freqmaxSpinBox.valueChanged.connect(self.updateUi) self.orderSpinBox.valueChanged.connect(self.updateUi) self.selectTypeCombo.currentIndexChanged.connect(self.updateUi) - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) def updateUi(self): type = self.selectTypeCombo.currentText() @@ -3136,10 +3177,6 @@ class FilterOptionsDialog(QDialog): return dlg.getFilterOptions() return None - def accept(self): - self.updateUi() - QDialog.accept(self) - class LoadDataDlg(QDialog): def __init__(self, parent=None): From f7e54275c363f5380b78e11b53f20f8f11d04da9 Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Thu, 6 Jul 2017 17:22:23 +0200 Subject: [PATCH 06/10] [change] structural changes to filteroptions WIP --- QtPyLoT.py | 3 +- pylot/core/io/inputs.py | 9 ++--- pylot/core/util/widgets.py | 69 ++++++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 566dda13..e14333fa 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1531,7 +1531,7 @@ class MainWindow(QMainWindow): def filterWaveformData(self): if self.get_data(): if self.getFilterOptions() and self.filterAction.isChecked(): - kwargs = self.getFilterOptions().parseFilterOptions() + kwargs = self.getFilterOptions()['P'].parseFilterOptions() self.pushFilterWF(kwargs) elif self.filterAction.isChecked(): self.adjustFilterOptions() @@ -2501,6 +2501,7 @@ class MainWindow(QMainWindow): self.paraBox._apply.clicked.connect(self.filterOptionsFromParameter) self.paraBox._okay.clicked.connect(self.filterOptionsFromParameter) if show: + self.paraBox.params_to_gui() self.paraBox.show() def PyLoTprefs(self): diff --git a/pylot/core/io/inputs.py b/pylot/core/io/inputs.py index 95317e05..56e26e99 100644 --- a/pylot/core/io/inputs.py +++ b/pylot/core/io/inputs.py @@ -341,12 +341,13 @@ class FilterOptions(object): def parseFilterOptions(self): if self: robject = {'type': self.getFilterType(), 'corners': self.getOrder()} - if len(self.getFreq()) > 1: + if not self.getFilterType() in ['highpass', 'lowpass']: robject['freqmin'] = self.getFreq()[0] robject['freqmax'] = self.getFreq()[1] - else: - robject['freq'] = self.getFreq() if type(self.getFreq()) is \ - float else self.getFreq()[0] + elif self.getFilterType() == 'highpass': + robject['freq'] = self.getFreq()[0] + elif self.getFilterType() == 'lowpass': + robject['freq'] = self.getFreq()[1] return robject return None diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 0be38ce2..00f595d4 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -3015,8 +3015,8 @@ class FilterOptionsDialog(QDialog): super(FilterOptionsDialog, self).__init__() if parent is not None and parent.getFilters(): self.filterOptions = parent.getFilters() - elif filterOptions is not None: - self.filterOptions = filterOptions + # elif filterOptions is not None: + # self.filterOptions = filterOptions else: self.filterOptions = {'P': FilterOptions(), 'S': FilterOptions()} @@ -3024,10 +3024,11 @@ class FilterOptionsDialog(QDialog): self.setWindowTitle(titleString) self.filterOptionWidgets = {'P': FilterOptionsWidget(self.filterOptions['P']), 'S': FilterOptionsWidget(self.filterOptions['S'])} - self.setupUI() + self.setupUi() + self.updateUi() self.connectButtons() - def setupUI(self): + def setupUi(self): self.main_layout = QtGui.QVBoxLayout() self.filter_layout = QtGui.QHBoxLayout() self.groupBoxes = {'P': QtGui.QGroupBox('P Filter'), @@ -3053,10 +3054,13 @@ class FilterOptionsDialog(QDialog): self.buttonBox.rejected.connect(self.reject) def accept(self): - for foWidget in self.filterOptionWidgets.values(): - foWidget.updateUi() + self.updateUi() QDialog.accept(self) + def updateUi(self): + for foWidget in self.filterOptionWidgets.values(): + foWidget.updateUi() + def getFilterOptions(self): filteroptions = {'P': self.filterOptionWidgets['P'].getFilterOptions(), 'S': self.filterOptionWidgets['S'].getFilterOptions()} @@ -3087,20 +3091,20 @@ class FilterOptionsWidget(QWidget): self.freqmaxSpinBox.setDecimals(2) self.freqmaxSpinBox.setSuffix(' Hz') - if _enable: + # if _enable: + # self.freqminSpinBox.setValue(self.getFilterOptions().getFreq()[0]) + # if self.getFilterOptions().getFilterType() in ['bandpass', + # 'bandstop']: + # self.freqmaxSpinBox.setValue( + # self.getFilterOptions().getFreq()[1]) + # else: + try: self.freqminSpinBox.setValue(self.getFilterOptions().getFreq()[0]) - if self.getFilterOptions().getFilterType() in ['bandpass', - 'bandstop']: - self.freqmaxSpinBox.setValue( - self.getFilterOptions().getFreq()[1]) - else: - try: - self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq()) - self.freqminSpinBox.setValue(self.getFilterOptions().getFreq()) - except TypeError as e: - print(e) - self.freqmaxSpinBox.setValue(1.) - self.freqminSpinBox.setValue(.1) + self.freqmaxSpinBox.setValue(self.getFilterOptions().getFreq()[1]) + except TypeError as e: + print(e) + self.freqmaxSpinBox.setValue(1.) + self.freqminSpinBox.setValue(.1) typeOptions = [None, "bandpass", "bandstop", "lowpass", "highpass"] @@ -3130,6 +3134,11 @@ class FilterOptionsWidget(QWidget): self.freqmaxSpinBox.setEnabled(_enable) + try: + self.orderSpinBox.setValue(self.getFilterOptions().getOrder()) + except: + self.orderSpinBox.setValue(2) + grid = QGridLayout() grid.addWidget(self.freqGroupBox, 0, 2, 1, 2) grid.addLayout(self.selectTypeLayout, 1, 2, 1, 2) @@ -3145,15 +3154,23 @@ class FilterOptionsWidget(QWidget): type = self.selectTypeCombo.currentText() _enable = type in ['bandpass', 'bandstop'] freq = [self.freqminSpinBox.value(), self.freqmaxSpinBox.value()] - self.freqmaxLabel.setEnabled(_enable) - self.freqmaxSpinBox.setEnabled(_enable) - + self.freqmaxLabel.setEnabled(True) + self.freqmaxSpinBox.setEnabled(True) + self.freqminLabel.setEnabled(True) + self.freqminSpinBox.setEnabled(True) + self.freqminLabel.setText("minimum:") + self.freqmaxLabel.setText("maximum:") + if not _enable: - self.freqminLabel.setText("cutoff:") - self.freqmaxSpinBox.setValue(freq[0]) - freq.remove(freq[1]) + if type == 'highpass': + self.freqminLabel.setText("cutoff:") + self.freqmaxLabel.setEnabled(False) + self.freqmaxSpinBox.setEnabled(False) + elif type == 'lowpass': + self.freqmaxLabel.setText("cutoff:") + self.freqminLabel.setEnabled(False) + self.freqminSpinBox.setEnabled(False) else: - self.freqminLabel.setText("minimum:") if not isSorted(freq): QMessageBox.warning(self, "Value error", "Maximum frequency must be at least the " From 0e566f9748326d31a9b3b9c5f3455c4bbc19587e Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Mon, 10 Jul 2017 15:49:15 +0200 Subject: [PATCH 07/10] [add] latest pylot.in file added to inputs! --- inputs/pylot.in | 173 ++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/inputs/pylot.in b/inputs/pylot.in index 611277b2..3858cb4f 100644 --- a/inputs/pylot.in +++ b/inputs/pylot.in @@ -1,98 +1,97 @@ -%This is a example parameter input file for PyLoT. +%This is a parameter input file for PyLoT/autoPyLoT. %All main and special settings regarding data handling %and picking are to be set here! -%Parameters shown here are optimized for local data sets! +%Parameters are optimized for %extent data sets! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #main settings# -/data/Geothermie/Insheim #rootpath# %project path -EVENT_DATA/LOCAL #datapath# %data path -2013.02_Insheim #database# %name of data base -e0019.048.13 #eventID# %event ID for single event processing -/data/Geothermie/Insheim/STAT_INFO #invdir# %full path to inventory or dataless-seed file -PILOT #datastructure# %choose data structure -0 #iplot# %flag for plotting: 0 none, 1 partly, >1 everything -True #apverbose# %choose 'True' or 'False' for terminal output -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#NLLoc settings# -/progs/bin #nllocbin# %path to NLLoc executable -/data/Geothermie/Insheim/LOCALISATION/NLLoc #nllocroot# %root of NLLoc-processing directory -AUTOPHASES.obs #phasefile# %name of autoPyLoT-output phase file for NLLoc - %(in nllocroot/obs) -Insheim_min1d2015.in #ctrfile# %name of PyLoT-output control file for NLLoc - %(in nllocroot/run) -ttime #ttpatter# %pattern of NLLoc ttimes from grid - %(in nllocroot/times) -AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file - %(returns 'eventID_outpatter') -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#parameters for seismic moment estimation# -3530 #vp# %average P-wave velocity -2500 #rho# %average rock density [kg/m^3] -300 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a) + #rootpath# %project path + #datapath# %data path + #database# %name of data base +e0010.065.17 #eventID# %event ID for single event processing (* for all events found in database) + #invdir# %full path to inventory or dataless-seed file +PILOT #datastructure# %choose data structure +True #apverbose# %choose 'True' or 'False' for terminal output %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -AUTOFOCMEC_AIC_HOS4_ARH.in #focmecin# %name of focmec input file containing derived polarities +#NLLoc settings# + #nllocbin# %path to NLLoc executable + #nllocroot# %root of NLLoc-processing directory +AUTOPHASES.obs #phasefile# %name of autoPyLoT-output phase file for NLLoc +Insheim_min1d2015_auto.in #ctrfile# %name of autoPyLoT-output control file for NLLoc +ttime #ttpatter# %pattern of NLLoc ttimes from grid +AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#parameters for seismic moment estimation# +3530.0 #vp# %average P-wave velocity +2500.0 #rho# %average rock density [kg/m^3] +300.0 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#settings local magnitude# +0.0 0.0 0.0 #WAscaling# %Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] If zeros are set, original Richter magnitude is calculated! +0.0 0.0 #magscaling# %Scaling relation for derived local magnitude [a*Ml+b]. If zeros are set, no scaling of network magnitude is applied! +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#filter settings# +1.0 1.0 #minfreq# %Lower filter frequency [P, S] +10.0 10.0 #maxfreq# %Upper filter frequency [P, S] +2 2 #filter_order# %filter order [P, S] +bandpass bandpass #filter_type# %filter type (bandpass, bandstop, lowpass, highpass) [P, S] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #common settings picker# -15.0 #pstart# %start time [s] for calculating CF for P-picking -60.0 #pstop# %end time [s] for calculating CF for P-picking --1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking -10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking -2 20 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz] -2 30 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz] -2 15 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz] -2 20 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz] +local #extent# %extent of array ("local", "regional" or "global") +15.0 #pstart# %start time [s] for calculating CF for P-picking +60.0 #pstop# %end time [s] for calculating CF for P-picking +-1.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking +10.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking +2.0 20.0 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz] +2.0 30.0 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz] +2.0 15.0 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz] +2.0 20.0 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz] #special settings for calculating CF# %!!Edit the following only if you know what you are doing!!% #Z-component# -HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3) -7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s] -4 #hosorder# %for HOS-picker, order of Higher Order Statistics -2 #Parorder# %for AR-picker, order of AR process of Z-component -1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick -0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick -0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick -0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick -0.001 #addnoise# %add noise to seismogram for stable AR prediction -3 0.1 0.5 0.5 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s] -3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s] -6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick) -0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s] -0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s] -0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P) -1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P) +HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3) +7.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s] +4 #hosorder# %for HOS-picker, order of Higher Order Statistics +2 #Parorder# %for AR-picker, order of AR process of Z-component +1.2 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick +0.4 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick +0.6 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick +0.2 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick +0.001 #addnoise# %add noise to seismogram for stable AR prediction +3.0 0.1 0.5 1.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s] +3.0 #pickwinP# %for initial AIC pick, length of P-pick window [s] +6.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick) +0.2 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s] +0.1 #tsmoothP# %for HOS/AR, take average of samples for smoothing CF [s] +0.001 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P) +1.3 #nfacP# %for HOS/AR, noise factor for noise level determination (P) #H-components# -ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3) -0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick -0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick -0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick -0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick -4 #Sarorder# %for AR-picker, order of AR process of H-components -5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H) -3.0 #pickwinS# %for initial AIC pick, length of S-pick window [s] -2 0.2 1.5 0.5 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise,tsafetey,tsignal,tslope] [s] -0.5 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s] -0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S) -0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S) -1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S) -%first-motion picker% -1 #minfmweight# %minimum required P weight for first-motion determination -2 #minFMSNR# %miniumum required SNR for first-motion determination -0.2 #fmpickwin# %pick window around P onset for calculating zero crossings -%quality assessment% -#inital AIC onset# -0.01 0.02 0.04 0.08 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P -0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S -4 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected -1.2 #minAICPSNR# %below this SNR the initial P pick is rejected -2 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected -1.5 #minAICSSNR# %below this SNR the initial S pick is rejected -#check duration of signal using envelope function# -3 #minsiglength# %minimum required length of signal [s] -1.0 #noisefactor# %noiselevel*noisefactor=threshold -40 #minpercent# %required percentage of samples higher than threshold -#check for spuriously picked S-onsets# -2.0 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude -#check statistics of P onsets# -2.5 #mdttolerance# %maximum allowed deviation of P picks from median [s] -#wadati check# -1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram +ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3) +0.8 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick +0.4 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick +0.6 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick +0.3 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick +4 #Sarorder# %for AR-picker, order of AR process of H-components +5.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H) +3.0 #pickwinS# %for initial AIC pick, length of S-pick window [s] +2.0 0.2 1.5 0.5 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s] +0.5 #aictsmoothS# %for AIC-picker, take average of samples for smoothing of AIC-function [s] +0.7 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S) +0.9 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S) +1.5 #nfacS# %for AR-picker, noise factor for noise level determination (S) +#first-motion picker# +1 #minfmweight# %minimum required P weight for first-motion determination +2.0 #minFMSNR# %miniumum required SNR for first-motion determination +0.2 #fmpickwin# %pick window around P onset for calculating zero crossings +#quality assessment# +0.01 0.02 0.04 0.08 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P +0.04 0.08 0.16 0.32 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S +0.8 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected +1.1 #minAICPSNR# %below this SNR the initial P pick is rejected +1.0 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected +1.5 #minAICSSNR# %below this SNR the initial S pick is rejected +1.0 #minsiglength# %length of signal part for which amplitudes must exceed noiselevel [s] +1.0 #noisefactor# %noiselevel*noisefactor=threshold +10.0 #minpercent# %required percentage of amplitudes exceeding threshold +1.5 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude +6.0 #mdttolerance# %maximum allowed deviation of P picks from median [s] +1.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram From 1d9e52f577716013802f1d04a9cb02672e321fd9 Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Tue, 11 Jul 2017 16:03:24 +0200 Subject: [PATCH 08/10] [change] several updates updates to filterOptions, FILTERDEFAULTS now loaded from pylot.in, filterOptions should be 'shared' between filterOptionsDialog and pylotParameter --- QtPyLoT.py | 39 ++++++++++++++++++++++---------- README.md | 4 ++-- makePyLoT.py | 3 +-- pylot/core/util/defaults.py | 45 ++++++++++++++----------------------- pylot/core/util/widgets.py | 32 ++++++++++++++++++-------- 5 files changed, 70 insertions(+), 53 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index e14333fa..a502ddd3 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -65,7 +65,8 @@ from pylot.core.pick.compare import Comparison from pylot.core.pick.utils import symmetrize_error from pylot.core.io.phases import picksdict_from_picks import pylot.core.loc.nll as nll -from pylot.core.util.defaults import FILTERDEFAULTS, OUTPUTFORMATS, SetChannelComponents +from pylot.core.util.defaults import FILTERDEFAULTS, OUTPUTFORMATS, SetChannelComponents, \ + readFilterInformation from pylot.core.util.errors import FormatError, DatastructureError, \ OverwriteError, ProcessingError from pylot.core.util.connection import checkurl @@ -180,8 +181,15 @@ class MainWindow(QMainWindow): # setup UI self.setupUi() - self.filteroptions = {'P': FilterOptions(), - 'S': FilterOptions()} + filter_info = readFilterInformation(self._inputs) + p_filter = filter_info['P'] + s_filter = filter_info['S'] + self.filteroptions = {'P': FilterOptions(p_filter['filtertype'], + p_filter['freq'], + p_filter['order']), + 'S': FilterOptions(s_filter['filtertype'], + s_filter['freq'], + s_filter['order'])} self.pylot_picks = {} self.pylot_autopicks = {} self.loc = False @@ -1543,16 +1551,23 @@ class MainWindow(QMainWindow): def adjustFilterOptions(self): fstring = "Filter Options" - filterDlg = FilterOptionsDialog(titleString=fstring, - parent=self) - if filterDlg.exec_(): - filteroptions = filterDlg.getFilterOptions() + self.filterDlg = FilterOptionsDialog(titleString=fstring, + parent=self) + if self.filterDlg.exec_(): + filteroptions = self.filterDlg.getFilterOptions() self.setFilterOptions(filteroptions) if self.filterAction.isChecked(): kwargs = self.getFilterOptions().parseFilterOptions() self.pushFilterWF(kwargs) self.plotWaveformDataThread() + def checkFilterOptions(self): + fstring = "Filter Options" + self.filterDlg = FilterOptionsDialog(titleString=fstring, + parent=self) + filteroptions = self.filterDlg.getFilterOptions() + self.setFilterOptions(filteroptions) + def getFilterOptions(self): return self.filteroptions # try: @@ -1584,7 +1599,7 @@ class MainWindow(QMainWindow): maxP, maxS = self._inputs['maxfreq'] orderP, orderS = self._inputs['filter_order'] typeP, typeS = self._inputs['filter_type'] - + filterP = self.getFilterOptions()['P'] filterP.setFreq([minP, maxP]) filterP.setOrder(orderP) @@ -1595,6 +1610,8 @@ class MainWindow(QMainWindow): filterS.setOrder(orderS) filterS.setFilterType(typeS) + self.checkFilterOptions() + def updateFilterOptions(self): try: settings = QSettings() @@ -2496,10 +2513,8 @@ class MainWindow(QMainWindow): def setParameter(self, show=True): if not self.paraBox: self.paraBox = PylotParaBox(self._inputs) - self.paraBox._apply.clicked.connect(self._setDirty) - self.paraBox._okay.clicked.connect(self._setDirty) - self.paraBox._apply.clicked.connect(self.filterOptionsFromParameter) - self.paraBox._okay.clicked.connect(self.filterOptionsFromParameter) + self.paraBox.accepted.connect(self._setDirty) + self.paraBox.accepted.connect(self.filterOptionsFromParameter) if show: self.paraBox.params_to_gui() self.paraBox.show() diff --git a/README.md b/README.md index 4c3cbe3e..b954d9b1 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ for regional distance seismicity cp path-to-pylot/inputs/autoPyLoT_regional.in ~/.pylot/autoPyLoT.in -and some extra information on filtering, error estimates (just needed for reading old PILOT data) and the Richter magnitude scaling relation +and some extra information on error estimates (just needed for reading old PILOT data) and the Richter magnitude scaling relation - cp path-to-pylot/inputs/filter.in path-to-pylot/inputs/PILOT_TimeErrors.in path-to-pylot/inputs/richter_scaling.data ~/.pylot/ + cp path-to-pylot/inputs/PILOT_TimeErrors.in path-to-pylot/inputs/richter_scaling.data ~/.pylot/ You may need to do some modifications to these files. Especially folder names should be reviewed. diff --git a/makePyLoT.py b/makePyLoT.py index 1e87f1fb..6796ee1d 100644 --- a/makePyLoT.py +++ b/makePyLoT.py @@ -159,8 +159,7 @@ def buildPyLoT(verbosity=None): def installPyLoT(verbosity=None): files_to_copy = {'autoPyLoT_local.in':['~', '.pylot'], - 'autoPyLoT_regional.in':['~', '.pylot'], - 'filter.in':['~', '.pylot']} + 'autoPyLoT_regional.in':['~', '.pylot']} if verbosity > 0: print ('starting installation of PyLoT ...') if verbosity > 1: diff --git a/pylot/core/util/defaults.py b/pylot/core/util/defaults.py index 68974f65..1b1532b4 100644 --- a/pylot/core/util/defaults.py +++ b/pylot/core/util/defaults.py @@ -12,38 +12,27 @@ from pylot.core.loc import hyposat from pylot.core.loc import hypo71 from pylot.core.loc import hypodd from pylot.core.loc import velest +from pylot.core.io.inputs import PylotParameter - -def readFilterInformation(fname): - def convert2FreqRange(*args): - if len(args) > 1: - return [float(arg) for arg in args] - elif len(args) == 1: - return float(args[0]) - return None - - filter_file = open(fname, 'r') - filter_information = dict() - for filter_line in filter_file.readlines(): - filter_line = filter_line.split(' ') - for n, pos in enumerate(filter_line): - if pos == '\n': - filter_line[n] = '' - filter_information[filter_line[0]] = {'filtertype': filter_line[1] - if filter_line[1] - else None, - 'order': int(filter_line[2]) - if filter_line[1] - else None, - 'freq': convert2FreqRange(*filter_line[3:]) - if filter_line[1] - else None} +def readDefaultFilterInformation(fname): + pparam = PylotParameter(fname) + return readFilterInformation(pparam) + +def readFilterInformation(pylot_parameter): + p_filter = {'filtertype': pylot_parameter['filter_type'][0], + 'freq': [pylot_parameter['minfreq'][0], pylot_parameter['maxfreq'][0]], + 'order': int(pylot_parameter['filter_order'][0])} + s_filter = {'filtertype': pylot_parameter['filter_type'][1], + 'freq': [pylot_parameter['minfreq'][1], pylot_parameter['maxfreq'][1]], + 'order': int(pylot_parameter['filter_order'][1])} + filter_information = {'P': p_filter, + 'S': s_filter} return filter_information -FILTERDEFAULTS = readFilterInformation(os.path.join(os.path.expanduser('~'), - '.pylot', - 'filter.in')) +FILTERDEFAULTS = readDefaultFilterInformation(os.path.join(os.path.expanduser('~'), + '.pylot', + 'pylot.in')) TIMEERROR_DEFAULTS = os.path.join(os.path.expanduser('~'), '.pylot', diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 00f595d4..497d5324 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -2048,7 +2048,7 @@ class TuneAutopicker(QWidget): return parameters def set_stretch(self): - self.tune_layout.setStretch(0, 3) + self.tune_layout.setStretch(0, 2) self.tune_layout.setStretch(1, 1) def clear_all(self): @@ -2079,7 +2079,9 @@ class TuneAutopicker(QWidget): self.qmb.show() -class PylotParaBox(QtGui.QWidget): +class PylotParaBox(QtGui.QWidget): + accepted = QtCore.Signal(str) + rejected = QtCore.Signal(str) def __init__(self, parameter, parent=None): ''' Generate Widget containing parameters for PyLoT. @@ -2106,7 +2108,9 @@ class PylotParaBox(QtGui.QWidget): self.params_to_gui() self._toggle_advanced_settings() self.resize(720, 1280) - self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) + self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) + self.accepted.connect(self.params_from_gui) + self.rejected.connect(self.params_to_gui) def _init_sublayouts(self): self._main_layout = QtGui.QVBoxLayout() @@ -2137,10 +2141,9 @@ class PylotParaBox(QtGui.QWidget): self._dialog_buttons.addWidget(self._okay) self._dialog_buttons.addWidget(self._close) self._dialog_buttons.addWidget(self._apply) - self._okay.clicked.connect(self.params_from_gui) + self._okay.clicked.connect(self.accept) self._okay.clicked.connect(self.close) - self._apply.clicked.connect(self.params_from_gui) - self._close.clicked.connect(self.params_to_gui) + self._apply.clicked.connect(self.accept) self._close.clicked.connect(self.close) self.layout.addLayout(self._dialog_buttons) @@ -2478,6 +2481,13 @@ class PylotParaBox(QtGui.QWidget): self._exclusive_widgets = [] QtGui.QWidget.show(self) + def close(self): + self.rejected.emit('reject') + QtGui.QWidget.close(self) + + def accept(self): + self.accepted.emit('accept') + def _warn(self, message): self.qmb = QtGui.QMessageBox(QtGui.QMessageBox.Icon.Warning, 'Warning', message) @@ -3058,8 +3068,10 @@ class FilterOptionsDialog(QDialog): QDialog.accept(self) def updateUi(self): + returnvals = [] for foWidget in self.filterOptionWidgets.values(): - foWidget.updateUi() + returnvals.append(foWidget.updateUi()) + return returnvals def getFilterOptions(self): filteroptions = {'P': self.filterOptionWidgets['P'].getFilterOptions(), @@ -3174,15 +3186,17 @@ class FilterOptionsWidget(QWidget): if not isSorted(freq): QMessageBox.warning(self, "Value error", "Maximum frequency must be at least the " - "same value as minimum frequency (notch)!") + "same value as minimum frequency (notch)! " + "Adjusted maximum frequency automatically!") self.freqmaxSpinBox.setValue(freq[0]) self.freqmaxSpinBox.selectAll() self.freqmaxSpinBox.setFocus() - return + return False self.getFilterOptions().setFilterType(type) self.getFilterOptions().setFreq(freq) self.getFilterOptions().setOrder(self.orderSpinBox.value()) + return True def getFilterOptions(self): return self.filterOptions From 43116ec2c6ad7e948732d737559a62e058f0e7bc Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Tue, 11 Jul 2017 16:22:22 +0200 Subject: [PATCH 09/10] [add] filtering in pickDlg will not be done by default anymore, changes in pushing filter in main traces window, still WIP (not going back to original wf after first filtering?) --- QtPyLoT.py | 4 ++-- pylot/core/util/widgets.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index a502ddd3..1e77d91e 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1539,7 +1539,7 @@ class MainWindow(QMainWindow): def filterWaveformData(self): if self.get_data(): if self.getFilterOptions() and self.filterAction.isChecked(): - kwargs = self.getFilterOptions()['P'].parseFilterOptions() + kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions() self.pushFilterWF(kwargs) elif self.filterAction.isChecked(): self.adjustFilterOptions() @@ -1557,7 +1557,7 @@ class MainWindow(QMainWindow): filteroptions = self.filterDlg.getFilterOptions() self.setFilterOptions(filteroptions) if self.filterAction.isChecked(): - kwargs = self.getFilterOptions().parseFilterOptions() + kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions() self.pushFilterWF(kwargs) self.plotWaveformDataThread() diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 497d5324..8593c244 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -752,7 +752,10 @@ class PickDlg(QDialog): else: self.autopicks = {} self._init_autopicks = {} - self.filteroptions = FILTERDEFAULTS + if hasattr(self.parent(), 'filteroptions'): + self.filteroptions = self.parent().filteroptions + else: + self.filteroptions = FILTERDEFAULTS self.pick_block = False self.nextStation = QtGui.QCheckBox('Continue with next station.') @@ -1160,7 +1163,10 @@ class PickDlg(QDialog): def getFilterOptions(self, phase): options = self.filteroptions[phase[0]] - return FilterOptions(**options) + if type(options) == dict: + return FilterOptions(**options) + else: + return options def getXLims(self): return self.cur_xlim From 818fb7a296e0afc75a9c64392f0e72a2bcd2a97f Mon Sep 17 00:00:00 2001 From: Marcel Paffrath Date: Wed, 12 Jul 2017 16:24:23 +0200 Subject: [PATCH 10/10] [change] final adjustments made to filteroptionsdialog and parabox, ready for testing --- QtPyLoT.py | 7 ++++++- pylot/core/util/widgets.py | 22 +++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/QtPyLoT.py b/QtPyLoT.py index 1e77d91e..42f40d2d 100755 --- a/QtPyLoT.py +++ b/QtPyLoT.py @@ -1566,7 +1566,12 @@ class MainWindow(QMainWindow): self.filterDlg = FilterOptionsDialog(titleString=fstring, parent=self) filteroptions = self.filterDlg.getFilterOptions() - self.setFilterOptions(filteroptions) + self.setFilterOptions(filteroptions) + filterP = filteroptions['P'] + filterS = filteroptions['S'] + minP, maxP = filterP.getFreq() + minS, maxS = filterS.getFreq() + self.paraBox.params_to_gui() def getFilterOptions(self): return self.filteroptions diff --git a/pylot/core/util/widgets.py b/pylot/core/util/widgets.py index 8593c244..3c8cd1b5 100644 --- a/pylot/core/util/widgets.py +++ b/pylot/core/util/widgets.py @@ -3076,8 +3076,7 @@ class FilterOptionsDialog(QDialog): def updateUi(self): returnvals = [] for foWidget in self.filterOptionWidgets.values(): - returnvals.append(foWidget.updateUi()) - return returnvals + foWidget.updateUi() def getFilterOptions(self): filteroptions = {'P': self.filterOptionWidgets['P'].getFilterOptions(), @@ -3099,6 +3098,7 @@ class FilterOptionsWidget(QWidget): self.freqminSpinBox = QDoubleSpinBox() self.freqminSpinBox.setRange(5e-7, 1e6) self.freqminSpinBox.setDecimals(2) + self.freqminSpinBox.setSingleStep(0.01) self.freqminSpinBox.setSuffix(' Hz') self.freqminSpinBox.setEnabled(_enable) @@ -3107,6 +3107,7 @@ class FilterOptionsWidget(QWidget): self.freqmaxSpinBox = QDoubleSpinBox() self.freqmaxSpinBox.setRange(5e-7, 1e6) self.freqmaxSpinBox.setDecimals(2) + self.freqmaxSpinBox.setSingleStep(0.01) self.freqmaxSpinBox.setSuffix(' Hz') # if _enable: @@ -3163,11 +3164,19 @@ class FilterOptionsWidget(QWidget): self.setLayout(grid) - self.freqminSpinBox.valueChanged.connect(self.updateUi) - self.freqmaxSpinBox.valueChanged.connect(self.updateUi) + self.freqminSpinBox.valueChanged.connect(self.checkMin) + self.freqmaxSpinBox.valueChanged.connect(self.checkMax) self.orderSpinBox.valueChanged.connect(self.updateUi) self.selectTypeCombo.currentIndexChanged.connect(self.updateUi) + def checkMin(self): + if not self.freqminSpinBox.value() <= self.freqmaxSpinBox.value(): + self.freqmaxSpinBox.setValue(self.freqminSpinBox.value()) + + def checkMax(self): + if not self.freqminSpinBox.value() <= self.freqmaxSpinBox.value(): + self.freqminSpinBox.setValue(self.freqmaxSpinBox.value()) + def updateUi(self): type = self.selectTypeCombo.currentText() _enable = type in ['bandpass', 'bandstop'] @@ -3194,15 +3203,14 @@ class FilterOptionsWidget(QWidget): "Maximum frequency must be at least the " "same value as minimum frequency (notch)! " "Adjusted maximum frequency automatically!") - self.freqmaxSpinBox.setValue(freq[0]) + freq[1] = freq[0] + self.freqmaxSpinBox.setValue(freq[1]) self.freqmaxSpinBox.selectAll() self.freqmaxSpinBox.setFocus() - return False self.getFilterOptions().setFilterType(type) self.getFilterOptions().setFreq(freq) self.getFilterOptions().setOrder(self.orderSpinBox.value()) - return True def getFilterOptions(self): return self.filterOptions