Search code examples
plotbokehglyph

Bokeh plot filled semicircle


I would like to plot a filled semicircle in bokeh to show a model of filling a pipe (https://www.engineersedge.com/fluid_flow/partially_full_pipe_flow_calculation/image003.png) where, based on user input, the water level changes. I looked at the available glyphs (https://docs.bokeh.org/en/latest/docs/reference/models/glyphs.html) but wasn't able to find one that would work. I was hoping I could fill the arc glyph but it doesn't seem like that is possible.

Any advice is appreciated.


Solution

  • There is nothing built-in to do just that. Looking at the diagram you linked, you could combine a wedge glyph (for the "pacman" part) and a patch to fill in the rest.

    from bokeh.io import show
    from bokeh.plotting import figure
    from math import pi, sin, cos
    
    p = figure(match_aspect=True)
    p.wedge(x=0, y=0, radius=1, start_angle=-5*pi/4, end_angle=pi/4)
    p.patch(x=[0, -cos(pi/4), cos(pi/4)], y=[0, sin(pi/4), sin(pi/4)])
    
    p.circle(0, 0, radius=1, fill_color=None, line_color="black", line_width=3)
    
    # hack: Bokeh does not yet auto-range this odd combination well
    p.rect(0, 0, 2, 2, color=None)
    
    show(p)
    

    enter image description here

    If these need to be updated somehow, you'd probably want to wrap this up in some helper function to generate the right data values and update ColumnDataSources for the existing glyphs. Best practice is to draw glyphs once up front when possible then later update only their data sources if they need to change.

    A couple of final notes:

    • you need match_aspect=True to ensure aspect ratios in "pixel space" and "data space" are the same, which is necessary to make sure the circle is actually a circle in "data space"

    • match_aspect requires you use the default auto-ranges. If you set explicit range values, Bokeh trusts you know what you want, even if this messes up the aspect.

    • This is an odd combination of single glyphs... the auto-ranges do not do great on them by themselves. I added an invisible rect around the circle to help it out.