Sending data from perl to gnuplot and getting an "ASCII-art" graph back?


A

Adam Funk

I'm generating some data points in a Perl program and trying to send
them to gnuplot and get back an "ASCII-art" graph (the kind that
gnuplot generates with the "set term dumb" setting). I'd like to
improve on the following steps:

(1)
foreach $x (sort {$a <=> $b} keys(%table) ) {
$y = $table{$x};
$line = sprintf("%5d %5d\n", $x, $y);
$max_y = $y if ($y > $max_y);
print($line) if ($option{v}); # verbose option
push(@output,$line);
}

This produces lines like this:
-5 2
-2 5

(2) Then I use recipe 7.5 from the Perl Cookbook to generate two temp
files, $data_file and $cmd_file, and I write @output from step (1)
into $data_file.

(3) Then I write a bunch of gnuplot commands as lines to $cmd_file:
set term dumb
set ylabel \"Frequency\"
set xlabel \"Time\"
unset key
set yrange [0:$max_y]
plot \"$temp_filename\" with impulses

(4) and call gnuplot thus:
system('gnuplot', $cmd_file);

The Perl program runs and prints the plot to the screen. I'm about to
modify it to use backticks
$gnuplot_output = `gnuplot $cmd_file`
but I can't believe there isn't a better way than what I've done to
send a list of commands to gnuplot and get the plot back.

Is there?
 
Ad

Advertisements

T

Theo Hopman

Adam said:
I'm generating some data points in a Perl program and trying to send
them to gnuplot and get back an "ASCII-art" graph (the kind that
gnuplot generates with the "set term dumb" setting). I'd like to
improve on the following steps:

I don't use Perl, but can offer some general suggestions.
(1)
foreach $x (sort {$a <=> $b} keys(%table) ) {
$y = $table{$x};
$line = sprintf("%5d %5d\n", $x, $y);
$max_y = $y if ($y > $max_y);
print($line) if ($option{v}); # verbose option
push(@output,$line);
}

This produces lines like this:
-5 2
-2 5

Store this data in an array for later use.
(2) Then I use recipe 7.5 from the Perl Cookbook to generate two temp
files, $data_file and $cmd_file, and I write @output from step (1)
into $data_file.

You should be able to avoid the use of temporary files entirely. See
below.
(3) Then I write a bunch of gnuplot commands as lines to $cmd_file:
set term dumb
set ylabel \"Frequency\"
set xlabel \"Time\"
unset key
set yrange [0:$max_y]
plot \"$temp_filename\" with impulses

What you really want to do is pipe these commands to the stdin of
gnuplot. You also want to use inline data (see `help datafile
special-filenames`) like such:

plot "-" with impulses
-5 2
2 5
e

The data is supplied to gnuplot's stdin via the same pipe the commands
go through.
(4) and call gnuplot thus:
system('gnuplot', $cmd_file);

The Perl program runs and prints the plot to the screen. I'm about to
modify it to use backticks
$gnuplot_output = `gnuplot $cmd_file`
but I can't believe there isn't a better way than what I've done to
send a list of commands to gnuplot and get the plot back.

I don't know how to do this in Perl, but in a shell script the
following would work (plus or minus the fact that I haven't done this
in a while):

gnuplot_output=`echo $gnuplot-commands-and-data | gnuplot`

THeo
 
E

Ethan Merritt

I'm generating some data points in a Perl program and trying to send
them to gnuplot and get back an "ASCII-art" graph (the kind that
gnuplot generates with the "set term dumb" setting). I'd like to
improve on the following steps:

(1)
foreach $x (sort {$a <=> $b} keys(%table) ) {
$y = $table{$x};
$line = sprintf("%5d %5d\n", $x, $y);
$max_y = $y if ($y > $max_y);
print($line) if ($option{v}); # verbose option
push(@output,$line);
}

This produces lines like this:
-5 2
-2 5

OK, although you could also just send this data directly to gnuplot.
(2) Then I use recipe 7.5 from the Perl Cookbook to generate two temp
files, $data_file and $cmd_file, and I write @output from step (1)
into $data_file.
(3) Then I write a bunch of gnuplot commands as lines to $cmd_file:
set term dumb
set ylabel \"Frequency\"
set xlabel \"Time\"
unset key
set yrange [0:$max_y]
plot \"$temp_filename\" with impulses

(4) and call gnuplot thus:
system('gnuplot', $cmd_file);

You can do that. But you could also do
it all in-line:

$gnuplot = '/usr/local/bin/gnuplot';

open(GNUPLOT, "| $gnuplot");
print GNUPLOT <<EOFgnuplot;
set term dumb
set output "plot.txt"
set ylabel "Frequency"
set xlabel "Time"
unset key
plot '' with impulses
EOFgnuplot

foreach $x (sort {$a <=> $b} keys(%table) ) {
... the stuff you were doing anyhow ...
printt GNUPLOT $line;
}
close(GNUPLOT);

Then you can copy the output in "plot.txt" to the screen
if you want, or dump it some other way.
 
B

Ben Morrow

Quoth Adam Funk said:
I'm generating some data points in a Perl program and trying to send
them to gnuplot and get back an "ASCII-art" graph (the kind that
gnuplot generates with the "set term dumb" setting). I'd like to
improve on the following steps:

Did you try http://search.cpan.org/search?query=gnuplot ? It shows up
two modules (Term::Gnuplot and Chart::Graph::Gnuplot) that look like
they may help.

Ben
 
J

John W. Krahn

Adam said:
I'm generating some data points in a Perl program and trying to send
them to gnuplot and get back an "ASCII-art" graph (the kind that
gnuplot generates with the "set term dumb" setting). I'd like to
improve on the following steps:

(1)
foreach $x (sort {$a <=> $b} keys(%table) ) {
$y = $table{$x};
$line = sprintf("%5d %5d\n", $x, $y);
$max_y = $y if ($y > $max_y);
print($line) if ($option{v}); # verbose option
push(@output,$line);
}

This produces lines like this:
-5 2
-2 5

(2) Then I use recipe 7.5 from the Perl Cookbook to generate two temp
files, $data_file and $cmd_file, and I write @output from step (1)
into $data_file.

(3) Then I write a bunch of gnuplot commands as lines to $cmd_file:
set term dumb
set ylabel \"Frequency\"
set xlabel \"Time\"
unset key
set yrange [0:$max_y]
plot \"$temp_filename\" with impulses

(4) and call gnuplot thus:
system('gnuplot', $cmd_file);

The Perl program runs and prints the plot to the screen. I'm about to
modify it to use backticks
$gnuplot_output = `gnuplot $cmd_file`
but I can't believe there isn't a better way than what I've done to
send a list of commands to gnuplot and get the plot back.

Is there?

You can probably do what you want with IPC::Open2 or Expect.

perldoc IPC::Open2
perldoc Expect



John
 
A

Adam Funk

You can do that. But you could also do
it all in-line:

$gnuplot = '/usr/local/bin/gnuplot';

open(GNUPLOT, "| $gnuplot");
print GNUPLOT <<EOFgnuplot;
set term dumb
set output "plot.txt"
set ylabel "Frequency"
set xlabel "Time"
unset key
plot '' with impulses
EOFgnuplot

foreach $x (sort {$a <=> $b} keys(%table) ) {
... the stuff you were doing anyhow ...
printt GNUPLOT $line;
}
close(GNUPLOT);

Then you can copy the output in "plot.txt" to the screen
if you want, or dump it some other way.

That's a good idea, but I think I'll try Theo's suggestion first,
since it should get gnuplot's output directly back into a variable in
the Perl program without needing a temp file.

Thanks.
 
Ad

Advertisements

A

Adam Funk

What you really want to do is pipe these commands to the stdin of
gnuplot.
Exactly.

You also want to use inline data (see `help datafile
special-filenames`) like such:

plot "-" with impulses
-5 2
2 5
e

I'd never come across this feature but it looks extremely useful...
I don't know how to do this in Perl, but in a shell script the
following would work (plus or minus the fact that I haven't done this
in a while):

gnuplot_output=`echo $gnuplot-commands-and-data | gnuplot`

....for this (which is about the same in Perl). Thanks!
 
A

Adam Funk

What you really want to do is pipe these commands to the stdin of
gnuplot. You also want to use inline data (see `help datafile
special-filenames`) like such:

plot "-" with impulses
-5 2
2 5
e ....
gnuplot_output=`echo $gnuplot-commands-and-data | gnuplot`

The Perl equivalent of that works perfectly. Thanks!
 
Ad

Advertisements

A

Adam Funk

You can probably do what you want with IPC::Open2 or Expect.

perldoc IPC::Open2
perldoc Expect

Those look quite useful, especially IPC::Open2 (which looks easier to
use).

I've got my program to work using Theo's suggestions, but I'll bear
those in mind for the future.

Thanks,
Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top