本文介绍了将配色方案标签更改为对数比例,而无需更改matplotlib中的轴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是python编程的新手.我有一个脚本,可以使用matplotlib绘制热图. X轴值的范围=(-180至+180),Y轴值的范围=(0至180). 2D热图根据在x-y图中指定区域中出现的点数(由"bin"定义(请参见下文))为Rainbow中的区域着色.在这种情况下,x = values_Rot和y = values_Tilt(有关代码,请参见下文).

I am quite new to python programming. I have a script with me that plots out a heat map using matplotlib. Range of X-axis value = (-180 to +180) and Y-axis value =(0 to 180). The 2D heatmap colours areas in Rainbow according to the number of points occuring in a specified area in the x-y graph (defined by the 'bin' (see below)).In this case, x = values_Rot and y = values_Tilt (see below for code).

到目前为止,该脚本以线性比例为2D热图着色.如何更改此脚本,使其在对数刻度上为热图着色?请注意,我只想将热图着色方案更改为对数比例,即仅更改指定区域中的点数. x和y轴的线性比例保持不变(而不是对数比例).代码的一部分在这里.

As of now, this script colours the 2D-heatmap in the linear scale. How do I change this script such that it colours the heatmap in the log scale? Please note that I only want to change the heatmap colouring scheme to log-scale, i.e. only the number of points in a specified area. The x and y-axis stay the same in linear scale (not in logscale).A portion of the code is here.

rot_number = get_header_number(headers, AngleRot)
tilt_number = get_header_number(headers, AngleTilt)
psi_number = get_header_number(headers, AnglePsi)

values_Rot = []
values_Tilt = []
values_Psi = []

for line in data:
    try:
        values_Rot.append(float(line.split()[rot_number]))
        values_Tilt.append(float(line.split()[tilt_number]))
        values_Psi.append(float(line.split()[psi_number]))

    except:
        print ('This line didnt work, it may just be a blank space. The line is:' + line)

# Change the values here if you want to plot something else, such as psi.
# You can also change how the data is binned here.
plt.hist2d(values_Rot, values_Tilt, bins=25,)
plt.colorbar()
plt.show()

plt.savefig('name_of_output.png')

推荐答案

您可以使用 LogNorm 表示颜色,请使用plt.hist2d(...., norm=LogNorm()).这是一个比较.

You can use a LogNorm for the colors, using plt.hist2d(...., norm=LogNorm()). Here is a comparison.

要使基数为2,开发人员建议添加基数到 LogLocator LogFormatter .因为在这种情况下,LogFormatter似乎用一个小数点(.0)来写数字,所以StrMethodFormatter可以用来显示不带小数点的数字.视数字范围而定,有时小刻度线(较短的标记线)也会得到一个字符串,可以通过为小彩条刻度线分配NullFormatter来抑制这种情况.

To have the ticks in base 2, the developers suggest adding the base to the LogLocator and the LogFormatter. As in this case the LogFormatter seems to write the numbers with one decimal (.0), a StrMethodFormatter can be used to show the number without decimals. Depending on the range of numbers, sometimes the minor ticks (shorter marker lines) also get a string, which can be suppressed assigning a NullFormatter for the minor colorbar ticks.

请注意,基数2和基数10定义了完全相同的颜色转换.刻度的位置和标签不同.下面的示例创建了两个颜色条,以演示不同的外观.

Note that base 2 and base 10 define exactly the same color transformation. The position and the labels of the ticks are different. The example below creates two colorbars to demonstrate the different look.

import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter, StrMethodFormatter, LogLocator
from matplotlib.colors import LogNorm
import numpy as np
from copy import copy

# create some toy data for a standalone example
values_Rot = np.random.randn(100, 10).cumsum(axis=1).ravel()
values_Tilt = np.random.randn(100, 10).cumsum(axis=1).ravel()

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 4))

cmap = copy(plt.get_cmap('hot'))
cmap.set_bad(cmap(0))

_, _, _, img1 = ax1.hist2d(values_Rot, values_Tilt, bins=40, cmap='hot')
ax1.set_title('Linear norm for the colors')
fig.colorbar(img1, ax=ax1)
_, _, _, img2 = ax2.hist2d(values_Rot, values_Tilt, bins=40, cmap=cmap, norm=LogNorm())
ax2.set_title('Logarithmic norm for the colors')
fig.colorbar(img2, ax=ax2)  # default log 10 colorbar
cbar2 = fig.colorbar(img2, ax=ax2)  # log 2 colorbar
cbar2.ax.yaxis.set_major_locator(LogLocator(base=2))
cbar2.ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.0f}'))
cbar2.ax.yaxis.set_minor_formatter(NullFormatter())
plt.show()

请注意,log(0)为负无穷大.因此,左图(最暗的颜色)中的零值在对数颜色值的图上保留为空(白色背景).如果您只想为这些零使用最低的颜色,则需要设置不良"颜色.为了不更改标准颜色图,最新的matplotlib版本希望您首先复制颜色图.

Note that log(0) is minus infinity. Therefore, the zero values in the left plot (darkest color) are left empty (white background) on the plot with the logarithmic color values. If you just want to use the lowest color for these zeros, you need to set a 'bad' color. In order not the change a standard colormap, the latest matplotlib versions wants you to first make a copy of the colormap.

PS:调用plt.savefig()时,在plt.show()之前调用它很重要,因为plt.show()会清除绘图.

PS: When calling plt.savefig() it is important to call it before plt.show() because plt.show() clears the plot.

此外,请尝试避免使用喷射"色图,因为它具有明亮的黄色区域,该区域不是极端.它可能看起来不错,但可能会产生误导. 此博客文章包含一个详尽的解释. matplotlib文档包含可用色图的概述.

Also, try to avoid the 'jet' colormap, as it has a bright yellow region which is not at the extreme. It may look nice, but can be very misleading. This blog article contains a thorough explanation. The matplotlib documentation contains an overview of available colormaps.

请注意,要比较两个图,需要使用plt.subplots(),而不是plt.hist2d,需要ax.hist2d(请参阅).同样,对于两个颜色条,需要指定颜色条所基于的元素作为参数.对您的代码进行的最小更改如下所示:

Note that to compare two plots, plt.subplots() needs to be used, and instead of plt.hist2d, ax.hist2d is needed (see this post). Also, with two colorbars, the elements on which the colorbars are based need to be given as parameter. A minimal change to your code would look like:

from matplotlib.ticker import NullFormatter, StrMethodFormatter, LogLocator
from matplotlib.colors import LogNorm
from matplotlib import pyplot as plt
from copy import copy

# ...
# reading the data as before

cmap = copy(plt.get_cmap('magma'))
cmap.set_bad(cmap(0))
plt.hist2d(values_Rot, values_Tilt, bins=25, cmap=cmap, norm=LogNorm())
cbar = plt.colorbar()
cbar.ax.yaxis.set_major_locator(LogLocator(base=2))
cbar.ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.0f}'))
cbar.ax.yaxis.set_minor_formatter(NullFormatter())

plt.savefig('name_of_output.png') # needs to be called prior to plt.show()
plt.show()

这篇关于将配色方案标签更改为对数比例,而无需更改matplotlib中的轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!