Merge branch 'export-and-save-picks' into develop
This commit is contained in:
		
						commit
						0b02e8c213
					
				
							
								
								
									
										35
									
								
								QtPyLoT.py
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								QtPyLoT.py
									
									
									
									
									
								
							| @ -23,7 +23,7 @@ https://www.iconfinder.com/iconsets/flavour | ||||
|     (http://www.gnu.org/copyleft/lesser.html) | ||||
| """ | ||||
| 
 | ||||
| import sys | ||||
| import os, sys | ||||
| import matplotlib | ||||
| 
 | ||||
| matplotlib.use('Qt4Agg') | ||||
| @ -64,7 +64,6 @@ class MainWindow(QMainWindow): | ||||
|         super(MainWindow, self).__init__(parent) | ||||
| 
 | ||||
|         self.createAction = createAction | ||||
|         self.dirty = False | ||||
|         settings = QSettings() | ||||
|         if settings.value("user/FullName", None) is None: | ||||
|             fulluser = QInputDialog.getText(self, "Enter Name:", "Full name") | ||||
| @ -102,8 +101,8 @@ class MainWindow(QMainWindow): | ||||
|             self.data = Data(self) | ||||
| 
 | ||||
|         # load and display waveform data | ||||
|         self.loadWaveformData() | ||||
|         self.dirty = False | ||||
|         self.loadWaveformData() | ||||
|         self.loadData() | ||||
|         self.updateFilterOptions() | ||||
| 
 | ||||
| @ -333,6 +332,10 @@ class MainWindow(QMainWindow): | ||||
|         self.fileMenu.addSeparator() | ||||
|         self.fileMenu.addAction(self.fileMenuActions[-1]) | ||||
| 
 | ||||
|     def getRoot(self): | ||||
|         settings = QSettings() | ||||
|         return settings.value("data/dataRoot") | ||||
| 
 | ||||
|     def loadData(self, fname=None): | ||||
|         if fname is None: | ||||
|             try: | ||||
| @ -390,18 +393,27 @@ class MainWindow(QMainWindow): | ||||
|             else: | ||||
|                 return | ||||
| 
 | ||||
|     def getEventFileName(self): | ||||
|         return self.getData().getEventFileName() | ||||
| 
 | ||||
|     def saveData(self): | ||||
|         settings = QSettings() | ||||
|         exform = settings.value('data/exportFormat', 'QUAKEML') | ||||
|         self.getData().applyEVTData(self.getPicks()) | ||||
|         try: | ||||
|             self.data.exportEvent(self.fname, exform) | ||||
|             self.getData().exportEvent(self.fname, exform) | ||||
|         except FormatError: | ||||
|             return False | ||||
|         except AttributeError, e: | ||||
|             print 'warning: {0}'.format(e) | ||||
|             fname = QFileDialog.getSaveFileName(self, 'Save event') | ||||
|             fname = fname[0] | ||||
|             self.getData().exportEvent(fname, exform) | ||||
|             directory = os.path.join(self.getRoot(), self.getEventFileName()) | ||||
|             file_filter = "Seismic observation files (*.cnv *.obs *.xml)" | ||||
|             fname = QFileDialog.getSaveFileName(self, 'Save event data ...', | ||||
|                                                 directory, file_filter) | ||||
|             fbasename, exform = os.path.splitext(fname[0]) | ||||
|             if not fbasename: | ||||
|                 return False | ||||
|             self.getData().exportEvent(fbasename, exform) | ||||
|         return True | ||||
| 
 | ||||
|     def getComponent(self): | ||||
| @ -455,7 +467,7 @@ class MainWindow(QMainWindow): | ||||
| 
 | ||||
|     def loadWaveformData(self): | ||||
|         if self.fnames and self.okToContinue(): | ||||
|             self.dirty = True | ||||
|             self.setDirty(True) | ||||
|             self.data.setWFData(self.fnames) | ||||
|         elif self.fnames is None and self.okToContinue(): | ||||
|             self.data.setWFData(self.getWFFnames()) | ||||
| @ -585,6 +597,7 @@ class MainWindow(QMainWindow): | ||||
|                           station=station, | ||||
|                           picks=self.getPicksOnStation(station)) | ||||
|         if pickDlg.exec_(): | ||||
|             self.setDirty(True) | ||||
|             self.updateStatus('picks accepted ({0})'.format(station)) | ||||
|             self.addPicks(station, pickDlg.getPicks()) | ||||
|             self.drawPicks(station) | ||||
| @ -593,6 +606,7 @@ class MainWindow(QMainWindow): | ||||
| 
 | ||||
|     def autoPick(self): | ||||
|         list = QListWidget() | ||||
|         self.setDirty(True) | ||||
|         logDockWidget = QDockWidget("AutoPickLog", self) | ||||
|         logDockWidget.setObjectName("LogDockWidget") | ||||
|         logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea) | ||||
| @ -700,11 +714,14 @@ class MainWindow(QMainWindow): | ||||
|                 cinfo = createCreationInfo(agency_id=self.agency) | ||||
|                 event = createEvent(evtpar['origintime'], cinfo) | ||||
|                 self.data = Data(self, evtdata=event) | ||||
|                 self.dirty = True | ||||
|                 self.setDirty(True) | ||||
| 
 | ||||
|     def draw(self): | ||||
|         self.getPlotWidget().draw() | ||||
| 
 | ||||
|     def setDirty(self, value): | ||||
|         self.dirty = value | ||||
| 
 | ||||
|     def closeEvent(self, event): | ||||
|         if self.okToContinue(): | ||||
|             self.closing.emit() | ||||
|  | ||||
| @ -3,9 +3,9 @@ | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from obspy.core import (read, Stream, UTCDateTime) | ||||
| from obspy.core import read, Stream, UTCDateTime | ||||
| from obspy import readEvents, read_inventory | ||||
| from obspy.core.event import (Event, Catalog) | ||||
| from obspy.core.event import Event, ResourceIdentifier, Pick, WaveformStreamID | ||||
| 
 | ||||
| from pylot.core.read.io import readPILOTEvent | ||||
| from pylot.core.util.utils import fnConstructor, getGlobalTimes | ||||
| @ -46,6 +46,7 @@ class Data(object): | ||||
|         else:  # create an empty Event object | ||||
|             self.newevent = True | ||||
|             self.evtdata = Event() | ||||
|             self.getEvtData().picks = [] | ||||
|         self.wforiginal = None | ||||
|         self.cuttimes = None | ||||
|         self.dirty = False | ||||
| @ -67,29 +68,25 @@ class Data(object): | ||||
|     def updateCutTimes(self): | ||||
|         self.cuttimes = getGlobalTimes(self.getWFData()) | ||||
| 
 | ||||
|     def exportEvent(self, fnout=None, evtformat='QUAKEML'): | ||||
|     def getEventFileName(self): | ||||
|         ID = self.getID() | ||||
|         # handle forbidden filenames especially on windows systems | ||||
|         return fnConstructor(str(ID)) | ||||
| 
 | ||||
|     def exportEvent(self, fnout, fnext='.xml'): | ||||
| 
 | ||||
|         from pylot.core.util.defaults import OUTPUTFORMATS | ||||
| 
 | ||||
|         if evtformat.strip() not in OUTPUTFORMATS.values(): | ||||
|             errmsg = 'selected format {0} not available'.format(evtformat) | ||||
|         try: | ||||
|             evtformat = OUTPUTFORMATS[fnext] | ||||
|         except KeyError, e: | ||||
|             errmsg = '{0}; selected file extension {1} not ' \ | ||||
|                      'supported'.format(e, fnext) | ||||
|             raise FormatError(errmsg) | ||||
| 
 | ||||
|         if fnout is None: | ||||
|             ID = self.getID() | ||||
|             # handle forbidden filenames especially on windows systems | ||||
|             fnout = fnConstructor(str(ID)) | ||||
|         else: | ||||
|             fnout = fnConstructor(str(fnout)) | ||||
| 
 | ||||
|         evtformat = evtformat.upper().strip() | ||||
| 
 | ||||
|         # establish catalog object (event object has no write method) | ||||
|         cat = Catalog() | ||||
|         cat.append(self.getEvtData()) | ||||
|         # try exporting event via ObsPy | ||||
|         try: | ||||
|             cat.write(fnout + evtformat.lower(), format=evtformat) | ||||
|             self.getEvtData().write(fnout + fnext, format=evtformat) | ||||
|         except KeyError, e: | ||||
|             raise KeyError('''{0} export format | ||||
|                               not implemented: {1}'''.format(evtformat, e)) | ||||
| @ -119,7 +116,7 @@ class Data(object): | ||||
|         assert isinstance(fnames, list), "input parameter 'fnames' is " \ | ||||
|                                          "supposed to be of type 'list' " \ | ||||
|                                          "but is actually {0}".format(type( | ||||
|                                                                         fnames)) | ||||
|             fnames)) | ||||
|         if self.dirty: | ||||
|             self.resetWFData() | ||||
| 
 | ||||
| @ -150,27 +147,57 @@ class Data(object): | ||||
|         st = self.getWFData() | ||||
|         inv = read_inventory(fninventory) | ||||
|         st.attach_response(inv) | ||||
|         pre_filt = (0.005, 0.006, 30.0, 35.0) # set in autoPyLoT.in | ||||
|         pre_filt = (0.005, 0.006, 30.0, 35.0)  # set in autoPyLoT.in | ||||
|         st.remove_response(output='VEL', pre_filt=pre_filt) | ||||
| 
 | ||||
|     def getEvtData(self): | ||||
|         return self.evtdata | ||||
| 
 | ||||
|     def applyEVTData(self, data, type='pick'): | ||||
|     def applyEVTData(self, data, type='pick', authority_id='rub'): | ||||
| 
 | ||||
|         def applyPicks(picks): | ||||
|             pass | ||||
|             firstonset = None | ||||
|             for station, onsets in picks.items(): | ||||
|                 print 'Reading picks on station %s' % station | ||||
|                 for label, phase in onsets.items(): | ||||
|                     onset = phase['mpp'] | ||||
|                     epp = phase['epp'] | ||||
|                     lpp = phase['lpp'] | ||||
|                     error = phase['spe'] | ||||
|                     pick = Pick() | ||||
|                     pick.time = onset | ||||
|                     pick.time_errors.lower_uncertainty = onset - epp | ||||
|                     pick.time_errors.upper_uncertainty = lpp - onset | ||||
|                     pick.time_errors.uncertainty = error | ||||
|                     pick.phase_hint = label | ||||
|                     pick.waveform_id = WaveformStreamID(station_code=station) | ||||
|                     self.getEvtData().picks.append(pick) | ||||
|                     try: | ||||
|                         polarity = phase['fm'] | ||||
|                     except KeyError, e: | ||||
|                         print 'No polarity information found for %s' % phase | ||||
|                     if firstonset is None or firstonset > onset: | ||||
|                         firstonset = onset | ||||
| 
 | ||||
|             if 'smi:local' in self.getID(): | ||||
|                 fonset_str = firstonset.strftime('%Y_%m_%d_%H_%M_%S') | ||||
|                 ID = ResourceIdentifier('event/' + fonset_str) | ||||
|                 ID.convertIDToQuakeMLURI(authority_id=authority_id) | ||||
|                 self.getEvtData().resource_id = ID | ||||
| 
 | ||||
|         def applyArrivals(arrivals): | ||||
|             pass | ||||
| 
 | ||||
|         def applyEvent(event): | ||||
|             pass | ||||
| 
 | ||||
|         applydata = {'pick':applyPicks, | ||||
|                      'arrival':applyArrivals, | ||||
|                      'event':applyEvent} | ||||
|         applydata = {'pick': applyPicks, | ||||
|                      'arrival': applyArrivals, | ||||
|                      'event': applyEvent} | ||||
| 
 | ||||
|         applydata[type](data) | ||||
| 
 | ||||
| 
 | ||||
| class GenericDataStructure(object): | ||||
|     ''' | ||||
|     GenericDataBase type holds all information about the current data- | ||||
| @ -280,14 +307,13 @@ class PilotDataStructure(GenericDataStructure): | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self, **fields): | ||||
| 
 | ||||
|         if not fields: | ||||
|             fields = {'database':'2006.01', | ||||
|                       'root':'/data/Egelados/EVENT_DATA/LOCAL'} | ||||
|             fields = {'database': '2006.01', | ||||
|                       'root': '/data/Egelados/EVENT_DATA/LOCAL'} | ||||
| 
 | ||||
|         GenericDataStructure.__init__(self, **fields) | ||||
| 
 | ||||
|         self.setExpandFields(['root','database']) | ||||
|         self.setExpandFields(['root', 'database']) | ||||
| 
 | ||||
| 
 | ||||
| class SeiscompDataStructure(GenericDataStructure): | ||||
| @ -304,7 +330,6 @@ class SeiscompDataStructure(GenericDataStructure): | ||||
|                  filesuffix=None, **kwargs): | ||||
|         super(GenericDataStructure, self).__init__() | ||||
| 
 | ||||
| 
 | ||||
|         edate = UTCDateTime() | ||||
|         halfyear = UTCDateTime('1970-07-01') | ||||
|         sdate = UTCDateTime(edate - halfyear) | ||||
| @ -324,9 +349,9 @@ class SeiscompDataStructure(GenericDataStructure): | ||||
|         # http://www.seiscomp3.org/wiki/doc/applications/slarchive/SDS | ||||
| 
 | ||||
|         self.dsFields = {'root': '/data/SDS', 'YEAR': year, 'NET': '??', | ||||
|                            'STA': '????', 'CHAN': 'HH?', 'TYPE': 'D', 'LOC': '', | ||||
|                            'DAY': '{0:03d}'.format(sdate.julday) | ||||
|         } | ||||
|                          'STA': '????', 'CHAN': 'HH?', 'TYPE': 'D', 'LOC': '', | ||||
|                          'DAY': '{0:03d}'.format(sdate.julday) | ||||
|                          } | ||||
|         self.modifiyFields(**kwargs) | ||||
| 
 | ||||
|     def modifiyFields(self, **kwargs): | ||||
|  | ||||
| @ -13,6 +13,6 @@ FILTERDEFAULTS = {'P': {'filtertype': None, | ||||
|                         'order': 4, | ||||
|                         'freq': [.5, 5]}} | ||||
| 
 | ||||
| OUTPUTFORMATS = {'QuakeML':'QUAKEML', | ||||
|                  'VelEst':'CNV', | ||||
|                  'NonLinLoc':'NLLOC_OBS'} | ||||
| OUTPUTFORMATS = {'.xml':'QUAKEML', | ||||
|                  '.cnv':'CNV', | ||||
|                  '.obs':'NLLOC_OBS'} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user