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.
Thanks Ricky, I'll check this out.
#105 addresses this as well. When using plotly.offline.iplot, the plot looks all right, except that LaTeX is not rendered in any of the text labels.
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?
FYI, sometimes after executing iplot, the LaTeX I have else where in my notebook (outside of plotly) breaks and stops rendering. I'm having trouble replicating this on sample data that I can share, but will update with code if I'm able to do so.
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>'
))
@jjaraalm's piece of code (above) fixed the problem for me. Thank you!
Thanks for posting @jjaraalm ! I tried to add that snippet to the offline code but was getting some errors from Mathjax. Here is the PR: https://github.com/plotly/plotly.py/pull/683.
Has anyone else been successful in adding this?
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.

Another update:
I found this code works well on Firefox, but not the same case on Chrome.

However, in Chrome, if I use the inspect mode and then refresh the page, this code works again.

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')
Better would be a PR enabling the MathJAX CDN, which I am working on.
I'm also interested in a solution to this problem. I do not use Jupyter notebooks, so the solution of jjaraalm does not work for me. The solution from ianhbell works fine for basic use, but it seems that it fails for parallel coordinates. Does anybody have a workaround for using latex in the labels of the parallel coordinate plots?
My MWE is no longer working, darn.
Unfortunately using the snippet from @jjaraalm now doesn't render any title when I try to use plot ly offline mode... Any ideas how to fix this? This occurs even after deleting the display(HTML(....)) code snippets and restarting the kernel. Before it would at least provide a title when I tried to use LATEX but now it only displays a title if I do not use any $ ... $ text in the title string.
Any help would be appreciated!
Same problem here.
Titles are not displayed if using $...$ math mode
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)
Any progress? Is anyone working on this issue?
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!
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.
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.
Most helpful comment
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: