OVH Cloud OVH Cloud

GD::Graph et axe des abscisses

3 réponses
Avatar
lfrigault
bonjour,

J'utilise depuis peu de temps GD::Graph et plus particulièrement
GD::Graph::area . Aucun pb pour obtenir les graphes que je souhaite mais
je n'arrive pas à obtenir un axe des X gradué comme je le souhaite.

L'axe des X de mon graphe représente l'évolution dans le temps d'une ou
plusieurs mesures (timestamp unix).

Je souhaire obtenir un axe des X avec une graduation toutes les 15
minutes et l'heure affichée toutes les heures. J'ai lu le man de
GD::Graph dans tous les sens mais visiblement, pas dans le bon :(

J'ai reproduit le problème dans le script suivant. Quelqu'un à une idée
de l'endroit ou je me suis planté ?


#!/usr/bin/perl -w

use strict;
use POSIX;
use GD::Graph::area;

my $DEBUT='2003-08-22';
my $FIN='2003-08-23';

my $width = 800;
my $height = 600;

$DEBUT =~ /(\d+)-(\d+)-(\d+)/;
my $tdebut = &POSIX::mktime(0,0,0,$3,$2-1,$1-1900,0,0,-1);
$FIN =~ /(\d+)-(\d+)-(\d+)/;
my $tfin = &POSIX::mktime(0,0,0,$3,$2-1,$1-1900,0,0,-1);
my $deltat = $tfin - $tdebut;

sub x_format($)
{
my $value = shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($value);
return sprintf("%02d:%02d",$hour,$min);
};

my $graph = GD::Graph::area->new($width, $height);
$graph->set(
bgclr => "white",
boxclr => "white",
transparent => 0,
y_max_value => $width,
y_min_value => 0,
x_number_format => \&x_format,
x_label_skip => 60*60,
y_tick_number => 5,
x_tick_number => (4*$deltat)/3600,
x_tick_offset => 0,
accent_treshold => 10000,
dclrs => [ qw(lred) ],
borderclrs => undef,
cycle_clrs => 0,
) or die $graph->error;

my @data;
my @y=();
for(my $col = 0;$col< $width;$col++)
{
push @y, $col;
};
push @data, [ @y ];

@y=();
for(my $col = 0;$col< $width;$col++)
{
push @y, int(($col*$deltat)/$width)+$tdebut;
};
unshift @data, [ @y ];

my $gd = $graph->plot(\@data) ;

open(IMG, ">/tmp/a.png") || die "Can't open >tmp/a.png $!";
binmode IMG;
print IMG $gd->png || die "Can't write tmp/a.png $!";
close(IMG) || die "Can't close tmp/a.png $!";


Lolo, perplexe
--
Laurent Frigault - NOC GANDI

3 réponses

Avatar
oups - Use ROT13 to decode
Laurent Frigault wrote:

bonjour,

J'utilise depuis peu de temps GD::Graph et plus particulièrement
GD::Graph::area . Aucun pb pour obtenir les graphes que je souhaite mais
je n'arrive pas à obtenir un axe des X gradué comme je le souhaite.

L'axe des X de mon graphe représente l'évolution dans le temps d'une ou
plusieurs mesures (timestamp unix).

Je souhaire obtenir un axe des X avec une graduation toutes les 15
minutes et l'heure affichée toutes les heures. J'ai lu le man de
GD::Graph dans tous les sens mais visiblement, pas dans le bon :(

J'ai reproduit le problème dans le script suivant. Quelqu'un à une idée
de l'endroit ou je me suis planté ?


[snip]

Lolo, perplexe


Bonjour,

Je ne suis pas un pro de GD::Graph mais plusieurs points me gènent :
- les data [x,y] ne dependent pas du temps mais de width ainsi [x,y] =
[0..800,(0..800)*$deltat/800] => étrange
- dans ta definition des propriété du graph, tu precise une fourchette
pour y mais pas pour x !

Ainsi,

#---------------=CUT
use strict;
use POSIX;
use GD::Graph::area;

my $DEBUG=0; # debug on(1) / off(0)

my $DEBUT='2003-08-22';
my $FIN='2003-08-23';

my $width = 800;
my $height = 600;

$DEBUT =~ /(d+)-(d+)-(d+)/;
my $tdebut = &POSIX::mktime(0,0,0,$3,$2-1,$1-1900,0,0,1); # 0h00 p.m le
$DEBUT
$FIN =~ /(d+)-(d+)-(d+)/;
my $tfin = &POSIX::mktime(0,0,0,$3,$2-1,$1-1900,0,0,1); # 0h00 p.m le $FIN
my $deltat = $tfin - $tdebut;

if ($DEBUG) {
printf "tdebut= " . $tdebut . "ttfin= " . $tfin;
printf "n";
printf "deltat= " . $deltat;
}

sub x_format($)
{
my $value = shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($value);
if ($DEBUG) {
print("nvalue= ", $value, " hour =", $hour, " minutes= ", $min,"n");
}
return sprintf("%02d:%02d",$hour,$min);
};

my $graph = GD::Graph::area->new($width, $height);
$graph->set(
bgclr => "white",
boxclr => "white",
transparent => 0,
y_max_value => $deltat,
y_min_value => 0,
y_tick_number => 5,
x_number_format => &x_format,
x_min_value => $tdebut,
x_max_value => $tfin,
x_label_skip => 4, # toutes les 4 graduation
x_tick_number => ($deltat)/900, # 15 min = 900 s
x_tick_offset => -2,
accent_treshold => 10000,
dclrs => [ qw(lred) ],
borderclrs => undef,
cycle_clrs => 0,
) or die $graph->error;

my @data;
my @y=();
for(my $col = 0;$col< $width;$col++)
{
push @y, $col;
};
push @data, [ @y ];

@y=();
for(my $col = 0;$col< $width;$col++)
{
#print "ny= ", int(($col*$deltat)/$width), "n";
push @y, int(($col*$deltat)/$width);
};
unshift @data, [ @y ];

my $gd = $graph->plot(@data) ;

open(IMG, ">a.png") || die "Can't open >tmp/a.png $!";
binmode IMG;
print IMG $gd->png || die "Can't write tmp/a.png $!";
close(IMG) || die "Can't close tmp/a.png $!";
#---------------=CUT

fournit la bonne echelle (celle voulue pour x) mais la definition de
data est incorrecte. De plus la définition originale :
push @y, int(($col*$deltat)/$width)+$tdebut;
est etrange $tdebut # 10^9 alors que ($col*$deltat)/$width vaut, au
maximum, $deltat # 8.10^4 et 10^9 + 8.10^4 est approximativement égal à
10^9 !

Voila, pour l'echelle je pense que c'est corrigé, pour les data je ne
sais pas ce que tu traces mais mathématiquement ca ne colle pas vraiment.

En esperant que ceci t'aide

Cordialement,

--
oups

Avatar
lfrigault
In article ,
oups - Use ROT13 to decode writes:

Bonjour,

J'utilise depuis peu de temps GD::Graph et plus particulièrement
GD::Graph::area . Aucun pb pour obtenir les graphes que je souhaite
mais je n'arrive pas à obtenir un axe des X gradué comme je le
souhaite.



...

Je ne suis pas un pro de GD::Graph mais plusieurs points me gènent :
- les data [x,y] ne dependent pas du temps mais de width ainsi [x,y] =
[0..800,(0..800)*$deltat/800] => étrange


Oui, pour tout un tas de raison liée à mon pb, je converti le timestamp
en abscisse.

- dans ta definition des propriété du graph, tu precise une fourchette
pour y mais pas pour x !


Normalement, GD::Graph est sensé les trouver tout seul :

x_min_value, x_max_value
The minimum and maximum value to use for the X axis.
Default:
computed.

Pour une raison que j'ignore, dès que j'utilise x_min_value et
x_max_value, ça fixhe une grouille pas possible.

[couic du script]

x_label_skip => 4, # toutes les 4 graduation


C'est ça que j'avais raté. Je me suis lourdement trompé sur
x_label_skip. Maintenant, ça va fonctionner.

@y=();
for(my $col = 0;$col< $width;$col++)
{
#print "ny= ", int(($col*$deltat)/$width), "n";
push @y, int(($col*$deltat)/$width);
};
unshift @data, [ @y ];

my $gd = $graph->plot(@data) ;

#---------------=CUT

fournit la bonne echelle (celle voulue pour x) mais la definition de
data est incorrecte. De plus la définition originale :
push @y, int(($col*$deltat)/$width)+$tdebut;
est etrange $tdebut # 10^9 alors que ($col*$deltat)/$width vaut, au
maximum, $deltat # 8.10^4 et 10^9 + 8.10^4 est approximativement égal à
10^9 !


Les timestamps unix actuels ont dépassé les 10^9 secondes donc c'est
normal.Le int(($col*$deltat)/$width)+$tdebut fait une conversion entre
l'échelle des timestamp (allant de $tdebut à tdebut + $width) et une
autre échelle dont j'ai besoin ailleurs (allant de 0 à $width).

J'ai l'impression qu'utiliser des abscisses ne commençant pas par zéro
fout la grouille. Je modifie mon script pour utiliser l'échelle
0..$width

Voila, pour l'echelle je pense que c'est corrigé, pour les data je ne
sais pas ce que tu traces mais mathématiquement ca ne colle pas
vraiment.


Dans mon exemple j'ai mis n'importe quoi pour simpliflier. En pratique,
je graphe des flux réseaux (flows, paquets, octets).

En esperant que ceci t'aide


Oui beaucoup.

Merci.

Lolo
--
Laurent Frigault - NOC GANDI


Avatar
lfrigault
In article ,
oups - Use ROT13 to decode writes:

Bonjour,

J'utilise depuis peu de temps GD::Graph et plus particulièrement
GD::Graph::area . Aucun pb pour obtenir les graphes que je souhaite
mais je n'arrive pas à obtenir un axe des X gradué comme je le
souhaite.



...

Je ne suis pas un pro de GD::Graph mais plusieurs points me gènent :
- les data [x,y] ne dependent pas du temps mais de width ainsi [x,y] =
[0..800,(0..800)*$deltat/800] => étrange


Oui, pour tout un tas de raisons, je converti le timestamp en abscisse.

- dans ta definition des propriété du graph, tu precise une fourchette
pour y mais pas pour x !


Normalement, GD::Graph est sensé les trouver tout seul :

x_min_value, x_max_value
The minimum and maximum value to use for the X axis.
Default:
computed.

Pour une raison que j'ignore, dès que j'utilise x_min_value et
x_max_value, ça fiche une grouille pas possible.

[couic du script]

x_label_skip => 4, # toutes les 4 graduation


C'est ça que j'avais raté. Je me suis lourdement trompé sur
x_label_skip. Maintenant, ça va fonctionner.

@y=();
for(my $col = 0;$col< $width;$col++)
{
#print "ny= ", int(($col*$deltat)/$width), "n";
push @y, int(($col*$deltat)/$width);
};
unshift @data, [ @y ];

my $gd = $graph->plot(@data) ;

#---------------=CUT

fournit la bonne echelle (celle voulue pour x) mais la definition de
data est incorrecte. De plus la définition originale :
push @y, int(($col*$deltat)/$width)+$tdebut;
est etrange $tdebut # 10^9 alors que ($col*$deltat)/$width vaut, au
maximum, $deltat # 8.10^4 et 10^9 + 8.10^4 est approximativement égal à
10^9 !


Les timestamps unix actuels ont dépassé les 10^9 secondes donc c'est
normal.Le int(($col*$deltat)/$width)+$tdebut fait une conversion entre
l'échelle des timestamp (allant de $tdebut à tdebut + $width) et une
autre échelle dont j'ai besoin ailleurs (allant de 0 à $width).

J'ai l'impression qu'utiliser des abscisses ne commençant pas par zéro
fout la grouille. Je modifie mon script pour utiliser l'échelle
0..$width

Voila, pour l'echelle je pense que c'est corrigé, pour les data je ne
sais pas ce que tu traces mais mathématiquement ca ne colle pas
vraiment.


Dans mon exemple j'ai mis n'importe quoi pour simpliflier. En pratique,
je graphe des flux réseaux (flows, paquets, octets).

En esperant que ceci t'aide


Oui beaucoup.

Merci.

Lolo
--
Laurent Frigault - NOC GANDI