見出し画像

DICOMオブジェクト:SQのエンコーディング

DICOMオブジェクトについて過去に解説してきた通り、SQ(Sequence)というVRタイプの属性は、DICOMデータのエンコーディングにおいて特別な役割を果たします。SQタグを用いることで、DICOMオブジェクトの構造上のレイアウトは劇的に整理しやすくなります。

SQ属性は、それ自身のデータを持ちません。代わりに、一つ以上のDICOMオブジェクトを風呂敷のように含み、ツリー状に入れ子にし、ひとつのDICOMオブジェクトにできます。

さらに、SQ属性の中へ入れ子にされたDICOMオブジェクトは、SQ属性であってもよいのです。つまり、DICOMオブジェクトをさらに入れ子の入れ子にすることができます。

その結果、図に示すように、複数の入れ子のレベル(ネストレベル)を持つことができます。

SQ属性によるDICOMオブジェクトのネスト

ネストされたDICOMオブジェクトがSQ属性を持たなくなったレベルで、ネストの階層は停止します。このようにすることで、オブジェクトの概念全体がきれいにまとめ上げられ、自然に理解できるようになります。

実際、広く用いられているXMLなどでは、DICOMと同じようにデータの入れ子構造をフル活用しています。

では、このSQ属性はどのようにエンコードするのかについてみていきます。

DICOMオブジェクトは、データエレメント(属性)の集合であるため、各エレメントをリストにして、逐次エンコードして、データを繋げていきます。

対象のエレメントがSQ属性であった場合は、SQエンコーディング方式を用いて、SQ属性内にネストされた複数のエレメントを一つのDICOMオブジェクトとしてカプセル化します。

このとき、VR エンコード(Implicit or Explicit)、SQ属性の区切り記号の有無(データ長が既知あるいは未定義長なのか)で、方法が異なってきます。

次に示す3つの例は、一般的なSQのエンコーディング方法です。

例1:SQデータエレメント(属性),明示的VR,SQ属性のデータ長は未定議長
例2:SQデータエレメント(属性),暗黙的VR,SQ属性のデータ長は既知(16進数で4+4+1234+4+4+1000=2244)
例3:SQデータエレメント(属性),暗黙的VR,SQ属性データ長は未定義,データ長が未定義のネストDICOMオブジェクトが混在

SQ属性内にネストされる(1つ以上の)DICOMオブジェクトは、シーケンスの中のアイテム(その名もシーケンスアイテム)としてエンコーディングされます。エンコードの際、各オブジェクトの前に、(FFFE,E000) Itemタグという属性が設定されます。

SQタグは、データ長が明示されるかどうかによって、エンコード方法が変わります。

  • ネストされるDICOMオブジェクトのデータ長がすべて明示されている場合(例1と2)

    • 暗黙的・明示的のVRから好きな方を選択して設定できます。SQが明示的VRを使うとき、すべてのDICOMオブジェクトのデータ長は明示される必要がありますが、SQ属性そのもののデータ長は未定義でもOKです(例1)。

  • ひとつでもデータ長が明示されない(未定義長が設定された)DICOMオブジェクトがシーケンスアイテムとして含まれる場合(例3)

    • 暗黙的・明示的のVRから好きな方を選択して設定できます。SQ属性自体のデータ長も未定義長になります。

SQ属性、あるいはシーケンスアイテム(ネストされるDICOMオブジェクト)が未定議長の場合は、いずれも0xFFFFFFFFがデータ長として設定されます。
SQ属性自体のデータ長が未定義の場合は、SQ属性の最後に、シーケンスの終わりを知らせるための(FFFE,E0DD) SequenceDelimitationItemタグを付けます。
また、ネストされるDICOMオブジェクトのデータ長が未定義の場合は、未定義長アイテムの最後に、(FFFE, E00D) ItemDelimitationItemタグを付けます。

  1. Explicit/Implicit VRなSQかつSQデータ長が定義されている場合
    SQ Item (DICOM Obj) Item (DICOM Obj) …

  2. Explicit/Implicit VRなSQかつSQデータ長が未定義の場合
    SQ Item (DICOM Obj) Item (DICOM Obj) …SeqDelimItem

  3. データ長が未定義のアイテムをネストする場合(SQの扱いは①②に従う)
     (シーケンスアイテム)… Item (DICOM Obj) ItemDelimItem …

SequenceDelimitationItem, ItemDelimitationItemの区切りタグは、前者はSQ VRな属性の終わりを、後者はシーケンスアイテムであるDICOMオブジェクトの終わりをマークするためだけに使われます。それ自体で値は持たないため、データ長は0です。

XMLでいえば、未定義のデータ長である(gggg, eeee) SQタグは、 "<"、(FFFE,E0DD)シーケンス区切りタグは">"の役割を果たしています。 同様に、ネストされるデータ長が未定義のオブジェクト(またはシーケンスアイテム)は、(FFFE,E000) Itemタグが"<"として機能し、(FFFE,E00D)Item区切りタグ が">"に対応しているイメージです。

Implicit/Explicit VRの選択にかかわらず、いずれの場合も、SQ属性データ長をあえて未定義にしておくと、このように区切りアイテムで仕切ればいいだけなので、扱いやすくなる利点があります。例2のように、すべてのシーケンスアイテムのデータ長が明示できる場合はそれはそれでいいのですが、あとから変更を加えるようなときには、データ長は未定義にして、区切っておくだけでいいなら、そのほうが扱いやすいという場面はあるでしょう。

最後に、ネストされるDICOMオブジェクトには、SQ属性も設定できることをおさらいしたいと思います。
次のような簡単な例をみていきます。

SQのネスト構造

データブロックの">"は、階層の深さを表します。">"はバナナレベル、">>"はミルクレベルです。入れ子にしたDICOMオブジェクトをシーケンスタグを使ってさらに入れ子にしていることがわかります。

このように階層化されたDICOMオブジェクトは、もっとも下の(枝葉でいうなれば葉っぱレベル,図でいえばミルクレベル)オブジェクトから順にエンコードされます。

まず、ミルクレベルのDICOMオブジェクトがエンコードされ、 次に、ミルクレベルのオブジェクトは、Referenced Instance SQ属性のシーケンスアイテムとして配置されます。これで、バナナレベルの階層がエンコードできました。そして最後に、リンゴレベルのDICOMオブジェクトがReferenced Series SQ属性に格納され、ルート(親)DICOMオブジェクトとなります。

このように、SQエンコーディングは、再帰的にエンコーディングが行われる仕組みになっています。


Stay Visionary

この記事が気に入ったらサポートをしてみませんか?