gdf2test
gdf2test je vzorový soubor (jakoby) biomedicínských dat ve formátu GDF, přiložený v balíku BioSig. (Aby se nám nepletly různé verze, přejmenujeme si ho na gdf2test199.gdf) Pokusíme se jej analyzovat:
GDF 1.99
[editovat]- délka souboru je 31400 bytes.
- fixed header (header 1) má délku 256 bytes.
- většina položek fixní hlavičky jsou buď řetězce anebo čísla bez znaménka, začínající na sudých posicích, proto si utilitou od (octal dump) vypíšme header jako znaky a jako dvojbytová dekadická čísla:
od -N 256 -Ad -t cu2 gdf2test199.gdf | less
0000000 G D F 1 . 9 9 X X 17479 8262 11825 14649 8280 8280 8224 8224 0000016 8224 8224 8224 8224 8224 8224 8224 8224 * 0000080 \0 \0 \0 002 r e c o r d i n 8224 8224 0 512 25970 28515 25714 28265 0000096 g i d e n t i f i c a t i o n 8295 25705 28261 26996 26982 24931 26996 28271 0000112 8224 8224 8224 8224 8224 8224 8224 8224 * 0000144 ) ) ) \0 \0 270 L 212 8224 8224 8224 8224 10537 41 47104 35404 0000160 200 371 7 203 270 210 \0 \0 225 032 321 226 374 . \v \0 63872 33591 35000 0 6805 38609 12028 11 0000176 \0 \0 \0 \0 021 340 \n \0 \a \0 \0 \0 \0 \0 \0 \0 0 0 57361 10 7 0 0 0 0000192 b 4 o m 1 . 9 2 \0 \0 \0 \0 \0 \0 \0 \0 13410 28015 11825 12857 0 0 0 0 0000208 \0 \0 \0 \0 \0 \0 300 377 \0 \0 300 377 \0 \0 300 377 0 0 0 65472 0 65472 0 65472 0000224 \0 \0 300 377 \0 \0 300 377 \0 \0 300 377 2 \0 \0 \0 0 65472 0 65472 0 65472 50 0 0000240 \0 \0 \0 \0 001 \0 \0 \0 005 \0 \0 \0 006 \0 \0 \0 0 0 1 0 5 0 6 0 0000256
Co z toho můžeme vykoukat:
- byty 0–7: formát a verze (char[8]) = 'GDF 1.99'
- byty 184–185: celková délka všech headerů (počet 256-bytových bloků) (uint16) = 7
- byty 236–243: počet datových záznamů (anebo -1 kdyžje neznámý) (int64) = 50
- byty 244–251: trvání záznamu ve tvaru zlomku čitatel, jmenovatel (nedoporučuje se) (uint32[2]) = 1 / 5 = 0.2 s
- (zbytek je zhruba stejný jako u verze 2.11, viz níže.)
Celková délka všech headerů je tedy 7 * 256 = 1792. Celková délka souboru je 31400 bytes, na data a tabulku eventů tedy zbývá 31400 - 1792 = 29608 bytes.
Popis kanálů
[editovat]#No | Label | Fs[Hz] | SPR |
---|---|---|---|
# 1: | chan 1 | 1000.0 | 200 |
# 2: | chan 2 | 100.0 | 20 |
# 3: | chan 3 | 200.0 | 40 |
# 4: | chan 4 | 100.0 | 20 |
# 5: | chan 5 | 20.0 | 4 |
# 6: | NEQS | 0.0 | 0 |
GDF 2.11
[editovat]konverze pomocí save2gdf
[editovat]Zkonvertujeme gdf2test199.gdf do poslední verze GDF konverzní utilitou save2gdf verze 0.94, nainstalovanou z binárek pro Ubuntu:
save2gdf -VERBOSE=4 gdf2test199.gdf gdf2test221-094.gdf > gdf2test199.gdf.094.VERBOSE4
- /199.gdf.094.VERBOSE4 – výpis headerů při konverzi
To samé zkusíme udělat konverzní utilitou verze 0.93, kterou jsme si přeložili ze zdrojových balíků:
./save2gdf -VERBOSE=4 gdf2test199.gdf gdf2test221-093.gdf > gdf2test199.gdf.093.VERBOSE4
Oba výpisy se v detailech liší (např. zřejmá chyba 1 s v datu narození a čase vyšetření). Výsledné GDF soubory gdf2test221-093.gdf a gdf2test221-094.gdf jsou ale shodné. Délka těchto souborů je 31656 bytes, jsou tedy delší než soubor verze GDF 1.99.
Headery
[editovat]Fixed header
[editovat]Je to povinný header o délce 256 bytes na začátku každého GDF souboru:
od -N 256 -Ad -t cu2 gdf2test221-094.gdf > gdf2test221hdr-od.txt
0000000 G D F 2 . 2 1 X X \0 \0 \0 \0 \0 17479 8262 11826 12594 8280 88 0 0 0000016 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 0 0 0 0 0 0 0 0 * 0000080 \0 \0 \0 \0 \0 \0 \0 002 r e c o r d i n 0 0 0 512 25970 28515 25714 28265 0000096 g i d e n t i f i c a t i o n 8295 25705 28261 26996 26982 24931 26996 28271 0000112 8224 8224 8224 8224 8224 8224 8224 8224 * 0000144 ) ) ) \0 \0 270 L 212 8224 8224 8224 8224 10537 41 47104 35404 0000160 200 371 7 203 270 210 \0 \0 225 032 321 226 374 . \v \0 63872 33591 35000 0 6805 38609 12028 11 0000176 \0 \0 \0 \0 021 340 \n \0 \b \0 \0 \0 \0 \0 \0 \0 0 0 57361 10 8 0 0 0 0000192 b 4 o m 1 . 9 2 \0 \0 \0 \0 \0 \0 \0 \0 13410 28015 11825 12857 0 0 0 0 0000208 \0 \0 \0 \0 \0 \0 300 377 \0 \0 300 377 \0 \0 300 377 0 0 0 65472 0 65472 0 65472 0000224 \0 \0 300 377 \0 \0 300 377 \0 \0 300 377 310 \0 \0 \0 0 65472 0 65472 0 65472 200 0 0000240 \0 \0 \0 \0 232 231 231 231 231 231 251 ? 006 \0 \0 \0 0 0 39322 39321 39321 16297 6 0 u4: 0 2576980378 1068079513 6 0000256
Co z toho můžeme vykoukat:
- byty 0–7: formát a verze (char[8]) = 'GDF 2.21'
- byty 8–73: identifikace pacienta (char[80]) = 'X X'
- byty 74–83: rezervovány (uint8[10]) = ' '
- byty 84–87: zakódováno: kouření, alkohol, drogy, váha, výška, pohlaví, dominantní ruka, slabozrakost (zakodováno do bitů a uint8, nebudeme teď řešit)
- byty 88–151: identifikace záznamu (char[64])= 'recording identification'
- byty 152–167: zeměpisná šířka, délka a nadmořská výška (uint32[4]) – neřešíme
- byty 168–175: datum a čas začátku záznamu (uint32) – speciální formát
- byty 176–183: datum narození (uint32) – speciální formát
- byty 184–185: celková délka všech headerů (počet 256-bytových bloků) (uint16) = 8
- byty 186–191: klasifikace pacianta dle ICD (byte[6])=
- byty 192–199: identifikace výrobce zařízení (uint64) = nějaké číslo
- byty 200–205: rezervováno (byte[6])= samé \0
- byty 206–211: rozměry hlavy (uint16[3]) = 0, 0, 0
- byty 212–223: posice referenční elektrody (float32[3]) =
- byty 224–235: posice zemnící elektrody (float32[3]) =
- byty 236–243: počet datových záznamů (anebo -1 když je neznámý) (int64) = 200
- byty 244–251: trvání záznamu ve tvaru zlomku čitatel, jmenovatel (nedoporučuje se) (uint32[2]) = 2576980378/1068079513 = 2.4127233474985679
- byty 252-253: počet kanálů (uint16) = 6
- byty 254–255: rezervováno (uint16)
- (Změny oproti verzi 1.99 vyznačeny tučně)
Variable header (Header 2)
[editovat]Obsahuje údaje o jednotlivých kanálech a tak jeho délka je přímo úměrná počtu kanálů NS; jeho celková délka je pak 256 * NS bytes. V našem případě tento header pro 6 kanálů má délku 6 * 256 = 1536 bytes.
Základní popis jednotlivých kanálů v headeru:
#No | Label | Fs[Hz] | SPR |
---|---|---|---|
# 1: | chan 1 | 1000.0 | 50 |
# 2: | chan 2 | 100.0 | 5 |
# 3: | chan 3 | 200.0 | 10 |
# 4: | chan 4 | 100.0 | 5 |
# 5: | chan 5 | 20.0 | 1 |
# 6: | NEQS | 0.0 | 0 |
(další informace zatím neuvádíme)
Seznam TLV elementů (Header 3)
[editovat]Je to optional header, který byl přidán až do verse GDF 2.00. Jeho význam zatím moc nechápu, TLV znamená "tag-length-value", ale co to má být? Předpokládám, že bude mít délku 256 bytes. Budu ho tedy hledat na offsetu 7 * 256 = 1792:
od -Ad -td2 -j1792 -N256 gdf2test221zk2.gdf
0001792 1029 0 127 257 0 0 0 0 0001808 0 0 0 0 0 0 0 0 * 0002048
od -Ad -tu1 -j1792 -N256 gdf2test221zk2.gdf
0001792 5 4 0 0 127 0 1 1 0 0 0 0 0 0 0 0 0001808 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 0002048
Všechny headery
[editovat]Všechny headery dohromady budou mít v našem případě délku 256 + 1536 + 256 = 2048 bytes. To odpovídá 8 datovým blokům po 256 bytech.
Celková délka souboru je 31656 bytes, na data + tabulky eventů tedy zbývá 31656 -2048 = 29608 bytes, což je stejná hodnota jako u verze 1.99.
Data
[editovat]Data jsou do souboru ukládána po jednotlivých kanálech, všechny navzorkované hodnoty jsou uloženy (v našem případě) jako int16. Fs[Hz] označuje vzorkovací frekvence, které mohou být pro různé kanály různé. Další náležitosti jsou však už předmětem dohadů.
Zkratka SPR ve variabilním headeru zřejmě znamená samples per record (block). Co se ale míní tím záznamem či blokem?
Sigviewer zobrazí soubor délky 10 s. Při vzorkovací frekvenci 1 kHz by kanál #1 obsahoval 10000 vzorků. Pokud to obnáší 50 bloků, pak 1 blok by obsahoval 200 vzorků neboli 400 bytes a stejně tak i u ostatních kanálů. Ale znamená 1 blok 400 anebo 512 bytes? A pokud délka dat nebude přesně celistvým násobkem bloků, jak se určí přesný počet vzorků? Aby to bylo zajímavější, hodnoty SPR u verze 2.11 se liší od hodnot téhož původního souboru – jsou 4x menší, tj. jakoby blok byl 4x větší.
Zkusíme utilitou save2gdf uložit soubor jako BIN, tj. do oddělených souborů, případně ASCII, a do tabulky si doplníme počty vzorků.
#No | Label | Fs[Hz] | SPR | samples |
---|---|---|---|---|
# 1: | chan 1 | 1000.0 | 50 | 10000 |
# 2: | chan 2 | 100.0 | 5 | 1000 |
# 3: | chan 3 | 200.0 | 10 | 2000 |
# 4: | chan 4 | 100.0 | 5 | 1000 |
# 5: | chan 5 | 20.0 | 1 | 200 |
# 6: | NEQS | 0.0 | 0 | 0 |
Všechny kanály #1 až #5 dohromady obsahují 10000+1000+2000+1000+200=14200 vzorků, tj. 28400 bytes.
Podíváme se tedy přímo do souboru:
od -Ad -td2 -w20 -j2048 gdf2test221zk2.gdf | less
0002048 1 6 11 16 21 26 31 36 41 46 0002068 51 56 61 66 71 76 81 86 91 96 0002088 1 6 11 16 21 26 31 36 41 46 0002108 51 56 61 66 71 76 81 86 91 96 0002128 1 6 11 16 21 26 31 36 41 46 0002148 ! 25 75 25 75 25 ! 13 38 63 88 13 0002168 38 63 88 13 38 ! 27 77 27 77 27 0002188 ! 44 !! 51 56 61 66 71 76 81 86 91 0002208 96 1 6 11 16 21 26 31 36 41 0002228 46 51 56 61 66 71 76 81 86 91 0002248 96 1 6 11 16 21 26 31 36 41 0002268 46 51 56 61 66 71 76 81 86 91 0002288 96 ! 75 25 75 25 75 ! 63 88 13 38 0002308 63 88 13 38 63 88 ! 77 27 77 27 0002328 77 ! 52 !! 1 6 11 16 21 26 31 36 0002348 41 46 51 56 61 66 71 76 81 86 0002368 91 96 1 6 11 16 21 26 31 36 0002388 41 46 51 56 61 66 71 76 81 86 0002408 91 96 1 6 11 16 21 26 31 36 0002428 41 46 25 75 25 75 25 13 38 63 0002448 88 13 38 63 88 13 38 27 77 27 0002468 77 27 44 51 56 61 66 71 76 81 0002488 86 91 96 1 6 11 16 21 26 31 0002508 36 41 46 51 56 61 66 71 76 81 0002528 86 91 96 1 6 11 16 21 26 31 0002548 36 41 46 51 56 61 66 71 76 81 0002568 86 91 96 75 25 75 25 75 63 88 0002588 13 38 63 88 13 38 63 88 77 27 0002608 77 27 77 52 1 6 11 16 21 26 0002628 31 36 41 46 51 56 61 66 71 76 0002648 81 86 91 96 1 6 11 16 21 26 0002668 31 36 41 46 51 56 61 66 71 76 0002688 81 86 91 96 1 6 11 16 21 26 :
Skutečně tam začínají data kanálu #1. Tak konečně možná začínám chápat, co je to ten blok? Vidíme, že tu po sobě následuje (pro čitelnost jsme si oddělili jednotlivé kanály vykřičníky, mezi #5 a #1 dva !!:
- 50 vzorků kanálu #1
- 5 vzorků kanálu #2
- 10 vzorků kanálu #3
- 5 vzorků kanálu #4
- 1 vzorků kanálu #5
- (0 vzorků kanálu #6)
Což jsou právě ty SPR. Takže v tomto případě record (blok) = 50+5+10+5+1=71 vzorků neboli 142 bytes. A takovýchto bloků bude celkem 200, tedy celkem bude datová sekce obsahovat 200*71=14200 vzorků a bude dlouhá 200*142 = 28400 bytes. Zkusíme si tedy zobrazit poslední blok na offsetu 2048+28400-142 = 30306:
od -Ad -td2 -w20 -j30306 gdf2test221zk2.gdf | less
0030306 51 56 61 66 71 76 81 86 91 96 0030326 1 6 11 16 21 26 31 36 41 46 0030346 51 56 61 66 71 76 81 86 91 96 0030366 1 6 11 16 21 26 31 36 41 46 0030386 51 56 61 66 71 76 81 86 91 96 0030406 75 25 75 25 75 63 88 13 38 63 0030426 88 13 38 63 88 77 27 77 27 77 0030446 52 !! 25603 0 0 17530 100 0 200 0 300 0030466 0 400 0 500 0 600 0 700 0 800 0030486 0 900 0 1000 0 1100 0 1200 0 1300
Takže to souhlasí, na offsetu 2048+28400 = 30448 nám už začíná zase něco jiného.