Merge branch 'develop' into feature/refactor
This commit is contained in:
		
						commit
						1edc745903
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| *.pyc | ||||
| *~ | ||||
| pylot/RELEASE-VERSION | ||||
							
								
								
									
										271
									
								
								PyLoT.py
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								PyLoT.py
									
									
									
									
									
								
							| @ -75,7 +75,7 @@ from pylot.core.util.dataprocessing import read_metadata, restitute_data | ||||
| from pylot.core.util.utils import fnConstructor, getLogin, \ | ||||
|     full_range, readFilterInformation, trim_station_components, check4gaps, make_pen, pick_color_plt, \ | ||||
|     pick_linestyle_plt, remove_underscores, check4doubled, identifyPhaseID, excludeQualityClasses, has_spe, \ | ||||
|     check4rotated, transform_colors_mpl, transform_colors_mpl_str | ||||
|     check4rotated, transform_colors_mpl, transform_colors_mpl_str, getAutoFilteroptions | ||||
| from pylot.core.util.event import Event | ||||
| from pylot.core.io.location import create_creation_info, create_event | ||||
| from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \ | ||||
| @ -182,25 +182,22 @@ class MainWindow(QMainWindow): | ||||
|             settings.setValue("data/dataRoot", dirname) | ||||
|         if settings.value('compclass', None) is None: | ||||
|             settings.setValue('compclass', SetChannelComponents()) | ||||
|         if settings.value('useGuiFilter') is None: | ||||
|             settings.setValue('useGuiFilter', False) | ||||
|         if settings.value('output/Format', None) is None: | ||||
|             outformat = QInputDialog.getText(self, | ||||
|                                              "Enter output format (*.xml, *.cnv, *.obs):", | ||||
|                                              "Format") | ||||
|             settings.setValue("output/Format", outformat) | ||||
|         if settings.value('autoFilter', None) is None: | ||||
|             settings.setValue('autoFilter', True) | ||||
|         settings.sync() | ||||
| 
 | ||||
|         # setup UI | ||||
|         self.setupUi() | ||||
| 
 | ||||
|         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.updateFilteroptions() | ||||
| 
 | ||||
|         self.loc = False | ||||
| 
 | ||||
|     def setupUi(self): | ||||
| @ -270,8 +267,12 @@ class MainWindow(QMainWindow): | ||||
|         s_icon.addPixmap(QPixmap(':/icons/key_S.png')) | ||||
|         print_icon = QIcon() | ||||
|         print_icon.addPixmap(QPixmap(':/icons/printer.png')) | ||||
|         filter_icon = QIcon() | ||||
|         filter_icon.addPixmap(QPixmap(':/icons/filter.png')) | ||||
|         self.filter_icon = QIcon() | ||||
|         self.filter_icon.addPixmap(QPixmap(':/icons/filter.png')) | ||||
|         self.filter_icon_p = QIcon() | ||||
|         self.filter_icon_p.addPixmap(QPixmap(':/icons/filter_p.png')) | ||||
|         self.filter_icon_s = QIcon() | ||||
|         self.filter_icon_s.addPixmap(QPixmap(':/icons/filter_s.png')) | ||||
|         z_icon = QIcon() | ||||
|         z_icon.addPixmap(QPixmap(':/icons/key_Z.png')) | ||||
|         n_icon = QIcon() | ||||
| @ -286,6 +287,8 @@ class MainWindow(QMainWindow): | ||||
|         locate_icon.addPixmap(QPixmap(':/icons/locate_button.png')) | ||||
|         compare_icon = QIcon() | ||||
|         compare_icon.addPixmap(QPixmap(':/icons/compare_button.png')) | ||||
|         qualities_icon = QIcon() | ||||
|         qualities_icon.addPixmap(QPixmap(':/icons/pick_qualities_button.png')) | ||||
|         self.newProjectAction = self.createAction(self, "&New project ...", | ||||
|                                                   self.createNewProject, | ||||
|                                                   QKeySequence.New, newIcon, | ||||
| @ -366,15 +369,23 @@ class MainWindow(QMainWindow): | ||||
|                                                  self.setParameter, | ||||
|                                                  None, paraIcon, | ||||
|                                                  "Modify Parameter") | ||||
|         self.filterAction = self.createAction(self, "&Filter ...", | ||||
|                                               self.filterWaveformData, | ||||
|                                               "Ctrl+F", filter_icon, | ||||
|                                               """Toggle un-/filtered waveforms | ||||
|                                               to be displayed, according to the | ||||
|                                               desired seismic phase.""", True) | ||||
|         self.filterActionP = createAction(parent=self, text='Apply P Filter', | ||||
|                                           slot=self.filterP, | ||||
|                                           icon=self.filter_icon_p, | ||||
|                                           tip='Toggle filtered/original' | ||||
|                                               ' waveforms', | ||||
|                                           checkable=True, | ||||
|                                           shortcut='P') | ||||
|         self.filterActionS = createAction(parent=self, text='Apply S Filter', | ||||
|                                           slot=self.filterS, | ||||
|                                           icon=self.filter_icon_s, | ||||
|                                           tip='Toggle filtered/original' | ||||
|                                               ' waveforms', | ||||
|                                           checkable=True, | ||||
|                                           shortcut='S') | ||||
|         filterEditAction = self.createAction(self, "&Filter parameter ...", | ||||
|                                              self.adjustFilterOptions, | ||||
|                                              "Alt+F", filter_icon, | ||||
|                                              "Ctrl+F", self.filter_icon, | ||||
|                                              """Adjust filter parameters.""") | ||||
|         self.inventoryAction = self.createAction(self, "Select &Inventory ...", | ||||
|                                               self.get_new_metadata, | ||||
| @ -402,6 +413,10 @@ class MainWindow(QMainWindow): | ||||
|                                                               "automatic pick " | ||||
|                                                               "data.", False) | ||||
|         self.compare_action.setEnabled(False) | ||||
|         self.qualities_action = self.createAction(parent=self, text='Show pick qualitites...',  | ||||
|                                                 slot=self.pickQualities, shortcut='Alt+Q', | ||||
|                                                 icon=qualities_icon, tip='Histogram of pick qualities') | ||||
|         self.qualities_action.setEnabled(False) | ||||
| 
 | ||||
|         printAction = self.createAction(self, "&Print event ...", | ||||
|                                         self.show_event_information, QKeySequence.Print, | ||||
| @ -472,7 +487,7 @@ class MainWindow(QMainWindow): | ||||
|                                                ' the complete project on grid engine.') | ||||
|         self.auto_pick_sge.setEnabled(False) | ||||
| 
 | ||||
|         pickActions = (self.auto_tune, self.auto_pick, self.compare_action) | ||||
|         pickActions = (self.auto_tune, self.auto_pick, self.compare_action, self.qualities_action) | ||||
| 
 | ||||
|         # pickToolBar = self.addToolBar("PickTools") | ||||
|         # pickToolActions = (selectStation, ) | ||||
| @ -500,8 +515,8 @@ class MainWindow(QMainWindow): | ||||
|         self.updateFileMenu() | ||||
| 
 | ||||
|         self.editMenu = self.menuBar().addMenu('&Edit') | ||||
|         editActions = (self.filterAction, filterEditAction, None, | ||||
|                        self.selectPAction, self.selectSAction, None, | ||||
|         editActions = (self.filterActionP, self.filterActionS, filterEditAction, None, | ||||
|                        #self.selectPAction, self.selectSAction, None, | ||||
|                        self.inventoryAction, self.initMapAction, None, | ||||
|                        prefsEventAction) | ||||
|                        #printAction) #TODO: print event? | ||||
| @ -561,20 +576,29 @@ class MainWindow(QMainWindow): | ||||
|         style = settings.value('style') | ||||
|         self.set_style(style) | ||||
| 
 | ||||
|         # add event combo box and ref/test buttons | ||||
|         # add event combo box, forward, backward and ref/test buttons | ||||
|         self.eventBox = self.createEventBox() | ||||
|         self.eventBox.setMaxVisibleItems(30) | ||||
|         self.eventBox.setEnabled(False) | ||||
|         self.previous_button = QPushButton('<') | ||||
|         self.next_button = QPushButton('>') | ||||
|         self.init_ref_test_buttons() | ||||
|         self._event_layout = QHBoxLayout() | ||||
|         self._event_layout.addWidget(QLabel('Event: ')) | ||||
|         self._event_layout.addWidget(self.eventBox) | ||||
|         self._event_layout.addWidget(self.previous_button) | ||||
|         self._event_layout.addWidget(self.next_button) | ||||
|         self._event_layout.addWidget(self.ref_event_button) | ||||
|         self._event_layout.addWidget(self.test_event_button) | ||||
|         self._event_layout.setStretch(1, 1)  # set stretch of item 1 to 1 | ||||
|         self._main_layout.addLayout(self._event_layout) | ||||
|         self.eventBox.activated.connect(self.refreshEvents) | ||||
| 
 | ||||
|         self.previous_button.clicked.connect(self.previous_event) | ||||
|         self.next_button.clicked.connect(self.next_event) | ||||
|         self.previous_button.setEnabled(False) | ||||
|         self.next_button.setEnabled(False) | ||||
| 
 | ||||
|         # add main tab widget | ||||
|         self.tabs = QTabWidget(self) | ||||
|         self._main_layout.addWidget(self.tabs) | ||||
| @ -650,6 +674,8 @@ class MainWindow(QMainWindow): | ||||
|         ''' | ||||
|         self.ref_event_button = QtGui.QPushButton('Tune') | ||||
|         self.test_event_button = QtGui.QPushButton('Test') | ||||
|         self.ref_event_button.setMinimumWidth(100) | ||||
|         self.test_event_button.setMinimumWidth(100) | ||||
|         self.ref_event_button.setToolTip('Set manual picks of current ' + | ||||
|                                          'event as reference picks for autopicker tuning.') | ||||
|         self.test_event_button.setToolTip('Set manual picks of current ' + | ||||
| @ -763,6 +789,17 @@ class MainWindow(QMainWindow): | ||||
|     def metadata(self, value): | ||||
|         self._metadata = value | ||||
| 
 | ||||
|     def updateFilteroptions(self): | ||||
|         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'])} | ||||
| 
 | ||||
|     def updateFileMenu(self): | ||||
| 
 | ||||
|         self.fileMenu.clear() | ||||
| @ -1004,7 +1041,8 @@ class MainWindow(QMainWindow): | ||||
|                          and len(item.split('/')[-1].split('.')) == 3 | ||||
|                          and len(item.split('/')[-1]) == 12] | ||||
|             if not eventlist: | ||||
|                 print('No events found! Expected structure for event folders: [evID.DOY.YR]') | ||||
|                 print('No events found! Expected structure for event folders: [eEVID.DOY.YR],\n' | ||||
|                       ' e.g. eventID=1, doy=2, yr=2016: e0001.002.16') | ||||
|                 return | ||||
|         else: | ||||
|             return | ||||
| @ -1100,9 +1138,16 @@ class MainWindow(QMainWindow): | ||||
|         Initiate GUI widgets in case of changed or newly added events. | ||||
|         ''' | ||||
|         nitems = self.eventBox.count() | ||||
|         if len(self.project.eventlist) == 0: | ||||
|         is_data = self.data_check() | ||||
|         if len(self.project.eventlist) == 0 or not is_data: | ||||
|             print('No events to init.') | ||||
|             self.clearWaveformDataPlot() | ||||
|             if not is_data: | ||||
|                 new_path, modifypath = self.user_modify_path('Event folders not found! ') | ||||
|                 if modifypath: | ||||
|                     self.modify_project_path(new_path) | ||||
|                     self.init_events(True) | ||||
|                     self.setDirty(True) | ||||
|             return | ||||
|         self.eventBox.setEnabled(True) | ||||
|         self.fill_eventbox() | ||||
| @ -1113,6 +1158,31 @@ class MainWindow(QMainWindow): | ||||
|         self.refreshEvents() | ||||
|         tabindex = self.tabs.currentIndex() | ||||
| 
 | ||||
|     def user_modify_path(self, reason=''): | ||||
|         dialog = QtGui.QInputDialog(parent=self) | ||||
|         new_path, executed = dialog.getText(self, 'Change Project rootpath', | ||||
|                                              '{}Rename project path {}:'.format(reason, self.project.rootpath)) | ||||
|         return new_path, executed | ||||
| 
 | ||||
|     def data_check(self): | ||||
|         paths_exist = [os.path.exists(event.path) for event in self.project.eventlist] | ||||
|         if all(paths_exist): | ||||
|             return True | ||||
|         else: | ||||
|             info_str = '' | ||||
|             for event, path_exists in zip(self.project.eventlist, paths_exist): | ||||
|                 info_str += '\n{} exists: {}'.format(event.path, path_exists) | ||||
|             print('Unable to find certain event paths:{}'.format(info_str)) | ||||
|             return False | ||||
| 
 | ||||
|     def modify_project_path(self, new_rootpath): | ||||
|         self.project.rootpath = new_rootpath | ||||
|         for event in self.project.eventlist: | ||||
|             event.rootpath = new_rootpath | ||||
|             event.path = os.path.join(event.rootpath, event.datapath, event.database, event.pylot_id) | ||||
|             event.path = event.path.replace('\\', '/') | ||||
|             event.path = event.path.replace('//', '/') | ||||
| 
 | ||||
|     def fill_eventbox(self, event=None, eventBox=None, select_events='all'): | ||||
|         ''' | ||||
|         (Re)fill the selected eventBox (type = QtGui.QComboBox). | ||||
| @ -1353,6 +1423,9 @@ class MainWindow(QMainWindow): | ||||
|         self.cmpw.refresh_tooltips() | ||||
|         self.cmpw.show() | ||||
| 
 | ||||
|     def pickQualities(self): | ||||
|         return | ||||
| 
 | ||||
|     def compareMulti(self): | ||||
|         if not self.compareoptions: | ||||
|             return | ||||
| @ -1401,7 +1474,8 @@ class MainWindow(QMainWindow): | ||||
|         return None | ||||
| 
 | ||||
|     def getStime(self): | ||||
|         return self._stime | ||||
|         if self.get_data(): | ||||
|             return full_range(self.get_data().getWFData())[0] | ||||
| 
 | ||||
|     def addActions(self, target, actions): | ||||
|         for action in actions: | ||||
| @ -1470,6 +1544,26 @@ class MainWindow(QMainWindow): | ||||
|         if self.tap: | ||||
|             self.tap.fill_eventbox() | ||||
| 
 | ||||
|     def checkEventButtons(self): | ||||
|         if self.eventBox.currentIndex() == 0: | ||||
|             prev_state = False | ||||
|         else: | ||||
|             prev_state = True | ||||
|         if self.eventBox.currentIndex() == len(self.project.eventlist) - 1: | ||||
|             next_state = False | ||||
|         else: | ||||
|             next_state = True | ||||
|         self.previous_button.setEnabled(prev_state) | ||||
|         self.next_button.setEnabled(next_state) | ||||
| 
 | ||||
|     def previous_event(self): | ||||
|         self.eventBox.setCurrentIndex(self.eventBox.currentIndex() - 1) | ||||
|         self.eventBox.activated.emit(-1) | ||||
| 
 | ||||
|     def next_event(self): | ||||
|         self.eventBox.setCurrentIndex(self.eventBox.currentIndex() + 1) | ||||
|         self.eventBox.activated.emit(+1) | ||||
| 
 | ||||
|     def refreshEvents(self): | ||||
|         ''' | ||||
|         Refresh GUI when events get changed. | ||||
| @ -1480,6 +1574,7 @@ class MainWindow(QMainWindow): | ||||
|         # array_map refresh is not necessary when changing event in waveform plot tab, | ||||
|         # but gets necessary when switching from one to another after changing an event. | ||||
|         self._eventChanged = [True, True] | ||||
|         self.checkEventButtons() | ||||
|         self.refreshTabs() | ||||
| 
 | ||||
|     def refreshTabs(self): | ||||
| @ -1554,18 +1649,38 @@ class MainWindow(QMainWindow): | ||||
|         # else: | ||||
|         #     ans = False | ||||
|         self.fnames = self.getWFFnames_from_eventbox() | ||||
|         self.data.setWFData(self.fnames) | ||||
|         wfdat = self.data.getWFData()  # all available streams | ||||
|         # remove possible underscores in station names | ||||
|         wfdat = remove_underscores(wfdat) | ||||
|         # check for gaps and doubled channels | ||||
|         check4gaps(wfdat) | ||||
|         check4doubled(wfdat) | ||||
|         # check for stations with rotated components | ||||
|         wfdat = check4rotated(wfdat, self.metadata, verbosity=0) | ||||
|         # trim station components to same start value | ||||
|         trim_station_components(wfdat, trim_start=True, trim_end=False) | ||||
|         self._stime = full_range(self.get_data().getWFData())[0] | ||||
|         self.data.setWFData(self.fnames, | ||||
|                             checkRotated=True, | ||||
|                             metadata=self.metadata) | ||||
| 
 | ||||
|     def check_plot_quantity(self): | ||||
|         settings = QSettings() | ||||
|         nth_sample = settings.value("nth_sample") if settings.value("nth_sample") else 1 | ||||
|         npts_max = 1e6 | ||||
|         npts = self.get_npts_to_plot() | ||||
|         npts2plot = npts/nth_sample | ||||
|         if npts2plot < npts_max: | ||||
|             return | ||||
|         nth_sample_new = int(np.ceil(npts/npts_max)) | ||||
|         message = "You are about to plot a huge dataset with {npts} datapoints. With a current setting of " \ | ||||
|                   "nth_sample = {nth_sample} a total of {npts2plot} points will be plotted which is more " \ | ||||
|                   "than the maximum setting of {npts_max}. " \ | ||||
|                   "PyLoT recommends to raise nth_sample from {nth_sample} to {nth_sample_new}. Continue?" | ||||
| 
 | ||||
|         ans = QMessageBox.question(self, self.tr("Optimize plot performance..."), | ||||
|                                    self.tr(message.format(npts=npts, | ||||
|                                                           nth_sample=nth_sample, | ||||
|                                                           npts_max=npts_max, | ||||
|                                                           nth_sample_new=nth_sample_new, | ||||
|                                                           npts2plot=npts2plot)), | ||||
|                                    QMessageBox.Yes | QMessageBox.No, | ||||
|                                    QMessageBox.Yes) | ||||
|         if ans == QMessageBox.Yes: | ||||
|             settings.setValue("nth_sample", nth_sample_new) | ||||
|             settings.sync() | ||||
| 
 | ||||
|     def get_npts_to_plot(self): | ||||
|         return sum(trace.stats.npts for trace in self.data.getWFData()) | ||||
| 
 | ||||
|     def connectWFplotEvents(self): | ||||
|         ''' | ||||
| @ -1661,8 +1776,10 @@ class MainWindow(QMainWindow): | ||||
|         if event.pylot_picks: | ||||
|             self.drawPicks(picktype='manual') | ||||
|             self.locateEvent.setEnabled(True) | ||||
|             self.qualities_action.setEnabled(True) | ||||
|         if event.pylot_autopicks: | ||||
|             self.drawPicks(picktype='auto') | ||||
|             self.qualities_action.setEnabled(True) | ||||
|         if True in self.comparable.values(): | ||||
|             self.compare_action.setEnabled(True) | ||||
|         self.draw() | ||||
| @ -1724,18 +1841,20 @@ class MainWindow(QMainWindow): | ||||
|         self.disableSaveEventAction() | ||||
|         self.draw() | ||||
| 
 | ||||
|     def plotWaveformDataThread(self): | ||||
|     def plotWaveformDataThread(self, filter=True): | ||||
|         ''' | ||||
|         Open a modal thread to plot current waveform data. | ||||
|         ''' | ||||
|         self.check_plot_quantity() | ||||
|         self.clearWaveformDataPlot() | ||||
|         self.wfp_thread = Thread(self, self.plotWaveformData, | ||||
|                                  arg=filter, | ||||
|                                  progressText='Plotting waveform data...', | ||||
|                                  pb_widget=self.mainProgressBarWidget) | ||||
|         self.wfp_thread.finished.connect(self.finishWaveformDataPlot) | ||||
|         self.wfp_thread.start() | ||||
| 
 | ||||
|     def plotWaveformData(self): | ||||
|     def plotWaveformData(self, filter=True): | ||||
|         ''' | ||||
|         Plot waveform data to current plotWidget. | ||||
|         ''' | ||||
| @ -1747,6 +1866,10 @@ class MainWindow(QMainWindow): | ||||
|         comp = self.getComponent() | ||||
|         title = 'section: {0} components'.format(zne_text[comp]) | ||||
|         wfst = self.get_data().getWFData() | ||||
|         if self.filterActionP.isChecked() and filter: | ||||
|             self.filterWaveformData(plot=False, phase='P') | ||||
|         elif self.filterActionS.isChecked() and filter: | ||||
|             self.filterWaveformData(plot=False, phase='S') | ||||
|         # wfst = self.get_data().getWFData().select(component=comp) | ||||
|         # wfst += self.get_data().getWFData().select(component=alter_comp) | ||||
|         plotWidget = self.getPlotWidget() | ||||
| @ -1786,18 +1909,51 @@ class MainWindow(QMainWindow): | ||||
|     def pushFilterWF(self, param_args): | ||||
|         self.get_data().filterWFData(param_args) | ||||
| 
 | ||||
|     def filterWaveformData(self): | ||||
|     def filterP(self): | ||||
|         self.filterActionS.setChecked(False) | ||||
|         if self.filterActionP.isChecked(): | ||||
|             self.filterWaveformData(phase='P') | ||||
|         else: | ||||
|             self.resetWFData() | ||||
| 
 | ||||
|     def filterS(self): | ||||
|         self.filterActionP.setChecked(False) | ||||
|         if self.filterActionS.isChecked(): | ||||
|             self.filterWaveformData(phase='S') | ||||
|         else: | ||||
|             self.resetWFData() | ||||
| 
 | ||||
|     def resetWFData(self): | ||||
|         self.get_data().resetWFData() | ||||
|         self.plotWaveformDataThread() | ||||
| 
 | ||||
|     def filterWaveformData(self, plot=True, phase=None): | ||||
|         if not self.get_current_event(): | ||||
|             return | ||||
| 
 | ||||
|         if self.get_data(): | ||||
|             if self.getFilterOptions() and self.filterAction.isChecked(): | ||||
|                 kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions() | ||||
|                 self.pushFilterWF(kwargs) | ||||
|             elif self.filterAction.isChecked(): | ||||
|             if not phase: | ||||
|                 if self.filterActionP.isChecked(): | ||||
|                     phase = 'P' | ||||
|                 elif self.filterActionS.isChecked(): | ||||
|                     phase = 'S' | ||||
|             if self.getFilterOptions(): | ||||
|                 if (phase == 'P' and self.filterActionP.isChecked()) or (phase == 'S' and self.filterActionS.isChecked()): | ||||
|                     kwargs = self.getFilterOptions()[phase].parseFilterOptions() | ||||
|                     self.pushFilterWF(kwargs) | ||||
|                 else: | ||||
|                     self.get_data().resetWFData() | ||||
|             elif self.filterActionP.isChecked() or self.filterActionS.isChecked(): | ||||
|                 self.adjustFilterOptions() | ||||
|             else: | ||||
|                 self.get_data().resetWFData() | ||||
|         self.plotWaveformDataThread() | ||||
|         self.drawPicks() | ||||
|         self.draw() | ||||
|             if plot: | ||||
|                 self.plotWaveformDataThread(filter=False) | ||||
|                 #self.drawPicks() | ||||
|                 #self.draw() | ||||
| 
 | ||||
|     def getAutoFilteroptions(self, phase): | ||||
|         return getAutoFilteroptions(phase, self._inputs) | ||||
| 
 | ||||
|     def adjustFilterOptions(self): | ||||
|         fstring = "Filter Options" | ||||
| @ -1806,10 +1962,11 @@ class MainWindow(QMainWindow): | ||||
|         if self.filterDlg.exec_(): | ||||
|             filteroptions = self.filterDlg.getFilterOptions() | ||||
|             self.setFilterOptions(filteroptions) | ||||
|             if self.filterAction.isChecked(): | ||||
|             if self.filterActionP.isChecked() or self.filterActionS.isChecked(): | ||||
|                 kwargs = self.getFilterOptions()[self.getSeismicPhase()].parseFilterOptions() | ||||
|                 self.pushFilterWF(kwargs) | ||||
|                 self.plotWaveformDataThread() | ||||
|             return True | ||||
| 
 | ||||
|     def checkFilterOptions(self): | ||||
|         fstring = "Filter Options" | ||||
| @ -1886,7 +2043,7 @@ class MainWindow(QMainWindow): | ||||
|     #                            '[{0}: {1} Hz]'.format( | ||||
|     #             self.getFilterOptions().getFilterType(), | ||||
|     #             self.getFilterOptions().getFreq())) | ||||
|     #     if self.filterAction.isChecked(): | ||||
|     #     if self.filterActionP.isChecked() or self.filterActionS.isChecked(): | ||||
|     #         self.filterWaveformData() | ||||
| 
 | ||||
|     def getSeismicPhase(self): | ||||
| @ -1934,7 +2091,7 @@ class MainWindow(QMainWindow): | ||||
|         if self._shift: | ||||
|             factor = {'up': 1. / 2., | ||||
|                       'down': 2.} | ||||
|             xlims = self.dataPlot.getXLims() | ||||
|             xlims = self.dataPlot.getXLims(self.dataPlot.axes[0]) | ||||
|             xdiff = xlims[1] - xlims[0] | ||||
|             xdiff *= factor[button] | ||||
|             xl = x - 0.5 * xdiff | ||||
| @ -1943,7 +2100,7 @@ class MainWindow(QMainWindow): | ||||
|                 xl = self._max_xlims[0] | ||||
|             if xr > self._max_xlims[1]: | ||||
|                 xr = self._max_xlims[1] | ||||
|             self.dataPlot.setXLims((xl, xr)) | ||||
|             self.dataPlot.setXLims(self.dataPlot.axes[0], (xl, xr)) | ||||
|             self.dataPlot.draw() | ||||
| 
 | ||||
|     def pickOnStation(self, gui_event): | ||||
| @ -1970,7 +2127,7 @@ class MainWindow(QMainWindow): | ||||
|         if not station: | ||||
|             return | ||||
|         self.update_status('picking on station {0}'.format(station)) | ||||
|         data = self.get_data().getWFData() | ||||
|         data = self.get_data().getOriginalWFData().copy() | ||||
|         event = self.get_current_event() | ||||
|         pickDlg = PickDlg(self, parameter=self._inputs, | ||||
|                           data=data.select(station=station), | ||||
| @ -1979,6 +2136,9 @@ class MainWindow(QMainWindow): | ||||
|                           autopicks=self.getPicksOnStation(station, 'auto'), | ||||
|                           metadata=self.metadata, event=event, | ||||
|                           filteroptions=self.filteroptions) | ||||
|         if self.filterActionP.isChecked() or self.filterActionS.isChecked(): | ||||
|             pickDlg.currentPhase = self.getSeismicPhase() | ||||
|             pickDlg.filterWFData() | ||||
|         pickDlg.nextStation.setChecked(nextStation) | ||||
|         if pickDlg.exec_(): | ||||
|             if pickDlg._dirty: | ||||
| @ -2315,7 +2475,7 @@ class MainWindow(QMainWindow): | ||||
|         if self.pg: | ||||
|             pw = self.getPlotWidget().plotWidget | ||||
|         else: | ||||
|             ax = self.getPlotWidget().axes | ||||
|             ax = self.getPlotWidget().axes[0] | ||||
|         ylims = np.array([-.5, +.5]) + plotID | ||||
| 
 | ||||
|         stat_picks = self.getPicks(type=picktype)[station] | ||||
| @ -2385,7 +2545,7 @@ class MainWindow(QMainWindow): | ||||
|             else: | ||||
|                 if picktype == 'manual': | ||||
|                     linestyle_mpp, width_mpp = pick_linestyle_plt(picktype, 'mpp') | ||||
|                     color = pick_color_plt(picktype, phase, quality) | ||||
|                     color = pick_color_plt(picktype, self.getPhaseID(phase), quality) | ||||
|                     if picks['epp'] and picks['lpp']: | ||||
|                         ax.fill_between([epp, lpp], ylims[0], ylims[1], | ||||
|                                         alpha=.25, color=color, label='EPP, LPP') | ||||
| @ -2927,6 +3087,7 @@ class MainWindow(QMainWindow): | ||||
|             if hasattr(self.project, 'parameter'): | ||||
|                 if self.project.parameter: | ||||
|                     self._inputs = self.project.parameter | ||||
|                     self.updateFilteroptions() | ||||
|             self.tabs.setCurrentIndex(0)  # implemented to prevent double-loading of waveform data | ||||
|             self.init_events(new=True) | ||||
|             self.setDirty(False) | ||||
|  | ||||
| @ -338,6 +338,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even | ||||
|                         local_mag = LocalMagnitude(corr_dat, evt, | ||||
|                                                    parameter.get('sstop'), | ||||
|                                                    WAscaling, True, iplot) | ||||
|                         # update pick with local magnitude property values | ||||
|                         for stats, amplitude in local_mag.amplitudes.items(): | ||||
|                             picks[stats]['S']['Ao'] = amplitude.generic_amplitude | ||||
|                         print("Local station magnitudes scaled with:") | ||||
| @ -412,6 +413,7 @@ def autoPyLoT(input_dict=None, parameter=None, inputfile=None, fnames=None, even | ||||
|                             local_mag = LocalMagnitude(corr_dat, evt, | ||||
|                                                        parameter.get('sstop'), | ||||
|                                                        WAscaling, True, iplot) | ||||
|                             # update pick with local magnitude property values | ||||
|                             for stats, amplitude in local_mag.amplitudes.items(): | ||||
|                                 if stats in picks: | ||||
|                                     picks[stats]['S']['Ao'] = amplitude.generic_amplitude | ||||
| @ -496,7 +498,7 @@ if __name__ == "__main__": | ||||
|                         help='''full path to the file containing the input | ||||
|                         parameters for autoPyLoT''') | ||||
|     parser.add_argument('-p', '-P', '--iplot', type=int,  | ||||
|                         action='store', | ||||
|                         action='store', default=0, | ||||
|                         help='''optional, logical variable for plotting: 0=none, 1=partial, 2=all''')  | ||||
|     parser.add_argument('-f', '-F', '--fnames', type=str, | ||||
|                         action='store', | ||||
|  | ||||
| @ -29,10 +29,12 @@ | ||||
|         <file>icons/map.png</file> | ||||
|         <file>icons/openloc.png</file> | ||||
|         <file>icons/compare_button.png</file> | ||||
|         <file>icons/pick_qualities_button.png</file> | ||||
|         <file>icons/locate_button.png</file> | ||||
|         <file>icons/Matlab_PILOT_icon.png</file> | ||||
|         <file>icons/printer.png</file> | ||||
|         <file>icons/delete.png</file> | ||||
|         <file>icons/key_A.png</file> | ||||
|         <file>icons/key_E.png</file> | ||||
|         <file>icons/key_N.png</file> | ||||
|         <file>icons/key_P.png</file> | ||||
| @ -45,6 +47,8 @@ | ||||
|         <file>icons/key_W.png</file> | ||||
|         <file>icons/key_Z.png</file> | ||||
|         <file>icons/filter.png</file> | ||||
|         <file>icons/filter_p.png</file> | ||||
|         <file>icons/filter_s.png</file> | ||||
|         <file>icons/sync.png</file> | ||||
|         <file>icons/zoom_0.png</file> | ||||
|         <file>icons/zoom_in.png</file> | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								icons/filter_p.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/filter_p.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 5.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								icons/filter_s.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/filter_s.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								icons/key_A.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/key_A.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 48 KiB | 
							
								
								
									
										11574
									
								
								icons_rc_2.py
									
									
									
									
									
								
							
							
						
						
									
										11574
									
								
								icons_rc_2.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										214148
									
								
								icons_rc_3.py
									
									
									
									
									
								
							
							
						
						
									
										214148
									
								
								icons_rc_3.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -16,7 +16,6 @@ from pylot.core.util.utils import common_range, fit_curve | ||||
| from scipy import integrate, signal | ||||
| from scipy.optimize import curve_fit | ||||
| 
 | ||||
| 
 | ||||
| def richter_magnitude_scaling(delta): | ||||
|     distance = np.array([0, 10, 20, 25, 30, 35, 40, 45, 50, 60, 70, 75, 85, 90, 100, 110, | ||||
|                          120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 230, 240, 250, | ||||
| @ -133,7 +132,7 @@ class Magnitude(object): | ||||
|                     station_count=len(self.magnitudes), | ||||
|                     azimuthal_gap=self.origin_id.get_referred_object().quality.azimuthal_gap) | ||||
|             else: | ||||
|                 # no saling necessary | ||||
|                 # no scaling necessary | ||||
|                 mag = ope.Magnitude( | ||||
|                     mag=np.median([M.mag for M in self.magnitudes.values()]), | ||||
|                     magnitude_type=self.type, | ||||
| @ -233,17 +232,33 @@ class LocalMagnitude(Magnitude): | ||||
|         # check for plot flag (for debugging only) | ||||
|         fig = None | ||||
|         if iplot > 1: | ||||
|             st.plot() | ||||
|             fig = plt.figure() | ||||
|             ax = fig.add_subplot(111) | ||||
|             ax = fig.add_subplot(211) | ||||
|             ax.plot(th, st[0].data, 'k') | ||||
|             ax.plot(th, sqH) | ||||
|             ax.plot(th[iwin], sqH[iwin], 'g') | ||||
|             ax.plot([t0, t0], [0, max(sqH)], 'r', linewidth=2) | ||||
|             ax.title( | ||||
|                 'Station %s, RMS Horizontal Traces, WA-peak-to-peak=%4.1f mm' \ | ||||
|                 % (st[0].stats.station, wapp)) | ||||
|             ax.plot([t0 - stime, t0 - stime], [0, max(sqH)], 'r', linewidth=2) | ||||
|             ax.set_title('Station %s, Channel %s, RMS Horizontal Trace, ' | ||||
|                          'WA-peak-to-peak=%6.3f mm' % (st[0].stats.station,  | ||||
|                                                        st[0].stats.channel, | ||||
|                                                                         wapp)) | ||||
|             ax.set_xlabel('Time [s]') | ||||
|             ax.set_ylabel('Displacement [mm]') | ||||
|             ax = fig.add_subplot(212) | ||||
|             ax.plot(th, st[1].data, 'k') | ||||
|             ax.plot(th, sqH) | ||||
|             ax.plot(th[iwin], sqH[iwin], 'g') | ||||
|             ax.plot([t0 - stime, t0 - stime], [0, max(sqH)], 'r', linewidth=2) | ||||
|             ax.set_title('Channel %s, RMS Horizontal Trace, ' | ||||
|                          'WA-peak-to-peak=%6.3f mm' % (st[1].stats.channel, | ||||
|                                                                        wapp)) | ||||
|             ax.set_xlabel('Time [s]') | ||||
|             ax.set_ylabel('Displacement [mm]') | ||||
|             fig.show() | ||||
|             try: input() | ||||
|             except SyntaxError: pass | ||||
|             plt.close(fig) | ||||
| 
 | ||||
| 
 | ||||
|         return wapp, fig | ||||
| 
 | ||||
| @ -251,6 +266,10 @@ class LocalMagnitude(Magnitude): | ||||
|         for a in self.arrivals: | ||||
|             if a.phase not in 'sS': | ||||
|                 continue | ||||
|             # make sure calculating Ml only from reliable onsets | ||||
|             # NLLoc: time_weight = 0 => do not use onset! | ||||
|             if a.time_weight == 0: | ||||
|                 continue | ||||
|             pick = a.pick_id.get_referred_object() | ||||
|             station = pick.waveform_id.station_code | ||||
|             wf = select_for_phase(self.stream.select( | ||||
| @ -347,7 +366,11 @@ class MomentMagnitude(Magnitude): | ||||
| 
 | ||||
|     def calc(self): | ||||
|         for a in self.arrivals: | ||||
|             if a.phase not in 'pP': | ||||
|             if a.phase not in 'pP':  | ||||
|                 continue | ||||
|             # make sure calculating Mo only from reliable onsets | ||||
|             # NLLoc: time_weight = 0 => do not use onset! | ||||
|             if a.time_weight == 0: | ||||
|                 continue | ||||
|             pick = a.pick_id.get_referred_object() | ||||
|             station = pick.waveform_id.station_code | ||||
|  | ||||
| @ -12,7 +12,8 @@ from pylot.core.io.phases import readPILOTEvent, picks_from_picksdict, \ | ||||
|     picksdict_from_pilot, merge_picks | ||||
| from pylot.core.util.errors import FormatError, OverwriteError | ||||
| from pylot.core.util.event import Event | ||||
| from pylot.core.util.utils import fnConstructor, full_range | ||||
| from pylot.core.util.utils import fnConstructor, full_range, remove_underscores, check4gaps, check4doubled, \ | ||||
|     check4rotated, trim_station_components | ||||
| import pylot.core.loc.velest as velest | ||||
| 
 | ||||
| 
 | ||||
| @ -99,6 +100,11 @@ class Data(object): | ||||
|         return self | ||||
| 
 | ||||
|     def getPicksStr(self): | ||||
|         """ | ||||
|         Return picks in event data | ||||
|         :return: picks seperated by newlines | ||||
|         :rtype: str | ||||
|         """ | ||||
|         picks_str = '' | ||||
|         for pick in self.get_evt_data().picks: | ||||
|             picks_str += str(pick) + '\n' | ||||
| @ -106,18 +112,11 @@ class Data(object): | ||||
| 
 | ||||
|     def getParent(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         Get PySide.QtGui.QWidget parent object | ||||
|         """ | ||||
|         return self._parent | ||||
| 
 | ||||
|     def isNew(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         """ | ||||
|         return self._new | ||||
| 
 | ||||
|     def setNew(self): | ||||
| @ -125,9 +124,9 @@ class Data(object): | ||||
| 
 | ||||
|     def getCutTimes(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         Returns earliest start and latest end of all waveform data | ||||
|         :return: minimum start time and maximum end time as a tuple | ||||
|         :rtype: (UTCDateTime, UTCDateTime) | ||||
|         """ | ||||
|         if self.cuttimes is None: | ||||
|             self.updateCutTimes() | ||||
| @ -135,22 +134,34 @@ class Data(object): | ||||
| 
 | ||||
|     def updateCutTimes(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         Update cuttimes to contain earliest start and latest end time | ||||
|         of all waveform data | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.cuttimes = full_range(self.getWFData()) | ||||
| 
 | ||||
|     def getEventFileName(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         """ | ||||
|         ID = self.getID() | ||||
|         # handle forbidden filenames especially on windows systems | ||||
|         return fnConstructor(str(ID)) | ||||
| 
 | ||||
|     def checkEvent(self, event, fcheck, forceOverwrite=False): | ||||
|         """ | ||||
|         Check information in supplied event and own event and replace own | ||||
|         information with supplied information if own information not exiisting | ||||
|         or forced by forceOverwrite | ||||
|         :param event: Event that supplies information for comparison | ||||
|         :type event: pylot.core.util.event.Event | ||||
|         :param fcheck: check and delete existing information | ||||
|         can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude'] | ||||
|         :type fcheck: str, [str] | ||||
|         :param forceOverwrite: Set to true to force overwrite own information. If false, | ||||
|         supplied information from event is only used if there is no own information in that | ||||
|         category (given in fcheck: manual, auto, origin, magnitude) | ||||
|         :type forceOverwrite: bool | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         if 'origin' in fcheck: | ||||
|             self.replaceOrigin(event, forceOverwrite) | ||||
|         if 'magnitude' in fcheck: | ||||
| @ -161,18 +172,47 @@ class Data(object): | ||||
|             self.replacePicks(event, 'manual') | ||||
| 
 | ||||
|     def replaceOrigin(self, event, forceOverwrite=False): | ||||
|         """ | ||||
|         Replace own origin with the one supplied in event if own origin is not | ||||
|         existing or forced by forceOverwrite = True | ||||
|         :param event: Event that supplies information for comparison | ||||
|         :type event: pylot.core.util.event.Event | ||||
|         :param forceOverwrite: always replace own information with supplied one if true | ||||
|         :type forceOverwrite: bool | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         if self.get_evt_data().origins or forceOverwrite: | ||||
|             if event.origins: | ||||
|                 print("Found origin, replace it by new origin.") | ||||
|             event.origins = self.get_evt_data().origins | ||||
| 
 | ||||
|     def replaceMagnitude(self, event, forceOverwrite=False): | ||||
|         """ | ||||
|         Replace own magnitude with the one supplied in event if own magnitude is not | ||||
|         existing or forced by forceOverwrite = True | ||||
|         :param event: Event that supplies information for comparison | ||||
|         :type event: pylot.core.util.event.Event | ||||
|         :param forceOverwrite: always replace own information with supplied one if true | ||||
|         :type forceOverwrite: bool | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         if self.get_evt_data().magnitudes or forceOverwrite: | ||||
|             if event.magnitudes: | ||||
|                 print("Found magnitude, replace it by new magnitude") | ||||
|             event.magnitudes = self.get_evt_data().magnitudes | ||||
| 
 | ||||
|     def replacePicks(self, event, picktype): | ||||
|         """ | ||||
|         Replace own picks with the one in event | ||||
|         :param event: Event that supplies information for comparison | ||||
|         :type event: pylot.core.util.event.Event | ||||
|         :param picktype: 'auto' or 'manual' picks | ||||
|         :type picktype: str | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         checkflag = 0 | ||||
|         picks = event.picks | ||||
|         # remove existing picks | ||||
| @ -189,10 +229,10 @@ class Data(object): | ||||
|                 picks.append(pick) | ||||
| 
 | ||||
|     def exportEvent(self, fnout, fnext='.xml', fcheck='auto', upperErrors=None): | ||||
| 
 | ||||
|         """ | ||||
|         Export event to file | ||||
|         :param fnout: basename of file | ||||
|         :param fnext: file extension | ||||
|         :param fnext: file extension, xml, cnv, obs | ||||
|         :param fcheck: check and delete existing information | ||||
|         can be a str or a list of strings of ['manual', 'auto', 'origin', 'magnitude'] | ||||
|         """ | ||||
| @ -304,17 +344,13 @@ class Data(object): | ||||
| 
 | ||||
|     def getComp(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         Get component (ZNE) | ||||
|         """ | ||||
|         return self.comp | ||||
| 
 | ||||
|     def getID(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         Get unique resource id | ||||
|         """ | ||||
|         try: | ||||
|             return self.evtdata.get('resource_id').id | ||||
| @ -323,16 +359,20 @@ class Data(object): | ||||
| 
 | ||||
|     def filterWFData(self, kwargs): | ||||
|         """ | ||||
| 
 | ||||
|         :param kwargs: | ||||
|         Filter waveform data | ||||
|         :param kwargs: arguments to pass through to filter function | ||||
|         """ | ||||
|         self.getWFData().filter(**kwargs) | ||||
|         data = self.getWFData() | ||||
|         data.detrend('linear') | ||||
|         data.taper(0.02, type='cosine') | ||||
|         data.filter(**kwargs) | ||||
|         self.dirty = True | ||||
| 
 | ||||
|     def setWFData(self, fnames): | ||||
|     def setWFData(self, fnames, checkRotated=False, metadata=None): | ||||
|         """ | ||||
| 
 | ||||
|         :param fnames: | ||||
|         Clear current waveform data and set given waveform data | ||||
|         :param fnames: waveform data names to append | ||||
|         :type fnames: list | ||||
|         """ | ||||
|         self.wfdata = Stream() | ||||
|         self.wforiginal = None | ||||
| @ -340,14 +380,31 @@ class Data(object): | ||||
|             self.appendWFData(fnames) | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|         # various pre-processing steps: | ||||
|         # remove possible underscores in station names | ||||
|         self.wfdata = remove_underscores(self.wfdata) | ||||
|         # check for gaps and doubled channels | ||||
|         check4gaps(self.wfdata) | ||||
|         check4doubled(self.wfdata) | ||||
|         # check for stations with rotated components | ||||
|         if checkRotated and metadata is not None: | ||||
|             self.wfdata = check4rotated(self.wfdata, metadata, verbosity=0) | ||||
|         # trim station components to same start value | ||||
|         trim_station_components(self.wfdata, trim_start=True, trim_end=False) | ||||
| 
 | ||||
|         # make a copy of original data | ||||
|         self.wforiginal = self.getWFData().copy() | ||||
|         self.dirty = False | ||||
|         return True | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     def appendWFData(self, fnames): | ||||
|         """ | ||||
| 
 | ||||
|         :param fnames: | ||||
|         Read waveform data from fnames and append it to current wf data | ||||
|         :param fnames: waveform data to append | ||||
|         :type fnames: list | ||||
|         """ | ||||
|         assert isinstance(fnames, list), "input parameter 'fnames' is " \ | ||||
|                                          "supposed to be of type 'list' " \ | ||||
| @ -372,54 +429,45 @@ class Data(object): | ||||
|             print(warnmsg) | ||||
| 
 | ||||
|     def getWFData(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         """ | ||||
|         return self.wfdata | ||||
| 
 | ||||
|     def getOriginalWFData(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         """ | ||||
|         return self.wforiginal | ||||
| 
 | ||||
|     def resetWFData(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         Set waveform data to original waveform data | ||||
|         """ | ||||
|         self.wfdata = self.getOriginalWFData().copy() | ||||
|         if self.getOriginalWFData(): | ||||
|             self.wfdata = self.getOriginalWFData().copy() | ||||
|         else: | ||||
|             self.wfdata = Stream() | ||||
|         self.dirty = False | ||||
| 
 | ||||
|     def resetPicks(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         Clear all picks from event | ||||
|         """ | ||||
|         self.get_evt_data().picks = [] | ||||
| 
 | ||||
|     def get_evt_data(self): | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
|         :return: | ||||
|         """ | ||||
|         return self.evtdata | ||||
| 
 | ||||
|     def setEvtData(self, event): | ||||
|         self.evtdata = event | ||||
| 
 | ||||
|     def applyEVTData(self, data, typ='pick', authority_id='rub'): | ||||
| 
 | ||||
|         """ | ||||
| 
 | ||||
|         :param data: | ||||
|         :param typ: | ||||
|         :param authority_id: | ||||
|         Either takes an `obspy.core.event.Event` object and applies all new | ||||
|         information on the event to the actual data if typ is 'event or | ||||
|         creates ObsPy pick objects and append it to the picks list from the | ||||
|         PyLoT dictionary contain all picks if type is pick | ||||
|         :param data: data to apply, either picks or complete event | ||||
|         :type data: | ||||
|         :param typ: which event data to apply, 'pick' or 'event' | ||||
|         :type typ: str | ||||
|         :param authority_id: (currently unused) | ||||
|         :type: str | ||||
|         :raise OverwriteError: | ||||
|         """ | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,10 @@ | ||||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8 -*- | ||||
| import numpy as np | ||||
| 
 | ||||
| """ | ||||
| Default parameters used for picking | ||||
| """ | ||||
| 
 | ||||
| defaults = {'rootpath': {'type': str, | ||||
|                          'tooltip': 'project path', | ||||
| @ -74,11 +79,15 @@ defaults = {'rootpath': {'type': str, | ||||
|             'vp': {'type': float, | ||||
|                    'tooltip': 'average P-wave velocity', | ||||
|                    'value': 3530., | ||||
|                    'min': 0., | ||||
|                    'max': np.inf, | ||||
|                    'namestring': 'P-velocity'}, | ||||
| 
 | ||||
|             'rho': {'type': float, | ||||
|                     'tooltip': 'average rock density [kg/m^3]', | ||||
|                     'value': 2500., | ||||
|                     'min': 0., | ||||
|                     'max': np.inf, | ||||
|                     'namestring': 'Density'}, | ||||
| 
 | ||||
|             'Qp': {'type': (float, float), | ||||
| @ -90,42 +99,58 @@ defaults = {'rootpath': {'type': str, | ||||
|                        'tooltip': 'start time [s] for calculating CF for P-picking (if TauPy:' | ||||
|                                   ' seconds relative to estimated onset)', | ||||
|                        'value': 15.0, | ||||
|                        'min': -np.inf, | ||||
|                        'max': np.inf, | ||||
|                        'namestring': 'P start'}, | ||||
| 
 | ||||
|             'pstop': {'type': float, | ||||
|                       'tooltip': 'end time [s] for calculating CF for P-picking (if TauPy:' | ||||
|                                  ' seconds relative to estimated onset)', | ||||
|                       'value': 60.0, | ||||
|                       'min': -np.inf, | ||||
|                       'max': np.inf, | ||||
|                       'namestring': 'P stop'}, | ||||
| 
 | ||||
|             'sstart': {'type': float, | ||||
|                        'tooltip': 'start time [s] relative to P-onset for calculating CF for S-picking', | ||||
|                        'value': -1.0, | ||||
|                        'min': -np.inf, | ||||
|                        'max': np.inf, | ||||
|                        'namestring': 'S start'}, | ||||
| 
 | ||||
|             'sstop': {'type': float, | ||||
|                       'tooltip': 'end time [s] after P-onset for calculating CF for S-picking', | ||||
|                       'value': 10.0, | ||||
|                       'min': -np.inf, | ||||
|                       'max': np.inf, | ||||
|                       'namestring': 'S stop'}, | ||||
| 
 | ||||
|             'bpz1': {'type': (float, float), | ||||
|                      'tooltip': 'lower/upper corner freq. of first band pass filter Z-comp. [Hz]', | ||||
|                      'value': (2, 20), | ||||
|                      'min': (0., 0.), | ||||
|                      'max': (np.inf, np.inf), | ||||
|                      '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), | ||||
|                      'min': (0., 0.), | ||||
|                      'max': (np.inf, np.inf), | ||||
|                      'namestring': ('Z-bandpass 2', 'Lower', 'Upper')}, | ||||
| 
 | ||||
|             'bph1': {'type': (float, float), | ||||
|                      'tooltip': 'lower/upper corner freq. of first band pass filter H-comp. [Hz]', | ||||
|                      'value': (2, 15), | ||||
|                      'min': (0., 0.), | ||||
|                      'max': (np.inf, np.inf), | ||||
|                      '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), | ||||
|                      'min': (0., 0.), | ||||
|                      'max': (np.inf, np.inf), | ||||
|                      'namestring': ('H-bandpass 2', 'Lower', 'Upper')}, | ||||
| 
 | ||||
|             'algoP': {'type': str, | ||||
| @ -136,76 +161,106 @@ defaults = {'rootpath': {'type': str, | ||||
|             'tlta': {'type': float, | ||||
|                      'tooltip': 'for HOS-/AR-AIC-picker, length of LTA window [s]', | ||||
|                      'value': 7.0, | ||||
|                      'min': 0., | ||||
|                      'max': np.inf, | ||||
|                      'namestring': 'LTA window'}, | ||||
| 
 | ||||
|             'hosorder': {'type': int, | ||||
|                          'tooltip': 'for HOS-picker, order of Higher Order Statistics', | ||||
|                          'value': 4, | ||||
|                          'min': 0, | ||||
|                          'max': np.inf, | ||||
|                          'namestring': 'HOS order'}, | ||||
| 
 | ||||
|             'Parorder': {'type': int, | ||||
|                          'tooltip': 'for AR-picker, order of AR process of Z-component', | ||||
|                          'value': 2, | ||||
|                          'min': 0, | ||||
|                          'max': np.inf, | ||||
|                          '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, | ||||
|                        'min': 0., | ||||
|                        'max': np.inf, | ||||
|                        '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, | ||||
|                         'min': 0., | ||||
|                         'max': np.inf, | ||||
|                         '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, | ||||
|                        'min': 0., | ||||
|                        'max': np.inf, | ||||
|                        '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, | ||||
|                         'min': 0., | ||||
|                         'max': np.inf, | ||||
|                         'namestring': 'AR pred. window Z 2'}, | ||||
| 
 | ||||
|             'addnoise': {'type': float, | ||||
|                          'tooltip': 'add noise to seismogram for stable AR prediction', | ||||
|                          'value': 0.001, | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          '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), | ||||
|                       'min': (0., 0., 0., 0.), | ||||
|                       'max': (np.inf, np.inf, np.inf, np.inf), | ||||
|                       '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, | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          '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, | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'Recal. window P'}, | ||||
| 
 | ||||
|             'aictsmooth': {'type': float, | ||||
|                            'tooltip': 'for HOS/AR, take average of samples for smoothing of AIC-function [s]', | ||||
|                            'value': 0.2, | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'AIC smooth P'}, | ||||
| 
 | ||||
|             'tsmoothP': {'type': float, | ||||
|                          'tooltip': 'for HOS/AR, take average of samples in this time window for smoothing CF [s]', | ||||
|                          'value': 0.1, | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          'namestring': 'CF smooth P'}, | ||||
| 
 | ||||
|             'ausP': {'type': float, | ||||
|                      'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (P)', | ||||
|                      'value': 0.001, | ||||
|                      'min': 0., | ||||
|                      'max': np.inf, | ||||
|                      'namestring': 'Artificial uplift P'}, | ||||
| 
 | ||||
|             'nfacP': {'type': float, | ||||
|                       'tooltip': 'for HOS/AR, noise factor for noise level determination (P)', | ||||
|                       'value': 1.3, | ||||
|                       'min': 0., | ||||
|                       'max': np.inf, | ||||
|                       'namestring': 'Noise factor P'}, | ||||
| 
 | ||||
|             'algoS': {'type': str, | ||||
| @ -216,61 +271,85 @@ defaults = {'rootpath': {'type': str, | ||||
|             'tdet1h': {'type': float, | ||||
|                        'tooltip': 'for HOS/AR, length of AR-determination window [s], H-components, 1st pick', | ||||
|                        'value': 0.8, | ||||
|                        'min': 0., | ||||
|                        'max': np.inf, | ||||
|                        '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, | ||||
|                         'min': 0., | ||||
|                         'max': np.inf, | ||||
|                         '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, | ||||
|                        'min': 0., | ||||
|                        'max': np.inf, | ||||
|                        '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, | ||||
|                         'min': 0., | ||||
|                         'max': np.inf, | ||||
|                         'namestring': 'AR pred. window H 2'}, | ||||
| 
 | ||||
|             'Sarorder': {'type': int, | ||||
|                          'tooltip': 'for AR-picker, order of AR process of H-components', | ||||
|                          'value': 4, | ||||
|                          'min': 0, | ||||
|                          'max': np.inf, | ||||
|                          'namestring': 'AR order S'}, | ||||
| 
 | ||||
|             'Srecalcwin': {'type': float, | ||||
|                            'tooltip': 'for AR-picker, window length [s] for recalculation of CF (2nd pick) (H)', | ||||
|                            'value': 5.0, | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'Recal. window S'}, | ||||
| 
 | ||||
|             'pickwinS': {'type': float, | ||||
|                          'tooltip': 'for initial AIC pick, length of S-pick window [s]', | ||||
|                          'value': 3.0, | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          '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), | ||||
|                       'min': (0., 0., 0., 0.), | ||||
|                       'max': (np.inf, np.inf, np.inf, np.inf), | ||||
|                       'namestring': ('SNR windows S', 'Noise', 'Safety', 'Signal', 'Slope')}, | ||||
| 
 | ||||
|             'aictsmoothS': {'type': float, | ||||
|                             'tooltip': 'for AIC-picker, take average of samples in this time window for smoothing of AIC-function [s]', | ||||
|                             'value': 0.5, | ||||
|                             'min': 0., | ||||
|                             'max': np.inf, | ||||
|                             'namestring': 'AIC smooth S'}, | ||||
| 
 | ||||
|             'tsmoothS': {'type': float, | ||||
|                          'tooltip': 'for AR-picker, take average of samples for smoothing CF [s] (S)', | ||||
|                          'value': 0.7, | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          'namestring': 'CF smooth S'}, | ||||
| 
 | ||||
|             'ausS': {'type': float, | ||||
|                      'tooltip': 'for HOS/AR, artificial uplift of samples (aus) of CF (S)', | ||||
|                      'value': 0.9, | ||||
|                      'min': 0., | ||||
|                      'max': np.inf, | ||||
|                      'namestring': 'Artificial uplift S'}, | ||||
| 
 | ||||
|             'nfacS': {'type': float, | ||||
|                       'tooltip': 'for AR-picker, noise factor for noise level determination (S)', | ||||
|                       'value': 1.5, | ||||
|                       'min': 0., | ||||
|                       'max': np.inf, | ||||
|                       'namestring': 'Noise factor S'}, | ||||
| 
 | ||||
|             'minfmweight': {'type': int, | ||||
| @ -281,103 +360,143 @@ defaults = {'rootpath': {'type': str, | ||||
|             'minFMSNR': {'type': float, | ||||
|                          'tooltip': 'miniumum required SNR for first-motion determination', | ||||
|                          'value': 2., | ||||
|                          'min': 0., | ||||
|                          'max': np.inf, | ||||
|                          'namestring': 'Min SNR'}, | ||||
| 
 | ||||
|             'fmpickwin': {'type': float, | ||||
|                           'tooltip': 'pick window [s] around P onset for calculating zero crossings', | ||||
|                           'value': 0.2, | ||||
|                           'min': 0., | ||||
|                           'max': np.inf, | ||||
|                           '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), | ||||
|                             'min': (0., 0., 0., 0.), | ||||
|                             'max': (np.inf, np.inf, np.inf, np.inf), | ||||
|                             '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), | ||||
|                             'min': (0., 0., 0., 0.), | ||||
|                             'max': (np.inf, np.inf, np.inf, np.inf), | ||||
|                             '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, | ||||
|                              'min': 0., | ||||
|                              'max': np.inf, | ||||
|                              'namestring': 'Min. slope P'}, | ||||
| 
 | ||||
|             'minAICPSNR': {'type': float, | ||||
|                            'tooltip': 'below this SNR the initial P pick is rejected', | ||||
|                            'value': 1.1, | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'Min. SNR P'}, | ||||
| 
 | ||||
|             'minAICSslope': {'type': float, | ||||
|                              'tooltip': 'below this slope [counts/s] the initial S pick is rejected', | ||||
|                              'value': 1., | ||||
|                              'min': 0., | ||||
|                              'max': np.inf, | ||||
|                              'namestring': 'Min. slope S'}, | ||||
| 
 | ||||
|             'minAICSSNR': {'type': float, | ||||
|                            'tooltip': 'below this SNR the initial S pick is rejected', | ||||
|                            'value': 1.5, | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'Min. SNR S'}, | ||||
| 
 | ||||
|             'minsiglength': {'type': float, | ||||
|                              'tooltip': 'length of signal part for which amplitudes must exceed noiselevel [s]', | ||||
|                              'value': 1., | ||||
|                              'min': 0., | ||||
|                              'max': np.inf, | ||||
|                              'namestring': 'Min. signal length'}, | ||||
| 
 | ||||
|             'noisefactor': {'type': float, | ||||
|                             'tooltip': 'noiselevel*noisefactor=threshold', | ||||
|                             'value': 1.0, | ||||
|                             'min': 0., | ||||
|                             'max': np.inf, | ||||
|                             'namestring': 'Noise factor'}, | ||||
| 
 | ||||
|             'minpercent': {'type': float, | ||||
|                            'tooltip': 'required percentage of amplitudes exceeding threshold', | ||||
|                            'value': 10., | ||||
|                            'min': 0., | ||||
|                            'max': np.inf, | ||||
|                            'namestring': 'Min amplitude [%]'}, | ||||
| 
 | ||||
|             'zfac': {'type': float, | ||||
|                      'tooltip': 'P-amplitude must exceed at least zfac times RMS-S amplitude', | ||||
|                      'value': 1.5, | ||||
|                      'min': 0., | ||||
|                      'max': np.inf, | ||||
|                      'namestring': 'Z factor'}, | ||||
| 
 | ||||
|             'mdttolerance': {'type': float, | ||||
|                              'tooltip': 'maximum allowed deviation of P picks from median [s]', | ||||
|                              'value': 6.0, | ||||
|                              'min': 0., | ||||
|                              'max': np.inf, | ||||
|                              'namestring': 'Median tolerance'}, | ||||
| 
 | ||||
|             'wdttolerance': {'type': float, | ||||
|                              'tooltip': 'maximum allowed deviation from Wadati-diagram', | ||||
|                              'value': 1.0, | ||||
|                              'min': 0., | ||||
|                              'max': np.inf, | ||||
|                              'namestring': 'Wadati tolerance'}, | ||||
| 
 | ||||
|             'jackfactor': {'type': float, | ||||
|                              'tooltip': 'pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor', | ||||
|                              'value': 5.0, | ||||
|                              'namestring': 'Jackknife safety factor'}, | ||||
|                             'tooltip': 'pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor', | ||||
|                             'value': 5.0, | ||||
|                             'min': 0., | ||||
|                             'max': np.inf, | ||||
|                             'namestring': 'Jackknife safety factor'}, | ||||
| 
 | ||||
|             '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.), | ||||
|                           'min': (0., 0., 0.), | ||||
|                           'max': (np.inf, np.inf, np.inf), | ||||
|                           '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.), | ||||
|                            'min': (0., 0.), | ||||
|                            'max': (np.inf, np.inf), | ||||
|                            'namestring': ('Local mag. scaling', '', '')}, | ||||
| 
 | ||||
|             'minfreq': {'type': (float, float), | ||||
|                         'tooltip': 'Lower filter frequency [P, S]', | ||||
|                         'value': (1.0, 1.0), | ||||
|                         'min': (0., 0.), | ||||
|                         'max': (np.inf, np.inf), | ||||
|                         'namestring': ('Lower freq.', 'P', 'S')}, | ||||
| 
 | ||||
|             'maxfreq': {'type': (float, float), | ||||
|                         'tooltip': 'Upper filter frequency [P, S]', | ||||
|                         'value': (10.0, 10.0), | ||||
|                         'min': (0., 0.), | ||||
|                         'max': (np.inf, np.inf), | ||||
|                         'namestring': ('Upper freq.', 'P', 'S')}, | ||||
| 
 | ||||
|             'filter_order': {'type': (int, int), | ||||
|                              'tooltip': 'filter order [P, S]', | ||||
|                              'value': (2, 2), | ||||
|                              'min': (0, 0), | ||||
|                              'max': (np.inf, np.inf), | ||||
|                              'namestring': ('Order', 'P', 'S')}, | ||||
| 
 | ||||
|             'filter_type': {'type': (str, str), | ||||
|  | ||||
| @ -70,6 +70,7 @@ class PylotParameter(object): | ||||
| 
 | ||||
|     # Set default values of parameter names | ||||
|     def __init_default_paras(self): | ||||
|         """set default values of parameter names""" | ||||
|         parameters = default_parameters.defaults | ||||
|         self.__defaults = parameters | ||||
| 
 | ||||
| @ -92,6 +93,11 @@ class PylotParameter(object): | ||||
|             return None | ||||
| 
 | ||||
|     def __setitem__(self, key, value): | ||||
|         try: | ||||
|             value = self.check_range(value, self.__defaults[key]['max'], self.__defaults[key]['min']) | ||||
|         except KeyError: | ||||
|             # no min/max values in defaults | ||||
|             pass | ||||
|         self.__parameter[key] = value | ||||
| 
 | ||||
|     def __delitem__(self, key): | ||||
| @ -104,15 +110,34 @@ class PylotParameter(object): | ||||
|         return len(self.__parameter.keys()) | ||||
| 
 | ||||
|     def iteritems(self): | ||||
|         """ | ||||
|         Iterate over parameters | ||||
|         :return: key, value tupel | ||||
|         :rtype: | ||||
|         """ | ||||
|         for key, value in self.__parameter.items(): | ||||
|             yield key, value | ||||
| 
 | ||||
|     def hasParam(self, parameter): | ||||
|         """ | ||||
|         Check if parameter is in keys | ||||
|         :param parameter: parameter to look for in keys | ||||
|         :type parameter: | ||||
|         :return: | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         if parameter in self.__parameter.keys(): | ||||
|             return True | ||||
|         return False | ||||
| 
 | ||||
|     def get(self, *args): | ||||
|         """ | ||||
|         Get first available parameter in args | ||||
|         :param args: | ||||
|         :type args: | ||||
|         :return: | ||||
|         :rtype: | ||||
|         """ | ||||
|         try: | ||||
|             for param in args: | ||||
|                 try: | ||||
| @ -128,15 +153,35 @@ class PylotParameter(object): | ||||
|                 raise ParameterError(e) | ||||
| 
 | ||||
|     def get_defaults(self): | ||||
|         """ | ||||
|         get default parameters | ||||
|         :return: | ||||
|         :rtype: dict | ||||
|         """ | ||||
|         return self.__defaults | ||||
| 
 | ||||
|     def get_main_para_names(self): | ||||
|         """ | ||||
|         Get main parameter names | ||||
|         :return: list of keys available in parameters | ||||
|         :rtype: | ||||
|         """ | ||||
|         return self._settings_main | ||||
| 
 | ||||
|     def get_special_para_names(self): | ||||
|         """ | ||||
|         Get pick parameter names | ||||
|         :return: list of keys available in parameters | ||||
|         :rtype: | ||||
|         """ | ||||
|         return self._settings_special_pick | ||||
| 
 | ||||
|     def get_all_para_names(self): | ||||
|         """ | ||||
|         Get all parameter names | ||||
|         :return: | ||||
|         :rtype: list | ||||
|         """ | ||||
|         all_names = [] | ||||
|         all_names += self.get_main_para_names()['dirs'] | ||||
|         all_names += self.get_main_para_names()['nlloc'] | ||||
| @ -150,7 +195,43 @@ class PylotParameter(object): | ||||
|         all_names += self.get_special_para_names()['quality'] | ||||
|         return all_names | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def check_range(value, max_value, min_value): | ||||
|         """ | ||||
|         Check if value is within the min/max values defined in default_parameters. Works for tuple and scalar values. | ||||
|         :param value: Value to be checked against min/max range | ||||
|         :param max_value: Maximum allowed value, tuple or scalar | ||||
|         :param min_value: Minimum allowed value, tuple or scalar | ||||
|         :return: value tuple/scalar clamped to the valid range | ||||
| 
 | ||||
|         >>> checkRange(-5, 10, 0) | ||||
|          0 | ||||
|          >>> checkRange((-5., 100.), (10., 10.), (0., 0.)) | ||||
|          (0.0, 10.0) | ||||
|         """ | ||||
|         try: | ||||
|             # Try handling tuples by comparing their elements | ||||
|             comparisons = [(a > b) for a, b in zip(value, max_value)] | ||||
|             if True in comparisons: | ||||
|                 value = tuple(max_value[i] if comp else value[i] for i, comp in enumerate(comparisons)) | ||||
|             comparisons = [(a < b) for a, b in zip(value, min_value)] | ||||
|             if True in comparisons: | ||||
|                 value = tuple(min_value[i] if comp else value[i] for i, comp in enumerate(comparisons)) | ||||
|         except TypeError: | ||||
|             value = max(min_value, min(max_value, value)) | ||||
|         return value | ||||
| 
 | ||||
|     def checkValue(self, param, value): | ||||
|         """ | ||||
|         Check type of value against expected type of param. | ||||
|         Print warning message if type check fails | ||||
|         :param param: | ||||
|         :type param: | ||||
|         :param value: | ||||
|         :type value: | ||||
|         :return: | ||||
|         :rtype: | ||||
|         """ | ||||
|         is_type = type(value) | ||||
|         expect_type = self.get_defaults()[param]['type'] | ||||
|         if not is_type == expect_type and not is_type == tuple: | ||||
| @ -159,9 +240,25 @@ class PylotParameter(object): | ||||
|             print(Warning(message)) | ||||
| 
 | ||||
|     def setParamKV(self, param, value): | ||||
|         """ | ||||
|         set parameter param to value | ||||
|         :param param: | ||||
|         :type param: | ||||
|         :param value: | ||||
|         :type value: | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.__setitem__(param, value) | ||||
| 
 | ||||
|     def setParam(self, **kwargs): | ||||
|         """ | ||||
|         Set multiple parameters | ||||
|         :param kwargs: | ||||
|         :type kwargs: | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         for key in kwargs: | ||||
|             self.__setitem__(key, kwargs[key]) | ||||
| 
 | ||||
| @ -170,11 +267,23 @@ class PylotParameter(object): | ||||
|         print('ParameterError:\n non-existent parameter %s' % errmsg) | ||||
| 
 | ||||
|     def reset_defaults(self): | ||||
|         """ | ||||
|         Reset current parameters to default parameters | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         defaults = self.get_defaults() | ||||
|         for param in defaults: | ||||
|             self.setParamKV(param, defaults[param]['value']) | ||||
| 
 | ||||
|     def from_file(self, fnin=None): | ||||
|         """ | ||||
|         read parameters from file and set values to read values | ||||
|         :param fnin: filename | ||||
|         :type fnin: | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         if not fnin: | ||||
|             if self.__filename is not None: | ||||
|                 fnin = self.__filename | ||||
| @ -221,6 +330,13 @@ class PylotParameter(object): | ||||
|         self.__parameter = self._parFileCont | ||||
| 
 | ||||
|     def export2File(self, fnout): | ||||
|         """ | ||||
|         Export parameters to file | ||||
|         :param fnout: Filename of export file | ||||
|         :type fnout: str | ||||
|         :return: | ||||
|         :rtype: | ||||
|         """ | ||||
|         fid_out = open(fnout, 'w') | ||||
|         lines = [] | ||||
|         # for key, value in self.iteritems(): | ||||
| @ -257,6 +373,19 @@ class PylotParameter(object): | ||||
|                            'quality assessment', None) | ||||
| 
 | ||||
|     def write_section(self, fid, names, title, separator): | ||||
|         """ | ||||
|         write a section of parameters to file | ||||
|         :param fid: File object to write to | ||||
|         :type fid: | ||||
|         :param names: which parameter names to write to file | ||||
|         :type names: | ||||
|         :param title: title of section | ||||
|         :type title: str | ||||
|         :param separator: section separator, written at start of section | ||||
|         :type separator: str | ||||
|         :return: | ||||
|         :rtype: | ||||
|         """ | ||||
|         if separator: | ||||
|             fid.write(separator) | ||||
|         fid.write('#{}#\n'.format(title)) | ||||
| @ -341,7 +470,9 @@ class FilterOptions(object): | ||||
| 
 | ||||
|     def parseFilterOptions(self): | ||||
|         if self: | ||||
|             robject = {'type': self.getFilterType(), 'corners': self.getOrder()} | ||||
|             robject = {'type': self.getFilterType(), | ||||
|                        'corners': self.getOrder(), | ||||
|                        'zerophase': False} | ||||
|             if not self.getFilterType() in ['highpass', 'lowpass']: | ||||
|                 robject['freqmin'] = self.getFreq()[0] | ||||
|                 robject['freqmax'] = self.getFreq()[1] | ||||
|  | ||||
| @ -54,7 +54,7 @@ def create_arrival(pickresID, cinfo, phase, azimuth=None, dist=None): | ||||
| 
 | ||||
| def create_creation_info(agency_id=None, creation_time=None, author=None): | ||||
|     ''' | ||||
| 
 | ||||
|     get creation info of obspy event | ||||
|     :param agency_id: | ||||
|     :param creation_time: | ||||
|     :param author: | ||||
| @ -197,9 +197,9 @@ def create_pick(origintime, picknum, picktime, eventnum, cinfo, phase, station, | ||||
| 
 | ||||
| def create_resourceID(timetohash, restype, authority_id=None, hrstr=None): | ||||
|     ''' | ||||
| 
 | ||||
|     :param timetohash: | ||||
|     :type timetohash | ||||
|     create unique resource id | ||||
|     :param timetohash: event origin time to hash | ||||
|     :type timetohash: class: `~obspy.core.utcdatetime.UTCDateTime` object | ||||
|     :param restype: type of the resource, e.g. 'orig', 'earthquake' ... | ||||
|     :type restype: str | ||||
|     :param authority_id: name of the institution carrying out the processing | ||||
|  | ||||
| @ -16,7 +16,8 @@ from pylot.core.io.inputs import PylotParameter | ||||
| from pylot.core.io.location import create_event, \ | ||||
|     create_magnitude | ||||
| from pylot.core.pick.utils import select_for_phase | ||||
| from pylot.core.util.utils import getOwner, full_range, four_digits | ||||
| from pylot.core.util.utils import getOwner, full_range, four_digits, transformFilteroptions2String, \ | ||||
|     transformFilterString4Export, backtransformFilterString | ||||
| 
 | ||||
| 
 | ||||
| def add_amplitudes(event, amplitudes): | ||||
| @ -118,6 +119,13 @@ def readPILOTEvent(phasfn=None, locfn=None, authority_id='RUB', **kwargs): | ||||
| 
 | ||||
| 
 | ||||
| def picksdict_from_pilot(fn): | ||||
|     """ | ||||
|     Create pick dictionary from matlab file | ||||
|     :param fn: matlab file | ||||
|     :type fn: | ||||
|     :return: pick dictionary | ||||
|     :rtype: dict | ||||
|     """ | ||||
|     from pylot.core.util.defaults import TIMEERROR_DEFAULTS | ||||
|     picks = dict() | ||||
|     phases_pilot = sio.loadmat(fn) | ||||
| @ -147,6 +155,13 @@ def picksdict_from_pilot(fn): | ||||
| 
 | ||||
| 
 | ||||
| def stations_from_pilot(stat_array): | ||||
|     """ | ||||
|     Create stations list from pilot station array | ||||
|     :param stat_array: | ||||
|     :type stat_array: | ||||
|     :return: | ||||
|     :rtype: list | ||||
|     """ | ||||
|     stations = list() | ||||
|     cur_stat = None | ||||
|     for stat in stat_array: | ||||
| @ -164,6 +179,13 @@ def stations_from_pilot(stat_array): | ||||
| 
 | ||||
| 
 | ||||
| def convert_pilot_times(time_array): | ||||
|     """ | ||||
|     Convert pilot times to UTCDateTimes | ||||
|     :param time_array: pilot times | ||||
|     :type time_array: | ||||
|     :return: | ||||
|     :rtype: | ||||
|     """ | ||||
|     times = [int(time) for time in time_array] | ||||
|     microseconds = int((time_array[-1] - times[-1]) * 1e6) | ||||
|     times.append(microseconds) | ||||
| @ -171,6 +193,13 @@ def convert_pilot_times(time_array): | ||||
| 
 | ||||
| 
 | ||||
| def picksdict_from_obs(fn): | ||||
|     """ | ||||
|     create pick dictionary from obs file | ||||
|     :param fn: filename | ||||
|     :type fn: | ||||
|     :return: | ||||
|     :rtype: | ||||
|     """ | ||||
|     picks = dict() | ||||
|     station_name = str() | ||||
|     for line in open(fn, 'r'): | ||||
| @ -207,6 +236,10 @@ def picksdict_from_picks(evt): | ||||
|         network = pick.waveform_id.network_code | ||||
|         mpp = pick.time | ||||
|         spe = pick.time_errors.uncertainty | ||||
|         if pick.filter_id: | ||||
|             filter_id = backtransformFilterString(str(pick.filter_id.id)) | ||||
|         else: | ||||
|             filter_id = None | ||||
|         try: | ||||
|             picker = str(pick.method_id) | ||||
|             if picker.startswith('smi:local/'): | ||||
| @ -222,10 +255,15 @@ def picksdict_from_picks(evt): | ||||
|             lpp = mpp + pick.time_errors.upper_uncertainty | ||||
|             epp = mpp - pick.time_errors.lower_uncertainty | ||||
|         except TypeError as e: | ||||
|             msg = e + ',\n falling back to symmetric uncertainties' | ||||
|             if not spe: | ||||
|                 msg = 'No uncertainties found for pick: {}. Uncertainty set to 0'.format(pick) | ||||
|                 lpp = mpp | ||||
|                 epp = mpp | ||||
|             else: | ||||
|                 msg = str(e) + ',\n falling back to symmetric uncertainties' | ||||
|                 lpp = mpp + spe | ||||
|                 epp = mpp - spe | ||||
|             warnings.warn(msg) | ||||
|             lpp = mpp + spe | ||||
|             epp = mpp - spe | ||||
|         phase['mpp'] = mpp | ||||
|         phase['epp'] = epp | ||||
|         phase['lpp'] = lpp | ||||
| @ -233,6 +271,7 @@ def picksdict_from_picks(evt): | ||||
|         phase['channel'] = channel | ||||
|         phase['network'] = network | ||||
|         phase['picker'] = picker | ||||
|         phase['filter_id'] = filter_id if filter_id is not None else '' | ||||
| 
 | ||||
|         onsets[pick.phase_hint] = phase.copy() | ||||
|         picksdict[picker][station] = onsets.copy() | ||||
| @ -240,6 +279,16 @@ def picksdict_from_picks(evt): | ||||
| 
 | ||||
| 
 | ||||
| def picks_from_picksdict(picks, creation_info=None): | ||||
|     """ | ||||
|     Create a list of picks out of a pick dictionary | ||||
|     :param picks: pick dictionary | ||||
|     :type picks: dict | ||||
|     :param creation_info: obspy creation information to apply to picks | ||||
|     :type creation_info: | ||||
|     :param creation_info: obspy creation information to apply to picks | ||||
|     :return: list of picks | ||||
|     :rtype: list | ||||
|     """ | ||||
|     picks_list = list() | ||||
|     for station, onsets in picks.items(): | ||||
|         for label, phase in onsets.items(): | ||||
| @ -274,6 +323,13 @@ def picks_from_picksdict(picks, creation_info=None): | ||||
|             pick.waveform_id = ope.WaveformStreamID(station_code=station, | ||||
|                                                     channel_code=ccode, | ||||
|                                                     network_code=ncode) | ||||
|             try: | ||||
|                 filter_id = phase['filteroptions'] | ||||
|                 filter_id = transformFilterString4Export(filter_id) | ||||
|             except KeyError as e: | ||||
|                 warnings.warn(e.message, RuntimeWarning) | ||||
|                 filter_id = '' | ||||
|             pick.filter_id = filter_id | ||||
|             try: | ||||
|                 polarity = phase['fm'] | ||||
|                 if polarity == 'U' or '+': | ||||
| @ -290,7 +346,6 @@ def picks_from_picksdict(picks, creation_info=None): | ||||
|             picks_list.append(pick) | ||||
|     return picks_list | ||||
| 
 | ||||
| 
 | ||||
| def reassess_pilot_db(root_dir, db_dir, out_dir=None, fn_param=None, verbosity=0): | ||||
|     import glob | ||||
| 
 | ||||
| @ -410,25 +465,24 @@ def writephases(arrivals, fformat, filename, parameter=None, eventinfo=None): | ||||
| 
 | ||||
|     HYPO71, NLLoc, VELEST, HYPOSAT, and hypoDD | ||||
| 
 | ||||
|     :param: arrivals | ||||
|     :type: dictionary containing all phase information including | ||||
|            station ID, phase, first motion, weight (uncertainty), | ||||
|            .... | ||||
|     :param arrivals:dictionary containing all phase information including | ||||
|      station ID, phase, first motion, weight (uncertainty), ... | ||||
|     :type arrivals: dict | ||||
| 
 | ||||
|     :param: fformat | ||||
|     :type:  string, chosen file format (location routine), | ||||
|             choose between NLLoc, HYPO71, HYPOSAT, VELEST, | ||||
|             HYPOINVERSE, and hypoDD | ||||
|     :param fformat: chosen file format (location routine), | ||||
|     choose between NLLoc, HYPO71, HYPOSAT, VELEST, | ||||
|     HYPOINVERSE, and hypoDD | ||||
|     :type fformat: str | ||||
| 
 | ||||
|     :param: filename, full path and name of phase file | ||||
|     :type:  string | ||||
|     :param filename: full path and name of phase file | ||||
|     :type filename:  string | ||||
| 
 | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
| 
 | ||||
|     :param: eventinfo, optional, needed for VELEST-cnv file  | ||||
|     :param eventinfo: optional, needed for VELEST-cnv file | ||||
|             and FOCMEC- and HASH-input files  | ||||
|     :type:  `obspy.core.event.Event` object | ||||
|     :type eventinfo: `obspy.core.event.Event` object | ||||
|     """ | ||||
| 
 | ||||
|     if fformat == 'NLLoc': | ||||
| @ -874,10 +928,20 @@ def merge_picks(event, picks): | ||||
| 
 | ||||
| def getQualitiesfromxml(xmlnames, ErrorsP, ErrorsS, plotflag=1): | ||||
|     """ | ||||
|    Script to get onset uncertainties from Quakeml.xml files created by PyLoT. | ||||
|     Script to get onset uncertainties from Quakeml.xml files created by PyLoT. | ||||
|    Uncertainties are tranformed into quality classes and visualized via histogram if desired. | ||||
|    Ludger Küperkoch, BESTEC GmbH, 07/2017 | ||||
|    """ | ||||
|     :param xmlnames: list of xml obspy event files containing picks | ||||
|     :type xmlnames: list | ||||
|     :param ErrorsP: time errors of P waves for the four discrete quality classes | ||||
|     :type ErrorsP: | ||||
|     :param ErrorsS: time errors of S waves for the four discrete quality classes | ||||
|     :type ErrorsS: | ||||
|     :param plotflag: | ||||
|     :type plotflag: | ||||
|     :return: | ||||
|     :rtype: | ||||
|     """ | ||||
| 
 | ||||
|     from pylot.core.pick.utils import getQualityFromUncertainty | ||||
|     from pylot.core.util.utils import loopIdentifyPhase, identifyPhase | ||||
|  | ||||
| @ -18,11 +18,11 @@ def export(picks, fnout, parameter, eventinfo): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|      | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
| 
 | ||||
|     :param: eventinfo, source information needed for focmec format | ||||
|     :type:  list object | ||||
|     :param eventinfo: source information needed for focmec format | ||||
|     :type eventinfo:  list object | ||||
|     ''' | ||||
|     # write phases to FOCMEC-phase file | ||||
|     writephases(picks, 'FOCMEC', fnout, parameter, eventinfo) | ||||
|  | ||||
| @ -18,11 +18,11 @@ def export(picks, fnout, parameter, eventinfo): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|      | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
| 
 | ||||
|     :param: eventinfo, source information needed for HASH format | ||||
|     :type:  list object | ||||
|     :param eventinfo: source information needed for HASH format | ||||
|     :type eventinfo:  list object | ||||
|     ''' | ||||
|     # write phases to HASH-phase file | ||||
|     writephases(picks, 'HASH', fnout, parameter, eventinfo) | ||||
|  | ||||
| @ -18,8 +18,8 @@ def export(picks, fnout, parameter): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
| 
 | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
|     ''' | ||||
|     # write phases to HYPO71-phase file | ||||
|     writephases(picks, 'HYPO71', fnout, parameter) | ||||
|  | ||||
| @ -18,11 +18,11 @@ def export(picks, fnout, parameter, eventinfo): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|      | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
| 
 | ||||
|     :param: eventinfo, source information needed for hypoDD format | ||||
|     :type:  list object | ||||
|     :param eventinfo: source information needed for hypoDD format | ||||
|     :type eventinfo:  list object | ||||
|     ''' | ||||
|     # write phases to hypoDD-phase file | ||||
|     writephases(picks, 'hypoDD', fnout, parameter, eventinfo) | ||||
|  | ||||
| @ -18,8 +18,8 @@ def export(picks, fnout, parameter): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|      | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
|     ''' | ||||
|     # write phases to HYPOSAT-phase file | ||||
|     writephases(picks, 'HYPOSAT', fnout, parameter) | ||||
|  | ||||
| @ -28,8 +28,8 @@ def export(picks, fnout, parameter): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|   | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
|     ''' | ||||
|     # write phases to NLLoc-phase file | ||||
|     writephases(picks, 'NLLoc', fnout, parameter) | ||||
| @ -38,19 +38,19 @@ def export(picks, fnout, parameter): | ||||
| def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn): | ||||
|     ''' | ||||
|     :param ctrfn: name of NLLoc-control file | ||||
|     :type: str | ||||
|     :type ctrfn: str | ||||
| 
 | ||||
|     :param root: root path to NLLoc working directory | ||||
|     :type: str | ||||
|     :type root: str | ||||
| 
 | ||||
|     :param nllocoutn: name of NLLoc-location output file | ||||
|     :type: str | ||||
|     :type nllocoutn: str | ||||
| 
 | ||||
|     :param phasefn: name of NLLoc-input phase file | ||||
|     :type: str | ||||
|     :type phasefn: str | ||||
| 
 | ||||
|     :param tttn: pattern of precalculated NLLoc traveltime tables | ||||
|     :type: str | ||||
|     :type tttn: str | ||||
|     ''' | ||||
|     # For locating the event the NLLoc-control file has to be modified! | ||||
|     # create comment line for NLLoc-control file NLLoc-output file | ||||
| @ -75,9 +75,9 @@ def modify_inputs(ctrfn, root, nllocoutn, phasefn, tttn): | ||||
| 
 | ||||
| def locate(fnin, infile=None): | ||||
|     """ | ||||
|     takes an external program name | ||||
|     :param fnin: | ||||
|     :return: | ||||
|     takes an external program name and tries to run it | ||||
|     :param fnin: external program name | ||||
|     :return: None | ||||
|     """ | ||||
| 
 | ||||
|     if infile is None: | ||||
|  | ||||
| @ -18,11 +18,11 @@ def export(picks, fnout, eventinfo, parameter=None): | ||||
|     :param fnout: complete path to the exporting obs file | ||||
|     :type fnout: str | ||||
|      | ||||
|     :param: eventinfo, source time needed for VELEST-cnv format | ||||
|     :type:  list object | ||||
|     :param eventinfo: source time needed for VELEST-cnv format | ||||
|     :type eventinfo:  list object | ||||
| 
 | ||||
|     :param: parameter, all input information | ||||
|     :type:  object | ||||
|     :param parameter: all input information | ||||
|     :type parameter:  object | ||||
|     ''' | ||||
|     # write phases to VELEST-phase file | ||||
|     writephases(picks, 'VELEST', fnout, parameter, eventinfo) | ||||
|  | ||||
| @ -155,7 +155,7 @@ def autopickstation(wfstream, pickparam, verbose=False, | ||||
|     :type metadata: tuple (str, ~obspy.io.xseed.parser.Parser) | ||||
|     :param origin: list containing origin objects representing origins for all events | ||||
|     :type origin: list(~obspy.core.event.origin) | ||||
|     :return:     :dictionary containing P pick, S pick and station name | ||||
|     :return: dictionary containing P pick, S pick and station name | ||||
|     :rtype: dict | ||||
|     """ | ||||
| 
 | ||||
|  | ||||
| @ -8,6 +8,13 @@ except: | ||||
| 
 | ||||
| 
 | ||||
| def checkurl(url='https://ariadne.geophysik.ruhr-uni-bochum.de/trac/PyLoT/'): | ||||
|     """ | ||||
|     check if URL is available | ||||
|     :param url: url | ||||
|     :type url: str | ||||
|     :return: available: True/False | ||||
|     :rtype: bool | ||||
|     """ | ||||
|     try: | ||||
|         urlopen(url, timeout=1) | ||||
|         return True | ||||
|  | ||||
| @ -15,6 +15,11 @@ class Event(ObsPyEvent): | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self, path): | ||||
|         """ | ||||
|         Initialize event by event directory | ||||
|         :param path: path to event directory | ||||
|         :type path: str | ||||
|         """ | ||||
|         self.pylot_id = path.split('/')[-1] | ||||
|         # initialize super class | ||||
|         super(Event, self).__init__(resource_id=ResourceIdentifier('smi:local/' + self.pylot_id)) | ||||
| @ -30,10 +35,20 @@ class Event(ObsPyEvent): | ||||
|         self.get_notes() | ||||
| 
 | ||||
|     def get_notes_path(self): | ||||
|         """ | ||||
|         Notes files is freely editable by the user and can contain notes regarding the event | ||||
|         :return: path to notes file | ||||
|         :rtype: str | ||||
|         """ | ||||
|         notesfile = os.path.join(self.path, 'notes.txt') | ||||
|         return notesfile | ||||
| 
 | ||||
|     def get_notes(self): | ||||
|         """ | ||||
|         set self.note attribute to content of notes file | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         notesfile = self.get_notes_path() | ||||
|         if os.path.isfile(notesfile): | ||||
|             with open(notesfile) as infile: | ||||
| @ -48,34 +63,81 @@ class Event(ObsPyEvent): | ||||
|                     pass | ||||
| 
 | ||||
|     def addNotes(self, notes): | ||||
|         """ | ||||
|         Set new notes string | ||||
|         :param notes: notes to save in Event object | ||||
|         :type notes: str | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.notes = str(notes) | ||||
| 
 | ||||
|     def clearNotes(self): | ||||
|         """ | ||||
|         Clear event notes | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.notes = None | ||||
| 
 | ||||
|     def isRefEvent(self): | ||||
|         """ | ||||
|         Return reference event flag | ||||
|         :return: True if event is refence event | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         return self._refEvent | ||||
| 
 | ||||
|     def isTestEvent(self): | ||||
|         """ | ||||
|         Return test event flag | ||||
|         :return: True if event is test event | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         return self._testEvent | ||||
| 
 | ||||
|     def setRefEvent(self, bool): | ||||
|         """ | ||||
|         Set reference event flag | ||||
|         :param bool: new reference event flag | ||||
|         :type bool: bool | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self._refEvent = bool | ||||
|         if bool: self._testEvent = False | ||||
| 
 | ||||
|     def setTestEvent(self, bool): | ||||
|         """ | ||||
|         Set test event flag | ||||
|         :param bool: new test event flag | ||||
|         :type bool: bool | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self._testEvent = bool | ||||
|         if bool: self._refEvent = False | ||||
| 
 | ||||
|     def clearObsPyPicks(self, picktype): | ||||
|         """ | ||||
|         Remove picks of a certain type from event | ||||
|         :param picktype: type of picks to remove, 'auto' or 'manual' | ||||
|         :type picktype: str | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         for index, pick in reversed(list(enumerate(self.picks))): | ||||
|             if picktype in str(pick.method_id): | ||||
|                 self.picks.pop(index) | ||||
| 
 | ||||
|     def addPicks(self, picks): | ||||
|         ''' | ||||
|         """ | ||||
|         add pylot picks and overwrite existing ones | ||||
|         ''' | ||||
|         :param picks: picks to add to event in pick dictionary | ||||
|         :type picks: dict | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         for station in picks: | ||||
|             self.pylot_picks[station] = picks[station] | ||||
|         # add ObsPy picks (clear old manual and copy all new manual from pylot) | ||||
| @ -83,6 +145,13 @@ class Event(ObsPyEvent): | ||||
|         self.picks += picks_from_picksdict(self.pylot_picks) | ||||
| 
 | ||||
|     def addAutopicks(self, autopicks): | ||||
|         """ | ||||
|         Add automatic picks to event | ||||
|         :param autopicks: automatic picks to add to event | ||||
|         :type autopicks dict: | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         for station in autopicks: | ||||
|             self.pylot_autopicks[station] = autopicks[station] | ||||
|         # add ObsPy picks (clear old auto and copy all new auto from pylot) | ||||
| @ -90,6 +159,15 @@ class Event(ObsPyEvent): | ||||
|         self.picks += picks_from_picksdict(self.pylot_autopicks) | ||||
| 
 | ||||
|     def setPick(self, station, pick): | ||||
|         """ | ||||
|         Set pick for a station | ||||
|         :param station: station name | ||||
|         :type station: str | ||||
|         :param pick: | ||||
|         :type pick: dict | ||||
|         :return: | ||||
|         :rtype: | ||||
|         """ | ||||
|         if pick: | ||||
|             self.pylot_picks[station] = pick | ||||
|         else: | ||||
| @ -101,21 +179,46 @@ class Event(ObsPyEvent): | ||||
|         self.picks += picks_from_picksdict(self.pylot_picks) | ||||
| 
 | ||||
|     def setPicks(self, picks): | ||||
|         ''' | ||||
|         set pylot picks and delete and overwrite all existing | ||||
|         ''' | ||||
|         """ | ||||
|         Set pylot picks and delete and overwrite all existing | ||||
|         :param picks: new picks | ||||
|         :type picks: dict | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.pylot_picks = picks | ||||
|         self.clearObsPyPicks('manual') | ||||
|         self.picks += picks_from_picksdict(self.pylot_picks) | ||||
| 
 | ||||
|     def getPick(self, station): | ||||
|         """ | ||||
|         Get pick at station | ||||
|         :param station: station name | ||||
|         :type station: str | ||||
|         :return: pick dictionary of station | ||||
|         :rtype: dict | ||||
|         """ | ||||
|         if station in self.pylot_picks.keys(): | ||||
|             return self.pylot_picks[station] | ||||
| 
 | ||||
|     def getPicks(self): | ||||
|         """ | ||||
|         Return pylot picks | ||||
|         :return: | ||||
|         :rtype: dict | ||||
|         """ | ||||
|         return self.pylot_picks | ||||
| 
 | ||||
|     def setAutopick(self, station, pick): | ||||
|         """ | ||||
|         Set pick at station | ||||
|         :param station: station name | ||||
|         :type station: str | ||||
|         :param pick: | ||||
|         :type pick: dict | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         if pick: | ||||
|             self.pylot_autopicks[station] = pick | ||||
|         else: | ||||
| @ -127,25 +230,46 @@ class Event(ObsPyEvent): | ||||
|         self.picks += picks_from_picksdict(self.pylot_autopicks) | ||||
| 
 | ||||
|     def setAutopicks(self, picks): | ||||
|         ''' | ||||
|         set pylot picks and delete and overwrite all existing | ||||
|         ''' | ||||
|         """ | ||||
|         Set pylot picks and delete and overwrite all existing | ||||
|         :param picks:  new picks | ||||
|         :type picks: dict | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.pylot_autopicks = picks | ||||
|         self.clearObsPyPicks('auto') | ||||
|         self.picks += picks_from_picksdict(self.pylot_autopicks) | ||||
| 
 | ||||
|     def getAutopick(self, station): | ||||
|         """ | ||||
|         Return autopick at station | ||||
|         :param station: station name | ||||
|         :type station: str | ||||
|         :return: pick dictionary | ||||
|         :rtype: dict | ||||
|         """ | ||||
|         if station in self.pylot_autopicks.keys(): | ||||
|             return self.pylot_autopicks[station] | ||||
| 
 | ||||
|     def getAutopicks(self): | ||||
|         """ | ||||
|         Get autopicks of event | ||||
|         :return: dict containing automatic picks | ||||
|         :rtype: dict | ||||
|         """ | ||||
|         return self.pylot_autopicks | ||||
| 
 | ||||
|     def save(self, filename): | ||||
|         ''' | ||||
|         Save PyLoT Event to a file.  | ||||
|         """ | ||||
|         Save PyLoT Event to a file. | ||||
|         Can be loaded by using event.load(filename). | ||||
|         ''' | ||||
|         Uses pickling to save event object to file | ||||
|         :param filename: filename to save project under | ||||
|         :type filename: str | ||||
|         :return: | ||||
|         :rtype: None | ||||
|         """ | ||||
|         try: | ||||
|             import cPickle | ||||
|         except ImportError: | ||||
| @ -159,9 +283,13 @@ class Event(ObsPyEvent): | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def load(filename): | ||||
|         ''' | ||||
|         Load project from filename. | ||||
|         ''' | ||||
|         """ | ||||
|         Load project from filename | ||||
|         :param filename: to load event file | ||||
|         :type filename: str | ||||
|         :return: event loaded from file | ||||
|         :rtype: Event | ||||
|         """ | ||||
|         try: | ||||
|             import cPickle | ||||
|         except ImportError: | ||||
|  | ||||
| @ -24,7 +24,7 @@ class Thread(QThread): | ||||
|         if self.redirect_stdout: | ||||
|             sys.stdout = self | ||||
|         try: | ||||
|             if self.arg: | ||||
|             if self.arg is not None: | ||||
|                 self.data = self.func(self.arg) | ||||
|             else: | ||||
|                 self.data = self.func() | ||||
|  | ||||
| @ -13,7 +13,7 @@ from obspy.core import AttribDict | ||||
| from obspy.signal.rotate import rotate2zne | ||||
| from obspy.io.xseed.utils import SEEDParserException | ||||
| 
 | ||||
| from pylot.core.io.inputs import PylotParameter | ||||
| from pylot.core.io.inputs import PylotParameter, FilterOptions | ||||
| from pylot.styles import style_settings | ||||
| 
 | ||||
| from scipy.interpolate import splrep, splev | ||||
| @ -31,6 +31,15 @@ def _pickle_method(m): | ||||
|     else: | ||||
|         return getattr, (m.im_self, m.im_func.func_name) | ||||
| 
 | ||||
| def getAutoFilteroptions(phase, parameter): | ||||
|     filtername = {'P': 'bpz2', | ||||
|                   'S': 'bph2'} | ||||
|     if not phase in filtername.keys(): | ||||
|         print('autoPickParameter: No filter options for phase {}.'.format(phase)) | ||||
|         return | ||||
|     freqmin, freqmax = parameter.get(filtername[phase]) | ||||
|     filteroptions = FilterOptions(type='bandpass', freq=[freqmin, freqmax], order=4) # order=4 default from obspy | ||||
|     return filteroptions | ||||
| 
 | ||||
| def readDefaultFilterInformation(fname): | ||||
|     """ | ||||
| @ -327,9 +336,9 @@ def real_Bool(value): | ||||
|     :return: true boolean value | ||||
|     :rtype: bool | ||||
|     """ | ||||
|     if value == 'True': | ||||
|     if value in ['True', 'true']: | ||||
|         return True | ||||
|     elif value == 'False': | ||||
|     elif value in ['False', 'false']: | ||||
|         return False | ||||
|     else: | ||||
|         return value | ||||
| @ -391,6 +400,38 @@ def full_range(stream): | ||||
|     return min_start, max_end | ||||
| 
 | ||||
| 
 | ||||
| def transformFilteroptions2String(filtopts): | ||||
|     st = '' | ||||
|     if not filtopts: | ||||
|         return st | ||||
|     if 'type' in filtopts.keys(): | ||||
|         st += '{}'.format(filtopts['type']) | ||||
|         if 'freq' in filtopts.keys(): | ||||
|             st += ' | freq: {}'.format(filtopts['freq']) | ||||
|         elif 'freqmin' in filtopts.keys() and 'freqmax' in filtopts.keys(): | ||||
|             st += ' | freqmin: {} | freqmax: {}'.format(filtopts['freqmin'], filtopts['freqmax']) | ||||
|     for key, value in filtopts.items(): | ||||
|         if key in ['type', 'freq', 'freqmin', 'freqmax']: | ||||
|             continue | ||||
|         st += ' | {}: {}'.format(key, value) | ||||
|     return st | ||||
| 
 | ||||
| 
 | ||||
| def transformFilterString4Export(st): | ||||
|     st = st.replace('|', '//') | ||||
|     st = st.replace(':', '/') | ||||
|     st = st.replace(' ', '') | ||||
|     return st | ||||
| 
 | ||||
| 
 | ||||
| def backtransformFilterString(st): | ||||
|     st = st.split('smi:local/') | ||||
|     st = st[1] if len(st) > 1 else st[0] | ||||
|     st = st.replace('//', ' | ') | ||||
|     st = st.replace('/', ': ') | ||||
|     return st | ||||
| 
 | ||||
| 
 | ||||
| def getHash(time): | ||||
|     """ | ||||
|     takes a time object and returns the corresponding SHA1 hash of the formatted date string | ||||
| @ -945,7 +986,7 @@ def check4rotated(data, metadata=None, verbosity=1): | ||||
|                 dip = blockette_.dip | ||||
|                 azimut = blockette_.azimuth | ||||
|                 break | ||||
|             if dip is None or azimut is None: | ||||
|             if (dip is None or azimut is None) or (dip == 0 and azimut == 0): | ||||
|                 error_msg = 'Dip and azimuth not available for trace_id {}'.format(trace_id) | ||||
|                 raise ValueError(error_msg) | ||||
|             return dip, azimut | ||||
| @ -1111,6 +1152,9 @@ def loopIdentifyPhase(phase): | ||||
|     """ | ||||
|     from pylot.core.util.defaults import ALTSUFFIX | ||||
| 
 | ||||
|     if phase == None: | ||||
|         raise NameError('Can not identify phase that is None') | ||||
| 
 | ||||
|     phase_copy = phase | ||||
|     while not identifyPhase(phase_copy): | ||||
|         identified = False | ||||
| @ -1135,8 +1179,10 @@ def identifyPhase(phase): | ||||
|     :rtype: str or bool | ||||
|     """ | ||||
|     # common phase suffix for P and S | ||||
|     common_P = ['P', 'p'] | ||||
|     common_P = ['P', 'p', 'R'] | ||||
|     common_S = ['S', 's'] | ||||
|     if phase is None: | ||||
|         return False | ||||
|     if phase[-1] in common_P: | ||||
|         return 'P' | ||||
|     if phase[-1] in common_S: | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -124,7 +124,6 @@ color:rgba(0, 0, 0, 255); | ||||
| border-style: outset; | ||||
| border-width: 1px; | ||||
| border-color: rgba(100, 100, 120, 255); | ||||
| min-width: 6em; | ||||
| padding: 4px; | ||||
| padding-left:5px; | ||||
| padding-right:5px; | ||||
|  | ||||
| @ -123,7 +123,6 @@ color:rgba(255, 255, 255, 255); | ||||
| border-style: outset; | ||||
| border-width: 2px; | ||||
| border-color: rgba(50, 50, 60, 255); | ||||
| min-width: 6em; | ||||
| padding: 4px; | ||||
| padding-left:5px; | ||||
| padding-right:5px; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user