首页 > 解决方案 > 循环中更新 imshow 和循环后颜色图中的问题

问题描述

我有两个我怀疑密切相关的 imshow() 问题。

首先,我不知道如何使用 set_data() 来更新我用 imshow() 创建的图像。

其次,我无法弄清楚为什么我在更新完绘图后添加到 imshow() 绘图的颜色栏与我添加到从头开始创建的相同数据的 imshow() 绘图中的颜色栏不匹配在我完成数据采集后。第二个图的颜色条似乎是正确的。

背景。

我在两个嵌套循环中收集测量数据,每个循环控制一个测量条件。我正在使用 pyplot.imshow() 绘制我的结果,并且每次在内部循环中获取数据时我都会更新 imshow() 图。

我在更新 imshow() 图方面所做的工作,但随着我添加更多循环迭代,它似乎变得越来越慢,所以它不能很好地扩展。(我在这篇文章中包含的程序创建了一个八行高六列宽的图。一个“真实”的图可能是这个大小的 10 倍或 20 倍,在两个维度上。)

我想做的是使用图像的 set_data() 方法,但我不知道怎么做。我尝试过的要么引发错误,要么似乎对 imshow() 图没有任何影响。

完成“获取数据”循环后,我会在我一直在更新的 imshow() 图中添加一个颜色条。然而,彩条比例显然是假的。

相反,如果我使用我在循环中获取的数据创建一个全新的 imshow() 图,然后添加一个颜色条,那么颜色条似乎是正确的。

我的预感是问题在于与我在循环中更新的 imshow() 图相关的 vmin 和 vmax 值,但我不知道如何修复它。

我已经看过几个相关的 StackOverflow 帖子。例如:

这些有帮助,因为他们将我指向 set_data() 并为我解决了我遇到的其他一些问题,但我仍然有我一开始提到的两个问题。

这是我的代码的简化版本。请注意,X 轴和 Y 轴上有重复的零值。这是故意的。

我正在运行 Python 3.5.1、matplotlib 1.5.1 和 numpy 1.10.4。(是的,其中一些已经很老了。企业 IT 原因。)

import numpy as np
import matplotlib.pyplot as plt
import random
import time
import warnings

warnings.filterwarnings("ignore", ".*GUI is implemented.*")  # Filter out bogus matplotlib warning.

# Create the simulated data for plotting

v_max = 120
v_step_size = 40
h_max = 50
h_step_size = 25
scale = 8

v_points = np.arange(-1*abs(v_max), 0, abs(v_step_size))
v_points = np.append(v_points, [-0.0])
reversed_v_points = -1 * v_points[::-1]  # Not just reverse order, but reversed sign
v_points = np.append(v_points, reversed_v_points)

h_points = np.arange(-1*abs(h_max), 0, abs(h_step_size))
h_points = np.append(h_points, [-0.0])
reversed_h_points = -1 * h_points[::-1]  # Not just reverse order, but reversed sign
h_points = np.append(h_points, reversed_h_points)

h = 0  # Initialize
v = 0  # Initialize

plt.ion()  # Turn on interactive mode.
fig, ax = plt.subplots()  # So I have access to the figure and the axes of the plot.

# Initialize the data_points
data_points = np.zeros((v_points.size, h_points.size))
im = ax.imshow(data_points, cmap='hot', interpolation='nearest')  # Specify the color map and interpolation
ax.set_title('Dummy title for initial plot')

# Set up the X-axis ticks and label them
ax.set_xticks(np.arange(len(h_points)))
ax.set_xticklabels(h_points)
ax.set_xlabel('Horizontal axis measurement values')

# Set up the Y-axis ticks and label them
ax.set_yticks(np.arange(len(v_points)))
ax.set_yticklabels(v_points)
ax.set_ylabel('Vertical axis measurement values')

plt.pause(0.0001)  # In interactive mode, need a small delay to get the plot to appear
plt.show()

for v, v_value in enumerate(v_points):
    for h, h_value in enumerate(h_points):

        # Measurement goes here.
        time.sleep(0.1)  # Simulate the measurement delay.
        measured_value = scale * random.uniform(0.0, 1.0)  # Create simulated data
        data_points[v][h] = measured_value  # Update data_points with the simulated data

        # Update the heat map with the latest point.
        #  - I *think* I want to use im.set_data() here, not ax.imshow(), but how?
        ax.imshow(data_points, cmap='hot', interpolation='nearest')  # Specify the color map and interpolation

        plt.pause(0.0001)  # In interactive mode, need a small delay to get the plot to appear
        plt.draw()

# Create a colorbar
#   - Except the colorbar here is wrong.  It goes from -0.10 to +0.10 instead
#     of matching the colorbar in the second imshow() plot, which goes from
#     0.0 to "scale".  Why?
cbar = ax.figure.colorbar(im, ax=ax)
cbar.ax.set_ylabel('Default heatmap colorbar label')
plt.pause(0.0001)  # In interactive mode, need a small delay to get the colorbar to appear
plt.show()

fig2, ax2 = plt.subplots()  # So I have access to the figure and the axes of the plot.
im = ax2.imshow(data_points, cmap='hot', interpolation='nearest')  # Specify the color map and interpolation
ax2.set_title('Dummy title for plot with pseudo-data')

# Set up the X-axis ticks and label them
ax2.set_xticks(np.arange(len(h_points)))
ax2.set_xticklabels(h_points)
ax2.set_xlabel('Horizontal axis measurement values')

# Set up the Y-axis ticks and label them
ax2.set_yticks(np.arange(len(v_points)))
ax2.set_yticklabels(v_points)
ax2.set_ylabel('Vertical axis measurement values')

# Create a colorbar
cbar = ax2.figure.colorbar(im, ax=ax2)
cbar.ax.set_ylabel('Default heatmap colorbar label')

plt.pause(0.0001)  # In interactive mode, need a small delay to get the plot to appear
plt.show()

dummy = input("In interactive mode, press the Enter key when you're done with the plots.")

标签: pythonmatplotlibcolorbarimshow

解决方案


好的,我谷歌了一些。更重要的是,我更聪明地用谷歌搜索并找到了自己的答案。

为了更新嵌套循环中的情节,我使用了以下命令:

ax.imshow(data_points, cmap='hot', interpolation='nearest')  # Specify the color map and interpolation

我试图更有效地更新我的情节是:

im.set_data(data_points)

应该使用的是:

im.set_data(data_points)
im.autoscale()

这会更新像素缩放,从而解决了我的“绘图不更新”问题和“颜色条的比例错误”问题。


推荐阅读