I am plotting some geometry using bokeh and came across this. I am plotting a rectangle with equal sides (i.e. a square), and in that square, plotting a circle with diameter = width of the square. The circle should tangent to the square at edges, but it is not.
here is the code:
from bokeh.plotting import output_notebook, figure, show
output_notebook()
p = figure(width=500, height=500)
p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
p.axis.minor_tick_out = 0
show(p)
Which results in this:
Is there anything I am doing wrong or could change to make the circle fit exactly in the square?
Thanks in advance, Randall
Here's another case - just drawing a circle:
p = figure(width=500, height=500, x_range=(-150, 150), y_range=(-150, 150))
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
show(p)
radius of the circle is 150 in the x direction, but not the y-direction.
I would like to report that as of Bokeh 0.12.7, this issue can now be fixed in a simpler manner.
As described in other posts, the main issue is not that the circle is not a circle, but that the square is not a square. This is due to the fact that actual area on which Bokeh draws the figure (the canvas) is usually not a square by default or even when the width and height are set to the same value. Bokeh by default will attempt to draw a figure by using up all the space on the canvas. This creates a mismatch between the data distance and the pixel distance of the plot.
As of 0.12.7, figures can now accept a match_aspect
property which when set to True will will match the aspect of the data space to the pixel space of the plot.
In your example, simply adding the match_aspect = True
in your figure
p = figure(width=500, height=500, match_aspect=True,
title="Circle touches all 4 sides of square")
p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
will now produce
UPDATE: Please note new answer by @DuCorey below. As of Bokeh 0.12.7, aspect control is now available, for situations like this.
The issue is actually that the square is not square, and that is because the pixel aspect ratio and the "data" aspect ratio do not match. i.e., the distance per pixel is different in the x direction than it is in the y direction.
There are a few options:
You can use various properties to control the dimensions of the central plot area (e.g. plot border width and axis tick label orientation) You can also control you data ranges explicitly. In other words, you can make the aspect ratios match, and then the circle and rect will match
You can use absolute pixel units (e.g. size
for a circle, and use a large square
marker instead of rect
) instead of "data" units.
Alternatively, if you want a circle that "deforms" when the aspects do not match, then your best bet is to use an ellipse
with an identical width
and height
, which will work because in this case bokeh has two dimensions to use to measure (instead of the single radius
) and can match each to the scale along each dimension independently.
(This is actually the fundamental difference that explains the behaviour: rect
has two dimensions to measure independently. circle
does not, it only has one, and has to arbitrarily use the x or y dimension to measure distance per pixel)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With