holoviz / geoviews

Simple, concise geographical visualization in Python
http://geoviews.org
BSD 3-Clause "New" or "Revised" License
597 stars 77 forks source link

Specifying EPSG Projection results in ValueError or empty plot #475

Open scottyhq opened 4 years ago

scottyhq commented 4 years ago

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc) geoviews 1.8.2 py_0 conda-forge
bokeh 2.2.1 py37hc8dfbb8_0 conda-forge hvplot 0.6.0 pyh9f0ad1d_0 conda-forge cartopy 0.18.0 py37h891f161_2 conda-forge

Description of expected behavior and the observed behavior

Specifying projection with cartopy.crs.epsg() raises ValueError: cannot convert float NaN to integer

Complete, minimal, self-contained example code that reproduces the issue

import geoviews as gv
import geopandas as gpd
from shapely import geometry
import cartopy.crs as ccrs
import hvplot.pandas

S,N,W,E = [74.5, 80, -102, -98]
bbox = geometry.box(W,S,E,N)
gf = gpd.GeoDataFrame(geometry=[bbox], crs=4326)

crs = ccrs.epsg(3413)
print(crs.proj4_init)
print(gf.crs)

box = gf.hvplot.polygons(line_color='m', fill_color='m', fill_alpha=0.1,
                         coastline=True, projection=crs,
                         #frame_height=400, frame_width=400,
                        )
box

Stack traceback and/or browser JavaScript console output

Full traceback: ```pytb --------------------------------------------------------------------------- ValueError Traceback (most recent call last) ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude) 968 969 if method is not None: --> 970 return method(include=include, exclude=exclude) 971 return None 972 else: ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude) 1310 combined and returned. 1311 """ -> 1312 return Store.render(self) 1313 1314 ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/core/options.py in render(cls, obj) 1392 data, metadata = {}, {} 1393 for hook in hooks: -> 1394 ret = hook(obj) 1395 if ret is None: 1396 continue ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj) 280 if not ip.display_formatter.formatters['text/plain'].pprint: 281 return None --> 282 return display(obj, raw_output=True) 283 284 ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs) 250 elif isinstance(obj, (CompositeOverlay, ViewableElement)): 251 with option_state(obj): --> 252 output = element_display(obj) 253 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)): 254 with option_state(obj): ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in wrapped(element) 144 try: 145 max_frames = OutputSettings.options['max_frames'] --> 146 mimebundle = fn(element, max_frames=max_frames) 147 if mimebundle is None: 148 return {}, {} ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in element_display(element, max_frames) 190 return None 191 --> 192 return render(element) 193 194 ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs) 66 renderer = renderer.instance(fig='png') 67 ---> 68 return renderer.components(obj, **kwargs) 69 70 ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs) 393 doc = Document() 394 with config.set(embed=embed): --> 395 model = plot.layout._render_model(doc, comm) 396 if embed: 397 return render_model(model, comm) ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/viewable.py in _render_model(self, doc, comm) 416 if comm is None: 417 comm = state._comm_manager.get_server_comm() --> 418 model = self.get_root(doc, comm) 419 420 if config.embed: ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/viewable.py in get_root(self, doc, comm) 645 """ 646 doc = doc or _curdoc() --> 647 root = self._get_model(doc, comm=comm) 648 self._preprocess(root) 649 ref = root.ref['id'] ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/layout.py in _get_model(self, doc, root, parent, comm) 118 if root is None: 119 root = model --> 120 objects = self._get_objects(model, [], doc, root, comm) 121 props = dict(self._init_properties(), objects=objects) 122 model.update(**self._process_param_change(props)) ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/layout.py in _get_objects(self, model, old_objects, doc, root, comm) 108 else: 109 try: --> 110 child = pane._get_model(doc, root, model, comm) 111 except RerenderError: 112 return self._get_objects(model, current_objects[:i], doc, root, comm) ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/pane/holoviews.py in _get_model(self, doc, root, parent, comm) 225 plot = self.object 226 else: --> 227 plot = self._render(doc, comm, root) 228 229 plot.pane = self ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/panel/pane/holoviews.py in _render(self, doc, comm, root) 284 kwargs = {} 285 --> 286 return renderer.get_plot(self.object, **kwargs) 287 288 def _cleanup(self, root): ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs) 71 combining the bokeh model with another plot. 72 """ ---> 73 plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs) 74 if plot.document is None: 75 plot.document = Document() if self_or_cls.notebook_context else curdoc() ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs) 238 init_key = tuple(v if d is None else d for v, d in 239 zip(plot.keys[0], defaults)) --> 240 plot.update(init_key) 241 else: 242 plot = obj ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/plot.py in update(self, key) 911 def update(self, key): 912 if len(self) == 1 and ((key == 0) or (key == self.keys[0])) and not self.drawn: --> 913 return self.initialize_plot() 914 item = self.__getitem__(key) 915 self.traverse(lambda x: setattr(x, '_updated', True)) ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/geoviews/plotting/bokeh/plot.py in initialize_plot(self, ranges, plot, plots, source) 111 def initialize_plot(self, ranges=None, plot=None, plots=None, source=None): 112 opts = {} if isinstance(self, HvOverlayPlot) else {'source': source} --> 113 fig = super(GeoPlot, self).initialize_plot(ranges, plot, plots, **opts) 114 if self.geographic and self.show_bounds and not self.overlaid: 115 from . import GeoShapePlot ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/bokeh/element.py in initialize_plot(self, ranges, plot, plots) 2277 if plot and not self.overlaid: 2278 self._update_plot(key, plot, element) -> 2279 self._update_ranges(element, ranges) 2280 2281 panels = [] ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/geoviews/plotting/bokeh/plot.py in _update_ranges(self, element, ranges) 90 91 def _update_ranges(self, element, ranges): ---> 92 super(GeoPlot, self)._update_ranges(element, ranges) 93 if not self.geographic: 94 return ~/miniconda3/envs/intake-stac-gui/lib/python3.7/site-packages/holoviews/plotting/bokeh/element.py in _update_ranges(self, element, ranges) 889 if fixed_height: 890 plot.frame_height = height --> 891 plot.frame_width = int(height/aspect) 892 plot.plot_width, plot.plot_height = None, None 893 elif fixed_width: ValueError: cannot convert float NaN to integer ```

Other notes

  1. Explicitly setting frame_width and frame_height avoids the error, but the resulting plot extents are off

  2. Using cartopy.NorthPolarStereo as crs does work crs = ccrs.NorthPolarStereo(central_longitude=-45, true_scale_latitude=70)

jlstevens commented 3 years ago

Thanks for reporting this issue!

Looking at that traceback, it can't be correct for either height or aspect to be NaN before casting to integer. I expect we need to figure out how cartopy is resulting in a NaN value...