Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix v1.9.4 #2337

Closed
wants to merge 11 commits into from
11 changes: 6 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ install:
- conda update -q conda
# Useful for debugging any issues with conda
- conda info -a
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION scipy=0.18.1 numpy freetype nose pandas=0.19.2 jupyter ipython=4.2.0 param pyqt=4 matplotlib=1.5.1 xarray
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION flake8 scipy=1.0.0 numpy freetype nose pandas=0.22.0 jupyter ipython=4.2.0 param matplotlib=2.1.2 xarray
- source activate test-environment
- conda install -c conda-forge iris sip=4.18 plotly flexx
- conda install -c bokeh datashader dask=0.13 bokeh=0.12.10 selenium
- conda install -c conda-forge iris plotly flexx --quiet
- conda install -c bokeh datashader dask=0.16.1 bokeh=0.12.14 selenium
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
conda install python=3.4.3;
fi
Expand Down Expand Up @@ -68,8 +68,9 @@ before-script:
script:
- export HOLOVIEWSRC=`pwd`'/holoviews.rc'
- echo 'import holoviews as hv;hv.config(style_17=True);hv.config.warn_options_call=True' > holoviews.rc
- nosetests --with-doctest --with-coverage --cover-package=holoviews
- cd doc/nbpublisher; chmod +x test_notebooks.py; BOKEH_DEV=True ./test_notebooks.py
- flake8 --ignore=E,W,F999,F405 holoviews tests
- nosetests --with-doctest --with-coverage --cover-package=holoviews -v
- cd doc/nbpublisher; chmod +x test_notebooks.py; QT_QPA_PLATFORM='offscreen' BOKEH_DEV=True ./test_notebooks.py
- chmod +x concat_html.py; ./concat_html.py ../test_data ../test_html
- cd ../../; mv doc/Tutorials/.coverage ./.coverage.notebooks
- coverage combine --append
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
Version 1.9.4
=============

This release contains a small number of important bug fixes:

- Compatibility with recent versions of dask and pandas
([\#2329](https://github.com/ioam/holoviews/pull/2329))
- Fixed bug referencing columns containing non-alphanumeric characters
in bokeh Tables ([\#2336](https://github.com/ioam/holoviews/pull/2336))
- Fixed issue in regrid operation
([2337](https://github.com/ioam/holoviews/pull/2337))
- Fixed issue when using datetimes with datashader when processing
ranges ([\#2344](https://github.com/ioam/holoviews/pull/2344))


Version 1.9.3
=============

Expand Down
2 changes: 1 addition & 1 deletion holoviews/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np # noqa (API import)
import param

__version__ = param.Version(release=(1,9,3), fpath=__file__,
__version__ = param.Version(release=(1,9,4), fpath=__file__,
commit="$Format:%h$", reponame='holoviews')

from .core import archive, config # noqa (API import)
Expand Down
7 changes: 5 additions & 2 deletions holoviews/core/data/dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def select_mask(cls, dataset, selection):
else:
masks.append(series == k)
for mask in masks:
if select_mask:
if select_mask is not None:
select_mask &= mask
else:
select_mask = mask
Expand Down Expand Up @@ -145,7 +145,10 @@ def groupby(cls, columns, dimensions, container_type, group_type, **kwargs):
if len(group_by) == 1:
column = columns.data[group_by[0]]
if column.dtype.name == 'category':
indices = ((ind,) for ind in column.cat.categories)
try:
indices = ((ind,) for ind in column.cat.categories)
except NotImplementedError:
indices = ((ind,) for ind in column.unique().compute())
else:
indices = ((ind,) for ind in column.unique().compute())
else:
Expand Down
2 changes: 1 addition & 1 deletion holoviews/core/data/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def values(cls, dataset, dim, expanded=True, flat=True):
else:
if not expanded:
return util.unique_array(values)
values = np.array(values)
values = np.asarray(values)
return values


Expand Down
2 changes: 1 addition & 1 deletion holoviews/core/traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def unique_dimkeys(obj, default_dim='Frame'):
for d, k in zip(dims, key):
dim_keys[d.name] = k
if dim_keys:
keys = [tuple(dim_keys[dim.name] for dim in dimensions)]
keys = [tuple(dim_keys.get(dim.name) for dim in dimensions)]
else:
keys = []
return merge_dimensions(dim_groups), keys
Expand Down
14 changes: 10 additions & 4 deletions holoviews/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def run(self):
self.counter += 1
try:
self.callback(self.counter)
except Exception as e:
except Exception:
self.stop()

if self.timeout is not None:
Expand Down Expand Up @@ -213,7 +213,7 @@ def deephash(obj):
basestring = basestring
unicode = unicode
from itertools import izip
generator_types = (izip, xrange, types.GeneratorType)
generator_types = (izip, xrange, types.GeneratorType) # noqa



Expand Down Expand Up @@ -1555,8 +1555,14 @@ def dt_to_int(value, time_unit='us'):
"""
Converts a datetime type to an integer with the supplied time unit.
"""
if time_unit == 'ns':
tscale = 1./np.timedelta64(1, time_unit).tolist()
if isinstance(value, np.datetime64):
value = np.datetime64(value, 'ns')
if time_unit == 'ns':
tscale = 1
else:
tscale = (np.timedelta64(1, time_unit)/np.timedelta64(1, 'ns')) * 1000.
elif time_unit == 'ns':
tscale = 1000.
else:
tscale = 1./np.timedelta64(1, time_unit).tolist().total_seconds()
if pd and isinstance(value, pd.Timestamp):
Expand Down
2 changes: 1 addition & 1 deletion holoviews/element/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def dframe(self, dimensions=None):
dimensions = [self.get_dimension(d, strict=True) for d in dimensions
if d in dimensions.kdims]
else:
dimensions = dimensions.kdims
dimensions = self.kdims
return self.interface.dframe(self, dimensions)


Expand Down
3 changes: 2 additions & 1 deletion holoviews/element/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ def circular_layout(nodes):
Lay out nodes on a circle and add node index.
"""
N = len(nodes)
if not N:
return ([], [], [])
circ = np.pi/N*np.arange(N)*2
x = np.cos(circ)
y = np.sin(circ)
Expand Down Expand Up @@ -269,7 +271,6 @@ def connect_edges_pd(graph):
df = df.sort_values('graph_edge_index').drop(['graph_edge_index'], axis=1)

edge_segments = []
N = len(nodes)
for i, edge in df.iterrows():
start = edge['src_x'], edge['src_y']
end = edge['dst_x'], edge['dst_y']
Expand Down
13 changes: 9 additions & 4 deletions holoviews/operation/datashader.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def _get_sampling(self, element, x, y):
ytype = 'datetime'
elif not np.isfinite(ystart) and not np.isfinite(yend):
if element.get_dimension_type(y) in datetime_types:
xstart, xend = 0, 10000
xtype = 'datetime'
ystart, yend = 0, 10000
ytype = 'datetime'
else:
ystart, yend = 0, 1
elif ystart == yend:
Expand Down Expand Up @@ -239,7 +239,7 @@ def get_agg_data(cls, obj, category=None):
paths = [p.compute() if isinstance(p, dd.DataFrame) else p for p in paths]
df = pd.concat(paths)
else:
df = paths[0]
df = paths[0] if paths else pd.DataFrame([], columns=[x.name, y.name])
if category and df[category].dtype.name != 'category':
df[category] = df[category].astype('category')

Expand Down Expand Up @@ -338,6 +338,10 @@ def _process(self, element, key=None):
xarray = xr.DataArray(np.full((height, width), np.NaN, dtype=np.float32),
dims=['y', 'x'], coords={'x': xs, 'y': ys})
return self.p.element_type(xarray)
elif not len(data):
xarray = xr.DataArray(np.full((height, width), np.NaN, dtype=np.float32),
dims=[y.name, x.name], coords={x.name: xs, y.name: ys})
return self.p.element_type(xarray)

cvs = ds.Canvas(plot_width=width, plot_height=height,
x_range=x_range, y_range=y_range)
Expand Down Expand Up @@ -432,7 +436,7 @@ def _get_xarrays(self, element, coords, xtype, ytype):
xarr = element.data[vd.name]
if 'datetime' in (xtype, ytype):
xarr = xarr.copy()
if dims != xarr.dims and not irregular:
if dims != xarr.dims:
xarr = xarr.transpose(*dims)
else:
arr = element.dimension_values(vd, flat=False)
Expand Down Expand Up @@ -492,6 +496,7 @@ def _process(self, element, key=None):
datatype=['xarray']+element.datatype)



class shade(Operation):
"""
shade applies a normalization function followed by colormapping to
Expand Down
3 changes: 2 additions & 1 deletion holoviews/plotting/bokeh/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ def _init_plot_handles(self):
requested[h] = handles[h]
elif h in self.extra_models:
print("Warning %s could not find the %s model. "
"The corresponding stream may not work.")
"The corresponding stream may not work."
% (type(self).__name__, h))
self.handle_ids.update(self._get_stream_handle_ids(requested))

return requested
Expand Down
14 changes: 7 additions & 7 deletions holoviews/plotting/bokeh/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@
import numpy as np
import param
from bokeh.models import (CategoricalColorMapper, CustomJS, HoverTool,
FactorRange, Whisker, Band, Range1d, Circle,
VBar, HBar)
FactorRange, Whisker, Range1d, Circle, VBar,
HBar)
from bokeh.models.tools import BoxSelectTool
from bokeh.transform import jitter

from ...core import Dataset, OrderedDict
from ...core.dimension import Dimension
from ...core import Dataset, OrderedDict, Dimension
from ...core.util import (max_range, basestring, dimension_sanitizer,
wrap_tuple, unique_iterator)
unique_iterator, wrap_tuple)
from ...element import Bars
from ...operation import interpolate_curve
from ..util import compute_sizes, get_min_distance, dim_axis_label
from .element import (ElementPlot, ColorbarPlot, LegendPlot, CompositeElementPlot,
line_properties, fill_properties)
from .element import (ElementPlot, CompositeElementPlot, ColorbarPlot,
LegendPlot, line_properties, fill_properties)
from .util import expand_batched_style, categorize_array, rgb2hex, mpl_to_bokeh


Expand Down Expand Up @@ -1078,6 +1077,7 @@ def get_data(self, element, ranges, style):

# Compute statistics
vals = g.dimension_values(g.vdims[0])
vals = vals[np.isfinite(vals)]
if len(vals):
qmin, q1, q2, q3, qmax = (np.percentile(vals, q=q) for q in range(0,125,25))
iqr = q3 - q1
Expand Down
3 changes: 1 addition & 2 deletions holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from itertools import groupby
import warnings

import param
Expand All @@ -21,7 +20,7 @@
from ...core import DynamicMap, CompositeOverlay, Element, Dimension
from ...core.options import abbreviated_exception, SkipRendering
from ...core import util
from ...streams import Stream, Buffer
from ...streams import Buffer
from ..plot import GenericElementPlot, GenericOverlayPlot
from ..util import dynamic_update, process_cmap
from .plot import BokehPlot, TOOLS
Expand Down
6 changes: 2 additions & 4 deletions holoviews/plotting/bokeh/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
from bokeh.models import (ColumnDataSource, Column, Row, Div)
from bokeh.models.widgets import Panel, Tabs

from ...core import (OrderedDict, Store, GridMatrix, AdjointLayout,
NdLayout, Empty, GridSpace, HoloMap, Element,
DynamicMap)
from ...core import (OrderedDict, Store, AdjointLayout, NdLayout,
Empty, GridSpace, HoloMap, Element, DynamicMap)
from ...core.util import basestring, wrap_tuple, unique_iterator
from ...element import Histogram
from ...streams import Stream
from ..plot import (DimensionedPlot, GenericCompositePlot, GenericLayoutPlot,
GenericElementPlot, GenericOverlayPlot)
Expand Down
2 changes: 1 addition & 1 deletion holoviews/plotting/bokeh/raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from bokeh.models import HoverTool
from ...core.util import cartesian_product, is_nan, dimension_sanitizer
from ...core.options import SkipRendering
from ...element import Raster
from ..renderer import SkipRendering
from .element import ElementPlot, ColorbarPlot, line_properties, fill_properties


Expand Down
33 changes: 18 additions & 15 deletions holoviews/plotting/bokeh/tabular.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,23 @@ def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
source = self._init_datasource(data)
self.handles['source'] = source

columns = self._get_columns(element, data)
style['reorderable'] = False
table = DataTable(source=source, columns=columns, height=self.height,
width=self.width, **style)
self.handles['plot'] = table
self.handles['glyph_renderer'] = table
self._execute_hooks(element)
self.drawn = True

for cb in self.callbacks:
cb.initialize()

return table

def _get_columns(self, element, data):
columns = []
dims = element.dimensions()
for d in dims:
for d in element.dimensions():
col = dimension_sanitizer(d.name)
kind = data[col].dtype.kind
if kind == 'i':
Expand All @@ -89,21 +103,10 @@ def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
else:
formatter = StringFormatter()
editor = StringEditor()
column = TableColumn(field=d.name, title=d.pprint_label,
column = TableColumn(field=dimension_sanitizer(d.name), title=d.pprint_label,
editor=editor, formatter=formatter)
columns.append(column)
style['reorderable'] = False
table = DataTable(source=source, columns=columns, height=self.height,
width=self.width, **style)
self.handles['plot'] = table
self.handles['glyph_renderer'] = table
self._execute_hooks(element)
self.drawn = True

for cb in self.callbacks:
cb.initialize()

return table
return columns


def update_frame(self, key, ranges=None, plot=None):
Expand Down
8 changes: 6 additions & 2 deletions holoviews/plotting/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@
mpl_ge_150 = LooseVersion(mpl.__version__) >= '1.5.0'

if pd:
from pandas.tseries import converter
converter.register()
try:
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
except ImportError:
from pandas.tseries import converter
converter.register()


def set_style(key):
Expand Down
2 changes: 1 addition & 1 deletion meta.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package:
name: holoviews
version: 1.9.3
version: 1.9.4

source:
path: .
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

setup_args.update(dict(
name='holoviews',
version="1.9.3",
version="1.9.4",
install_requires=install_requires,
extras_require=extras_require,
description='Stop plotting your data - annotate your data and let it visualize itself.',
Expand Down
16 changes: 15 additions & 1 deletion tests/operation/testdatashader.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import datashader as ds
from holoviews.operation.datashader import (
aggregate, regrid, ds_version, stack, directly_connect_edges,
shade, rasterize
shade
)
except:
ds_version = None
Expand Down Expand Up @@ -77,6 +77,20 @@ def test_aggregate_curve_datetimes(self):
datatype=['xarray'], bounds=bounds, vdims='Count')
self.assertEqual(img, expected)

def test_aggregate_curve_datetimes_microsecond_timebase(self):
dates = pd.date_range(start="2016-01-01", end="2016-01-03", freq='1D')
xstart = np.datetime64('2015-12-31T23:59:59.723518000', 'us')
xend = np.datetime64('2016-01-03T00:00:00.276482000', 'us')
curve = Curve((dates, [1, 2, 3]))
img = aggregate(curve, width=2, height=2, x_range=(xstart, xend), dynamic=False)
bounds = (np.datetime64('2015-12-31T23:59:59.585277000'), 1.0,
np.datetime64('2016-01-03T00:00:00.414723000'), 3.0)
dates = [np.datetime64('2016-01-01T11:59:59.861759000',),
np.datetime64('2016-01-02T12:00:00.138241000')]
expected = Image((dates, [1.5, 2.5], [[1, 0], [0, 2]]),
datatype=['xarray'], bounds=bounds, vdims='Count')
self.assertEqual(img, expected)

def test_aggregate_ndoverlay(self):
ds = Dataset([(0.2, 0.3, 0), (0.4, 0.7, 1), (0, 0.99, 2)], kdims=['x', 'y', 'z'])
ndoverlay = ds.to(Points, ['x', 'y'], [], 'z').overlay()
Expand Down
Loading