![]() |
3-d surface plotting - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: 3-d surface plotting (/thread-42247.html) Pages:
1
2
|
3-d surface plotting - Tuxedo - Jun-03-2024 Looking for a Python package for publication quality 3d surface plots. The surfaces I deal with have just a single peak but can have odd shapes near the base (e.g. banana shaped or triangular-ish shaped). I want to be able to "slice" the surface at a particular z value and highlight the resulting contour in some way. I'd also like to cut the base at a particular z value and discard everything below that value. I've fiddled with matplotlib quite a bit and can't really get the result I want. I'd also like to be able to easily rotate the plot to determine the best viewing angle. It appears plotly might have some promise, but most of the videos I find show everything but surface plots. Is there some clear winner for surface plotting? I'd even consider a ray tracing package (probably not Python based) but am wary about the learning curve. RE: 3-d surface plotting - sawtooth500 - Jun-04-2024 Here is some sample code with plotly, it may not do exactly what you are looking for but perhaps it can give you a starting point: import numpy as np import plotly.graph_objects as go # Generate example data x = np.linspace(-10, 10, 100) y = np.linspace(-10, 10, 100) x, y = np.meshgrid(x, y) z = np.sin(np.sqrt(x**2 + y**2)) # Specify the z-value for slicing and cutting the base slice_z_value = 0.5 cut_base_z_value = -0.5 # Create a mask to discard values below the cut_base_z_value z[z < cut_base_z_value] = np.nan # Create the 3D surface plot fig = go.Figure(data=[go.Surface(z=z, x=x, y=y)]) # Add contour at the slice_z_value fig.add_trace(go.Surface( z=np.ones_like(z) * slice_z_value, x=x, y=y, showscale=False, opacity=0.5, surfacecolor=np.where(z >= slice_z_value, z, np.nan), contours={"z": {"show": True, "start": slice_z_value, "end": slice_z_value, "size": 0.1}} )) # Update layout for better visualization fig.update_layout(scene=dict( zaxis=dict(range=[cut_base_z_value, np.nanmax(z)]) )) # Show plot fig.show() RE: 3-d surface plotting - Tuxedo - Jun-21-2024 Thanks so much! I use spyder, so didn't get any plot. Using: https://community.plotly.com/t/plotly-in-spyder/5414/3 I was able to get an interactive plot in my web browser by using from plotly.offline import plot plot(fig) Next, I tried to save a static imaging based on: https://plotly.com/python/static-image-export/ by installing kaleido: conda install -c conda-forge python-kaleido and writing the image with fig.write_image('fig1.png') For some reason, the program just hangs/stops and doesn't write the image file. I get no error messages, but the program doesn't complete. Nothing. What am I doing wrong? RE: 3-d surface plotting - paul18fr - Jun-22-2024 I'm also a Spyder user. Here after my code works perfectly. The figure is plotted on Spyder and saved. # -*- coding: utf-8 -*- import matplotlib.pyplot as plt from matplotlib.ticker import LinearLocator, FormatStrFormatter import numpy as np import os Path = os.getcwd() fig = plt.figure(figsize=(18, 18)) ax = fig.add_subplot(projection='3d') ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') # Make data. x = np.linspace(-10, 10, 100) y = np.linspace(-10, 10, 100) x, y = np.meshgrid(x, y) z = np.sin(np.sqrt(x**2 + y**2)) # Plot the surface. surf = ax.plot_wireframe(x, y, z, color='black') surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, linewidth=1, antialiased=True, edgecolor='black') # Customize the z axis. ax.set_zlim(-1.01, 1.01) ax.zaxis.set_major_locator(LinearLocator(10)) ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) plt.show() fig.savefig(Path + '/fig.png', dpi=300)[attachment=2920] RE: 3-d surface plotting - paul18fr - Jun-22-2024 On my previous post, I forgot to add "elevation" and "azimut" features import matplotlib.pyplot as plt from matplotlib.ticker import LinearLocator, FormatStrFormatter import numpy as np import os elevation = 45; # vertical azimut = 30.; # theta Path = os.getcwd() fig = plt.figure(figsize=(18, 18)) ax = fig.add_subplot(projection='3d') ax.view_init(elevation, azimut) ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') # Make data. x = np.linspace(-10, 10, 100) y = np.linspace(-10, 10, 100) x, y = np.meshgrid(x, y) z = np.sin(np.sqrt(x**2 + y**2)) # Plot the surface. surf = ax.plot_wireframe(x, y, z, color='black') surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, linewidth=1, antialiased=True, edgecolor='black') # Customize the z axis. ax.set_zlim(-1.01, 1.01) ax.zaxis.set_major_locator(LinearLocator(10)) ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) plt.show() fig.savefig(Path + '/fig.png', dpi=100) RE: 3-d surface plotting - Tuxedo - Jun-23-2024 Thanks, but I'm trying to use plotly instead of matplotlib. RE: 3-d surface plotting - paul18fr - Jun-23-2024 I was not aware about plotly. The following information partially answers (i guess) to your need: 1) From sawtooth500 code, the picture can be directly displayed in your browser with fig.write_html(Path + '/figure.html', auto_open=True)It also writes an html file. 2) you can record the file using an icon in the browser (see screenshot), but in my case, it's done in the Download repertory. 3) I tried to install imgkit on Anaconda, but i failed so far. import imgkit imgkit.from_file(Path + '/figure.html', Path + '/out.png')Complete code: # -*- coding: utf-8 -*- import numpy as np import plotly.graph_objects as go import os Path = os.getcwd() # Generate example data x = np.linspace(-10, 10, 100) y = np.linspace(-10, 10, 100) x, y = np.meshgrid(x, y) z = np.sin(np.sqrt(x**2 + y**2)) # Specify the z-value for slicing and cutting the base slice_z_value = 0.5 cut_base_z_value = -0.5 # Create a mask to discard values below the cut_base_z_value z[z < cut_base_z_value] = np.nan # Create the 3D surface plot fig = go.Figure(data=[go.Surface(z=z, x=x, y=y)]) # Add contour at the slice_z_value fig.add_trace(go.Surface( z=np.ones_like(z) * slice_z_value, x=x, y=y, showscale=False, opacity=0.5, surfacecolor=np.where(z >= slice_z_value, z, np.nan), contours={"z": {"show": True, "start": slice_z_value, "end": slice_z_value, "size": 0.1}} )) # Update layout for better visualization fig.update_layout(scene=dict( zaxis=dict(range=[cut_base_z_value, np.nanmax(z)]) )) # Show plot fig.show() fig.write_html(Path + '/figure.html', auto_open=True) # import imgkit # imgkit.from_file(Path + '/figure.html', Path + '/out.png') RE: 3-d surface plotting - Tuxedo - Jun-23-2024 I'm trying to write png or jpg files to import into a Latex document, but my Python script hangs whenever it gets to the command: fig.write_image('plotly_test.png')I have to restart the Python kernel from Spyder to recover. I have no idea what's wrong. RE: 3-d surface plotting - paul18fr - Jun-24-2024 I've had to install kaleido as well, but just typing conda install python-kaleido (see conda-forge) and it works fine for me. I would uninstall first your kaleido release and reinstall it, otherwise it may come from anaconda incompatibilities, broken links ...Personnal feeling: In my opinion it's better to print the figure from the browser (after rotating, zooming, etc.) RE: 3-d surface plotting - Tuxedo - Jun-24-2024 Sorry for the pivot, but it looks like I was too quick to abandon matplotlib. After implementing some tips in this thread (thanks!) I was able to get m-u-c-h closer to what I'm looking for. See attached. What I can't figure out how to do though, is restrict the face color to the area inside the axes. I want everything outside the axes to be white. How to do it? I've seen it done with 2d plots but not 3d. This is what I included: ax.set_facecolor('Blue') |