Linuxでdcmtkを利用することにより、DICOMヘッダーから被験者のID、生年月日、性別、年齢を取得できるワンライナー

ある研究データセットにおいて、被験者リストに性別や年齢の記載もれがあり、MRIのDICOMデータから取得することを考えてみました。

説明が不要な方は、dcmtkさえインストールしてあれば、次のワンライナーで得られます。

$ for f in $(ls -F | grep /); do echo $f; dcmdump $(find $f -type f | sed -n 1p) | grep -E "0010,0020|0010,0030|0010,0040|0010,1010" | awk '{ print $7, $3}' ; echo ""; done

以下、解説です。

  • DICOMタグ
  • DICOMでは、被験者情報は以下のタグで規定されています。

    (0010,0020) 被験者ID
    (0010,0030) 被験者生年月日
    (0010,0040) 被験者性別
    (0010,1010) 被験者年齢

    なので、この情報を抽出できればいいわけです。

  • DICOMヘッダを参照できるプログラム
  • LinuxではDICOMのヘッダを確認するツールとしては、dcmtk がよく使われているかと思います。
    Ubuntuでは、コマンド一発で入ります。

    $ sudo apt install dcmtk
    

    dcmdumpというのがヘッダを出力するプログラムとなります。

  • DICOMファイルひとつを選択
  • DICOMは何千ものファイルがひとつのディレクトリに入っています。しかし、被験者情報はすべて同一ですから、
    とりあえずひとつのファイルを参照できればいいことになります。
    (なお、今回は、ひとつのディレクトリに複数の被験者が入っている場合は想定していません。ひとつのディレクトリに一人のデータが入っていることを想定しています。モダリティ毎にサブディレクトリがあるのは問題ありません)

    たいていの場合、DICOMファイルは .dcm という拡張子がつきますが、ときにはつかない場合もあります。

    ただ、ラッキーなことに、DICOMファイル以外にファイルが入る可能性は少ないですから、とりあえずファイルをひとつ選択します。
    これは、 find と sed を使えば可能になります。

    find 検索ディレクトリ -type f 
    

    で検索ディレクトリ以下にあるファイルを検索できますし、

    sed -n 1p
    

    をパイプでつないであげれば、findの結果のうち、1番上にあるものだけを表示できるわけです。

    これまで説明したことを組み合わせると

    dcmdump $(find 検索ディレクトリ -type f | sed -n 1p)
    

    となります。

  • 該当タグのある領域を抽出
  • grep を使います。grep はオプション -E を使えば、検索キーワードを | で区切ることで複数のキーワード検索ができます。

    今の場合は、

    grep -E "0010,0020|0010,0030|0010,0040|0010,1010"
    

    となります。

    先程のものと組み合わせると、

    dcmdump $(find 検索ディレクトリ -type f | sed -n 1p) | grep -E "0010,0020|0010,0030|0010,0040|0010,1010"
    

    となるわけです。

    今、検索ディレクトリを . に置き換えて実行してみると以下のようになりました。

    (0010,0020) LO [Subject001] # 28, 1 PatientID
    (0010,0030) DA [19730903] # 8, 1 PatientBirthDate
    (0010,0040) CS [F] # 2, 1 PatientSex
    (0010,1010) AS [042Y] # 4, 1 PatientAge

    いい感じで抜き出せています。
    こうなると少し贅沢をしたくなってきます。

  • 出力書式の整形
  • awkを使って、出力形式を変更してみます。
    [Subject001] は第3列、PatientIDは第7列にありますので、以下のようにしてみます。

    dcmdump $(find -type f | sed -n 1p) | grep -E "0010,0020|0010,0030|0010,0040|0010,1010" | awk '{ print $7, $3 }'
    

    PatientID [Subject001]
    PatientBirthDate [19730903]
    PatientSex [F]
    PatientAge [042Y]

    いい感じですね。

  • forループで繰り返し対応
  • 最後は、forループに入れ、一気に情報を取得できるようにします。

    for f in $(ls -F | grep /); do echo $f; dcmdump $(find $f -type f | sed -n 1p) | grep -E "0010,0020|0010,0030|0010,0040|0010,1010" | awk '{ print $7, $3}' ; echo ""; done
    

これで一気に情報を取得できるようになりました。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください