最終更新: a few seconds agoRemove Netlify-related code from main (grafted, HEAD)

CIRCUS DB データ構造

CIRCUS DB の基本的なデータ構造と各種キーの意味について解説する。用語はトップダウン的に並んでいるので、新規の用語の意味については後の方を参照。

凡例

  • 🔑: Primary key、ないし Primary key 的に扱う必要があるもの。兄弟間で一意である必要があるもの。API 実装において、プログラム的に一意であることを保証する必要がある。
  • (🔑): 通常は兄弟間で一意であることが期待されるが、プログラム的にそれを強制する必要がないということを明示的に示す。逆に言えば、これでマークされている値は必ずしも一意ではないため、プログラム上でキーとして利用してはいけない。
  • 🔗: 外部の何らかのキー 🔑 への参照となっているもの。API 実装において、データ作成・更新時に整合性の確認が必要なもの。
  • 🔸: データの意味あいとして省略可能な文字列。リソース作成時にこのデータが空文字列でも受け付ける。ただし API からリソースを返す場合には、これらは空文字列として返すこと。

下記で「グローバルに一意」とは、GUID のように世界中で一意となる、十分に長い識別子のことを表す。

基本的なデータ概念図

DB構造

プロジェクト Project

名前のついた、「ケースのコンテナ」となる概念。例えば「XYZ病院の大腸CT症例収集プロジェクト」「肺転移症例集」といったものがプロジェクトである。

すべてのケースは1つのプロジェクトに所属する。ケースが1つでも結び付いている場合、プロジェクトの削除はできない。プロジェクト名やプロジェクトの説明は後から自由に変更可能。

Project:

field type description
projectId 🔑 string ランダム生成されるプロジェクト識別用文字列。プロジェクトを新規作成した時に生成される。通常はユーザの目に見えない。共有機能との兼ね合いで、世界で一意であることが期待されるため、十分に長いものである必要がある。
projectName (🔑) string 短いプロジェクト名。英数字推奨。
description string 🔸 プロジェクトの長い説明。
tags Tag[] プロジェクトで利用可能なタグ一覧。
caseAttributesSchema SchemaEntry[] 所属するケースのケースアトリビュートのスキーマ情報。
labelAttributesSchema SchemaEntry[] 所属するケースのラベルアトリビュートのスキーマ情報。
windowPresets WindowPreset[] CIRCUS RS のビューアで使うウィンドウプリセットの一覧。
windowPriority string CIRCUS RS の初期ウィンドウをどの値にするかを決定する文字列。...

現バージョンでは readGroups, writeGroups, addSeriesGroups, viewPersonalInfoGroups, moderateGroups という権限に関係する設定がここに書かれていたが、これらは廃止し、Gruop 側で持たせる情報とする。Project としてはインストレーション間で共有できるようなスキーマ系情報を主に記載することにする。

Tag:

field type description
caption 🔑 string タグ名。
color like #ffffff タグ背景色。

SchemaEntry:

field type description
key 🔑 string キー。通常は英数字。
caption (🔑) string 表示用キャプションとなる任意の文字列。
type 'text' | 'number' | 'boolean' | 'select' このキーに対応する値の型。
spec object 様々な付帯情報(選択肢など)。ソースコード参照。

WindowPreset:

field type description
label (🔑) string プリセット名。
level number ウィンドウレベルとなる数字。
width number ウィンドウ幅となる数字。

ケース Case

ユーザ操作によって作成され、プロジェクトに集められる、個々の臨床症例のこと。CIRCUS DB で作成・編集される最も重要なデータ。ケースはリビジョンの集合としてバージョン管理される。

Case という語は多くの言語で予約語であるため、これが使えない場面では必要に応じて ClinicalCase という識別子を使う。意味は同じ。

すべてのケースは1つのプロジェクトに所属する(ケース作成時にプロジェクトを設定する。あとで所属を変更することは現時点では不可能)。

field type description
caseId 🔑 string ケースID。グローバルに一意。
projectId 🔗 string 所属しているプロジェクトの projectID
revisions Revision[] リビジョンのリスト。ケースの実データの大部分はここに保存される。新しいリビジョンはリストの最後に付加される。つまりインデックスが大きいほど新しいデータになる。
latestRevision Revision 最新リビジョンのデータ。revisions[revisions.lenght - 1] と同じものをそのまま格納する。データとしては冗長だが MongoDB で検索を高速に行うために存在している。
patientInfoCache object 患者個人情報のキャッシュ。プライマリシリーズの個人情報 personalInfo と同じものを保存する。データとしては冗長だが MongoDB で検索を高速に行うために存在している。
tags 🔗 string[] タグのリスト。利用可能な文字列は所属する Project の tags で指定される。

リビジョン Revision

あるケースを「保存」するたびに作成されていく逐次データのことを「リビジョン」と呼ぶ。一度作成したリビジョンはイミュータブルなものとして扱われ、通常のユーザ操作では削除・更新できない。個々のリビジョンはケース内の revisions 配列の要素として保管される。「リビジョンID」のような文字列は存在しないので、単にケース中の revisions のインデックス(整数)によって特定のリビジョンを指定する。

1つのリビジョンには少なくとも1つのシリーズが結びついている。特に series[0] のシリーズをプライマリシリーズと呼ぶ。

Revision:

field type description
creator string このリビジョンの作成者を示すメールアドレス。基本的には登録されているユーザのうちどれかのメールアドレスに対応しているが、外部からケースをインポートした場合にはシステムが知らないメールアドレスが入っていることがある(つまり Git のコミットメールアドレスのように動作する)。
description string 🔸 リビジョンを保存するときに指定可能な任意の文字列。Git のコミットメッセージのようなもの。
series 🔗 SeriesEntry[] ケースに所属するシリーズとそれに付随するラベル情報の一覧。
status string
attributes object ケースアトリビュートの実データ。その構造は所属するプロジェクトの caseAttributesSchema によって決定される。

SeriesEntry:

field type description
seriesUid 🔗 string シリーズUID。
images string シリーズ中で利用するイメージ番号。 multi-integer-range NPM パッケージによる正規化された整数レンジを使用する。例として 1-200, 1,3-5,9-15 のようになる。
labels Label[] 後述するラベルデータのリスト。

タグ Tag

タグとは、ケースに付随するラベル的な情報(ただし「ラベル」は CIRCUS DB では別のものを指すので混同しないこと)。ケースのメタ情報を保持するが、リビジョンで管理されない。リビジョン管理が必要な情報はケースアトリビュートとして処理するべき。典型的なタグは「興味深い症例」「要レビュー」「共有用データ」など。

ケース中に保持されるタグは単なる文字列であるが、そのケースで使用可能なタグの一覧は Project.tags で保持しており、これに合わないタグは登録することができない。

ケースアトリビュート Case Attribute

個々のケースに付随する任意の構造化情報であり、そのスキーマは自由に設定できる。スキーマはプロジェクトの caseAttributesSchema で管理し、実データは Series.revisions[n].attributes に保存される(つまりリビジョン管理の対象)。

ケースアトリビュートの例:

{ smoking: 'never', smokingIndex: 300, hypertension: true}

上記にケースアトリビュートに対応するスキーマの例:

[
	{ key: 'smoking', caption: '喫煙', type: 'select', spec: { options: ['never', 'current', 'ex'] } },
	{ key: 'smokingIndex', caption: '喫煙指数', type: 'number' },
	{ key: 'hypertension', caption: '高血圧', type: 'boolean' }
]

アトリビュートは、内部では @smikitky/rb-componentsPropertyEditor を使って実装する。

ラベル Label

ラベルとは ClinicalCase.revisions[n].series[m].labels に保存される情報であり、ケース内で特定のシリーズに付随するアノテーション情報を保持する。

「ラベル」と「タグ」を混同しないように注意! タグはリビジョン管理されず、 Case.tags 配下に保存される文字列のリストのこと。ラベルはケース内のリビジョン内のシリーズ内に保存され、すなわちリビジョン管理の対象となる、構造化されたデータのリストのこと。

現時点で実装されているラベルはボリューム情報のみ。

Label:

field type description
type string ラベルの種類。現時点では voxel 型のみ定義されている。
data object ラベルを表現するデータ本体。構造は type によって異なる。
attributes object ラベルアトリビュートの実データ。その構造は所属するプロジェクトの labelAttributesSchema によって決定される。

Label[type='voxel'].data:

field type description
voxels string ラベルのピクセル実データのハッシュ。下記参照。
origin [number, number, number] ボクセルラベルの原点のシリーズ内での座標。整数3つのタプル。
size [number, number, number] ボクセルラベルのx, y, z方向のサイズ(RawData.size)。整数3つのタプル。
color like #ffffff ボクセルラベルのカラー。
alpha number (<=1, >=0) ボクセルラベルの透明度。

voxels フィールドには、CIRCUS RSの RawData(type=BINARY) のピクセルデータを gzip 圧縮し、そのデータに対して SHA-1 をとったもの(16進文字列)を保管する。ピクセルデータ本体が変わらない場合は同じハッシュとなることが保証されるため、これにより何度も同じボクセルデータを保存してデータ領域が浪費されることを防ぐ(Git の SHA-1 ハッシュと同じ原理)。ボリュームデータ本体は別の API を使ってあらかじめ保存しておく。

ラベルデータの例:

{
    type: "voxel",
    data: {
        voxels: "5a616841a4fdd6066ee5c7e2d3118e0963ec1fc6",
        color: "#00ff00",
        alpha: 1,
        origin: [ 224, 183, 50 ],
        size: [ 64, 47, 17 ]
    },
    attributes: {
        fusiform: false,
        location: "A-com",
        laterality: "Right"
    }
}

ラベルアトリビュート Label Attribute

個々のラベルに付随する任意の構造化情報であり、そのスキーマは自由に設定できる。スキーマはプロジェクトの labelAttributesSchema で管理し、実データは Series.revisions[n].series[m].labels[k].attributes に保存される(つまりリビジョン管理の対象)。

構造はケースアトリビュートと全く同じ。ケース単位の情報なのかラベル単位の情報なのかの違い。

シリーズ Series

シリーズとはいわゆる DICOM 画像のシリーズのこと。CIRCUS DB では画像を DICOM シリーズベースで処理する。シリーズUID (Series Instance UID) は全世界でグローバルであるため、これをプライマリキーとして利用する。

シリーズは API 経由でインポートできるほか、常駐する C プログラムである "DICOM Image Server" の通信経由でもインポートされる。詳しくはシリーズのインポートを参照。

シリーズとして保存される情報の大半は DICOM 画像そのものに DICOM タグとして保管されている。

Series:

field type description
seriesUid 🔑 string シリーズインスタンスUID。グローバルに一意。
studyUid string このシリーズが所属する検査のスタディインスタンスUID。(0020,000d)
width number シリーズの1枚の画像の幅。
height number シリーズの1枚の画像の高さ。
seriesDate Date シリーズの作成時刻(DICOMに記載されているもの)。
modality string モダリティを表す2文字の文字列。 CT, PT など。
seriesDescription string シリーズ記述。T2_star axial など、シリーズに付いている人間が読むためのキャプション。
bodyPart string 撮像部位。 'HEAD', 'CHEST' など。
stationName string ステーション名。
modelName string モデル名。
manufacturer string 製造者。
storageId number シリーズの保管場所のID。 ❓
patientInfo PatientInfo 🔸 シリーズに付属する氏名などの個人情報データ。個人情報は CIRCUS DB にとってオプションのデータであり、まったく個人情報を含まない匿名化された DICOM ファイルを正しく扱うことができる。
parameters object CT における X 線線量や MRI におけるエコー時間といった、モダリティ固有の様々な撮像パラメータを保管しておくためのオブジェクト。プログラム的には静的データとしてそのまま送受信すればよい。
domain string このシリーズが所属するドメイン。

PatientInfo:

field type description
patientId string 🔸 施設における患者 ID。(0010,0020)
patientName string 🔸 患者の氏名。(0010,0010)
birthDate string 🔸 生年月日。 'YYYY-MM-DD' 形式の文字列。(0010,0030)
age number 🔸 患者の年齢(検査当時のもの)。DICOM規約では '3M'(月齢3か月)のような表現もできるが、満年齢を表す整数で統一して格納する。
sex string 🔸 患者の性別。'M', 'F', 'O' のいずれか。(0010,0040)
size number 🔸 患者の身長。 (0010,1020)
weight number 🔸 患者の体重。(0010,1030)

ドメイン Domain

ドメインとは、セキュリティ確保目的で使用する、シリーズの「由来」「出所」を表すための文字列。ユーザがシリーズ情報にアクセスする際には、そのシリーズに対するドメインレベルでのアクセス情報があるかを確認する必要がある。

CIRCUS DBではシリーズUID自体は個人情報ではないと見なす。

ユーザ User

いわゆるログインアカウントのこと。個々のユーザのレベルでは何らの権限情報も保持しない。ユーザは複数のグループに所属することができ、そのレベルで CIRCUS 内の様々な行動への権限が付与される。

あまり意味はないが、どのグループにも所属しないユーザを作成することは可能(その場合はログインしてトップページを表示できること以外に何の権限も持たないユーザということになる)。

field type description
userEmail 🔑 string ユーザのEメール。グローバルに一意であることが期待される。
loginId 🔑 string ユーザ名。 userEmail へのエイリアスとして使用できる短い英数字の文字列。このインストール中では一意である必要があるが、グローバルに一意である必要はない。ユーザのログイン操作の時に使用するが、外部キーとして参照する目的で使用してはいけない
password string パスワードのハッシュ。
groups 🔗 string[] このユーザが所属しているグループ。とあるユーザが持っている最終的な権限は、所属しているグループが持っている権限の和集合となる。
lastLoginTime Date 最終ログイン時刻。
lastLoginIP string 最終ログインIPアドレス。
description string 🔸 ユーザのフルネームや組織内での所属など、管理者用の任意の文字列。
preferences Preferences ユーザのプレファレンス。
loginEnabled boolean false にするとユーザのログインを一時的に無効にできる。

プレファレンス Preference

ユーザ毎に保存されるプレファレンスデータ。基本的にGUI側で使う情報なので、そのまま保存すればよい。

Preferences:

field type description
theme 'mode_black' | 'mode_white' カラーテーマとなる文字列。
personInfoView boolean 個人情報を表示するかどうか。 false の場合は(仮に権限があっても)個人情報を非表示にできる。

グループ Group

ユーザが所属するグループ。あるユーザは複数のグループ(0個でもよい)に同時に所属することができ、所属しているグループ経由で与えられる権限の和集合が、ユーザが保持している最終的な権限セットとなる。

field type description
gruopId 🔑 number グループID。グループを作成する際に内部的に降られる連番。ユーザからは見えない。あくまで CIRCUS DB のインストレーション毎に一意である(グローバルに一意ではない)。
groupName (🔑) string グループ名。任意の英数字。
privileges 🔗 string[] このグループに所属しているユーザに付与されるグローバルな権限のリスト。グローバル権限文字列の組み合わせでなければならない。
readProjects 🔗 string[] このグループに所属しているユーザが参照可能なプロジェクト ID のリスト。
writeProjects 🔗 string[] このグループに所属しているユーザがラベルやアトリビュートの編集をできるプロジェクト ID のリスト。
addSeriesProjects 🔗 string[] このグループに所属しているユーザがシリーズの追加やケースの作成をできるプロジェクト ID のリスト。
viewPersonalInfoProjects 🔗 string[] このグループに所属しているユーザが個人情報を参照できるプロジェクト ID のリスト。
moderateProjects 🔗 string[] このグループに所属しているユーザが管理者としてあらゆる操作を行えるプロジェクト ID のリスト。
domains 🔗 string[] このグループに所属しているユーザがアクセス可能になるドメインのリスト。

なお、この privileges として指定されるのは、特定のプロジェクトに結びつかないグローバルな権限のみである。個々のプロジェクトに結びついた書き込み・読み込みなどの権限は、 Project 側の readGrouops などの権限フィールドによって指定される。

メモ

以下は現行CIRCUS DBから変更する。

  • グループ権限を