vizualizacio: X vagy gdk/gtk?

 ( apal | 2008. március 29., szombat - 17:41 )

Sziasztok!
Szeretnenk csinalni numerikus szamitasokat, amiket futas kozben jo lenne vizualizalni: a progi megnyit egy kelloen nagy, mondjuk 500x500-as ablakot es abba rajzol ki a szimulacio altal kiszamolt bitmap-eket (nehany frame/sec-es sebesseggel).
A hatteresemenyekkel meg az interakciokkal (XEvent, foleg expose) sem kell torodni, ha valaki kozben rahuz valamit az ablakra az igy jart.
Porbalkoztam gtk+gdk, ezen belul GdkPixbuf/GdkPixmap kombinacioval, de valahogy csak akkor hajlando mukodni a dolog, ha gtk_main()-t hasznalok, es abbol hivok ki (akar "expose_event"-tel, akar g_timeout_add()-dal idokozonkent, de ugye pont az expose-val nem akarok foglalkozni). Ugy, hogy kezzel (gdk_draw_drawable(), gdk_draw_pixmap()) teszem ki a dolgokat egymas utan, nem akar mukodni, csak akkor rajzol ki barmit is, ha ezek callback-ban (lasd ugye expose, timeout) vannak. A kirajzolando eredmeny az tenyleg egy bitmap-ben (egy sx * sy * 3-as, sorfolytonos RGB unsigned char * tombben) keletkezik, ez a GdkPixbuf szamara tok jo is lenne (lasd gdk_pixbuf_new_from_data()).
Van-e erre a problemara valami egyszeru megoldas vagy trukk? gtk az jo lenne, mert hordozhato, de akar nativ Xlib is jo, lenyeg hogy linux/unix alatt menjen.
koszi, A.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

No, vegul a nativ X11, azon belul is az XCreateImage es az XPutImage gyozott...:] Van par dolog me'g amit nem ertek, pl minek kell XNextEvent()-et hivni a legelejen, enelkul az elso frame-t nem rajzolja ki, de ezt leszamitva szepen mukodik.

Nem 100%, hogy értem a problémát, illetve eddig egy gtk-s progit írtam, de az biztos, hogy az összes ablakozó rendszer úgy múködik, hogy fut bennük egy eventloop, ami kezeli a történéseket.
Többek között frissíti a képernyőt.

Tehát ha te belekezdesz egy jó kis számításba, és nem hagyod az eventloop-ot futni, akkor nem lesz képernyőre rajzolás.

A megoldás az, hogy a számítás külön threadben fut, majd minden kép elkészültekor küldesz egy signal-t a GUI threadnek, hogy most rajzoljon.
(Hogy az szálak közötti signal küldés gtk-ban hogy megy, arrol fogalmam nincs...)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

A szimulacio egy nagyonsoktest-problema lenne, durvan ~10k-100k pontszeru reszecske mozgasat kene figyelni, hogy hogy mozognak, hol alakulnak ki lokeshullamok, stb. Tehat az, hogy a gui-nak / x-nek pixelenkent adom a't a pontok koordinatait, az szoba sem johet: csak az lehet hatekony hogy a memoriaba egy bitmap/pixmap-be kipreparalom az abrat, es egy hivassal kirajzoltatom ezt a bitmap-et, majd folytatodik a szimulacio.

A tobbszalusag/szignalok/... kicsit agyu-vereb lenne, bar kinomban mar gtk-val ezt is kiprobaltam (nem jott be, nem hatekony).

De most ez az xcreateimage() + xputimage() kombinacio tenyleg jonak tunik, ma'r az antialiast is megcsinaltam...:]

Ez érdekes. Véletlenül nem a klasszikus mechanikában tárgyalt kéttest-probléma kiterjesztéséről van szó? Arról én azt tanultam, hogy több testre nem oldható meg szimbolikus módszerekkel, aztán később még hallottam ezt-azt, hogy bizonyos egyszerűsítésekkel 3 testre kezelhető, de nem nagyon foglalkoztam már vele. Te mit csinálsz? Numerikus módszerekkel "hajtod meg" a Lagrange-egyenletet? Vagy ez valami egészen más?

Véletlenül nem a klasszikus mechanikában tárgyalt kéttest-probléma kiterjesztéséről van szó?
Nem pontosan: a sokszazezer reszecske egymassal nem hat kolcson, csak egy adott gravitacios potenciallal, tehat lenyegeben a klasszikus kettest-problemat kell megoldani (amit meg meg lehet oldani analitikusan, tehat jo mert nem kell numerikusan integralni, stb). Ennek a kis kiserletnek inkabb az a lenyege, hogy milyen hullamok es/vagy surusodesek alakulnak ki az anyagban, mikor ez a gravitacios potencial megvaltozik. Itt maga't az "anyagot" modellezzuk sokszazezer ponttal, mert ugy joval egyszerubb, mintha folytonos kozegkent kene kezelni.

Aha. Tehát akkor egy kontinuumról van szó? Mert akkor lehetne használni egészen "alapvető" numerikus módszereket is, mint pl. véges differenciák, vagy variációs módszerek (pl. FEM, na jó, ez már leginkább semennyire sem "alapvető" :). Az elterjedt CFD módszerek is ezeket szeretik. Persze lehet, hogy nem jó, mert ezekhez atomerőmű kell, ha egy kicsit is bonyolultabb a dolog...

"Tehat az, hogy a gui-nak / x-nek pixelenkent adom a't a pontok koordinatait, az szoba sem johet"

Mondtam én ilyet? Nem.
Semeddig nem tart elküldeni a GUI threadnek egy mutatót a képre.

"A tobbszalusag/szignalok/... kicsit agyu-vereb lenne"
Pedig az eventloop miatt nagyon mást nem csinálhatsz...
(De fenntartom magamnak a jogot, hogy félreértettem a problémádat :) )

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Mondtam én ilyet? Nem.
Persze, tudom. csak azert irtm igy le a problemat, hogy jobban atjojjon hogy miert is kell kulon bitmap-ekkel szivnom, miert nem eleg ha csak pontokat/vonalakat rajzolgatok ki ;) (es az eredeti, szamitastechnikai problema is ez volt: itt akadtam el, hogy egy alapos rtfm meg kerese's utan a (pelda)programok nem akartak mukodni, kicsit nagyon felrevezeto" a libx11-hez adott manual)

Az eventekkel meg igy halistennek nem kell foglalkozni... Persze nem a legszebb - hogyha workspace-t valtasz vagy raviszel valamit vagy ki akarod loni az ablakot, akkor semmi sem fog tortenni - de most a celnak ez megfelel, remelem jodarabig.

Pedig az eventloop miatt nagyon mást nem csinálhatsz...
Igen, ezt a reszet a problemanak nehezen fogalmazhattam meg...
Szoval eventek. Ha azt mondom naivan (X11-ben) hogy

w=createwindow();
mapwindow(w);
drawsomething(w,valami);

akkor nem latok az ablakban semmit. Haviszont:

w=createwindow();
askforevents(w,"expose");
mapwindow(w);
waitevents();
drawsomething(w,valami);

akkor mar jo. Viszont nekem igazabol semmi szuksegem nincs az eventekre, en csak egy egyszeri emberke vagyok, aki _rajzolgatni_ szeretne, ablakokba.

Az első Xlib tutorial amit találtam rögtön magyarázatot adott a problémára az első oldalon. :)

http://tronche.com/gui/x/xlib-tutorial/

Az okozza a gondot, hogy az X aszinkron, tehát mikor mondasz egy mapot, akkor az visszatér, mielőtt valóban megtörténne a kérés teljesítése.
A gond az, hogy mennek a kukába azok a kérések melyek akkor érkeznek amikor nincs az ablak a képen.
Tehát neked meg kell várnod a MapNotify eventet...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Amit írok, az nem biztos, hogy segíteni fog, de a kérdésen sokat rágódtam, vitatkoztam kollégáimmal és próbálgattam magam a dolgokat.

Szóval, nekem az jött be, hogy numerikus számítások eredményeit folytonosan fájlokba mentem: néha teljes mentést, közben állandó logolást a kulcsfontosságú paraméterekről csak sima szövegfájlba. Ha érdekel valami, tail -f -fel nézegetem a logfájlt. Ha gyanúsat látok, behívom a vizualizáló progit és megnézem az eredményeket részletesebben.

A tesztelési fázisban jól jön a futás közbeni sok info, de ezt bőbeszédűbb logolással is meg lehet oldani. Nekem ez hasznosabbnak bizonyult. (17 éve írtam az első progimat, ami komolyabb num. modellezést csinált, nem vagyok teljesen kezdő.)

Menet közbeni vizualizálásra olyan dolgot szeretek, ami szkriptelhető, egyszerű grafikonokra gnuplot, komolyabb dologra opendx.

De ha Neked eleve van bitmap-ed, ki is lökheted őket mondjuk ppm-be könnyedén. Így vissza is nézheted a részlépéseket. A folytonos megjelenítésnél teljesen a memóriádra kell hagyatkoznod.

De persze lehet, hogy régimódi a gondolkozásom. Csak a saját tapasztalataimat szerettem volna leírni...

Igen, eloszor en is ilyeneken gondolkodtam hogy nagy adatfile + gnuplot vagy hogy pgm-be bele, majd mplayer-rel csinalok belole mozit, de ezelobbi megoldas a sok pont (lasd feljebb, ~100ezres nagysagrend) miatt annyira nagy overhead lenne, hogy fel perc alatt teleirna 10gigat, osszedol a diszk, stb. Ezutobbi meg kicsit tul oszver megoldas lenne, nem tul elegans szerintem...

OK, most már látom: én nem ilyeneken szoktam dolgozni. Biztos jól átgondoltad.

Az jött ki nekem a fenti írásodból, hogy a futás olyan gyors, hogy on-line érdemes szemmel "elemezni" az adatokat. Ha ez így van, akkor persze nem gond, hogy ha valamit elfelejtettél megnézni, újraindítod az egész futást. Én általában olyanokba futottam bele, hogy az éles futtatások mindig sok óráig tartanak, esélyem sincs végigvárni a futást a gép előtt, és nincs lehetőség csak azért újra indítgatni a futásokat, mert elfelejtettem valamit megnézni. Szóval a helyzetünk más.

De a kisördög tapasztalatból megszólal: ha túl leszel a teszteken, nem lesz az az igény, hogy addig nyomasd fel a részecskeszámot/egyéb paramétert, a nagyobb pontosság érdekében, hogy nem tudod a folyamatokat on-line követni és nem tudsz újra futtatni csak mert nem vettél észre valamit? És a másik kérdés tapasztalatból: rendben, hogy látsz valamit futás közben, de hogy dokumentálod? Szerintem előbb-utóbb mégiscsak valami elmentésre leszel kényszerítve.

Nekem az a tapasztalatom, hogy ha annyi adatot akarnék elmenteni a diszkre, ami nem fér el, akkor nem jól választottam ki, miket is kell elmenteni, mert nem értem még a lényeget. Lehetetlen, hogy 10G mind releváns adat legyen, miközben vizuálisan ki tudod a lényeget jelölni. Pl. ha 10^5 részecske felhőjében a sűrűséghullámokat akarod elemezni, akkor mondjuk egy cellás felosztásban a cellákba jutó részecskeszámokat elmentve (ügyes cellaméret-választással) már nagyot tömöríthetsz. Durva megoldás: a részecskék mozgási terét 65536 részre osztod, azaz x,y,és z koordinátáit 2-2 bájton ábrázolod. Ekkor 10^5 részecske koordinátáit 600kB-on le tudod tárolni, 1000 ilyen kép még csak 600MB és a lementésről kül. irányokból, nagyítással tudsz utólag képet generálni. Vagy ha csak a sűrűség számít, akkor egy listát mentesz el azon cellák x-y-z 2-2-2 bájtos halmazairól, és a cellában található részecsekszámról (erre is elég lehet 2 bájt), ahol van részecske. Ez nemüres cellánként 8 bájt, így ha mondjuk 5 részecske van nemüres cellánként átlagban, akkor 160kB egy állapot rögzítése. Persze, a felosztás finomságával lehet játszadozni...

És ha még egy front-felismerőt is beleteszel a progiba és csak a frontok helyét írod ki, az nemcsak kevesebb adatot, hanem jobban dokumentált dolgot jelent. (Durva módszerek is hatásosak lehetnek. Pl. a sűrűségeloszlás lokális maximumai vagy a sűrűségeloszlás Laplace-a.)

Bocs, fáradt vagyok, okoskodom... Ha ezeket mind végigjártad, akkor csak üres okoskodás volt mindez. Hátha mégse....