ANSI-Heatmap

 view release on metacpan or  search on metacpan

README.pod  view on Meta::CPAN

=head1 DESCRIPTION

Produce cutting-edge ANSI heatmaps using 256 colours and weird Unicode
characters! Perfect for 3D (2D + intensity) data.

=head1 METHODS

=head2 new ( [ARGS] )

C<ARGS> may be a hash or hashref accepting the following keys, which
also have getter/setter methods:

=over 4

=item min_x, max_x ( INT )

Specify the smallest and largest X-axis value to include. If not
provided, defaults to the smallest/largest values passed to C<set>
or C<inc>. Can be used to crop the map or ensure it keeps a fixed
size even if some values are unset.

To make automatic again, set to C<undef>.

=item min_y, max_y ( INT )

Ditto for the Y-axis.

=item min_z, max_z ( FLOAT )

Ditto for intensity; useful for keeping a fixed intensity across
multiple heatmaps.

README.pod  view on Meta::CPAN


=item width, height ( INT )

Specify the width/height of the map in characters. Defaults to
using the min_I<axis> and max_I<axis> values to determine the
width/height.

=item interpolate ( BOOL )

If width/height is not a nice multiple of the input data and
this flag is set, perform bilinear interpolation (instead of
nearest neighbour). This is a trade off; interpolated data is
blurrier, but retains a linear relationship with the original
data. Off by default.

=back

=head2 set ( X, Y, Z )

Set the heatmap intensity for the given X and Y co-ordinate.

Currently, only integer values for X and Y are supported.

=head2 get ( X, Y )

Return the heatmap intensity for the given X and Y co-ordinate,
or 0 if unset.

=head2 inc ( X, Y )

Increase the intensity at the given co-ordinate by 1.

=head2 to_string

Return a string containing the ANSI heatmap. If C<half> is set,
this string contains wide characters, so you may need to:

 binmode STDOUT, ':utf8';

or

 use open OUT => ':utf8';

before printing anything (in this case) to STDOUT.

examples/boxes.pl  view on Meta::CPAN

            max_x => $x,
            max_y => $y,
            swatch => 'grayscale',
        );

        my @white = (
            (map { [1,$_], [$x,$_] } (1..$y)),
            (map { [$_, 1], [$_, $y] } (1..$x)),
        );
        for my $c (@white) {
            $map->set(@$c, 100);
        }
        print "$x x $y\n";
        print $map, "\n";
    }
}

examples/gray.pl  view on Meta::CPAN

my $map = ANSI::Heatmap->new(
    half => 1,
    min_x => 1,
    min_y => 1,
    max_x => 10,
    max_y => 10,
    swatch => 'grayscale',
 );
 for my $x (1..10) {
    for my $y (1..10) {
        $map->set($x, $y, $x * $y);
    }
 }
 print $map->to_string;  # explicit

examples/interp.pl  view on Meta::CPAN

use ANSI::Heatmap;

binmode STDOUT, ':utf8';

my $map = ANSI::Heatmap->new(
    half => 1,
    swatch => 'grayscale',
);
for my $x (0..5) {
   for my $y (0..5) {
       $map->set($x, $y, ($x % 2 == $y % 2));
   }
}

for my $wh ([3,3], [3,5], [5,5], [6,6], [12,12], [15,16], [10,20]) {
    my ($w, $h) = @$wh;
    $map->width($w);
    $map->height($h);
    $map->interpolate(0);
    print "${w}x${h}\n";
    print $map;

examples/smallinterp.pl  view on Meta::CPAN

binmode STDOUT, ':utf8';

my $map = ANSI::Heatmap->new(
    half => 1,
    swatch => 'grayscale',
);
for my $x (0..19) {
    for my $y (0..19) {
        my $sc = 1 + ($x >= 10) + ($y >= 10) * 2;
        my $z = (($x/$sc) % 2 == ($y/$sc) % 2);
        $map->set($x, $y, $z);
    }
}
print "$map\n";
$map->width(15);
$map->height(15);
print "$map\n";
$map->interpolate(1);
print "$map\n";

lib/ANSI/Heatmap.pm  view on Meta::CPAN

        croak "Invalid constructor argument(s) " . join(', ', sort keys %args);
    }
    return $self;
}

sub swatch_names {
    my $self = shift;
    return (sort keys %SWATCHES);
}

sub set {
    my ($self, $x, $y, $z) = @_;
    $self->{map}[$y][$x] = $z;
    $self->_set_minmax(x => $x, y => $y, z => $z);
}

sub get {
    my ($self, $x, $y) = @_;
    return $self->{map}[$y][$x] || 0;
}

sub inc {
    my ($self, $x, $y) = @_;
    $self->set( $x, $y, $self->get($x, $y) + 1 );
}

sub swatch {
    my $self = shift;
    if (@_) {
        my $sw = shift;
        @_ == 0 or croak "swatch: excess arguments";
        if (ref $sw) {
            ref $sw eq 'ARRAY' or croak "swatch: invalid argument, should be string or arrayref";
            @$sw > 0 or croak "swatch: swatch is empty";

lib/ANSI/Heatmap.pm  view on Meta::CPAN

        my ($fy, $by) = modf($y);
        my @p = map { $get->($bx + $_->[0], $by + $_->[1]) } ([0,0],[0,1],[1,0],[1,1]);

        my $y1 = $p[0] + ($p[1] - $p[0]) * $fy;
        my $y2 = $p[2] + ($p[3] - $p[2]) * $fy;
        my $z = $y1 + ($y2 - $y1) * $fx;
        return $z;
    };
}

sub _set_minmax {
    my ($self, %vals) = @_;
    my $mm = $self->{minmax};
    while (my ($k, $v) = each %vals) {
        if (!defined $mm->{"min_$k"}) {
            $mm->{"min_$k"} = $mm->{"max_$k"} = $v;
        }
        else {
            $mm->{"min_$k"} = min($mm->{"min_$k"}, $v);
            $mm->{"max_$k"} = max($mm->{"max_$k"}, $v);
        }

lib/ANSI/Heatmap.pm  view on Meta::CPAN

=head1 DESCRIPTION

Produce cutting-edge ANSI heatmaps using 256 colours and weird Unicode
characters! Perfect for 3D (2D + intensity) data.

=head1 METHODS

=head2 new ( [ARGS] )

C<ARGS> may be a hash or hashref accepting the following keys, which
also have getter/setter methods:

=over 4

=item min_x, max_x ( INT )

Specify the smallest and largest X-axis value to include. If not
provided, defaults to the smallest/largest values passed to C<set>
or C<inc>. Can be used to crop the map or ensure it keeps a fixed
size even if some values are unset.

To make automatic again, set to C<undef>.

=item min_y, max_y ( INT )

Ditto for the Y-axis.

=item min_z, max_z ( FLOAT )

Ditto for intensity; useful for keeping a fixed intensity across
multiple heatmaps.

lib/ANSI/Heatmap.pm  view on Meta::CPAN


=item width, height ( INT )

Specify the width/height of the map in characters. Defaults to
using the min_I<axis> and max_I<axis> values to determine the
width/height.

=item interpolate ( BOOL )

If width/height is not a nice multiple of the input data and
this flag is set, perform bilinear interpolation (instead of
nearest neighbour). This is a trade off; interpolated data is
blurrier, but retains a linear relationship with the original
data. Off by default.

=back

=head2 set ( X, Y, Z )

Set the heatmap intensity for the given X and Y co-ordinate.

Currently, only integer values for X and Y are supported.

=head2 get ( X, Y )

Return the heatmap intensity for the given X and Y co-ordinate,
or 0 if unset.

=head2 inc ( X, Y )

Increase the intensity at the given co-ordinate by 1.

=head2 to_string

Return a string containing the ANSI heatmap. If C<half> is set,
this string contains wide characters, so you may need to:

 binmode STDOUT, ':utf8';

or

 use open OUT => ':utf8';

before printing anything (in this case) to STDOUT.

t/basic.t  view on Meta::CPAN

use Test::More tests => 16;
use strict;
use warnings;

use ANSI::Heatmap;

my $map = ANSI::Heatmap->new;
$map->set(0,0,1);
$map->set(1,1,1);

is_deeply( $map->data, [[1,0], [0,1]], 'set' );
is( $map->get(0,0), 1 );
is( $map->get(0,1), 0 );
is( $map->get(1,0), 0 );
is( $map->get(1,1), 1 );
is( $map->get(200,0), 0 );

is( $map->to_string, "\e[48;5;196m \e[0m\e[48;5;16m \e[0m\n\e[48;5;16m \e[0m\e[48;5;196m \e[0m\n" );
is( "$map", $map->to_string );

$map->inc(0,0);
is( $map->get(0,0), 2 );
is_deeply( $map->data, [[1,0], [0,0.5]], 'inc' );

$map->set(0,3,1);
is( $map->get(0,3), 1 );
is( $map->get(1,3), 0 );
is_deeply( $map->data, [[1,0], [0,.5], [0,0], [.5,0]], 'extend y' );

$map->set(3,0,1);
is( $map->get(3,0), 1 );
is( $map->get(3,1), 0 );
is_deeply( $map->data, [[1,0,0,.5], [0,.5,0,0], [0,0,0,0], [.5,0,0,0]], 'extend x' );



( run in 0.615 second using v1.01-cache-2.11-cpan-49f99fa48dc )