2012. szeptember 15., szombat

Német tanulás és programozás egyszerre


Ehhez csak annyi kell, hogy beleerőltessünk egy német korpuszt az NLTK szófaj-taggerébe. 
Mondjuk ebbe: unigram_tagger.tag(line)
Mondjuk ezt: TIGER korpusz



2012. augusztus 15., szerda

HTML tisztítás és Google keyword teszt

A HTML dokumentumokból való szövegkinyerés közel sem triviális feladat -- úgy tűnhet, hogy elég kidobálni minden HTML taget és kész is vagyunk. Sajnos, már a tagek törlése is gyakran problémás, mert egy ártatlan HTML mélyén aljas Javascript-ek, kommentek, etc, etc.. lapulhatnak.

A másik probléma, hogy nem minden szöveg "szöveg" abban az értelemben, hogy érdemes vele foglalkozni: egy átlagos page jókora része kölünféle linkekből , feliratokból és egyéb haszontalan elemekből áll; és akkor még itt van a kommentek kérdése is.

Sztenderd és széles körben alkalmazott szemantikus tagelésnek pedig továbbra is híján vagyunk...

Jó hasznát vehetjük azonban a HTML dokumentumok fa-természetének, illetve a józan paraszti észnek -- pl. kiindulhatunk abból, hogy sok oldalon a cikkek szövegét P tagek közé ékelik.

És szerencsére itt van nekink a BeautifulSoup nevű remek python modul: HTML-t iterálható és kereshető objektumokká alakít.  Ennyi az egész:


Ettől a kis változtatástól a kulcsszó-kiemelő sokkal tisztább bemeneti szövegekkel tud dolgozni, és sokkal jobb eredményt is produkál:




Egy másik érdekes megfigyelés, hogy az első 6 kulcsszó alapján a Google már elég jó eséllyel rátalál a kérdéses dokumentumra (és valójában lejjebb is lehet menni, tessék kipróbálni!). Így tehát bizonyítottnak tekinthetjük, hogy a Google is használ TF-IDF elemeket az algoritmusában:)

2012. augusztus 12., vasárnap

Kulcsszó kiemelő alkalmazás

Korábban már írtam a kulcsszó kiemelésről a TF-IDF modell segítségével, most pedig végre volt egy kis időm, és megírtam rendesen minimálisan működőképesre.

Az igazi öröm számomra eközben a Google App Engine-nel való megismerkedés volt: a google ugyanis megengedi, hogy a felhőben futtassuk a kis alkalmazásainkat, ad hozzá egy elég gyorsan kiismerhető framework-ot, és nem utolsó sorban 1GB tárhelyet az adataink tárolására. INGYEN! (aztán ha több kell, lehet venni még)

A kulcsszó-kiemelő egy blog (vagy bámi más) RSS feedjének címét kéri, valamint még két paramétert: hány oldalt szeretnénk kielemeztetni a géppel és hány karakternél vágjuk le az oldal alját (ezt azonnal megérted, ha rákattintasz).



A dolog persze messze nem tökéletes, pl. szótövezés nincs beépítve, és nagyon kevés dokumentumhoz képest elemzi a kód az adott dokumentum kifejezését (egészen pontosan csak az adott feedhez képest). Igazából az a meglepő, hogy így is viszonylag értelmes dolgokat dob ki!

Tessék ezért minnél több feed címét beírni, mert az alkalmazás szorgalmasan elmenti a statisztikákat, ami a későbbiekben nagy segítség lesz nekem!;)







2012. július 17., kedd

Blogoszféra - a központok felkutatása

Az Udacity nevű online-egyetemen futó algoritmika kurzuson éppen a közösségi hálózatokról van szó, illetve a téma kapcsán a gráfokról -- isteni, csak ajánlani tudom!

A kurzuson bevezették a csomósodási együttható (clustering coefficient) fogalmát is, amely azt mutatja meg, hogy egy gráf adott csúcsa mennyire foglal el központi helyet a hálózatban. A kiszámításához két dolgot kell tudni:

  • egy blogra hány oldalról mutat link (legyen LINK)
  • a fenti oldalak között hány link van (legyen INTERLINK)

Az együttható kiszámítása a következő képlettel történik:

2*INTERLINK / (LINK*(LINK-1))

Minnél sűrűbb a hivatkozó oldalak közti linkhálózat, ez az érték annál nagyobb lesz.

A csomósodási együttható segítségével meg tudjuk mondani, mely blogok körül csomósodnak a linkek -- ezek az oldalak vélhetően hasonló témakörben publikálnak, hiszen különben nem linkelnének egymásra. Ezzel ellentétben, egy nagyon népszerű, sok befelé mutató linkkel rendelkező blognál ez az érték valószínűleg kisebb, hisz a hivatkozók egymásra ritkábban hivatkoznak.

A gyakorlatban több problémával is meg kell küzdeni: először is, az adatok rossz minősége itt már komoly probléma -- az index egymást körbehivatkozó foci-blogjai nagyon csúnyán eltorzítják az ábrát. Ezen kívül, komolyan el kell gondolkodni azon is, hogy mit számolunk: a befelé vagy a kifelé mutató linkeket, esetleg mind a kettőt? Végül, egy kicsi hálózatnak jellemzően nagyobb lesz a csomósodási együtthatója, ezért valamilyen határt is fel kell állítani -- az itt látható ábrákon 5 hivatkozásnál kevesebbel rendelkező blogok nem válhattak 'központokká'.


1. ábra

 
Az 1. ábrán kiválóan látható, hogy a boros blogok szépen kirajzolódó hálózatokba szerveződnek (a hálózat központja mindig színes hátterű, és az adott hálózat élei is ilyen színűek)



 Itt az látható, hogy a hálózatok átfedik egymást -- egy csúcs több hálózatnak is tagja lehet, hiszen bármely szomszédból lehet "központ", ha elég magas a csomósodási együtthatója.





Itt az index focis blogjai egymásra települt hálózatokat alkotnak, ezért a sok párhuzamos él. Értelmezhetetlen, de legalább szép:)



2012. július 10., kedd

Blogoszféra: scatter plot

Szép a gráf, de áttekinthetetlen. Mennyivel szebb egy scatter plot (hogy van magyarul?), amelyen minden pont egy linket képvisel; az X koordináta az mondja meg, honnan, az Y pedig, hogy hová mutat (ez ugyanaz, mintha felírnánk a gráfot mátrix-alakban).

A tengelyek mentén a blogokra mutató linkek összessége (kékkel, az Y mentén), illetve a blogokon található hivatkozások száma (pirossal, X mentén) látható. A legnépszerűbb oldalakat fel is írtam az ábrára (kékkel), mint ahogy a legtöbb oldalra mutató blogok nevét is (pirossal). Ebből látszik, hogy a népszerű oldalak nem feltétlenül hivatkoznak sokat (itt persze közrejátszik az adatok minősége is, ugyanis teljes szöveget veszünk, olvasói kommentekkel is, amelyekben sok link lehet).



Érdekes kérdés, vajon ezek az adatok alapján csoportokba lehet-e rendezni a blogokat, és vajon ezek a csoportok kirajzolnak-e valamilyen értelmes mintát? (a gráfot nézegetve látható valamiféle mintázat, pl. a politikai blogok egymáshoz közel vannak). Ehhez valamilyen clustering-algoritmust kell alkalmazni, de mielőtt ezzel megpróbálkoznék, még át kell olvasnom egy-két dolgot;)





2012. június 30., szombat

Magyar blogoszféra 500

Kis híján kigyulladt a számítógépem, de végül mégiscsak sikerült rávenni a Graphviz-t, hogy számolja le a magyar blogoszféra első 500 oldalát. Az előző posztban a graphviz dot parancsával számoltam (ez szép, görbe, csúcsokat gondosan megkerülő éleket rajzol) -- ennek azonban sajnos ára van (lassú). Az fdp parancs egyszerű vonalakkal operál.

fdp teszt500.dot -Tsvg > proba500.svg




 A teljes ábrához kattints ide.

Érdekes, hogy így sokkal szebben látszik a linkek sűrűsége. Pl. az ábra jobb alsó felén az index saját foci-EB blogjai vannak, amelyek minden oldala linkel egymásra, de "kintről" már sokkal kevesebb kapcsolódási pont van. Feljebb, balra, az igazi sűrűben továbbra is a politikai-közéleti blogok uralkodnak.

Egyébként már a 150 oldalas mintán is látszik az 500 oldalas mintán kirajzolódó struktúra: ugyanazok az oldalak a legnépszerűbbek, és hasonlóképpen is rendeződnek egymás mellé.


2012. június 24., vasárnap

Magyar blogoszféra vizualizáció


Kicsit azért ciki, hogy ha beírom a google képkeresőbe a "magyar blogoszféra" kifejezést, Tóta W. Árpád valamint Orbán Viktor képe jelenik meg. Úgyhogy kéne csinálni valami informatívabbat.

Az webet jól lehet ábrázolni gráfként, hiszen minden oldal egy csomó másikra mutat -- minden oldal csúcs, minden link él. Azt is tudjuk a google óta, hogy minnél több oldal mutat egy oldalra, az annál fontosabb.

A rajzolás piszkos munkáját meg lehet spórolni a graphviz programcsomaggal -- amely egy szkriptelhető, gráf-rajzoló rendszer. A lényeg elovasható pl. itt.

Gyorsan írtam egy buta pókot, ami elindul a blog.hu-n, és az ott talált linkeken továbbmászik (hogy csak blogokat találjon, csak a blog.hu-s linkekre figyelünk). Összeszámoljuk, honnan hová mutatnak a linkek. Ez után generálunk egy .dot kimenetet, ami hihetetlenük egyszerű:

digraph blogosphere {
//ezek a csúcsok, vagyis az egyes blogok
blog1 [label="első blog"]
blog2 [label="második blog"]
//satöbbi
// itt jönnek az élek
blog1 -> blog2
blog1 -> blog3
satobbi -> blabla
}

Érdekes kérdés, hogy mennyi idő után tiltja le a blog.hu szervere a pókot -- 500 kérést gyorsan egymás után még kibír, de valószínűleg mindennek van határa...

A fentiek után a .dot file-t megetetjük a graphviz-zel és kész is vagyunk -- minden másról a program gondoskodik. Jó, mi?

dot -Tpng teszt500.dot > teszt500.png



Mivel a graphviz próbálja minnél ésszerűbben elrendezni az éleket, az egymásra gyakran mutató, vagyis tartalmilag közel álló blogok közel kerülnek egymáshoz. Pl. a modoros, dezsőmail és a gyűlölt ellenségeink (ezek vicces blogok, ha valaki nem ismernő) egymáshoz közel, az ábra felső részében helyezkednek el, jobbra lent találhatók a politikus blogok, balra középen pedig a meztelen csajos oldalak helyezkednek el. De vannak itt furcsaságok is: ide került a tévé-sorozatos és a cuki állatos blog is. Hogy mi vannak!





Egyébként, itt egy 150 oldalnál megálló pók útja látható -- 500 oldal egyszerre nem fér fel a lapra (elfogy a memória), de bizonyosan van valami okos megoldás erre is.
Folyt. köv.

2012. február 28., kedd

Keyword keresés és a TF-IDF

Ben Fry a Visualizing Data: Exploring and Explaining Data with the Processing Environment című könyvében (amelyről bővebben is szeretnék majd írni a jövőben) felhívja a figyelmet, hogy a jó vizualizáció csak félig szól az az adatok tetszetős formában öntéséről.

A folyamat hét lépésből áll:
  1. aquire
  2. parse
  3. filter
  4. mine
  5. represent
  6. refine
  7. interact 
Az első rész az adatok beszerzéséről, használható formába öntéséről, a szemét eltávolításáról és az értelmes összefüggések felkutatásáról szól.

Tegyük fel, hogy szeretnénk kideríteni, hogy egy weboldalon körülbelül miről írnak, aztán ezt gyorsan áttekinthető formában megtekinteni -- egy jól felépített oldal esetében a lap címlapja magáért beszél, esetleg még kulcsszavakat is mellékeltek -- de mi van, ha mégsem? Az index.hu pl. viszonylag értelmes címekkel látja el a cikkeit, de nem biztos, hogy ez elmondható egy pletykalapról vagy egy személyes blogról is.


Jó ötlet lehet minden oldalnál megjeleníteni a legjellemzőbb kulcsszavakat -- a fenti képen ennek egy kezdetleges változata látható. De hogyan szereztük meg ezeket?

Az adatok beszerzésének az első lépése itt az oldalak letöltése lesz -- már itt is számos problémáva ütközhetünk. Ha szerencsénk van, találhatunk RSS feedeket, ha nincs, akkor különféle trükkökkel kell kinyerni a releváns linkeket a HTML lapokból. Ezután a tisztítás következik, ami esetünkben a HTML tagek kidobását, esetleg a reklámok, kommentek, stb. eltávolítását jelenti. A magyar nyelv esetében külön probléma a karakterkódolás is.

A következő lépés a finomabb szűrés -- írásjelek, rövidítések, számok, stb... Hatalmas -- nyelvspecifikus -- probléma, hogy a magyar ragozó nyelv, így egy jellemző kulcsszó külünböző alakjait nem biztos, hogy sikerül felismerni.

Eddig eljutva látszólag használható adataink vannak: egy csomó cikk, tiszta szöveges formában. A kulcsszavak megtalálása látszólag pofonegyszerű: megszámolunk minden szót (pl. az python NLTK eszközeivel), és a leggyakoribbakat kijelöljük kulcsszónak (ez a bag of words technika). Sajnálatos módon azonban minden nyelvben a leggyakoribbak a segédszavak (a, az, van, meg...), így ezzel semmire nem megyünk. Ha ezeket a szavakat ignoráljuk, már valamennyire juthatunk, de még így sem az igazi -- kifinomultabb modellre van szükség.

A Számítógépes Nyelvészet blogon már szóba került a TF-IDF formula, mint a keyword kinyerés elterjedt eszköze (leírás itt és itt). Az eljárás lényege, hogy egy dokumentum jellemző kulcsszavait nem csak a dokumentumhoz képest, hanem más (lehetőleg hasonló) dokumentumokhoz képest is vizsgáljuk: ha az index.hu újságírói szívesen használnak bizonyos kifejezéseket, akkor ezt figyelembe kell vennünk a kulcsszavak keresése közben, és az ilyen "általában gyakori" kifejezéseket "le kell pontoznunk".

Egészen pontosan így működik a formula:

kulcsszó fontossága: TF x IDF

TF: (term frequency): egy kulcsszó előfordulása az adott dokumentumban
IDF: (invers document freqency) egy kulcszó előfordulása a teljes dokumentum-szettban -- majd ennek az értéknek az "inverze", pl. reciproka, logaritmusa, stb.

Így a fontos kulcsszavak azok lesznek, amelyek gyakoriak az adott dokumentumban ÉS ritkák a teljes szettben.

A fenti két linkeken ezt a modellt vektor térben mutatják be. Ez elsősorban akkor jön jól, ha NAGYON SOK adatunk van, mivel így könnyeb lesz számolni (mármint a gépnek;)

Érdekes kérdés, hogy mennyire KEVÉS adatnál kezd el működni a modell. Hiszen, az egyik viszonyítási pontunk a teljes dokumentum-szett, így ha az túl kicsi, akkor nem biztos, hogy a jól méri fel a modell a kulcsszavak valódi fontosságát. A fenti próba azt mutatja, hogy meglepően kevés szöveg is elég -- az index címlapon egyszerre körülbelül 40 cikk szerepel -- ezeken végigfuttatva a modellt már értelmes eredményeket produkál.

Van tehát egy használhatónak tűnő adatszettünk és egy modellünk. A következő lépés az adatok tetszetős megjelenítése és a felhasználóval való interakció lesz.

(folyt. köv)






2012. február 19., vasárnap

Mozgás és vektorok

A processing.org-on igazán remek oktató anyagok találhatók (szerintem ezek egy része átfedésben lehet a külön megvásárolható könyvek tartalmával, bár ki tudja...). A vektorokról szóló anyag inspirálta a következő alkotást.

Húzd a lap felé az egeret, majd kattintgass, vagy nyomkodd az ENTER-t!



Az oktató anyag nagyon jól elmagyaráz mindent a vektorokkal és a mozgás modellezésével kapcsolatban. A lényeg tulajdonképpen az, hogy a processing rendelkezik egy beépített PVector osztállyal -- ez az adattípus két- és háromdimenziós vektorok tárolására lett kitalálva, a metódusai pedig az ehhez tartozó matematikai műveletek (összeadás, kivonás, skalárszorzat, vektorszorzat, normalizálás, etc.) elvégzésének a nyűgét veszik le a vállunkról.

A fent látható sketch-ben tulajdonképpen nem történik más, mint hogy a repülő labdákat mindig abba az irányba gyorsítjuk, amelyik irányba az egérkurzor esik tőlük. Szóval, mindig az egér felé akarnak repülni. Az érdekesség ott van a dologban, hogy mivel egészen addig, amíg el nem érik a kurzort, gyorsítjuk őket, mindig túlrepülnek -- hogy aztán megfordulhassanak és ismét gyorsulhassanak, csak immár a másik irányba. És így tovább, a végtelenségig.
 

2012. február 18., szombat

3D grafika egyszerűen

A processing nem csak két dimenzióban enged firkálni a rajzfelületre, de három dimenziós világokat is elég egyszerű létrehozni. Következzenek az első tapasztalataim.


Húzd az egeret a rózsaszín felület fölé!


A kód, utána pedig a kommentár:


void setup() {
  size(640, 360, P3D);
  background(0);
  frameRate(10);
}
 
void draw() {
  background(#FF66CC);
  lights();
  for (int i=0; i <= 32; i++) {
    for (int c=0; c < 20; c++) {   
      int plusz=0;
      int forgat=0;
      float tav=dist(i,c,int(mouseX/20),int((height-mouseY)/20));
      if (tav < 10) {
        //plusz=int((11-tav)*4);
        forgat=int((11-tav)*3);
      }
      fill(255);
      lemez(i*23,360-plusz,-c*23,forgat);
    }
  }
}
 
void lemez (int x,int y,int z, int forgat) {
  pushMatrix();
  translate(x,y,z);
 
  rotateX(radians(random(forgat)));
  rotateY(radians(random(forgat)));
  rotateZ(radians(random(forgat)));
 
  scale(10);
  beginShape(QUADS);
  vertex(-1,  0,  -1);
  vertex(- 1,  0, 1);
  vertex( 1, 0,  1);
  vertex(1, 0,  - 1);
  endShape();
  popMatrix();
}



A rajzlapot a harmadik dimenzió felé megnyitni a size parancs harmadik paraméterével tudjuk. Az alapvető rajzoló funkciók ugyanúgy működnek, vagyis minden képkockánál törölhetünk (vagy éppen nem), vonalat húzhatunk, stb.

size(640, 360, P3D);

A három dimenziós testek építése egy kicsivel trükkösebb, mint a két dimenziós rajzolás. A kódban ez mind a lemez() függvényben történik. Először minden testet fel kell építenünk egy pufferben, amit a

pushMatrix();
paranccsal hozunk létre, majd a
popMatrix();

rajzoljuk ki a tartalmát a "vászonra".

Közvetlenül a puffer létrehozása után kell megmondanunk azt is, hogy hová akarjuk elhelyezni a testet, illetve mennyit szeretnénk forgatni rajta (radiánban kéri!). A kódban ez így néz ki:

 translate(x,y,z);
  rotateX(radians(random(forgat)));
  rotateY(radians(random(forgat)));
  rotateZ(radians(random(forgat)));

Ezek után nem meglepő, hogy az olyan primitív testek, mint a box() vagy a sphere() csak egy paramétert kérnek: a méretüket. Ha magunk szeretnénk építkezni, megtehetjük:

beginShape(QUADS);
  vertex(-1,  0,  -1);
  vertex(- 1,  0, 1);
  vertex( 1, 0,  1);
  vertex(1, 0,  - 1);
  endShape();

Ilyen felületekből akármennyit létrehozhatunk. Fontos megjegyezni, hogy ez egy relatív koordináta-rendszer, vagyis ahhoz, hol fog megjelenni a képernyőn, nincsen semmi köze (ezt a translate csinálja). Annál fontosabb a (0,0,0) pont: e körül tudjuk forgatni a testet.

Ennyivel gyakorlatilag már képesek vagyunk egyszerű három dimenziós világokat készíteni. 

További példákért és információért ide érdemes ellátogatni, illetve továbbra is figyelemmel kísérni a Kép és Kód blogot:)








2012. február 9., csütörtök

BKV térkép megállókkal

Nagyon megörültem, hogy a teljes BKV menetrend-adatbázis elérhető, és szabadon lehet vele játszadozni -- a GTFS formátum ugyanis ezt erősen megkönnyíti. Az adatok egyszerű plain text-ben, egészen pontosan CSV-ben, vagyis veszőkkel elválasztva érkeznek. Ezt az Excel és társai minden további nélkül tudják olvasni.

Mivel az adatbázis nagyon sok mindent tartalmaz, szükséges egy kis előszűrés -- egyrészt, hogy egyszerűbb legyen az élet, másrészt, mert a processing bizony elég lassú. A nagy adatbázis alatt kb. 200 megabájt szöveges adatot kell érteni, vagyis egy táblázatkezelővel még éppen, egy egyszerű python szkripttel pedig pikk-pakk megbírkózhatunk vele.

Én legalábbis ezt csináltam: csupán az útvonalakat szerettem volna ábrázolni egy minimálisan interaktív térképen. Ehhez teljesen felesleges foglalkozni a járatok indulási idejével, vagy éppen azzal, hogy melyik jármű mikor melyik megállóban áll. Nekem csak annyit kell tudni, hogy melyik járat mely megallókat érinti. Csakhogy, a GTFS külön táblákban tárolja a járatokat, a megállókat és a járatok által érintett pontokat, Ezért szükség volt az adatok előkészítésére, ami python-nal és táblázatkezelővel történt. Természetesen a legelegánsabb megoldás az összes adatot bedobni egy adatbázisba, és táblákon átívelő lekérdezéseket csinálni, de verébre felesleges ágyúval lőni.

Tehát, lássuk a működő programot (mozgatás: az egér húzgálásával, zoom: +/-):




A forrás az alábbi linken érhető el. A kódot viszonylag sűrűn kommentáltam. Talán érdemes kiemelni, hogy processing-ben nagyon kényelmes a saját adat-típusok (objektumok) létrehozása (ilyenben tárolom a megállókat és az útvonalakat). A másik megjegyzés, hogy ebben a programban a folyamatosan újrainduló draw() funkció csak a hosszúsági és szélességi koordináták kiírásáért felel; a térképet a program elején, illetve csak akkor rajzoljuk ki, ha pl. elmozdítottuk (ugyanis elég sokat kell számolni hozzá). A mozgatásra és a zoomolásra a mousePressed() és a keyPressed() funkciók figyelnek (ezek a nyelvbe beépített funkciók).



2012. február 1., szerda

Magyar földrajzi adatok

A Statisztikai Hivatalnál elérhető a Helységnévtár, amiben megtalálható az összes magyar település földrajzi koordinátája (és még számos egyéb). Remekül el lehet szórakozni például az irányítószámok eloszlásának ábrázolásával:





De ami ennél sokkal felvilanyozóbb: a BKV fél éve publikálta a teljes menetrend-adatbázisát. És nem is akárhogy, hanem a Google Maps által bevezetett GTFS formátumban -- így gyakorlatilag bárki megírhatja a saját menetrend-tervező applikációját. Nekem persze nincsenek ilyen ambícióim, de azért jó tudni, hogy Budapetről is van egy csomó egyszerűen feldolgozható földrajzi adat (nem is olyan rég került fel a netre a Budapest egy napja videó -- szintén ezekből táplálkozik).


Ez Budapest összes viszonylata -- a hiba egyelőre ott van, hogy csaka végpontokat kötjük össze, vagyis pl. a körúti villamosból csak egy vonás marad. A HÉV és a metróvonalak azonban már itt is felismerhetők.


2012. január 29., vasárnap

Adat vizualizáció processing-gel

A Számítógépes Nyelvészeten korábban már szóba került a processing programozási környezet, amelyet azért terveztek, hogy egyszerűen és hatékonyan lehessen vizuális alkalmazásokat készíteni: egy java-ra épülő (pontosabban, a java alá épülő) nyelvről van szó, amely a számos grafikus megjelenítéssel kacsolatos feladatot megkönnyít a beépített funciók segítségével.

Mint már akkor Zoli elmondta, nem egy játékról van szó, hanem egy igen hatékony eszközről; ugyanezt Ben Fry (a nyelv egyik atyja), Visualizing Data c. könyvében úgy fogalmazza meg, hogy kész eszközök helyett a processing építőkockákat ad -- egyedi problémákhoz ugyanis szinte lehetetlen előre legyártott szabványos megoldásokat kitalálni.

A processing építőkockái valójában nem mások, mint a beépített funkciók -- valójában mindent a Java programnyelv végez, így nem is meglepő, hogy a szintaxis megegyező; és az sem, hogy bármikor "kinyúlhatunk" a processing nyelvből a Java funkcióihoz.

Mit szeretnénk tehát? A processing két dologban jó: a vizualizációban és az interaktivitásban; tehát -- hogy újra feltaláljuk a spanyolviaszt -- készítünk egy primitív tag-felhőt. A megoldás annyiban nem lesz szabványos, hogy kezdetben minden tag-et azonos méretben fogunk megjeleníteni; csak utóbb, a az egér mozgatásával dönti el a felhasználó, hogy mennyire szeretné "kiugrasztani" a gyakran előforduló elemeket. Tehát, lesz egy "áttekintő nézetünk" és egy "közelítő nézetünk".



 Áttekintő nézet -- minden szó egyforma méretű

  
A gyakori szavakat kiemeltük


OK. A legegyszerűbb processing program két funkcióból áll: a setup() és a draw(). A setup() induláskor fut le egyszer, mint neve is mutatja, itt érdemes elhelyezni minden kezdetben szükséges lépést. Pl., mi itt állítjuk be a rajzfelület méretét (800x600), itt töltjük be a betűtípust és itt olvassuk be az adat.txt-ből a szavakat, amelyeket majd később ki szeretnénk írni a képernyőre.

Ezután a draw() funkció fut le. Ez, mint neve is mutatja, alapvetően a megjelenítésért felel, de természetesen bármi mást is elhelyezhetünk itt. Kiemelt szerepe abban áll, hogy folyamatosan ismétlődik, vagyis miután a program mindent kirajzolt, azonnal újra kezdi. Hogy mire jó ez? Ha úgy képzeljük el a dolgok, mint az egymást követő filmkockákat, egyből értelmet nyer a dolog: ha a két kocka közt nincs eltérés, akkor nem veszünk észre semmit. Azonban ha van, akkor mozgásba lendül a kép. Pl., ha egy kirajzolt pont koordinátáit minden egyes funkció-híváskor megnöveljük egyel (x++;), akkor egy mozgó pont lesz az eredmény. A processing környezet tehát azt a könnyedséget adja, hogy nem kell magunknak megírnunk a "filmkockák kirajzolásáért" felelős részt, elég csak a képekkel foglalkoznunk.

Ezen a ponton érdemes megjegyezni, hogy a processing komolyan veszi a globális és lokális változók kérdését. Pl. a draw() funkción belül deklarált változók minden egyes újrahíváskor elvesznek, így ha pl. a mozgó képpont x koordinátáját az x változóban tárolnánk, azt mindenképpen globálisan (vagyis a funkción kívül) kell először deklarálnunk. A programunkban pl. ilyen az adat[], meret_szamlalo vagy a lastMX.

Az interaktivitás beépítését a processing azzal támogatja, hogy nagyon egyszerűvé teszi teszi a különböző események figyelését. Pl. minden alkalommal, amikor kattintunk, a mousePressed() funkció kerül meghívásra, majd visszatér a program oda, ahol abbahagyta a futást. Ugyanez a történik a mouseMoved() funkció esetén is. Az egérkurzor koordinátáit a mouseX ill. a mouseY változókból tudhatjuk meg.

Lássuk tehát, mi történik az interaktív szövegfelhőnk kódjában. Először deklarálunk néhány globális változót (mivel azt szeretnénk, hogy minden funkció elérje ezeket). Ezután elindul a setup(), ami betölti az adat.txt tartalmát (itt a szavak és a hozzájuk tartozó értékek találhatók).

Végül elindul a draw(), amely folyamatosan ismétlődik a program leálltáig. Először kirajzoljuk az "irányító felületet" -- ez az a része a képernyőnek, amelyen ha megmozdítjuk az egeret, akkor változik a szavak mérete. Majd kiszámoljuk (egy gyökvonással), hogy hány sorba és hány oszlopba rendezzük az adatainkat. Ezután elindítunk egy ciklust, amely szép sorban kiírja megfelelő helyekre az adat[] tömbben tárolt szavakat. Ha a szó maximális mérete nagyobb, mint az aktuálisan beállított szövegméret, akkor az utóbbit használjuk. Ha az aktuális szövegméret nagyobb, akkor a szó maximális méretét használjuk.

Az utolsó két funkció az egér mozgatását és az egérkattintást figyeli. Ha megmozdítjuk az egeret ÉS a kurzor a "kezelőfelület" felett áll, akkor növeljük vagy csökkentjük a szöveg méretét (attól függően, hogy jobbra vagy balra húztuk az egeret). Ha kattintunk, akkor egy új szöveg-elrendezést kérünk -- ezt egyszerűen úgy érjük el, hogy megkeverjük az adat[] tömböt.




Végül néhány megjegyzés:

1. A virtuális gép és a grafikus felület sajnos lelassítja a program futását. Nagyon. Ezért az egymásba ágyazott ciklusokkal, nagy tömbökkel és minden hasonlóval csak nagyon óvatosan szabad bánni. Szerencsére a bonyolultabb grafikus műveletekhez vannak beépített funkciók.

2. A Java típusai sokkal finnyásabbak, mint mondjuk a python-éi. A float nem változik automatikusan integerré, a string-et nem lehet csak úgy pikk-pakk karakterekké szedni, stb... A tömbök sem túl rugalmasak: deklaráláskor el kell döntenünk, milyen hosszúak legyenek, tehát nem tudjuk őket a végtelenségig bővíteni. Többdimenziós tömbök léteznek, de egy tömbnek csak egy eleme már nem lehet egy újabb tömb. Dictionary/hash típus nincsen.

4. A programok könnyen konvertálhatók java appletté, illetve az processing.js javascript könyvtár segítségével közvetlenül böngészőből is futtathatók.

3. Az oktató anyagok és a dokumentáció jók; sok kiegészítő könyvtár is készült már.


Folyt. köv.