From e22ccdc2dea18656c72af576331c588e36bf43bf Mon Sep 17 00:00:00 2001 From: michaelchin Date: Tue, 23 Apr 2024 11:26:50 +1000 Subject: [PATCH] code refactor --- gplately/__init__.py | 6 +- gplately/plot.py | 90 ++++++++----------- .../{read_geometries.py => utils/io_utils.py} | 0 gplately/utils/log_utils.py | 4 +- gplately/utils/plot_utils.py | 7 +- tests-dir/unittest/test_plot.py | 39 ++++++-- 6 files changed, 81 insertions(+), 65 deletions(-) rename gplately/{read_geometries.py => utils/io_utils.py} (100%) diff --git a/gplately/__init__.py b/gplately/__init__.py index 6cfeff49..265c4bab 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -183,7 +183,6 @@ plot, ptt, pygplates, - read_geometries, reconstruction, ) from .data import DataCollection @@ -191,7 +190,6 @@ from .grids import Raster from .oceans import SeafloorGrid from .plot import PlotTopologies -from .read_geometries import get_geometries, get_valid_geometries from .reconstruction import ( PlateReconstruction, Points, @@ -200,6 +198,8 @@ _ReconstructByTopologies, ) from .tools import EARTH_RADIUS +from .utils import io_utils +from .utils.io_utils import get_geometries, get_valid_geometries __pdoc__ = { "data": False, @@ -218,7 +218,7 @@ "oceans", "plot", "pygplates", - "read_geometries", + "io_utils", "reconstruction", "plate_model_manager", "ptt", diff --git a/gplately/plot.py b/gplately/plot.py index 3722a5d2..8bdebf4f 100644 --- a/gplately/plot.py +++ b/gplately/plot.py @@ -2,8 +2,7 @@ Methods in `plot.py` reconstruct geological features using [pyGPlates' `reconstruct` function](https://www.gplates.org/docs/pygplates/generated/pygplates.reconstruct.html), -turns them into plottable Shapely geometries, and plots them onto -Cartopy GeoAxes using Shapely and GeoPandas. +turns them into plottable Shapely geometries, and plots them onto Cartopy GeoAxes using Shapely and GeoPandas. Classes ------- @@ -16,7 +15,6 @@ import cartopy.crs as ccrs import geopandas as gpd -import matplotlib.pyplot as plt import numpy as np import pygplates from shapely.geometry.base import BaseGeometry, BaseMultipartGeometry @@ -25,24 +23,36 @@ from . import ptt from .gpml import _load_FeatureCollection from .pygplates import FeatureCollection as _FeatureCollection -from .read_geometries import ( - get_valid_geometries, -) # included for backwards compatibility from .reconstruction import PlateReconstruction as _PlateReconstruction from .tools import EARTH_RADIUS from .utils.feature_utils import shapelify_features as _shapelify_features -from .utils.plot_utils import ( - _clean_polygons, - _meridian_from_ax, - _plot_geometries, - plot_subduction_teeth, -) +from .utils.plot_utils import (_clean_polygons, _meridian_from_ax, + _plot_geometries) +from .utils.plot_utils import plot_subduction_teeth as _plot_subduction_teeth logger = logging.getLogger("gplately") -shapelify_features = _shapelify_features -shapelify_feature_lines = _shapelify_features -shapelify_feature_polygons = _shapelify_features + +def shapelify_features(*args, **kwargs): + return _shapelify_features(*args, **kwargs) + + +def shapelify_feature_lines(*args, **kwargs): + return _shapelify_features(*args, **kwargs) + + +def shapelify_feature_polygons(*args, **kwargs): + return _shapelify_features(*args, **kwargs) + + +def plot_subduction_teeth(*args, **kwargs): + return _plot_subduction_teeth(*args, **kwargs) + + +plot_subduction_teeth.__doc__ = _plot_subduction_teeth.__doc__ +shapelify_features.__doc__ = _shapelify_features.__doc__ +shapelify_feature_lines.__doc__ = _shapelify_features.__doc__ +shapelify_feature_polygons.__doc__ = _shapelify_features.__doc__ class PlotTopologies(object): @@ -1689,7 +1699,13 @@ def plot_plate_polygon_by_id(self, ax, plate_id, **kwargs): # the old function name(plot_plate_id) is bad. we should change the name # for backward compatibility, we have to allow users to use the old name - plot_plate_id = plot_plate_polygon_by_id + def plot_plate_id(self, *args, **kwargs): + logger.warn( + "The class method plot_plate_id will be deprecated in the future soon. Use plot_plate_polygon_by_id instead." + ) + return self.plot_plate_polygon_by_id(*args, **kwargs) + + plot_plate_id.__doc__ = plot_plate_polygon_by_id.__doc__ def plot_grid(self, ax, grid, extent=[-180, 180, -90, 90], **kwargs): """Plot a `MaskedArray` raster or grid onto a standard map Projection. @@ -3379,26 +3395,10 @@ def plot_all_topologies(self, ax, color="black", **kwargs): A standard cartopy.mpl.geoaxes.GeoAxes or cartopy.mpl.geoaxes.GeoAxesSubplot map with unclassified features plotted onto the chosen map projection. """ - if "transform" in kwargs.keys(): - warnings.warn( - "'transform' keyword argument is ignored by PlotTopologies", - UserWarning, - ) - kwargs.pop("transform") - tessellate_degrees = kwargs.pop("tessellate_degrees", 1) - central_meridian = kwargs.pop("central_meridian", None) - if central_meridian is None: - central_meridian = _meridian_from_ax(ax) - gdf = self.get_all_topologies( - central_meridian=central_meridian, - tessellate_degrees=tessellate_degrees, + return _plot_geometries( + ax, self.base_projection, color, self.get_all_topologies, **kwargs ) - if hasattr(ax, "projection"): - gdf = _clean_polygons(data=gdf, projection=ax.projection) - else: - kwargs["transform"] = self.base_projection - return gdf.plot(ax=ax, facecolor="none", edgecolor=color, **kwargs) def get_all_topological_sections( self, @@ -3530,26 +3530,10 @@ def plot_all_topological_sections(self, ax, color="black", **kwargs): A standard cartopy.mpl.geoaxes.GeoAxes or cartopy.mpl.geoaxes.GeoAxesSubplot map with unclassified features plotted onto the chosen map projection. """ - if "transform" in kwargs.keys(): - warnings.warn( - "'transform' keyword argument is ignored by PlotTopologies", - UserWarning, - ) - kwargs.pop("transform") - tessellate_degrees = kwargs.pop("tessellate_degrees", 1) - central_meridian = kwargs.pop("central_meridian", None) - if central_meridian is None: - central_meridian = _meridian_from_ax(ax) - gdf = self.get_all_topological_sections( - central_meridian=central_meridian, - tessellate_degrees=tessellate_degrees, + return _plot_geometries( + ax, self.base_projection, color, self.get_all_topological_sections, **kwargs ) - if hasattr(ax, "projection"): - gdf = _clean_polygons(data=gdf, projection=ax.projection) - else: - kwargs["transform"] = self.base_projection - return gdf.plot(ax=ax, color=color, **kwargs) def get_ridges(self, central_meridian=0.0, tessellate_degrees=1): """Create a geopandas.GeoDataFrame object containing geometries of reconstructed ridge lines. @@ -3647,7 +3631,7 @@ def plot_ridges(self, ax, color="black", **kwargs): logger.warn( "Plate model does not have topology features. Unable to plot_ridges." ) - return + return ax return _plot_geometries( ax, self.base_projection, color, self.get_ridges, **kwargs diff --git a/gplately/read_geometries.py b/gplately/utils/io_utils.py similarity index 100% rename from gplately/read_geometries.py rename to gplately/utils/io_utils.py diff --git a/gplately/utils/log_utils.py b/gplately/utils/log_utils.py index 0aa2c3da..d9063331 100644 --- a/gplately/utils/log_utils.py +++ b/gplately/utils/log_utils.py @@ -7,7 +7,9 @@ # configurate the logging utility def setup_logging(): - cfg_file_path = f"{os.path.dirname(os.path.realpath(__file__))}/logging_config.yaml" + cfg_file_path = ( + f"{os.path.dirname(os.path.realpath(__file__))}/../logging_config.yaml" + ) if os.path.isfile(cfg_file_path): with open(cfg_file_path, "rt") as f: config = yaml.safe_load(f.read()) diff --git a/gplately/utils/plot_utils.py b/gplately/utils/plot_utils.py index d20aa5b5..55264d47 100644 --- a/gplately/utils/plot_utils.py +++ b/gplately/utils/plot_utils.py @@ -9,7 +9,7 @@ from shapely.geometry.base import BaseGeometry, BaseMultipartGeometry from shapely.ops import linemerge, substring -from ..read_geometries import get_geometries as _get_geometries +from .io_utils import get_geometries as _get_geometries logger = logging.getLogger("gplately") @@ -513,6 +513,11 @@ def _plot_geometries(ax, projection, color, get_data_func, **kwargs): central_meridian=central_meridian, tessellate_degrees=tessellate_degrees, ) + + if len(gdf) == 0: + logger.warn("No geometry found for plotting. Do nothing and return.") + return ax + if hasattr(ax, "projection"): gdf = _clean_polygons(data=gdf, projection=ax.projection) else: diff --git a/tests-dir/unittest/test_plot.py b/tests-dir/unittest/test_plot.py index 9694d504..8029cb87 100755 --- a/tests-dir/unittest/test_plot.py +++ b/tests-dir/unittest/test_plot.py @@ -44,17 +44,42 @@ def main(show=True): fig = plt.figure(figsize=(10, 5), dpi=96) ax = fig.add_subplot(111, projection=ccrs.Robinson(central_longitude=180)) - gplot.plot_continent_ocean_boundaries(ax, color="cornflowerblue") - gplot.plot_coastlines(ax, color="black") - gplot.plot_ridges_and_transforms(ax, color="red") - gplot.plot_trenches(ax, color="orange") - gplot.plot_subduction_teeth(ax, color="orange") - gplot.plot_ridges(ax, color="green") + plot_flag = { + "continent_ocean_boundaries": 1, + "coastlines": 1, + "ridges_and_transforms": 1, + "trenches": 1, + "subduction_teeth": 1, + "ridges": 1, + "all_topologies": 1, + "all_topological_sections": 1, + "plot_plate_polygon_by_id": 1, + } + + if plot_flag["continent_ocean_boundaries"]: + gplot.plot_continent_ocean_boundaries(ax, color="cornflowerblue") + if plot_flag["coastlines"]: + gplot.plot_coastlines(ax, color="black") + if plot_flag["ridges_and_transforms"]: + gplot.plot_ridges_and_transforms(ax, color="red") + if plot_flag["trenches"]: + gplot.plot_trenches(ax, color="orange") + if plot_flag["subduction_teeth"]: + gplot.plot_subduction_teeth(ax, color="orange") + if plot_flag["ridges"]: + gplot.plot_ridges(ax, color="green") + if plot_flag["all_topologies"]: + gplot.plot_all_topologies(ax, color="red") + if plot_flag["all_topological_sections"]: + gplot.plot_all_topological_sections(ax, color="red") ax.set_global() ids = set([f.get_reconstruction_plate_id() for f in gplot.topologies]) for id in ids: - gplot.plot_plate_id(ax, id, facecolor="None", edgecolor="lightgreen") + if plot_flag["plot_plate_polygon_by_id"]: + gplot.plot_plate_polygon_by_id( + ax, id, facecolor="None", edgecolor="lightgreen" + ) plt.title(f"{age} Ma") if show: