Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address Shapely 2.0 Deprecations #1930

Merged
merged 2 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ jobs:
if: matrix.python-version == '3.7' && matrix.os == 'macos-latest'
id: minimum-packages
run: |
echo "PACKAGES=cython=0.28.5 matplotlib=3.1 numpy=1.18 owslib=0.17 pyproj=3.0 proj=8.0 scipy=1.2.0" >> $GITHUB_ENV
echo "PACKAGES=cython=0.28.5 matplotlib=3.1 numpy=1.18 owslib=0.17 pyproj=3.0 proj=8.0 scipy=1.2.0 shapely=1.6.4" >> $GITHUB_ENV
echo "CFLAGS=-stdlib=libc++" >> $GITHUB_ENV

- name: Latest packages
if: steps.minimum-packages.conclusion == 'skipped'
run: |
echo "PACKAGES=cython fiona matplotlib-base numpy pyproj pykdtree scipy" >> $GITHUB_ENV
echo "PACKAGES=cython fiona matplotlib-base numpy pyproj pykdtree scipy shapely" >> $GITHUB_ENV

- name: Coverage packages
id: coverage
Expand Down
10 changes: 5 additions & 5 deletions lib/cartopy/crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
threshold = max(np.abs(self.x_limits + self.y_limits)) * 1e-5

# 2) Simplify the segments where appropriate.
if len(multi_line_string) > 1:
if len(multi_line_string.geoms) > 1:
# Stitch together segments which are close to continuous.
# This is important when:
# 1) The first source point projects into the map and the
Expand All @@ -833,7 +833,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
# 2) The cut ends of segments are too close to reliably
# place into an order along the boundary.

line_strings = list(multi_line_string)
line_strings = list(multi_line_string.geoms)
any_modified = False
i = 0
if debug:
Expand Down Expand Up @@ -874,7 +874,7 @@ def _project_linear_ring(self, linear_ring, src_crs):
# 3) Check for rings that have been created by the projection stage.
rings = []
line_strings = []
for line in multi_line_string:
for line in multi_line_string.geoms:
if len(line.coords) > 3 and np.allclose(line.coords[0],
line.coords[-1],
atol=threshold):
Expand Down Expand Up @@ -941,7 +941,7 @@ def _project_polygon(self, polygon, src_crs):
p_rings, p_mline = self._project_linear_ring(src_ring, src_crs)
if p_rings:
rings.extend(p_rings)
if len(p_mline) > 0:
if len(p_mline.geoms) > 0:
multi_lines.append(p_mline)

# Convert any lines to rings by attaching them to the boundary.
Expand Down Expand Up @@ -979,7 +979,7 @@ def boundary_distance(xy):
# Squash all the LineStrings into a single list.
line_strings = []
for multi_line_string in multi_line_strings:
line_strings.extend(multi_line_string)
line_strings.extend(multi_line_string.geoms)

# Record the positions of all the segment ends
for i, line_string in enumerate(line_strings):
Expand Down
2 changes: 1 addition & 1 deletion lib/cartopy/io/ogc_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def _target_extents(extent, requested_projection, available_projection):

# Return the polygons' rectangular bounds as extent tuples.
target_extents = []
for poly in polys:
for poly in polys.geoms:
min_x, min_y, max_x, max_y = poly.bounds
if fudge_mode:
# If we shrunk the request area before, then here we
Expand Down
11 changes: 8 additions & 3 deletions lib/cartopy/mpl/gridliner.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,15 +839,20 @@ def update_artist(artist, renderer):
sgeom.MultiLineString)):
if isinstance(intersection, sgeom.LineString):
intersection = [intersection]
elif len(intersection) > 4:
elif len(intersection.geoms) > 4:
# Gridline and map boundary are parallel and they
# intersect themselves too much it results in a
# multiline string that must be converted to a single
# linestring. This is an empirical workaround for a
# problem that can probably be solved in a cleaner way.
xy = np.append(intersection[0], intersection[-1],
axis=0)
xy = np.append(
intersection.geoms[0].coords,
intersection.geoms[-1].coords,
axis=0,
)
intersection = [sgeom.LineString(xy)]
else:
intersection = intersection.geoms
tails = []
heads = []
for inter in intersection:
Expand Down
7 changes: 5 additions & 2 deletions lib/cartopy/tests/crs/test_albers_equal_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ def test_central_longitude(self, lon):
'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'}
check_proj_params('aea', aea_offset, other_args)

assert_array_almost_equal(aea_offset.boundary, aea.boundary,
decimal=0)
assert_array_almost_equal(
aea_offset.boundary.coords,
aea.boundary.coords,
decimal=0,
)

def test_standard_parallels(self):
aea = ccrs.AlbersEqualArea(standard_parallels=(13, 37))
Expand Down
7 changes: 5 additions & 2 deletions lib/cartopy/tests/crs/test_equidistant_conic.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ def test_central_longitude(self, lon):
'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'}
check_proj_params('eqdc', eqdc_offset, other_args)

assert_array_almost_equal(eqdc_offset.boundary, eqdc.boundary,
decimal=0)
assert_array_almost_equal(
eqdc_offset.boundary.coords,
eqdc.boundary.coords,
decimal=0,
)

def test_standard_parallels(self):
eqdc = ccrs.EquidistantConic(standard_parallels=(13, 37))
Expand Down
6 changes: 3 additions & 3 deletions lib/cartopy/tests/test_crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ def test_project_point(self):

result = pc_rotated.project_geometry(multi_point, pc)
assert isinstance(result, sgeom.MultiPoint)
assert len(result) == 2
assert_arr_almost_eq(result[0].xy, [[-180.], [45.]])
assert_arr_almost_eq(result[1].xy, [[0], [45.]])
assert len(result.geoms) == 2
assert_arr_almost_eq(result.geoms[0].xy, [[-180.], [45.]])
assert_arr_almost_eq(result.geoms[1].xy, [[0], [45.]])

def test_utm(self):
utm30n = ccrs.UTM(30)
Expand Down
72 changes: 36 additions & 36 deletions lib/cartopy/tests/test_line_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_out_of_bounds(self):
expected = 0
else:
expected = 1
assert len(multi_line_string) == expected, \
assert len(multi_line_string.geoms) == expected, \
f'Unexpected line when working from {start} to {end}'

def test_simple_fragment_count(self):
Expand All @@ -51,15 +51,15 @@ def test_simple_fragment_count(self):
multi_line_string = projection.project_geometry(line_string)
# from cartopy.tests.mpl import show
# show(projection, multi_line_string)
assert len(multi_line_string) == pieces
assert len(multi_line_string.geoms) == pieces

def test_split(self):
projection = ccrs.Robinson(170.5)
line_string = sgeom.LineString([(-10, 30), (10, 60)])
multi_line_string = projection.project_geometry(line_string)
# from cartopy.tests.mpl import show
# show(projection, multi_line_string)
assert len(multi_line_string) == 2
assert len(multi_line_string.geoms) == 2

def test_out_of_domain_efficiency(self):
# Check we're efficiently dealing with lines that project
Expand Down Expand Up @@ -103,80 +103,80 @@ def test_repeated_point(self):
projection = FakeProjection()
line_string = sgeom.LineString([(10, 0), (10, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_interior_repeated_point(self):
projection = FakeProjection()
line_string = sgeom.LineString([(0, 0), (10, 0), (10, 0), (20, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 4
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 4

def test_circular_repeated_point(self):
projection = FakeProjection()
line_string = sgeom.LineString([(0, 0), (360, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_short(self):
projection = FakeProjection()
line_string = sgeom.LineString([(0, 0), (1e-12, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_empty(self):
projection = FakeProjection(right_offset=10)
line_string = sgeom.LineString([(175, 0), (175, 10)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 0
assert len(multi_line_string.geoms) == 0

def test_simple_run_in(self):
projection = FakeProjection(right_offset=10)
line_string = sgeom.LineString([(160, 0), (175, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_simple_wrap(self):
projection = FakeProjection()
line_string = sgeom.LineString([(160, 0), (-160, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 2
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string[1].coords) == 2
assert len(multi_line_string.geoms) == 2
assert len(multi_line_string.geoms[0].coords) == 2
assert len(multi_line_string.geoms[1].coords) == 2

def test_simple_run_out(self):
projection = FakeProjection(left_offset=10)
line_string = sgeom.LineString([(-175, 0), (-160, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_point_on_boundary(self):
projection = FakeProjection()
line_string = sgeom.LineString([(180, 0), (-160, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

# Add a small offset to the left-hand boundary to make things
# even more pathological.
projection = FakeProjection(left_offset=5)
line_string = sgeom.LineString([(180, 0), (-160, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_nan_start(self):
projection = ccrs.TransverseMercator(central_longitude=-90,
approx=False)
line_string = sgeom.LineString([(10, 50), (-10, 30)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
for line_string in multi_line_string:
assert len(multi_line_string.geoms) == 1
for line_string in multi_line_string.geoms:
for coord in line_string.coords:
assert not any(np.isnan(coord)), \
'Unexpected NaN in projected coords.'
Expand All @@ -188,8 +188,8 @@ def test_nan_end(self):
multi_line_string = projection.project_geometry(line_string)
# from cartopy.tests.mpl import show
# show(projection, multi_line_string)
assert len(multi_line_string) == 1
for line_string in multi_line_string:
assert len(multi_line_string.geoms) == 1
for line_string in multi_line_string.geoms:
for coord in line_string.coords:
assert not any(np.isnan(coord)), \
'Unexpected NaN in projected coords.'
Expand All @@ -203,7 +203,7 @@ def test_misc(self):
multi_line_string = projection.project_geometry(line_string)
# from cartopy.tests.mpl import show
# show(projection, multi_line_string)
for line_string in multi_line_string:
for line_string in multi_line_string.geoms:
for coord in line_string.coords:
assert not any(np.isnan(coord)), \
'Unexpected NaN in projected coords.'
Expand All @@ -213,20 +213,20 @@ def test_something(self):
pole_latitude=37.5)
line_string = sgeom.LineString([(0, 0), (1e-14, 0)])
multi_line_string = projection.project_geometry(line_string)
assert len(multi_line_string) == 1
assert len(multi_line_string[0].coords) == 2
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string.geoms[0].coords) == 2

def test_global_boundary(self):
linear_ring = sgeom.LineString([(-180, -180), (-180, 180),
(180, 180), (180, -180)])
pc = ccrs.PlateCarree()
merc = ccrs.Mercator()
multi_line_string = pc.project_geometry(linear_ring, merc)
assert len(multi_line_string) > 0
assert len(multi_line_string.geoms) > 0

# check the identity transform
multi_line_string = merc.project_geometry(linear_ring, merc)
assert len(multi_line_string) > 0
assert len(multi_line_string.geoms) > 0


class TestSymmetry:
Expand All @@ -244,9 +244,9 @@ def test_curve(self):

# Make sure that they generated the same points.
# (Although obviously they will be in the opposite order!)
assert len(multi_line_string) == 1
assert len(multi_line_string2) == 1
coords = multi_line_string[0].coords
coords2 = multi_line_string2[0].coords
assert len(multi_line_string.geoms) == 1
assert len(multi_line_string2.geoms) == 1
coords = multi_line_string.geoms[0].coords
coords2 = multi_line_string2.geoms[0].coords
np.testing.assert_allclose(coords, coords2[::-1],
err_msg='Asymmetric curve generation')
14 changes: 7 additions & 7 deletions lib/cartopy/tests/test_linear_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_cuts(self):
rings, multi_line_string = projection.project_geometry(linear_ring)

# The original ring should have been split into multiple pieces.
assert len(multi_line_string) > 1
assert len(multi_line_string.geoms) > 1
assert not rings

def assert_intersection_with_boundary(segment_coords):
Expand All @@ -37,7 +37,7 @@ def assert_intersection_with_boundary(segment_coords):
# segment that crosses the boundary when extended to double length.
# (This is important when considering polygon rings which need to be
# attached to the boundary.)
for line_string in multi_line_string:
for line_string in multi_line_string.geoms:
coords = list(line_string.coords)
assert len(coords) >= 2
assert_intersection_with_boundary(coords[1::-1])
Expand Down Expand Up @@ -68,7 +68,7 @@ def test_out_of_bounds(self):
assert rings
assert not mlinestr
else:
assert len(mlinestr) == expected_n_lines
assert len(mlinestr.geoms) == expected_n_lines
if expected_n_lines == 0:
assert mlinestr.is_empty

Expand All @@ -86,7 +86,7 @@ def test_small(self):
rings, multi_line_string = projection.project_geometry(linear_ring)
# There should be one, and only one, returned ring.
assert isinstance(multi_line_string, sgeom.MultiLineString)
assert len(multi_line_string) == 0
assert len(multi_line_string.geoms) == 0
assert len(rings) == 1

# from cartopy.tests.mpl import show
Expand Down Expand Up @@ -135,13 +135,13 @@ def test_stitch(self):

linear_ring = sgeom.LinearRing(coords)
rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj)
assert len(mlinestr) == 1
assert len(mlinestr.geoms) == 1
assert len(rings) == 0

# Check the stitch works in either direction.
linear_ring = sgeom.LinearRing(coords[::-1])
rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj)
assert len(mlinestr) == 1
assert len(mlinestr.geoms) == 1
assert len(rings) == 0

def test_at_boundary(self):
Expand Down Expand Up @@ -170,7 +170,7 @@ def test_at_boundary(self):
rings, mlinestr = tcrs._project_linear_ring(tring, scrs)

# Number of linearstrings
assert len(mlinestr) == 4
assert len(mlinestr.geoms) == 4
assert not rings

# Test area of smallest Polygon that contains all the points in the
Expand Down
Loading