Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] plotting text via figure.text() gives BAD_COLUMN_NAME for text_font key #11044

Open
kiramt opened this issue Mar 12, 2021 · 5 comments
Open

Comments

@kiramt
Copy link

kiramt commented Mar 12, 2021

ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)

bokeh 2.3.0
python 3.7.4
MacOS Big Sur
Chrome 88.0.4324.192

Description of expected behavior and the observed behavior

In bokeh 2.3.0, if I use the figure.text() method to plot text then setting text_font="arial" gives an error:

ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name. This could either be due to a misspelling or typo, or due to an expected column being missing. : key "text_font" value "arial" [renderer: GlyphRenderer(id='1037', ...)]

and the text is plotted in (I presume) the default font.

In bokeh 2.2.3 there is no error and the text is plotted in Arial.

Example code:

    from bokeh.plotting import figure, ColumnDataSource
    from bokeh.models import Range1d
    from bokeh.io import show
    import pandas as pd

    output_file("test_text.html")
    plot = figure(
        plot_width=500,
        plot_height=500,
        x_range=Range1d(0, 200),
        y_range=Range1d(0, 100))
    plot.text(
        x="x",
        y="y",
        text="text",
        text_align="center",
        text_font_size="30px",
        text_font="arial",
        text_font_style="normal",
        source=ColumnDataSource(
            pd.DataFrame.from_records(
                [
                    dict(
                        x=100,
                        y=50,
                        text="Hello",
                        color="black",
                    )
                ]
            )
        ),
    )
    show(plot)

JavaScript console output:

[bokeh] setting log level to: 'info'
bokeh-2.3.0.min.js:183 [bokeh] attempted to retrieve property array for nonexistent field 'arial'
uniform @ bokeh-2.3.0.min.js:183
bokeh-2.3.0.min.js:165 [bokeh] document idle at 35 ms

Compared to this for 2.2.3:

[bokeh] setting log level to: 'info'
bokeh-2.2.3.min.js:166 [bokeh] document idle at 28 ms

Screenshots

Screen Shot 2021-03-12 at 10 35 18

compared to 2.2.3:
Screen Shot 2021-03-12 at 10 35 49

@kiramt kiramt added the TRIAGE label Mar 12, 2021
@mattpap
Copy link
Contributor

mattpap commented Mar 12, 2021

text_font="arial"

text_font property became vectorizable in bokeh 2.3, so text_font="arial" shorthand is interpreted as text_font=field("arial") instead of text_font=value("arial") (as it used to be pre 2.3). This is a side effect of how the properties system resolves string values of vectorizable properties, where a subset of strings is interpreted as values and the rest as fields, where the later is the preferred outcome.

(from bokeh.core.properties import value, field)

@kiramt
Copy link
Author

kiramt commented Mar 12, 2021

ok, thanks for the explanation/how to fix!

@bryevdv
Copy link
Member

bryevdv commented Mar 12, 2021

@mattpap I'm not aware of any way to discern whether a given string is a font name or not, so I'm not sure what there is to do except possibly special case a collection of common font names, which won't be able to catch everything.

@Haptein
Copy link

Haptein commented Mar 22, 2021

Why not check if text_font is a column name, if not then assume it's a font name?

@bryevdv
Copy link
Member

bryevdv commented Mar 22, 2021

A user could add the glyph before the data source. i.e., the column might not exist yet, but could be added later. There is no way to know.

The only way to actually disambiguate this is to put the burden squarely on the user to tell us explicitly what they intend, e.g.

text_font=field(colum_name)
text_font=value(font_name)

I suppose we could use an .asserts clause to enforce this more explicit usage, but doing so would break all existing code that sets fonts.

Realistically I think the best we can do is change all the examples to illustrate the above as best practice and reinforce that guidance in the docs. And possibly use an .asserts clause to merely issue a warning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants