Skip to content

Commit

Permalink
Adjust locations of CartoPy and Shapely imports
Browse files Browse the repository at this point in the history
  • Loading branch information
23ccozad committed Jul 26, 2021
1 parent 8728e9c commit 9cae783
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
23 changes: 13 additions & 10 deletions src/metpy/plots/declarative.py
Expand Up @@ -1840,8 +1840,6 @@ def copy(self):
class PlotGeometry(HasTraits):
"""Plot collections of Shapely objects and customize their appearance."""

import shapely.geometry as shp

parent = Instance(Panel)
_need_redraw = Bool(default_value=True)

Expand Down Expand Up @@ -1976,6 +1974,8 @@ def name(self):

def _position_label(self, geo_obj, label):
"""Return a (lon, lat) where the label of a polygon/line/point can be placed."""
from shapely.geometry import MultiLineString, MultiPoint, MultiPolygon, Polygon

# A hash of the label is used in choosing a point along the polygon or line that
# will be returned. This "psuedo-randomizes" the position of a label, in hopes of
# spatially dispersing the labels and lessening the chance that labels overlap.
Expand All @@ -1984,13 +1984,13 @@ def _position_label(self, geo_obj, label):
# If object is a MultiPolygon or MultiLineString, associate the label with the single
# largest Polygon or LineString from the collection. If MultiPoint, associate the label
# with one of the Points in the MultiPoint, chosen based on the label hash.
if isinstance(geo_obj, (self.shp.MultiPolygon, self.shp.MultiLineString)):
if isinstance(geo_obj, (MultiPolygon, MultiLineString)):
geo_obj = max(geo_obj, key=lambda x: x.length)
elif isinstance(geo_obj, self.shp.MultiPoint):
elif isinstance(geo_obj, MultiPoint):
geo_obj = geo_obj[label_hash % len(geo_obj)]

# Get the list of coordinates of the polygon/line/point
if isinstance(geo_obj, self.shp.Polygon):
if isinstance(geo_obj, Polygon):
coords = geo_obj.exterior.coords
else:
coords = geo_obj.coords
Expand Down Expand Up @@ -2041,6 +2041,9 @@ def copy(self):

def _build(self):
"""Build the plot by calling needed plotting methods as necessary."""
from shapely.geometry import (LineString, MultiLineString, MultiPoint, MultiPolygon,
Point, Polygon)

# Cast attributes to a list if None, since traitlets doesn't call validators (like
# `_valid_color_list()` and `_valid_labels()`) when the proposed value is None.
self.fill = ['none'] if self.fill is None else self.fill
Expand All @@ -2056,18 +2059,18 @@ def _build(self):
self.geometry, cycle(self.stroke), cycle(self.fill), cycle(self.labels),
cycle(self.label_facecolor), cycle(self.label_edgecolor)):
# Plot the Shapely object with the appropriate method and colors
if isinstance(geo_obj, (self.shp.MultiPolygon, self.shp.Polygon)):
if isinstance(geo_obj, (MultiPolygon, Polygon)):
self.parent.ax.add_geometries([geo_obj], edgecolor=stroke,
facecolor=fill, crs=ccrs.PlateCarree())
elif isinstance(geo_obj, (self.shp.MultiLineString, self.shp.LineString)):
elif isinstance(geo_obj, (MultiLineString, LineString)):
self.parent.ax.add_geometries([geo_obj], edgecolor=stroke,
facecolor='none', crs=ccrs.PlateCarree())
elif isinstance(geo_obj, self.shp.MultiPoint):
elif isinstance(geo_obj, MultiPoint):
for point in geo_obj:
lon, lat = point.coords[0]
self.parent.ax.plot(lon, lat, color=fill, marker=self.marker,
transform=ccrs.PlateCarree())
elif isinstance(geo_obj, self.shp.Point):
elif isinstance(geo_obj, Point):
lon, lat = geo_obj.coords[0]
self.parent.ax.plot(lon, lat, color=fill, marker=self.marker,
transform=ccrs.PlateCarree())
Expand All @@ -2091,7 +2094,7 @@ def _build(self):

# If polygon, put label directly on edge of polygon. If line or point, put
# label slightly below line/point.
if isinstance(geo_obj, (self.shp.MultiPolygon, self.shp.Polygon)):
if isinstance(geo_obj, (MultiPolygon, Polygon)):
offset = (0, 0)
else:
offset = (0, -12)
Expand Down
10 changes: 6 additions & 4 deletions tests/plots/test_declarative.py
Expand Up @@ -11,8 +11,6 @@
import numpy as np
import pandas as pd
import pytest
from shapely.geometry import (LineString, MultiLineString, MultiPoint, MultiPolygon, Point,
Polygon)
from traitlets import TraitError
import xarray as xr

Expand Down Expand Up @@ -1464,6 +1462,8 @@ def test_copy():
@needs_cartopy
def test_declarative_plot_geometry_polygons():
"""Test that `PlotGeometry` correctly plots MultiPolygon and Polygon objects."""
from shapely.geometry import MultiPolygon, Polygon

# MultiPolygons and Polygons to plot
slgt_risk_polygon = MultiPolygon([Polygon(
[(-87.43, 41.86), (-91.13, 41.39), (-95.24, 40.99), (-97.47, 40.4), (-98.39, 41.38),
Expand Down Expand Up @@ -1503,9 +1503,10 @@ def test_declarative_plot_geometry_polygons():


@pytest.mark.mpl_image_compare(remove_text=False, tolerance=2.985)
@needs_cartopy
def test_declarative_plot_geometry_lines(ccrs):
"""Test that `PlotGeometry` correctly plots MultiLineString and LineString objects."""
from shapely.geometry import LineString, MultiLineString

# LineString and MultiLineString to plot
irma_fcst = LineString(
[(-52.3, 16.9), (-53.9, 16.7), (-56.2, 16.6), (-58.6, 17.0), (-61.2, 17.8),
Expand Down Expand Up @@ -1541,9 +1542,10 @@ def test_declarative_plot_geometry_lines(ccrs):


@pytest.mark.mpl_image_compare(remove_text=False, tolerance=1.900)
@needs_cartopy
def test_declarative_plot_geometry_points(ccrs):
"""Test that `PlotGeometry` correctly plots Point and MultiPoint objects."""
from shapely.geometry import MultiPoint, Point

# Points and MultiPoints to plot
irma_track = [Point(-74.7, 21.8), Point(-76.0, 22.0), Point(-77.2, 22.1)]
irma_track_shadow = MultiPoint([
Expand Down

0 comments on commit 9cae783

Please sign in to comment.