gdf2test

Z Wikiverzity


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

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.