# Function that magnifies small changes and compresses large changes

I need a function (for a heatmap algorithm) that takes a percentage difference between two values, and returns a number between 0 and 1.

The output will be used in coloring parts of the screen. The output will be passed to an alpha channel.

The catch is, most of the time the percentage value I want to plot will be small and it will be hard to discern the difference between the colors.

That's why I want to magnify small values and compress the large ones.

The output should be something like this:

f(0) = 0

f(1) = 1

f(0.001) = 0.1

f(0.002) = 0.2

f(0.7) = 0.75

f(0.8) = 0.78

...

Do you see the pattern?

I've tried log, but I need the function to be defined at f(0). I've also tried x^a where a < 1, but in order to get the magnification I need I need to use a << 1 and that makes all the output so small it can't be discerned or the resolution is so small that the graphics assume it's the same color.

-
Well, the $\log$ function and the power law are the usual suspects for this sort of thing. So if you want something different that works better for your data, it would help if you told us a little more about just how big or small these numbers that you're dealing with can be. – Rahul Jun 15 '12 at 1:21
Another nice function to experiment with is $arctan(x)$. For example, if the region to be magnified is centred around $h$, try $arctan((x-h)*k)/\pi+1/2$ for different values of $k$. – Théophile Jun 15 '12 at 1:52
Both answers suggested so far are based on $f(x)=g(ax)/g(a)$ for some nondecreasing function $g$ such that $g(0)=0$, with $a\gt0$. Rick uses $g(t)=t/(1+t)$ and E.O. uses $g(t)=\log(1+t)$. – Did Jun 15 '12 at 7:14
I second Rahul's request for more information. For example: do you want the magnification ratio to grow without bound, as the numbers approach zero, or do you want to set a maximum, so that e.g. $f(0.002)$ is roughly twice as large as $f(0.001)$? Same at the other end: do you also want to set a lower bound to the compression ratio? Is it ok, if everything above, say $0.8$ is mapped to the same color, so $f(x)>255/256$ for all $x>0.8$ (assuming 24bit true color or 256 level greyscale)? Or what would you use there in place of $0.8$? – Jyrki Lahtonen Jun 15 '12 at 7:19
For example the average $$f(x)=\frac{x^a+x}2$$ for some $a$ between $0$ and $1$ will magnify the lower end, but at the same time make sure that the compression ratio is $2:1$ at worst. However, this is non-linear for small inputs, so you won't have $$f(2\delta)\approx 2 f(\delta)$$ for small values of $\delta$. With this function the magnification ratio grows without bound as $\delta\to0$. – Jyrki Lahtonen Jun 15 '12 at 7:22

Any function that goes through $(0,0)$ and $(1,1)$ passing above the diagonal satisfies the basic shape you are looking for. If you also want the function to be symmetric, perhaps the simplest choice is a hyperbolic segment such as

$f(x)={{(n+1) x}\over{n x+1}}$ where $n>0$

plotted here for $n=10,5,$ and $1$:

As a result, by choosing $n$ you can select the amount compression/magnification.

-
+1: This is a simple way of controlling the maximum magnification ($1:(n+1)$) as well as the minimum compression ($(n+1):1$). Let's wait for the OP to comment, whether this meets the requirements. – Jyrki Lahtonen Jun 15 '12 at 7:32

Picking up on your idea of using $\log$, since you want $f(0)=0$ and $f(1)=1$ the function must be of the form $$f(x)=\frac{1}{\log\left(\frac{b-1}{b}\right)}\log\left(\frac{b-x}{b}\right), b\in(-\infty,0)$$ Depending on how much emphasis you want to put on the smaller numbers you can change the value of $b$. If you want a lot of emphasis on the smaller numbers you want $b$ to be close to 0. Here is an animation to illustrate what I mean:

$$b\in[-5,-0.001]$$

If you want a lot of emphasis on the smaller numbers, this is an example when $b=-0.005$:

Note that in the example you give, you want $f(0.8)=0.78$ and $f(1)=1$. That would mean that you would need to emphasize numbers when to $x$ is close to $1$. This would possibly defeat the purpose of your function. For a function to do what you wish $f(x)\ge x, \forall x\in[0,1]$

-