Matplotlib: `pcolormesh.get_array()` возвращает сплющенный массив - как вернуть данные 2D? - python


1

Я пытаюсь получить значения данных вдоль строки (например, этот подсказку). В этом примере используется imshow(), но в настоящее время я использую pcolormesh() для построения.

Я обнаружил, что функция get_array() для захвата построенных данных из pcolormesh() возвращает 1-D, сплющенный массив моих данных вместо исходных (или усеченных) двухмерных данных.

Например:

D = np.genfromtxt(DataFilePath, skip_header=4, delimiter=,, unpack=True)
print( D.shape )
: (500, 500)

...more code...

img = ax[0].pcolormesh( np.arange( len(D[0,:]) ), np.arange(len(D[:,0])), D)

>>> D
: array([[ 42.38,  41.93,  41.92, ...,  41.73,  41.74,  41.51],
       [ 41.88,  42.24,  42.21, ...,  41.88,  41.67,  41.64],
       [ 42.4 ,  41.47,  41.49, ...,  41.92,  42.07,  41.49],
       ..., 
       [ 44.24,  44.14,  44.17, ...,  40.2 ,  40.68,  40.67],
       [ 44.59,  44.24,  44.3 , ...,  40.91,  40.92,  40.95],
       [ 44.2 ,  44.27,  44.27, ...,  40.82,  40.91,  40.94]])
>>> img.get_array()
: array([ 42.38,  41.93,  41.92, ...,  40.85,  40.91,  40.92])

Так как я пытаюсь захватить щелчки пользователя на сюжете, а затем переделать с использованием значений данных щелкнув (например, этот подсказку), Я хотел бы использовать функцию/класс, которая не будет иметь глобального доступа к исходным данным, но имеет доступ к объекту img.

Любая идея, как получить 2D-данные из pcolormesh(), используя только объект img (QuadMesh)? Он даже не имеет значений длины/формы x/y, для меня можно восстановить данные из 1-D get_array().

Спасибо!

  •  21
  •  2
  • 8 фев 2020 2020-02-08 08:05:51

2 ответа

2

Да, он активирует входные данные:

https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py

    # convert to one dimensional arrays
    C = C.ravel()
    X = X.ravel()
    Y = Y.ravel()

Если вы знаете желаемую 2d-форму, вы можете распутать с помощью простого вызова reshape.

Если результат должен иметь ту же форму, что и D, используйте:

img.get_array().reshape(D.shape)

Если размер растрового C может измениться, это не сработает.


Если я создаю массив D, который (10,20), и постройте его

img = pyplot.pcolormesh(D)

img._A - (200), массив, возвращаемый img.get_array().

img._meshHeight, img._meshWidth
# 10, 20

Таким образом, массив можно изменить следующим образом:

img._A.reshape(img._meshHeight, img._meshWidth)

img._coordinates - это массив (11,21,2), координаты в направлении x и y плюс одна точка. Таким образом, вы можете получить информацию о преобразовании C из _coordinates. Я не вижу никакого общедоступного метода API для извлечения этих атрибутов, но это не останавливает "серьезных" программистов на Python. В этом тестовом случае он генерировал coordinates из формы D.

Этот Quadmesh был создан с помощью

    coords = np.zeros(((Nx * Ny), 2), dtype=float)
    coords[:, 0] = X
    coords[:, 1] = Y

    collection = QuadMesh(
        Nx - 1, Ny - 1, coords, ...)
    ....
    collection.set_array(C)

Поиск get_array в репозитории matplotlib github не получает много обращений.


Я немного вкопался в код pcolor. Он возвращает PolyCollections img, а не квадрат. Он содержит информацию для рисования коллекции четырехугольников.

Например, в моем тестовом примере с входом 10x20 img._paths - это список из 200 Path объектов

In [486]: img1._paths[0]
Out[486]: 
Path(array([[ 0.,  0.],
       [ 0.,  1.],
       [ 1.,  1.],
       [ 1.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]]), array([ 1,  2,  2,  2,  2, 79], dtype=uint8))

Он имеет пять координатных пар, xy точек, необходимых для рисования границы квадрата, который будет иметь значение цвета, соответствующее C[0] (в раскованной форме).

Итак, вся информация о сетке X Y теперь закодирована в этих объектах Path. Вместо того, чтобы прокладывать сетку, он отображает 200 цветных квадратов (квадрациклов). Код PolyCollections не предполагает, что квадраты находятся в любом порядке или даже касаются друг друга. Большая картина была заменена кучей независимых небольших изображений.

Возможно, вы сможете собрать эти квадратики в сетку, найти совпадающие вершины и т.д. Но это будет очень много работы.

  • 8 фев 2020 2020-02-08 08:05:52
3

Форма массива, хранящаяся в частных атрибутах, _meshWidth и _meshHeight. Тем не менее, поскольку эти атрибуты не являются частью публичного API, было бы лучше сохранить форму исходных данных, чем полагаться на них, если это возможно.

import matplotlib.pyplot as plt
import numpy as np

D = np.random.uniform(0, 100, size=(5, 5))
fig, ax = plt.subplots()
h, w = D.shape
img = ax.pcolormesh( np.arange(h+1), np.arange(w+1), D)

D2 = img.get_array().reshape(img._meshWidth, img._meshHeight)
assert  np.array_equal(D, D2)

Обратите также внимание, что если вы хотите восстановить исходный массив D, тогда массивы координат np.arange(h+1), np.arange(w+1) должны иметь длину, большую, чем форма D. В противном случае img.get_array() возвращает массив формы (499, 499), когда D имеет форму (500, 500).

  • 8 фев 2020 2020-02-08 08:05:52