Skip to content

Commit

Permalink
Fix x ranges upon projection (#722)
Browse files Browse the repository at this point in the history
Co-authored-by: Philipp Rudiger <[email protected]>
  • Loading branch information
ahuang11 and philippjfr authored Jun 3, 2024
1 parent f6f4698 commit 68ba9e1
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
4 changes: 4 additions & 0 deletions geoviews/plotting/bokeh/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ def project_ranges(cb, msg, attributes):
extents = x0, y0, x1, y1
x0, y0, x1, y1 = project_extents(extents, plot.projection,
plot.current_frame.crs)
if plot._unwrap_lons and -180 <= x0 < 0 or -180 <= x1 < 0:
x0, x1 = x0 + 360, x1 + 360
if x0 > x1:
x0, x1 = x1, x0
coords = {'x_range': (x0, x1), 'y_range': (y0, y1)}
return {k: v for k, v in coords.items() if k in attributes}

Expand Down
15 changes: 14 additions & 1 deletion geoviews/plotting/bokeh/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import param

from cartopy.crs import GOOGLE_MERCATOR, PlateCarree, Mercator
from cartopy.crs import GOOGLE_MERCATOR, PlateCarree, Mercator, _CylindricalProjection
from bokeh.models.tools import BoxZoomTool, WheelZoomTool
from bokeh.models import MercatorTickFormatter, MercatorTicker, CustomJSHover
from holoviews.core.dimension import Dimension
Expand Down Expand Up @@ -70,6 +70,8 @@ def __init__(self, element, **params):
'and disable the show_grid option.'
)

self._unwrap_lons = False

def _axis_properties(self, axis, key, plot, dimension=None,
ax_mapping=None):
if ax_mapping is None:
Expand Down Expand Up @@ -103,6 +105,11 @@ def _update_ranges(self, element, ranges):
ax_range.end = mid + min_interval/2.
ax_range.min_interval = min_interval

def _set_unwrap_lons(self, element):
if isinstance(self.geographic, _CylindricalProjection):
x1, x2 = element.range(0)
self._unwrap_lons = 0 <= x1 <= 360 and 0 <= x2 <= 360

def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
opts = {} if isinstance(self, HvOverlayPlot) else {'source': source}
fig = super().initialize_plot(ranges, plot, plots, **opts)
Expand All @@ -113,8 +120,14 @@ def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
overlaid=True, renderer=self.renderer)
shapeplot.geographic = False
shapeplot.initialize_plot(plot=fig)
self._set_unwrap_lons(self.current_frame)
return fig

def update_frame(self, key, ranges=None, element=None):
if element is not None:
self._set_unwrap_lons(element)
super().update_frame(key, ranges, element)

def _postprocess_hover(self, renderer, source):
super()._postprocess_hover(renderer, source)
hover = self.handles["plot"].hover
Expand Down
37 changes: 37 additions & 0 deletions geoviews/tests/test_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,40 @@ def test_quadmesh_contoures_filled():
p1 = gv.QuadMesh(ds, kdims=["lon", "lat"])
p2 = contours(p1, filled=True)
gv.renderer("bokeh").get_plot(p2)


def test_unwrap_lons():
pytest.importorskip("datashader")
# Regression test for: https://github.com/holoviz/geoviews/pull/722
from holoviews.operation.datashader import rasterize
ds = xr.tutorial.open_dataset("air_temperature").isel(time=0)
p1 = gv.Image(ds)
p2 = rasterize(p1, filled=True)
gv.renderer("bokeh").get_plot(p2)
for x in p2.range(0):
assert x >= 0
assert x <= 360
p2.callback()
for x in p2.range(0):
assert x >= 0
assert x <= 360


def test_no_unwrap_lons():
pytest.importorskip("datashader")
# Regression test for: https://github.com/holoviz/geoviews/pull/722
from holoviews.operation.datashader import rasterize
ds = xr.tutorial.open_dataset("air_temperature").isel(time=0)
# to -180, 180
ds["lon"] = (ds["lon"] + 180) % 360 - 180

p1 = gv.Image(ds)
p2 = rasterize(p1, filled=True)
gv.renderer("bokeh").get_plot(p2)
for x in p2.range(0):
assert x >= -180
assert x <= 180
p2.callback()
for x in p2.range(0):
assert x >= -180
assert x <= 180

0 comments on commit 68ba9e1

Please sign in to comment.