Как визуализировать скалярные 2D данные с помощью Matplotlib? - PullRequest
10 голосов
/ 26 февраля 2011

Итак, у меня есть сетка (матрицы X и Y) вместе со скалярными данными (матрица Z), и мне нужно это визуализировать.Предпочтительно какое-то 2D изображение с цветами в точках, показывающих значение Z там.Я провел некоторое исследование, но не нашел ничего, что бы делало именно то, что я хочу.

pyplot.imshow (Z) хорошо выглядит, но он не принимает мои матрицы X и Y, поэтомуоси неправильны, и он не может обрабатывать нелинейно разнесенные точки, заданные X и Y.

pyplot.pcolor (X, Y, Z) создает цветные квадраты с цветами, соответствующими данным в одном из его угловТаким образом, он как бы искажает данные (он должен показывать данные в центре или что-то в этом роде).Кроме того, он игнорирует два ребра из матрицы данных.

Я почти уверен, что где-то в Matplotlib должен быть какой-то лучший способ, но документация затрудняет получение обзора.Поэтому я спрашиваю, знает ли кто-то еще о лучшем способе.Бонус, если он позволяет мне обновить матрицу Z, чтобы сделать анимацию.

Ответы [ 4 ]

10 голосов
/ 26 февраля 2011

Это выглядит красиво, но неэффективно:

from pylab import *
origin = 'lower'

delta = 0.025

x = y = arange(-3.0, 3.01, delta)
X, Y = meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10 * (Z1 - Z2)

nr, nc = Z.shape

CS = contourf(
    X, Y, Z,
    levels = linspace(Z.min(), Z.max(), len(x)),
    ls = '-',
    cmap=cm.bone,
    origin=origin)

CS1 = contour(
    CS,
    levels = linspace(Z.min(), Z.max(), len(x)),
    ls = '-',
    cmap=cm.bone,
    origin=origin)

show()

Если бы это был я, я бы повторно интерполировал (используя scipy.interpolate) данные в обычную сетку и использовал imshow (), устанавливая экстенты для фиксации осей.

fine contour

Редактировать (за комментарий):

Анимация контурного графика может быть выполнена следующим образом, но, как я уже сказал, вышеупомянутое неэффективно, просто злоупотребление функцией контурного графика. Самый эффективный способ сделать то, что вы хотите, это использовать SciPy. У вас это установлено?

import matplotlib
matplotlib.use('TkAgg') # do this before importing pylab
import time
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

def animate():
    origin = 'lower'
    delta = 0.025

    x = y = arange(-3.0, 3.01, delta)
    X, Y = meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10 * (Z1 - Z2)

    CS1 = ax.contourf(
        X, Y, Z,
        levels = linspace(Z.min(), Z.max(), 10),
        cmap=cm.bone,
        origin=origin)

    for i in range(10):
        tempCS1 = contourf(
            X, Y, Z,
            levels = linspace(Z.min(), Z.max(), 10),
            cmap=cm.bone,
            origin=origin)
        del tempCS1
        fig.canvas.draw()
        time.sleep(0.1)
        Z += x/10

win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate)
plt.show()
2 голосов
/ 26 февраля 2011

Если ваша сетка имеет равномерный интервал, вы можете продолжать использовать pcolor, но просто сдвиньте X и Y для целей центрирования данных на определенных значениях, а не на углах.

Вы также можете использовать точечную диаграмму для явного размещения точек некоторого размера в точных точках X и Y, а затем установить цвет Z:

x = numpy.arange(10)
y = numpy.arange(10)
X,Y = numpy.meshgrid(x,y)
Z = numpy.arange(100).reshape((10,10))
scatter(X,Y,c=Z,marker='s',s=1500) 
#I picked a marker size that basically overlapped the symbols at the edges
axis('equal')

или

pcolor(X+0.5,Y+0.5,Z)
axis('equal')

или, как предложил Пол, используя одну из функций контура

1 голос
/ 20 апреля 2012

В случае, если кто-нибудь натолкнется на эту статью в поисках того, что я искал, я взял приведенный выше пример и изменил его, чтобы использовать imshow со входным стеком кадров вместо генерации и использования контуров на лету.Начиная с трехмерного массива изображений формы (nBins, nBins, nBins), называемого frames.

def animate_frames(frames):
    nBins   = frames.shape[0]
    frame   = frames[0]
    tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
    for k in range(nBins):
        frame   = frames[k]
        tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
        del tempCS1
        fig.canvas.draw()
        #time.sleep(1e-2) #unnecessary, but useful
        fig.clf()

fig = plt.figure()
ax  = fig.add_subplot(111)

win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate_frames, frames)

, я также нашел гораздо более простой способ выполнения всего этого процесса, хотя и менее надежный:

fig = plt.figure()

for k in range(nBins):
    plt.clf()
    plt.imshow(frames[k],cmap=plt.cm.gray)
    fig.canvas.draw()
    time.sleep(1e-6) #unnecessary, but useful

Обратите внимание, что оба из них, кажется, работают только с ipython --pylab=tk, он же backend = TkAgg

Спасибо за помощь во всем.

0 голосов
/ 31 июля 2015

Следующая функция создает прямоугольники с половиной размера на границе (как показано на прикрепленном рисунке).

import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage.filters import convolve

def pcolor_all(X, Y, C, **kwargs):
    X = np.concatenate([X[0:1,:], X], axis=0)
    X = np.concatenate([X[:,0:1], X], axis=1)

    Y = np.concatenate([Y[0:1,:], Y], axis=0)
    Y = np.concatenate([Y[:,0:1], Y], axis=1)

    X = convolve(X, [[1,1],[1,1]])/4
    Y = convolve(Y, [[1,1],[1,1]])/4

    plt.pcolor(X, Y, C, **kwargs)

X, Y = np.meshgrid(
    [-1,-0.5,0,0.5,1],
    [-2,-1,0,1,2])

C = X**2-Y**2

plt.figure(figsize=(4,4))

pcolor_all(X, Y, C, cmap='gray')

plt.savefig('plot.png')

plot.png

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...