[update] major improvements of array_map, code restyled, increased flexibility

This commit is contained in:
Marcel Paffrath 2018-06-13 17:01:05 +02:00
parent f50e38241e
commit 06cacdd4cb
2 changed files with 158 additions and 120 deletions

View File

@ -86,7 +86,7 @@ from pylot.core.util.widgets import FilterOptionsDialog, NewEventDlg, \
PylotCanvas, WaveformWidgetPG, PropertiesDlg, HelpForm, createAction, PickDlg, \
getDataType, ComparisonWidget, TuneAutopicker, PylotParaBox, AutoPickDlg, CanvasWidget, AutoPickWidget, \
CompareEventsWidget
from pylot.core.util.map_projection import map_projection
from pylot.core.util.array_map import Array_map
from pylot.core.util.structure import DATASTRUCTURE
from pylot.core.util.thread import Thread, Worker
from pylot.core.util.version import get_git_version as _getVersionString
@ -2850,9 +2850,9 @@ class MainWindow(QMainWindow):
if not self.metadata:
return
self.am_figure = Figure()
self.am_canvas = FigureCanvas(self.am_figure)
self.am_canvas = PylotCanvas(self.am_figure, parent=self, panZoomX=False, panZoomY=False)
self.am_toolbar = NavigationToolbar(self.am_canvas, self)
self.array_map = map_projection(self)
self.array_map = Array_map(self)
# self.array_map_thread()
self.array_layout.addWidget(self.array_map)
self.tabs.setCurrentIndex(index)
@ -2891,7 +2891,8 @@ class MainWindow(QMainWindow):
lon = event.origins[0].longitude
self.array_map.eventLoc = (lat, lon)
if self.get_current_event():
self.array_map.refresh_drawings(self.get_current_event().getPicks())
self.array_map.refresh_drawings(self.get_current_event().getPicks(),
self.get_current_event().getAutopicks(),)
self._eventChanged[1] = False
def init_event_table(self, tabindex=2):

View File

@ -13,19 +13,20 @@ from scipy.interpolate import griddata
plt.interactive(False)
class map_projection(QtGui.QWidget):
class Array_map(QtGui.QWidget):
def __init__(self, parent, figure=None):
'''
:param: picked, can be False, auto, manual
:value: str
Create a map of the array.
:param parent: PyLoT Mainwindow class
:param figure:
'''
QtGui.QWidget.__init__(self)
self._parent = parent
self.metadata = parent.metadata
self.parser = parent.metadata[1]
self.metadata_type = parent.metadata[0]
self.metadata = parent.metadata[1]
self.picks = None
self.picks_dict = None
self.autopicks_dict = None
self.eventLoc = None
self.figure = figure
self.init_graphics()
@ -49,9 +50,9 @@ class map_projection(QtGui.QWidget):
return
data = self._parent.get_data().getWFData()
for index in ind:
station = str(self.station_names[index].split('.')[-1])
station = str(self._station_onpick_ids[index].split('.')[-1])
try:
pickDlg = PickDlg(self, parameter=self._parent._inputs,
pickDlg = PickDlg(self._parent, parameter=self._parent._inputs,
data=data.select(station=station),
station=station,
picks=self._parent.get_current_event().getPick(station),
@ -84,7 +85,29 @@ class map_projection(QtGui.QWidget):
def connectSignals(self):
self.comboBox_phase.currentIndexChanged.connect(self._refresh_drawings)
self.zoom_id = self.basemap.ax.figure.canvas.mpl_connect('scroll_event', self.zoom)
self.comboBox_am.currentIndexChanged.connect(self._refresh_drawings)
#self.zoom_id = self.basemap.ax.figure.canvas.mpl_connect('scroll_event', self.zoom)
def _from_dict(self, function, key):
return function(self.stations_dict.values(), key=lambda x: x[key])[key]
def get_min_from_stations(self, key):
return self._from_dict(min, key)
def get_max_from_stations(self, key):
return self._from_dict(max, key)
def get_min_from_picks(self):
return min(self.picks_rel.values())
def get_max_from_picks(self):
return max(self.picks_rel.values())
def current_picks_dict(self):
picktype = self.comboBox_am.currentText()
auto_manu = {'auto': self.autopicks_dict,
'manual': self.picks_dict}
return auto_manu[picktype]
def init_graphics(self):
if not self.figure:
@ -115,103 +138,97 @@ class map_projection(QtGui.QWidget):
self.top_row.addWidget(QtGui.QLabel('Select a phase: '))
self.top_row.addWidget(self.comboBox_phase)
self.top_row.setStretch(1, 1) # set stretch of item 1 to 1
self.top_row.addWidget(QtGui.QLabel('Pick type: '))
self.top_row.addWidget(self.comboBox_am)
self.top_row.setStretch(3, 1) # set stretch of item 1 to 1
self.main_box.addWidget(self.canvas)
self.main_box.addWidget(self.toolbar)
def init_stations(self):
def get_station_names_lat_lon(parser):
station_names = []
lat = []
lon = []
def stat_info_from_parser(parser):
stations_dict = {}
for station in parser.stations:
station_name = station[0].station_call_letters
network = station[0].network_code
if not station_name in station_names:
station_names.append(network + '.' + station_name)
lat.append(station[0].latitude)
lon.append(station[0].longitude)
return station_names, lat, lon
network_name = station[0].network_code
if not station_name in stations_dict.keys():
st_id = network_name + '.' + station_name
stations_dict[st_id] = {'latitude': station[0].latitude,
'longitude': station[0].longitude}
return stations_dict
station_names, lat, lon = get_station_names_lat_lon(self.parser)
self.station_names = station_names
self.lat = lat
self.lon = lon
def stat_info_from_inventory(inventory):
stations_dict = {}
for network in inventory.networks:
for station in network.stations:
station_name = station.code
network_name = network_name.code
if not station_name in stations_dict.keys():
st_id = network_name + '.' + station_name
stations_dict[st_id] = {'latitude': station[0].latitude,
'longitude': station[0].longitude}
return stations_dict
read_stat = {'xml': stat_info_from_inventory,
'dless': stat_info_from_parser}
self.stations_dict = read_stat[self.metadata_type](self.metadata)
self.latmin = self.get_min_from_stations('latitude')
self.lonmin = self.get_min_from_stations('longitude')
self.latmax = self.get_max_from_stations('latitude')
self.lonmax = self.get_max_from_stations('longitude')
def init_picks(self):
phase = self.comboBox_phase.currentText()
def get_picks(station_names):
picks = []
for station in station_names:
def get_picks(station_dict):
picks = {}
phase = self.comboBox_phase.currentText()
for st_id in station_dict.keys():
try:
station = station.split('.')[-1]
picks.append(self.picks_dict[station][phase]['mpp'])
except:
picks.append(np.nan)
station_name = st_id.split('.')[-1]
picks[st_id] = self.current_picks_dict()[station_name][phase]['mpp']
except KeyError:
continue
except Exception as e:
print('Cannot display pick for station {}. Reason: {}'.format(station_name, e))
return picks
def get_picks_rel(picks):
picks_rel = []
picks_rel = {}
picks_utc = []
for pick in picks:
for pick in picks.values():
if type(pick) is obspy.core.utcdatetime.UTCDateTime:
picks_utc.append(pick)
minp = min(picks_utc)
for pick in picks:
for st_id, pick in picks.items():
if type(pick) is obspy.core.utcdatetime.UTCDateTime:
pick -= minp
picks_rel.append(pick)
picks_rel[st_id] = pick
return picks_rel
self.picks = get_picks(self.station_names)
self.picks = get_picks(self.stations_dict)
self.picks_rel = get_picks_rel(self.picks)
def init_picks_active(self):
def remove_nan_picks(picks):
picks_no_nan = []
for pick in picks:
if not np.isnan(pick):
picks_no_nan.append(pick)
return picks_no_nan
self.picks_no_nan = remove_nan_picks(self.picks_rel)
def init_stations_active(self):
def remove_nan_lat_lon(picks, lat, lon):
lat_no_nan = []
lon_no_nan = []
for index, pick in enumerate(picks):
if not np.isnan(pick):
lat_no_nan.append(lat[index])
lon_no_nan.append(lon[index])
return lat_no_nan, lon_no_nan
self.lat_no_nan, self.lon_no_nan = remove_nan_lat_lon(self.picks_rel, self.lat, self.lon)
def init_lat_lon_dimensions(self):
def get_lon_lat_dim(lon, lat):
londim = max(lon) - min(lon)
latdim = max(lat) - min(lat)
return londim, latdim
self.londim, self.latdim = get_lon_lat_dim(self.lon, self.lat)
# init minimum and maximum lon and lat dimensions
self.londim = self.lonmax - self.lonmin
self.latdim = self.latmax - self.latmin
def init_x_y_dimensions(self):
def get_x_y_dim(x, y):
xdim = max(x) - min(x)
ydim = max(y) - min(y)
return xdim, ydim
# transformation of lat/lon to ax coordinate system
for st_id, coords in self.stations_dict.items():
lat, lon = coords['latitude'], coords['longitude']
coords['x'], coords['y'] = self.basemap(lon, lat)
self.x, self.y = self.basemap(self.lon, self.lat)
self.xdim, self.ydim = get_x_y_dim(self.x, self.y)
self.xdim = self.get_max_from_stations('x') - self.get_min_from_stations('x')
self.ydim = self.get_max_from_stations('y') - self.get_min_from_stations('y')
def init_basemap(self, resolution='l'):
# basemap = Basemap(projection=projection, resolution = resolution, ax=self.main_ax)
basemap = Basemap(projection='lcc', resolution=resolution, ax=self.main_ax,
width=5e6, height=2e6,
lat_0=(min(self.lat) + max(self.lat)) / 2.,
lon_0=(min(self.lon) + max(self.lon)) / 2.)
lat_0=(self.latmin + self.latmax) / 2.,
lon_0=(self.lonmin + self.lonmax) / 2.)
# basemap.fillcontinents(color=None, lake_color='aqua',zorder=1)
basemap.drawmapboundary(zorder=2) # fill_color='darkblue')
@ -222,60 +239,81 @@ class map_projection(QtGui.QWidget):
self.basemap = basemap
self.figure.tight_layout()
def init_lat_lon_grid(self):
def get_lat_lon_axis(lat, lon):
steplat = (max(lat) - min(lat)) / 250
steplon = (max(lon) - min(lon)) / 250
lataxis = np.arange(min(lat), max(lat), steplat)
lonaxis = np.arange(min(lon), max(lon), steplon)
return lataxis, lonaxis
def get_lat_lon_grid(lataxis, lonaxis):
longrid, latgrid = np.meshgrid(lonaxis, lataxis)
return latgrid, longrid
self.lataxis, self.lonaxis = get_lat_lon_axis(self.lat, self.lon)
self.latgrid, self.longrid = get_lat_lon_grid(self.lataxis, self.lonaxis)
def init_lat_lon_grid(self, nstep=250):
# create a regular grid to display colormap
lataxis = np.linspace(self.latmin, self.latmax, nstep)
lonaxis = np.linspace(self.lonmin, self.lonmax, nstep)
self.longrid, self.latgrid = np.meshgrid(lonaxis, lataxis)
def init_picksgrid(self):
self.picksgrid_no_nan = griddata((self.lat_no_nan, self.lon_no_nan),
self.picks_no_nan, (self.latgrid, self.longrid),
method='linear') ##################
picks, lats, lons = self.get_picks_lat_lon()
self.picksgrid_active = griddata((lats, lons), picks, (self.latgrid, self.longrid),
method='linear')
def get_st_lat_lon_for_plot(self):
stations = []
latitudes = []
longitudes = []
for st_id, coords in self.stations_dict.items():
stations.append(st_id)
latitudes.append(coords['latitude'])
longitudes.append(coords['longitude'])
return stations, latitudes, longitudes
def get_st_x_y_for_plot(self):
stations = []
xs = []
ys = []
for st_id, coords in self.stations_dict.items():
stations.append(st_id)
xs.append(coords['x'])
ys.append(coords['y'])
return stations, xs, ys
def get_picks_lat_lon(self):
picks = []
latitudes = []
longitudes = []
for st_id, pick in self.picks_rel.items():
picks.append(pick)
latitudes.append(self.stations_dict[st_id]['latitude'])
longitudes.append(self.stations_dict[st_id]['longitude'])
return picks, latitudes, longitudes
def draw_contour_filled(self, nlevel='50'):
levels = np.linspace(min(self.picks_no_nan), max(self.picks_no_nan), nlevel)
self.contourf = self.basemap.contourf(self.longrid, self.latgrid, self.picksgrid_no_nan,
levels = np.linspace(self.get_min_from_picks(), self.get_max_from_picks(), nlevel)
self.contourf = self.basemap.contourf(self.longrid, self.latgrid, self.picksgrid_active,
levels, latlon=True, zorder=9, alpha=0.5)
def scatter_all_stations(self):
self.sc = self.basemap.scatter(self.lon, self.lat, s=50, facecolor='none', latlon=True,
stations, lats, lons = self.get_st_lat_lon_for_plot()
self.sc = self.basemap.scatter(lons, lats, s=50, facecolor='none', latlon=True,
zorder=10, picker=True, edgecolor='m', label='Not Picked')
self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
self._station_onpick_ids = stations
if self.eventLoc:
lat, lon = self.eventLoc
self.sc_event = self.basemap.scatter(lon, lat, s=100, facecolor='red',
lats, lons = self.eventLoc
self.sc_event = self.basemap.scatter(lons, lats, s=100, facecolor='red',
latlon=True, zorder=11, label='Event (might be outside map region)')
def scatter_picked_stations(self):
lon = self.lon_no_nan
lat = self.lat_no_nan
picks, lats, lons = self.get_picks_lat_lon()
# workaround because of an issue with latlon transformation of arrays with len <3
if len(lon) <= 2 and len(lat) <= 2:
self.sc_picked = self.basemap.scatter(lon[0], lat[0], s=50, facecolor='white',
c=self.picks_no_nan[0], latlon=True, zorder=11, label='Picked')
if len(lon) == 2 and len(lat) == 2:
self.sc_picked = self.basemap.scatter(lon[1], lat[1], s=50, facecolor='white',
c=self.picks_no_nan[1], latlon=True, zorder=11)
if len(lons) <= 2 and len(lats) <= 2:
self.sc_picked = self.basemap.scatter(lons[0], lats[0], s=50, facecolor='white',
c=picks[0], latlon=True, zorder=11, label='Picked')
if len(lons) == 2 and len(lats) == 2:
self.sc_picked = self.basemap.scatter(lons[1], lats[1], s=50, facecolor='white',
c=picks[1], latlon=True, zorder=11)
else:
self.sc_picked = self.basemap.scatter(lon, lat, s=50, facecolor='white',
c=self.picks_no_nan, latlon=True, zorder=11, label='Picked')
self.sc_picked = self.basemap.scatter(lons, lats, s=50, facecolor='white',
c=picks, latlon=True, zorder=11, label='Picked')
def annotate_ax(self):
self.annotations = []
for index, name in enumerate(self.station_names):
self.annotations.append(self.main_ax.annotate(' %s' % name, xy=(self.x[index], self.y[index]),
stations, xs, ys = self.get_st_x_y_for_plot()
for st, x, y in zip(stations, xs, ys):
self.annotations.append(self.main_ax.annotate(' %s' % st, xy=(x, y),
fontsize='x-small', color='white', zorder=12))
self.legend = self.main_ax.legend(loc=1)
@ -284,8 +322,9 @@ class map_projection(QtGui.QWidget):
cbar.set_label(label)
return cbar
def refresh_drawings(self, picks=None):
def refresh_drawings(self, picks=None, autopicks=None):
self.picks_dict = picks
self.autopicks_dict = autopicks
self._refresh_drawings()
def _refresh_drawings(self):
@ -295,9 +334,7 @@ class map_projection(QtGui.QWidget):
def draw_everything(self):
if self.picks_dict:
self.init_picks()
self.init_picks_active()
self.init_stations_active()
if len(self.picks_no_nan) >= 3:
if len(self.picks) >= 3:
self.init_picksgrid()
self.draw_contour_filled()
self.scatter_all_stations()
@ -311,15 +348,15 @@ class map_projection(QtGui.QWidget):
self.canvas.draw()
def remove_drawings(self):
if hasattr(self, 'cbar'):
self.cbar.remove()
del (self.cbar)
if hasattr(self, 'sc_picked'):
self.sc_picked.remove()
del (self.sc_picked)
if hasattr(self, 'sc_event'):
self.sc_event.remove()
del (self.sc_event)
if hasattr(self, 'cbar'):
self.cbar.remove()
del (self.cbar)
if hasattr(self, 'contourf'):
self.remove_contourf()
del (self.contourf)