Graph::Layout::Aesthetic::Monitor::GnuPlot - Display progress of a graph layout using gnuplot


Graph-Layout-Aesthetic documentation Contained in the Graph-Layout-Aesthetic distribution.

Index


Code Index:

NAME

Top

Graph::Layout::Aesthetic::Monitor::GnuPlot - Display progress of a graph layout using gnuplot

SYNOPSIS

Top

    use Graph::Layout::Aesthetic::Monitor::GnuPlot;
    $monitor = Graph::Layout::Aesthetic::Monitor::GnuPlot->new(%parameters);

    # Now use it with Graph::Layout::Aesthetic object $aglo:
    $aglo->gloss(monitor => $monitor);

    # That's the basics. You likely won't need the stuff after this point
    $monitor->plot($aglo);
    $monitor->command($command);
    $monitor->command_flush($command);
    $monitor->commandf($format, @arguments);
    $time = $monitor->last_plot_time;

DESCRIPTION

Top

Graph::Layout::Aesthetic::Monitor::GnuPlot is a simple class based on gnuplot (gnuplot(1)) that is meant to help you to monitor the progress of a graph layout. It has the right interface so it can be directly used as the value of the monitor parameter to Graph::Layout::Aesthetic method gloss.

METHODS

Top

new$monitor = Graph::Layout::Aesthetic::Monitor::GnuPlot->new(%parameters)

Creates a new Graph::Layout::Aesthetic::Monitor::GnuPlot object. The parameters are name/value pairs which currently can be:

new_after_plotafter_plot => $callback

Whenever the plot|"plot" method is called, this callback is also executed after flushing the actual plot commands to gnuplot (gnuplot(1)) like this:

    $callback->($aglo, $monitor);

Unless $callback is false (the default) in which case nothing gets done.

plot$monitor->plot($aglo)

Takes the current Graph::Layout::Aesthetic $aglo state and plots it. At the end of this call the after_plot|"new_after_plot" callback is done if any was given.

This method usually gets called implicitly by the Graph::Layout::Aesthetic method gloss.

command$monitor->command($command)

Sends $command directly to gnuplot (gnuplot(1)). Since no flush on the controlling pipe is done the command may (or may not) get buffered and therefore not executed until something flushes it. See command_flush|"command_flush".

A newline gets appended to the $command internally.

command_flush$monitor->command_flush($command)

The same as command|"command", but also flushes the controlling pipe to gnuplot (gnuplot(1)). So all already buffered commands and this command will get executed.

commandf$monitor->commandf($format, @arguments)

The same as command|"command", but with a printf (printf in perlfunc) style interface.

last_plot_time$time = $monitor->last_plot_time

Return the epoch time of the last time a plot|"plot" method call returned. Returns undef if a plot|"plot" has never been done yet.

EXPORTS

Top

None.

SEE ALSO

Top

Graph::Layout::Aesthetic, gnuplot(1)

AUTHOR

Top

Ton Hospel, <Graph-Layout-Aesthetic@ton.iguana.be>

COPYRIGHT AND LICENSE

Top


Graph-Layout-Aesthetic documentation Contained in the Graph-Layout-Aesthetic distribution.

package Graph::Layout::Aesthetic::Monitor::GnuPlot;
use 5.006001;
use strict;
use warnings;
use Carp;

our $VERSION = '0.02';
our @CARP_NOT = qw(package Graph::Layout::Aesthetic);

our @gnu_plot = $^O eq "MSWin32" ? 
    qw(pgnuplot) : qw(gnuplot -geometry 600x700-1+1);
# our @gnu_plot = qw(tee blub);
our $margin = 0.05;
our $init_config = ($^O eq "MSWin32" ? "set terminal windows" : "set terminal X11") . "
set data style linespoints
set offsets 0.1, 0.1, 0.1, 0.1
set nokey
set clip two
";

sub new {
    my ($class, %params) = @_;
    my $after_plot = delete $params{after_plot};
    croak "Unknown parameter ", join(", ", keys %params) if %params;

    my $fh;
    if ($^O eq "MSWin32") {
        local $" = " ";	# " unconfuse emacs
        open($fh, "|-", "@gnu_plot") || 
            croak "Could not start $gnu_plot[0]: $!";
    } else {
        no warnings 'exec';
        open($fh, "|-", @gnu_plot) || 
            croak "Could not start $gnu_plot[0]: $!";
    }
    my $old = select($fh);
    eval {
        local $| = 1;
        print($init_config) || croak "Error writing to $gnu_plot[0] pipe: $!";
    };
    select($old);
    die $@ if $@;

    return bless {
        program => $gnu_plot[0],
        fh => $fh,
        after_plot => $after_plot,
        start_time => time,
    }, $class;
}

sub command {
    my $monitor = shift;
    my $fh = $monitor->{fh};
    print($fh @_, "\n") ||
        croak "Error writing to $monitor->{program} pipe: $!";
}

sub commandf {
    my $monitor = shift;
    my $fh = $monitor->{fh};
    printf($fh shift() . "\n", @_) ||
        croak "Error writing to $monitor->{program} pipe: $!";
}

sub command_flush {
    my $monitor = shift;
    my $fh = select($monitor->{fh});
    eval {
        local $| = 1;
        print(@_, "\n") ||
            croak "Error writing to $monitor->{program} pipe: $!";
    };
    select($fh);
    die $@ if $@;
}

sub plot {
    my ($monitor, $aglo) = @_;

    my ($min, $max) = $aglo->iso_frame;
    @$min == 2 || @$min == 3 ||
        croak "Space is ", scalar @$min, "-dimensional (gnuplot display only work in 2 or 3 dimensions)";
    my $edge = ($max->[0]-$min->[0]) * $margin;
    $edge = 1 if $edge == 0;

    my @coordinates = $aglo->all_coordinates;
    my $fh = $monitor->{"fh"};
    printf($fh "set xrange [ %f : %f ]\n", $min->[0]-$edge, $max->[0]+$edge) ||
        croak  "Error writing to $monitor->{program} pipe: $!";
    printf($fh "set yrange [ %f : %f ]\n", $min->[1]-$edge, $max->[1]+$edge) ||
        croak  "Error writing to $monitor->{program} pipe: $!";
    printf($fh "set zrange [ %f : %f ]\n", $min->[2]-$edge, $max->[2]+$edge) ||
        croak  "Error writing to $monitor->{program} pipe: $!" if @$min == 3;
    printf($fh "set title \"Time=%u    Temp=%.3f\"\n",
           time() - $monitor->{start_time}, $aglo->temperature) ||
               croak  "Error writing to $monitor->{program} pipe: $!";
    print($fh "plot \"-\"\n") || croak "Error writing to $monitor->{program} pipe: $!";
    for ($aglo->topology->edges) {
        print($fh "@$_\n") || croak "Error writing to $monitor->{program} pipe: $!" for
            @coordinates[@$_];
        print($fh "\n") || croak "Error writing to $monitor->{program} pipe: $!";
    }
    $monitor->command_flush("e");
    $monitor->{last_plot} = time;
    $monitor->{after_plot}->($aglo, $monitor) if $monitor->{after_plot};
}

sub last_plot_time {
    return shift->{last_plot};
}

sub DESTROY {
    my $monitor = shift;
    my $fh = $monitor->{"fh"};
    print $fh "quit\n";
    close($fh);
    warn("Unexpected returncode from gnuplot: $?") if $?;
}

__END__