I have a figure in which I render rectlinear cells. The aspect ratio of my figure is expected not to be 1:1, or better to say a good deal of. Thus the cells are not squares.
Within some of the squares I want to render circles. These circles are supposed to appear as actual circles, not elongated ellipses, and they should be as big as possible without leaving the cell.
My first attempt was to go with going like
self.plot = figure(...
self.plot.image(...
radius = min(cell_size_x_in_dataspace, cell_size_y_in_dataspace)
self.plot.circle('x', 'y', source=self.my_source, radius=radius)
This did not work well - the size of the circle depended heavily on the aspect ratio.
So I tried some convoluted code in which I used ellipses and computed the screen space ratio of the cell. However, I for that I needed to access the inner dimensions of the plot and using code like width = self.plot.inner_width
resulted in an bokeh.core.property.descriptors.UnsetValueError
.
So I went and made this delayed:
def _routine_for_plotting(self):
self.plot = figure(...
self.plot.image(...
...
self.plot.on_change('inner_width', self._create_ellipses)
self.plot.on_change('inner_height', self._create_ellipses)
def _create_ellipses(self, attr, old, new):
if not self._has_inner_sizes():
return
inner_width = self.plot.inner_width
...
<do some calculations regarding the cell ratios>
self.plot.ellipse('x', 'y', source=self.my_source, width=ellipse_width, height=ellipse_height)
def _has_inner_sizes(self) -> bool:
try:
width = self.plot.inner_width
height = self.plot.inner_height
except UnsetValueError:
return False
return True
Now this works, but it is not exactly clean code. I see no way to check whether the inner dimensions exist yet without either relying that inner_height
is created last or doing that black magic regarding exceptions.
But I thought that maybe I made this far too complicated anyway and the latter part about checking whether the inner dimensions exist might be a XY-problem.
In any case, does anybody see a more elegant way to do this?