Home > Blockchain >  Save 3D Matplot as interactive HTML
Save 3D Matplot as interactive HTML

Time:08-14

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