最終更新: a few seconds ago Remove Netlify-related code from main (grafted, HEAD)
CIRCUS DB データ構造
CIRCUS DB の基本的なデータ構造と各種キーの意味について解説する。用語はトップダウン的に並んでいるので、新規の用語の意味については後の方を参照。
凡例
- 🔑: Primary key、ないし Primary key 的に扱う必要があるもの。兄弟間で一意である必要があるもの。API 実装において、プログラム的に一意であることを保証する必要がある。
- (🔑): 通常は兄弟間で一意であることが期待されるが、プログラム的にそれを強制する必要がないということを明示的に示す。逆に言えば、これでマークされている値は必ずしも一意ではないため、プログラム上でキーとして利用してはいけない。
- 🔗: 外部の何らかのキー 🔑 への参照となっているもの。API 実装において、データ作成・更新時に整合性の確認が必要なもの。
- 🔸: データの意味あいとして省略可能な文字列。リソース作成時にこのデータが空文字列でも受け付ける。ただし API からリソースを返す場合には、これらは空文字列として返すこと。
下記で「グローバルに一意」とは、GUID のように世界中で一意となる、十分に長い識別子のことを表す。
基本的なデータ概念図
プロジェクト 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 としてはインストレーション間で共有できるようなスキーマ系情報を主に記載することにする。
| field | type | description |
|---|---|---|
| caption 🔑 | string | タグ名。 |
| color | like #ffffff |
タグ背景色。 |
| field | type | description |
|---|---|---|
| key 🔑 | string | キー。通常は英数字。 |
| caption (🔑) | string | 表示用キャプションとなる任意の文字列。 |
| type | 'text' | 'number' | 'boolean' | 'select' |
このキーに対応する値の型。 |
| spec | object | 様々な付帯情報(選択肢など)。ソースコード参照。 |
| 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] のシリーズをプライマリシリーズと呼ぶ。
| field | type | description |
|---|---|---|
| creator | string | このリビジョンの作成者を示すメールアドレス。基本的には登録されているユーザのうちどれかのメールアドレスに対応しているが、外部からケースをインポートした場合にはシステムが知らないメールアドレスが入っていることがある(つまり Git のコミットメールアドレスのように動作する)。 |
| description | string | 🔸 リビジョンを保存するときに指定可能な任意の文字列。Git のコミットメッセージのようなもの。 |
| series 🔗 | SeriesEntry[] | ケースに所属するシリーズとそれに付随するラベル情報の一覧。 |
| status | string | |
| attributes | object | ケースアトリビュートの実データ。その構造は所属するプロジェクトの caseAttributesSchema によって決定される。 |
| 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-components の PropertyEditor を使って実装する。
ラベル Label
ラベルとは ClinicalCase.revisions[n].series[m].labels に保存される情報であり、ケース内で特定のシリーズに付随するアノテーション情報を保持する。
「ラベル」と「タグ」を混同しないように注意! タグはリビジョン管理されず、 Case.tags 配下に保存される文字列のリストのこと。ラベルはケース内のリビジョン内のシリーズ内に保存され、すなわちリビジョン管理の対象となる、構造化されたデータのリストのこと。
現時点で実装されているラベルはボリューム情報のみ。
| 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 | このシリーズが所属するドメイン。 |
| 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側で使う情報なので、そのまま保存すればよい。
| 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から変更する。
- グループ権限を