Matplotilb-如何使用对数刻度设置线图的颜色条 [英] Matplotilb - How to set colorbar for line plot with log scale

查看:65
本文介绍了Matplotilb-如何使用对数刻度设置线图的颜色条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将颜色条添加到与幂律相对应的多条线的图中时遇到问题.

要为非图像图创建颜色条,我添加了一个虚拟图(来自此处的答案:

通过与图例进行比较,您可以看到刻度值与实际颜色不匹配.例如,128 在颜色图中显示为绿色,而在图例中显示为红色.

实际结果应该是线性颜色的彩条.在颜色条上有规律的间隔(对应于不规则的时间间隔......).当然,还要为刻度值正确设置颜色.

(最终该图包含许多图(len(time_vector) ~ 100),我减少了图的数量以说明并能够显示图例.)

澄清一下,这就是我想要的结果.

解决方案

最重要的原理是使线图中的颜色与 ScalarMappable 保持同步.这意味着,线条的颜色不应取自独立的颜色列表,而应取自相同的颜色图并使用与要显示的颜色条相同的标准化.

然后一个主要问题是决定如何处理 0,它不能成为对数归一化的一部分.以下是一种变通方法,假设使用 SymLogNorm 的线性标度介于 0 和 2 之间,上面是对数标度.

 将matplotlib导入为mpl导入matplotlib.pyplot作为plt将numpy导入为np"""创建数据"""时间向量 = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]幅度= [t ** 2 * np.exp(-t * np.power(np.linspace(-0.5,0.5,100),2))对于time_vector中的t]"获取数据的非零最小值""数据 = np.concatenate(amplitudes).ravel()data_min = np.min(data[np.nonzero(data)])"创建K空间数据""k_vector = np.linspace(0,1,100)"""绘图"""cmap = plt.cm.get_cmap("jet")范数 = mpl.colors.SymLogNorm(2, vmin=time_vector[0], vmax=time_vector[-1])sm = mpl.cm.ScalarMappable(范数=范数,cmap=cmap)sm.set_array([])对于我在范围内(len(time_vector)):plt.plot(k_vector, 振幅[i], color=cmap(norm(time_vector[i])), label=time_vector[i])#c = np.arange(1,number_of_plots +1)plt.xlabel('频率')plt.ylabel('振幅')plt.yscale('symlog', linthreshy=data_min)plt.xscale('log')plt.legend(loc = 3)cbar = plt.colorbar(sm,ticks = time_vector,format = mpl.ticker.ScalarFormatter(),收缩=1.0,分数=0.1,填充=0)plt.show()

I'm having a problem adding a colorbar to a plot of many lines corresponding to a power-law.

To create the color-bar for a non-image plot, I added a dummy plot (from answers here: Matplotlib - add colorbar to a sequence of line plots).

To colorbar ticks do not correspond to the colors of the plot.

I have tried changing the norm of the colorbar, and I can fine-tune it to be semy accurate for a particular case, but I can't do that generally.

def plot_loglog_gauss():
    from matplotlib import cm as color_map
    import matplotlib as mpl

    """Creating the data"""
    time_vector = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
    amplitudes = [t ** 2 * np.exp(-t * np.power(np.linspace(-0.5, 0.5, 100), 2)) for t in time_vector]

    """Getting the non-zero minimum of the data"""
    data = np.concatenate(amplitudes).ravel()
    data_min = np.min(data[np.nonzero(data)])

    """Creating K-space data"""
    k_vector = np.linspace(0,1,100)

    """Plotting"""
    number_of_plots = len(time_vector)
    color_map_name = 'jet'
    my_map = color_map.get_cmap(color_map_name)
    colors = my_map(np.linspace(0, 1, number_of_plots, endpoint=True))

    # plt.figure()
    # dummy_plot = plt.contourf([[0, 0], [0, 0]], time_vector, cmap=my_map)
    # plt.clf()

    norm = mpl.colors.Normalize(vmin=time_vector[0], vmax=time_vector[-1])
    cmap = mpl.cm.ScalarMappable(norm=norm, cmap=color_map_name)
    cmap.set_array([])


    for i in range(number_of_plots):
        plt.plot(k_vector, amplitudes[i], color=colors[i], label=time_vector[i])

    c = np.arange(1, number_of_plots + 1)
    plt.xlabel('Frequency')
    plt.ylabel('Amplitude')
    plt.yscale('symlog', linthreshy=data_min)
    plt.xscale('log')
    plt.legend(loc=3)

    ticks = time_vector
    plt.colorbar(cmap, ticks=ticks, shrink=1.0, fraction=0.1, pad=0)

    plt.show()

By comparing with the legend you see the ticks values don't match the actual colors. For example, 128 is shown in green in the colormap while red in the legend.

The actual result should be a linear-color colorbar. with ticks at regular intervals on the colorbar (corresponding to irregular time intervals...). And of course correct color for value of tick.

(Eventually the plot contains many plots (len(time_vector) ~ 100), I lowered the number of plots to illustrate and to be able to show the legend.)

To clarify, this is what I want the result to look like.

解决方案

The most important principle is to keep the colors from the line plots and the ScalarMappable in sync. This means, the color of the line should not be taken from an independent list of colors, but rather from the same colormap and using the same normalization as the colorbar to be shown.

One major problem is then to decide what to do with 0 which cannot be part of a loagrithmic normalization. The following is a workaround assuming a linear scale between 0 and 2, and a log scale above, using a SymLogNorm.

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

"""Creating the data"""
time_vector = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
amplitudes = [t ** 2 * np.exp(-t * np.power(np.linspace(-0.5, 0.5, 100), 2)) for t in time_vector]

"""Getting the non-zero minimum of the data"""
data = np.concatenate(amplitudes).ravel()
data_min = np.min(data[np.nonzero(data)])

"""Creating K-space data"""
k_vector = np.linspace(0,1,100)

"""Plotting"""
cmap = plt.cm.get_cmap("jet")
norm = mpl.colors.SymLogNorm(2, vmin=time_vector[0], vmax=time_vector[-1])

sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])

for i in range(len(time_vector)):
    plt.plot(k_vector, amplitudes[i], color=cmap(norm(time_vector[i])), label=time_vector[i])

#c = np.arange(1, number_of_plots + 1)
plt.xlabel('Frequency')
plt.ylabel('Amplitude')
plt.yscale('symlog', linthreshy=data_min)
plt.xscale('log')
plt.legend(loc=3)

cbar = plt.colorbar(sm, ticks=time_vector, format=mpl.ticker.ScalarFormatter(), 
                    shrink=1.0, fraction=0.1, pad=0)

plt.show()

这篇关于Matplotilb-如何使用对数刻度设置线图的颜色条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆