Подтвердить что ты не робот

Есть ли способ использовать бивариантные цветовые карты в matplotlib?

Другими словами, я хочу создать тепловую карту (или участок поверхности), где цвет меняется в зависимости от двух переменных. (В частности, яркость = величина и оттенок = фаза.) Есть ли какой-нибудь родной способ сделать это? Некоторые примеры подобных графиков:

uses two colorbars, one for magnitude and one for phase

uses a colorbar for magnitude and a circular legend for phase

uses a 2D colorbar to indicate the changes in both variables

Несколько хороших примеров точно (?), что я хочу сделать.

Дополнительные примеры из астрономии, но с не воспринимаемым оттенком

4b9b3361

Ответ 1

imshow возьмет массив NxMx3 (rbg) или NxMx4 (grba), чтобы вы могли сделать свое цветовое сопоставление "вручную".

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

Я сделал что-то вроде этого (pdf-ссылка, см. рисунок на стр. 24), но код находится в MATLAB (и похоронен где-то в моих архивах).

Я согласен, что бивариантная цветовая карта была бы полезна (прежде всего для представления очень плотных векторных полей, где ваш вид на ручей, независимо от того, что вы делаете). Я думаю, что очевидное расширение состоит в том, чтобы позволить цветным картам принимать сложные аргументы. Для этого потребуются специализированные подклассы Normalize и Colormap, и я буду идти туда и обратно, если я думаю, что это будет много работы для реализации. Я подозреваю, что если вы заработаете его вручную, это будет просто вопрос априанства.

Ответ 2

imshow может принимать массив из записей [r, g, b]. Таким образом, вы можете преобразовать абсолютные значения в интенсивности и фазы - в оттенки.

Я буду использовать в качестве примера комплексные числа, потому что для него это имеет наибольший смысл. При необходимости вы всегда можете добавить numpy массивы Z = X + 1j * Y.

Итак, для ваших данных Z вы можете использовать, например,

imshow(complex_array_to_rgb(Z))

где (EDIT: сделать это быстрее и приятнее благодаря этому предложению)

def complex_array_to_rgb(X, theme='dark', rmax=None):
    '''Takes an array of complex number and converts it to an array of [r, g, b],
    where phase gives hue and saturaton/value are given by the absolute value.
    Especially for use with imshow for complex plots.'''
    absmax = rmax or np.abs(X).max()
    Y = np.zeros(X.shape + (3,), dtype='float')
    Y[..., 0] = np.angle(X) / (2 * pi) % 1
    if theme == 'light':
        Y[..., 1] = np.clip(np.abs(X) / absmax, 0, 1)
        Y[..., 2] = 1
    elif theme == 'dark':
        Y[..., 1] = 1
        Y[..., 2] = np.clip(np.abs(X) / absmax, 0, 1)
    Y = matplotlib.colors.hsv_to_rgb(Y)
    return Y

Итак, например:

Z = np.array([[3*(x + 1j*y)**3 + 1/(x + 1j*y)**2
              for x in arange(-1,1,0.05)] for y in arange(-1,1,0.05)])
imshow(complex_array_to_rgb(Z, rmax=5), extent=(-1,1,-1,1))

enter image description here

imshow(complex_array_to_rgb(Z, rmax=5, theme='light'), extent=(-1,1,-1,1))

enter image description here