Plots.contourf and PlotlyJS.contour behaviour with regard to the x,y,z input

I have been using PlotlyJS.contour() in a program to plot data, but I need to switch to Plot.contourf().

I use PlotlyJS.contour(x=x,y=y,z=z) such that x::Vector and y::Vector contain the x and y coordinates of the points I want to plot, and z::Vector contains the value to be displayed in color. Note that in my case, x, y and z are 1-dimensional vectors and have the same length N. They are not sorted. To put it in other words, x[k] and y[k] are the plane coordinates of the z[k] value (with k contained in the range between 1 and N). It means that I want to plot z[k] at location (x[k], y[k]) and it is possible that some coordinate combinations of x[i] and x[j] have no corresponding color value (z-value) (i and j in range between 1 and N)

Here lies my problem: the Plot.contourf() does not have the same behavior. It needs x and y to be sorted and takes z::Matrix of size (length(x),length(y)) for the color value.

In the following example, N is 4.

using PlotlyJS
using Plots

#PlotlyJS
x = [1,2,3,1];
y = [1,1,2,2];
z = [1,2,3,4];

#heatmap to assess the fact that some location have no color value (z-axis)
p = PlotlyJS.plot(PlotlyJS.heatmap(x=x,y=y,z=z))
#desired contour plot
p = PlotlyJS.plot(PlotlyJS.contour(x=x,y=y,z=z))

# ---
#Plots
p = Plots.contourf(x,y,z) # ERROR: Arrays have incorrect length or dimension.

I tried to reformat my input data, but it is not possible as some plane locations are intentionally left unfilled.

Heatmap using PlotlyJS:

Contour using PlotlyJS:

With ScatteredInterpolation.jl we can get from the three vectors, x, y, z, a matrix zg, consisting in interpolated values at the points of a meshgrid associated to linear grids, xg and yg.
As long as we don’t know what interpolation method is used by
plotly.js, we cannot obtain exactly the same contours. Among different methods of interpolation from ScatteredInterpolation.jl, the radial basis function method with Multiquadratic basis function defines a Plots.contourf somehow similar to PlotlyJS.contour.

using ScatteredInterpolation, Plots, ColorSchemes
let 
    x = [1, 2, 3, 1]
    y = [1, 1, 2, 2]
    z = [1.0, 2, 3, 4]
    points = stack(zip(x,y)) 
    itp = interpolate(Multiquadratic(), points, z);

    xm, xM = extrema(x)
    ym, yM = extrema(y)
    n = 50
    m = 25
    xg = range(xm, xM, n)
    yg = range(ym, yM, m)
    X = [s for t in yg, s in xg] #size(X) is (m,n)
    Y = [t for t in yg, s in xg] # size(Y) is also (m,n)
    gridP = stack(vec([[x, y] for (x,y) in zip(X, Y)])) #2 x m*n - matrix; each column is a grid point
    interpolated = evaluate(itp, gridP)
    zg = reshape(interpolated,  m, n)
    p = Plots.contourf(xg, yg, zg; levels=6, c=cgrad(ColorSchemes.plasma))
end    

1 Like