plotly.py: MathJax not loaded in plotly offline

plotly.offline.plot fails (shows an unstyled plot after bailing out early due to errors) if latex is used since MathJax is not loaded in the default html. Short of getting fancy, it seems like plotly.offline.plot might need a manual option to inject MathJax from a cdn into the head tag.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 20 (6 by maintainers)

Commits related to this issue

Most upvoted comments

EDIT: Actually, this might not be the right place for this since the original issue did not explicitly specify Jupyter notebooks, might be more closely related to #105 or #444

This is not really an issue with plotly.py per-se, but is the result of issues upstream at plotly.js.

plotly.js does not encapsulate mathjax but instead relies on it being loaded globally and configured in a specific way. The problem is that there are multiple different output renderers for mathjax. Juypter globally loads mathjax with HTML output, but plotly.js requires SVG output. A quick and easy fix is just to change the output renderer for mathjax globally as this does not affect Juypter’s markdown rendering.

In order to address #445, mathjax should also be configured to set displayAlign = center since plotly.js explicitly sets this to left align. As far as I can tell in simple testing, the display alignment actually has no bearing on the output rendered by plotly.

Right now the code block I’m using to fix all these issues is:


# Startup plotly
init_notebook_mode(connected=True)

# The polling here is to ensure that plotly.js has already been loaded before
# setting display alignment in order to avoid a race condition.
display(HTML(
    '<script>'
        'var waitForPlotly = setInterval( function() {'
            'if( typeof(window.Plotly) !== "undefined" ){'
                'MathJax.Hub.Config({ SVG: { font: "STIX-Web" }, displayAlign: "center" });'
                'MathJax.Hub.Queue(["setRenderer", MathJax.Hub, "SVG"]);'
                'clearInterval(waitForPlotly);'
            '}}, 250 );'
    '</script>'
))

This is actually the only reason that stops me using plotly for my publication graphics. No LaTeX in offline plotly is a serious issue, is there any news on this? #444 and #445 also addresses latex problems with plotly.

Done in #1243 and will be released in version 3.4.0. LaTeX support requires no API changes for iplot or FigureWidget support. An additional include_mathjax argument has been added to plotly.offline.plot to specify how MathJax should be included in the resulting html file/div.

Hi All,

I’ve started digging into this a bit and I’m pretty confident we’ll have latex/MathJax support working for plotly.offline.plot (standalone html/div) for version 3.3.0. I’m also hopeful that we’ll be able to add support for plotly.offline.iplot and plotly.graph_objs.FigureWidget at the same time, but these are a bit more complicated because Jupyter also relies on MathJax, and it requires MathJax be configured in a different global mode.

In case it’s helpful for building workarounds in the meantime, here is the PR where I started experimenting with this: https://github.com/plotly/plotly.py/pull/1169. This PR won’t be merged in it’s current form, but the basic concepts seem pretty sound.

Also in the meantime, plotly.plotly.plot, plotly.plotly.iplot, and the orca static image export already support latex/MathJax.

Thanks Ricky, I’ll check this out.

Here is a MWE of latex working in offline mode. A bit hacky, but it works. Basically, add our own custom header with mathjax included, and then store our figure in a div.

import plotly.offline as offline
import plotly.graph_objs as go
import os

trace1 = go.Scatter(
    x=[1, 2, 3, 4],
    y=[1, 4, 9, 16],
    name='$\\alpha_{1c} = 352 \\pm 11 \\text{ km s}^{-1}$'
)
data = [trace1]
layout = go.Layout(
    xaxis=dict(
        title='$\\sqrt{(n_\\text{c}(t|{T_\\text{early}}))}$'
    ),
    yaxis=dict(
        title='$d, r \\text{ (solar radius)}$'
    )
)
fig = go.Figure(data=data, layout=layout)

def with_jax(fig, filename):

    plot_div = offline.plot(fig, output_type = 'div')

    template = """
    <head>
    <script type="text/javascript" async
      src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG">
    </script>
    </head>
    <body>
    {plot_div:s}
    </body>""".format(plot_div = plot_div)
    with open(filename, 'w') as fp:
        fp.write(template)
    os.startfile(filename)
with_jax(fig, 'cube.html')

Hi, are we still working on a fix for this issue?

I tried the code block posted by @jjaraalm but unfortunately it doesn’t work for me.

import plotly
plotly.offline.init_notebook_mode(connected=True)
from IPython.core.display import display, HTML
# The polling here is to ensure that plotly.js has already been loaded before
# setting display alignment in order to avoid a race condition.
display(HTML(
    '<script>'
        'var waitForPlotly = setInterval( function() {'
            'if( typeof(window.Plotly) !== "undefined" ){'
                'MathJax.Hub.Config({ SVG: { font: "STIX-Web" }, displayAlign: "center" });'
                'MathJax.Hub.Queue(["setRenderer", MathJax.Hub, "SVG"]);'
                'clearInterval(waitForPlotly);'
            '}}, 250 );'
    '</script>'
))

I used nbconvert to html, but the latex will still show as $$ code $$. I am not sure if I used this code correctly.

screen shot 2017-02-20 at 7 00 30 pm

I’ve been having the same (or a very similar one?) issue. Latex works in the jupyter notebook, but not always in the exported html version. Chrome still shows the equations fine (even though sometimes it doesn’t and a reload of the page is required), while firefox doesn’t.

I found that a quick (if not very handy) fix is to add the following in the source of the exported html file, just after the MathJax configuration lines:

<script type="text/javascript">MathJax.Hub.Queue(["Typeset", MathJax.Hub]);</script>

I see the above behaviour already with the following MWE (plus any markdown cell with some latex in it):

import numpy as np
import plotly
import plotly.graph_objs as go
plotly.offline.init_notebook_mode(connected=False)
zs = np.random.randn(50, 50)
data = [go.Surface(z=zs)]
layout = go.Layout(
    autosize=False,
    width=500,
    height=500,
    margin=dict(
        l=0, r=0, b=0, t=0
    )
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig)

Hi @sursu ,

I haven’t started digging into this yet, but I definitely agree with everyone that it’s very important.

One bit of good news is that Mathjax/latex support is already working in the new offline static image export feature that is coming in version 3.2. So the publication use-case should finally be covered!

My MWE is no longer working, darn.