我正在使用Matplotlib根据某些数据创建图像。所有数据都在0到1的范围内,我试图使用色彩图基于其值对数据进行着色,这在Matlab中完美运行,但是当将代码转换为Python时,我只需得到一个黑色正方形输出。我相信这是因为我正在绘制错误的图像,因此它将所有数据绘制为0.我已经尝试了几个小时搜索此问题而我已经尝试了plt.set_clim([0, 1])
但是似乎没有做任何事情。我是Python和Matplotlib的新手,虽然我不是编程新手(Java,javascript,PHP等),但我看不出我哪里出错了。如果我的代码中有任何正文可以看到任何明显不正确的内容,那么我将非常感激。
谢谢
from numpy import *
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as myColor
e1cx=[]
e1cy=[]
e1cz=[]
print("Reading files...")
in_file = open("eigenvector_1_component_x.txt", "rt")
for line in in_file.readlines():
e1cx.append([])
for i in line.split():
e1cx[-1].append(float(i))
in_file.close()
in_file = open("eigenvector_1_component_y.txt", "rt")
for line in in_file.readlines():
e1cy.append([])
for i in line.split():
e1cy[-1].append(float(i))
in_file.close()
in_file = open("eigenvector_1_component_z.txt", "rt")
for line in in_file.readlines():
e1cz.append([])
for i in line.split():
e1cz[-1].append(float(i))
in_file.close()
print("...done")
nx = 120
ny = 128
nz = 190
fx = zeros((nz,nx,ny))
fy = zeros((nz,nx,ny))
fz = zeros((nz,nx,ny))
z = 0
while z<nz-1:
x = 0
while x<nx:
y = 0
while y<ny:
fx[z][x][y]=e1cx[(z*128)+y][x]
fy[z][x][y]=e1cy[(z*128)+y][x]
fz[z][x][y]=e1cz[(z*128)+y][x]
y += 1
x += 1
z+=1
if((z % 10) == 0):
plt.figure(num=None)
plt.axis("off")
normals = myColor.Normalize(vmin=0,vmax=1)
plt.pcolor(fx[z][:][:],cmap='spectral', norm=normals)
filename = 'Imagex_%d' % z
plt.savefig(filename)
plt.colorbar(ticks=[0,2,4,6], format='%0.2f')
答案 0 :(得分:7)
虽然您已经解决了原始问题并且代码有效,但我想指出python和numpy都提供了一些工具,使得这样的代码编写起来更加简单。以下是一些例子:
不是通过附加到空列表的末尾来构建列表,而是通过其他列表生成列表通常更容易。例如,而不是
e1cx = []
for line in in_file.readlines():
e1cx.append([])
for i in line.split():
e1cx[-1].append(float(i))
你可以简单地写一下:
e1cx = [[float(i) for i in line.split()] for line in in_file]
语法[x(y) for y in l]
称为list comprehension,除了更简洁之外,执行速度比for
循环更快。
但是,要从文本文件加载表格数据,使用numpy.loadtxt
更简单:
import numpy as np
e1cx = np.loadtxt("eigenvector_1_component_x.txt")
了解更多信息,
print np.loadtxt.__doc__
另请参阅其稍微复杂的表亲numpy.genfromtxt
现在我们已经加载了数据,我们需要对其进行重塑。您使用的while循环工作正常,但numpy
提供了一种更简单的方法。首先,如果您更喜欢使用加载数据的方法,那么使用e1cx = array(e1cx)
等将您的特征向量数组转换为适当的numpy数组。
array
类提供了重新排列数组中数据索引的方法,而无需复制数据。最简单的方法是array.reshape
,它将执行while
循环的一半:
almost_fx = e1cx.reshape((nz,ny,nx))
此处,almost_fx
是索引为almost_fx[iz,iy,ix]
的排名3数组。需要注意的一件重要事情是e1cx
和almost_fx
分享他们的数据。因此,如果您更改e1cx[0,0]
,则还会更改almost_fx[0,0,0]
。
在您的代码中,您交换了x和y位置。如果这确实是您想要做的,您可以使用array.swapaxes
完成此操作:
fx = almost_fx.swapaxes(1,2)
当然,您总是可以将其合并为一行
fx = e1cx.reshape((nz,ny,nx)).swapaxes(1,2)
但是,如果您希望z切片(fx[z,:,:]
)以x水平和y垂直绘图,您可能不希望交换上面的轴。只是重塑并策划。
最后,不是循环遍历z-index并测试10的倍数,而是使用以下方法直接在数组的一个切片上循环:
for fx_slice in fx[::10]:
# plot fx_slice and save it
此索引语法为array[start:end:step]
,结果start
中包含end
的语法不是start
。将end
留空意味着0,而留空enumerate
意味着列表的结尾。
总结一下,你的完整代码(在介绍了一些像import numpy as np
from matplotlib import pyplot as pt
shape = (190,128,120)
fx = np.loadtxt("eigenvectors_1_component_x.txt").reshape(shape).swapaxes(1,2)
for i,fx_slice in enumerate(fx[::10]):
z = i*10
pt.figure()
pt.axis("off")
pt.pcolor(fx_slice, cmap='spectral', vmin=0, vmax=1)
pt.colorbar(ticks=[0,2,4,6], format='%0.2f')
pt.savefig('Imagex_%d' % z)
这样的python习语之后)可能看起来像:
for
或者,如果每个元素需要一个像素,则可以用
替换z = i*10
pt.imsave('Imagex_%d' % z, fx_slice, cmap='spectral', vmin=0, vmax=1)
循环的主体
{{1}}