Extending MultiLine gives Error

I would like to try and extend MultiLine to support vertical offsets as described in #3443

I have tried copy pasting multiline properties from glyph.py and multi_line.js as a start.
This has already helped me implement box selection as discussed in #6336 (by implementing _hit_rect for any point on the curve)
However, this time I need to implement offset and scale vector parameters so I started to try and find out how to parse the extra parameters and update the ys parameter.

My offset_multiline.py:

from typing import Any

from bokeh.core.property.dataspec import NumberSpec, field
from bokeh.io import output_file, show
from bokeh.models import MultiLine, ColumnDataSource, GlyphRenderer
import numpy as np
from bokeh.plotting._decorators import glyph_method


class OffsetMultiLine(MultiLine):
    __implementation__ = "offset_multiline.js"
    _args = ('xs', 'ys', 'offset', 'scale')

    offset = NumberSpec(default=field("offset"), help="""
    The offset in the y-scale
    """)

    scale = NumberSpec(default=field("scale"), help="""
    The gain in y-scale
    """)

@glyph_method(OffsetMultiLine)
def offset_multiline(self, *args: Any, **kwargs: Any) -> GlyphRenderer:
    pass

from bokeh.plotting import Figure, figure
Figure.offset_multiline = offset_multiline

if __name__ == '__main__':
    x = np.linspace(0, 10, 100)
    xs = [x]*2
    ys = [np.sin(x+i) for i in range(2)]
    offset= np.linspace(0,2,2)
    scale=[1,1]

    source = ColumnDataSource(dict(xs=xs,ys=ys,offset=offset,scale=scale))
    p = figure(tools='tap,wheel_zoom,pan,box_select')
    p.offset_multiline(source=source, xs="xs", ys="ys",
                       offset="offset", scale="scale",
                       line_color="#8073ac", line_width=2, hover_line_width=5)

    show(p)

and offset_multiline.js:

var _a;
import {MultiLine, MultiLineView} from "models/glyphs/multi_line"
import * as p from "core/properties";
import {LineVector} from "core/property_mixins";

export class OffsetMultiLineView extends MultiLineView {
}

export class OffsetMultiLine extends MultiLine {
}

_a = OffsetMultiLine;
_a.__name__ = "OffsetMultiLine";
(() => {
    _a.prototype.default_view = OffsetMultiLineView;
    // When I include the following lines, I get an "Error: Model 'OffsetMulitiLine' does not exist"
    _a.define(({}) => ({
        xs: [p.XCoordinateSeqSpec, { field: "xs" }],
        ys: [p.YCoordinateSeqSpec, { field: "ys" }],
    }));
    _a.mixins(LineVector);
})();

The problem arises when I include the _a.define() and _a.mixins() lines in the bottom of the .js file. (which probably just exposes my limited knowledge about JS.)

Secondly I would implement the offset and scale and parameters but I am happy to do some exploring/experimenting myself…

1 Like