# Julia Surface or Non-Square Heatmap Plots with Spesific Function

Hi! I have some coordinates points (non-grid or non-square): 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,y_co) = 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?

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 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)

# 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)

# 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,y))

# 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? 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