hvplot 0.9.3a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hvplot/__init__.py +322 -0
- hvplot/_version.py +16 -0
- hvplot/backend_transforms.py +329 -0
- hvplot/converter.py +2855 -0
- hvplot/cudf.py +26 -0
- hvplot/dask.py +42 -0
- hvplot/data/crime.csv +56 -0
- hvplot/datasets.yaml +48 -0
- hvplot/fugue.py +64 -0
- hvplot/ibis.py +21 -0
- hvplot/intake.py +32 -0
- hvplot/interactive.py +968 -0
- hvplot/networkx.py +625 -0
- hvplot/pandas.py +30 -0
- hvplot/plotting/__init__.py +63 -0
- hvplot/plotting/andrews_curves.py +99 -0
- hvplot/plotting/core.py +2288 -0
- hvplot/plotting/lag_plot.py +34 -0
- hvplot/plotting/parallel_coordinates.py +85 -0
- hvplot/plotting/scatter_matrix.py +220 -0
- hvplot/polars.py +21 -0
- hvplot/sample_data.py +30 -0
- hvplot/streamz.py +21 -0
- hvplot/tests/__init__.py +0 -0
- hvplot/tests/conftest.py +44 -0
- hvplot/tests/data/README.md +5 -0
- hvplot/tests/data/RGB-red.byte.tif +0 -0
- hvplot/tests/plotting/__init__.py +0 -0
- hvplot/tests/plotting/testcore.py +108 -0
- hvplot/tests/plotting/testohlc.py +34 -0
- hvplot/tests/plotting/testscattermatrix.py +138 -0
- hvplot/tests/test_links.py +99 -0
- hvplot/tests/testbackend_transforms.py +89 -0
- hvplot/tests/testcharts.py +452 -0
- hvplot/tests/testfugue.py +46 -0
- hvplot/tests/testgeo.py +468 -0
- hvplot/tests/testgeowithoutgv.py +60 -0
- hvplot/tests/testgridplots.py +259 -0
- hvplot/tests/testhelp.py +75 -0
- hvplot/tests/testibis.py +17 -0
- hvplot/tests/testinteractive.py +1442 -0
- hvplot/tests/testnetworkx.py +26 -0
- hvplot/tests/testoperations.py +385 -0
- hvplot/tests/testoptions.py +596 -0
- hvplot/tests/testoverrides.py +74 -0
- hvplot/tests/testpanel.py +70 -0
- hvplot/tests/testpatch.py +135 -0
- hvplot/tests/testplotting.py +69 -0
- hvplot/tests/teststreaming.py +28 -0
- hvplot/tests/testtransforms.py +39 -0
- hvplot/tests/testui.py +383 -0
- hvplot/tests/testutil.py +378 -0
- hvplot/tests/util.py +82 -0
- hvplot/ui.py +1032 -0
- hvplot/util.py +677 -0
- hvplot/utilities.py +129 -0
- hvplot/xarray.py +62 -0
- hvplot-0.9.3a1.dist-info/LICENSE +29 -0
- hvplot-0.9.3a1.dist-info/METADATA +243 -0
- hvplot-0.9.3a1.dist-info/RECORD +63 -0
- hvplot-0.9.3a1.dist-info/WHEEL +5 -0
- hvplot-0.9.3a1.dist-info/entry_points.txt +2 -0
- hvplot-0.9.3a1.dist-info/top_level.txt +1 -0
hvplot/tests/testgeo.py
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
"""
|
|
2
|
+
These tests depends on GeoViews.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import pathlib
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from unittest import TestCase, SkipTest
|
|
9
|
+
|
|
10
|
+
import holoviews as hv
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pandas as pd
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
from hvplot.util import proj_to_cartopy
|
|
16
|
+
from packaging.version import Version
|
|
17
|
+
|
|
18
|
+
pytestmark = pytest.mark.geo
|
|
19
|
+
|
|
20
|
+
bk_renderer = hv.Store.renderers['bokeh']
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def simple_df():
|
|
25
|
+
return pd.DataFrame(np.random.rand(10, 2), columns=['x', 'y'])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TestGeo(TestCase):
|
|
29
|
+
def setUp(self):
|
|
30
|
+
if sys.platform == 'win32':
|
|
31
|
+
raise SkipTest('Skip geo tests on windows for now')
|
|
32
|
+
try:
|
|
33
|
+
import xarray as xr # noqa
|
|
34
|
+
import rasterio # noqa
|
|
35
|
+
import geoviews # noqa
|
|
36
|
+
import cartopy.crs as ccrs # noqa
|
|
37
|
+
import pyproj # noqa
|
|
38
|
+
import rioxarray as rxr
|
|
39
|
+
except ImportError:
|
|
40
|
+
raise SkipTest(
|
|
41
|
+
'xarray, rasterio, geoviews, cartopy, pyproj or rioxarray not available'
|
|
42
|
+
)
|
|
43
|
+
import hvplot.xarray # noqa
|
|
44
|
+
import hvplot.pandas # noqa
|
|
45
|
+
|
|
46
|
+
self.da = rxr.open_rasterio(
|
|
47
|
+
pathlib.Path(__file__).parent / 'data' / 'RGB-red.byte.tif'
|
|
48
|
+
).isel(band=0)
|
|
49
|
+
self.crs = proj_to_cartopy(self.da.spatial_ref.attrs['crs_wkt'])
|
|
50
|
+
|
|
51
|
+
def assertCRS(self, plot, proj='utm'):
|
|
52
|
+
import cartopy
|
|
53
|
+
|
|
54
|
+
if Version(cartopy.__version__) < Version('0.20'):
|
|
55
|
+
assert plot.crs.proj4_params['proj'] == proj
|
|
56
|
+
else:
|
|
57
|
+
assert plot.crs.to_dict()['proj'] == proj
|
|
58
|
+
|
|
59
|
+
def assert_projection(self, plot, proj):
|
|
60
|
+
opts = hv.Store.lookup_options('bokeh', plot, 'plot')
|
|
61
|
+
assert opts.kwargs['projection'].proj4_params['proj'] == proj
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class TestCRSInference(TestGeo):
|
|
65
|
+
def setUp(self):
|
|
66
|
+
if sys.platform == 'win32':
|
|
67
|
+
raise SkipTest('Skip CRS inference on Windows')
|
|
68
|
+
super().setUp()
|
|
69
|
+
|
|
70
|
+
def test_plot_with_crs_as_proj_string(self):
|
|
71
|
+
da = self.da.copy()
|
|
72
|
+
da.rio._crs = False # To not treat it as a rioxarray
|
|
73
|
+
|
|
74
|
+
plot = self.da.hvplot.image('x', 'y', crs='epsg:32618')
|
|
75
|
+
self.assertCRS(plot)
|
|
76
|
+
|
|
77
|
+
def test_plot_with_geo_as_true_crs_undefined(self):
|
|
78
|
+
plot = self.da.hvplot.image('x', 'y', geo=True)
|
|
79
|
+
self.assertCRS(plot)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class TestProjections(TestGeo):
|
|
83
|
+
def test_plot_with_crs_as_object(self):
|
|
84
|
+
plot = self.da.hvplot.image('x', 'y', crs=self.crs)
|
|
85
|
+
self.assertCRS(plot)
|
|
86
|
+
|
|
87
|
+
def test_plot_with_crs_as_attr_str(self):
|
|
88
|
+
da = self.da.copy()
|
|
89
|
+
da.rio._crs = False # To not treat it as a rioxarray
|
|
90
|
+
da.attrs = {'bar': self.crs}
|
|
91
|
+
plot = da.hvplot.image('x', 'y', crs='bar')
|
|
92
|
+
self.assertCRS(plot)
|
|
93
|
+
|
|
94
|
+
def test_plot_with_crs_as_pyproj_Proj(self):
|
|
95
|
+
import pyproj
|
|
96
|
+
|
|
97
|
+
da = self.da.copy()
|
|
98
|
+
da.rio._crs = False # To not treat it as a rioxarray
|
|
99
|
+
plot = da.hvplot.image('x', 'y', crs=pyproj.Proj(self.crs))
|
|
100
|
+
self.assertCRS(plot)
|
|
101
|
+
|
|
102
|
+
def test_plot_with_crs_as_nonexistent_attr_str(self):
|
|
103
|
+
da = self.da.copy()
|
|
104
|
+
da.rio._crs = False # To not treat it as a rioxarray
|
|
105
|
+
|
|
106
|
+
# Used to test crs='foo' but this is parsed under-the-hood
|
|
107
|
+
# by PROJ (projinfo) which matches a geographic projection named
|
|
108
|
+
# 'Amersfoort'
|
|
109
|
+
with self.assertRaisesRegex(ValueError, "'name_of_some_invalid_projection' must be"):
|
|
110
|
+
da.hvplot.image('x', 'y', crs='name_of_some_invalid_projection')
|
|
111
|
+
|
|
112
|
+
def test_plot_with_geo_as_true_crs_no_crs_on_data_returns_default(self):
|
|
113
|
+
da = self.da.copy()
|
|
114
|
+
da.rio._crs = False # To not treat it as a rioxarray
|
|
115
|
+
da.attrs = {'bar': self.crs}
|
|
116
|
+
plot = da.hvplot.image('x', 'y', geo=True)
|
|
117
|
+
self.assertCRS(plot, 'eqc')
|
|
118
|
+
|
|
119
|
+
def test_plot_with_projection_as_string(self):
|
|
120
|
+
da = self.da.copy()
|
|
121
|
+
plot = da.hvplot.image('x', 'y', crs=self.crs, projection='Robinson')
|
|
122
|
+
self.assert_projection(plot, 'robin')
|
|
123
|
+
|
|
124
|
+
def test_plot_with_projection_as_string_google_mercator(self):
|
|
125
|
+
da = self.da.copy()
|
|
126
|
+
plot = da.hvplot.image('x', 'y', crs=self.crs, projection='GOOGLE_MERCATOR')
|
|
127
|
+
self.assert_projection(plot, 'merc')
|
|
128
|
+
|
|
129
|
+
def test_plot_with_projection_as_invalid_string(self):
|
|
130
|
+
with self.assertRaisesRegex(ValueError, 'Projection must be defined'):
|
|
131
|
+
self.da.hvplot.image('x', 'y', projection='foo')
|
|
132
|
+
|
|
133
|
+
def test_plot_with_projection_raises_an_error_when_tiles_set(self):
|
|
134
|
+
da = self.da.copy()
|
|
135
|
+
with self.assertRaisesRegex(ValueError, 'Tiles can only be used with output projection'):
|
|
136
|
+
da.hvplot.image('x', 'y', crs=self.crs, projection='Robinson', tiles=True)
|
|
137
|
+
|
|
138
|
+
def test_overlay_with_projection(self):
|
|
139
|
+
# Regression test for https://github.com/holoviz/hvplot/issues/1090
|
|
140
|
+
df = pd.DataFrame({'lon': [0, 10], 'lat': [40, 50], 'v': [0, 1]})
|
|
141
|
+
|
|
142
|
+
plot1 = df.hvplot.points(x='lon', y='lat', s=200, c='y', geo=True, tiles='CartoLight')
|
|
143
|
+
plot2 = df.hvplot.points(x='lon', y='lat', c='v', geo=True)
|
|
144
|
+
|
|
145
|
+
# This should work without erroring
|
|
146
|
+
plot = plot1 * plot2
|
|
147
|
+
hv.renderer('bokeh').get_plot(plot)
|
|
148
|
+
|
|
149
|
+
def test_geo_with_rasterize(self):
|
|
150
|
+
import xarray as xr
|
|
151
|
+
import cartopy.crs as ccrs
|
|
152
|
+
import geoviews as gv
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
from holoviews.operation.datashader import rasterize
|
|
156
|
+
except ImportError:
|
|
157
|
+
raise SkipTest('datashader not available')
|
|
158
|
+
|
|
159
|
+
ds = xr.tutorial.open_dataset('air_temperature')
|
|
160
|
+
hvplot_output = ds.isel(time=0).hvplot.points(
|
|
161
|
+
'lon',
|
|
162
|
+
'lat',
|
|
163
|
+
crs=ccrs.PlateCarree(),
|
|
164
|
+
projection=ccrs.LambertConformal(),
|
|
165
|
+
rasterize=True,
|
|
166
|
+
dynamic=False,
|
|
167
|
+
aggregator='max',
|
|
168
|
+
project=True,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
p1 = gv.Points(ds.isel(time=0), kdims=['lon', 'lat'], crs=ccrs.PlateCarree())
|
|
172
|
+
p2 = gv.project(p1, projection=ccrs.LambertConformal())
|
|
173
|
+
expected = rasterize(p2, dynamic=False, aggregator='max')
|
|
174
|
+
|
|
175
|
+
xr.testing.assert_allclose(hvplot_output.data, expected.data)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class TestGeoAnnotation(TestCase):
|
|
179
|
+
def setUp(self):
|
|
180
|
+
try:
|
|
181
|
+
import geoviews # noqa
|
|
182
|
+
import cartopy.crs as ccrs # noqa
|
|
183
|
+
except ImportError:
|
|
184
|
+
raise SkipTest('geoviews or cartopy not available')
|
|
185
|
+
import hvplot.pandas # noqa
|
|
186
|
+
|
|
187
|
+
self.crs = ccrs.PlateCarree()
|
|
188
|
+
self.df = pd.DataFrame(np.random.rand(10, 2), columns=['x', 'y'])
|
|
189
|
+
|
|
190
|
+
def test_plot_with_coastline(self):
|
|
191
|
+
import geoviews as gv
|
|
192
|
+
|
|
193
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, coastline=True)
|
|
194
|
+
self.assertEqual(len(plot), 2)
|
|
195
|
+
coastline = plot.get(1)
|
|
196
|
+
self.assertIsInstance(coastline, gv.Feature)
|
|
197
|
+
|
|
198
|
+
def test_plot_with_coastline_sets_geo_by_default(self):
|
|
199
|
+
import geoviews as gv
|
|
200
|
+
|
|
201
|
+
plot = self.df.hvplot.points('x', 'y', coastline=True)
|
|
202
|
+
self.assertEqual(len(plot), 2)
|
|
203
|
+
coastline = plot.get(1)
|
|
204
|
+
self.assertIsInstance(coastline, gv.Feature)
|
|
205
|
+
|
|
206
|
+
def test_plot_with_coastline_scale(self):
|
|
207
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, coastline='10m')
|
|
208
|
+
opts = plot.get(1).opts.get('plot')
|
|
209
|
+
assert opts.kwargs['scale'] == '10m'
|
|
210
|
+
|
|
211
|
+
def test_plot_with_tiles(self):
|
|
212
|
+
plot = self.df.hvplot.points('x', 'y', geo=False, tiles=True)
|
|
213
|
+
self.assertEqual(len(plot), 2)
|
|
214
|
+
self.assertIsInstance(plot.get(0), hv.Tiles)
|
|
215
|
+
self.assertIn('openstreetmap', plot.get(0).data)
|
|
216
|
+
|
|
217
|
+
def test_plot_with_tiles_with_tiles_opts(self):
|
|
218
|
+
plot = self.df.hvplot.points('x', 'y', geo=False, tiles=True, tiles_opts=dict(alpha=0.5))
|
|
219
|
+
assert len(plot) == 2
|
|
220
|
+
tiles = plot.get(0)
|
|
221
|
+
assert isinstance(tiles, hv.Tiles)
|
|
222
|
+
assert 'openstreetmap' in tiles.data
|
|
223
|
+
assert tiles.opts['alpha'] == 0.5
|
|
224
|
+
|
|
225
|
+
def test_plot_with_tiles_with_geo(self):
|
|
226
|
+
import geoviews as gv
|
|
227
|
+
|
|
228
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles=True)
|
|
229
|
+
self.assertEqual(len(plot), 2)
|
|
230
|
+
self.assertIsInstance(plot.get(0), gv.element.WMTS)
|
|
231
|
+
self.assertIn('openstreetmap', plot.get(0).data)
|
|
232
|
+
|
|
233
|
+
def test_plot_with_tiles_with_tiles_opts_with_geo(self):
|
|
234
|
+
import geoviews as gv
|
|
235
|
+
|
|
236
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles=True, tiles_opts=dict(alpha=0.5))
|
|
237
|
+
assert len(plot) == 2
|
|
238
|
+
tiles = plot.get(0)
|
|
239
|
+
assert isinstance(tiles, gv.element.WMTS)
|
|
240
|
+
assert 'openstreetmap' in tiles.data
|
|
241
|
+
assert tiles.opts['alpha'] == 0.5
|
|
242
|
+
|
|
243
|
+
def test_plot_with_specific_tiles(self):
|
|
244
|
+
plot = self.df.hvplot.points('x', 'y', geo=False, tiles='ESRI')
|
|
245
|
+
self.assertEqual(len(plot), 2)
|
|
246
|
+
self.assertIsInstance(plot.get(0), hv.Tiles)
|
|
247
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
248
|
+
|
|
249
|
+
def test_plot_with_specific_tiles_geo(self):
|
|
250
|
+
import geoviews as gv
|
|
251
|
+
|
|
252
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles='ESRI')
|
|
253
|
+
self.assertEqual(len(plot), 2)
|
|
254
|
+
self.assertIsInstance(plot.get(0), gv.element.WMTS)
|
|
255
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
256
|
+
|
|
257
|
+
def test_plot_with_specific_tile_class(self):
|
|
258
|
+
plot = self.df.hvplot.points('x', 'y', geo=False, tiles=hv.element.tiles.EsriImagery)
|
|
259
|
+
self.assertEqual(len(plot), 2)
|
|
260
|
+
self.assertIsInstance(plot.get(0), hv.Tiles)
|
|
261
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
262
|
+
|
|
263
|
+
def test_plot_with_specific_tile_class_with_geo(self):
|
|
264
|
+
import geoviews as gv
|
|
265
|
+
|
|
266
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles=gv.tile_sources.EsriImagery)
|
|
267
|
+
self.assertEqual(len(plot), 2)
|
|
268
|
+
self.assertIsInstance(plot.get(0), gv.element.WMTS)
|
|
269
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
270
|
+
|
|
271
|
+
def test_plot_with_specific_tile_obj(self):
|
|
272
|
+
plot = self.df.hvplot.points('x', 'y', geo=False, tiles=hv.element.tiles.EsriImagery())
|
|
273
|
+
self.assertEqual(len(plot), 2)
|
|
274
|
+
self.assertIsInstance(plot.get(0), hv.Tiles)
|
|
275
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
276
|
+
|
|
277
|
+
def test_plot_with_specific_tile_obj_with_geo(self):
|
|
278
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles=hv.element.tiles.EsriImagery())
|
|
279
|
+
self.assertEqual(len(plot), 2)
|
|
280
|
+
self.assertIsInstance(plot.get(0), hv.Tiles)
|
|
281
|
+
self.assertIn('ArcGIS', plot.get(0).data)
|
|
282
|
+
|
|
283
|
+
def test_plot_with_specific_gv_tile_obj(self):
|
|
284
|
+
import geoviews as gv
|
|
285
|
+
|
|
286
|
+
plot = self.df.hvplot.points('x', 'y', geo=True, tiles=gv.tile_sources.CartoDark)
|
|
287
|
+
self.assertEqual(len(plot), 2)
|
|
288
|
+
self.assertIsInstance(plot.get(0), gv.element.WMTS)
|
|
289
|
+
|
|
290
|
+
def test_plot_with_xyzservices_tiles(self):
|
|
291
|
+
xyzservices = pytest.importorskip('xyzservices')
|
|
292
|
+
import geoviews as gv
|
|
293
|
+
|
|
294
|
+
plot = self.df.hvplot.points(
|
|
295
|
+
'x', 'y', geo=True, tiles=xyzservices.providers.Esri.WorldImagery
|
|
296
|
+
)
|
|
297
|
+
assert len(plot) == 2
|
|
298
|
+
assert isinstance(plot.get(0), gv.element.WMTS)
|
|
299
|
+
assert isinstance(plot.get(0).data, xyzservices.TileProvider)
|
|
300
|
+
|
|
301
|
+
def test_plot_with_features_properly_overlaid_underlaid(self):
|
|
302
|
+
# land should be under, borders should be over
|
|
303
|
+
plot = self.df.hvplot.points('x', 'y', features=['land', 'borders'])
|
|
304
|
+
assert plot.get(0).group == 'Land'
|
|
305
|
+
assert plot.get(2).group == 'Borders'
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class TestGeoElements(TestCase):
|
|
309
|
+
def setUp(self):
|
|
310
|
+
try:
|
|
311
|
+
import geoviews # noqa
|
|
312
|
+
import cartopy.crs as ccrs # noqa
|
|
313
|
+
except ImportError:
|
|
314
|
+
raise SkipTest('geoviews or cartopy not available')
|
|
315
|
+
import hvplot.pandas # noqa
|
|
316
|
+
|
|
317
|
+
self.crs = ccrs.PlateCarree()
|
|
318
|
+
self.df = pd.DataFrame(np.random.rand(10, 2), columns=['x', 'y'])
|
|
319
|
+
|
|
320
|
+
def test_geo_hexbin(self):
|
|
321
|
+
hextiles = self.df.hvplot.hexbin('x', 'y', geo=True)
|
|
322
|
+
self.assertEqual(hextiles.crs, self.crs)
|
|
323
|
+
|
|
324
|
+
def test_geo_points(self):
|
|
325
|
+
points = self.df.hvplot.points('x', 'y', geo=True)
|
|
326
|
+
self.assertEqual(points.crs, self.crs)
|
|
327
|
+
|
|
328
|
+
def test_geo_points_color_internally_set_to_dim(self):
|
|
329
|
+
altered_df = self.df.copy().assign(red=np.random.choice(['a', 'b'], len(self.df)))
|
|
330
|
+
plot = altered_df.hvplot.points('x', 'y', c='red', geo=True)
|
|
331
|
+
opts = hv.Store.lookup_options('bokeh', plot, 'style')
|
|
332
|
+
self.assertIsInstance(opts.kwargs['color'], hv.dim)
|
|
333
|
+
self.assertEqual(opts.kwargs['color'].dimension.name, 'red')
|
|
334
|
+
|
|
335
|
+
def test_geo_opts(self):
|
|
336
|
+
points = self.df.hvplot.points('x', 'y', geo=True)
|
|
337
|
+
opts = hv.Store.lookup_options('bokeh', points, 'plot').kwargs
|
|
338
|
+
self.assertEqual(opts.get('data_aspect'), 1)
|
|
339
|
+
self.assertEqual(opts.get('width'), None)
|
|
340
|
+
|
|
341
|
+
def test_geo_opts_with_width(self):
|
|
342
|
+
points = self.df.hvplot.points('x', 'y', geo=True, width=200)
|
|
343
|
+
opts = hv.Store.lookup_options('bokeh', points, 'plot').kwargs
|
|
344
|
+
self.assertEqual(opts.get('data_aspect'), 1)
|
|
345
|
+
self.assertEqual(opts.get('width'), 200)
|
|
346
|
+
self.assertEqual(opts.get('height'), None)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class TestGeoPandas(TestCase):
|
|
350
|
+
def setUp(self):
|
|
351
|
+
try:
|
|
352
|
+
import geopandas as gpd # noqa
|
|
353
|
+
import geoviews # noqa
|
|
354
|
+
import cartopy.crs as ccrs # noqa
|
|
355
|
+
import shapely # noqa
|
|
356
|
+
except ImportError:
|
|
357
|
+
raise SkipTest('geopandas, geoviews, shapely or cartopy not available')
|
|
358
|
+
import hvplot.pandas # noqa
|
|
359
|
+
|
|
360
|
+
from shapely.geometry import Polygon
|
|
361
|
+
|
|
362
|
+
p_geometry = gpd.points_from_xy(
|
|
363
|
+
x=[12.45339, 12.44177, 9.51667, 6.13000, 158.14997],
|
|
364
|
+
y=[41.90328, 43.93610, 47.13372, 49.61166, 6.91664],
|
|
365
|
+
crs='EPSG:4326',
|
|
366
|
+
)
|
|
367
|
+
p_names = ['Vatican City', 'San Marino', 'Vaduz', 'Luxembourg', 'Palikir']
|
|
368
|
+
self.cities = gpd.GeoDataFrame(dict(name=p_names), geometry=p_geometry)
|
|
369
|
+
|
|
370
|
+
pg_geometry = [
|
|
371
|
+
Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))),
|
|
372
|
+
Polygon(((2, 2), (2, 3), (3, 3), (3, 2), (2, 2))),
|
|
373
|
+
]
|
|
374
|
+
pg_names = ['A', 'B']
|
|
375
|
+
self.polygons = gpd.GeoDataFrame(dict(name=pg_names), geometry=pg_geometry)
|
|
376
|
+
|
|
377
|
+
def test_points_hover_cols_is_empty_by_default(self):
|
|
378
|
+
points = self.cities.hvplot()
|
|
379
|
+
assert points.kdims == ['x', 'y']
|
|
380
|
+
assert points.vdims == []
|
|
381
|
+
|
|
382
|
+
def test_points_hover_cols_does_not_include_geometry_when_all(self):
|
|
383
|
+
points = self.cities.hvplot(x='x', y='y', hover_cols='all')
|
|
384
|
+
assert points.kdims == ['x', 'y']
|
|
385
|
+
assert points.vdims == ['index', 'name']
|
|
386
|
+
|
|
387
|
+
def test_points_hover_cols_when_all_and_use_columns_is_false(self):
|
|
388
|
+
points = self.cities.hvplot(x='x', hover_cols='all', use_index=False)
|
|
389
|
+
assert points.kdims == ['x', 'y']
|
|
390
|
+
assert points.vdims == ['name']
|
|
391
|
+
|
|
392
|
+
def test_points_hover_cols_index_in_list(self):
|
|
393
|
+
points = self.cities.hvplot(y='y', hover_cols=['index'])
|
|
394
|
+
assert points.kdims == ['x', 'y']
|
|
395
|
+
assert points.vdims == ['index']
|
|
396
|
+
|
|
397
|
+
def test_points_hover_cols_positional_arg_sets_color(self):
|
|
398
|
+
points = self.cities.hvplot('name')
|
|
399
|
+
assert points.kdims == ['x', 'y']
|
|
400
|
+
assert points.vdims == ['name']
|
|
401
|
+
opts = hv.Store.lookup_options('bokeh', points, 'style').kwargs
|
|
402
|
+
assert opts['color'] == 'name'
|
|
403
|
+
|
|
404
|
+
def test_points_hover_cols_with_c_set_to_name(self):
|
|
405
|
+
points = self.cities.hvplot(c='name')
|
|
406
|
+
assert points.kdims == ['x', 'y']
|
|
407
|
+
assert points.vdims == ['name']
|
|
408
|
+
opts = hv.Store.lookup_options('bokeh', points, 'style').kwargs
|
|
409
|
+
assert opts['color'] == 'name'
|
|
410
|
+
|
|
411
|
+
def test_points_hover_cols_with_by_set_to_name(self):
|
|
412
|
+
points = self.cities.hvplot(by='name')
|
|
413
|
+
assert isinstance(points, hv.core.overlay.NdOverlay)
|
|
414
|
+
assert points.kdims == ['name']
|
|
415
|
+
assert points.vdims == []
|
|
416
|
+
for element in points.values():
|
|
417
|
+
assert element.kdims == ['x', 'y']
|
|
418
|
+
assert element.vdims == []
|
|
419
|
+
|
|
420
|
+
def test_points_project_xlim_and_ylim(self):
|
|
421
|
+
points = self.cities.hvplot(geo=False, xlim=(-10, 10), ylim=(-20, -10))
|
|
422
|
+
opts = hv.Store.lookup_options('bokeh', points, 'plot').options
|
|
423
|
+
np.testing.assert_equal(opts['xlim'], (-10, 10))
|
|
424
|
+
np.testing.assert_equal(opts['ylim'], (-20, -10))
|
|
425
|
+
|
|
426
|
+
def test_points_project_xlim_and_ylim_with_geo(self):
|
|
427
|
+
points = self.cities.hvplot(geo=True, xlim=(-10, 10), ylim=(-20, -10))
|
|
428
|
+
opts = hv.Store.lookup_options('bokeh', points, 'plot').options
|
|
429
|
+
np.testing.assert_allclose(opts['xlim'], (-10, 10))
|
|
430
|
+
np.testing.assert_allclose(opts['ylim'], (-20, -10))
|
|
431
|
+
|
|
432
|
+
def test_polygons_by_subplots(self):
|
|
433
|
+
polygons = self.polygons.hvplot(geo=True, by='name', subplots=True)
|
|
434
|
+
assert isinstance(polygons, hv.core.layout.NdLayout)
|
|
435
|
+
|
|
436
|
+
def test_polygons_turns_off_hover_when_there_are_no_fields_to_include(self):
|
|
437
|
+
polygons = self.polygons.hvplot(geo=True)
|
|
438
|
+
opts = hv.Store.lookup_options('bokeh', polygons, 'plot').kwargs
|
|
439
|
+
assert 'hover' not in opts.get('tools')
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class TestGeoUtil(TestCase):
|
|
443
|
+
def setUp(self):
|
|
444
|
+
if sys.platform == 'win32':
|
|
445
|
+
raise SkipTest('Skip geo tests on windows for now')
|
|
446
|
+
try:
|
|
447
|
+
import cartopy.crs as ccrs
|
|
448
|
+
except ImportError:
|
|
449
|
+
raise SkipTest('cartopy not available')
|
|
450
|
+
self.ccrs = ccrs
|
|
451
|
+
|
|
452
|
+
def test_proj_to_cartopy(self):
|
|
453
|
+
from ..util import proj_to_cartopy
|
|
454
|
+
|
|
455
|
+
crs = proj_to_cartopy('+init=epsg:26911')
|
|
456
|
+
|
|
457
|
+
assert isinstance(crs, self.ccrs.CRS)
|
|
458
|
+
|
|
459
|
+
def test_proj_to_cartopy_wkt_string(self):
|
|
460
|
+
from ..util import proj_to_cartopy
|
|
461
|
+
|
|
462
|
+
crs = proj_to_cartopy(
|
|
463
|
+
'GEOGCRS["unnamed",BASEGEOGCRS["unknown",DATUM["unknown",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1,ID["EPSG",9001]]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8901]]],DERIVINGCONVERSION["unknown",METHOD["PROJ ob_tran o_proj=latlon"],PARAMETER["o_lon_p",0,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],PARAMETER["o_lat_p",37.5,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],PARAMETER["lon_0",357.5,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]]],CS[ellipsoidal,2],AXIS["longitude",east,ORDER[1],ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]],AXIS["latitude",north,ORDER[2],ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9122]]]]'
|
|
464
|
+
) # noqa: E501
|
|
465
|
+
|
|
466
|
+
assert isinstance(crs, self.ccrs.RotatedPole)
|
|
467
|
+
assert crs.proj4_params['lon_0'] == 357.5
|
|
468
|
+
assert crs.proj4_params['o_lat_p'] == 37.5
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geo tests **without** importing GeoViews.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import holoviews as hv
|
|
6
|
+
import hvplot.pandas # noqa
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
bk_renderer = hv.Store.renderers['bokeh']
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def simple_df():
|
|
17
|
+
return pd.DataFrame(np.random.rand(10, 2), columns=['x', 'y'])
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestAnnotationNotGeo:
|
|
21
|
+
def test_plot_tiles_doesnt_set_geo(self, simple_df):
|
|
22
|
+
plot = simple_df.hvplot.points('x', 'y', tiles=True)
|
|
23
|
+
assert len(plot) == 2
|
|
24
|
+
assert isinstance(plot.get(0), hv.Tiles)
|
|
25
|
+
assert 'openstreetmap' in plot.get(0).data
|
|
26
|
+
bk_plot = bk_renderer.get_plot(plot)
|
|
27
|
+
assert bk_plot.projection == 'mercator'
|
|
28
|
+
|
|
29
|
+
def test_plot_specific_tiles_doesnt_set_geo(self, simple_df):
|
|
30
|
+
plot = simple_df.hvplot.points('x', 'y', tiles='ESRI')
|
|
31
|
+
assert len(plot) == 2
|
|
32
|
+
assert isinstance(plot.get(0), hv.Tiles)
|
|
33
|
+
assert 'ArcGIS' in plot.get(0).data
|
|
34
|
+
bk_plot = bk_renderer.get_plot(plot)
|
|
35
|
+
assert bk_plot.projection == 'mercator'
|
|
36
|
+
|
|
37
|
+
def test_plot_with_specific_tile_class(self, simple_df):
|
|
38
|
+
plot = simple_df.hvplot.points('x', 'y', tiles=hv.element.tiles.EsriImagery)
|
|
39
|
+
assert len(plot) == 2
|
|
40
|
+
assert isinstance(plot.get(0), hv.Tiles)
|
|
41
|
+
assert 'ArcGIS' in plot.get(0).data
|
|
42
|
+
bk_plot = bk_renderer.get_plot(plot)
|
|
43
|
+
assert bk_plot.projection == 'mercator'
|
|
44
|
+
|
|
45
|
+
def test_plot_with_specific_tile_obj(self, simple_df):
|
|
46
|
+
plot = simple_df.hvplot.points('x', 'y', tiles=hv.element.tiles.EsriImagery())
|
|
47
|
+
assert len(plot) == 2
|
|
48
|
+
assert isinstance(plot.get(0), hv.Tiles)
|
|
49
|
+
assert 'ArcGIS' in plot.get(0).data
|
|
50
|
+
bk_plot = bk_renderer.get_plot(plot)
|
|
51
|
+
assert bk_plot.projection == 'mercator'
|
|
52
|
+
|
|
53
|
+
def test_plot_with_xyzservices_tileprovider(self, simple_df):
|
|
54
|
+
xyzservices = pytest.importorskip('xyzservices')
|
|
55
|
+
plot = simple_df.hvplot.points('x', 'y', tiles=xyzservices.providers.Esri.WorldImagery)
|
|
56
|
+
assert len(plot) == 2
|
|
57
|
+
assert isinstance(plot.get(0), hv.Tiles)
|
|
58
|
+
assert isinstance(plot.get(0).data, xyzservices.TileProvider)
|
|
59
|
+
bk_plot = bk_renderer.get_plot(plot)
|
|
60
|
+
assert bk_plot.projection == 'mercator'
|