3

I am having two mutually exclusive issues with my sample plot below.

  1. The y-axis label and y-tick labels are on top of each other. I have not been able to find a way to shift either. I would like the size of the plot to expand to accommodate the necessary spacing.
  2. I want the y-axis label to be sigma with a subscript theta. It looks like Unicode does not allow a subscript theta. I was hoping to get around this limitation by using LaTeXStrings. However, I cannot get the LatexString to expand into the appropriate form on the plot. Note that issue #1 occurs with or without a LatexString as the ylabel and that LatexString expansion is not working for other string values either.

Sample plot, code, and data are provided below to reproduce. I am using the Juno editor with the Plotly backend on Windows.

Sample plot showing y-axis issues

using Plots, DelimitedFiles, LaTeXStrings
plotly(linewidth=3,titlefont=18,legendfont=16,guidefont=18,tickfont=14,formatter=:plain)
data=readdlm("hoopstress.txt",skipstart=1)
r=data[:,2]
σθ=data[:,end-1:end]
plot(r,σθ,label=["Simplified Vessel" "Full Vessel"],xlabel="r",ylabel=L"\sigma_\theta")
    Length  Simple  Full
1   0.  53280   56859
2   9.4e-2  52158   55405
3   0.1875  51036   53951
4   0.28125 49915   52498
5   0.375   48793   51044
6   0.46875 47671   49590
7   0.5625  46550   48136
8   0.65625 45428   46682
9   0.75    44307   45228
10  0.84375 43185   43774
11  0.9375  42063   42320
12  1.0312  40942   40866
13  1.125   39883   39411
14  1.2187  39256   38780
15  1.3125  38629   38150
16  1.4062  38002   37519
17  1.5 37375   36888
18  1.5938  36748   36257
19  1.6875  36121   35627
20  1.7813  35494   34996
21  1.875   34867   34365
22  1.9688  34239   33735
23  2.0625  33612   33104
24  2.1562  32985   32473
25  2.25    32389   31842
26  2.3437  31998   31441
27  2.4375  31607   31039
28  2.5312  31216   30637
29  2.625   30825   30235
30  2.7187  30434   29833
31  2.8125  30043   29431
32  2.9062  29652   29029
33  3.  29261   28628
34  3.0938  28870   28226
35  3.1875  28479   27824
36  3.2813  28088   27422
37  3.375   27714   27020
38  3.4688  27452   26693
39  3.5625  27190   26367
40  3.6563  26927   26040
41  3.75    26665   25714
42  3.8438  26403   25387
43  3.9375  26141   25061
44  4.0313  25879   24734
45  4.125   25617   24408
46  4.2187  25354   24081
47  4.3125  25092   23755
48  4.4062  24830   23428
49  4.5 24568   23102
Nathan Boyer
  • 1,412
  • 1
  • 6
  • 20

4 Answers4

2

Latex output seems to be currently broken in Plotly. I read, that for some people it depends on the browser. I couldn't get it to work on neither Edge nor Chrome.

Concerning the overlap it is, unfortunately, the standard setting of plotly itself. However, plotly and also the Julia package Plotly provide the yaxis.automargin = true parameter to overwrite this setting. If you want additional space you can achieve this by adding a non-empty line to your title, which is done by adding the html code <br>&nbsp; Below I have supplied an example code to achieve this in Plotly. (Currently, the plotly() backend of Plotsdoes not support passing backend-specific parameters. But there is work going on to achieve this.)

using Plotly

trace1 = Plotly.scatter(Dict(
  "x" => [1, 2, 3, 4],
  "y" => [1, 4, 9, 16] .* 1000000,
  "name" => L"\alpha_{1c} = 352 \pm 11 \text{ km s}^{-1}",
  "type" => "scatter")
)

trace2 = Plotly.scatter(Dict(
  "x" => [1, 2, 3, 4],
  "y" => [0.5, 2, 4.5, 8] .* 1000000,
  "name" => L"\beta_{1c} = 25 \pm 11 \text{ km s}^{-1}",
  "type" => "scatter")
)

data = [trace1, trace2]

# standard layout (shortens numbers by SI prefix)
layout1 = Layout(xaxis = attr(title = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}"),
                 yaxis = attr(title = L"$d, r \text{ (solar radius)}")
)

# sets the number format to "0", i.e. without prefixing
layout2 = Layout(xaxis = attr(title = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}"),
                 yaxis = attr(title = L"$d, r \text{ (solar radius)}",
                             tickformat = "0")
)

# forces automargin
layout3 = Layout(xaxis = attr(title = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}"),
                 yaxis = attr(title = L"$d, r \text{ (solar radius)}",
                             tickformat = "0",
                             automargin = true)
)

# adds an additional space by adding a line to the title
# note that Plotly seems to accept html code ...
layout4 = Layout(xaxis = attr(title = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}"),
                 yaxis = attr(title = L"$d, r \text{ (solar radius)}<br>&nbsp;",
                              tickformat = "0",
                              automargin = true)
)

p1 = Plotly.plot(data, layout1)
p2 = Plotly.plot(data, layout2)
p3 = Plotly.plot(data, layout3)
p4 = Plotly.plot(data, layout4)

Layout 1 Layout 2 Layout 3 Layout 4

HHFox
  • 311
  • 2
  • 7
  • For others' benefit, PyPlot will accept `"\n"` as newline in plot labels, but GR and Plotly will not. Also "\n" won't work within a LaTeX string. – Nathan Boyer May 13 '20 at 18:21
2

I filed a PR to solve the problem, which has just been merged into master :-)

So in the future you will be able to do

plotly(linewidth=3,titlefont=18,legendfont=16,guidefont=18,tickfont=14,formatter=:plain)
r = 1:10
σθ = [100000 ./ (1:10) .+ 10000, 100000 ./ (1:10) .- 1000 .+ 10000]
plot(r , σθ, label=["Simplified Vessel" "Full Vessel"],
    xlabel = "r",
    ylabel = L"\sigma_\theta\\\color{white}.",
    yformatter = :plain,
    include_mathjax = "cdn",
    extra_kwargs = :plot)

if you are connected to the internet.

For for local use, if Conda and IJulia are installed and the TeX fonts are copied as described in my previous answer, you can do the following.

import Conda.ROOTENV
function local_mathjax()
    joinpath(ROOTENV, "Lib", "site-packages", "notebook", "static", "components", "MathJax",
            "MathJax.js?config=TeX-AMS-MML_HTMLorMML-full")
end

plotly(linewidth=3,titlefont=18,legendfont=16,guidefont=18,tickfont=14,formatter=:plain)
r = 1:10
σθ = [100000 ./ (1:10) .+ 10000, 100000 ./ (1:10) .- 1000 .+ 10000]
plot(r , σθ, label=["Simplified Vessel" "Full Vessel"],
    xlabel = "r",
    ylabel = L"\sigma_\theta\\\color{white}.",
    yformatter = :plain,
    include_mathjax = local_mathjax(),
    extra_kwargs = :plot)

The formatting of y-axis numbers is now realised via yformatter = :plain and the space in the y-title was achieved by adding a line with a white-formatted dot.

Of course, you could also place a mathjax copy anwhere on your system and put the link in the includ_mathjax argument.

More details on the usage can be found in the PR. Happy coding!

HHFox
  • 311
  • 2
  • 7
1

PyPlot Output

Switching to the PyPlot backend fixed both problems straight away.

Switching to the GR backend fixed the LaTeX issue, but made the label overlap worse.

I had some success with the Plotly backend by adding using Plots.PlotMeasures to the top of the script and adding left_margin=80px to either the plot or plotly statements. However, the result wasn't really satisfactory. The margin additions did not affect label spacing with the GR backend.

I still would like to find a solution for directly modifying the plot label positioning since plotly has better interactivity.

Nathan Boyer
  • 1,412
  • 1
  • 6
  • 20
1

Currently plotly does not provide the mathjax environment, but Jupyter does. However, Jupyter by default, does not install the TeX fonts, which seem to be Mathjax default fonts by now.

In order to fix this you have to copy the original mathjax distribution to the directory where jupyter keeps its static files.

  • download MathJax-2.7.7.zip
  • copy the jax-folder from the MathJax-2.7.7.zip to C:\Users\<username>\.julia\conda\3\Lib\site-packages\notebook\static\components\MathJax or whereever the files are stored on your system. Note that there might be more MathJax folders, e.g. C:\Users\<username>\.julia\conda\3\pkgs\notebook-6.0.3-py36_0\Lib\site-packages\notebook\static\components\MathJax, but only one is the true source for the server.

Now you can either use Plotly

using Plotly

trace1 = Plotly.scatter(Dict(
  "x" => [1, 2, 3, 4],
  "y" => [1, 4, 9, 16] .* 1000000,
  "name" => L"\alpha_{1c} = 352 \pm 11 \text{ km s}^{-1}",
  "type" => "scatter")
)

trace2 = Plotly.scatter(Dict(
  "x" => [1, 2, 3, 4],
  "y" => [0.5, 2, 4.5, 8] .* 1000000,
  "name" => L"\beta_{1c} = 25 \pm 11 \text{ km s}^{-1}",
  "type" => "scatter")
)

data = [trace1, trace2]


layout = Layout(xaxis = attr(title = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}"),
                 yaxis = attr(title = L"\sigma_\theta\\?",
                              tickformat = "0",
                              automargin = true)
)

p = Plotly.plot(data, layout)

LaTeX in Plotly

(I couldn't find a quick solution for a line break in LaTeX syntax. The linebreak was only kept if I added a character. Maybe, someone else can contribute here ;-) )

or Plots:

using Plots, LaTeXStrings

plotly()
Plots.plot(1:4, [[1,4,9,16], [0.5, 2, 4.5, 8]], 
    labels = [L"\alpha_{1c} = 352 \pm 11 \text{ km s}^{-1}" L"\beta_{1c} = 25 \pm 11 \text{ km s}^{-1}"],
    xlabel = L"\sqrt{(n_\text{c}(t|{T_\text{early}}))}",
    ylabel = L"d, r \text{ (solar radius)}"
    )

LaTeX with plotly backend of Plots

In order to make it work in Juno make sure that the Conda package is installed and the mathjax fonts are copied as described above. Then make the following definitions:

import Plots.plotly_html_head
import Conda.ROOTENV

function mathjax()
    mathjaxdir = joinpath(ROOTENV, "Lib\\site-packages\\notebook\\static\\components\\MathJax")
    mathjaxfile =  joinpath(mathjaxdir, "MathJax.js?config=TeX-AMS-MML_HTMLorMML-full")
    return """<script type="text/javascript" src="file://$mathjaxfile"></script>"""
end

function plotly_html_head(plt::Plots.Plot)
    local_file = ("file://" * Plots.plotly_local_file_path)
    plotly = Plots.use_local_dependencies[] ? Plots.local_file : Plots.plotly_remote_file_path
    if Plots.isijulia() && !Plots.ijulia_initialized[]
        # using requirejs seems to be key to load a js depency in IJulia!
        # https://requirejs.org/docs/start.html
        # https://github.com/JuliaLang/IJulia.jl/issues/345
        display("text/html", """
        <script type="text/javascript">
        requirejs([$(repr(plotly))], function(p) {
        window.Plotly = p
        });
        </script>
        """)
        ijulia_initialized[] = true
    end
    return """$(mathjax())
    <script src=$(repr(plotly))></script>"""
end
HHFox
  • 311
  • 2
  • 7