Choosing a plotting library

Since 9 months I am trying to find a good Julia plotting library,
but I was not successful.

So I am going back to PythonPlot.jl, the latest wrapper for the
Python based matplotlib library.

What does it offer that the more native Julia libraries do not offer?

A combination of features that are crucial for my work:

  1. one plot window per plot; I often want to compare different plots
    or want to see a number of plots in context
  2. the possibility to zoom and pan the plot
  3. when zooming, the axis lables should adapt
  4. beeing able to see the x and y positions of the cursor as numbers
  5. nice layout
  6. good choice of plotting types and layouts
  7. some stability

The InspectDR library supports 1, 2 and 4, but not 3, 5 and 6.
If I use Plots.jl with PythonPlot I loose 3. and 4.

With PlotlyJS I loose 5.

I hope that - perhaps in a year - the Julia plotting libraries are
good enough to finally replace matplotlib.

5 Likes

I think both Gnuplot.jl and Gaston.jl have all those features (depending on the specifics of 5 and 6).

You seem to have missed Plots.jl plot() keyword argument: ticks = :native

2 Likes

May I ask why you are not considering Makie?

2 Likes

I think you have a point here - matplotlib matured over many years, that is why it is so good in many cases. I also use PyPlot in many situations.

Its biggest drawback IMHO besides the fact that it is not native Julia is missing 3D accelerated rendering support, and speed (due to python…). The later is also not solved by gnuplot/Gaston, as all data are piped with ascii encoding.
With mostly 1D plots, this may be no problem though.

My biggest hope is Makie: it is really fast (besides TTFP which btw improved with 1.9) and uses modern OpenGL as a backend. The API is in a way special, but adapter packages could help with this. Multiple windows are kind of WIP.

So yeah I think we are not there yet with plotting compared to what could be possible - no blame intended here, it is all lots of sometimes very detailed work.

Due to this situation I created GridVisualize.jl which provides a common API on top of different backends for the visualizations I need (1D/2D/3D).

5 Likes

A great pure Julia plotting library would be nice to have, but why is that so important for usecases covered by matplotlib?
Matplotlib interface is reasonable (through far from perfect and shows its age), plots are very customizable, and it’s immensely popular with lots of solutions even for tricky problems on stackoverflow. Most often, exactly the same matplotlib code works in Julia and in Python, or with obvious minor modifications (great kudos to PyCall!).
Btw, for simple interactive plots (including hover) you may also want to try altair based on vegalite. It’s also a python library, and also works great with PyCall.

3 Likes

Well, the installation of conda/Python in addition to Julia is something I would prefer to avoid, in particular because it can easily brake… For myself it doesn’t matter so much, but if I give a piece of software to a group of 20 people it does matter a lot.

11 Likes

A comment on Makie:

one plot window per plot; I often want to compare different plots
or want to see a number of plots in context

It’s not the default because we thought for most workflows you do not want so many windows accumulating, so you have to manually make new windows. Mayne that could become a setting in the future.

the possibility to zoom and pan the plot

Check

when zooming, the axis lables should adapt

Check

beeing able to see the x and y positions of the cursor as numbers

There’s the data inspector which is already pretty useful, although you have to activate it manually and it’s not as nicely integrated into the gui as it could be, for example through a toggle button.

nice layout

Check

good choice of plotting types and layouts

I would say check, there’s a lot of stuff available. Not really sure what choice of layouts means. We need work regarding polar plots, ternary plots and other more special types in the long tail.

some stability

Makie does break from time to time but recently the changes have been less work to incorporate into old code I would say. Before the Figure workflow to now is a big step but that has been around for a while now. We do have larger changes somewhere on the horizon though, to fix long-standing pain points.

15 Likes

You probably know of it already but there is TernaryDiagrams.jl. I haven’t used it but from what I can see it looks like you can make pretty good plots with it already.

To point 4, I think that mouse hovering (data picking in MATLAB) is a very useful feature to have. That’s one point for plotlyjs.jl which as this as default behaviour (as discussed here).
Looks like it’s also possible with Makie but it did not look straightforward
to me (MWE would be welcome).
In practice, I currently use Plots.jl for teaching and for simple scripts, Plotlyjs.jl for visualising results of a 2D production code using 2D rectangular meshes and Makie for visualising data on unstructured meshes. I’m trying to find a way to only use one package…

Thanks for pointing that out. The keyword ticks = :native indeed helps.

But the resulting layout is not so good. Example:

using PythonPlot

fig = figure()
X = 1:10
Y = [11.28812, 11.1200048, 10.9518896, 10.7837744, 
    10.6156592, 10.447544, 10.279428800000002, 10.111313599999999, 9.9431984, 9.7750832]
plot(X, Y,  label="Scenario 1 [Mt]")
X1 = X
Y1 = [11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 
      11.209272, 11.209272, 11.209272]
println(Y1)
plot(X, Y1, label="Reference [Mt]")
grid("on")
ylim(0, 12)
title("Yearly CO2 emmissions")
legend()
nothing

Resulting diagram:

Pretty nice!

Now the same with Plots.jl and PythonPlot, first the code:

using Plots
pythonplot()  
X = 1:10
Y = [11.28812, 11.1200048, 10.9518896, 10.7837744, 
    10.6156592, 10.447544, 10.279428800000002, 10.111313599999999, 9.9431984, 9.7750832]
X1 = X
Y1 = [11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 11.209272, 
      11.209272, 11.209272, 11.209272]
plot(X, Y,  ylims=(0,12), label="Scenario 1 [Mt]", ticks = :native, title="Yearly CO2 emmissions")
plot!(X, Y1, label="Reference [Mt]", ticks = :native)

And the resulting diagram:
Plots

There are two things that I do not like:

  • the diagram is not centred, instead there is a large margin on the right
  • bad location of the legend, it hides one line

Why is PythonPlot on its own able to do it good, and as soon as you add the Plots.jl layer the layout becomes bad?

Well, I use an old version of Makie for 3D plots, but I am not updating the version because the updates would brake my code a couple of times per year. So I will wait with using Makie for 2D until the 1.0 version of Makie.

And is Makie able to export high quality graphics for publications?

1 Like

For the first point, you have to use Measures and keyword argument to plot() function: rightmargin=-20mm

For the second point, I thought this had been implemented in Plots.jl following a push from @lmiq, but it doesn’t seem to be the case here with pythonplot(). See this thread for several solutions.

And is Makie able to export high quality graphics for publications?

Certainly, CairoMakie can export pdf / svg and for bitmaps you can oversample resolution as much as you want (soon also in GLMakie).

I know you’ve had your frustrations with breaking changes in Makie. I’m not sure if it’s still accurate to say that we break stuff a couple times per year. You can check News · Makie and search for breaking there, you’ll see that the last ones were pretty mild, while of course technically breaking. Also, I think it’s perfectly fine to just keep your version pinned and only update when convenient, I’m just saying the time needed to update on a technically breaking version change can differ a lot. So maybe the recent ones wouldn’t have been as frustrating for you.

4 Likes

It should be, with an updated version of Plots you should get:

image

(ps: I didn’t test it with pythonplot(), I tested it with GR, I’m not sure if what we did at the Plots level is useful on every backend - tested now: It does not work with pythonplot() - opened an issue here)

3 Likes

I think the main thing Makie could use is just a more “idiot-proof” API for the most common / simplest use cases. It’s an incredibly powerful library which comes with a lot of essential complexity, so I still sometimes struggle to do something basic like “plot some scatterpoints then a linear regression on top”

I know this is what AlgebraOfGraphics.jl attempts, but that library still feels a little ideologically experimental & not yet mature.

6 Likes

Following https://github.com/JuliaPlots/Plots.jl/pull/4536, by @lmiq , it shouldn’t be too hard to reuse the automatic placement logic used in the GR backend for the PythonPlot (and other) backends.

EDIT: just saw [FR] optimal legend positions for `pythonplot` backend · Issue #4725 · JuliaPlots/Plots.jl · GitHub, tracking this specific issue.

1 Like

Why? Why have things to be so complicated? Why can Plots.jl not see that there is a whitespace that is not needed?

This is what I mean with the low quality of Julia plotting packages at the current point in time, compared with mature packages like matplotlib (PythonPlot).

Perhaps because the people with your know-how haven’t found the time or the interest to improve things?

3 Likes

PlotlyLight: it has got it all.

5 Likes