#! /usr/bin/perl if(@ARGV != 4) { die < output.data This program converts the three column output of a postgres query (which returns 3 columns) into a format suitable for being used as gnuplot data. You'll want to use a set of commands something like: set pm3d map set terminal png truecolor size 800,600 set output "/tmp/gnuplot.png" splot "/tmp/input.data" with pm3d EOHELP } use strict; my ($datafile, $x_step, $y_step, $z_step) = @ARGV; open(my $df, "<", $datafile); my %data; # read the data foreach my $line (<$df>) { if($line =~ m{(\d+\.?\d*).*?[, |](\d+\.?\d*).*?[, |](\d+\.?\d*)}) { $data{$1}->{$2} = $3; } } # calculate the ranges # # note: yes, the min is cheating, but it works for pretty much any # reasonable data set. More properly, I should just check for null as # a special case (or alternatively, initialize with any random value # from the set), but this is already coded and works, and this program # is mostly just a quick hack anyhow. my ($x_min, $x_max, $y_min, $y_max) = (2**30, 0, 2**30, 0); foreach my $xkey (keys %data) { $x_min = min($xkey, $x_min); $x_max = max($xkey, $x_max); foreach my $ykey (keys %{$data{$xkey}||{}}) { $y_min = min($ykey, $y_min); $y_max = max($ykey, $y_max); } } # print out the complete data foreach my $x ($x_min..$x_max) { for(my $y = $y_min; $y <= $y_max; $y += $y_step) { print "$x $y " . ($data{$x}->{$y} + 0) . "\n"; } print "\n"; } sub min { return $_[0] > $_[1] ? $_[1] : $_[0]; } sub max { return $_[0] > $_[1] ? $_[0] : $_[1]; }