![]() |
|
URL dieses Artikels:
zu Ausgabe:
04.2002
Auf einen Blick
Datenvisualisierung mit JpGraph
von Florian Lanthaler
Bei der Menge an Daten, die in manchen Arbeitsbereichen anfallen, kann ein Graph sehr hilfreich sein, um einen schnellen Eindruck der Situation zu vermitteln. Mit JpGraph existiert eine ausgezeichnete Klassenbibliothek zum Erstellen von Graphen in PHP. Dieser Artikel führt in die Erzeugung von Graphen am Beispiel eines Balkendiagramms, eines kombinierten Balken- und Liniendiagramms sowie eines Gantt-Charts ein.
Mit der zunehmenden Datenflut in der heutigen Informationsgesellschaft wird es besonders in vielen Bereichen des Arbeitslebens immer aufwändiger, die richtigen Daten zum richtigen Zeitpunkt zu erkennen. Mit der zur Verfügung stehenden Vielzahl an Datenbanken unterschiedlicher Preiskategorien und dem immer billiger werdenden Speicherplatz wird eine Vielzahl von Arbeits- und Prozessdaten protokolliert, um z.B eine spätere Rückverfolgung zu garantieren oder um Tendenzen festzuhalten. Ein grafischer Überblick über diese Daten ist in vielen Fällen hilfreicher als das reine Blättern in Tabellen: Ein Graph kann die tabellarische Darstellung nicht ersetzen, aber ausgezeichnet ergänzen. Ob es nun um die Entwicklung der Temperatur- und Druckverhältnisse in einer Presse während des Pressvorgangs, um die Menge der produzierten Einheiten pro Stunde an einem Fließband oder um die Anzahl und Art der verkauften Artikel pro Kalenderwoche geht, ein Blick auf den Graphen erlaubt eine schnelle Analyse der Situation. Etwaige Eigenheiten, Tendenzen oder Anomalien lassen sich am Graphen schnell feststellen und können anhand der tabellarischen Daten anschließend im Detail analysiert werden. Wer Webapplikationen in PHP schreibt, hat mit Hilfe der GD-Erweiterung die Möglichkeit, Grafiken dynamisch zu erzeugen. Die entsprechenden Funktionen sind gut dokumentiert und erlauben große Flexibilität beim Entwickeln. Wer allerdings Diagramme darstellen möchte, eventuell auch verschiedene Typen, muss einiges an Programmierarbeit leisten, um zu einem dynamisch skalierbaren, optisch ansprechenden und mathematisch korrekten Ergebnis zu kommen. JpGraph ist eine von Johan Persson entwickelte Klassenbibliothek, welche auf der GD-Erweiterung aufbaut und mit deren Hilfe komplexe und grafisch ansprechende Diagramme erstellt werden können. Dabei werden unter anderem Balken-, Torten-, Punkt- und Liniendiagramme ebenso unterstützt wie Scatterplots und Gantt-Charts; auch eine Kombination diverser Diagrammtypen in einem Graphen ist möglich, z.B. Balken- und Liniendiagramm. Auf Grund des objektorientierten Aufbaus von JpGraph reicht es, eine Instanz eines (Graphen-) Objekts anzulegen, deren gewünschte Eigenschaften zu setzen, ein oder mehrere Diagramme zu erzeugen und an den Graphen anzufügen und die nötigen Methoden aufzurufen, um einen Graphen zu schaffen. Installation JpGraph benötigt folgende Softwarepakete:
Das jeweils neueste JpGraph-Paket kann von [1] heruntergeladen (zum Zeitpunkt des Verfassens dieses Artikels handelt es sich um jpgraph1.7.tar.gz) und mit tar xvzf jpgraph1.7.tar.gz entpackt werden. Das daraus entstandene Verzeichnis jpgraph-1.7/ beinhaltet zwei Textdateien, welche Informationen zur Installation (README) und zur Lizenz (QPL.txt) enthalten, sowie das Unterverzeichnis src/, in welchem sich die Sourcen von JpGraph befinden. Das Hauptverzeichnis kann beliebig umbenannt und an eine passende Stelle im Filesystem verschoben werden; es ist nicht nötig, dass dieses Verzeichnis im DocumentRoot des Webservers liegt, also kann es z. B. nach /usr/local/jpgraph verschoben werden. Damit nicht bei jeder include-Anweisung der volle Pfad zu den Bibliotheken angegeben werden muss, empfiehlt es sich, den Include-Pfad von PHP entsprechend zu setzen. Dafür gibt es drei Möglichkeiten, welche je nach Benutzerberechtigung eingesetzt werden können. Wer die nötigen Schreibrechte besitzt, kann die Konfigurationsdatei php.ini editieren und die Option include_path entsprechend setzen, z. B.: include_path = ".:/usr/share/pear/:/usr/local/jpgraph/src"Eine andere Möglichkeit besteht darin, den Webserver so zu konfigurieren, dass er den Include-Pfad von PHP für alle Skripte unterhalb eines Verzeichnisses modifiziert. Dies kann z. B. bei Apache je nach Berechtigung direkt in der Webserverkonfiguration erfolgen oder auch in Form einer .htaccess-Datei im Dokumentenverzeichnis, falls der Benutzer die Rechte AllowOverride Options oder AllowOverride All besitzt. Anbei ein Beispiel: <Directory "/data/webs/agua/">Des Weiteren bleibt auch jenen, die keine der obengenannten Benutzerrechte haben, eine Möglichkeit, den Include-Pfad zu setzen: Mit der PHP-Funktion ini_set können bestimmte Konfigurationsoptionen zur Laufzeit geändert werden. Ein solcher Aufruf kann in jeder beliebigen Datei platziert werden, die zu Beginn aller Skripte eingebunden wird, und sieht folgendermaßen aus: ini_set("include_path", ini_get("include_path").":/usr/local/jpgraph/src");
KonfigurationIn der Datei jpgraph.php können alle Konfigurationsoptionen gesetzt werden, die das Verhalten von JpGraph beeinflussen. Diese Datei ist gut dokumentiert, weshalb im Folgenden nur einige wichtige Optionen beschrieben werden, die nach Bedarf gesetzt werden sollten. Aus Performancegründen kann es sinnvoll sein, mit JpGraph erstellte Graphen zu cachen, sodass ein Graph nicht bei jedem Aufruf neu generiert werden muss, sondern eventuell aus dem Cache geladen werden kann, was den Webserver stark entlastet. Wer lieber mit Cache arbeitet, setzt die Option USE_CACHE auf true, die Defaulteinstellung ist false. Die Option CACHE_DIR beinhaltet den vollen, absoluten Pfad des Verzeichnisses, in welchem gecachte Graphen gespeichert werden. Der Benutzer, unter welchem der Webserver und somit JpGraph läuft, muss Lese- und Schreibrechte für dieses Verzeichnis besitzen. Diese Option ist nur wirksam, wenn die vorher genannte Option USE_CACHE auf true gesetzt ist. Wer Version 1.xx von GD benutzt, muss die Option USE_LIBRARY_GD2 auf false setzen, wer GD 2.x einsetzt, setzt USE_LIBRARY_GD2 dementsprechend auf true. Ein Beispiel Nachdem nun alle Formalitäten erledigt sind, kann uns eigentlich nichts mehr davon abhalten, ein kleines Skript zu erstellen, welches ein einfaches Balkendiagramm erzeugt. Bei den Beispieldaten handelt es sich um die Anzahl der Downloads eines fiktiven Softwarepakets, welche in einer Woche getätigt wurden: <?phpDieses Beispiel kann betrachtet werden, indem die Datei direkt im Browser aufgerufen wird oder indem sie als Bild in eine HTML-Seite eingebunden wird. Dies erfolgt wie bei einem gewöhnlichen Bild mittels eines Image-Tags, welches auf das Listing zeigt: <img src=listing01.php> Mit diesen wenigen Zeilen Code ist bereits ein Diagramm erzeugt worden. Was geschieht eigentlich genau in diesem Listing?
Abb. 1: Einfaches Balkendiagramm Diese wenigen Anweisungen reichen aus, um aus einer Reihe von Zahlen einen übersichtlichen Graphen zu erstellen. Um diesen Graphen zu verschönern und lesbarer zu machen, können nun ein paar Beschriftungen angebracht werden. Wer statt des tristen Grau lieber einen neutralen, weißen Hintergrund hat, kann dies mit der Methode SetColor() setzen. Mit der Methode SetFrame() kann angegeben werden, ob ein Rahmen um den Graphen gezogen werden soll: $graph->SetColor("white");
Ein Graph macht sich mit Titel einfach besser. Des Weiteren ist eine Beschriftung der X- und Y-Achsen hilfreich. Titel und Achsenbeschriftungen sollen in diesem Beispiel fett dargestellt werden, deshalb werden folgende Zeilen vorangestellt: $graph->title->SetFont(FF_FONT1, FS_BOLD);Fonts Zur Textausgabe in Graphen stellt JpGraph drei interne Fonts zur Verfügung FF_FONT0, FF_FONT1 und FF_FONT2. Des Weiteren können die Stile FS_NORMAL, FS_BOLD (fett), FS_ITALIC (kursiv) und FS_BOLDIT (fett und kursiv) benutzt werden. Wer lieber einen anderen Font verwendet, kann TrueType-Fonts einsetzen, vorausgesetzt die Option TTF_DIR in jpgraph.php zeigt auf ein Verzeichnis, welches die entsprechenden Fontdateien enthält. Vordefinierte Fontfamilien sind FF_COURIER, FF_VERDANA, FF_TIMES, FF_HANDWRT, FF_COMIC, FF_ARIAL sowie FF_BOOK. Wer sich mutig fühlt und die standardmäßig definierten Fonts dieser Familien mit eigenen Fonts ersetzen möchte, kann dies im Konstruktor der Klasse TTF() bewirken. Nun soll ersichtlich sein, welche Wochentage durch die einzelnen Balken repräsentiert werden. Dazu wird ein neuer Array definiert, der die gleiche Anzahl an Elementen wie der Datenarray $data besitzt, und an die Methode SetTickLabels() der X-Achse übergeben: $labels = array("Sonntag", "Montag", "Dienstag", "Mittwoch",
Wem die Balkenfarbe nicht gefällt, der kann sowohl den Rahmen als auch die Fläche der Balken nach eigenem Gutdünken einfärben: $barplot->SetColor("red");
Um zu vermeiden, dass einige der Beschriftungen über den Bildrand hinausgehen, wird mit SetMargin() ein Abstand zum Rand festgelegt: $graph->img->SetMargin(40,40,40,60);Eins drauf Nun wird ein weiteres Diagramm hinzugefügt; es wäre nämlich interessant, den entsprechenden Jahresdurchschnitt der Downloads pro Wochentag darzustellen und über das bestehende Diagramm zu legen. Da diese Information als Liniendiagramm dargestellt werden soll, muss zunächst die entsprechende Bibliothek eingebunden werden. Ein neues Liniendiagramm wird mit den entsprechenden Daten erzeugt und gewünschte Eigenschaften wie Farbe und Form dieses Diagramms werden gesetzt. Die Datenpunkte auf der Linie können mittels mark->SetType(MARK_CIRCLE) hervorgehoben werden. Dadurch wird an den entsprechenden X/Y-Koordinaten ein nicht gefüllter Kreis eingezeichnet. Weitere gültige Parameter für diese Methode sind MARK_SQUARE (gefülltes Viereck), MARK_UTRIANGLE (nach oben zeigendes Dreieck), MARK_DTRIANGLE (nach unten zeigendes Dreieck), MARK_DIAMOND (Diamantenform). Mit der Methode SetCenter() wird das resultierende Diagramm zwecks erhöhten optischen Genusses ins Zentrum des Graphen gerückt. Dabei kümmert sich JpGraph selbst darum, das darunter liegende Balkendiagramm ebenfalls korrekt einzurücken. Wenn ein Linien- und ein Balkendiagramm zusammen dargestellt werden, wird das Liniendiagramm am linken Ende eines jeden Balkens ausgerichtet: include ("jpgraph_line.php");
Damit der Betrachter dieses Kunstwerks nun auch nach einigen Tagen noch weiß, was die Balken und die Linie bedeuten, wird eine Legende angebracht. Dazu wird jeweils für das Balkendiagramm und das Liniendiagramm die Methode SetLegend() mit dem zu setzenden Text aufgerufen. Damit die Legende nicht die Diagramme überdeckt, wird sie ans untere Ende des Graphen verschoben und dort ohne Schatten horizontal dargestellt. $graph->legend->setLayout(LEGEND_HOR);Es ist möglich, den einzelnen Balken des Diagramms mittels einer Imagemap diverse URLs zuzuweisen. Auf diese Weise kann z.B. von einem Balken direkt auf die entsprechende Seite mit den Tagesdaten in tabellarischer Form gelinkt werden. Des Weiteren können Bezeichnungen für den jeweiligen ALT-Tag eines Balkens angegeben werden. Solche Imagemaps sind für Balken-, Linien- und Tortendiagramme (2D und 3D) sowie für Scatter-Plots möglich. Im vorliegenden Beispiel soll nun eine Imagemap für die Balken und die Einzelwerte des Liniendiagramms angelegt werden. Dazu werden vier neue Arrays definiert: $btargets und $balts beinhalten die URLs der einzelnen Balken respektive deren Bezeichner, $ltargets und $lalts beinhalten die entsprechenden Daten des Liniendiagramms. Mit der Methode SetCSIMTargets() werden die nötigen Werte gesetzt, bevor das Balken- bzw. Liniendiagramm dem Graphen angefügt wird (vergl. Listing 1). Listing 1 $btargets = array("sonntag.php", "montag.php", "dienstag.php", "mittwoch.php",
Am Ende des Skripts muss der Graph diesmal zwangsläufig in eine Datei geschrieben werden. Dazu muss der Webserver Schreibrechte im entsprechenden Verzeichnis besitzen. Mit dem Aufruf der Methode Stroke("auto") kann der Graph in eine Datei geschrieben werden, deren Name von JpGraph automatisch vergeben wird. Danach wird die von JpGraph erzeugte Imagemap mit der Methode GetHTMLImageMap() im Browser ausgegeben und die Grafikdatei, welche den Graphen beinhaltet, wird angezeigt und mit der Imagemap verknüpft: $graph->Stroke("auto");
Der daraus resultierende Graph ist in Abbildung 2 zu sehen. Wer nun den Mauszeiger über einen Balken bzw. über einen der Kennpunkte der Linie bewegt, erhält über den ALT-Tag Informationen bzw. kann den zugewiesenen Link anklicken. Abb. 2: Graph mit Balken- und Liniendiagramm Wer andere Diagrammtypen gruppieren möchte oder komplexere Datenabhängigkeiten darstellen will, kann unter [2] nachsehen, wo Johan Persson eine Auswahl an möglichen Graphen angesammelt hat. Wer den Sourcecode zu einem der dargestellten Beispiele sehen will, braucht nur das entsprechende Bild anzuwählen. Diese Sourcen sind ein guter Ausgangspunkt zum Erstellen der ersten eigenen Graphen. GANTT-CHART Wer häufiger mit der Erstellung von Projekt- und Entwicklungsplänen zu tun hat, ist wahrscheinlich mit Gantt-Diagrammen - bzw. Gantt-Charts - vertraut. Henry Gantt, ein amerikanischer Industrieingenieur und Berater, erfand 1917 den nach ihm benannten Diagrammtyp, der zur Veranschaulichung zeitlicher Abläufe und ihrer einzelnen Teilabschnitte ebenso wie zur Visualisierung von Abhängigkeiten und Fortschritt der einzelnen Abschnitte dient. Mit Hilfe von Softwarepaketen wie MrProject, MS Project oder MS Visio können Gantt- Charts relativ komfortabel erzeugt werden. JpGraph bietet seit Version 1.5-BETA die Möglichkeit, Gantt-Charts zu erstellen. Im Folgenden soll dazu ein kleines Beispiel erstellt werden. Dazu muss zusätzlich zur Hauptbibliothek jpgraph.php die Bibliothek jpgraph_gantt.php eingebunden werden. Eine neue Instanz von GanttGraph() wird angelegt. Wer möchte, dass Breite und Höhe des auszugebenden Graphen automatisch berechnet werden, kann dem Konstruktor des Objekts jeweils den Wert 0 für die entsprechenden Parameter übergeben bzw. ihn auch gänzlich ohne Parameter aufrufen: $graph = new GanttGraph();Danach werden Titel sowie Untertitel des Graphen gesetzt: $graph->title->Set("Entwicklung Dispomodul");
Mit der Methode ShowHeaders() kann bestimmt werden, welche Informationen im Kopfteil des Diagramms angezeigt werden sollen. Zum Beispiel sollen die Jahreszahl, der Monat, die Wochentage und die Wochen angeführt werden: $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HDAY | GANTT_HWEEK);Anstatt der Kalenderwochen soll immer das Datum des ersten Tages der Woche (Montag) stehen: $graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY);In einem Datenarray werden nun die darzustellenden Informationen definiert. Dieser Array besteht wiederum aus einer Reihe von Arrays, von denen jeder die Daten für einen Balken des Gantt-Charts beinhaltet. Die benötigten Informationen sind Balkenposition, Bezeichnung, Start- und Enddatum sowie Fortschritt (siehe unten): $data = array(array(0, "Dispo", "2002-08-15","2002-09-25", 55),Anschließend werden in einer Schleife alle Elemente des Datenarrays durchlaufen und jeweils ein Balken mit den nötigen Parametern angelegt. Ein Balken erwartet folgende Parameter:
for ($i = 0; $i < count($data); ++$i)Die Fortschrittsanzeige des Prozesses wird auf den entsprechenden Prozentwert gesetzt. Dabei ist zu beachten, dass JpGraph einen Wert zwischen 0 und 1 erwartet, dementsprechend wird der Parameter im Beispiel durch 100 geteilt: $bar->progress->Set($data[$i][4] / 100);Jetzt werden einige optische Attribute des Balkens gesetzt. Der Rahmen wird schwarz gefärbt. Wenn es sich um eine Teilaufgabe handelt (im Beispiel erkennbar am Leerzeichen zu Beginn der Bezeichnung), wird die Füllfarbe auf grün gesetzt, andernfalls wird die Bezeichnung in fettem Text dargestellt und die Füllfarbe auf blau gesetzt: $bar->SetColor("black");
Nachdem die nötigen Werte und Eigenschaften gesetzt wurden, kann der Balken an das Diagramm angefügt und es kann mit dem nächsten Element der Schleife fortgefahren werden: $graph->Add($bar);Nach Durchlaufen aller Aufgaben in der Schleife wird schlussendlich der Gantt-Chart mit $graph->Stroke() ausgegeben (siehe Abbildung 3). Abb. 3: Gantt-Chart Graph() oder JpGraph()? Es sei auf folgendes hingewiesen: Mit Version 2.0 von JpGraph, deren Veröffentlichung für das erste Quartal 2003 geplant ist, findet eine zu beachtende Änderung statt: Um einen Namenskonflikt mit der Standardklasse Graph() zu vermeiden, die mit PHP im Laufe des nächsten Jahres kommen wird, wird die eigene Graph()-Klasse in JpGraph() umbenannt. Wer also Applikationen schreibt, welche mit JpGraph 2.0 oder später laufen sollen, kann eventuellen Problemen jetzt schon vorbeugen, indem er eine Wrapperklasse verwendet. Diese Wrapperklasse kann in einer eigenen Include-Datei definiert werden; nachdem alle benötigten JpGraph-Bibliotheken eingebunden sind, reicht die folgende Anweisung: class JpGraph extends GraphIn den einzelnen Skripts, die die Graphen erzeugen, wird dann diese Wrapperklasse eingebunden. Instanzen des Graphenobjekts werden dann jeweils mit $graph = new JpGraph($breite, $hoehe); erzeugt. Beim späteren Einsatz von JpGraph 2.0 reicht das Entfernen der Wrapperklasse. Um allgemeine Verwirrung zu vermeiden, wird in den Beispielen in diesem Artikel allerdings die klassische Variante und somit die Graph()-Klasse verwendet. Lizenz Während frühere Versionen der GPL unterlagen, wird JpGraph ab Version 1.6 unter der QPL (Qt Public License) verteilt. Bei der QPL handelt es sich um eine anerkannte Open Source-Lizenz, die allerdings nicht mit der GPL kompatibel ist (siehe [3] unter The Q Public License (QPL), Version 1.0). Zwar dürfen der QPL unterliegende Softwarepakete unmodifiziert weitergegeben werden, wer allerdings Änderungen oder Erweiterungen an solch einem Paket macht, darf diese Änderungen nicht mit dem Paket selbst verteilen, sondern nur als gesonderte Patches zur Verfügung stellen. Dabei bleibt dem ursprünglichen Autor des Softwarepakets das nicht-exklusive und gebührenfreie Recht vorbehalten, Patches von anderen Entwicklern in die offizielle Version mit einfließen zu lassen. Es ist gestattet, eine unter der QPL lizenzierte Bibliothek in einem GPL-Programm aufzurufen und zu verwenden, allerdings nicht, ein QPL-Programm mit einem GPL-Programm zu verschmelzen (siehe obengenannte URL für Details). Nähere Informationen zu den verschiedenen Lizenzen finden sich unter [4] sowie unter [5]. Wer ein unter der QPL lizenziertes Paket gerne kommerziell einsetzen und zusammen mit seiner Eigenentwicklung vertreiben möchte, ohne seinen Kunden aber alle Sourcen seines Programms bereit stellen zu müssen, dem bleibt die Möglichkeit, den Autor und Copyrightinhaber des Paketes zu kontaktieren. Dieser kann bei Bedarf und nach eigenem Gutdünken eigens lizenzierte Versionen an Interessierte vergeben. Fazit Mit JpGraph existiert eine Software für PHP, welche es erlaubt, auf schnelle, einfache und optisch ansprechende Weise Graphen zu erzeugen und somit Daten zu visualisieren. Dabei besticht JpGraph vor allem durch die Vielfalt der möglichen Diagrammtypen und die Möglichkeit, mehrere, auch unterschiedliche Diagramme in einem Graphen darzustellen. Der Autor Johan Persson verbessert und erweitert JpGraph kontinuierlich; Interessierte können den Release-Plan mit Zeiten und Angaben zu den zu erwartenden neuen Features unter [6] einsehen. Die vollständigen und mit Kommentaren versehenen Sourcen zu den Beispielen finden sich auf der Heft-CD. Florian Lanthaler ist freiberuflicher Entwickler und Berater in Meran (Südtirol), mit den Schwerpunkten Web-basierte Applikationen sowie Datenbanken und arbeitet zur Zeit an einer zum Großteil Web-basierten Software zur Verwaltung und Visualisierung von Prozess-, Produktions- und Lagerdaten für einen Industriekonzern. Er setzt JpGraph unter anderem im Open-Source-Projekt phpaga ein [phpaga.net/]. Links
|
||
|