Skip to content

Commit

Permalink
Fix index-out-of-bounds line glyph crash and run select tests with JI…
Browse files Browse the repository at this point in the history
…T disabled (holoviz#683)

* Support disabling JIT compilation when NUMBA_DISABLE_JIT is set
* Add failing test case for bug 570
* Change `int` to `round` when recomputing the canvas width/height
* Run select unit tests with JIT disabled
* Fix windows CMD syntax for multiple commands on one line
* Add tests for lines/points along the outside edge of canvas
  • Loading branch information
jonmmease authored and jbednar committed Jan 7, 2019
1 parent 38351bc commit 0955e86
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 9 deletions.
1 change: 1 addition & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ build: off

test_script:
- "doit test_all"
- "set NUMBA_DISABLE_JIT=1 && doit test_unit_nojit & set NUMBA_DISABLE_JIT="
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ jobs:
- source activate test-environment
- doit develop_install $CHANS_DEV
- doit env_capture
script: doit test_all
script:
- doit test_all
- export NUMBA_DISABLE_JIT=1; doit test_unit_nojit

# python 2 flake checking typically catches python 2 syntax
# errors where python 3's been assumed...
Expand Down
19 changes: 14 additions & 5 deletions datashader/composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import numba as nb
import numpy as np
import os


__all__ = ('composite_op_lookup', 'over', 'add', 'saturate', 'source')
Expand All @@ -28,19 +29,27 @@ def combine_scaled(r, g, b, a):
return np.uint32((a2 << 24) | (b2 << 16) | (g2 << 8) | r2)


extract_scaled.disable_compile()
combine_scaled.disable_compile()
jit_enabled = os.environ.get('NUMBA_DISABLE_JIT', '0') == '0'


if jit_enabled:
extract_scaled.disable_compile()
combine_scaled.disable_compile()

# Lookup table for storing compositing operators by function name
composite_op_lookup = {}


def operator(f):
"""Define and register a new composite operator"""
f2 = nb.vectorize(f)
f2._compile_for_argtys((nb.types.uint32, nb.types.uint32))
f2._frozen = True

if jit_enabled:
f2 = nb.vectorize(f)
f2._compile_for_argtys((nb.types.uint32, nb.types.uint32))
f2._frozen = True
else:
f2 = np.vectorize(f)

composite_op_lookup[f.__name__] = f2
return f2

Expand Down
14 changes: 12 additions & 2 deletions datashader/glyphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,18 @@ def map_onto_pixel(vt, bounds, x, y):
xx = int(x_mapper(x) * sx + tx)
yy = int(y_mapper(y) * sy + ty)

xxmax = int(x_mapper(xmax) * sx + tx)
yymax = int(y_mapper(ymax) * sy + ty)
# Note that sx and tx were designed so that
# x_mapper(xmax) * sx + tx equals the width of the canvas in pixels
#
# Likewise, sy and ty were designed so that
# y_mapper(ymax) * sy + ty equals the height of the canvas in pixels
#
# We round these results to integers (rather than casting to integers
# with the int constructor) to handle cases where floating-point
# precision errors results in a value just under the integer number
# of pixels.
xxmax = round(x_mapper(xmax) * sx + tx)
yymax = round(y_mapper(ymax) * sy + ty)

return (xx - 1 if xx == xxmax else xx,
yy - 1 if yy == yymax else yy)
Expand Down
60 changes: 60 additions & 0 deletions datashader/tests/test_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,46 @@ def test_line():
assert_eq(agg, out)


def test_points_on_edge():
df = pd.DataFrame(dict(x=[0, 0.5, 1.1, 1.5, 2.2, 3, 3, 0],
y=[0, 0, 0, 0, 0, 0, 3, 3]))

canvas = ds.Canvas(plot_width=3, plot_height=3,
x_range=(0, 3), y_range=(0, 3))

agg = canvas.points(df, 'x', 'y', agg=ds.count())

sol = np.array([[2, 2, 2],
[0, 0, 0],
[1, 0, 1]], dtype='int32')
out = xr.DataArray(sol,
coords=[('x', [0.5, 1.5, 2.5]),
('y', [0.5, 1.5, 2.5])],
dims=['y', 'x'])

assert_eq(agg, out)


def test_lines_on_edge():
df = pd.DataFrame(dict(x=[0, 3, 3, 0],
y=[0, 0, 3, 3]))

canvas = ds.Canvas(plot_width=3, plot_height=3,
x_range=(0, 3), y_range=(0, 3))

agg = canvas.line(df, 'x', 'y', agg=ds.count())

sol = np.array([[1, 1, 1],
[0, 0, 1],
[1, 1, 1]], dtype='int32')
out = xr.DataArray(sol,
coords=[('x', [0.5, 1.5, 2.5]),
('y', [0.5, 1.5, 2.5])],
dims=['y', 'x'])

assert_eq(agg, out)


def test_log_axis_line():
axis = ds.core.LogAxis()
logcoords = axis.compute_index(axis.compute_scale_and_translate((1, 10), 2), 2)
Expand Down Expand Up @@ -533,3 +573,23 @@ def test_trimesh_agg_api():
cvs = ds.Canvas(x_range=(0, 10), y_range=(0, 10))
agg = cvs.trimesh(pts, tris, agg=ds.mean('weight'))
assert agg.shape == (600, 600)


def test_bug_570():
# See https://github.com/pyviz/datashader/issues/570
df = pd.DataFrame({
'Time': [1456353642.2053893, 1456353642.2917893],
'data': [-59.4948743433377, 506.4847376716022],
}, columns=['Time', 'data'])

x_range = (1456323293.9859753, 1456374687.0009754)
y_range = (-228.56721300380943, 460.4042291124646)

cvs = ds.Canvas(x_range=x_range, y_range=y_range,
plot_height=300, plot_width=1000)
agg = cvs.line(df, 'Time', 'data', agg=ds.count())

# Check location of line
yi, xi = np.where(agg.values == 1)
assert np.array_equal(yi, np.arange(73, 300))
assert np.array_equal(xi, np.array([590] * len(yi)))
9 changes: 8 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

[tox]
# python version test group extra envs extra commands
envlist = {py27,py35,py36}-{lint,unit,examples,all,examples_extra}-{default}-{dev,pkg}
envlist = {py27,py35,py36}-{lint,unit,unit_nojit,examples,all,examples_extra}-{default}-{dev,pkg}
build = wheel

[_lint]
Expand All @@ -19,6 +19,11 @@ description = Run unit tests
deps = .[tests]
commands = pytest datashader

[_unit_nojit]
description = Run select unit tests with numba jit disabled
deps = .[tests]
commands = pytest datashader -k "not benchmarks and not test_tiles"

[_examples]
description = Test that default examples run
deps = .[examples, tests]
Expand Down Expand Up @@ -46,12 +51,14 @@ changedir = {envtmpdir}

commands = pkg: {[_pkg]commands}
unit: {[_unit]commands}
unit_nojit: {[_unit_nojit]commands}
lint: {[_lint]commands}
examples: {[_examples]commands}
examples_extra: {[_examples_extra]commands}
all: {[_all]commands}

deps = unit: {[_unit]deps}
unit_nojit: {[_unit_nojit]deps}
lint: {[_lint]deps}
examples: {[_examples]deps}
examples_extra: {[_examples_extra]deps}
Expand Down

0 comments on commit 0955e86

Please sign in to comment.