bokeh / bokeh

Interactive Data Visualization in the browser, from Python
https://bokeh.org
BSD 3-Clause "New" or "Revised" License
19.21k stars 4.18k forks source link

[BUG] `bokeh.plotting.figure.circle` does not display circles in bokeh 3.4.1 #13899

Open yuji38kwmt opened 3 months ago

yuji38kwmt commented 3 months ago

Software versions

Python version : 3.12.1 (main, Feb 7 2024, 10:25:21) [GCC 11.4.0] IPython version : 8.21.0 Tornado version : 6.4 Bokeh version : 3.4.1 BokehJS static path : /home/yuji/.pyenv/versions/3.12.1/lib/python3.12/site-packages/bokeh/server/static node.js version : (not installed) npm version : (not installed) jupyter_bokeh version : (not installed) Operating system : Linux-5.15.146.1-microsoft-standard-WSL2-x86_64-with-glibc2.35

Browser name and version

Google Chrome 124.0.6367.208(Official Build)

Jupyter notebook / Jupyter Lab version

No response

Expected behavior

I created the figure with bokeh.plotting.figure.circle method.

I expected that circles are displayed in the figure.

Observed behavior

But circles are not displayed in the figure. And no warning was displayed in stdout.

Example code

from bokeh.io import output_file, save
from bokeh.plotting import figure, ColumnDataSource

fig = figure(width=400, height=400)

data = {"a": [1, 2, 3], "b": [3, 1, 2]}
source = ColumnDataSource(data)

fig.circle(
    source=source,
    x="a",
    y="b",
)

output_file("output.html")
save(fig)
$ python sample.py

Stack traceback or browser console output

When specifying radius argument, circles are displayed in the figure.

fig.circle(
    source=source,
    x="a",
    y="b",
    radius=0.1
)

When specifying size argument, circles are displayed in the figure and BokehDeprecationWarning occurred in the console.

fig.circle(
    source=source,
    x="a",
    y="b",
    size=8
)
$ python sample.py
BokehDeprecationWarning: 'circle() method with size value' was deprecated in Bokeh 3.4.0 and will be removed, use 'scatter(size=...) instead' instead.

Screenshots

image

bryevdv commented 3 months ago

@yuji38kwmt Your original code, with size=8 added, plots just fine for me:

Screenshot 2024-05-17 at 10 02 20

You'll need to look for some additional information, e.g. is there any output or error messages in the browser's JS console log?

mattpap commented 3 months ago
data = {"a": [1, 2, 3], "b": [3, 1, 2]}
source = ColumnDataSource(data)

fig.circle(source=source,  x="a",  y="b")

In 3.3 and earlier this would produce Scatter glyph, which has a default value for size property (4), that results in a working plot. Whereas now this will produce Circle glyph which has a field("radius") default value for radius property, which doesn't result in a working plot.

In bokehjs radius positional argument in fig.circle(x, y, radius, ...args) is required, so at least there will be an immediate error. In bokeh's plotting API this argument is optional and omitting it, like in the test case, results in an empty plot and the warning in JS console:

[bokeh 3.5.0-dev.3] attempted to retrieve property array for nonexistent field 'radius'
yuji38kwmt commented 3 months ago

You'll need to look for some additional information, e.g. is there any output or error messages in the browser's JS console log?

@bryevdv I summarized screenshot images and browser console again.

If radius is None and size is None

$ python sample.py
$ 
fig.circle(
    source=source,
    x="a",
    y="b",
)

image

Browser Console

[bokeh 3.4.1] setting log level to: 'info'
bokeh-3.4.1.min.js:184 [bokeh 3.4.1] attempted to retrieve property array for nonexistent field 'radius'
uniform @ bokeh-3.4.1.min.js:184
bokeh-3.4.1.min.js:166 [bokeh 3.4.1] document idle at 40 ms

If radius is None and size is not None

fig.circle(
    source=source,
    x="a",
    y="b",
    size=8
)
$ python sample.py
BokehDeprecationWarning: 'circle() method with size value' was deprecated in Bokeh 3.4.0 and will be removed, use 'scatter(size=...) instead' instead.

image

Browser Console

[bokeh 3.4.1] setting log level to: 'info'
bokeh-3.4.1.min.js:166 [bokeh 3.4.1] document idle at 68 ms

If radius is not None and size is None

fig.circle(
    source=source,
    x="a",
    y="b",
    radius=0.1
)
$ python sample.py
$

image

Browser Console

[bokeh 3.4.1] setting log level to: 'info'
bokeh-3.4.1.min.js:166 [bokeh 3.4.1] document idle at 77 ms
yuji38kwmt commented 3 months ago

In bokehjs radius positional argument in fig.circle(x, y, radius, ...args) is required,

In bokeh 3.3.4, the following code worked without any problems.

fig.circle(
    source=source,
    x="a",
    y="b",
)

So, I was not aware that radius argument is required.

golmschenk commented 3 months ago

I'm seeing a similar issue where, if neither size nor radius is set, no circle glyphs appear. I would expect that the default setting (not setting either) would still have glyphs appear. It occurs in both Safari and Chrome.

Example

from bokeh.io import show
from bokeh.plotting import figure as Figure

figure = Figure()
figure.circle(x=[0, 1, 2], y=[3, 5, 4])
show(figure)

screenshot_2024_05_21_12_04_47

Output of bokeh info

Python version        :  3.11.8 | packaged by conda-forge | (main, Feb 16 2024, 20:49:36) [Clang 16.0.6 ]
IPython version       :  8.12.3
Tornado version       :  6.4
Bokeh version         :  3.4.1
BokehJS static path   :  /opt/homebrew/Caskroom/mambaforge/base/envs/haplo/lib/python3.11/site-packages/bokeh/server/static
node.js version       :  v21.6.2
npm version           :  10.2.4
jupyter_bokeh version :  (not installed)
Operating system      :  macOS-14.4.1-arm64-arm-64bit
bryevdv commented 2 months ago

@mattpap is field("radius") a default we should keep? I guess it makes this one very specific case work "automagically"?

source = ColumnDataSource(radius=...)
plot.circle(..., source=source)

i.e. if you happen to have a CDS with a "radius" column and you happen to want to use that column for the circle radius property, then you can save a few characters and omit radius="radius".

I'm not sure that is worth the confusion in all other cases. I think we could just make radius actually non-optional on the Python side.

bryevdv commented 1 month ago

@mattpap thoughts on making radius non-optional in 3.6?