Source code for mtpy.imaging.plot_stations

# -*- coding: utf-8 -*-
"""
===============
PlotStations
===============

Plots station locations in map view.


Created on Fri Jun 07 18:20:00 2013

@author: jpeacock-pr
"""

# =============================================================================
import matplotlib.pyplot as plt
import numpy as np

try:
    import contextily as cx

    has_cx = True
except ModuleNotFoundError:
    has_cx = False
import mtpy.utils.exceptions as mtex
from mtpy.imaging.mtplot_tools import PlotBase

# ==============================================================================


[docs] class PlotStations(PlotBase): """Plot station locations in map view. Can set `x_limits` and `y_limits` to zoom in on a specific area. or set `image_extent` to plot an image in the background. or set `pad` to set the padding around the stations. Uses contextily to get the basemap. See https://contextily.readthedocs.io/en/latest/index.html for more information about options. """ def __init__(self, geo_df, **kwargs): # --> set plot properties self.plot_title = None self.station_id = None self.ref_point = (0, 0) self.map_epsg = 4326 self.plot_names = True self.plot_cx = True self.image_file = None self.image_extent = None self.pad = None super().__init__(**kwargs) self._basename = "stations_map" self.gdf = geo_df self.cx_source = None self.cx_zoom = None if has_cx and self.plot_cx: self.cx_source = cx.providers.USGS.USTopo self._set_subplot_parameters() for key, value in kwargs.items(): setattr(self, key, value) if self.image_file is not None: if self.image_extent is None: raise mtex.MTpyError_inputarguments( "Need to input extents " + "of the image as" + "(x0, y0, x1, y1)" ) # --> plot if desired if self.show_plot: self.plot() def _set_subplot_parameters(self): """Set subplot parameters.""" plt.rcParams["font.size"] = self.font_size plt.rcParams["figure.subplot.left"] = self.subplot_left plt.rcParams["figure.subplot.right"] = self.subplot_right plt.rcParams["figure.subplot.bottom"] = self.subplot_bottom plt.rcParams["figure.subplot.top"] = self.subplot_top def _get_pad(self): """Get pad.""" return max( [ np.abs(self.gdf.geometry.x.min() - self.gdf.geometry.x.max()) * 0.05, np.abs(self.gdf.geometry.y.min() - self.gdf.geometry.y.max()) * 0.05, ] ) def _get_xlimits(self, x): """Get xlimits.""" return (x.min() - self.pad, x.max() + self.pad) def _get_ylimits(self, y): """Get ylimits.""" return (y.min() - self.pad, y.max() + self.pad)
[docs] def plot(self): """Plot function. :param cx_source: DESCRIPTIONproviders.USGS.USTopo, defaults to cx. :type cx_source: TYPE, optional :param cx_zoom: DESCRIPTION, defaults to None. :type cx_zoom: TYPE, optional :return: DESCRIPTION. :rtype: TYPE """ # make a figure instance self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi) if self.pad is None: self.pad = self._get_pad() if self.image_extent: x_limits = (self.image_extent[0], self.image_extent[2]) y_limits = (self.image_extent[1], self.image_extent[3]) elif self.x_limits is not None: x_limits = self.x_limits if self.y_limits is None: y_limits = self._get_ylimits(self.gdf.geometry.y) else: y_limits = self.y_limits elif self.y_limits is not None: y_limits = self.y_limits if self.x_limits is None: x_limits = self._get_xlimits(self.gdf.geometry.x) else: x_limits = self.x_limits else: x_limits = self._get_xlimits(self.gdf.geometry.x) y_limits = self._get_ylimits(self.gdf.geometry.y) # add and axes self.ax = self.fig.add_subplot(1, 1, 1, aspect="equal") self.ax.set_xlim(x_limits) self.ax.set_ylim(y_limits) # --> plot the background image if desired----------------------- if self.image_file is not None: im = plt.imread(self.image_file) self.ax.imshow(im, origin="lower", extent=self.image_extent, aspect="auto") # plot stations gax = self.gdf.plot( ax=self.ax, marker=self.marker, color=self.marker_color, markersize=self.marker_size, ) for x, y, label in zip( self.gdf.geometry.x, self.gdf.geometry.y, self.gdf.station ): gax.annotate( label, xy=(x, y), ha="center", va="baseline", xytext=(x, y + self.text_y_pad), rotation=self.text_angle, color=self.text_color, fontsize=self.text_size, fontweight=self.text_weight, ) if self.image_file is None: if has_cx and self.plot_cx: try: cx_kwargs = { "crs": self.gdf.crs.to_string(), "source": self.cx_source, } if self.cx_zoom is not None: cx_kwargs["zoom"] = self.cx_zoom cx.add_basemap( gax, **cx_kwargs, ) except Exception as error: self.logger.warning(f"Could not add base map because {error}") # set axis properties if self.plot_cx: self.ax.set_ylabel("latitude (deg)", fontdict=self.font_dict) self.ax.set_xlabel("longitude (deg)", fontdict=self.font_dict) else: self.ax.set_xlabel("relative east (m)", fontdict=self.font_dict) self.ax.set_ylabel("relative north (m)", fontdict=self.font_dict) self.ax.grid(alpha=0.35, color=(0.35, 0.35, 0.35), lw=0.35) self.ax.set_axisbelow(True) plt.show()