ANSI-Heatmap

 view release on metacpan or  search on metacpan

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

    }

    for my $y (0..$mm{height}-1) {
        for my $x (0..$mm{width}-1) {
            my $sx = ($x / $xscale) + $mm{min_x};
            my $sy = ($y / $yscale) + $mm{min_y};
            my $z = $sample->($sx, $sy);

            # Normalise intensity
            $z = $mm{max_z} if $z > $mm{max_z};
            $z -= $mm{min_z};
            $z *= $inv_max_z;

            $out[$y][$x] = $z;
        }
    }

    return \@out;
}

sub render {
    my ($self, $matrix) = @_;
    my $half = $self->half;

    my @s;
    for my $y (0..$#{$matrix}) {
        next if $half && $y % 2 == 1;

        for my $x (0..$#{$matrix->[$y]}) {
            my $top = $matrix->[$y][$x] || 0;
            my $bottom = $half ? ($y == $#{$matrix} ? undef : $matrix->[$y+1][$x] || 0)
                               : $top;

            my ($top_color, $bottom_color) = map {
                $self->_swatch_lookup($_)
            } grep { defined } ($top, $bottom);

            my $fg = sprintf "\e[38;5;%d%s", $top_color, 'm';
            my $bg = defined $bottom ? sprintf "\e[48;5;%d%s", $bottom_color, 'm'
                                     : '';

            my $char = $half ? $fg . $bg . $TOPBLOCK : $bg . ' ';

            push @s, $char . "\e[0m";
        }
        push @s, "\n";
    }
    return join '', @s;
}


# Return hash of min/max values for each axis.
sub _figure_out_min_and_max {
    my $self = shift;
    my %calc = (
        (map { $_ => 0 } @_minmax_fields),
        %{$self->{minmax}},
        ($self->{minmax}{min_z}||0) >= 0 ? (min_z => 0) : (),
    );

    # Override with user-specified values, if supplied.
    for my $k (keys %calc) {
        $calc{$k} = $self->{$k} if defined $self->{$k};
    }

    # If user did not specify width/height, assume 1x scale.
    $calc{width}  = $self->{width} || ($calc{max_x} - $calc{min_x} + 1);
    $calc{height} = $self->{height} || ($calc{max_y} - $calc{min_y} + 1);
    $calc{zrange} = $calc{max_z} - $calc{min_z};

    return %calc;
}

sub _binterp {
    my $get = shift;
    return sub {
        my ($x, $y) = @_;
        my ($fx, $bx) = modf($x);
        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);
        }
    }
}

# Maps a number from [0,1] to a swatch colour.
sub _swatch_lookup {
    my ($self, $index) = @_;
    return $self->{swatch}->[$index * $#{$self->{swatch}} + .5];
}

1;

=head1 NAME

ANSI::Heatmap - render heatmaps to your terminal

=head1 SYNOPSIS

 my $map = ANSI::Heatmap->new(
    half => 1,
    min_x => 0, max_x => 49,
    min_y => 0, max_y => 49,
    swatch => 'blue-red',



( run in 1.515 second using v1.01-cache-2.11-cpan-39bf76dae61 )