Portál AbcLinuxu, 26. května 2024 23:42

Použití gnuplot pro tvorbu grafů v PHP - I

26. 4. 2004 | Petr Bravenec
Články - Použití gnuplot pro tvorbu grafů v PHP - I  

Určitě se mnoho z vás dostalo do situace, kdy jste potřebovali prezentovat svá data na internetu v grafické podobě. V článku najdete návod pro snadné vytvoření dynamických grafů.

Úvod

Má-li být graf statický, je jednou z možností nastartovat nějaký kancelářský balík a uložit ručně vytvořený graf jako obrázek. Pro tvorbu dynamických grafů běžná distribuce Linuxu zdánlivě nic rozumného nenabízí. Pro jednodušší grafy lze ale celkem snadno použít program gnuplot, který je běžnou součástí různých distribucí už dlouhá léta.

gnuplot je určený spíše na vizualizaci vědeckých dat. Jenže co si budeme vykládat - veškerá matematická věda nakonec stejně skončí u počítání peněz. Použitelnost programu gnuplot je pro grafy ekonomického zaměření ale poněkud omezená. Nos budou nad výstupy programu gnuplot ohrnovat především lidé s otiskem telefonního sluchátka na uchu - obchodníci, marketingoví specialisté a jim podobná sorta podnikové fauny. Grafy z gnuplot jim budou připadat málo barevné, málo koláčové, málo interaktivní, málo jásavé a celkově hnusné. Ovšem pomineme-li nároky této specifické kategorie lidí, dá se gnuplot použít i na velikou spoustu ekonomických a statistických grafů.

Typické použití programu gnuplot můžete vidět na příkladu grafu charakteristiky solárního článku.

Charakteristika solárního článku - typické využítí gnuplot

Interaktivní režim - seznámení s gnuplot

gnuplot nastartujte nejlépe v X-terminálu příkazem gnuplot. Dostanete se na povelovou řádku - i když ta není zdaleka tak komfortní jako třeba povelová řádka bash, můžete v ní procházet příkazy v historii a editovat je (marně ale budete toužit po příkazové řádce ve stylu svého oblíbeného editoru vi). Můžete hned vyzkoušet první graf:

plot sin(x);

gnuplot si volí meze grafu podle vlastního uvážení. Pokud vám nevyhovují meze vybrané programem, můžete zadat hranice grafu vlastní:

plot [-3.14:3.14] sin(x);

Hranice lze zadat jak pro vodorovnou, tak pro svislou osu. Hranice se zadávají v hranatých závorkách hned za příkazem plot, ještě před zadáním vykreslovaných funkcí. První zadaná hranice platí pro vodorovnou osu - v našem příkladu se zobrazuje sinusovka od -3.14 do +3.14. Další v hranatých závorkách zadaná hranice platí pro osu svislou.

gnuplot umí pracovat i s proměnnými a funkcemi. Složitější funkce lze naprogramovat předem a použít později například na výpočty, iterace a jiné různé psí kusy:

pi=3.1415926535;
f(x)=sin(x)/cos(x)
plot [-pi:pi] f(x);

Spíše než funkce nás bude zajímat zobrazování dat z externích zdrojů. Vytvořte si textový soubor se jménem x.data s následujícím (či podobným obsahem):

1 40 5
2 50 6
3 50 8
6 70 3
8 12 2
9 10 1
10 6 4

V gnuplot si pak vyzkoušejte několik jednoduchých grafů:

plot "x.data";
plot "x.data" using 1 with lines;
plot "x.data" using 2 with lines;
plot "x.data" using 1:2 with lines;

První příkaz vykreslí do grafu několik puntíků - i když je v tomto případě jednoduché vysledovat podle dat, co gnuplot kreslí, ve složitějších grafech to není tak snadné. Parametrem using můžete lépe specifikovat, jak má gnuplot datový soubor interpretovat.

Příkaz plot s parametrem using 1 nakreslí prostý výčet hodnot z prvního sloupce souboru, plot s parametrem using 2 nakreslí výčet hodnot z druhého sloupce souboru. Parametr using 1:2 použije první sloupec jako vodorovnou souřadnici a druhý sloupec jako svislou souřadnici.

Nakonec jsem si nechal trochu složitější příklad grafu, který lze využít například pro zobrazení průměrů, související standardní odchylky a podobných statistických záležitostí:

plot "x.data" using 1:2 with lines, "x.data" using 1:2:3 with errorbars;

Příkazem plot nemusíte vykreslovat do grafu pouze jednu hodnotu - v tomto případě se nakreslí normální čárový graf a do každého zadaného bodu se nakreslí ještě svislá čára, jejíž délka je určená třetím zadaným parametrem (using 1:2:3).

Dávkový režim

Stejně dobře, jako funguje gnuplot v interaktivní režimu, může pracovat v režimu dávkovém, a graf vykreslovat místo na obrazovku přímo ve formátu například GIF na standardní výstup. Toho se dá využít a přesměrovat výstup přes http server přímo na http klienta.

Starší verze programu gnuplot umějí pracovat ještě s formátem GIF, novější verze (určitě verze 4) už formát GIF nepodporují a alespoň podle manuálu při požadavku o formát GIF generují místo toho formát PNG.

Bohužel starší verze programu gnuplot neumožňují při generování PNG formátu zadat ani tak základní věc, jako je požadovaná velikost grafu. Vzhledem k tomu a vzhledem k velkému množství historických grafů používám vesele formát GIF ve verzi 3.7 a možnosti, které mi nabízejí novější verze, jsem s lehkým srdcem oželel. Ve verzi 4 se podpora PNG formátu něco málo změnila a použitelným se tak stal i formát PNG. Protože ale nemám nikde nainstalovanou verzi 4, použiji v příkladech raději formát GIF a nebudu riskovat, že něco z příkladů nebude fungovat, protože to nebylo kde vyzkoušet.

Pro volání programu gnuplot si vytvořte jednoduchý skript v PHP. Skriptu se v proměnné TEXT posílá jediný parametr - jméno souboru, ve kterém je uložený příkazový soubor pro gnuplot.

<?
Header("Content-type: image/gif");
Header("Pragma: no-cache");
Header("Cache-Control: no-cache");
Header("Expires: ".GMDate("D, d M Y H:i:s")." GMT");
$TEXT = basename ($TEXT);
$TEXT = "/tmp/".$TEXT;
# Nelze použít funkci PassThru() - nebafruje a je pomalá.
$fd = popen("gnuplot $TEXT", "r");
while ( ($X = fread($fd, 8192)) ) {
    print $X;
    }
fclose ($fd);
# Datové a příkazové soubory NEMAZAT, jinak nelze
# graf vytisknout v MSIE!
?>

Jako ukázkový příklad jsem zvolil Z-graf pro sledování měsíčního plánu výroby. Data i s příkazy pro tvorbu tabulek jsou přibalena v souboru gnuplot.sql. Předpokládám databázi PostgreSQL.

Z-graf: plnění měsíčního plánu výroby

Celý graf byl vytvořený následujícím skriptem. Kvůli jednoduchosti není ve skriptu prakticky žádné ošetření chyb. Snažil jsem se do skriptu napsat něco málo komentářů, takže by vám jeho pochopení nemuselo dělat větší potíže.

<!DOCTYPE HTML
    PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<?
# Připojení k databázi
$DB = pg_connect ("host=dbserver dbname=pokusy");

# Dotaz vyhledávající potřebná data v tabulkách.
$ri = pg_exec ($DB, "
set datestyle to 'german';
select 
   to_char(datum, 'DD.MM.') as datum,
   vyroba as denni_vyroba,
   extract('dow' from datum) as dow,
   int4(datum - '1.4.2004'::date + 1) as den,
   (select sum(vyroba)
      from pk_vyroba v2
     where v2.datum>=v1.datum-'30 days'::interval
       and v2.datum<=v1.datum
       ) as klouzavy_soucet,
   (select sum(vyroba)
      from pk_vyroba v3
     where v3.datum<=v1.datum
       and v3.datum>='1.4.2004'::date) as vyrobeno
    from pk_vyroba v1
   where v1.datum>='1.4.2004'
    order by datum;
");

# Data máme v paměti - uložíme si je do dočasného souboru,    
# ze kterého je pak bude lovit gnuplot.
$Fd1 = tempnam ("/tmp", "graf.dt.");
$fd = fopen ($Fd1, "w");
for ($i=0; $i<pg_numrows($ri); $i++) {
    $data = pg_fetch_object ($ri, $i);
    # Do datového souboru zapíšeme všechny hodnoty.
    fwrite ($fd, $data->den." ".
                 $data->denni_vyroba." ".
                 $data->vyrobeno." ".
                 $data->klouzavy_soucet."\n");
    }
fclose ($fd);

# Nyní vytvoříme soubor s příkazy pro gnuplot
$Fprg = tempnam ("/tmp", "graf.pr.");
$fd = fopen ($Fprg, "w");
fwrite ($fd, "
set terminal gif transparent size 480, 340 \\
    xffffff x000000 xa0a0a0 x909000 x000000 xaa9090
set output;
set grid;
set key left reverse;
set bmargin 4; set xtics rotate (\\
");

# Popisky na vodorovné ose - kreslí se pouze někde.
# V příkazovém souboru vypadají popisky asi takto:
# set xtics rotate (\
#      "1.4.2004" 1,\
#      "2.4.2004" 2,\
#      "3.4.2004" 3);
for ($ODDELOVAC="", $i=0; $i<pg_numrows($ri); $i++) {
    $data = pg_fetch_object($ri, $i);
    if ($data->dow==0 || $data->dow==6) continue;
    fwrite ($fd, "$ODDELOVAC\"$data->datum\" $data->den");
    $ODDELOVAC=",\\\n";
    }
fwrite ($fd, ");");

# Nalezení plánovaného objemu výroby v databázi
$ri = pg_exec ($DB, "select 
     int4(datum-'1.4.2004'::date+1) as den, plan 
     from pk_plan;");
$data = pg_fetch_object ($ri, 0);

fwrite ($fd, "plot [1:30] \
  \"$Fd1\" using 1:2 title \"Denní výroba\" with linespoints,\
  \"$Fd1\" using 1:3 title \"Vyrobeno\" with linespoints,\
  \"$Fd1\" using 1:4 title \"Klouzavý úhrn\" with linespoints,\
  \"-\"    using 1:2 title \"Plán\" with lines;
0 0
$data->den $data->plan
e
");
fclose ($fd);

print "<img src=\"graf.php3?TEXT=".URLencode($Fprg)."\">\n";

pg_close($DB)
?>
</body>
</html>

Příště...

Ve druhém a posledním dílu článku naleznete několik šikovných fíglů, které vám mimo jiné pomohou graf vybarvit, opatřit popiskami atp.

Související články

Použití gnuplot pro tvorbu grafů v PHP - II
Přihlašování uživatelů do webové aplikace v PHP
Praktický návod k PgSQL
Tvorba databází v MySQL

Odkazy a zdroje

gnuplot homepage
PHP homepage

Další články z této rubriky

LLVM a Clang – více než dobrá náhrada za GCC
Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Reverzujeme ovladače pro USB HID zařízení
Linux: systémové volání splice()
Programování v jazyce Vala - základní prvky jazyka

Diskuse k tomuto článku

26.4.2004 10:16 gregy
Rozbalit Rozbalit vše gif vytvareny na serveru
Odpovědět | Sbalit | Link | Blokovat | Admin
dnes jsem na zive.cz narazil na tvrzeni, ze Unisys vyžaduje platby pro GIF vytvářený na straně serveru.

je to pravda ?
26.4.2004 13:26 Hynek (Pichi) Vychodil | skóre: 43 | blog: Pichi | Brno
Rozbalit Rozbalit vše Re: gif vytvareny na serveru
Proc by jsi mel pouzivat takovy zastarali stupidni format jako je gif a nepouzil treba png?
XML je zbytečný, pomalý, nešikovný balast, znovu vynalézané kolo a ještě ke všemu šišaté, těžké a kýčovitě pomalované.
26.4.2004 16:35 Leoš Literák | skóre: 74 | blog: LL | Praha
Rozbalit Rozbalit vše Re: gif vytvareny na serveru
Opravdu dneska? Ne pred dvema roky? Opravdu se ten server jmenuje mrtve.cz, oops, chtel jsem rici zive.cz? ;-) Mam totiz takovy silny pocit, ze patent na LZW, kterym se Unisys zastitoval, uz pred par mesici vyprsel.

A Unisys vyzadoval platby za kazde pouziti softwaru, jehoz autori neodvedli licencni poplatky. Takze se to teoreticky tykalo vsech Open Source projektu vcetne GIMPu.
Zakladatel tohoto portálu. Twitter, LinkedIn, blog, StackOverflow
27.4.2004 01:10 Petr Mach
Rozbalit Rozbalit vše Re: gif vytvareny na serveru
Tak to pozor, on to ma v ruznych zemich patentovano v ruzne dobe a tak vyprselo to jen v nekterych zemich.
27.4.2004 08:16 gregy
Rozbalit Rozbalit vše Re: gif vytvareny na serveru
nekdo to zminil v diskusi, neslo o zpravu zive.cz. vim, ze pred nekolika lety byl humbuk s prevodem gif->png.

a jak uz to byva, pouzije se nejdrive to co je v prikladech (viz napr. mysql a postgresql v php).
28.4.2004 15:45 Petr Mikulik
Rozbalit Rozbalit vše Re: gif vytvareny na serveru
Vyprsel tusim v Americe, v Evrope asi az za rok.
26.4.2004 11:04 Martin Kratochvil | skóre: 3
Rozbalit Rozbalit vše JPGraph
Odpovědět | Sbalit | Link | Blokovat | Admin
Ten kdo nechce pouzivat GnuPLOT, muze pouzivat jpgraph (skripty do php) - velice uzitecne podminkou je gd knihovna (do /etc/php4/php.ini: extensions=gd.so )

http://www.aditus.nu/jpgraph/

MaKr
28.4.2004 15:44 Petr Mikulik
Rozbalit Rozbalit vše Re: JPGraph
gnuplot tez pouziva gd knihovnu
26.4.2004 12:42 Pritf
Rozbalit Rozbalit vše log
Odpovědět | Sbalit | Link | Blokovat | Admin
Poradite jak v gnuplotu udelat graf s osou v logaritmickem meritku? (tak aby byl i grid logaritmicky)
Petr Bravenec avatar 26.4.2004 12:47 Petr Bravenec | skóre: 43 | blog: Bravenec
Rozbalit Rozbalit vše Re: log
set logscale y 10

nastaví logaritmickou stupnici se základem 10 na svislé ose
Petr Bravenec - Hobrasoft s.r.o.
28.4.2004 15:46 Petr Mikulik
Rozbalit Rozbalit vše Re: log
Anebo zmacknete horkou klavesu "l" ve svem oblibenem interaktivnim terminalu (X11, OS/2 PM, Windows, ...)
26.4.2004 13:27 Yeti
Rozbalit Rozbalit vše Gnuplot 4
Odpovědět | Sbalit | Link | Blokovat | Admin
Protože ale nemám nikde nainstalovanou verzi 4

Tak to rozhodně rychle naprav. Používal jsem i alfa a beta verze gnuplotu 4 a gnuplot bez pm3d už ani nepovažuji za funkční gnuplot... ;)
Petr Bravenec avatar 26.4.2004 13:49 Petr Bravenec | skóre: 43 | blog: Bravenec
Rozbalit Rozbalit vše Re: Gnuplot 4
Tak jsem zkusil nainstalovat Gnuplot 4 - a u png formátu stále nelze nastavit požadovanou velikost formátu. Takže zůstávám u gifu :-(
Petr Bravenec - Hobrasoft s.r.o.
27.4.2004 10:35 Yeti
Rozbalit Rozbalit vše Re: Gnuplot 4
myslíš set term png ... size x,y? tak to mi normálně funguje, používám to běžně. nebo co je velikost formátu?
Petr Bravenec avatar 27.4.2004 10:48 Petr Bravenec | skóre: 43 | blog: Bravenec
Rozbalit Rozbalit vše Re: Gnuplot 4
Ano, myslím set term png size x,y - ať provádím co provádím, řve to, že "expecting: {small, medium, large}, or {monochrome, gray, color}" - zastaví se vždy na slově size :-(
Petr Bravenec - Hobrasoft s.r.o.
27.4.2004 12:52 Yeti
Rozbalit Rozbalit vše Re: Gnuplot 4
To nechápu. Gnuplot, verze 4.0, patchlevel 0:
gnuplot> set term png size 400,300
Terminal type set to 'png'
Options are 'nocrop medium size 400,300 '
gnuplot>
28.4.2004 15:50 Petr Mikulik
Rozbalit Rozbalit vše Re: Gnuplot 4
Doporucuji k prostudovani "help png". Funguje to korektne. Gnuplot 4.0:

gnuplot> set term png size 555,666 font arial 28 Terminal type set to 'png' Options are 'nocrop font arial 28 size 555,666 ' gnuplot> show term

terminal type is png nocrop font arial 28 size 555,666

gnuplot>
13.5.2004 19:24 tyctor
Rozbalit Rozbalit vše Re: Gnuplot 4
asi uz to vies, ale pre istotu: chyba ti gd kniznica, mne robil to iste az pokial som ju nenainstaloval. (http://www.boutell.com/gd/)

pekny den
egg avatar 26.4.2004 13:57 egg | skóre: 20 | Praha
Rozbalit Rozbalit vše Hydronet
Odpovědět | Sbalit | Link | Blokovat | Admin
Mám chuť si zase přihřát polívčičku. ;-) Gnuplot používáme k prezentaci dat Hydronetu. Ovšem grafy se teď nekreslí na požádání uživatele, gnuplot je volaný co pár minut z crona. Způsob popsaný v článku je určitě lepší, protože si uživatel bude moci navolit, jak má graf vypadat. Díky za článek, to se bude hodit!
Proč led klouže? --Aldebaran bulletin
26.4.2004 21:15 Jáchym Čepický | skóre: 29 | blog: U_Jachyma
Rozbalit Rozbalit vše R
Odpovědět | Sbalit | Link | Blokovat | Admin
Zapomeňte na GNU PLOT, přichází R! :-D

Rko je IMHO fakt o dost lepší, než GNU Plot ... možnosti formátování grafů mi přijdou jako neskutečné. Umí export do kde čeho a podle mě se dá i jaksi "lépe uchopit", než třeba GNU Plot. Nezanedbatelnou možností je možnost dělání statistik. Je fakt, že si ale žádá o něco více systémových prosředků...

Zajímal by mě názor někoho dalšího, kdo má s objema produkty zkušenosti...

Jáchym

Petr Bravenec avatar 27.4.2004 06:15 Petr Bravenec | skóre: 43 | blog: Bravenec
Rozbalit Rozbalit vše Re: R
Čas od času, když mi přestává GnuPlot stačit, si vzpomenu na R a chvíli si s ním hraju. Nevím, jestli je to mým zkostnatělým myšlením, ale nikdy jsem nedovedl dotáhnout práci s R do nějakého zdárného konce. Připadá mi, že R je orientovaný hodně na různé statistické funkce a na programování - tyhle věci pro mě dělá databáze s mnohem větší efektivitou. A ta grafika se mi v tom beznadějně ztrácela...
Petr Bravenec - Hobrasoft s.r.o.
27.4.2004 12:45 Yeti
Rozbalit Rozbalit vše Re: GNU Plot
Nevyvolávej prosím zmatek psaním gnuplot jako GNU Plot. Na gnuplotu není naprosto nic GNU, ani není pod GPL licencí.

Někde jsem kdysi viděl i vysvětlené, jak jeho název vznikl, ale už jsem to zapomněl...
27.4.2004 15:21 Jáchym Čepický | skóre: 29 | blog: U_Jachyma
Rozbalit Rozbalit vše Re: GNU Plot
dík za upozornění
28.4.2004 15:43 Petr Mikulik
Rozbalit Rozbalit vše Re: GNU Plot
Ano, gnuplot je opravdu gnuplot a ne GnuPlot, Gnu Plot, GNUPlot ani zadny jiny patvar.

A kdeze je to zodpovezeno? No prece na FAQ -- www.gnuplot.info/faq/
28.4.2004 15:55 unchallenger | skóre: 69 | blog: unchallenger
Rozbalit Rozbalit vše Re: GNU Plot
A hele ;) Myslel jsem si, že to tam musí někde být, ale nacházel jsem pořád jen FAQ 1.7 Does gnuplot have anything to do with the FSF and the GNU project?, kde to není a na FAQ 1.2 se neodkazuje...
28.4.2004 16:08 Petr Mikulik
Rozbalit Rozbalit vše Ruzne ke clanku
Odpovědět | Sbalit | Link | Blokovat | Admin
Mam par technickych poznamek ke clanku:

- Spravne je gnuplot, nikoliv GnuPlot --- prectete si prosim FAQ

- > novejsí verze (urcite verze 4) uz formát GIF nepodporují

Tohle neni problem gnuplotu, ale Vas -- mate-li zakoupenu radnou licenci GIFu od firmy Unisys, muzete si GIFy generovat podle libosti diky patricne verze knihovny gd. V Evrope vyprsi licence myslim pristi rok. Tj. nemate-li licenci a generujete GIFy, muzete mit problem...

Viz README a INSTALL gnuplotu od 3.7.(1? 2? 3?) a vyse, tam je to popsane poradne.

- >Ve verzi 4 se podpora PNG formátu nìco málo zmenila Zmenila se tedy poradne! - >alespon podle manuálu při požadavku o formát GIF generují místo toho formát PNG.

Proc "alespon"? Je to tam snad napsane jasne, ne? http://www.gnuplot.info/docs/gnuplot.html#What_is_New_in_Version_4.0 => `gif`: Support for this terminal has been dropped in favour of the `png` format for legal reasons; under usual configure conditions, old scripts that request gif will work but will produce a `png` file instead.

- >Grafy z GnuPlot jim budou připadat málo barevné, málo koláčové, málo interaktivní, málo jásavé a celkově hnusné.

* ??? Videl jste screenshoty na www.gnuplot.info?

* Interaktivni terminaly jsou dispozici uz dlouha leta: na OS/2 od roku 1998, X11 od 2000, Windows 2001. Jenom byly v "development" verzi gnuplotu, ne v oficialni.

* Jasave si je muzete udelat, jak chcete. 'help palette'.

* Kolacovy typ grafu neni typem grafu pro vedecke grafy, takze vycitat gnuplotu, ze ho nepodporuje, neni uplne korektni.

* > není zdaleka tak komfortní jako třeba povelová řádka bash

A zkompiloval jste si gnuplot s GNU readline? ./configure --with-readline=gnu

* > marně ale budete toužit po příkazové řádce ve stylu svého oblíbeného editoru vi)

Asi po tom nikdo nikdy netouzil, kdyz to dosud nikdo nedoprogramoval. Anebo -- jestli GNU readline podporuje vi mod, tak to podporuje i gnuplot.

Jinak: neni duvod neprejit na gnuplot verze 4.0!

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.