Matplotlib pcolor

3
我正在使用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')

2
e1cxe1cye1cz 定义在哪里?你检查过是否真的有非零数据了吗? - Avaris
抱歉,我不应该从我的代码中删除那一部分,它们现在已经被定义了。另外,我已经检查过了,它是非零数据。谢谢。 - jbm1991
你能否也发布一下第一个文件的几行代码?另外,你能检查一下你的代码缩进吗?它有点不对齐,我不想猜测哪些属于哪里。 - Avaris
谢谢你的帮助,但我已经通过将绘图插入到自己的循环中解决了它。现在它完美地工作了。 - jbm1991
1个回答

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]被称为列表推导式,除了更加简洁外,执行速度比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是一个排名为3的数组,索引为almost_fx[iz,iy,ix]。需要注意的一件重要事情是e1cxalmost_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-slices (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 留空意味着从 0 开始,而将 end 留空意味着到列表末尾。

概述

总之,你的完整代码(在引入更多 Python 惯用语之后,如 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)

如果你想要每个元素一个像素,你可以用以下代码替换for循环的主体部分:

z = i*10
pt.imsave('Imagex_%d' % z, fx_slice, cmap='spectral', vmin=0, vmax=1)

这太棒了。我很惊讶只有4个“赞”。 - varantir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接