matplotlib 为什么plot_surface是透明的?

h6my8fg2  于 2023-06-23  发布在  其他
关注(0)|答案(2)|浏览(151)

我试图用Python 3创建一个曲面图,现在我想知道为什么它是透明的?有什么想法吗?我希望它看起来像我用MATLAB使用相同的数据集ETOPO1创建的图。第二个问题,用plot_surface不能改变长宽比,对吗?
最好,马丁

import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt
from matplotlib.colors import LightSource

ETOPO1 = np.flipud(ETOPO1)

lon = np.arange(30,60+1/60,1/60)
lat = np.arange(-20,20+1/60,1/60)
LON,LAT = np.meshgrid(lon,lat)

fig, ax2 = plt.subplots(subplot_kw={"projection": "3d"})
ls = LightSource(270,45)
rgb = ls.shade(ETOPO1,
        cmap=cm.gist_earth,
        vert_exag=0.1,
        blend_mode='hsv')
ax2.plot_surface(LON,LAT,ETOPO1,
        rstride=1, cstride=1,
        linewidth=0,
        facecolors=rgb,
        antialiased=True,
        shade=True)
ax2.view_init(60, 20-90)
ax2.tick_params(axis='both', labelsize=6)
ax2.grid(False)
plt.show()

3D surface from python
3D surface from matlab
编辑1 Dec 2021
以下是几个相关问题:
1.如果我使用rstride=5,cstride=5,则上面的代码需要15秒,但如果我使用全分辨率rstride=1,cstride=1,则需要318秒= 5.3分钟。这是令人惊讶的,因为MATLAB需要0.14秒的完整分辨率-为什么?
1.我尝试在表面上添加轮廓使用

v = np.array([500,1000,2000,3000])
ax2.contour(LON,LAT,ETOPO1+1,
     levels=v,linewidths=0.3,
     colors='r',linestyles='solid')

但是,尽管向ETOPO 1添加1、10或100,它们总是被表面隐藏。
1.我试图使用ETOPO 1保存数字,我
plt.savefig('etopo1_python.png',dpi=300)
但是PNG文件中有一个空的图像。有什么想法吗
1.自从
antialiased=True
导致透明度,问题来了,这是一个bug吗?

k4aesqcs

k4aesqcs1#

根据this answer,这是plot_surface()函数的已知问题。
This other answer建议在plot_surface()中设置antialiased=False,这对我在您的数据上起作用。但我没有仔细观察它是否会引起任何问题。
如下图所示,您可以通过添加ax.set_box_aspect((1, 1, 0.1))来调整纵横比(下面我计算Z参数来实现一些所需的近似垂直放大,但您已经明白了)。

import numpy as np
from matplotlib import cm
from matplotlib.colors import LightSource
import matplotlib.pyplot as plt

url = 'http://141.89.112.21/wp-content/uploads/2021/11/etopo1_data_python.txt'
ETOPO1 = np.loadtxt(np.DataSource().open(url), skiprows=5)

h, w = ETOPO1.shape
lon = np.linspace( 30,  60, w)  # linspace recommended for non-integer intervals.
lat = np.linspace( 20, -20, h)  # Reverse this instead of flipping the array.
LON, LAT = np.meshgrid(lon, lat)

fig, ax = plt.subplots(figsize=(20, 15),
                       subplot_kw={"projection": "3d"})

ve = 200  # Approx. vertical exaggeration.
ax.set_box_aspect((1, 1, ve/1850))

rgb = LightSource(270, 45).shade(ETOPO1,
                                 cmap=cm.Blues_r,
                                 blend_mode='soft',
                                 vert_exag=ve/1850)

ax.plot_surface(LON, LAT, ETOPO1,
                rstride=2, cstride=2,
                facecolors=rgb,
                antialiased=False)

ax.view_init(20, -70)
ax.tick_params(axis='both', labelsize=6)
ax.grid(False)
plt.show()

这产生:

8mmmxcuj

8mmmxcuj2#

在@kwinkunks的基础上,您对shade的尝试与您所追求的非常接近。注:我认为LATLON在kwinkunks的答案中被切换出meshgrid

h, w = ETOPO1.shape
lon = np.linspace( 30, 60, w)
lat = np.linspace(-20, 20, h)
LAT, LON = np.meshgrid(lon, lat)

fig, ax = plt.subplots(
    figsize=(10, 10),
    subplot_kw={"projection": "3d"})

ve = 100  # Approx. vertical exaggeration.
ax.set_box_aspect((1, 1, ve/1850))

ls = LightSource(270,45)
cs = ls.shade(
    ETOPO1, cmap=cm.gist_earth,
    vert_exag=ve/1850)
ax.plot_surface(
    LON, LAT, ETOPO1,
    rstride=5, cstride=5,
    facecolors=cs)

ax.view_init(20, 15)

相关问题