NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

## All the Perl that's Practical to Extract and Report

#### Ovid (2709)

Ovid
(email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

### Journal of Ovid (2709)

Wednesday September 03, 2008
09:49 AM

### Heatmap Ranges

[ #37337 ]

I'd like to take a series of values and convert them to numbers between 0 and 255, but on a logarithmic scale. My math studies were a long time ago and for the life of me I can't remember how to do this. I'm hoping to take a 2D table of values and project them onto an HTML table in a 'heatmap' fashion.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.

Full
Abbreviated
Hidden
• #### scale linear then log(Score:0)

Maybe I'm misunderstanding, but I think you want to first scale logarithmically: log(\$val) if it's log base 'e'. Then linearly: so find the max value in the logged sequence, then multiply each value by 255 and divide by the max. Here's a kind of generic script, if I got it right:

#!/usr/bin/perl
# convert @VALS to a log scale base \$LOG_BASE
# and scaled linearly to \$SCALE_MAX

use strict;
use warnings;
use List::Util qw(max);

my \$SCALE_MAX = 1000;
my \$LOG_BASE = 10;
my @VALS = (1, 10, 100, 1000);

main();

sub main

• #### Re:(Score:1)

Need to scale linearly first in the case the minimum value is less than 1 before taking logs. (Also, \$SCALE_MAX should be 255)

Instead, if you simplify the mathematics (and you know the minimum and maximum values), calculate the logarithmic 'scaling factor'

\$scale = log( \$maximum ) / 255;

Then apply logarithmic scaling to each data element

map { int( log( \$_ - \$minimum + 1 ) / \$scale ) } @VALS;

So that the minimum value scales to zero, maximum value scales to 255. Adjust the linear scale in the log calculatio

• #### Log2 for heatmap, fun with pack(Score:1)

i think both of the prior comments are on target.

If you have such quantities of data that scaling and calling log repeatedly is a problem - and only if - there are old integer bitbang routines for log2 that could be done with XS or Inline::C or PDL.

Or you could (ab)use Perl 5.10 pack() to grab the floating point representation's exponent

Note that 256 buckets is a lot, hi res, for loglinear data unless it already was floating point or Math::BigFloat - as log2(MAXLONG) - log2(1) 256 or 8 bits -- it'

--
Bill
# I had a sig when sigs were cool
use Sig;