Interactivity of Makie plots

So I have read several places that Makie plots are interactive. I take that to mean that I can mouse over them to highlight points and their values, and that I can zoom and pan. This does however not work with plots created from the REPL and VSCode. MWE:

using GLMakie
xs = range(0, 2pi, length=1000)
ys = cos.(xs)
lines(xs, ys)

Am I doing something wrong, or is something else meant by interactivity?

If mousing over datapoints and zooming is not what is meant, is this going to be added to Makie in the future? It is vital to me - I use Plotlyjs normally, and it’s interactivity is just amazing and extremely useful.

1 Like

Try using WGLMakie instead of GLMakie:

makie_vscode_demo

While you can zoom in, there is no “mousing over datapoints” as in Plotly though AFAIK.

6 Likes

Are you not getting a window when you display your plot? It should be zoomable and pannable

Like this:

7 Likes
julia> versioninfo()
Julia Version 1.5.3
Commit 788b2c77c1 (2020-11-09 13:37 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
  JULIA_PKG_SERVER =

(@v1.5) pkg> status WGLMakie
Status `C:\Users\densb\.julia\environments\v1.5\Project.toml`
  [276b4fcb] WGLMakie v0.2.12

When trying to use WGLMakie, one of two things happen. I can get the following output in the REPL:

julia> WGLMakie.plot([(x, x^2) for x in 0:0.01:2])
Scene (600px, 400px):
  14 Plots:
    ├ Combined{AbstractPlotting.poly,Tuple{Array{Array{Point{2,Float32},1},1}}}
    ├ Combined{AbstractPlotting.linesegments,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.linesegments,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.linesegments,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.annotations,Tuple{Array{Tuple{String,Point{2,Float32}},1}}}
    ├ Combined{AbstractPlotting.text,Tuple{String}}
    ├ Combined{AbstractPlotting.lines,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.linesegments,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.annotations,Tuple{Array{Tuple{String,Point{2,Float32}},1}}}
    ├ Combined{AbstractPlotting.text,Tuple{String}}
    ├ Combined{AbstractPlotting.lines,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.lines,Tuple{Array{Point{2,Float32},1}}}
    ├ Combined{AbstractPlotting.lines,Tuple{Array{Point{2,Float32},1}}}
    â”” Combined{AbstractPlotting.text,Tuple{String}}
  1 Child Scene:
    â”” Scene (513px, 302px)

OR, I get the following output in VSCode

Display Error: ERROR: type Nothing has no field js_fully_loaded
getproperty(::Nothing, ::Symbol) at 
.\Base.jl:33
(::WGLMakie.var"#132#134")() at C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\display.jl:40
timedwait(::WGLMakie.var"#132#134", 
::Float64; pollint::Float64) at .\asyncevent.jl:287
timedwait at .\asyncevent.jl:267 [inlined]
scene2image(::Scene) at C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\display.jl:40
backend_show at C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\display.jl:49 [inlined]
show(::Base64.Base64EncodePipe, ::MIME{Symbol("image/png")}, ::Scene) at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\display.jl:117
show at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\figures.jl:95 [inlined]
show(::Base64.Base64EncodePipe, ::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot) at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\figureplotting.jl:14   
base64encode(::Function, ::MIME{Symbol("image/png")}, ::Vararg{Any,N} where N; context::Nothing) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\encode.jl:206
_binstringmime at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:46 [inlined]
stringmime(::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot; context::Nothing) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:43
stringmime at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:43 [inlined]
display(::VSCodeServer.InlineDisplay, ::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\display.jl:25
display(::VSCodeServer.InlineDisplay, ::String, ::Any) at .\multimedia.jl:216
display(::VSCodeServer.InlineDisplay, ::AbstractPlotting.FigureAxisPlot) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\display.jl:87
#invokelatest#1 at .\essentials.jl:710 [inlined]
invokelatest at .\essentials.jl:709 
[inlined]
(::VSCodeServer.var"#61#65"{String,Int64,Int64,String,Module,Bool,VSCodeServer.ReplRunCodeRequestParams})() 
at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:164
withpath(::VSCodeServer.var"#61#65"{String,Int64,Int64,String,Module,Bool,VSCodeServer.ReplRunCodeRequestParams}, ::String) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\repl.jl:124
(::VSCodeServer.var"#60#64"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:142
hideprompt(::VSCodeServer.var"#60#64"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams}) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\repl.jl:36
(::VSCodeServer.var"#59#63"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:110
with_logstate(::Function, ::Any) at 
.\logging.jl:408
with_logger at .\logging.jl:514 [inlined]
(::VSCodeServer.var"#58#62"{VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:109
#invokelatest#1 at .\essentials.jl:710 [inlined]
invokelatest(::Any) at .\essentials.jl:709
macro expansion at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:27 [inlined]     
(::VSCodeServer.var"#56#57")() at .\task.jl:356
Stacktrace:
 [1] timedwait(::WGLMakie.var"#132#134", ::Float64; pollint::Float64) at .\asyncevent.jl:289
 [2] timedwait at .\asyncevent.jl:267 [inlined]
 [3] scene2image(::Scene) at C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\display.jl:40
 [4] backend_show at C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\display.jl:49 [inlined]
 [5] show(::Base64.Base64EncodePipe, ::MIME{Symbol("image/png")}, ::Scene) at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\display.jl:117
 [6] show at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\figures.jl:95 [inlined]
 [7] show(::Base64.Base64EncodePipe, ::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot) at C:\Users\densb\.julia\packages\AbstractPlotting\3t1M8\src\figureplotting.jl:14
 [8] base64encode(::Function, ::MIME{Symbol("image/png")}, ::Vararg{Any,N} where N; context::Nothing) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\encode.jl:206
 [9] _binstringmime at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:46 [inlined]
 [10] stringmime(::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot; context::Nothing) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:43
 [11] stringmime at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Base64\src\Base64.jl:43 [inlined]
 [12] display(::VSCodeServer.InlineDisplay, ::MIME{Symbol("image/png")}, ::AbstractPlotting.FigureAxisPlot) 
at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\display.jl:25
 [13] display(::VSCodeServer.InlineDisplay, ::String, ::Any) at .\multimedia.jl:216
 [14] display(::VSCodeServer.InlineDisplay, ::AbstractPlotting.FigureAxisPlot) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\display.jl:87
 [15] #invokelatest#1 at .\essentials.jl:710 [inlined]
 [16] invokelatest at .\essentials.jl:709 [inlined]
 [17] (::VSCodeServer.var"#61#65"{String,Int64,Int64,String,Module,Bool,VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:164
 [18] withpath(::VSCodeServer.var"#61#65"{String,Int64,Int64,String,Module,Bool,VSCodeServer.ReplRunCodeRequestParams}, ::String) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\repl.jl:124        
 [19] (::VSCodeServer.var"#60#64"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:142
 [20] hideprompt(::VSCodeServer.var"#60#64"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams}) at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\repl.jl:36
 [21] (::VSCodeServer.var"#59#63"{String,Int64,Int64,String,Module,Bool,Bool,VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:110
 [22] with_logstate(::Function, ::Any) at .\logging.jl:408
 [23] with_logger at .\logging.jl:514 [inlined]
 [24] (::VSCodeServer.var"#58#62"{VSCodeServer.ReplRunCodeRequestParams})() at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:109
 [25] #invokelatest#1 at .\essentials.jl:710 [inlined]
 [26] invokelatest(::Any) at .\essentials.jl:709
 [27] macro expansion at c:\Users\densb\.vscode\extensions\julialang.language-julia-1.0.10\scripts\packages\VSCodeServer\src\eval.jl:27 [inlined]
 [28] (::VSCodeServer.var"#56#57")() at .\task.jl:356


julia> An exception was thrown in JS: ReferenceError: get_observable is 
not defined
Additional message: Error during running onjs callback
Callback:
function setup(scenes){
    const canvas = __eval_context__[0]
    if ( WEBGL.isWebGLAvailable() ) 
{
        const renderer = WGLMakie.threejs_module(canvas, '4403351519407190137', 600, 400)
        const three_scenes = scenes.map(WGLMakie.deserialize_scene)     

        on_update('4876615431255205141', open=>{
            WGLMakie.delete_scene(14096429437790364682)
        })

        const cam = new THREE.PerspectiveCamera(45, 1, 0, 100)
        WGLMakie.start_renderloop(renderer, three_scenes, cam)
        on_update('10189461588449820543', canvas_width => {
            const w_h = deserialize_js(canvas_width);
            renderer.setSize(w_h[0], w_h[1]);
            canvas.style.width = w_h[0];
            canvas.style.height = w_h[1];
        })
    } else {
        const warning = WEBGL.getWebGLErrorMessage();
        canvas.appendChild(warning);    }
}
Stack trace:
    ReferenceError: get_observable is not defined
        at deserialize_scene (C:\Users\densb\.julia\packages\WGLMakie\x0zje\src\wglmakie.js:439)
        at Array.map (<anonymous>)  
        at Array.setup (eval at deserialize_js (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:167), <anonymous>:7:37)    
        at run_js_callbacks (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:257)      
        at process_message (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:363)       
        at Array.forEach (<anonymous>)
        at process_message (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:381)       
        at process_message (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:354)       
        at WebSocket.websocket.onmessage (C:\Users\densb\.julia\packages\JSServe\PClmK\js_dependencies\core.js:444)

So trying in VSCode and the REPL both two days in a row (Meaning that my computer has been restarted), does not give a plot but an error or something that looks like it should be passed to an HTML-reader.

That right there looks pretty neat. I am plotting in the plotting pane of VSCode, in which case there is no popout window, and the plotting pane can not be zoomed in on. But in the REPL, I get a window like this:
image

aaaand I just realized that I can zoom in it by click and drag (I though I tried that when writing this post. But in any case, it works now). I have to select the window by clicking on it to get the selection box that indicates the possibility. Two current problems:

  1. I don’t see how I am able to zoom out
  2. VSCode plotting-pane plots are not zoomable
  3. I am still missing the possibility to mouse over points to see their value. A lot

Other than that, this is pretty great. Thanks <3

I can zoom in/out but the axis do not update (In juno) so if you zoom in too much, you dont know where you are.

Are you not getting a window when you display your plot? It should be zoomable and pannable

I could not find the code for this example.

Dear Jules,
A great thanks for sharing thiis amazing demo which is great tool for teaching.
Would you know were I can get some example code of GUIs with MakieLayout which will get me started?
Thanks for any help you may provide :smiley:.

There are examples of gui elements here Overview | Makie

1 Like

Two more questions:

How can you zoom out once you have zoomed in?

Is there a way to obtain the mouse position? Or better yet the nearest point on the line to the mouse position? Or best, be able to put a datatip on the plot to the nearest mouse position, much like Matlab does?

Thanks

How can you zoom out once you have zoomed in?

Mouse wheel in the opposite direction should zoom out.
To autoscale, Ctrl + Right Click.
Note: that works only if the plot has focus, so sometimes one has to click twice
(once to get focus, then another time to autoscale).

Or better yet the nearest point on the line to the mouse position? Or best, be able to put a datatip on the plot to the nearest mouse position, much like Matlab does?

You might be looking for DataInspector ?

My Makie gets stuck in VSCode plot panes sometimes, and it loses all of its interactivity then. I’m often able to pop it out by running: GLMakie.activate!() which switches backends. Upon replotting it opens a seperate interactive window.