Julia Surface or Non-Square Heatmap Plots with Spesific Function

Hi! I have some coordinates points (non-grid or non-square):

Capture

Each scatter points have x values:

74-element Vector{Any}:
13.0
2.0
59.5
55.0
22.0
57.5
21.0
28.0
100.5
35.0
64.0
34.5
23.0

85.5
83.0
66.0
27.5
93.0
61.0
69.5
76.0
69.0
16.5
110.0
106.0

and y values:

74-element Vector{Any}:
0.0
0.0
0.8660254037844386
1.7320508075688772
1.7320508075688772
2.598076211353316
3.4641016151377544
3.4641016151377544
4.330127018922193
5.196152422706632
5.196152422706632
6.06217782649107
6.928203230275509

0.8660254037844386
1.7320508075688772
1.7320508075688772
2.598076211353316
3.4641016151377544
3.4641016151377544
4.330127018922193
5.196152422706632
5.196152422706632
6.06217782649107
6.928203230275509
6.928203230275509

And also, I have specific returning values of the function (or depth) according to each of these scatter points. The returning values of the function:

192-element Vector{Float64}:
0.01026092990158084
0.009416080348692598
0.012298969043634662
0.013916606632920811
0.013167799244802145
0.014012477885523053
0.012621339395756463
0.010104323450266985
0.009989015887079901
0.0079859912194493
0.00572453020447633
0.006531826655798263
0.008111449480620387

0.00899896427675875
0.006889139181813508
0.007463671690395065
0.007420493510579368
0.008208763532334944
0.0071625911073200915
0.007557154510503339
0.00962856024830995
0.007751236255200042
0.007921710076830122
0.009087707129757795
0.009139276992711463

My function depends on x and y coordinates. For example;
MyFunction(x_co[6],y_co[6]) = 0.00899896427675875

So, I want to plot z values (or depth or returning values of the MyFunction()) on this 2D scatter plot via a non-square heatmap (due to the structure of scatter points) or surface.

When I try to plot as a surface, I encounter the error:
*** IDENTICAL DATA POINTS.
NDP = 74 IP1 = 28 IP2 = 44 XD=21 YD=6.9282
ERROR DETECTED IN ROUTINE IDTANG.

Hi! Can you provide us with a reproducible example?
As a first remark, your vectors for x and y coordinates have element type Any, which suggests you might have defined them using something like x = [] before pushing into them. It works, but your code will be more efficient if you specify the element type beforehand, like so: x = Float64[].

Let’s keep it simple. I have basic following code:

x = Int64[1,2,3,4,5]
y = Int64[1,2,3,4,5]
function Myfun(x,y)
    return x*y
end
surface(x,y,Myfun())

My coordinate list like this:

[0,0
0,1
0,2
0,3
.
.
.
5,5]

I want to plot density values (returning values of Myfun(x,y) in this case) in each coordinates points. I don’t have range to plot basic 3D surface plot like this:

f(x, y) = sin(x) + cos(y)
surface(0:0.1:10, 0:0.1:10, f)

Instead of, I have spesific x and y values to plot surface plot. How can I solve my problem?

Could you maybe extend the example to code that we can easily run?
See Please read: make it easier to help you.

In your smaller example here

  1. Which package are you using? Plots.jl?
  2. surface(x,y,Myfun()) does not work, since MyFun does not work for zero parameters as it is called here

But if you have a list of points, say

using Plots
x = [1,1,2,2,3,3]
y = [1,2,2,3,3,4]

and have computed

z = f.(x,y)

then

surface(x,y,z)

(from Plots.jl) works just as intended

But note that if you have a point twice, like in the following where I repeated the first

x = [1,1,1,2,2,3,3]
y = [1,1,2,2,3,3,4]
z = f.(x,y)

you get

julia> surface(x,y,z)
 ***   IDENTICAL DATA POINTS.
   NDP =    7   IP1 =    1   IP2 =    2   XD=1   YD=1
 ERROR DETECTED IN ROUTINE   IDTANG.

Since if a point appears double (in my example the first and the second are both [1,1]) the plot does not know what to do (here even_though_ the z value is the same.

As far as I see the result, IP1, IP2 tell you the inices (for me nodes 1 and 2, for you 28 and 44) and the x and y value that is repeated (for me again both are 1 for you the point (21,6.9282).
In scatter, I think, it will just plot the blue dot twice, but for the surface, you have to avoid duplicates.

I hope I guessed your code correct – and welcome to the Julia forum :slight_smile:

1 Like

Change the type of your data as @gdalle pointed out. Then this code should work (incidentally, last week I experimented with the new version of DelaunayTriangulation.jl):

using DelaunayTriangulation, PlotlyJS

function get_surface(x::T,y::T,z::T) where  T<:Real
    pts=[[xe, ye] for (xe, ye) in zip(x,y)]
     tri = triangulate(pts)
    #PlotlyJS mesh3d works with triangle ids starting from 0:
    mtriangles= mapreduce(permutedims, vcat, [[id for id in t]  for t in tri.triangles]) .-1

    surf = mesh3d(x=x, y=y, z=z, 
             i=mtriangles[:, 1], 
             j=mtriangles[:, 2], 
             k=mtriangles[:, 3],
             intensity=z,
             colorscale=colors.plasma,
             colorbar_thickness=24,
            )
    layout = Layout(width=500, height=500, 
                scene_camera_eye=attr(x=1.65, y=1.65, z=1))
    pl = Plot(surf, layout)
end

pl=get_surface(x,y,z)
display(pl)

All of my problems are that:

# Please, don't care what are the function arguments and their's values.
# Just focus x and y coordinates and the plot section.
Nx = 2;Ny = 2

# A any given function to get x coordinates. 
x_coordinates = get_sites(Nx, Ny, a1_vec, a2_vec, Basis)[4]

# Recreate the array to avoid the 'OffsetArray' function. It maybe prevents the plotting process (?)
x = Float64[]
for i in x_coordinates
    push!(x, i)
end
println("My x-values: \n", x)

# A any given function to get y coordinates.
y_coordinates = get_sites(Nx, Ny, a1_vec, a2_vec, Basis)[5]

# Recreate the array to avoid the 'OffsetArray' function. It maybe prevents the plotting process (?)
y = Float64[]
for i in y_coordinates
    push!(y, i)
end
println("\n My y-values: \n", y)

# !
my_coordinate_list = hcat(x, y) # there is no repeated (x,y) pairs !
println("\n My coordinate or (x,y) pairs: \n",my_coordinate_list)

# My Function
function MyFun(x,y)
    return x*y
end
# Get returning value for specific (x,y) pair
println("\n The output of my function: \n",MyFun(x[1],y[1]))

# Plot section
using Plots
surface(x, y, MyFun(x, y))

The outputs of my code:

My x-values: 
[0.0, 1.0, 0.5, 1.0, 2.0, 1.5, 2.0, 3.0, 2.5, 3.0, 4.0, 3.5]

 My y-values: 
[0.0, 0.0, 0.8660254037844386, 1.7320508075688772, 1.7320508075688772, 2.598076211353316, 0.0, 0.0, 0.8660254037844386, 1.7320508075688772, 1.7320508075688772, 2.598076211353316]

 My coordinate or (x,y) pairs: 
[0.0 0.0; 1.0 0.0; 0.5 0.8660254037844386; 1.0 1.7320508075688772; 2.0 1.7320508075688772; 1.5 2.598076211353316; 2.0 0.0; 3.0 0.0; 2.5 0.8660254037844386; 3.0 1.7320508075688772; 4.0 1.7320508075688772; 3.5 2.598076211353316]

 The output of my function: 
0.0

In this case, I want to plot the surface of z values according to each (x,y) pair.

I am sorry I can not run your code since the function get_sites is not defined (in your example if I run the code lines in the order you provide them). The same holds for a1_vec and a2_vec and Basis.

So I can again just take an educated guess…

If I use your print and define

x = [0.0, 1.0, 0.5, 1.0, 2.0, 1.5, 2.0, 3.0, 2.5, 3.0, 4.0, 3.5]
y = [0.0, 0.0, 0.8660254037844386, 1.7320508075688772, 1.7320508075688772, 2.598076211353316, 0.0, 0.0, 0.8660254037844386, 1.7320508075688772, 1.7320508075688772, 2.598076211353316]

Then I can also define

function MyFun(x,y)
    return x*y
end

But your call to MyFun(x, y) does not work since * is not defined for vectors. If I do instead

z = MyFun.(x,y)
using Plots
surface(x,y,z)

(Note the . in the first line since I want to apply MyFun to every pair of x and y!)
This works just fine.

2 Likes

Thank you so much ^^. My problem was the usage of surface(x,y,MyFun(x,y)) instead of surface(x,y,MyFun.(x,y)). So can I ask an additional question? How can I set the top view of the surface with the camera=(Int,Int) argument?

Capture3

You‘re welcome.

I am not sure about camera=, where do you have that from? Ah maybe from GR? It might be that the first is rotation in x,y, the second elevation angle? To me

surface(x,y,z; camera = (0,90))

seems right, but might again just be a guess, since I could find no docs.

1 Like