在给定的时间间隔内循环或包装颜色图
Looping or wrapping a colormap over a given interval
我最近 运行 遇到了一个问题,我希望在给定的时间间隔内循环颜色图 'wrapped',因为需要一个更好的词。在下面的示例中,我在区间 [-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()
更改。但是,据我所知,这只能设置为静态颜色。
我想出的不令人满意的解决方案是定义一个函数,将我的 norm
函数应用于数组 mod 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])
输出:
问题:
是否有 better/built 方式 loop/wrap 颜色图而无需定义自定义函数,如底部子图所示?
一个想法可能是调整来自 tutorial 的自定义范数以获得循环范数:
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()
我最近 运行 遇到了一个问题,我希望在给定的时间间隔内循环颜色图 'wrapped',因为需要一个更好的词。在下面的示例中,我在区间 [-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()
更改。但是,据我所知,这只能设置为静态颜色。
我想出的不令人满意的解决方案是定义一个函数,将我的 norm
函数应用于数组 mod 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])
输出:
问题:
是否有 better/built 方式 loop/wrap 颜色图而无需定义自定义函数,如底部子图所示?
一个想法可能是调整来自 tutorial 的自定义范数以获得循环范数:
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()