Open Source im professionellen Einsatz
Linux-Magazin 07/2009
© Utzel-Butzel, Photocase.com

© Utzel-Butzel, Photocase.com

Perl-Skript lässt Google Diagramme zeichnen

Datenmaler

Googles Chart-Service zeichnet optisch ansprechende Diagramme, ganz gleich, woher die Daten dafür stammen. Ein CPAN-Modul gibt die Zeichenanweisungen dafür in objektorientiertem Perl weiter, statt vom Programmierer URL-Fitzelei zu verlangen.

969

Schon geraume Zeit liebäugelte ich heimlich mit einem Ersatz für meinen alten Laptop und als dann neulich die Firma Dell eines dieser putzigen Mini-9-Zoll-Ubuntu-Netbooks (Abbildung 1) zum unschlagbaren Preis von nur 230 Dollar feilbot, gab es kein Halten mehr und ich schlug endlich zu. Mein Arbeitskollege Leif fand dann auch noch einen lustigen Namen für den Winzling: "Mini-Me" - nach dem gleichnamigen winzigen Klon von Dr. Evil aus dem zweiten Austin-Powers-Film.

Abbildung 1: Michael Schillis kleines Dell-Netbook mit Ubuntu und ursprünglich nur 512 MByte RAM.

Der erste Eindruck war berauschend, es funktionierte sogar alles halbwegs! Als ich dann noch die mageren 512 MByte RAM mit 2 GByte eines Billiganbieters für 9,95 Dollar nachrüstete, war mein Glück perfekt, allerdings schlich sich ein verstörender Gedanke ein: Würde das Netbook mit dem größeren Speicherbaustein im Suspend-Mode vielleicht mehr Strom schlucken, also die Batterie vorzeitig entleeren? Dem Ingenieur ist nichts zu schwör - ich ging der Sache auf den Grund.

Also baute ich zunächst wieder das alte Speichermodul ein, suspendierte den Rechner und las in unregelmäßigen Abständen über die nächsten 36 Stunden auf dem dazu kurz reanimierten Gerät den Ladezustand der Batterie ab. In Abbildung 2 sind die handgeschriebenen Notizzettel zu sehen, die das aktuelle Ergebnis jeweils neben der Uhrzeit auflisten.

Abbildung 2: Die gemessenen Daten auf handgeschriebenen Notizzetteln.

Vom Zettel zum Diagramm

Das gleiche Verfahren wiederholte ich eineinhalb Tage später noch einmal mit dem dazu wieder eingebauten 2-GByte-Baustein. Beide Messreihen haben wegen des unorthodoxen Verfahrens unterschiedlich Messzeitpunkte. Um die Entladungskurven - wie in Abbildung 3 zu sehen - grafisch nebeneinander darzustellen, muss man die Daten erst mit dem Skript in Listing 1 normalisieren, bevor sie sich anschließend mit dem Skript in Listing 2 durch Googles Chart-Service zeichnen lassen.

Das Ergebnis zeigt, dass die Entladung mit beiden Speichermodulen anfangs in etwa gleich schnell vonstatten geht. Mit schwächerer Batterie saugt das größere Speichermodul später sogar etwas mehr Saft und sorgt für eine schnellere Entladung des Akkus. Kein besorgniserregender Vorgang, aber schön, wenn man harte Daten in einem ansprechend gestalteten Diagramm vorweisen könnte.

Listing 1:
»data-normalize«

01 #!/usr/local/bin/perl -w
02 use strict;
03 use DateTime;
04
05 my @result = ();
06 my $max    = {};
07
08 my $data = {
09     "2gb" => [qw(
10   21:33 100 08:18 83 10:52 80
11   18:40 57  08:36 35 12:21 28
12 )],
13     "0.5gb" => [qw(
14   14:44 100 16:09 97 18:08 95
15   20:43 88  22:19 86 08:47 73
16   15:19 65  17:52 61 21:19 56
17   23:04 55  07:35 43
18 )]};
19
20 for my $conf (keys %$data) {
21
22   my $points = $data->{ $conf };
23   my $day_start;
24   my $day_current;
25
26   while( my($time, $charge) =
27          splice( @$points, 0, 2 ) ) {
28
29     my($hour, $minute) = split /:/, $time;
30
31     if(!defined $day_start) {
32         $day_start = DateTime->today();
33         $day_start->set_hour( $hour );
34         $day_start->set_minute( $minute );
35         $day_current = $day_start->clone();
36     }
37
38     my $time_current =
39                      $day_current->clone();
40     $time_current->set_hour( $hour );
41     $time_current->set_minute( $minute );
42
43     if($time_current < $day_current) {
44         $time_current->add( days => 1 );
45         $day_current->add( days => 1 );
46     }
47
48     $day_current = $time_current->clone();
49
50     my $x = (($time_current->epoch() -
51               $day_start->epoch()) / 60);
52
53     push @result, [ $conf, $x, $charge ];
54
55     if(!exists $max->{x} or
56        $max->{x} < $x) {
57         $max->{x} = $x;
58     }
59     if(!exists $max->{y} or
60        $max->{y} < $charge) {
61         $max->{y} = $charge;
62     }
63   }
64 }
65
66 my $margin = 2;
67
68 for my $result (@result) {
69     my($symbol, $x, $y) = @$result;
70     print "$symbol ",
71           int($x*(100-2*$margin)/
72               $max->{x})+$margin,
73           " ",
74           int($y*(100-2*$margin)/
75               $max->{y})+$margin,
76           "n";
77 }

Listing 2:
»graph-discharge«

001 #!/usr/local/bin/perl -w
002 use strict;
003 use Google::Chart;
004 use Google::Chart::Marker;
005
006 my $data = {};
007
008 open PIPE, "./data-normalize |" or die;
009 while(<PIPE>) {
010     chomp;
011     my($symbol, $x, $y) = split ' ', $_;
012     next unless $y;
013     push @{ $data->{ $symbol }->{x} }, $x;
014     push @{ $data->{ $symbol }->{y} }, $y;
015 }
016 close PIPE or die;
017
018 my $graph = Google::Chart->new(
019   type => 'XY',
020
021   data => [$data->{"0.5gb"}->{x},
022            $data->{"0.5gb"}->{y},
023            $data->{"2gb"}->{x},
024            $data->{"2gb"}->{y},
025           ],
026
027   size => '750x400',
028
029   title => {
030     text => "Dell Mini Standby Discharge"
031   },
032
033   fill => {
034     module => "LinearGradient",
035     args   => {
036       target  => "c",
037       angle   => 45,
038       color1  => "abbaab",
039       offset1 => 1,
040       color2  => "FFFFFF",
041       offset2 => 0,
042     }
043   },
044
045   grid => {
046     x_step_size => 33,
047     y_step_size => 20,
048   },
049
050   axis => [
051     { location => 'x',
052       labels => [1..36],
053     },
054     { location => 'y',
055       labels => [0,25,50,75,100],
056     },
057   ],
058
059   color => ['E6E9FD', '4D89F9'],
060
061   legend => ['0.5gb', '2gb'],
062
063   margin => [50, 50, 50, 50, 100, 100],
064
065   marker =>  Google::Chart::Marker->new(
066     markerset => [
067       { marker_type => 'x',
068         color => 'FFCC33',
069         dataset   => 0,
070         datapoint => -1,
071         size => 15,
072         priority => 1,
073       },
074       { marker_type => 'x',
075         color => 'FF0000',
076         dataset   => 1,
077         datapoint => -1,
078         size => 15,
079         priority => 1,
080       },
081       { marker_type => 'D',
082         color => 'E6E9FD', # light blue
083         dataset   => 0,
084         datapoint => -1,
085         size => 4,
086         priority => -1,
087       },
088       { marker_type => 'D',
089         color => '4D89F9', # blue
090         dataset   => 1,
091         datapoint => -1,
092         size => 4,
093         priority => -1,
094       },
095     ]),
096 );
097
098 $graph->render_to_file(filename =>
099                        "chart.png");
100 system("xv chart.png");
101

Diagrammgestaltung outsourcen

Kein Programm auf dem lokalen Rechner erzeugt in diesem Fall das Diagramm, sondern ein Clusterrechner der Firma Google. Das Perl-Skript baut lediglich eine URL nach Abbildung 4 zusammen, schickt sie an den Google-Chart-Service, und zurück kommt ein Bild im PNG-Format, das der Abbildung 3 entspricht. Google beschränkt die Zugriffe auf maximal 50000 pro Tag, das sollte aber für private Spielereien fürs Erste noch reichen. Ein anderer Perl-Snapshot [5] benutzte den gleichen Service schon einmal, um Spammer auf einer Weltkarte einzuzeichnen.

Abbildung 3: Google Charts zeichnet die Entladung des Netbooks mit den verschieden großen Speicherbausteinen.

Abbildung 4: Die an Google geschickte URL, nach deren Angaben der Chart-Service das Diagramm in Abbildung 3 zeichnet. Manuell wäre sie nur mit großem Aufwand zu konstruieren.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Perl-Snapshot

    Handgeräte für die Navigation weisen den Weg und schreiben bei Wanderungen laufend die aktuelle Position mit. Mit einigen Skripten unter Linux bereitet Extrembergsteiger Michael Schilli die Daten seiner waghalsigen Erstbesteigungen optisch ansprechend auf.

  • Torte statt vieler Worte

    Diagramme machen naturgemäß optisch mehr her als spröde Zahlenkolonnen. In der grafischen Aufbereitung erkennt das Auge außerdem leicht Muster und Tendenzen. Das Chart-API des Webgiganten Google visualisiert Daten mit wenig Aufwand.

  • Perl-Snapshot

    Der elektronische Armreif Up misst die Armbewegungen seines Trägers und schließt daraus auf tags zurückgelegte Wege und nächtliche Schlafrhythmen. Wen die offizielle Smartphone-App langweilt, der lässt eigene Perl-Skripte auf das inoffizielle Web-API zugreifen.

  • Bessere Diagramm-Features in Open Office 2.4

    Die nächste Ausgabe von Open Office erweitert die Diagramm-Funktionen, die für die Vorgängerversion 2.3 generalüberholt wurden.

  • Malen nach Zahlen

    Mit zunehmendem Datenwust gehen für den Betrachter relevante Informationen unter. Sinnvolle Grafiken bringen Wichtiges wieder ans Licht. Die leistungsfähige Bibliothek JFreechart hilft dabei, mit Java aussagefähige Diagramme zu zeichnen und sie in eigene Programme einzubauen.

comments powered by Disqus