最終更新: a few seconds ago Remove Netlify-related code from main (grafted, HEAD)
MongoDB に保持するシリーズパラメータ追加
概要
CIRCUS システムがまだ対応していないタイプの DICOM 画像(カラー画像、H.264 動画など)があるので、それらに対してはインポート時に警告が出たり、ジョブ投入前にエラーが出せるようにしたい。一方で、現状では対応していないタイプかどうかを決定できるだけの情報 (TransferSyntaxUID, PixelRepresentation, etc.) が MongoDB データベースに入っていない。
正しくエラーを出すという目的を達成するための前段階として、MongoDB のシリーズに保存する DICOM タグデータの種類を大幅に増やし、今後の処理が容易になるようにする。
新たに保管する DICOM データ
- (0002,0010) TransferSyntaxUID
- (0018, xxxx) / (0020, xxxx) のすべて
- (0028, xxxx) のすべて
TransferSyntaxUID は画像データの基本的なフォーマット(ビッグエンディアンであるか否か、など)が規定されている重要なタグであり、この時点で完全にサポート外のデータ(動画など)をはじくことができる。
0018 グループおよび 0020 グループには、機械の撮像パラメータに対応する雑多な数字が羅列されている(0018 と 0020 に本質的な違いはなく、単にここに保管されるデータの種類が多いので 0020 が 0018 の続きのようになっている)。CT の管電圧や再構成関数、MRI の磁場強度やエコー時間など。ここの値で CIRCUS 自体の動作が変わる可能性は低いが、CAD 側の処理にとっては割と重要な値である可能性もあるので、今のように選択的に保管するのではなく、多めにデータとして保管しておく。
0028 グループには、BitsAllocated, PhotometricRepresentation, WindowCeneter など、画像の形式・画像表示に関わるパラメータが羅列されている。ここは CIRCUS RS などの動作に必須な情報が多く保存されており、ここの値がおかしい場合には CIRCUS が誤作動する可能性が大いにある。
問題として、これらの DICOM タグがファイル内にどんなバイナリ形式で保管されているのかについては、DICOM ファイル内に書き込まれているとは限らない。DICOM のデフォルトである Implicit VR Little Endian と呼ばれる TransferSyntax の画像では、例えば (0028, 0301) というタグに保存されているのが文字列なのか整数なのか日付なのか、といった情報は DICOM ファイル内には載っていない。代わりにアプリケーション(つまり circus-api)側が (0028, 0301) に保存されているバイナリ列がどんな形式 (Value Representation; VR) で保管されているのかを知っておく必要がある。
この目的で使うのが DICOM 辞書であり、今回は dicom-data-dictionary を使う。これを使うと (0028, 0301) は CS (Code String) という形式 (VR) であり、うまり ASCII 文字列としてバイト列を解釈すべき、ということが判断できる。DICOM で使われている VR はこちらのページで確認できる。
ステップ 1. パラメータ取得と保存
- dicom-data-dictionary を circus-api の dependency として追加する。
createDicomTagReader.tsにあるextractParametersを、現在の既知のタグのみをハードコードで取ってくる形式ではなく、上記の DICOM 辞書ベースで上記グループのデータを全部とってくる形式に改める。Parametersインターフェースを、もっとなんでも入る汎用的なものに改める。
注意事項:
- 下の 2 つの DICOM タグは全走査対象外のグループにあるため、これらは現状と同じような形でハードコードで取得して、parameters に含める。
- transferSyntaxUID: x00020010
- pixelValueUnits: x00541001
- dicom-data-dictionary が PascalCase 形式の文字列なので、全部
extractParametersの中身も PascalCase にする。RepetitionTimeではなくRepetitionTimetransferSyntaxUidではなくTransferSyntaxUID
- それぞれの VR から文字列に変換するための仕組みについては以前に作ったことがあるので、https://github.com/smikitky/vscode-dicom-dump/blob/master/src/extractor.ts#L41 を参照してだいたい再利用して良い。(文字コードまで対応する必要があるかどうかは要検討)
ステップ 2. インポート済みの DICOM ファイルへのパラメータ付加
過去のインポート済みのシリーズに対応する MongoDB のドキュメントには parameters があるものの、その中身はキーが camelCase で入っていたり、必要なデータが十分含まれていなかったりする。これを修正するために、新しく refresh-series-parameters という CLI スクリプトを作成し、テストも行う。
基本的には以下のような動作を行う。
const cursor = models.series.findAsCursor({ importDate: { $lte: { maxDate }}});
for await (const series of cursor) {
const repoSeries = dicomFileRepository.getSeries(series.seriesUid);
const firstImage = await repoSeries.getImage(multirange(series.images).min());
const tags = dicomTagReader(firstImage);
models.series.updateOne(...);
}
"maxDate" は「これより前にインポートされた日付を処理する」というオプション。適宜コマンドラインから取ってくる。
テストは専用の series の fixture とモック化した memoryDicomFileRepository / dicomTagReader を使って行う。