Reputation: 448
I'm plotting graphs with Perl using RRDs/RRDtool. I'm able to generate a graph with a legend, but I'm struggling to align the fields in the legend.
The code I'm using is:
"COMMENT:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\n",
"COMMENT:\t\t\t\t\t\t\tMinimum\t\t\tMaximum\t\t\tAverage\t\t\t\tCurrent\\n",
"COMMENT:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\n",
"LINE2:e2gran#DF01D7:\t2GRAN\t\t\t\t",
"GPRINT:e2gmin:\t%6.3lf %s\t\t",
"GPRINT:e2gmax:\t%6.3lf %s\t\t",
"GPRINT:e2gaver:\t%6.3lf %s\t\t",
"GPRINT:e2glast:\t%6.3lf %s\\n",
"LINE2:e3gran#0000FF:\t3GRAN\t\t\t\t",
"GPRINT:e3gmin:\t%6.3lf %s\t\t",
"GPRINT:e3gmax:\t%6.3lf %s\t\t",
"GPRINT:e3gaver:\t%6.3lf %s\t\t",
"GPRINT:e3glast:\t%6.3lf %s\\n",
"LINE2:e4gran#FF8000:\t4GRAN\t\t\t\t",
"GPRINT:e4gmin:\t%6.3lf %s\t\t",
"GPRINT:e4gmax:\t%6.3lf %s\t\t",
"GPRINT:e4gaver:\t%6.3lf %s\t\t",
"GPRINT:e4glast:\t%6.3lf %s\\n",
"LINE2:e2gtran#FFFF00:\t2GTRAN\t\t\t",
"GPRINT:e2gtmin:\t%6.3lf %s\t\t",
"GPRINT:e2gtmax:\t%6.3lf %s\t\t",
"GPRINT:e2gtaver:\t%6.3lf %s\t\t",
"GPRINT:e2gtlast:\t%6.3lf %s\\n",
"LINE2:allregmax#FF0000:\tALL_REGIONS\t\t",
"GPRINT:allmin:%6.3lf%s\t\t",
"GPRINT:allmax:%6.3lf%s\t\t",
"GPRINT:allaver:%6.3lf%s\t\t",
"GPRINT:alllast:%6.3lf%s\\n",
"LINE3:wrongdata#000000:\\tINCOMPLETE DATA\\n",
The font used for the legend is Arial. The output looks like this:
While I'm aiming for something like this:
I have tried TEXTALIGN
, fiddling with spaces and tabs, and checked the RRDtool docs and different tutorials, but I just can't figure this out.
Upvotes: 2
Views: 3057
Reputation: 448
Thanks to the great help and hints from simbabque, I managed to use this (in the RRD:graph declaration):
"--font","LEGEND:14:Courier New",
sprintf('COMMENT:%s\\n', '-' x 110),
sprintf('COMMENT:% 35s%18s%19s%19s\n', qw/Minimum Maximum Average Current/),
sprintf('COMMENT:%s\\n', '-' x 110),
sprintf('LINE2:e2gran#DF01D7:%-11s','2GRAN'),
"GPRINT:e2gmin:% 19.0lf",
"GPRINT:e2gmax:% 16.0lf",
"GPRINT:e2gaver:% 16.0lf",
"GPRINT:e2glast:% 16.0lf\\n",
to get this
which is much better than before.
Upvotes: 2
Reputation: 54333
You have two problems.
The first problem is that the Arial font is proportional. Every glyph has a different width. That looks nice in a book, but doesn't work for reports.
You need to use a monospaced font (like Courier New) for this to work at all.
Your second problem are the \t
s.
If stuff is too wide, you might have one \t
too much. That's why you are seeing things being one set of 8 spaces too far left. To fix this, don't use whitespace and tabs directly. The underlying sprintf
has syntax to create columns.
You can do %-20s
to make a right-aligned column of width 20 characters that will always be filled up with spaces. You can also do % 15s
to make
a 15 character column that is left-aligned.
If we put that into practice, we'll get:
my @cols = (
sprintf( '%-20s', '2GRAN' ),
sprintf( '% 15.3lf', 10_754 ),
sprintf( '% 15.3lf', 48_964 ),
sprintf( '% 15.3lf', 12_812 ),
);
print join '', @cols;
This creates:
2GRAN 10754.000 48964.000 12812.000
Now if we do multiple lines, it still looks nice.
foreach my $row (
[qw/ 2GRAN 10754 48964 12812 /],
[qw/ ASDFLONGERSTUFF 123 4444444 12312313 /],
)
{
CORE::say join '',
sprintf( '%-20s', $row->[0] ),
sprintf( '% 15.3lf', $row->[1] ),
sprintf( '% 15.3lf', $row->[2] ),
sprintf( '% 15.3lf', $row->[3] );
}
__END__
2GRAN 10754.000 48964.000 12812.000
ASDFLONGERSTUFF 123.000 4444444.000 12312313.000
Remember that all this stuff that you showed in your question is also just Perl code. Part of this is from the question, and another part is from chat.
sub process_all_regions { my ($region, $start,$end,$description) = @_; RRDs::graph "$img/$region-$description-$start-days.png", "-s -$start d", "-e -$end d", #"-s -1$duration*86400", "--font","TITLE:18:Arial", "--font","AXIS:11:Arial", "--font","LEGEND:14:Courier New", "COMMENT:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\n", "COMMENT:\t\t\t\t\t\t\tMinimum\t\t\tMaximum\t\t\tAverage\t\t\t\tCurrent\\n", "COMMENT:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\n", "LINE2:e2gran#DF01D7:\t2GRAN\t\t\t\t", "GPRINT:e2gmin:\t%6.3lf %s\t\t", "GPRINT:e2gmax:\t%6.3lf %s\t\t", "GPRINT:e2gaver:\t%6.3lf %s\t\t", "GPRINT:e2glast:\t%6.3lf %s\\n",
All of those lines with the sprintf
patterns are just arguments to graph()
. You don't have to put the verbatim into your code. You can create them programmatically. So if you wanted to have the header the with the same column width as the data, you can just use sprintf
yourself to construct that.
sprintf('COMMENT:%s\\n', '-' x 80),
sprintf('COMMENT:% 35s%15s%15s%15s\n', qw/Minimum Maximum Average Current/),
sprintf('COMMENT:%s\\n', '-' x 80),
Upvotes: 4