I have a set of 3D data (X,Y,Z) and an array of values (let's call it C). X,Y,Z and C have the same length.
My goal is to plot a surface by creating a 3D mesh with X,Y,Z points and to color each point (thus the surface) according to the value of C.
I managed to this using plotly library after asking for help here. It works perfectly fine in most cases. However it's not able to draw a closed surface (e.g. a sphere), but it only plots the lower half of it.
import plotly.graph_objects as go
import numpy as np
DATA = np.loadtxt(open("surface.dat", "rb"))
Xs = DATA[:,0]
Ys = DATA[:,1]
Zs = DATA[:,2]
value = np.loadtxt(open("0.dat", "rb"))
fig = go.Figure(data=[
go.Mesh3d(
x=Xs,
y=Ys,
z=Zs,
colorbar_title='value',
colorscale="hot",
# Intensity of each vertex, which will be interpolated and color-coded
intensity=value,
showscale=True
)
])
fig.show()
I understand that this happen because plotly's mesh3d can't take multiple values of Z for a X,Y couple, so I even try to plot 2 half-shapes, one for the bottom and one for the upper part, but this results in a hole in the middle of the 2 halves.
Here is the code and the result:
import plotly.graph_objects as go
import numpy as np
DATA = np.loadtxt(open("surface.dat", "rb"))
Xs = DATA[:,0]
Ys = DATA[:,1]
Zs = DATA[:,2]
value = np.loadtxt(open("0.dat", "rb"))
#find the permutation that put Z in ascending order
p = Zs.argsort()
#sort the arrays with that permutation and invert them ('pos' stands for 'positive')
Xpos = Xs[p][::-1]
Ypos = Ys[p][::-1]
Zpos = Zs[p][::-1]
Vpos = value[p][::-1]
top = go.Mesh3d(
x=Xpos,
y=Ypos,
z=Zpos,
colorbar_title='value',
colorscale="hot",
intensity=Vpos,
showscale=True
)
bottom = go.Mesh3d(
x=Xs,
y=Ys,
z=Zs,
colorbar_title='value',
colorscale="hot",
intensity=value,
showscale=True
)
fig = go.Figure(data=[top,bottom])
fig.show()
Is there a way to achieve what I need? Some solutions could be:
- filling the holes connecting the 2 halves somehow
- using a different library (e.g. matplotlib, Open3D)
- using a complete different method that I can't come up with
- drawing the sphere first and then color it. I don't favor this last solution because the shape should be somewhat arbitrary (not a function), but if no other solutions exist, I can get the coordinates of C and color the sphere with them.