Matplotilb - Как установить цветовую шкалу для линейного графика с масштабом журнала - PullRequest
0 голосов
/ 04 февраля 2019

У меня проблема с добавлением цветовой шкалы к графику из многих линий, соответствующих степенному закону.

Чтобы создать цветную полосу для графика без изображения, я добавил фиктивный график (из ответов здесь: Matplotlib - добавьте цветную полосу в последовательность линейных графиков ).

Чтобы метки цветовой шкалы не соответствовали цветам графика.

Я попытался изменить норму цветовой шкалы, и я могу настроить ее так, чтобы она была почти точной для конкретного случая., но я не могу сделать это вообще.

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()

Plot generated

При сравнении с легендой вы видите, что значения тиков не соответствуют фактическим цветам.Например, 128 обозначено зеленым цветом в цветовой карте, а красное - в легенде.

Фактическим результатом должна быть линейная цветовая шкала.с галочками через регулярные интервалы на цветовой панели (соответствующие нерегулярным временным интервалам ...).И, конечно, правильный цвет для значения галочки.

(В конечном итоге график содержит много графиков (len (time_vector) ~ 100), я уменьшил количество графиков, чтобы проиллюстрировать и показать легенду.)

Чтобы уточнить, этоэто то, что я хочу, чтобы результат выглядел.

Plot wanted

1 Ответ

0 голосов
/ 04 февраля 2019

Самый важный принцип - синхронизировать цвета линий и графиков ScalarMappable.Это означает, что цвет линии должен быть взят не из независимого списка цветов, а из той же карты цветов и с использованием той же нормализации, что и отображаемая цветовая полоса.

Одна из главных проблем состоит в том, чтобы решить, что делать с 0, который не может быть частью логической нормализации.Ниже представлен обходной путь, предполагающий линейную шкалу от 0 до 2 и логарифмическую шкалу выше, используя 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()

enter image description here

...