Зацикливание или перенос цветовой карты за заданный интервал - PullRequest
2 голосов
/ 04 февраля 2020

Недавно я столкнулся с проблемой, когда я хотел, чтобы цветовая карта cycli c была «обернута» из-за отсутствия лучшего слова на заданном интервале. В приведенном ниже примере я отображаю значения в интервале [-5, 5] и хочу повторить карту цветов для каждого интервала [-1, 1]. Я начал с использования matplotlib.colors.Normalize, но хотя я намеревался это нормализовать числа в интервале [0, 1], числа вне заданных аргументов vmin и vmax были отображены вне этого интервала:

>>> norm = mpl.colors.Normalize(vmin=-1, vmax=1)
>>> norm(2)
1.5

Когда это значение передается в цветовую карту, по умолчанию возвращается значение cmap(1), но это можно изменить с помощью cmap.set_over() / cmap.set_under(). Однако из того, что я вижу, это можно установить только для цвета * stati c.

Неудовлетворительное решение, которое я придумал, заключалось в определении функции, которая применяет мою функцию norm к массиву, мод 1, а затем передать это как мои данные imshow(), без необходимости передавать norm в качестве аргумента. Мои попытки до сих пор приведены ниже:

Код:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

# Plot values between -5 and 5
x = np.linspace(-5,5,1000).reshape(1, -1)

# Normalize values to between -1 and 1
norm = mpl.colors.Normalize(vmin=-1, vmax=1)

# Function to apply norm cyclicly
def f(x):
    return norm(x)%1

# Use a cyclic cmap
cmap=plt.cm.hsv

# Plot image
fig, axs = plt.subplots(3, 1)

# Attempt using just cmap, no norm
axs[0].imshow(x, cmap=cmap, extent=[-5,5,0,1])

# Attempt applying norm, no application of modulus function
axs[1].imshow(x, cmap=cmap, norm=norm, extent=[-5,5,0,1])

# Correct output, applying norm%1 to data before passing to cmap
axs[2].imshow(f(x), cmap=cmap, extent=[-5,5,0,1])

Выход:

enter image description here

Вопрос:

Существует ли лучший / встроенный способ зацикливания / переноса цветовой карты без необходимости определения пользовательской функции, как в нижнем подпункте

1 Ответ

4 голосов
/ 04 февраля 2020

Идея может состоять в том, чтобы адаптировать пользовательскую норму из учебника , чтобы получить циклическую c норму:

import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np

class CyclicNormalize(colors.Normalize):
    def __init__(self, cmin=0, cmax=1, vmin=0, vmax=1, clip=False):
        self.cmin = cmin
        self.cmax = cmax
        colors.Normalize.__init__(self, vmin, vmax, clip=clip)

    def __call__(self, value, clip=False):
        x, y = [self.cmin, self.cmax], [0, 1]
        return np.ma.masked_array(np.interp(value, x, y, period=self.cmax - self.cmin))

x = np.linspace(-5, 5, 1000).reshape(1, -1)
cmap = plt.cm.hsv

cyclicnorm = CyclicNormalize(cmin=-1, cmax=1, vmin=-5, vmax=5)

fig, ax = plt.subplots()
pcm = ax.imshow(x, cmap=cmap, norm=cyclicnorm, extent=[-5, 5, 0, 1])
plt.show()

plot

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