Matplotlib Симметричная логарифмическая цветовая карта не центрирована на нуле

Я столкнулся с проблемой, когда цветовая карта по умолчанию, SymLogNorm импортированная из matplotlib.colors, на самом деле не является симметричной для моих данных. Среднее значение и медиана моих данных выше нуля, но я хочу, чтобы нулевые значения отображались как белый цвет. SymLogNorm возвращает цветовую карту с центральным значением чуть выше нуля — незаметно, но определенно заметно.

Есть ли решение этой проблемы?

Это не самые лучшие вопросы и ответы, но этого достаточно, чтобы +1 компенсировал -1. Я думаю, вы могли бы предоставить более подробную информацию в своем вопросе с данными и изображениями, как в блоге Криса Уиллиса.

David Erickson 12.12.2020 04:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
645
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот мое исправление — оно по существу использует ручную линейную шкалу для областей, близких к центру, и использует логарифмическую шкалу для областей, расположенных дальше от центра. Вы указываете lin_thres и другие аргументы так же, как и для SymLogNorm.

class MidpointLogNorm(colors.SymLogNorm):
    """
    Normalise the colorbar so that diverging bars work there way either side from a prescribed midpoint value)
    e.g. im=ax1.imshow(array, norm=MidpointNormalize(midpoint=0.,vmin=-100, vmax=100))

    All arguments are the same as SymLogNorm, except for midpoint    
    """
    def __init__(self, lin_thres, lin_scale, midpoint=None, vmin=None, vmax=None):
        self.midpoint = midpoint
        self.lin_thres = lin_thres
        self.lin_scale = lin_scale
        #fraction of the cmap that the linear component occupies
        self.linear_proportion = (lin_scale / (lin_scale + 1)) * 0.5
        print(self.linear_proportion)

        colors.SymLogNorm.__init__(self, lin_thres, lin_scale, vmin, vmax)

    def __get_value__(self, v, log_val, clip=None):
        if v < -self.lin_thres or v > self.lin_thres:
            return log_val
        
        x = [-self.lin_thres, self.midpoint, self.lin_thres]
        y = [0.5 - self.linear_proportion, 0.5, 0.5 + self.linear_proportion]
        interpol = np.interp(v, x, y)
        return interpol

    def __call__(self, value, clip=None):
        log_val = colors.SymLogNorm.__call__(self, value)

        out = [0] * len(value)
        for i, v in enumerate(value):
            out[i] = self.__get_value__(v, log_val[i])

        return np.ma.masked_array(out)

Я черпал вдохновение вокруг середины отсюда: http://chris35wills.github.io/matplotlib_diverging_colorbar/

Ваш предыдущий ответ на самом деле не сработал для меня, так как средняя точка была «далеко» от исходной средней точки. Проблема в том, что в ваших лагорифмических значениях не учитывается средняя точка.

Я немного изменил ваш код и исправил эту проблему, создав 2 SymLogNorm. Оба центрированы посередине. Один начинается с vmin, а другой заканчивается на vmax (экстремумы заполняются по средней точке).

Если я беру значение v, я назначаю координаты цветовой полосы следующим образом:

  • vmin < v < midpoint — lin_thresh, поэтому используйте SymLogNorm, который начинается с vmin

  • midpoint - lin_thresh < v < midpoint + lin_thresh, поэтому используйте интерполяцию

  • midpoint + lin_thresh < v < vmax, поэтому используйте SymLogNorm, который заканчивается на vmax

    class MidpointLogNorm(colors.SymLogNorm):
      def __init__(self, lin_thres, lin_scale, midpoint=None, vmin=None, vmax=None):
          self.midpoint = midpoint
          self.lin_thres = lin_thres
          self.lin_scale = lin_scale
          #fraction of the cmap that the linear component occupies
          self.linear_proportion = (lin_scale / (lin_scale + 1)) * 0.5
          print(self.linear_proportion)
    
          # Create norm with vmin at 0 and midpoint at 0.5
          self.SymLogNorm1 = colors.SymLogNorm(lin_thres, lin_scale, vmin, 2*self.midpoint + np.abs(vmin))
          # Create norm with midpoint at 0.5 and vmax at 1
          self.SymLogNorm2 = colors.SymLogNorm(lin_thres, lin_scale, 2*self.midpoint - vmax, vmax)
          colors.SymLogNorm.__init__(self, lin_thres, lin_scale, vmin, vmax)
    
      def __get_value__(self, v, log_val1_i, log_val2_i, clip=None):
          v = np.array(v)
          x = [self.vmin, self.midpoint, self.vmax]
          y = [0., 0.5, 1.]
          interpol = np.interp(v, x, y)
          out = np.where(np.abs(v) < self.lin_thres, interpol, v)
          out = np.where(out > self.lin_thres, log_val2_i, out)
          out = np.where(out < self.lin_thres, log_val1_i, out)
          return np.ma.masked_array(out)
    
      def __call__(self, value, clip=None):
          log_val1 = self.SymLogNorm1(value)
          log_val2 = self.SymLogNorm2(value)
    
          out = [0] * len(value)
          for i, v in enumerate(value):
              out[i] = self.__get_value__(v, log_val1[i], log_val2[i])
          return np.ma.masked_array(out)
    

Другие вопросы по теме