Как рассчитать логарифмический 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]
]
Чтобы рассчитать цвет каждой конкретной точки, я привожу её к нужному диапазону:
и рисую график (здесь и далее псевдокод):
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'
при известном x
и неизвестных z
, a
, b
, но как бы Кикимер ни старался, он не мог этого сделать.
Например, если сложить эти два уравнения, получится:
Убрать z
, a
, b
никак не получается. Интуиция подсказывает, что решение есть, но я его не вижу.
Ответы (2 шт):
Вам нужно потенцировать (взять экспоненту) первую колонку таблицы. Вот только диапазон 0..1
отобразится в 1..e
, а вам нужно этот 1..e
ещё линейно преобразовать в тот диапазон, который у вас после логарифмирования (то, что у вас на графике `0..147), т.е. выполнить для данного примера
x' = (exp(x)-1.0)*147.0 / (e-1.0)
Примените эту формулу ко всем 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) |