1# Copyright Cartopy Contributors 2# 3# This file is part of Cartopy and is released under the LGPL license. 4# See COPYING and COPYING.LESSER in the root of the repository for full 5# licensing details. 6 7from unittest import mock 8 9from matplotlib.testing.decorators import cleanup 10import matplotlib.path as mpath 11import matplotlib.pyplot as plt 12import numpy as np 13import pytest 14 15import cartopy.crs as ccrs 16from cartopy.mpl.geoaxes import InterProjectionTransform, GeoAxes 17from cartopy.tests.mpl import ImageTesting 18from cartopy.tests.mpl.test_caching import CallCounter 19 20 21class TestNoSpherical: 22 def setup_method(self): 23 self.ax = plt.axes(projection=ccrs.PlateCarree()) 24 self.data = np.arange(12).reshape((3, 4)) 25 26 def teardown_method(self): 27 plt.clf() 28 plt.close() 29 30 def test_contour(self): 31 with pytest.raises(ValueError): 32 self.ax.contour(self.data, transform=ccrs.Geodetic()) 33 34 def test_contourf(self): 35 with pytest.raises(ValueError): 36 self.ax.contourf(self.data, transform=ccrs.Geodetic()) 37 38 def test_pcolor(self): 39 with pytest.raises(ValueError): 40 self.ax.pcolor(self.data, transform=ccrs.Geodetic()) 41 42 def test_pcolormesh(self): 43 with pytest.raises(ValueError): 44 self.ax.pcolormesh(self.data, transform=ccrs.Geodetic()) 45 46 47def test_transform_PlateCarree_shortcut(): 48 src = ccrs.PlateCarree(central_longitude=0) 49 target = ccrs.PlateCarree(central_longitude=180) 50 51 # of the 3 paths, 2 of them cannot be short-cutted. 52 pth1 = mpath.Path([[0.5, 0], [10, 10]]) 53 pth2 = mpath.Path([[0.5, 91], [10, 10]]) 54 pth3 = mpath.Path([[-0.5, 0], [10, 10]]) 55 56 trans = InterProjectionTransform(src, target) 57 58 counter = CallCounter(target, 'project_geometry') 59 60 with counter: 61 trans.transform_path(pth1) 62 # pth1 should allow a short-cut. 63 assert counter.count == 0 64 65 with counter: 66 trans.transform_path(pth2) 67 assert counter.count == 1 68 69 with counter: 70 trans.transform_path(pth3) 71 assert counter.count == 2 72 73 74class Test_InterProjectionTransform: 75 def pc_2_pc(self): 76 return InterProjectionTransform( 77 ccrs.PlateCarree(), ccrs.PlateCarree()) 78 79 def pc_2_rob(self): 80 return InterProjectionTransform(ccrs.PlateCarree(), ccrs.Robinson()) 81 82 def rob_2_rob_shifted(self): 83 return InterProjectionTransform( 84 ccrs.Robinson(), ccrs.Robinson(central_longitude=0)) 85 86 def test_eq(self): 87 assert self.pc_2_pc() == self.pc_2_pc() 88 assert self.pc_2_rob() == self.pc_2_rob() 89 assert self.rob_2_rob_shifted() == self.rob_2_rob_shifted() 90 91 assert not self.pc_2_rob() == self.rob_2_rob_shifted() 92 assert not self.pc_2_pc() == 'not a transform obj' 93 94 def test_ne(self): 95 assert not self.pc_2_pc() != self.pc_2_pc() 96 print(self.pc_2_pc() != self.pc_2_rob()) 97 assert self.pc_2_pc() != self.pc_2_rob() 98 99 100class Test_Axes_add_geometries: 101 def teardown_method(self): 102 plt.close() 103 104 @mock.patch('cartopy.mpl.geoaxes.GeoAxes.add_feature') 105 @mock.patch('cartopy.feature.ShapelyFeature') 106 def test_styler_kwarg(self, ShapelyFeature, add_feature_method): 107 ax = GeoAxes(plt.figure(), [0, 0, 1, 1], 108 map_projection=ccrs.Robinson()) 109 ax.add_geometries(mock.sentinel.geometries, mock.sentinel.crs, 110 styler=mock.sentinel.styler, wibble='wobble') 111 112 ShapelyFeature.assert_called_once_with( 113 mock.sentinel.geometries, mock.sentinel.crs, wibble='wobble') 114 115 add_feature_method.assert_called_once_with( 116 ShapelyFeature(), styler=mock.sentinel.styler) 117 118 119@cleanup 120def test_geoaxes_subplot(): 121 ax = plt.subplot(1, 1, 1, projection=ccrs.PlateCarree()) 122 assert str(ax.__class__) == "<class 'cartopy.mpl.geoaxes.GeoAxesSubplot'>" 123 124 125@ImageTesting(['geoaxes_subslice']) 126def test_geoaxes_no_subslice(): 127 """Test that we do not trigger matplotlib's line subslice optimization.""" 128 # This behavior caused lines with > 1000 points and 129 # sorted data to disappear 130 131 fig, axes = plt.subplots(1, 2, subplot_kw={'projection': ccrs.Mercator()}) 132 for ax, num_points in zip(axes, [1000, 1001]): 133 lats = np.linspace(35, 37, num_points) 134 lons = np.linspace(-117, -115, num_points) 135 ax.plot(lons, lats, transform=ccrs.PlateCarree()) 136 137 138@ImageTesting(['geoaxes_set_boundary_clipping']) 139def test_geoaxes_set_boundary_clipping(): 140 """Test that setting the boundary works properly for clipping #1620.""" 141 lon, lat = np.meshgrid(np.linspace(-180., 180., 361), 142 np.linspace(-90., -60., 31)) 143 fig = plt.figure() 144 ax1 = fig.add_subplot(1, 1, 1, projection=ccrs.SouthPolarStereo()) 145 146 # Limit the map to -60 degrees latitude and below. 147 ax1.set_extent([-180, 180, -90, -60], ccrs.PlateCarree()) 148 ax1.gridlines() 149 150 ax1.contourf(lon, lat, lat, transform=ccrs.PlateCarree()) 151 152 ax1.set_boundary(mpath.Path.circle(center=(0.5, 0.5), radius=0.5), 153 transform=ax1.transAxes) 154