更改现有Matplotlib pyplot的色彩Map表(在创建绘图后)?

l0oc07j2  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(159)

我正在编写一个模糊控制示例,它使用了skfuzzy库,它的visualization模块构建在Matplotlib之上。
通常,在构造完一个模糊变量后,使用必要的隶属函数(或者使用自动构造函数,给定要使用的语言变量的数量-3、5或7,或者提供一个自定义的语言变量列表),可以调用.view()方法,该方法返回隶属函数的图,该图使用默认的cmap。
这通常是好的,但在我的例子中,我构建了一个温度控制的例子,如果对于隶属函数的绘图,我可以使用从蓝色(冷)到红色(暖)的颜色梯度来表示各种温度(定性)变量,那就太好了。因此,我想将cmap改为'bwr'。
所以我需要设法解决图形或坐标轴的问题,并给予它一个新的cmap。在skfuzzy库中进行了一些挖掘之后,我找到了包含.view的FuzzyVariableVisualizer类()方法等,而不是直接使用.view在我创建的skfuzzy.control.先行对象上使用(它使用了.view().show(),因此不能访问底层的图形和轴),我首先将.Antecedent传递给FuzzyVariableVisualizer(),然后使用它的.view()方法,该方法返回图形和轴。
但是现在,我不知道如何为它设置新的cmap,不幸的是google搜索只得到了一个类似的结果(this),但它对我来说没有什么用处,而且Matplotlib对我来说太复杂了,我无法深入研究(而且会花太多时间)。
这里有一些代码来重现我所处的状态。有人有优雅的方法来解决这个问题吗?

import numpy as np
import matplotlib.pyplot as plt
import skfuzzy as fuzz
from skfuzzy import control as ctrl
from skfuzzy.control import visualization

room_temp = ctrl.Antecedent(np.arange(0, 11, 1), 'room temperature')
clothing = ctrl.Antecedent(np.arange(0, 11, 1), 'amount of clothing')
temp_control = ctrl.Consequent(np.arange(0, 11, 1), 'temperature control')

temp_qualitative_values = ['absolute zero',
                           'freezing',
                           'extremely cold',
                           'cold',
                           'chilly',
                           'OK',
                           'warm',
                           'hot',
                           'very hot',
                           'hot as hell',
                           'melting']

clothing.automf(3)
clothing.view()

temp_control.automf(5)
temp_control.view()

# I want to chage the cmap of the following figure
room_temp.automf(10, names=temp_qualitative_values)
room_temp_viz = visualization.FuzzyVariableVisualizer(room_temp)
fig, ax = room_temp_viz.view()

plt.show()

我尝试过(但没有成功):

plt.set_cmap('bwr')
plt.show()
knsnq2tg

knsnq2tg1#

以下是我最终找到解决方案的过程(感谢JohanC为我指明了正确的方向):
正如JohanC在他的评论中所指出的,skfuzzy的可视化模块在为单个隶属函数调用plot函数时并不使用颜色Map,而是使用matplotlib的颜色循环器。因此,调用循环器并给它一个自定义列表来使用,这是一个足够简单的解决方案。
首先,我必须进口一台腹透机:from cycler import cycler。然后使用JohanC的建议,可以使用linspace()对所需颜色Map表(在本例中为"RdYlBu")进行采样,以获得所需的颜色(在本例中为11种),并将它们传递给循环器:plt.rc('axes', prop_cycle=cycler(color=plt.get_cmap('RdYlBu')(np.linspace(0, 1, 11))))
编辑:在之前的迭代中,我尝试在色彩Map表上使用. color方法(正如JohanC在他的第一条评论中所建议的),但它返回了一个错误,因为"RdYlBu"是LinerSegmentedColormap("bwr"和"coolwarm"也是如此),而在matplotlib中,它们没有. color方法(因为它们动态地生成样本)。但是当然,linspace解决了这个问题。你可以使用ListedColormap(它们确实有. color方法),但是我在matplotlib色彩Map表参考文档中找不到任何东西来说明哪个色彩Map表属于哪个类。
或者,你也可以定义你自己的颜色列表,而不是从一个颜色Map表中采样颜色,就像我在最终版本中所做的那样。只需要提供必要数量的颜色作为列表(使用matplotlib使用的RGBA符号)。在我的例子中,我写了一个函数来生成一个渐变(根据需要从它中采样多少),给定一个开始和结束颜色。
下面是最终代码:

import numpy as np
import matplotlib.pyplot as plt
import skfuzzy as fuzz
from cycler import cycler
from skfuzzy import control as ctrl
from skfuzzy.control import visualization

def gradient_colour_list(start, end, steps):
    '''
    The function generates 'steps' amount of solid colours,
    sampled from a gradient between the 'start' and 'end' colours.
    'start' and 'end' are defined in RGBA tuples.
    '''
    r_step = (end[0] - start[0]) / (steps - 1)
    g_step = (end[1] - start[1]) / (steps - 1)
    b_step = (end[2] - start[2]) / (steps - 1)
    a_step = (end[3] - start[3]) / (steps - 1)

    gradient = []
    for i in range(steps):
        r = start[0] + (r_step * i)
        g = start[1] + (g_step * i)
        b = start[2] + (b_step * i)
        a = start[3] + (a_step * i)
        gradient.append((r, g, b, a))

    return gradient

room_temp = ctrl.Antecedent(np.arange(0, 11, 1), 'room temperature')
clothing = ctrl.Antecedent(np.arange(0, 11, 1), 'amount of clothing')
temp_control = ctrl.Consequent(np.arange(0, 11, 1), 'temperature control')

temp_qualitative_values = ['absolute zero',
                           'freezing',
                           'extremely cold',
                           'cold',
                           'chilly',
                           'OK',
                           'warm',
                           'hot',
                           'very hot',
                           'hot as hell',
                           'melting']

# Create a list of colours, for as many steps
# as the amount of membership functions, sampled
# from a gradient between blue and red, at 100% opacity.
colours = gradient_colour_list((0.0, 0.0, 1.0, 1.0),
                               (1.0, 0.4, 0.0, 1.0),
                               len(temp_qualitative_values))

clothing.automf(3)
clothing.view()

temp_control.automf(5)
temp_control.view()

# Tell the cycler to use the custom list of colours
plt.rc('axes', prop_cycle=cycler(color=colours))

# Or use a predefined matplotlib cmap (in which case
# the list of custom colours and the function are redundant):
# plt.rc('axes', prop_cycle=cycler(color=plt.get_cmap('RdYlBu')(np.linspace(0, 1, 11))))

# No more need to pass through the FuzzyVariableVisualizer separately 
room_temp.view()

plt.show()

相关问题