Как рассчитать логарифмический colormap?

Требуется раскрасить точки логарифмического графика, но так, как будто они не логарифмические.

Пусть некоторая величина z, отображаемая на графике, может принимать значения от a до b. Я составил colormap - функцию, которая рассчитывает и возвращает цвет в зависимости от переданного ей числового значения в диапазоне от 0 до 1. Допустим, так:

table = [
    # x  R     G     B
    [0, 0.01, 0.043, 1],
    [0.2, 0.641, 0.164, 0.725],
    [0.3, 0.988, 0.051, 0.11],
    [0.5, 1, 0.975, 0.5],
    [0.8, 1, 1, 1],
    [1, 1, 1, 1]
]

Чтобы рассчитать цвет каждой конкретной точки, я привожу её к нужному диапазону:

x=\frac{z-a}{b-a}

и рисую график (здесь и далее псевдокод):

plot(values=z, colormap=colormap) # значения x для цвета рассчитываются внутри построителя

Все точки раскрашиваются правильно:

Обычный график

Теперь я логарифмирую величину z и рисую график:

plot(values=ln(z), colormap=colormap)

График рисуется правильно, однако раскраску хотелось бы сделать такой, какой она была бы без применения логарифмирования.

Логарифмический график

Поскольку цвета рассчитывает построитель, я могу изменить только colormap. Поэтому нужно каким-то образом изменить значения первого столбца colormap.

Величина z'=ln(z) может принимать значения от a'=ln(a) до b'=ln(b). Получаем, что:

x'=\frac{ln(z)-ln(a)}{ln(b)}

Далее я приказал своему домовому эльфу разобраться, как выразить x' при известном x и неизвестных z, a, b, но как бы Кикимер ни старался, он не мог этого сделать. Например, если сложить эти два уравнения, получится:

x'\operatorname{=}\frac{\left( b\operatorname{-}a\right)  \log{(z)}\operatorname{+}\left( \log{(b)}\operatorname{-}\log{(a)}\right)  z\operatorname{+}\left( \left( a\operatorname{-}b\right)  \log{(b)}\operatorname{+}\log{(a)} b\operatorname{-}a \log{(a)}\right)  x\operatorname{-}a \log{(b)}\operatorname{-}\log{(a)} b\operatorname{+}2 a \log{(a)}}{\left( b\operatorname{-}a\right)  \log{(b)}\operatorname{-}\log{(a)} b\operatorname{+}a \log{(a)}}

Убрать z, a, b никак не получается. Интуиция подсказывает, что решение есть, но я его не вижу.


Ответы (2 шт):

Автор решения: MBo

Вам нужно потенцировать (взять экспоненту) первую колонку таблицы. Вот только диапазон 0..1 отобразится в 1..e, а вам нужно этот 1..e ещё линейно преобразовать в тот диапазон, который у вас после логарифмирования (то, что у вас на графике `0..147), т.е. выполнить для данного примера

x' = (exp(x)-1.0)*147.0 / (e-1.0)
→ Ссылка
Автор решения: Stanislav Volodarskiy

Примените эту формулу ко всем x из таблицы цветов. Без a и b обойтись невозможно, отображение (логарифм) не линейная функция, границы существенно влияют на результат:

x' = (ln((b - a)x + a) - ln a)/(ln b - ln a)

Или так:

x' = ln((b/a - 1)x + 1)/ln b/a

Вывод:

что как
Приведение z к x x = (z - a)/(b - a)
z = (b - a)x + a
Диапазоны x и z x ∈ [0, 1]
z ∈ [a, b]
Вводим логарифмы z' = ln z
z' ∈ [ln a, ln b]
Вводим a', b' a' = ln a
b' = ln b
z' ∈ [a', b']
Штрихованное приведение x' = (z' - a')/(b' - a')
Подставляем штрихи x' = (ln z - ln a)/(ln b - ln a)
Подставляем z x' = (ln((b - a)x + a) - ln a)/(ln b - ln a)
→ Ссылка