经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Python作图三维等高面
来源:cnblogs  作者:DECHIN  时间:2024/5/22 9:38:10  对本文有异议

技术背景

对于等高线,大家都是比较熟悉的,因为日常生活中遇到的山体和水面,都可以用一系列的等高线描绘出来。而等高面,顾名思义,就是在三维空间“高度一致”的曲面。当然了,在二维平面上我们所谓的“高度”实际上就是第三个维度的值,但是三维曲面所谓的“高度”,实际上我们可以理解为密度。“高度”越高,“密度”越大。

等高线作图

如果是Python中画等高线,这个用Matplotlib就可以实现,这里就直接放一个Matplotlib的官方示例

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. plt.style.use('_mpl-gallery-nogrid')
  4. # make data
  5. X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
  6. Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2)
  7. levels = np.linspace(np.min(Z), np.max(Z), 7)
  8. # plot
  9. fig, ax = plt.subplots()
  10. ax.contour(X, Y, Z, levels=levels)
  11. plt.show()

输出图像为:

其实关于Matplotlib还有一些可玩性更高的操作,比如画一个三维空间的断层扫描等高线:

实现的代码也是比较简单的:

  1. # 该函数在z3维度做了断层
  2. def plot3d(distribution, z1, z2, z3, z_level=[0, 5, 10, 15, 20, 25], levels=np.arange(0, 500, 50)):
  3. import matplotlib.pyplot as plt
  4. fig = plt.figure()
  5. ax = fig.add_subplot(111, projection='3d')
  6. idZ = np.array(z_level, np.int32)
  7. for idx in idZ:
  8. Z = z3[idx]
  9. g = ax.contourf(
  10. z1, z2, distribution[:, :, idx],
  11. zdir='z', offset=z3[idx], levels=levels
  12. )
  13. fig.colorbar(g, ax=ax)
  14. gap = (z3[idZ[-1]]-z3[idZ[0]])/10
  15. ax.set_zlim(z3[idZ[0]]-gap,z3[idZ[-1]]+gap)
  16. ax.set_xlabel('X')
  17. ax.set_ylabel('Y')
  18. ax.set_zlabel('Z')
  19. plt.show()

但是因为画出来的图效果也是比较一般,而且速度并不是很快,因此关于这类问题,我还是比较推荐使用Plotly的登高面作图。

等高面作图

这里的数据没办法直接提供,有作图需求的童鞋可以自行准备数据。数据的维度为:z1->(m,),z2->(n,),z3->(p,),distribution->(m,n,p)。在作图函数的内部我们可以用一个meshgrid的操作对z1,z2,z3做展开,但是准备数据阶段我们就尽可能的简单就行了。这里直接上代码:

  1. def iso_surface(distribution, z1, z2, z3, show=True, save_file=None, colorbar_min=0., colorbar_max=500.,
  2. opacity=0.4, surface_number=3):
  3. import os
  4. try:
  5. import plotly.graph_objects as go
  6. import plotly.offline as offline
  7. except ImportError:
  8. # 确保plotly正常安装
  9. os.system('python3 -m pip install --upgrade plotly')
  10. import plotly.graph_objects as go
  11. import plotly.offline as offline
  12. # Plotly作图要求数据展平,这里我们手动操作
  13. x, y, z = np.meshgrid(z1, z2, z3)
  14. distribution = distribution.reshape(-1)
  15. fig= go.Figure(data=go.Isosurface(
  16. x=x.reshape(-1),
  17. y=y.reshape(-1),
  18. z=z.reshape(-1),
  19. value=distribution,
  20. isomin=colorbar_min,
  21. isomax=colorbar_max,
  22. opacity=opacity,
  23. surface_count=surface_number
  24. ))
  25. if save_file is not None:
  26. import plotly.io as pio
  27. fmt = save_file.split('.')[-1]
  28. # Plotly支持的图片导出格式就是这几种了
  29. if fmt not in ['png', 'jpg', 'jpeg', 'webp', 'svg', 'pdf', 'eps']:
  30. raise ValueError("The format {} is not supported in plotly!".format(fmt))
  31. try:
  32. pio.write_image(fig, format=fmt, file=save_file)
  33. except ValueError:
  34. # 导出图片需要依赖kaleido环境
  35. os.system('python3 -m pip install --upgrade kaleido')
  36. pio.write_image(fig, format=fmt, file=save_file)
  37. # Plotly生成的结果是以html格式保存的,我们做了一个简单的本地备份
  38. if os.path.exists('offline_plot.html'):
  39. os.rename('offline_plot.html', 'offline_plot.html.bak')
  40. # 生成html文件以后选择是否需要打开,默认生成结束之后自动在浏览器打开图像
  41. if show:
  42. offline.plot(fig, filename='offline_plot.html', auto_open=True)
  43. else:
  44. offline.plot(fig, filename='offline_plot.html', auto_open=False)

为了复现起来容易一些,这里我自己通过添加异常捕获的方法,来确认环境配置问题。最终展示的结果为:

也可以换一个角度看:

这个数据用的跟前面章节展示的断层扫描图是同一个数据,在这个等高面结果中可以看到,三维空间中存在着一条低密度的“通路”。而且最关键的是,这个展示图像除了显示效果不错以外,速度也还是相当可观的,没有出现明显的卡顿。

总结概要

在一维空间下,我们要表示密度时可以给出一个二维的函数y=f(x),画出来是一条二维平面上的曲线。在二维空间下,我们要表示密度可以使用一个三维的函数z=f(x,y),画出来是一个三维空间的曲面。而三维空间下,密度表示是一个四维的函数:q=f(x,y,z),这个密度我们在三维空间已经没有办法用线或者面去表示,只能用体积元的颜色来表示。但是我们可以把这个密度投影到一个三维的等高曲面上,这个曲面就称为等高面。本文介绍了一个python中性能比较好的画等高面的工具:Plotly。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/iso-surface.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

参考链接

  1. https://matplotlib.org/stable/plot_types/arrays/contour.html#sphx-glr-plot-types-arrays-contour-py

原文链接:https://www.cnblogs.com/dechinphy/p/18203996/iso-surface

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号