Refactoring custom MarkerView from < v2

hello!

so…i’ve been putting this off for a while, but i’m returning to a project that’s been…on hold for a bit and…well…i really want my damn custom marker.

so…when figured out that i couldn’t quite get the stock markers to do exactly what i needed, i popped into…whatever the live chat for bokeh is and one of the devs was kind enough to quickly throw together the below:

from bokeh.models import Marker

JS_CODE = """
import {Marker, MarkerView} from "models/markers/marker"

export class MyTriangleView extends MarkerView
  _render_one: (ctx, i, r, line, fill) ->
    h = r * Math.sqrt(3)
    a = h

    ctx.moveTo(-r, a)
    ctx.lineTo(r, a)
    ctx.lineTo(0, a - h)
    ctx.closePath()

    if (fill.doit)
      fill.set_vectorize(ctx, i)
      ctx.fill()

    if (line.doit)
      line.set_vectorize(ctx, i)
      ctx.stroke()

export class BuySell extends Marker
  default_view: MyTriangleView
  type: "BuySell"
"""
class BuySell(Marker):

    __implementation__ = JS_CODE

i remember seeing the dreaded “we’re going to be deprecating this…so get your shit together with this custom JS marker.” but life and i had to put the project on hiatus. i think even at the time, the documentation for what the dev did…didn’t really exist…sort of an in-house hookup, if you will. I’ve tried giving the documentation another college try, to no avail. i’m either missing something or i just don’t know wtf i’m supposed to be searching for.

that said, i suppose i have the following:

  • how does one implement custom markers with the current stable bokeh release?
  • if there is documentation, please for the love of superman point the way.
  • if there is not, how in the name of kelly clarkson does one refactor the above for python?

i sort of just #yolo’d the below, but i have a feeling it’s…you know…not correct.

class BSTriangle(MarkerView):

    def __init__(self, ctx, i, r, line, fill):

        self.ctx = ctx
        self.i = i
        self.r = r
        self.line = line
        self.fill = fille

    def _render_one(self):

        h = r * math.sqrt(3)
        a = h

        ctx.moveTo(-r, a)
        ctx.lineTo(r, a)
        ctx.lineTo(0, a - h)
        ctx.closePath()

        if fill.doit:
            fill.set_vectorize(ctx, i)

        if line.doit:
            line.set_vectorixe(ctx, i)
            ctx.stroke()

class BuySell(Marker):

    def __init__(self):

        self.default_view = BSTriangle
        self.type = 'BuySell'

help me obi wan(s)!

alright…so i THINK this is where this came from…

if i’m not terribly far off…looks like…the js code is creating a custom glyph and ctx, i, r, line, and fill, refer to the associated properties pertaining to one of the glyphs…or marker glyph…

line and fill have to correspond to the line properties and fill properties.
r is most likely radius.
i, could be inner radius?
wtf is ctx? there’s a cx and cy property…is ctx like…a coord tuple?

oh god my brain is leaking out of my ear again.

This is the most relevant documentation section: https://docs.bokeh.org/en/latest/docs/user_guide/extensions.html

Note that BokehJS is still not standardized in any way, so whatever you implement might still break with the next update, even a minor one.
Also note that you don’t really need a full-blown custom marker if you can just plot it by combining other markers. I.e. instead of a single custom marker that draws three lines, you can just draw 3 line markers, something like that.

…this might be pure speculation, but wouldn’t a custom marker be…the more optimized route as it’s being rendered on import instead of having to draw three separate lines during figure generation?

the reason for the custom marker was that at the time i initially requested this code, there was no marker which could pivot around an external point. if i recall, the anchor was the central point of INSERTGLYPHVARIANTHERE…there’s a method to the madness. this marker does exactly what i need it to, so i’d just like to know how to convert it to the most…future proof variant (typescript?) at the moment so i can get it working again.

Having a specialized marker would be more efficient, yes. But you should not care about that unless you start having noticeable performance degradation when using multiple markers representing a single one.

As of now, there’s no future proof variant. Many of the relevant things are a subject to change in any future version. Perhaps there will be such a way past Bokeh 3.