[Megoldva] gnuplot újrarajzoláskor ne vibráljon

Fórumok

Tudom, zavaros a cím, ezért elmondom. Valósidejű mérési adatokat szeretnék kirajzoltatni gnuplottal. Egy awk programban szerzem be a mérési eredményeket, majd írok tmpfs-re egy file-t, amelyik hízik mondjuk 100 mérési eredményig, aztán a 101. mérési eredmény megérkezte után az elsőt törlöm, tehát innentől kezdve a file mindig az utolsó 100 mérést tartalmazza. Van neki időbélyege, ez lesz az x tengelyen, illetve utána négy mérési pont ezek az y tengelyeken. Set multiplot layout 2,1-et használok, így két koordinátarendszer van egymás alatt, mindegyik koordinátarendszerben két-két időfüggvényt ábrázolok. A plot loop nem aszinkron, mert akkor előfordulhatna, hogy épp íródik az új adatfile, amikor olvassa a gnuplot. A szinkronizációt úgy oldom meg, hogy a

gnuplot -

parancsnak pipe-olom awk-ból a gnuplot scriptet azután, hogy a legutóbbi ideiglenes adatfile előállt. Mindig felülírom az ideiglenes adatfile-t, tehát abból csak egy van, de mindig más tartalommal.

A problémám az, hogy ez így villódzik, mert mindig újrarajzol mindent. Viszont újra is kell, mert az idő halad, tehát az x tengely felirata biztosan változik.

Hogyan lehet a gnuplot-ot dupla bufferelésre bírni? Az előző kép látszana, amíg az újat rajzolná, majd buffer cserével azonnal, flicker mentesen lenne ott az új kép.

Megoldás

Részint workaround. Nem használom a multiplotot. Két gnuplot processt futtatok, mindegyiket egy-egy wxt terminál ablakkal. Mindegyik ablakban két függvényt ábrázolok. A gnuplottal csak egyszer olvastatom fel a teljes scriptet, amikor 4 mérési pontom van. Ennyiből már illeszkedő görbét is tud rajzolni, ha szeretném. Bár most nem szeretném. :) Utána mérési pontonként újra generálom az adatfile-t, majd pipe-olom a gnuplot process-eknek az alábbiakat:

reread
replot

Más dolgom nincs vele, szépen rajzol, nem villódzik. 100 mérési pontig nő az adatfile-om, utána viszont mindig csak az utolsó 100 mérési eredmény van benne. Természetesen timestamp van a mérési pontokhoz.

Hozzászólások

Miért pipeolod a gnuplotnak a scriptet? Ahogy látom létezik reread és pause függvény, ami pont változó input miatt lett beépítve. Ott az újrarajzolásig nem fogja módosítani az előző.

Azért, mert ezzel biztosítom a szinkront. Ha újra leküldöm neki, hogy plot akármi, akkor kirajzolja, de ezt akkor teszem, amikor az adatfile-om készen van, s biztosan nem változik. A reread és pause nekem azért nem tetszik, mert a gnuplot időzít, s ehhez képest aszinkron a pillanat, amikor felülírom a file-t. Ha a reread beletrafál abba, amikor újragenerálom az adatfile-t, abból lehet baj.

De valóban, feltehetem úgy is a kérdést: hogyan tudok eseményvezérelten várakozni a gnuplotban? Tehát nem időre, hanem szeretném átjelezni neki, hogy kész az adatfile-om, dolgozhatsz vele.

Erre egyébként van ötletem. A scriptet letöltöm neki előre, utána csak a reread-et mondom neki, amikor kell. De az a gyanúm, ugyanúgy villanni fog, akkor sem fog olyan gyorsan rajzolni, hogy ne vegyem észre. Félő, hogy png ideiglenes file-t kell generálnom, azt képnézegetővel meg kell majd etetni, majd valamilyen signalt - pl. SIGUSR1 - küldeni neki, hogy hello, változott a képfile, renderelheted újra. Azt hiszem, a Geeqie tudja ezt, de ez így egyre bonyolultabb. Nem lehet egy sima oszcilloszkópot csinálni a gnuplotból?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Aha, köszi így már értem. Mondjuk ha valahogy megoldható lenne, hogy ne tempfs-t használj hanem valami pipeot akkor nagyon kis esély lenne hogy épp valami írási művelet közepét kapod el, minden memóriában menne.

Én ha lehetne tutira valami bloated megoldást használnék inkább, van realtime plotolásra pár pythonos könyvtár (pl. https://dash.plotly.com/). Persze, menőbb coreutilsból összerakni egy oszcilloszkópot de itt is jó eséllyel 10 sorból megúszod úgy, hogy már awk sem kell meg temp fájlok, közvetlenül eteted az inputtal (pollozod selecttel változott e az output, leszűröd és plotolod). Így tuti nem kell png-ket sem gyártani. 

Szerkesztve: 2020. 04. 06., h – 23:39

Milyen terminallal hasznalod a gnuplot?

Nalam a Qt terminallal a kovetkezo parancs teljesen sima animaciot produkal:

perl -MTime::HiRes=usleep -le '$|=1;for (1..1000) { print "set xr [$_:$_+1000]; plot 1, x/$_"; usleep 10000}' | gnuplot -

szerk: a tmp fajlra nincs szukseg, ha az abrazolando adatokat is a pipe-on at eteted:

perl -MTime::HiRes=usleep -le '$|=1;for (1..1000) { print "plot \"-\""; print rand() for 1..100; print "e";print""; usleep 10000}' | gnuplot -
gnuplot> help special

Multiplot, két koordinátarendszer, s mindkettőben két grafikon, azaz négy mérési eredmény az idő függvényében a cél. Amíg nem használom a multiplotot, s csak két grafikont rajzolok, nekem is tetszik. Ennek mentén a másik ötletem két gnuplot process futtatása, s két külön ablakban rajzolás.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ha a gnuplottal egy file-ba plotolsz (mondjuk megfelelő felbontású jpg), és azt megjeleníted valamivel (pl. imagemagick), az nem jó?

Elindultam ezen az úton. Ha pipe-oltam, mindig új abalkot nyitott, ami még az eddigi flickernél is rosszabb. Nem elvetendő a gondolat, vannak olyan képnézegetők, amelyeknek be lehet jelezni, hogy olvassák fel a képet újra. Van, aminek remote parancsa van erre, van, aminek signal handler-e - pl. SIGUSR1-et kell küldeni -, és van, aminek inotify interface-e, így kiszúrja, ha megváltozott a file, s újra rendereli a képet.

Egyelőre még nem fogytam ki az ötletekből, csak reméltem, van valami kézenfekvő megoldás, mivel a Gnuplot nagyon sokat tud, én meg nagyon keveset róla. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Konkrét megoldást nem tudok javasolni, csak egy két tanácsot, ami lehet hogy talán segít valamennyit.

Én multiplotot kerülni szoktam, amennyire lehet, nekem sok bajom volt vele.

Ha két koordináta rendszer kell, arra nem jó az axes x1y2, axes x2y1, stb? Többre nem jó, de kettőre még jó kell legyen.

A másik az utolsó 100 adatra: azt gondoltam, hogy az every keyword-el meg lehet oldani, de úgy tűnik nem.

Megoldás lehet viszont az x tengelyek beállítása úgy, hogy csak az utolsó 100 adatot tartalmazza. Ehhez előre be kellhet olvasni a fájlt mondjuk.

Még a stack overflow-on találtam ezt https://stackoverflow.com/questions/23587104/gnuplot-use-only-last-n-li…

A villódzásra szerintem is a fájlba plottolás lesz a megoldás.

Ez elvileg a kompozitor feladata, hogy igazodjon a vsync-hez, így nem villódzik a változó tartalom, se görgetésnél, se videóknál, és ennek érvényesnek kéne lennie gnuplot-os kirajzolásnál is.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

A helyzet ennél rosszabb. Ha sokat akar rajzolni, több frame is eltelik, mire elkészül. Szóval most nem az a legnagyobb problémám, hogy hol tart a kép letapogatása a monitorra frissítéskor, s ennek milyen a fázishelyzete a képtartalom frissítéséhez képest.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Én úgy szoktam kikerülni a villódzást, hogy a háttérben megrajzolom a képet és amikor kész az előtérbe hozom. Nem tudom ez gnuplot-tal működik-e.

Ha közvetlenül rajzolsz változó inputtal, villódzani fog, mert a rajzolást - gondolom én - a háttér inicializálásával kezded. (Az én tapasztalatom az X közvetlen programozásából származik.)

> Sol omnibus lucet.

Volt már hasonló fájdalmam nekem is, csak nem adatgyűjtés volt, hanem szimuláció, de végül is az adat az adat, mindegy, honnan van.

Tisztában vagyok vele, hogy ez most nem lesz igazán segítség, de én úgy oldottam meg a gondot, hogy írtam egy saját grafikonrajzoló modult a rendszeremhez az Allegro könyvtárra alapozva. Viszont emlékeim szerint kb. 1 hét alatt készen voltam vele, minden olyasmit tud, amit a gnuplotból használnék és értelemszerűen örök darab.

Mindazonáltal érdekelne, ha jutsz valamire a projekteddel.

Nem a külön layer-ekre gondoltam, hanem az időben egymás után jövő bufferekre. Egyiken összerakjuk a képet, aztán ha elkészült, statikus mivoltában kitesszük a kijelzőre. Utána a háttérben megint lehet firkálgatni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Azt látom, hogy lehet egyetlen gnuplottal is több x11 terminált nyitni, mégis azt az utat választottam, hogy awk-ból két külön gnuplotba pipe-olok. Ez sem triviális, hiszen honnan tudja az awk, melyik gnuplot melyik? Erre ez lett a megfejtés:

    gnuplot1 = "/tmp/gnuplot1";
    gnuplot2 = "/tmp/gnuplot2";

    cmd = "ln -sf /usr/bin/gnuplot ";

    system(cmd gnuplot1);
    system(cmd gnuplot2);

Tehát csináltam két eltérő nevű szimbolikus linket a gnuplotra, így eltérő nevekkel hivatkozhatok a pipe-ban rájuk.

A gnuplot scriptem pedig így kezdődik:

set term x11 noraise

Így nem kapkodja el a fókuszt, és az ablakok is tetszőleges pozícióba húzhatók. Mivel használok interpolációt, akkor pipe-olom a gnuplotba a gnuplot scriptemet, amikor van már négy mérési eredmény. De csak ekkor, s egyben ez indítja el a gnuplotot. Amikor a mintaszámom 4 fölött van, akkor csak egy

reread
replot

párost küldök, semmi mást. Így most élvezhető képet ad valós időben, nagyjából 4-5 új mérési eredménnyel másodpercenként.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A double-triple bufferingnek kb 50-100 hz-ig működnie kell. Afölött kicsit át kell gondolni a kijelzés módjait. Nekem voltak adataim, amiket 8-10 kHz-val kellett megjeleníteni, ehhez már csak a pöttyöket lehet kiírni, előtte törölni kell a kijelzőt egy keskeny sávban, kb, mint az oszcilloszkópnál.

Mindig a feladat határozza meg, hogy milyen kijelzőt használsz. Én a gnuplotot kerülném, saját megoldást írnék, ha a feladat egy kicsikét nagyobbacska. A gnuplott inkább csak tesztüzem. (Nem ismerem a feladatot, amit csinálsz, úgyhogy lehet, hogy mellélőttem. ebben az esetben: bocs.)

> Sol omnibus lucet.

Csak azért csináltam, hogy tudjam lehet-e, lássam a tartalékokat. (-::

1 kHz, viszont előfordult már, ha nem is általános. Volt olyan, hogy 96 kHz-val jött az adat, csak annyira volt idő, hogy egy duplapufferelt DMA átvitellel ki lehessen lapátolni az adatokat a winchesterre. A DMA puffereket oszcillószkóppal nézve lehetett csak összehangolni, hogy ne legyen adatvesztés (a két DMA áramkör valami miatt nem azonos sebességgel dolgozott!) Itt az online kijelzés szóba sem jöhetett, viszont az adatokra illetve azok változására triggerelni kellett.

Ezek csak érdekességek..., ha nem is teljesen off.

> Sol omnibus lucet.