Skip to content

Commit

Permalink
Merge ef671af into 27da6a3
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 7, 2022
2 parents 27da6a3 + ef671af commit e0c9b7f
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 73 deletions.
14 changes: 11 additions & 3 deletions holoviews/core/data/xarray.py
Expand Up @@ -217,9 +217,17 @@ def retrieve_unit_and_label(dim):
# not need to be canonicalized
if any(len(da.coords[c].shape) > 1 for c in da.coords):
continue
undeclared = [
c for c in da.coords if c not in kdims and len(da[c].shape) == 1 and
da[c].shape[0] > 1]
undeclared = []
for c in da.coords:
if c in kdims or len(da[c].shape) != 1 or da[c].shape[0] <= 1:
# Skip if coord is declared, represents irregular coordinates or is constant
continue
elif all(d in kdims for d in da[c].dims):
continue # Skip if coord is alias for another dimension
elif any(all(d in da[kd.name].dims for d in da[c].dims) for kd in kdims):
# Skip if all the dims on the coord are present on another coord
continue
undeclared.append(c)
if undeclared:
raise DataError(
'The coordinates on the %r DataArray do not match the '
Expand Down
4 changes: 2 additions & 2 deletions holoviews/plotting/mpl/element.py
Expand Up @@ -174,7 +174,7 @@ def _finalize_axis(self, key, element=None, title=None, dimensions=None, ranges=
if self.logy:
axis.set_yscale('log')

if not isinstance(self.projection, str) and self.projection == '3d':
if not (isinstance(self.projection, str) and self.projection == '3d'):
self._set_axis_position(axis, 'x', self.xaxis)
self._set_axis_position(axis, 'y', self.yaxis)

Expand Down Expand Up @@ -330,7 +330,7 @@ def _set_axis_limits(self, axis, view, subplots, ranges):
coords = [coord if isinstance(coord, np.datetime64) or np.isreal(coord) else np.NaN for coord in extents]
coords = [date2num(util.dt64_to_dt(c)) if isinstance(c, np.datetime64) else c
for c in coords]
if isinstance(self.projection, str) and self.projection == '3d' or len(extents) == 6:
if (isinstance(self.projection, str) and self.projection == '3d') or len(extents) == 6:
l, b, zmin, r, t, zmax = coords
if self.invert_zaxis or any(p.invert_zaxis for p in subplots):
zmin, zmax = zmax, zmin
Expand Down
8 changes: 8 additions & 0 deletions holoviews/tests/core/data/testxarrayinterface.py
Expand Up @@ -60,6 +60,14 @@ def get_multi_dim_irregular_dataset(self):
'time': pd.date_range('2014-09-06', periods=3),
'reference_time': pd.Timestamp('2014-09-05')})

def test_ignore_dependent_dimensions_if_not_specified(self):
coords = OrderedDict([('time', [0, 1]), ('lat', [0, 1]), ('lon', [0, 1])])
da = xr.DataArray(np.arange(8).reshape((2, 2, 2)),
coords, ['time', 'lat', 'lon']).assign_coords(
lat1=xr.DataArray([2,3], dims=['lat']))
assert Dataset(da, ['time', 'lat', 'lon'], vdims='value').kdims == ['time', 'lat', 'lon']
assert Dataset(da, ['time', 'lat1', 'lon'], vdims='value').kdims == ['time', 'lat1', 'lon']

def test_xarray_dataset_irregular_shape(self):
ds = Dataset(self.get_multi_dim_irregular_dataset())
shape = ds.interface.shape(ds, gridded=True)
Expand Down
95 changes: 27 additions & 68 deletions holoviews/tests/plotting/bokeh/testserver.py
@@ -1,8 +1,6 @@
import time
import threading

from unittest import SkipTest
from threading import Event

import param

Expand All @@ -14,21 +12,18 @@
from holoviews.streams import Stream, RangeXY, PlotReset

try:
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.client import pull_session
from bokeh.document import Document
from bokeh.io.doc import curdoc, set_curdoc
from bokeh.models import ColumnDataSource
from bokeh.server.server import Server

from holoviews.plotting.bokeh.callbacks import (
Callback, RangeXYCallback, ResetCallback
)
from holoviews.plotting.bokeh.renderer import BokehRenderer
from panel.widgets import DiscreteSlider, FloatSlider
from panel.io.server import StoppableThread
from panel.io.state import state
from panel import serve
bokeh_renderer = BokehRenderer.instance(mode='server')
except:
bokeh_renderer = None
Expand Down Expand Up @@ -107,78 +102,39 @@ def setUp(self):
if not bokeh_renderer:
raise SkipTest("Bokeh required to test plot instantiation")
Store.current_backend = 'bokeh'
self._loaded = Event()
self._port = None
self._thread = None
self._server = None

def tearDown(self):
Store.current_backend = self.previous_backend
Callback._callbacks = {}
if self._thread is not None:
try:
self._thread.stop()
except:
pass
state._thread_id = None
if self._server is not None:
try:
self._server.stop()
except:
pass
state.kill_all_servers()
time.sleep(1)

def _launcher(self, obj, threaded=False, io_loop=None):
if io_loop:
io_loop.make_current()
launched = []
def modify_doc(doc):
bokeh_renderer(obj, doc=doc)
launched.append(True)
handler = FunctionHandler(modify_doc)
app = Application(handler)
server = Server({'/': app}, port=0, io_loop=io_loop)
server.start()
self._port = server.port
self._server = server
if threaded:
server.io_loop.add_callback(self._loaded.set)
thread = threading.current_thread()
state._thread_id = thread.ident if thread else None
io_loop.start()
else:
url = "http://localhost:" + str(server.port) + "/"
session = pull_session(session_id='Test', url=url, io_loop=server.io_loop)
self.assertTrue(len(launched)==1)
return session, server
return None, server

def _threaded_launcher(self, obj):
from tornado.ioloop import IOLoop
io_loop = IOLoop()
thread = StoppableThread(target=self._launcher, io_loop=io_loop,
args=(obj, True, io_loop))
thread.setDaemon(True)
thread.start()
self._loaded.wait()
self._thread = thread
return self.session
def _launcher(self, obj, threaded=True, port=6001):
self._port = port
server = serve(obj, threaded=threaded, show=False, port=port)
time.sleep(0.5)
return server, self.session

@property
def session(self):
url = "http://localhost:" + str(self._port) + "/"
return pull_session(session_id='Test', url=url)

def test_launch_simple_server(self):
obj = Curve([])
self._launcher(obj)
server, _ = self._launcher(obj, port=6001)
server.stop()

def test_launch_server_with_stream(self):
obj = Curve([])
stream = RangeXY(source=obj)
el = Curve([])
stream = RangeXY(source=el)

_, server = self._launcher(obj)
cb = bokeh_renderer.last_plot.callbacks[0]
obj, _ = bokeh_renderer._validate(el, None)
server, _ = self._launcher(obj, port=6002)
[(plot, _)] = obj._plots.values()

cb = plot.callbacks[0]
self.assertIsInstance(cb, RangeXYCallback)
self.assertEqual(cb.streams, [stream])
x_range = bokeh_renderer.last_plot.handles['x_range']
Expand All @@ -195,15 +151,15 @@ def test_launch_server_with_complex_plot(self):
static = Polygons([]) * Path([]) * Curve([])
layout = overlay + static

_, server = self._launcher(layout)
server, _ = self._launcher(layout, port=6003)
server.stop()

def test_server_dynamicmap_with_dims(self):
dmap = DynamicMap(lambda y: Curve([1, 2, y]), kdims=['y']).redim.range(y=(0.1, 5))
obj, _ = bokeh_renderer._validate(dmap, None)
session = self._threaded_launcher(obj)
server, session = self._launcher(obj, port=6004)
[(plot, _)] = obj._plots.values()
[(doc, _)] = obj.layout._documents.items()
[(doc, _)] = obj._documents.items()

cds = session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(cds.data['y'][2], 0.1)
Expand All @@ -214,13 +170,14 @@ def run():
time.sleep(1)
cds = self.session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(cds.data['y'][2], 3.1)
server.stop()

def test_server_dynamicmap_with_stream(self):
stream = Stream.define('Custom', y=2)()
dmap = DynamicMap(lambda y: Curve([1, 2, y]), kdims=['y'], streams=[stream])
obj, _ = bokeh_renderer._validate(dmap, None)
session = self._threaded_launcher(obj)
[(doc, _)] = obj.layout._documents.items()
server, session = self._launcher(obj, port=6005)
[(doc, _)] = obj._documents.items()

cds = session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(cds.data['y'][2], 2)
Expand All @@ -230,14 +187,15 @@ def run():
time.sleep(1)
cds = self.session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(cds.data['y'][2], 3)
server.stop()

def test_server_dynamicmap_with_stream_dims(self):
stream = Stream.define('Custom', y=2)()
dmap = DynamicMap(lambda x, y: Curve([x, 1, y]), kdims=['x', 'y'],
streams=[stream]).redim.values(x=[1, 2, 3])
obj, _ = bokeh_renderer._validate(dmap, None)
session = self._threaded_launcher(obj)
[(doc, _)] = obj.layout._documents.items()
server, session = self._launcher(obj, port=6006)
[(doc, _)] = obj._documents.items()

orig_cds = session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(orig_cds.data['y'][2], 2)
Expand All @@ -256,3 +214,4 @@ def run():
time.sleep(1)
cds = self.session.document.roots[0].select_one({'type': ColumnDataSource})
self.assertEqual(cds.data['y'][0], 3)
server.stop()
8 changes: 8 additions & 0 deletions holoviews/tests/plotting/matplotlib/testelementplot.py
Expand Up @@ -59,6 +59,14 @@ def test_element_font_scaling_fontsize_override_specific(self):
self.assertEqual(ax.xaxis._major_tick_kw['labelsize'], 24)
self.assertEqual(ax.yaxis._major_tick_kw['labelsize'], 20)

def test_element_no_xaxis_yaxis(self):
element = Curve(range(10)).options(xaxis=None, yaxis=None)
axes = mpl_renderer.get_plot(element).handles['axis']
xaxis = axes.get_xaxis()
yaxis = axes.get_yaxis()
self.assertEqual(xaxis.get_visible(), False)
self.assertEqual(yaxis.get_visible(), False)

def test_element_xlabel(self):
element = Curve(range(10)).options(xlabel='custom x-label')
axes = mpl_renderer.get_plot(element).handles['axis']
Expand Down

0 comments on commit e0c9b7f

Please sign in to comment.