我当前正在使用Rectangle
来尝试以每个矩形单色填充曲线下的区域。但是,矩形的宽度大于1像素。我想绘制1像素宽的线,以免它们重叠。目前,曲线下方的垂直矩形水平重叠1或2个像素。
def rect(x,y,w,h,c):
ax = plt.gca()
polygon = plt.Rectangle((x,y),w,h,color=c, antialiased=False)
ax.add_patch(polygon)
def mask_fill(X,Y, fa, cmap='Set1'):
plt.plot(X,Y,lw=0)
plt.xlim([X[0], X[-1]])
plt.ylim([0, MAX])
dx = X[1]-X[0]
for n, (x,y, f) in enumerate(zip(X,Y, fa)):
color = cmap(f)
rect(x,0,dx,y,color)
如果我使用下面的代码画线,则重叠减少了,但仍然有重叠
def vlines(x_pos, y1, y2, c):
plt.vlines(x_pos, ymin=y1, ymax=y2, color=c)
def draw_lines(X, Y, trend_len, cmap='Blues_r']):
plt.plot(X, Y, lw=0)
plt.xlim([X[0], X[-1]])
plt.ylim([0, MAX])
dx = X[1] - X[0]
ydeltas = y_trend(Y, trend_len)
for n, (x, y, yd) in enumerate(zip(X, Y, ydeltas)):
color = cmap(y / MAX)
vlines(x, y1=0, y2=y, c=color)
将参数值的前3个迭代打印到vlines中,我们可以看到x_pos递增了1-但是红线与下面的图像清晰地重叠了第一条蓝线(NB优先(LHS)蓝线是1像素宽) ):
x_pos: 0, y1: 0, y2: 143.51, c: (0.7816378316032295, 0.8622683583237216, 0.9389773164167627, 1.0)
x_pos: 1, y1: 0, y2: 112.79092811646952, c: (0.9872049211841599, 0.5313341022683583, 0.405843906189927, 1.0)
x_pos: 2, y1: 0, y2: 123.53185623293905, c: (0.9882352941176471, 0.6059669357939254, 0.4853671664744329, 1.0)
样本数据:
47.8668447889, 1
78.5668447889, 1
65.9768447889, 1
139.658525932, 2
123.749454049, 2
116.660382165, 3
127.771310282, 3
114.792238398, 3
上面的第一列对应于系列的y值(x值只是值的数量,从0开始计数) 第二列对应于该类。
我正在生成两个图像:
一个具有每个类别的唯一值(0-6),每个具有不同的颜色(7个唯一的颜色),并且颜色填充到y值将被用作下面数据图像的遮罩。
第二张图片(显示的示例)针对不同的类别值(例如0 = Blues_r,1 = Reds_r等)使用不同的颜色图,并且颜色的强度由y的值给出。
用于计算颜色的代码很好,但是我只是无法获得matplotlib来绘制竖线像素宽度的垂直线。
答案 0 :(得分:1)
由于您的目标不是创建交互式图形,并且您正在尝试操纵像素列,因此可以使用numpy而不是matplotlib来生成结果。
这是一个函数,它将接受y
和category
数组,并使用指定的y
创建宽度为height
长的图像。颜色缩放与解决方案类似,y
除以最大值。
from matplotlib import pyplot as plt
import numpy as np
def draw_lines(y, category, filename, cmap='Set1', max=None, height=None):
y = np.asanyarray(y).ravel()
category = np.asanyarray(category).ravel()
assert y.size == category.size
if max is None:
max = y.max()
if height is None:
height = int(np.ceil(max))
if isinstance(cmap, str):
cmap = plt.get_cmap(cmap)
colors = cmap(category)
colors[:, 3] = y / max
colors = (255 * colors).astype(np.uint8)
output = np.repeat(colors[None, ...], height, axis=0)
heights = np.round(height * (y / max))
mask = np.arange(height)[:, None] >= heights
mask = np.broadcast_to(mask[::-1, :, None], output.shape)
output[mask] = 0
plt.imsave(filename, output)
return output
第一部分只是设置输入值。第二部分获取颜色值。调用具有n
值数组的颜色图将返回(n, 4)
范围内的[0, 1.0]
颜色数组。 colors[:, 3] = y / max
设置与高度成比例的Alpha通道。然后将颜色垂直涂抹到所需的height
。根据{{3}}提出的方法,最后一部分创建一个掩码,将每列的顶部设置为零。
此版本使用透明度关闭颜色并修剪形状。如果您愿意缩放颜色而不是调整透明度,则可以在白色背景上执行相同的操作:
def draw_lines_b(y, category, filename, cmap='Set1', max=None, height=None):
y = np.asanyarray(y).ravel()
category = np.asanyarray(category).ravel()
assert y.size == category.size
if max is None:
max = y.max()
if height is None:
height = int(np.ceil(max))
if isinstance(cmap, str):
cmap = plt.get_cmap(cmap)
colors = cmap(category)
colors[..., :3] *= (y / max)[..., None]
colors = (255 * colors).astype(np.uint8)
output = np.repeat(colors[None, ...], height, axis=0)
heights = np.round(height * (y / max))
mask = np.arange(height)[:, None] >= heights
mask = np.broadcast_to(mask[::-1, :, None], output.shape)
output[mask] = 255
plt.imsave(filename, output)
return output
在两种情况下,正如您可以想象的那样,matplotlib并非绝对必要。您可以定义自己的颜色列表,并使用更合适的库(例如PIL)来保存图像。