PlotlyJS.jl icon indicating copy to clipboard operation
PlotlyJS.jl copied to clipboard

Quiver plots

Open truefalsename opened this issue 7 years ago • 14 comments
trafficstars

Hello,

is there any way to produce 2d quiver plots with PlotlyJS? For instance something like this: https://plot.ly/python/quiver-plots/

Thanks!

truefalsename avatar Sep 26 '18 12:09 truefalsename

We don't have a built in way to do this, but would be open to accepting a contribution.

If you are comfortable reading Python code, you can find (here) the function used to create quivers in the example you linked to

If you are interested in working on it, but would like some more guidance just let us know

sglyon avatar Sep 26 '18 13:09 sglyon

I can read Python but cannot promise anything as I have no time at the moment. If at some point I end up with a decent Julia translation for quiver I'll let you know!

truefalsename avatar Sep 28 '18 06:09 truefalsename

Btw, I think I have found a workaround using annotations in layout, if you are interested I can show you.

truefalsename avatar Oct 04 '18 08:10 truefalsename

Great! I think leaving a note here would be helpful for anyone else that comes looking for this functionality.

sglyon avatar Oct 04 '18 11:10 sglyon

Ok, so I am using something like this

function quiver_test(x::Array, y::Array, u::Array, v::Array; scale = 1.0, show_origins = true)
"""
Fuction to plot vector fields in two dimensions",

Inputs:
      - x,y:: origin of each arrow
      - u,v:: components of each arrow. The arrow endpoint is at (x + scale*u, y + scale * v) 

Kwargs:
      - scale:: magnification factor for the arrow lengths


Example:

x = [0., 1., 2.]
y = [1., 2., 3.]
u = [10., 20., 30]
v = [0., 10., 50]

quiver_test(x, y, u, v; scale = 0.1, show_origins=false)

"""   

vels = [attr(
        x = x[i] + scale * u[i], y = y[i] + scale * v[i],
        showarrow = true, 
        axref = "x",
        ayref = "y",
        ax =  x[i],
        ay = y[i])
for i in 1:length(x)]

layout = Layout(; 
            autosize = false, width = 800, height = 800, 
            margin = attr(l = 50, r = 50, b = 50, t = 65),
            showlegend = false,
            annotations = vels
            )

if show_origins
    t0 = scatter(; x = x, y = y, mode = "markers",
                 marker = attr(color = "#000000", size = 8, symbol = "o", opacity = 1))
    plot(t0, layout)
else
    t0 = scatter(; x = 0, y = 0, mode = "markers",
                 marker = attr(color = "#000000", size = 1, symbol = "o", opacity = 1))
    plot(t0, layout)
end
end

truefalsename avatar Oct 04 '18 13:10 truefalsename

I also had some quiver code lying around. Here is a copy. It's done slightly differently from the example above. The arrows are explicitly drawn.

"""
    quiver(x, u; scale = 1.0)

Returns a trace, to be plotted using PlotlyJS, corresponding to a quiver plot.

Inputs:

      - x::Matrix{Float64}: matrix of size 2 x n, origin of each arrow
      - u::Matrix{Float64}: matrix of size 2 x n, components of each arrow. The arrow endpoint is at (x + scale*u, y + scale*v)

We assume that the (x,y) coordinates are given in each column of x and u. The number of
columns is the number of points to plot.

Kwargs:

      - scale::Float64 magnification factor for the arrow lengths

Example:

    using LinearAlgebra # This is needed by quiver 
    using PlotlyJS      # Plotting is done using PlotlyJS
    x = [0. 1. 2.; 
         1. 2. 3.]
    u = [10. 20. 30; 
          0. 10. 50.]
    plot([quiver(x, u, scale = .1)], Layout(yaxis_scaleanchor="x"))
    # Layout(...) is important to make sure that x and y axis have the same scale
"""
function quiver(x::Matrix{Float64},u::Matrix{Float64}; scale::Float64 = 1.0)
    n = size(x,2)
    s = 8
    X = Matrix{Float64}(undef,2,s*n)
    for i=1:n
        k = s*(i-1)
        
        r = x[:,i]
        V = scale * u[:,i]
        
        dist = norm(V)
        arrow_h = 0.1dist     # height of arrowhead
        arrow_w = 0.5arrow_h  # halfwidth of arrowhead
        U1 = V ./ dist        # vector of arrowhead height
        U2 = [-U1[2], U1[1]]  # vector of arrowhead halfwidth
        U1 *= arrow_h
        U2 *= arrow_w
        
        X[:,k+1] = r        
        r += V
        X[:,k+2:k+s] = [r-U1 [NaN, NaN] r r-U1+U2 r-U1-U2 r [NaN, NaN]]
    end
    trace = scatter(fill="toself")
    trace[:x] = X[1,:]; trace[:y] = X[2,:]
    return trace
end
screen shot 2018-10-08 at 10 45 13 am

ghuba avatar Oct 08 '18 17:10 ghuba

Thanks @ghuba

sglyon avatar Oct 08 '18 21:10 sglyon

+1 would love to see quiver plots in plotlyjs

alexlenail avatar May 13 '21 19:05 alexlenail

+1 would love to see quiver plots in plotlyjs

Boomer91 avatar Nov 24 '21 18:11 Boomer91

@alexlenail, @Boomer91 I have an experimental version of quiver plot with PlotlyJS.jl here: https://nbviewer.org/gist/empet/e93943ab1c34501df3812fe35a25429a

empet avatar Nov 25 '21 12:11 empet

@alexlenail, @Boomer91 I have an experimental version of quiver plot with PlotlyJS.jl here: https://gist.github.com/empet/bcf0d27abf80f6da7dfd9e6136e29771 This is the fig1 in the above notebook: arrow_angpi18 fig2: a single arrow with smaller angle, i.e. a more sharp arrow: arrow_angpi24

and a 2D- vector field represented by a quiver plot: quiver-example2

Just a typo: π should be replaced by pi

arghavanpartovifard avatar Nov 25 '21 14:11 arghavanpartovifard

The error is caused by pi displayed as an odd char. Replace it by its name pi or by \pi followed by tab in:

  1. function quiver(x::AbstractArray, y::AbstractArray, u::AbstractArray, v::AbstractArray; scale=0.1, arrow_scale=0.3, angle=Ï€/9, scaleratio=1.0, d=1, color="RoyalBlue") #here is pi/9

  2. fig1 = quiver([0],[0], [1], [1], scale=1, angle=Ï€/18, d=0.95) #pi/18

and so on. In each call of quiver function, angle=pi/n for some n.

empet avatar Nov 25 '21 15:11 empet

@alexlenail, @Boomer91 I have an experimental version of quiver plot with PlotlyJS.jl here: https://gist.github.com/empet/bcf0d27abf80f6da7dfd9e6136e29771

Hello, I just started using PlotlyJS.jl recently and I really enjoy it! By curiosity, is this experimental quiver function going to be made available in a coming update? I have tried to access the link but it seems broken. I would be indeed great to have a quiver plotting function. Cheers

tduretz avatar Apr 14 '23 14:04 tduretz

@tduretz

Hello, ...is this experimental quiver function going to be made available in a coming update? I would be indeed great to have a quiver plotting function. Cheers

No, quiver plot will not be available in a near future. Unfortunately this repo is unmaintained. There are a lot of new attributes of some traces, as well as new trace types, introduced in the last plotly.js versions, which cannot be used by PlotlyJS community.

I updated the link, posted above, to the gist illustrating how to generate a quiver plot.

empet avatar Apr 14 '23 19:04 empet