Hlavní navigace

Nástroje pro tvorbu grafů a diagramů z příkazové řádky

22. 1. 2015
Doba čtení: 20 minut

Sdílet

Ve světě otevřeného softwaru existuje poměrně velké množství aplikací určených pro interaktivní tvorbu diagramů. V mnoha případech je však výhodnější použít nástroje volané z příkazové řádky. Mezi takové nástroje patří poměrně známý gnuplot a Graphviz a taktéž překvapivě snadno ovladatelná utilitka Ditaa.

Obsah

1. Nástroje pro tvorbu grafů a diagramů z příkazové řádky

2. Základní informace o aplikaci gnuplot

3. Vytváření grafů funkcí a grafů vytvořených z externích dat

4. Styly vykreslovaného grafu

5. Trojrozměrné grafy

6. Balíček nástrojů Graphviz

7. Jednoduché neorientované grafy

8. Orientované grafy

9. Praktický příklad – zobrazení závislostí mezi instalovanými balíčky

10. Ditaa aneb uživatelsky přívětivá tvorba diagramů z ASCII artu

11. Jednoduché příklady

12. Složitější příklady: styly spojnic

13. Změna stylu uzlů

14. Odkazy na Internetu

1. Nástroje pro tvorbu grafů a diagramů z příkazové řádky

V dnes již velmi rozsáhlé nabídce programů s otevřeným zdrojovým kódem můžeme nalézt poměrně velké množství aplikací určených pro interaktivní tvorbu diagramů a grafů. Jedná se například o známý program LibreOffice Draw či o aplikaci Dia, které jsou určeny mj. i pro tvorbu rozličných diagramů. Dvourozměrné a někdy i trojrozměrné grafy získané z různých typů dat lze vytvářet například v GNU Octave či (při menších nárocích) i v programu KChart. V praxi se však velmi často setkáme i s nutností vytvářet různé diagramy a grafy s využitím nástrojů ovládaných z příkazové řádky, tj. neinteraktivně a bez využití grafického uživatelského rozhraní.

Těchto nástrojů taktéž existuje celá řada, například specializovaný RRDtool či Ploticus. My se v dnešním článku seznámíme s poměrně známou aplikací gnuplot, dále pak s nástroji dostupnými v balíčku Graphviz a na závěr si popíšeme velmi zajímavý a přitom snadno ovladatelný nástroj nazvaný Ditaa, který se stává populární například mezi autory píšícími své knihy (či skripta) v jednoduchých značkovacích jazycích typu AsciiDoc či Markdown (evidentně tento nástroj vyhovuje filozofii takto zaměřených autorů).

2. Základní informace o aplikaci gnuplot

Aplikace gnuplot je určena pro tvorbu plošných (2D), ale i prostorových (3D) grafů, včetně možností vizualizace vektorových polí. Přitom se jedná o program, který je možné v celé šíři ovládat pouze z příkazové řádky, a to buď s využitím uživatelsky vytvořených skriptů, nebo interaktivním způsobem, tj. postupným zadáváním a následným prováděním příkazů zapsaných na standardní vstup (stdin), což většinou znamená z klávesnice, ale standardní vstup je samozřejmě možné pomocí prostředků operačního systému přesměrovat a použít místo něj například výstup z jiného běžícího procesu. Vývoj této aplikace probíhal velmi dlouho (poprvé jsem se s gnuplotem setkal ještě v dobách kralování DOSu na počítačích s procesorem 386 a pouhými čtyřmi megabyty RAM) a mimo jiné i proto se dnes jedná o jeden z nejvíce propracovaných programů určených pro dávkovou tvorbu grafů (mezi další používané aplikace s podobným zaměřením patří například plotutils, což je taktéž utilita, resp. sada utilit šířených pod GNU licencí).

Další předností gnuplotu je – minimálně pro programátory – zabudování poměrně sofistikovaného příkazového jazyka, pomocí kterého je možné zadávat a spouštět makra řídící načtení dat uložených v externím souboru, vytvoření grafu a jeho uložení, resp. export do zvoleného formátu atd. gnuplot se také vyznačuje malým počtem interních chyb – to je důležité zejména při dávkovém vytváření mnoha grafů, kdy není možná jejich důsledná kontrola člověkem a musíme se spolehnout na to, že grafy budou po automatickém zpracování korektní. gnuplot je k dispozici pro mnoho platforem, zjednodušeně je možné říci, že tam, kde se rozběhne nějaký překladač ANSI C (dokonce i šestnáctibitový), je možné zprovoznit i gnuplot.

Při popisu dalších vlastností gnuplotu začněme – možná poněkud netypicky – popisem možností exportu vytvořených grafů do některých podporovaných souborových formátů. Při výstupu grafů je možné použít jak rastrové, tak i vektorové grafické souborové formáty. Oba dva typy grafických formátů jsou totiž důležité: rastrovou grafiku využijeme například při publikování grafů na Internetu, vektorová grafika se naopak hodí při přípravě publikací určených pro tisk. Mezi podporované rastrové formáty patří PBM (Portable BitMap), PNG (Portable Network Graphics – vhodné pro web), GIF (pouze s podporou dalších knihoven), JPEG apod. Z vektorových formátů je podporován především PostScript, dále je pak možné provést výstup například do LATEXu, DXF (Drawing Interchange File Format – formát podporovaný prakticky každým CAD systémem) a do SVG.

S využitím gnuplotu je možné vytvářet velké množství grafů. Mezi nejjednodušší a současně také nejpoužívanější grafy patří zobrazení průběhů funkcí s jednou závislou a jednou nezávislou proměnnou. Takové funkce se vytvoří velmi jednoduše, například obligátní sinusovka vznikne příkazem:

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot1.png'
plot sin(x)

Obrázek 1: Graf funkce jedné nezávislé proměnné.

Pokud je zapotřebí na grafu vyznačit průběhy více funkcí, není nic jednoduššího, než zadat například tento příkaz:

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot2.png'
plot sin(x)/x, sin(x)/(x**2+1)

Jak je patrné z druhého obrázku, nastaví gnuplot automaticky i limity pro obě osy grafu. Tyto limity je však možné specifikovat i ručně či ve skriptu (to je nutné například při vytváření grafů, které se mají navzájem porovnávat).

Obrázek 1: Graf dvou funkcí jedné nezávislé proměnné.

Kromě grafů funkcí jedné nezávislé proměnné je však možné vytvořit složitější grafy, například parametrickou křivku:

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot3.png'
i = {0.0,1.0}
set parametric
plot real(exp(i*t)), imag(exp(i*t*3))

Obrázek 3: Graf parametricky zadané funkce.

3. Vytváření grafů funkcí a grafů vytvořených z externích dat

Aplikace gnuplot podporuje i tvorbu grafů s využitím externích dat. Externí datové soubory, ve kterých jsou numerická data uložena, nemusí mít nějakou speciální předem předepsanou strukturu. Právě naopak, pomocí poměrně jednoduché syntaxe (příkazem using) se gnuplot nakonfiguruje přesně podle struktury konkrétního souboru, takže je možné zpracovat data vytvořená například ve formátu CSV apod. V podstatě je „pouze“ nutné specifikovat, které numerické hodnoty je potřeba ze souboru načíst a v jakém formátu se mají tyto údaje načítat. Gnuplot poté automaticky provede všechny potřebné konverze dat, data načte, zpracuje a následně vytvoří (tj. vykreslí či uloží do rastrového či vektorového souboru) požadovaný graf. Ukažme si tedy jednoduchý příklad, pomocí kterého je vykreslen graf sestrojený z několika hodnot uložených v textovém souboru. Příkaz provádějící načtení hodnot z textového souboru „test.txt“ a následné vytvoření grafu bude mít tento tvar:

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot4.png'
plot "test.txt"

Datový soubor „test.txt“ byl získán následujícím skriptem napsaným v programovacím jazyku Lua:

local x
 
for x=0.1, 25.0, 0.1 do
    local y = math.sin(x)/x
    print(y)
end
 

Obrázek 4: Graf získaný z bodů uložených v externím souboru „test.txt“, ve kterém jsou specifikovány pouze jejich x-ové souřadnice.

4. Styly vykreslovaného grafu

Pokud by z libovolných důvodů nevyhovoval způsob kreslení jednotlivých bodů, ze kterých se graf skládá, pomocí malých křížků, je možné při kresbě grafu zadat specifikátor stylu kreslení – ten rozšiřuje možnosti příkazu plot. Existuje poměrně velké množství různých stylů, všechny si ukážeme na obrázcích, přičemž u každého popisu stylu bude uveden i příslušný příkaz, který vedl k tvorbě grafu. Na následujících screenshotech si všimněte, že v pravém horním rohu každého grafu je pomocí značky ukázáno, jaký styl (a mimo jiné také barva) je pro daný průběh funkce použit. To je výhodné zejména při slučování více průběhů funkcí do jednoho grafu.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot5.png'
plot "test.txt" with lines

Obrázek 5: Graf získaný předchozím skriptem, vrcholy jsou propojeny úsečkami.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot6.png'
plot "test.txt" with dots

Obrázek 6: Graf získaný předchozím skriptem, vrcholy se zobrazují formou bodů.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot7.png'
plot "test.txt" with linespoints

Obrázek 7: Graf získaný předchozím skriptem, kombinace předchozích dvou grafů.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot8.png'
plot "test.txt" with steps

Obrázek 8: Graf získaný předchozím skriptem, „schody“.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot9.png'
plot "test.txt" with boxes

Obrázek 9: Graf získaný předchozím skriptem, obdélníky začínající na x-ové ose.

5. Trojrozměrné grafy

gnuplot dokáže vykreslovat i trojrozměrné grafy, takže se v rychlosti podívejme na několik příkladů. Pro vytvoření trojrozměrných grafů, zejména grafů funkcí dvou nezávislých proměnných, se používá příkaz splot, kde písmeno „s“ značí surface.

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot10.png'
splot x*y

Obrázek 10: Trojrozměrný graf získaný předchozím skriptem.

Poněkud složitější příklad se specifikací rozsahu v osách x a y:

set terminal png size 400,300 enhanced font "Helvetica,10"
set output 'gnuplot11.png'
set xrange [-10:10]
set yrange [-10:10]
splot sin(sqrt(x**2+y**2))/sqrt(x**2+y**2)

Obrázek 11: Trojrozměrný graf získaný předchozím skriptem.

6. Balíček nástrojů Graphviz

Zatímco nástroj gnuplot popsaný – i když pouze ve velmi zkrácené podobě – v předchozích pěti kapitolách je určený převážně pro kreslení různých typů dvourozměrných a trojrozměrných grafů, je v mnoha dokumentech popř. v různých reportech nutné vytvářet diagramy s uzly propojenými neorientovanými či orientovanými hranami. Pro tento účel je vhodné ve většině případů použít balíček nástrojů nazvaný Graphviz. V tomto balíčku nalezneme především utilitu dot, která na základě textové definice orientovaného či neorientovaného grafu vytvoří rastrový či vektorový obrázek s grafem, přičemž je možné zvolit, jaký algoritmus bude použit pro rozmístění uzlů a hran na vytvořeném obrázku. Textová definice grafu používá jednoduchý popisný jazyk, který je v současnosti podporován i několika dalšími nástroji a stává se tak nepsaným standardem pro mnoho programů pracujících s grafovými strukturami.

7. Jednoduché neorientované grafy

Podívejme se na jednoduchý příklad – graf se třemi uzly a čtyřmi hranami (spojnicemi) mezi těmito uzly. Takový graf může být popsán v textovém souboru s následující strukturou:

Obsah souboru graph1.dot:

graph languages {
    Algol -- "K&R C";
    "K&R C" -- "ANSI C";
    Algol -- Perl;
    Algol -- "PL/I";
}

Povšimněte si, že u některých uzlů bylo zapotřebí uzavřít jejich názvy do uvozovek. Není těžké zjistit proč – objevují se zde znaky, které by mohly být interpretovány odlišným způsobem (ampersand, mezera, lomítko) a uzavřením do uvozovek se (většina) těchto problémů automaticky vyřeší. Celý soubor začíná klíčovým slovem graph značící neorientovaný graf; ve skutečnosti je však možné celou hlavičku bloku vynechat (což ostatně dělají i některé nástroje). Neorientované hrany mezi jednotlivými uzly jsou naznačeny dvojicí znaků – a jak uvidíme v následující kapitole, bude tato značka u orientovaných grafů nahrazena šipkou.

O automatické rozmístění uzlů i hran a následné vykreslení diagramu do rastrového obrázku s formátem PNG se postará tento příkaz:

dot graph1.dot -T png & graph1.png

Výsledek si můžete prohlédnout na dalším obrázku zobrazeném pod tímto odstavcem. Příkaz dot v tomto případě vytvořil klasický strom s kořenem Algol, což nám v tomto případě vyhovuje.

Obrázek 12: Neorientovaný graf vytvořený na základě definičního souboru graph1.dot.

Zajímavé je, že příkaz dot zapisuje obrázek (či popis vektorového výkresu) na standardní výstup, takže je možné použít přesměrování standardního výstupu do souboru. Alternativní výstupní formáty jsou svg, gifps (PostScript).

Kromě příkazu dot lze použít i příkazy neato, fdp či sfdp, které se odlišují algoritmem použitým pro rozmístění uzlů diagramu.

8. Orientované grafy

Podívejme se nyní na tvorbu grafu, v němž jsou neorientované hrany mezi uzly nahrazeny šipkami. Použijeme přitom stejné uzly (přesněji řečeno uzly se stejným textem), jako tomu bylo i v předchozím příkladu. Změn v definičním textovém (zdrojovém) souboru je jen několik. První změnu můžeme vidět již na prvním řádku, protože se namísto klíčového slova graph používá slovo digraph. Dále se pak na dalších řádcích nahradila dvojice znaků – za šipku → naznačující přímo směr hrany:

Obsah souboru graph2.dot:

digraph languages {
    Algol -> "K&R C";
    "K&R C" -> "ANSI C";
    Algol -> Perl;
    Algol -> "PL/I";
}

Obrázek 13: Orientovaný graf vytvořený na základě definičního souboru graph2.dot.

U uzlů a hran je možné specifikovat různé vlastnosti a ovlivnit tak výsledné zobrazení grafu. Podívejme se na jednoduchou úpravu spočívající v tom, že se nejdříve deklaruje styl dvou uzlů (tvar uzlu + jeho barva) a následně se tyto uzly použijí pro specifikaci topologie grafu:

Obsah souboru graph3.dot:

digraph languages {
    Algol [shape=box];
    Algol [color="#ff0000"];
    "ANSI C" [color="#00ff00"];
    Algol -> "K&R C";
    "K&R C" -> "ANSI C";
    Algol -> Perl;
    Algol -> "PL/I";
}

Obrázek 14: Orientovaný graf vytvořený na základě definičního souboru graph3.dot.

9. Praktický příklad – zobrazení závislostí mezi instalovanými balíčky

Jedním z praktických příkladů pro použití nástroje Graphviz je grafické znázornění závislostí mezi nainstalovanými balíčky. Na Linuxových distribucích založených na RPM je možné pro tento účel použít skript nazvaný rpmdep.pl, který vygeneruje soubor s koncovkou .dot a strukturou korespondující s výše popsanou strukturou orientovaných grafů. Nejdříve je nutné do systému nainstalovat balíček rpmorphan obsahující zmíněný skript rpmdep.pl:

yum install "rpmorphan"

Následně je již možné tento skript spustit s parametry -dot (určuje formát výstupního souboru), vim-enhanced.dot (jméno výstupního souboru) a vim-enhanced (jméno nainstalovaného balíčku, pro který zjišťujeme jeho závislosti):

rpmdep.pl -dot vim-enhanced.dot vim-enhanced

Skript by měl po svém spuštění vytvořit soubor nazvaný vim-enhanced.dot s následujícím obsahem. Konkrétní jména balíčků samozřejmě závisí na tom, v jaké distribuci a její verzi se tento skript spustí, příklad byl vytvořen pro Fedoru 20:

digraph "rpmdep" {
vim_enhanced -> glibc;
glibc -> basesystem;
basesystem -> setup;
basesystem -> filesystem;
glibc -> glibc_common;
glibc_common -> bash;
bash -> ncurses_libs;
ncurses_libs -> libstdc;
libstdc -> libgcc;
ncurses_libs -> ncurses_base;
glibc_common -> tzdata;
glibc_common -> libselinux;
libselinux -> pcre;
libselinux -> libsepol;
libselinux -> xz_libs;
glibc -> nss_softokn_freebl;
vim_enhanced -> which;
which -> info;
info -> zlib;
vim_enhanced -> perl_libs;
perl_libs -> perl;
perl -> perl_PathTools;
perl_PathTools -> perl_Scalar_List_Utils;
perl_Scalar_List_Utils -> perl_Carp;
perl_Carp -> perl_Exporter;
perl -> perl_constant;
perl -> perl_threads_shared;
perl_threads_shared -> perl_threads;
perl -> gdbm;
perl -> perl_Pod_Simple;
perl_Pod_Simple -> perl_Pod_Escapes;
perl_Pod_Simple -> perl_Getopt_Long;
perl_Getopt_Long -> perl_Text_ParseWords;
perl_Getopt_Long -> perl_Pod_Usage;
perl_Pod_Usage -> perl_Pod_Perldoc;
perl_Pod_Perldoc -> perl_podlators;
perl_podlators -> perl_Encode;
perl_Pod_Perldoc -> perl_parent;
perl_Pod_Perldoc -> perl_HTTP_Tiny;
perl_HTTP_Tiny -> perl_Time_Local;
perl_Pod_Perldoc -> perl_File_Temp;
perl_File_Temp -> perl_File_Path;
perl_Pod_Perldoc -> groff_base;
groff_base -> sed;
sed -> libacl;
libacl -> libattr;
perl -> perl_Filter;
perl -> perl_macros;
perl -> perl_Socket;
perl -> perl_Time_HiRes;
perl -> perl_Storable;
perl -> perl_Module_CoreList;
perl_Module_CoreList -> perl_version;
vim_enhanced -> gpm_libs;
vim_enhanced -> vim_common;
vim_common -> vim_filesystem;
}

Nyní je již možné si známým postupem nechat vygenerovat příslušný (již poměrně rozsáhlý) graf:

Obrázek 15: Závislosti balíčku vim-enhanced zobrazené formou stromu.

Popř. lze příkaz dot nahradit jiným příkazem (neato, fdp či sfdp) a použít tak odlišný algoritmus určující rozmístění uzlů na obrázku:

Obrázek 16: Závislosti balíčku vim-enhanced zobrazené odlišným algoritmem.

Podobným způsobem lze vygenerovat graf závislostí i pro balíčky s mnohem větším množstvím závislostí. Jen na ukázku se podívejme na příklad balíčku java-1.7.0-openjdk, což je JRE Javy 1.7:

rpmdep.pl -dot openjdk.dot java-1.7.0-openjdk
digraph "rpmdep" {
java_1_7_0_openjdk -> libXtst;
libXtst -> glibc;
glibc -> libgcc;
glibc -> nss_softokn_freebl;
glibc -> glibc_common;
glibc_common -> tzdata;
glibc_common -> bash;
bash -> ncurses_libs;
ncurses_libs -> ncurses_base;
ncurses_libs -> libstdc;
glibc_common -> libselinux;
libselinux -> xz_libs;
libselinux -> pcre;
libselinux -> libsepol;
glibc -> basesystem;
basesystem -> setup;
basesystem -> filesystem;
libXtst -> libXi;
libXi -> libXext;
libXext -> libX11;
libX11 -> libxcb;
libxcb -> libXau;
libX11 -> libX11_common;
java_1_7_0_openjdk -> glib2;
glib2 -> zlib;
glib2 -> shared_mime_info;
shared_mime_info -> pkgconfig;
shared_mime_info -> libxml2;
glib2 -> libffi;
java_1_7_0_openjdk -> giflib;
giflib -> libICE;
giflib -> libSM;
libSM -> libuuid;
java_1_7_0_openjdk -> cups_libs;
cups_libs -> openssl_libs;
openssl_libs -> krb5_libs;
krb5_libs -> sed;
sed -> info;
sed -> libacl;
libacl -> libattr;
krb5_libs -> coreutils;
coreutils -> gmp;
coreutils -> util_linux;
util_linux -> libmount;
libmount -> libblkid;
util_linux -> audit_libs;
util_linux -> pam;
pam -> libpwquality;
libpwquality -> cracklib_dicts;
cracklib_dicts -> cracklib;
cracklib -> gzip;
pam -> libdb;
util_linux -> libcap_ng;
util_linux -> libutempter;
libutempter -> shadow_utils;
shadow_utils -> libsemanage;
libsemanage -> ustr;
libsemanage -> bzip2_libs;
util_linux -> systemd_libs;
systemd_libs -> dbus_libs;
systemd_libs -> libgcrypt;
libgcrypt -> libgpg_error;
systemd_libs -> libcap;
util_linux -> libuser;
libuser -> popt;
libuser -> openldap;
openldap -> nss;
nss -> nspr;
nss -> chkconfig;
nss -> nss_util;
nss -> nss_softokn;
nss_softokn -> sqlite;
sqlite -> readline;
nss -> nss_sysinit;
openldap -> nss_tools;
openldap -> cyrus_sasl_lib;
coreutils -> grep;
coreutils -> ncurses;
krb5_libs -> gawk;
krb5_libs -> keyutils_libs;
krb5_libs -> libcom_err;
krb5_libs -> libverto;
openssl_libs -> ca_certificates;
ca_certificates -> p11_kit;
ca_certificates -> p11_kit_trust;
p11_kit_trust -> libtasn1;
cups_libs -> avahi_libs;
java_1_7_0_openjdk -> libjpeg_turbo;
java_1_7_0_openjdk -> java_1_7_0_openjdk_headless;
java_1_7_0_openjdk_headless -> javapackages_tools;
javapackages_tools -> libxslt;
javapackages_tools -> lua;
javapackages_tools -> python;
python -> python_libs;
python_libs -> gdbm;
python_libs -> expat;
javapackages_tools -> python_javapackages;
python_javapackages -> python_lxml;
python_lxml -> python_cssselect;
java_1_7_0_openjdk_headless -> lcms2;
java_1_7_0_openjdk_headless -> freetype;
freetype -> libpng;
java_1_7_0_openjdk_headless -> gdk_pixbuf2;
gdk_pixbuf2 -> libtiff;
libtiff -> jbigkit_libs;
gdk_pixbuf2 -> jasper_libs;
java_1_7_0_openjdk_headless -> atk;
java_1_7_0_openjdk_headless -> pango;
pango -> libthai;
pango -> cairo;
cairo -> pixman;
cairo -> libXrender;
cairo -> mesa_libGL;
mesa_libGL -> libXfixes;
mesa_libGL -> libdrm;
libdrm -> systemd;
systemd -> dbus;
systemd -> tcp_wrappers_libs;
systemd -> kmod_libs;
systemd -> kmod;
systemd -> cryptsetup_libs;
cryptsetup_libs -> fipscheck_lib;
fipscheck_lib -> fipscheck;
cryptsetup_libs -> device_mapper_libs;
device_mapper_libs -> device_mapper;
systemd -> qrencode_libs;
systemd -> acl;
systemd -> diffutils;
libdrm -> libpciaccess;
libpciaccess -> hwdata;
mesa_libGL -> libXdamage;
mesa_libGL -> libXxf86vm;
mesa_libGL -> mesa_libglapi;
cairo -> mesa_libEGL;
mesa_libEGL -> libwayland_client;
mesa_libEGL -> libwayland_server;
mesa_libEGL -> mesa_libgbm;
cairo -> fontconfig;
fontconfig -> fontpackages_filesystem;
pango -> harfbuzz;
harfbuzz -> graphite2;
pango -> libXft;
java_1_7_0_openjdk_headless -> tzdata_java;
java_1_7_0_openjdk_headless -> gtk2;
gtk2 -> libXcursor;
gtk2 -> libXrandr;
gtk2 -> hicolor_icon_theme;
gtk2 -> libXinerama;
gtk2 -> libXcomposite;
java_1_7_0_openjdk -> pulseaudio_libs;
pulseaudio_libs -> libsndfile;
libsndfile -> libvorbis;
libvorbis -> libogg;
libsndfile -> flac_libs;
libsndfile -> gsm;
pulseaudio_libs -> libasyncns;
pulseaudio_libs -> json_c;
java_1_7_0_openjdk -> xorg_x11_fonts_Type1;
xorg_x11_fonts_Type1 -> ttmkfdir;
xorg_x11_fonts_Type1 -> xorg_x11_font_utils;
xorg_x11_font_utils -> libfontenc;
xorg_x11_font_utils -> libXfont;
java_1_7_0_openjdk -> alsa_lib;
}

Obrázek 17: Závislosti balíčku java-1.7.0-openjdk zobrazené odlišným algoritmem.

Obrázek 18: Závislosti balíčku java-1.7.0-openjdk zobrazené odlišným algoritmem (zvětšená část grafu).

10. Ditaa aneb uživatelsky přívětivá tvorba diagramů z ASCII artu

Třetím a současně i posledním nástrojem, s nímž se dnes alespoň ve stručnosti seznámíme, je aplikace nazvaná Ditaa. Jedná se o program vytvořený v Javě, nicméně nemusíte se bát, že jde o (další) typicky Javovský moloch :-), ale o relativně malou aplikaci, kterou lze získat na adrese http://sourceforge.net/pro­jects/ditaa/. Ditaa slouží k převodu diagramů vytvořených v ASCII artu do bitmapových obrázků, typicky do formátu PNG. Tento program navíc – na rozdíl od výše popsané utility dot – zachovává umístění jednotlivých uzlů v diagramu, nesnaží se tedy o přeuspořádání do jiné podoby. To mj. znamená, že Ditaa bude používána v jiných oblastech než nástroje dostupné v balíčku Graphviz. Příklady si ukážeme v navazujících kapitolách.

11. Jednoduché příklady

Použití programu Ditaa je skutečně velmi jednoduché. Začněme s následujícím diagramem, který lze snadno vytvořit v jakémkoli textovém editoru (dokonce i v Notepadu :-):

             +-------+    +------+
      +------+ Algol +--->| PL/I +
      |      +---+---+    +------+
      |          |
      |          |
      v          v
  +-------+  +-------+
  |  Perl |  | K&R C |
  +-------+  +---+---+
                 |
                 |
                 v
             +-------+
             | ANSI C|
             +-------+

Ditta automaticky zjistí, které znaky odpovídají uzlům a které hranám. Následně vytvoří tento obrázek:

Obrázek 19: První diagram vytvořený aplikací Ditaa.

V případě, že výsledný diagram neodpovídá očekávání, lze použít přepínač –debug, který povolí výpis různých ladicích informací na standardní výstup a současně do výsledného obrázku nakreslí mřížku:

ditaa version 0.9, Copyright (C) 2004--2009  Efstathios (Stathis) Sideris

Running with options:
debug
Reading file: ditta1.txt
Using grid:
    0123456789012345678901234567890123456789
 0 (                                      )
 1 (                                      )
 2 (               +-------+    +------+  )
 3 (        +------+ Algol +--->| PL/I +  )
 4 (        |      +---+---+    +------+  )
 5 (        |          |                  )
 6 (        |          |                  )
 7 (        v          v                  )
 8 (    +-------+  +-------+              )
 9 (    |  Perl |  | K&R C |              )
10 (    +-------+  +---+---+              )
11 (                   |                  )
12 (                   |                  )
13 (                   v                  )
14 (               +-------+              )
15 (               | ANSI C|              )
16 (               +-------+              )
17 (                                      )
18 (                                      )
Locale: en_US
Dialog.bold
Rendering to file: ditta1_3.png
Done in 0sec

Obrázek 20: První diagram vytvořený aplikací Ditaa při použití parametru –debug.

Podívejme se nyní na to, co se stane, když se jeden uzel posune (samozřejmě včetně spojnic):

             +-------+
      +------+ Algol +-+
      |      +---+---+ |
      |          |     |   +------+
      |          |     +-->| PL/I +
      v          v         +------+
  +-------+  +-------+
  |  Perl |  | K&R C |
  +-------+  +---+---+
                 |
                 |
                 v
             +-------+
             | ANSI C|
             +-------+

Z obrázku je patrné, že i ve výsledku došlo k posunu uzlu:

Obrázek 21: Druhý diagram vytvořený aplikací Ditaa.

12. Složitější příklady: styly spojnic

Velmi snadným způsobem lze změnit styl spojnic (hran) mezi uzly. Stačí, aby jediný znak ve spojnici byl nahrazen znakem : (dvojtečka) nebo = (rovnost) a celá hrana bude vykreslena čárkovaně. Proč postačuje změnit jediný znak? Je tomu tak z toho důvodu, aby úpravy diagramu byly velmi rychlé, bez nutnosti „překreslovat“ celou hranu:

             /-------\
      +------+ Algol +-+
      :      \---+---/ |
      |          |     |   +------+
      |          |     +-->| PL/I +
      v          v         \------/
  +-------+  +-------+
  |  Perl |  | K∓R C |
  \-------/  +---+---+
                 |
                 |
                 v
             /-------\
             | ANSI C|
             +-------+

Obrázek 22: Třetí diagram vytvořený aplikací Ditaa.

13. Změna stylu uzlů

Již na předchozím obrázku bylo naznačeno, jak lze jednoduše změnit styl uzlů, konkrétně zaoblení (libovolného) rohu: namísto znaku + (ostrý roh) se použije lomítko či zpětné lomítko (zaoblený roh). Různé varianty jsou ukázány níže:

             /-------\
      +------+ Algol +-+
      |      \---+---/ |
      |          |     |   +------+
      |          |     +-->| PL/I +
      v          v         \------/
  +-------+  +-------+
  |  Perl |  | K&R C |
  \-------/  +---+---+
                 |
                 |
                 v
             /-------\
             | ANSI C|
             +-------+

Obrázek 23: Čtvrtý diagram vytvořený aplikací Ditaa.

Kromě toho je možné změnit i barevnou výplň jednotlivých uzlů. Jedná se sice o vlastnost, která není stabilizovaná, ale z dalšího obrázku je patrné, že (částečně) funguje. Částečně proto, že názvy barev roztáhnou jednotlivé uzly:

             /------------------\
      +------+ cRED Algol       +--+
      :      \---+-----------+--/  |
      |          |           |     |   +------+
      |          |           |     +-->| PL/I +
      v          v           v         \------/
  +-------+  +------------------+
  |  Perl |  | cBLU K&R C       |
  \-------/  +---+-----------+--+
                 |           |
                 |           |
                 v           v
             /------------------\
             | cGRE ANSI C      |
             +------------------+

Obrázek 24: Pátý diagram vytvořený aplikací Ditaa.

CS24_early

Poslední vlastností programu Ditaa je schopnost měnit tvar uzlů pomocí speciálních značek zapisovaných do složených závorek. Opět se podívejme na příklad:

             /------------------\
      +------+ cRED Algol {d}   +--+
      :      \---+-----------+--/  |
      |          |           |     |   +------------+
      |          |           |     +-->|   PL/I {s} |
      v          v           v         \------------/
  +-------+  +------------------+
  |  Perl |  | cBLU K&R C {io}  |
  \-------/  +---+-----------+--+
                 |           |
                 |           |
                 v           v
             /------------------\
             | cGRE ANSI C      |
             +------------------+

Obrázek 25: Šestý diagram vytvořený aplikací Ditaa.

14. Odkazy na Internetu

  1. Plain-text diagrams take shape in Asciidoctor!
    http://asciidoctor.org/new­s/2014/02/18/plain-text-diagrams-in-asciidoctor/
  2. Graphviz – Graph Visualization Software
    http://www.graphviz.org/
  3. graphviz (Manual Page)
    http://www.root.cz/man/7/graphviz/
  4. dot (Manual page)
    http://www.root.cz/man/1/dot/
  5. Ditaa home page
    http://ditaa.sourceforge.net/
  6. Ditaa introduction
    http://ditaa.sourceforge.net/#intro
  7. Ditaa usage
    http://ditaa.sourceforge.net/#usage
  8. Node, Edge and Graph Attributes
    http://www.graphviz.org/doc/in­fo/attrs.html
  9. Graphviz (Wikipedia)
    http://en.wikipedia.org/wiki/Graphviz

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.