I´m trying to save my 3D trisurface Plot as an interactive HTML figure, so it should be possible to zoom in/ out and change the viewpoint. In the IDE the plot already exists and works so far, but I can`t save it in the HTML format because of the ValueError: "The fig parameter must be a dict or Figure. Received value of type <class 'matplotlib.figure.Figure'>: Figure(1600x900)". I don´t understand why the "<class 'matplotlib.figure.Figure'>" is not a Figure?
This was my approach: https://plotly.com/python/interactive-html-export/ And I tried it with go.Figure() (Export rotable 3D plots from Python to HTML) already but it didn´t work with the trisurf.
Is there a way to keep my Plot settings (use trisurf as it is) and get the interactive figure in HTML?
Thanks a lot for any answer
#Import libraries
import matplotlib
#matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pandas as pd
import plotly.express as px
import io
import plotly.io as pio
%matplotlib notebook
E = np.arange(225)
D = np.arange(225)
A = np.arange(225)
E = [10000.0, 10000.0, ...]
D = [500.0, 1000.0, ...]
A = [1.9495, 1.9644, ...]
#Create figure
fig = plt.figure(figsize =(16, 9))
ax = plt.axes(projection ='3d')
# Creating color map
my_cmap = plt.get_cmap('hot')
# Data for three-dimensional scattered points
zdata = A
xdata = D
ydata = E
# Creating plot
trisurf = ax.plot_trisurf(xdata, ydata, zdata,
cmap = my_cmap,
linewidth = 0.2,
antialiased = True,
edgecolor = 'grey')
fig.colorbar(trisurf, ax = ax, shrink = 0.5, aspect = 10)
ax.set_title('AIE_SIM0.003__lowE_10000_upE_460000_stepE_30000_lowD_500.0_upD_8000.0_stepD_500.0')
ax.set_xlabel('Damping Ns/m')
ax.set_ylabel('Stifness N/m')
ax.set_zlabel('Amplification')
A2 = np.arange(225)
A2.fill(20.757)
# Creating color map
my_cmap2 = plt.get_cmap('gray')
# Data for three-dimensional scattered points
zdata2 = A2
xdata = D
ydata = E
# Creating plot
trisurf2 = ax.plot_trisurf(xdata, ydata, zdata2,
cmap = my_cmap2,
linewidth = 0.2,
antialiased = False,
edgecolor = 'none', alpha = 0.2)
fig.colorbar(trisurf2, ax = ax, shrink = 0.5, aspect = 10)
print(type(fig))
#fig.write_html("file.html")
plotly.io.to_html(fig=fig)
fig.savefig('3D_Plot_PNG_lowE_10000_upE_460000_stepE_30000_lowD_500.0_upD_8000.0_stepD_500.0.png')
fig.show()
------------------------------------------------------------------------------------------
Figure 1
printed: <class 'matplotlib.figure.Figure'>
ValueError:
The fig parameter must be a dict or Figure.
Received value of type <class 'matplotlib.figure.Figure'>: Figure(1600x900)
CodePudding user response:
As far as I'm aware, Matplotlib is not able to generate 3D html plot.
Moreover, what you tried above is wrong. That error message is telling you that Plotly's to_html
only works with Plotly's Figure
. So mixing Plotly and Matplotlib is not going to work. You need to create a Plotly figure.
Also, I don't think that Plotly exposes something similar to Matplotlib's plot_trisurf
. However, it exposes go.Mesh
that allows us to achieve the same result.
The recipe:
- Generate your numerical data.
- Create a triangulation. We will use Matplotlib's
Triangulation
class for this part. - Create the Plotly figure and add the surface.
- Export the figure to html.
Here I'm going to post an example to guide you:
import numpy as np
import matplotlib.tri as mtri
import plotly.graph_objects as go
### DATA GENERATION
# Make parameter spaces radii and angles.
n_angles = 36
n_radii = 8
min_radius = 0.25
radii = np.linspace(min_radius, 0.95, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
angles[:, 1::2] = np.pi/n_angles
# Map radius, angle pairs to x, y, z points.
x = (radii*np.cos(angles)).flatten()
y = (radii*np.sin(angles)).flatten()
z = (np.cos(radii)*np.cos(3*angles)).flatten()
### TRIANGULATION
# Create the Triangulation; no triangles so Delaunay triangulation created.
triang = mtri.Triangulation(x, y)
# Mask off unwanted triangles.
xmid = x[triang.triangles].mean(axis=1)
ymid = y[triang.triangles].mean(axis=1)
mask = xmid**2 ymid**2 < min_radius**2
triangles = triang.triangles[~mask]
### PLOT
fig = go.Figure(data=[
# go.Mesh allows to provide the triangulation
go.Mesh3d(
x=x, y=y, z=z,
colorbar_title='z',
colorscale="aggrnyl",
# Intensity of each vertex, which will be interpolated and color-coded
intensity =z,
# i, j and k give the vertices of triangles
i = triangles[:, 0],
j = triangles[:, 1],
k = triangles[:, 2],
showscale=True
)
])
fig.show()
### EXPORT TO HTML
# Please, execute `help(fig.write_html)` to learn about all the
# available keyword arguments to control the output
fig.write_html("test.html", include_plotlyjs=True, full_html=True)