feature/port-to-py3 #11

Merged
marcel merged 59 commits from feature/port-to-py3 into develop 2022-03-21 15:30:06 +01:00
Showing only changes of commit 04067cac8e - Show all commits

View File

@ -1,45 +1,47 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
import os import os
import matplotlib import matplotlib
matplotlib.use('Qt5Agg') matplotlib.use('Qt5Agg')
from PySide2 import QtCore, QtGui, QtWidgets
import matplotlib.pyplot as plt from PySide2.QtCore import Qt
import numpy as np
import obspy
import traceback
from PySide2 import QtWidgets
from matplotlib.figure import Figure
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
# from mpl_toolkits.basemap import Basemap
from scipy.interpolate import griddata
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import cartopy.crs as ccrs import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cf import cartopy.feature as cf
from cartopy.feature import ShapelyFeature
from cartopy.io.shapereader import Reader from cartopy.io.shapereader import Reader
from cartopy.feature import ShapelyFeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
from pylot.core.util.widgets import PickDlg, PylotCanvas import traceback
import obspy
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from scipy.interpolate import griddata
from pylot.core.util.widgets import PickDlg
from pylot.core.pick.utils import get_quality_class from pylot.core.pick.utils import get_quality_class
plt.interactive(False) class MplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
self.fig = plt.figure(figsize=(width, height), dpi=dpi)
self.axes = self.fig.add_subplot(111)
super(MplCanvas, self).__init__(self.fig)
class Array_map(QtWidgets.QWidget): class Array_map(QtWidgets.QWidget):
def __init__(self, parent, metadata, parameter=None, figure=None, annotate=True, pointsize=25., def __init__(self, parent, metadata, parameter=None, figure=None, annotate=True, pointsize=25.,
linewidth=1.5, width=5e6, height=2e6): linewidth=1.5, width=5e6, height=2e6):
''' super(Array_map, self).__init__(parent)
Create a map of the array.
:param parent: object of PyLoT Mainwindow class # set properties
:param parameter: object of PyLoT parameter class
:param figure:
'''
QtWidgets.QWidget.__init__(self)
assert (parameter != None or parent != None), 'either parent or parameter has to be set'
self._parent = parent self._parent = parent
self.metadata = metadata self.metadata = metadata
self.pointsize = pointsize self.pointsize = pointsize
@ -54,197 +56,33 @@ class Array_map(QtWidgets.QWidget):
self.hybrids_dict = None self.hybrids_dict = None
self.eventLoc = None self.eventLoc = None
self.parameter = parameter if parameter else parent._inputs self.parameter = parameter if parameter else parent._inputs
self.figure = figure
self.picks_rel = {} self.picks_rel = {}
self.marked_stations = [] self.marked_stations = []
self.highlighted_stations = [] self.highlighted_stations = []
# call functions to draw everything
self.init_graphics() self.init_graphics()
self.init_stations() self.init_stations()
self.init_basemap() self.init_crtpyMap()
self.init_map() self.init_colormap()
self.draw_everything()
self._style = None if not hasattr(parent, '_style') else parent._style self._style = None if not hasattr(parent, '_style') else parent._style
self.show() self.show()
def update_hybrids_dict(self):
self.hybrids_dict = self.picks_dict.copy()
for station, pick in self.autopicks_dict.items():
if not station in self.hybrids_dict.keys():
self.hybrids_dict[station] = pick
return self.hybrids_dict
def init_map(self):
self.init_colormap()
self.connectSignals()
self.draw_everything()
# self.canvas.setZoomBorders2content()
def init_colormap(self):
self.init_lat_lon_dimensions()
self.init_lat_lon_grid()
# self.init_x_y_dimensions()
def onpick(self, event):
ind = event.ind
button = event.mouseevent.button
if ind == []:
return
if button == 1:
self.openPickDlg(ind)
elif button == 2:
self.deletePick(ind)
elif button == 3:
self.pickInfo(ind)
def deletePick(self, ind):
self.update_hybrids_dict()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
try:
phase = self.comboBox_phase.currentText()
picks = self.current_picks_dict()[station]
pick = picks.get(phase)
if pick:
picker = pick['picker']
message = 'Deleted {} pick for phase {}, station {}.{} at timestamp {}'
message = message.format(picker, phase, network, station,
pick['mpp'])
if picker == 'auto':
del (self.autopicks_dict[station])
elif picker == 'manual':
del (self.picks_dict[station])
else:
raise TypeError('Unknown "picker" {}'.format(picker))
print(message)
pyl_mw = self._parent
pyl_mw.deletePicks(station, pick, type=picker)
pyl_mw.setDirty(True)
pyl_mw.update_status(message)
if self.auto_refresh_box.isChecked():
self._refresh_drawings()
else:
self.highlight_station(network, station, color='red')
pyl_mw.drawPicks(station)
pyl_mw.draw()
except Exception as e:
print('Could not delete pick for station {}.{}: {}'.format(network, station, e))
def highlight_station(self, network, station, color):
stat_dict = self.stations_dict['{}.{}'.format(network, station)]
lat = stat_dict['latitude']
lon = stat_dict['longitude']
self.highlighted_stations.append(self.basemap.scatter(lon, lat, s=self.pointsize, edgecolors=color,
facecolors='none', zorder=12, label='deleted'))
self.canvas.draw()
def pickInfo(self, ind):
self.update_hybrids_dict()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
dic = self.current_picks_dict()[station]
for phase, picks in dic.items():
# because of wadati...
if phase == 'SPt':
continue
print('{} - Pick:'.format(phase))
for key, info in picks.items():
print('{}: {}'.format(key, info))
def openPickDlg(self, ind):
data = self._parent.get_data().getWFData()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
pyl_mw = self._parent
try:
data = data.select(station=station)
if not data:
self._warn('No data for station {}'.format(station))
return
pickDlg = PickDlg(self._parent, parameter=self.parameter,
data=data, network=network, station=station,
picks=self._parent.get_current_event().getPick(station),
autopicks=self._parent.get_current_event().getAutopick(station),
filteroptions=self._parent.filteroptions, metadata=self.metadata,
event=pyl_mw.get_current_event())
except Exception as e:
message = 'Could not generate Plot for station {st}.\n {er}'.format(st=station, er=e)
self._warn(message)
print(message, e)
print(traceback.format_exc())
return
try:
if pickDlg.exec_():
pyl_mw.setDirty(True)
pyl_mw.update_status('picks accepted ({0})'.format(station))
pyl_mw.addPicks(station, pickDlg.getPicks(picktype='manual'), type='manual')
pyl_mw.addPicks(station, pickDlg.getPicks(picktype='auto'), type='auto')
if self.auto_refresh_box.isChecked():
self._refresh_drawings()
else:
self.highlight_station(network, station, color='yellow')
pyl_mw.drawPicks(station)
pyl_mw.draw()
else:
pyl_mw.update_status('picks discarded ({0})'.format(station))
except Exception as e:
message = 'Could not save picks for station {st}.\n{er}'.format(st=station, er=e)
self._warn(message)
print(message, e)
print(traceback.format_exc())
def connectSignals(self):
self.comboBox_phase.currentIndexChanged.connect(self._refresh_drawings)
self.comboBox_am.currentIndexChanged.connect(self._refresh_drawings)
self.cmaps_box.currentIndexChanged.connect(self._refresh_drawings)
self.annotations_box.stateChanged.connect(self.switch_annotations)
self.refresh_button.clicked.connect(self._refresh_drawings)
self.canvas.mpl_connect('motion_notify_event', self.mouse_moved)
self.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 mouse_moved(self, event):
if not event.inaxes == self.main_ax:
return
x = event.xdata
y = event.ydata
# lat, lon = self.basemap(x, y, inverse=True)
lat = y
lon = x
self.status_label.setText('Latitude: {}, Longitude: {}'.format(lat, lon))
def current_picks_dict(self):
picktype = self.comboBox_am.currentText().split(' ')[0]
auto_manu = {'auto': self.autopicks_dict,
'manual': self.picks_dict,
'hybrid': self.hybrids_dict}
return auto_manu[picktype]
def init_graphics(self): def init_graphics(self):
if not self.figure: """
self.figure = plt.figure() Initializes all GUI components and figure elements to be populeted by other functions
"""
# initialize figure elements
self.canvas = MplCanvas(self)
self.plotWidget = FigureCanvas(self.canvas.fig)
# initialize GUI elements
self.status_label = QtWidgets.QLabel() self.status_label = QtWidgets.QLabel()
self.main_ax = self.figure.add_subplot(111)
#self.main_ax.set_facecolor('0.7')
self.canvas = FigureCanvas(self.figure)
# parent=self._parent, multicursor=True, panZoomX=False, panZoomY=False)
self.main_box = QtWidgets.QVBoxLayout() self.main_box = QtWidgets.QVBoxLayout()
self.setLayout(self.main_box) self.setLayout(self.main_box)
@ -282,8 +120,184 @@ class Array_map(QtWidgets.QWidget):
self.top_row.addWidget(self.auto_refresh_box) self.top_row.addWidget(self.auto_refresh_box)
self.top_row.addWidget(self.refresh_button) self.top_row.addWidget(self.refresh_button)
self.main_box.addWidget(self.canvas, 1) self.main_box.addWidget(self.plotWidget, 1)
self.main_box.addWidget(self.status_label, 0) self.main_box.addWidget(NavigationToolbar(self.plotWidget, self), 0)
#self.main_box.addWidget(self.status_label, 0)
self.connectSignals()
def init_colormap(self):
self.init_lat_lon_dimensions()
self.init_lat_lon_grid()
def init_crtpyMap(self):
self.canvas.axes.cla()
self.canvas.axes = plt.axes(projection=ccrs.PlateCarree())
self.canvas.axes.add_feature(cf.LAND)
self.canvas.axes.add_feature(cf.OCEAN)
self.canvas.axes.add_feature(cf.COASTLINE, linewidth=1, edgecolor='gray')
self.canvas.axes.add_feature(cf.BORDERS, alpha=0.7)
# parallels and meridians
gridlines = self.canvas.axes.gridlines(draw_labels=True, alpha=0.5, zorder=7)
gridlines.xformatter = LONGITUDE_FORMATTER
gridlines.yformatter = LATITUDE_FORMATTER
# self.canvas.axes.set_global()
self.canvas.fig.tight_layout()
# self.plotWidget.draw_idle()
def connectSignals(self):
self.comboBox_phase.currentIndexChanged.connect(self._refresh_drawings)
self.comboBox_am.currentIndexChanged.connect(self._refresh_drawings)
self.cmaps_box.currentIndexChanged.connect(self._refresh_drawings)
self.annotations_box.stateChanged.connect(self.switch_annotations)
self.refresh_button.clicked.connect(self._refresh_drawings)
self.plotWidget.mpl_connect('motion_notify_event', self.mouse_moved)
self.plotWidget.mpl_connect('scroll_event', self.mouse_scroll)
self.plotWidget.mpl_connect('button_press_event', self.mouseLeftPress)
self.plotWidget.mpl_connect('button_release_event', self.mouseLeftRelease)
# set mouse events -----------------------------------------------------
def mouse_moved(self, event):
if not event.inaxes == self.canvas.axes:
return
lat = event.ydata
lon = event.xdata
self.status_label.setText('Latitude: {}, Longitude: {}'.format(lat, lon))
def mouse_scroll(self, event):
if not event.inaxes == self.canvas.axes:
return
zoom = {'up': 1. / 2., 'down': 2.}
if event.button in zoom:
xlim = self.canvas.axes.get_xlim()
ylim = self.canvas.axes.get_ylim()
x, y = event.xdata, event.ydata
factor = zoom[event.button]
xdiff = (xlim[1] - xlim[0]) * factor
xl = x - 0.5 * xdiff
xr = x + 0.5 * xdiff
ydiff = (ylim[1] - ylim[0]) * factor
yb = y - 0.5 * ydiff
yt = y + 0.5 * ydiff
self.canvas.axes.set_xlim(xl, xr)
self.canvas.axes.set_ylim(yb, yt)
kaan marked this conversation as resolved
Review

consider adding "TODO:" comment for future releases of cartopy

consider adding "TODO:" comment for future releases of cartopy
self.canvas.axes.figure.canvas.draw_idle()
def mouseLeftPress(self, event):
if not event.inaxes == self.canvas.axes:
return
self.map_x = event.xdata
self.map_y = event.ydata
self.map_xlim = self.canvas.axes.get_xlim()
self.map_ylim = self.canvas.axes.get_ylim()
def mouseLeftRelease(self, event):
if not event.inaxes == self.canvas.axes:
return
new_x = event.xdata
new_y = event.ydata
dx = new_x - self.map_x
dy = new_y - self.map_y
self.canvas.axes.set_xlim((self.map_xlim[0] - dx, self.map_xlim[1] - dx))
self.canvas.axes.set_ylim(self.map_ylim[0] - dy, self.map_ylim[1] - dy)
self.canvas.axes.figure.canvas.draw_idle()
def onpick(self, event):
ind = event.ind
button = event.mouseevent.button
if ind == []:
return
if button == 1:
self.openPickDlg(ind)
elif button == 2:
self.deletePick(ind)
elif button == 3:
self.pickInfo(ind)
# data handling -----------------------------------------------------
def update_hybrids_dict(self):
self.hybrids_dict = self.picks_dict.copy()
for station, pick in self.autopicks_dict.items():
if not station in self.hybrids_dict.keys():
self.hybrids_dict[station] = pick
return self.hybrids_dict
def deletePick(self, ind):
self.update_hybrids_dict()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
try:
phase = self.comboBox_phase.currentText()
picks = self.current_picks_dict()[station]
pick = picks.get(phase)
if pick:
picker = pick['picker']
message = 'Deleted {} pick for phase {}, station {}.{} at timestamp {}'
message = message.format(picker, phase, network, station,
pick['mpp'])
if picker == 'auto':
del (self.autopicks_dict[station])
elif picker == 'manual':
del (self.picks_dict[station])
else:
raise TypeError('Unknown "picker" {}'.format(picker))
print(message)
pyl_mw = self._parent
pyl_mw.deletePicks(station, pick, type=picker)
pyl_mw.setDirty(True)
pyl_mw.update_status(message)
if self.auto_refresh_box.isChecked():
self._refresh_drawings()
else:
self.highlight_station(network, station, color='red')
pyl_mw.drawPicks(station)
pyl_mw.draw()
except Exception as e:
print('Could not delete pick for station {}.{}: {}'.format(network, station, e))
def pickInfo(self, ind):
self.update_hybrids_dict()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
dic = self.current_picks_dict()[station]
for phase, picks in dic.items():
# because of wadati...
if phase == 'SPt':
continue
print('{} - Pick:'.format(phase))
for key, info in picks.items():
print('{}: {}'.format(key, info))
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().split(' ')[0]
auto_manu = {'auto': self.autopicks_dict,
'manual': self.picks_dict,
'hybrid': self.hybrids_dict}
return auto_manu[picktype]
def init_stations(self): def init_stations(self):
self.stations_dict = self.metadata.get_all_coordinates() self.stations_dict = self.metadata.get_all_coordinates()
@ -337,35 +351,6 @@ class Array_map(QtWidgets.QWidget):
self.londim = self.lonmax - self.lonmin self.londim = self.lonmax - self.lonmin
self.latdim = self.latmax - self.latmin self.latdim = self.latmax - self.latmin
def init_basemap(self):
# initialize cartopy coordinate reference system
proj = ccrs.Mercator() # PlateCarree(central_longitude=self.lonmin + abs(self.lonmax - self.lonmin) / 2.)
# crtpy_map = self.figure.axes
self.main_ax = plt.axes(projection=proj)
mapxtent = [self.lonmin, self.lonmax, self.latmin, self.latmax] # add conditional buffer
self.main_ax.set_extent(mapxtent) # find way to directly open zoomed map on area
# self.main_ax.set_global()
# add features (option for plate boundaries)
self.main_ax.add_feature(cf.LAND, edgecolor='face', facecolor=cf.COLORS['land']) # replace with background map
self.main_ax.add_feature(cf.OCEAN, edgecolor='face', facecolor=cf.COLORS['water'])
self.main_ax.add_feature(cf.BORDERS, linestyle=':', edgecolor='k') # include province borders
self.main_ax.add_feature(cf.COASTLINE, color='gray', linewidth=1)
# fname = 'PB2002_plates.shp'
# plateBoundaries = ShapelyFeature(Reader(fname).geometries(), ccrs.PlateCarree(), facecolor='none', edgecolor='r')
# crtpy_map.add_feature(plateBoundaries)
# parallels and meridians
gridlines = self.main_ax.gridlines(draw_labels=True, alpha=0.5, zorder=7)
gridlines.xformatter = LONGITUDE_FORMATTER
gridlines.yformatter = LATITUDE_FORMATTER
self.basemap = self.main_ax
# plt.show()
# self.show()
# self.figure._tight = True
# self.figure.tight_layout()
def init_lat_lon_grid(self, nstep=250): def init_lat_lon_grid(self, nstep=250):
# create a regular grid to display colormap # create a regular grid to display colormap
lataxis = np.linspace(self.latmin, self.latmax, nstep) lataxis = np.linspace(self.latmin, self.latmax, nstep)
@ -401,34 +386,90 @@ class Array_map(QtWidgets.QWidget):
longitudes.append(self.stations_dict[st_id]['longitude']) longitudes.append(self.stations_dict[st_id]['longitude'])
return picks, uncertainties, latitudes, longitudes return picks, uncertainties, latitudes, longitudes
# plotting -----------------------------------------------------
def init_colormap(self):
self.init_lat_lon_dimensions()
self.init_lat_lon_grid()
def highlight_station(self, network, station, color):
stat_dict = self.stations_dict['{}.{}'.format(network, station)]
lat = stat_dict['latitude']
lon = stat_dict['longitude']
self.highlighted_stations.append(self.canvas.axes.scatter(lon, lat, s=self.pointsize, edgecolors=color,
facecolors='none', zorder=12, label='deleted'))
self.canvas.idle_draw()
def openPickDlg(self, ind):
data = self._parent.get_data().getWFData()
for index in ind:
network, station = self._station_onpick_ids[index].split('.')[:2]
pyl_mw = self._parent
try:
data = data.select(station=station)
if not data:
self._warn('No data for station {}'.format(station))
return
pickDlg = PickDlg(self._parent, parameter=self.parameter,
data=data, network=network, station=station,
picks=self._parent.get_current_event().getPick(station),
autopicks=self._parent.get_current_event().getAutopick(station),
filteroptions=self._parent.filteroptions, metadata=self.metadata,
event=pyl_mw.get_current_event())
except Exception as e:
message = 'Could not generate Plot for station {st}.\n {er}'.format(st=station, er=e)
self._warn(message)
print(message, e)
print(traceback.format_exc())
return
try:
if pickDlg.exec_():
pyl_mw.setDirty(True)
pyl_mw.update_status('picks accepted ({0})'.format(station))
pyl_mw.addPicks(station, pickDlg.getPicks(picktype='manual'), type='manual')
pyl_mw.addPicks(station, pickDlg.getPicks(picktype='auto'), type='auto')
if self.auto_refresh_box.isChecked():
self._refresh_drawings()
else:
self.highlight_station(network, station, color='yellow')
pyl_mw.drawPicks(station)
pyl_mw.draw()
else:
pyl_mw.update_status('picks discarded ({0})'.format(station))
except Exception as e:
message = 'Could not save picks for station {st}.\n{er}'.format(st=station, er=e)
self._warn(message)
print(message, e)
print(traceback.format_exc())
def draw_contour_filled(self, nlevel=100): def draw_contour_filled(self, nlevel=100):
# self.test_gradient() # self.test_gradient()
levels = np.linspace(self.get_min_from_picks(), self.get_max_from_picks(), nlevel) 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, self.contourf = self.canvas.axes.contourf(self.longrid, self.latgrid, self.picksgrid_active, levels,
linewidths=self.linewidth, transform=ccrs.PlateCarree(), linewidths=self.linewidth, transform=ccrs.PlateCarree(),
alpha=0.7, zorder=8, cmap=self.get_colormap()) alpha=0.7, zorder=8, cmap=self.get_colormap())
def get_colormap(self): def get_colormap(self):
return plt.get_cmap(self.cmaps_box.currentText()) return plt.get_cmap(self.cmaps_box.currentText())
def scatter_all_stations(self): def scatter_all_stations(self):
stations, lats, lons = self.get_st_lat_lon_for_plot() stations, lats, lons = self.get_st_lat_lon_for_plot()
#self.sc = self.basemap.scatter(lons, lats, s=self.pointsize, facecolor='none', latlon=True, marker='.', # self.sc = self.basemap.scatter(lons, lats, s=self.pointsize, facecolor='none', latlon=True, marker='.',
# zorder=10, picker=True, edgecolor='0.5', label='Not Picked') # zorder=10, picker=True, edgecolor='0.5', label='Not Picked')
self.sc = self.basemap.scatter(lons, lats, s=self.pointsize, facecolor='none', marker='.', self.sc = self.canvas.axes.scatter(lons, lats, s=self.pointsize, facecolor='none', marker='.',
zorder=10, picker=True, edgecolor='0.5', label='Not Picked', zorder=10, picker=True, edgecolor='0.5', label='Not Picked',
transform=ccrs.PlateCarree()) transform=ccrs.PlateCarree())
self.cid = self.canvas.mpl_connect('pick_event', self.onpick) self.cid = self.canvas.mpl_connect('pick_event', self.onpick)
self._station_onpick_ids = stations self._station_onpick_ids = stations
if self.eventLoc: if self.eventLoc:
lats, lons = self.eventLoc lats, lons = self.eventLoc
self.sc_event = self.basemap.scatter(lons, lats, s=2*self.pointsize, facecolor='red', zorder=11, self.sc_event = self.canvas.axes.scatter(lons, lats, s=2 * self.pointsize, facecolor='red', zorder=11,
label='Event (might be outside map region)', label='Event (might be outside map region)',
transform=ccrs.PlateCarree()) transform=ccrs.PlateCarree())
def scatter_picked_stations(self): def scatter_picked_stations(self):
picks, uncertainties, lats, lons = self.get_picks_lat_lon() picks, uncertainties, lats, lons = self.get_picks_lat_lon()
@ -441,18 +482,9 @@ class Array_map(QtWidgets.QWidget):
for uncertainty in uncertainties]) for uncertainty in uncertainties])
cmap = self.get_colormap() cmap = self.get_colormap()
self.sc_picked = self.basemap.scatter(lons, lats, s=sizes, edgecolors='white', cmap=cmap, self.sc_picked = self.canvas.axes.scatter(lons, lats, s=sizes, edgecolors='white', cmap=cmap,
c=picks, zorder=11, label='Picked', transform=ccrs.PlateCarree()) c=picks, zorder=11, label='Picked', transform=ccrs.PlateCarree())
# workaround because of an issue with latlon transformation of arrays with len <3
# if len(lons) <= 2 and len(lats) <= 2:
# self.sc_picked = self.basemap.scatter(lons[0], lats[0], s=sizes, edgecolors='white', cmap=cmap,
# c=picks[0], zorder=11, transform=ccrs.PlateCarree())
# if len(lons) == 2 and len(lats) == 2:
# self.sc_picked = self.basemap.scatter(lons[1], lats[1], s=sizes, edgecolors='white', cmap=cmap,
# c=picks[1], zorder=11, transform=ccrs.PlateCarree())
# if len(lons) > 2 and len(lats) > 2:
# self.sc_picked = self.basemap.scatter(lons, lats, s=sizes, edgecolors='white', cmap=cmap,
# c=picks, zorder=11, label='Picked', transform=ccrs.PlateCarree())
def annotate_ax(self): def annotate_ax(self):
self.annotations = [] self.annotations = []
@ -469,15 +501,15 @@ class Array_map(QtWidgets.QWidget):
color = 'lightgrey' color = 'lightgrey'
if st in self.marked_stations: if st in self.marked_stations:
color = 'red' color = 'red'
self.annotations.append(self.main_ax.annotate(' %s' % st, xy=(x, y), fontsize=self.pointsize/4., self.annotations.append(self.canvas.axes.annotate(' %s' % st, xy=(x, y), fontsize=self.pointsize / 4.,
fontweight='semibold', color=color, zorder=14)) fontweight='semibold', color=color, zorder=14))
self.legend = self.main_ax.legend(loc=1) self.legend = self.canvas.axes.legend(loc=1)
self.legend.get_frame().set_facecolor((1, 1, 1, 0.75)) self.legend.get_frame().set_facecolor((1, 1, 1, 0.75))
def add_cbar(self, label): def add_cbar(self, label):
self.cbax_bg = inset_axes(self.main_ax, width="6%", height="75%", loc=5) self.cbax_bg = inset_axes(self.canvas.axes, width="6%", height="75%", loc=5)
cbax = inset_axes(self.main_ax, width='2%', height='70%', loc=5) cbax = inset_axes(self.canvas.axes, width='2%', height='70%', loc=5)
cbar = self.main_ax.figure.colorbar(self.sc_picked, cax=cbax) cbar = self.canvas.axes.figure.colorbar(self.sc_picked, cax=cbax)
cbar.set_label(label) cbar.set_label(label)
cbax.yaxis.tick_left() cbax.yaxis.tick_left()
cbax.yaxis.set_label_position('left') cbax.yaxis.set_label_position('left')
@ -488,7 +520,7 @@ class Array_map(QtWidgets.QWidget):
self.cbax_bg.patch.set_facecolor((1, 1, 1, 0.75)) self.cbax_bg.patch.set_facecolor((1, 1, 1, 0.75))
return cbar return cbar
# handle drawings -----------------------------------------------------
def refresh_drawings(self, picks=None, autopicks=None): def refresh_drawings(self, picks=None, autopicks=None):
self.picks_dict = picks self.picks_dict = picks
self.autopicks_dict = autopicks self.autopicks_dict = autopicks
@ -573,43 +605,79 @@ class Array_map(QtWidgets.QWidget):
annotation.remove() annotation.remove()
self.annotations = [] self.annotations = []
def zoom(self, event):
if not event.inaxes == self.canvas.axes:
return
zoom = {'up': 1. / 2.,
'down': 2.}
# if not event.xdata or not event.ydata:
# return
if event.button in zoom:
m = self.basemap
xlim = m.get_xlim()
ylim = m.get_ylim()
x, y = event.xdata, event.ydata
factor = zoom[event.button]
xdiff = (xlim[1] - xlim[0]) * factor
xl = x - 0.5 * xdiff
xr = x + 0.5 * xdiff
ydiff = (ylim[1] - ylim[0]) * factor
yb = y - 0.5 * ydiff
yt = y + 0.5 * ydiff
#if xl < map.xmin or yb < map.ymin or xr > map.xmax or yt > map.ymax:
# xl, xr = map.xmin, map.xmax
# yb, yt = map.ymin, map.ymax
m.set_xlim(xl, xr)
m.set_ylim(yb, yt)
m.figure.canvas.draw_idle()
def _warn(self, message): def _warn(self, message):
self.qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Icon.Warning, self.qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Icon.Warning, 'Warning', message)
'Warning', message)
self.qmb.show() self.qmb.show()