Matlab figure replacement

In Matlab it is possible to make a figure and save it to disk. If you re-open this figure you can still zoome, have linked axis and so on.
Is there a Julia equivalent?

I tried PlotlyJS.jl and saving the plot as a html but the data is stored in the html as text, which is very inefficient.

3 Likes

With PyPlot, you could use Python pickle module (via PyCall) to save the axes and restore them.

A related solution for this using Plots.jl is provided here, and it uses the hdf5() backend. In the same thread there is also a solution using VegaLite.jl.

WGLMakie can export to HTML: Home · WGLMakie.jl

Yes but it is static.

With PlotlyJS.jl you can save the plot as JSON:


julia> x=0:Ď€/56:Ď€/2
0.0:0.05609986881410345:1.5707963267948966

julia> p=PlotlyJS.plot(x, sin.(x))

julia> open("saved_sinplot.json", "w") do io
           write(io, json(p))
       end
8037

To reload the plot

julia> open("saved_sinplot.json") do io
           global p2=JSON.parse(PlotlyJS.Plot, read(io, String))
       end

Now you can edit the plot, e.g. add a title:

julia> p2.layout[:title]="sin(x)"
"sin(x)"
1 Like

serialize (from the stdlib module Serializer) seems to works out-of-the-box with Plots, and probably for many other plotting modules.

1 Like

I like the serialization approach. However it seems very risky to do so.

import Serialization
using GLMakie

f1 = let 
    f = Figure()
    ax1 = Axis(f[1,1])
    lines!(cumsum(randn(100)))
    ax2 = Axis(f[2,1])
    lines!(cumsum(randn(100)))
    linkxaxes!(ax1, ax2)
    f
end

open("figure.makie", "w") do io
    Serialization.serialize(io, f1)
end

# can be loaded later
f2 = open("figure.makie", "r") do io
    Serialization.deserialize(io)
end

Risky, in which sense?

I made and use an SQLite database for storing my PlotlyJS plots as compressed JSON. It is in alternative to having the plots scattered all over the home directory, where they are difficult to find after a while. With modifications this should also work with serialized Makieplots, MATLAB figures, etc.

By risky I mean that it could happen that the serialized version is pure garbage and can not be re-opend.
The Julia documentation states:

In general, this process will not work if the reading and writing are done by different versions of Julia, or an instance of Julia with a different system image.

I guess this is not such a big problem with the JSON and the HTML/JS route.

I see, yes, this seems scary. With PlotlyJS and JSON I so far did not have problems across different versions over time ~2 years.

2 Likes

I don’t have much experience, but here @kristoffer.carlsson claims that

In my opinion, Serialization has proven to be significantly more stable between Julia versions than many other packages that claim to be so.

YMMV.

Also, note that you can make your code shorter/simpler with serialize("figure.makie", f1) and f2 = deserialize("figure.makie").

1 Like

Sorry in advance for this stupid question but I wonder about the advantage of this approach over re-running the plotting scripts ?

2 Likes

One advantage might be to pass it on to a third party who doesn’t know much about complex scripts but is good at artwork to edit figures for later distribution?

4 Likes

Well, in my experience it’s very rare that a definitive, publication-ready, plot will pop out of a script. There is a lot of fine-tuning work (position of legend, color and thickness, global aspect ratio…) that could be done just after seeing the actual plot. It’s just that you can’t take all those visual optimizations away from a case-by-case fashion.

Once you don’t have an abstract script that you could just run after loading generic data, you don’t want, for a specific data set, to repeat yourself doing all those customizations, nor you want to export already to a more or less immutable form (pdf, svg) in case you need to make some final cosmetics, or last minute change (let’s say a referee asks for something…).

That’s in my opinion the typical use case where you want to save not only the data, but also all the custom graphical setup for the plot. Matlab .fig files allow for an easy and efficient way to do that, embeddeding everything in hdf5 format, so that the figure does not take much more space than the raw data themselves :slight_smile:

Ok I get it.
So it only make sense if the plotting tool allows for GUI based fine tuning. It is not the case for PyPlot (and not really for Makie). Is it possible to tune PlotlyJS.jl plots with a GUI ?

1 Like

When PlotlyJS.jl plots are displayed in the Electron browser, via Blink.jl, some simple tuning is possible using the mouse. More advanced plot editing can be done with functions as described in the docs. This includes “classical” reviewer/supervisor requests like the font is too small, the line to thin/thick, colors not enough distinct, even “could you add another curve showing also these data” is possible. After some practice I don’t really miss a GUI when editing Plotly plots.

3 Likes

A Makie figure has tons of state that would be really hard to serialize and deserialize correctly. We could think about making a subset of functionality serializable, that would mostly be the basic structure of Axes and plots, but not interactions that have been hooked in and other Observables related stuff. Right now I think the “rerun script” option is much simpler, if not as convenient.

2 Likes

IMO, more declarative approaches than Makie (say AlgebraOfGraphics or Gadfly) probably have a better chance of managing to save everything that is needed for a figure, but I imagine it would still be somewhat complex…

A reasonable approach could be to use something like https://github.com/invenia/JLSO.jl, which uses serialization, but also stores all versions of packages needed to load the data, so it should be safer for long term storage.

1 Like

Yes, I’d say that if you do all the fine tuning through written commands, you can just save a plot-specific script along with the main basic/generic script, and then everytime you need to reproduce the picture just run both.

But think about 3D surface plots, and viewpoint (angles). You can surely modify that by commands/functions, with whatever tool. But it will be a frustrating matter of trial and error, until you get an acceptable pair of angles. With an interactive GUI you just move your mouse until you get the perfect view and that’s it. Surely you can retrieve from the plot the angles and then update the script, but I see just ad more comfortable to just save the whole editable figure.