Newer
Older
TIASDataHub / docs / 04_SPEC / SPEC_01_アーキテクチャ設計.md

アーキテクチャ設計 (Architecture)

基本方針 (Principles)

  1. 置き場所をコードに書かない: 目録・データ置き場・取り込み元・計算サーバの場所は,研究室 PC の設定ファイルに書く.使う側はデータセット名と版で指定する
  2. 登録したファイルは変えない: 取り込むときに管理用の置き場(ストア)へコピーし,ファイル名を中身の SHA-256 にする.同じ名前のファイルは常に同じ中身であり,過去の版を確実に再現できる
  3. 版は凍結する: データセットの版は作った時点の構成(ファイルとラベル)を記録し,以後変更しない.データやラベルを足しても過去の版の中身は変わらない
  4. 由来を必ず記録する: 派生データは,元データ・プログラム名・プログラムの版とひも付けて登録する
  5. 個人情報を出さない: 実際の患者 ID は目録に入れない(研究用 ID だけを使う).CLI の出力・ログ・エラーメッセージは集計値と研究用 ID に限る(SPEC_03「出力の規則」)
  6. 拡張は行の追加で行う: 所見の種類・ファイルの種類の追加は,種類の定義(表の行と検証用の型)の追加で済ませ,表の構造を作り直さない(SPEC_02)

構成要素 (Components)

研究室 PC(原本・目録)                         計算サーバ(Newton・Archimedes)
┌──────────────────────────────┐               ┌──────────────────────────────┐
│ 取り込み元(原本.読むだけ)   │               │ ~/data/tiasdata/<名前>/v<版>/  │
│   clinical-data/TIASJudgeModel │               │   manifest.csv・dataset.json   │
│        │ tiasdata import       │               │   files/<sha256>.<拡張子>      │
│        ▼                       │  tiasdata     │        ▲                       │
│ 目録 catalog.sqlite            │  deliver      │        │ tiasdata.load()      │
│ ストア store/<sha256>          │ ────────────▶ │ 使う側(TIASJudgeModel 等)    │
│ バンドル bundles/<名前>/v<版>/ │  (直送)     └──────────────────────────────┘
└──────────────────────────────┘
        ▲ ssh labpc "tiasdata ..."(手元 PC から操作.ENV_02)
要素役割
目録(catalog.sqlite)症例・撮影・ファイル・ラベル・由来・データセットの版・受け渡しの記録(SPEC_02)
ストア(store/)登録したファイルの実体.中身の SHA-256 をファイル名にし,変更しない(下記「ストアの規則」)
対応表(identity.sqlite)実際の患者 ID ↔ 研究用 ID.目録とは別のファイル・別のフォルダに置く.現在の舌色データは対応表の xlsx から作る
バンドルデータセットの 1 つの版を,manifest とファイルのコピーにまとめたもの.計算サーバ・Python 以外のツールへ渡す単位(SPEC_03)
ライブラリ(tiasdata)目録の操作(研究室 PC)と,バンドルの読み込み・検証(どこでも)
CLI(tiasdata)取り込み・データセットの版の作成・バンドルの書き出し・受け渡し・点検(研究室 PC)
データセットの定義(datasets/*.toml)どのファイル・ラベルを集めるかの条件.個人情報を含まないのでリポジトリで管理し,PR で変更する

ストアの規則 (Store Rules)

src/tiasdata/store.py が担う(2026-10-06 実装).

  • 置き場所は store/<SHA-256 の先頭 2 文字>/<SHA-256>.<拡張子(小文字)>.目録には保存せず,SHA-256 と拡張子から決める
  • 取り込みは「一時ファイル(.tmp- で始まる名前)へハッシュを計算しながらコピー → 読み直して照合 → 正式な名前に変える」の順で行い,書きかけのファイルを正式な名前で残さない.失敗したら一時ファイルを消す
  • 同じ中身が既にあればコピーしない.同じ置き場所に中身の違うファイルがあれば上書きせずに停止する
  • 原本(取り込み元)は読むだけで,中身・更新日時・属性を変えない
  • ストアに置いたファイルは読み取り専用にする(手作業・他のプログラムによる誤った書き換え・削除を防ぐため.2026-10-06 のユーザー判断).同じ中身を再び取り込んで既存のファイルを再利用するときも付け直す.属性が外れたファイルは tiasdata check が数を報告する.バックアップや手での削除では,この属性を意識する
  • ファイルを直したい・使わないようにしたい場合も,ストアのファイルは書き換えない.直したファイルは新しいファイルとして由来付きで登録し,ラベルは所見の訂正で,除外はデータセットの定義と新しい版で行う.データを本当に消す必要がある場合(同意の撤回等)は,専用のコマンドで影響する版を確かめ,記録を残してから消す(未実装.PLAN_02「マイルストーン 2 以降の候補」)
  • store フォルダが無いときは作らずに停止する(tiasdata init で作る.設定の誤りで別の場所にストアが黙って作られるのを防ぐため)
  • エラーメッセージにはパス・元のファイル名・拡張子を出さず,SHA-256 で示す

配置 (Locations)

リポジトリ (Repository)

TIASDataHub/
├── src/tiasdata/
│   ├── config.py          # 設定ファイルの読み込み・検証(pydantic)
│   ├── catalog/           # 目録(SQLite)の接続・マイグレーション・各表の操作
│   │   └── migrations/    # スキーマ変更の SQL(catalog/・identity/ の 2 系列.NNNN_<内容>.sql)
│   ├── store.py           # ストア(ハッシュの計算・コピー・検証)
│   ├── kinds/             # ファイルの種類・所見の種類の定義(値の検証用の型)
│   ├── importers/         # 取り込み元ごとの読み取り(例: 舌色の 9 フォルダ)
│   ├── manifest.py        # manifest.csv の生成(純関数.catalog に依存しない)
│   ├── repo.py            # リポジトリのルートと git の状態
│   ├── datasets.py        # データセットの定義の評価・版の作成
│   ├── bundle.py          # バンドルの書き出し・読み込み・検証
│   ├── deliver.py         # 計算サーバへの受け渡し
│   └── cli.py             # エントリポイント
├── datasets/              # データセットの定義(TOML)
├── holds/                 # 取り込み元ごとの保留リスト(TOML.SPEC_03「保留リスト」)
├── tests/                 # ダミーデータのみで動くテスト
└── docs/

マイグレーションの SQL はリポジトリ直下ではなくパッケージの中(src/tiasdata/catalog/migrations/)に置き,importlib.resources で読む(サブモジュール・パッケージとして使われたときも見つけられるようにするため.2026-10-06 の判断).

依存の向きは cli → datasets・bundle・deliver・importers → catalog・store・kinds・config とする.bundle の読み込み側は catalog に依存しない(目録の無い計算サーバで使うため).

研究室 PC (Lab PC)

E:\clinical-data\
├── TIASJudgeModel\            # 取り込み元(原本.基盤は読むだけで変更しない)
├── TongueSegmentation\        # 取り込み元(原本)
├── DeepTIAS_TIASJudgeModel\   # 取り込み元(舌色データセットの DeepTIAS 出力.番号ごと)
├── DeepTIAS後_ID_番号.xlsx    # 画像の番号 → 患者 ID・何枚目の対応表(取り込みで読む)
├── tiasdata\                  # 基盤のデータ(catalog.root)
│   ├── catalog.sqlite         # 目録
│   ├── store\                 # ストア(store\<先頭 2 文字>\<sha256>.<拡張子>)
│   ├── bundles\               # 書き出したバンドル(受け渡し後は削除してよい.再生成できる)
│   └── backups\               # 目録のバックアップ
└── tiasdata-identity\         # 対応表(identity.sqlite).目録とは別のフォルダ
  • 研究室 PC の内蔵 SSD の E ドライブ(約 465GB.OneDrive の同期対象外)に置く.2026-10-06 に C:\Users\Papin\clinical-data\ から移した(docs/PROGRESS.md)
  • E ドライブは BitLocker で暗号化していない(C ドライブも同じ).倫理審査の保管ルールで暗号化が必要なら,管理者権限で有効にする(人間の作業)
  • .claude/repo-access.json の deny_read に E:/clinical-data が入っているため,上記はすべて Claude の読み取り禁止の対象になる

設定ファイル (Configuration)

研究室 PC のユーザー領域に置き(リポジトリには入れない),pydantic で検証する(未知のキーは拒否する).

  • 場所: 環境変数 TIASDATA_CONFIG があればそのパス,無ければ %USERPROFILE%\.config\tiasdata\config.toml(Linux では ~/.config/tiasdata/config.toml)
  • 相対パスは設定ファイルのあるフォルダを基準にする.~ を展開する(servers.*.root はサーバ側のパスなので展開しない)
  • catalog.identity(対応表)は catalog.root の外に置く.中にある設定は検証エラーにする(対応表を目録とは別のフォルダに分けるため)
  • catalog.root の下の catalog.sqlite・store/・bundles/・backups/ は固定の名前で,設定には書かない
[catalog]
root = "E:/clinical-data/tiasdata"                     # catalog.sqlite・store/・bundles/・backups/
identity = "E:/clinical-data/tiasdata-identity/identity.sqlite"

[sources.tiasjudgemodel]                                            # 取り込み元(名前で指定する)
path = "E:/clinical-data/TIASJudgeModel"
importer = "tongue_color_folders"
patient_map = "E:/clinical-data/DeepTIAS後_ID_番号.xlsx"  # 画像の番号 → 患者 ID・何枚目(患者 ID は identity.sqlite にだけ入れる)

[servers.newton]                                                    # 受け渡し先
host = "hasegawa@192.168.23.14"
key = "C:/Users/Papin/.ssh/id_ed25519_newton"
root = "~/data/tiasdata"

[servers.archimedes]
host = "hasegawa@192.168.23.15"
key = "C:/Users/Papin/.ssh/id_ed25519_newton"
root = "~/data/tiasdata"
  • CLI はパスを引数に取らず,取り込み元・受け渡し先を名前で指定する(SSH 経由のコマンドにデータのパスが現れないようにするため.ENV_02「研究室 PC の操作方針」)
  • テストは一時ディレクトリに設定ファイル・目録・ストアを作り,TIASDATA_CONFIG で指す

使う側からの利用 (Consumer Usage)

場所使い方
計算サーバ(Python)tiasdata.load("tongue_color", version=1) がバンドルを開く.バンドルの置き場所は環境変数 TIASDATA_BUNDLES(既定 ~/data/tiasdata)の下の <名前>/v<版>/
Python 以外(DeepTIAS 等)バンドルの manifest.csv と files/ を読む
研究室 PC(Python)tiasdata.Catalog.open() で目録を直接開ける(通常は CLI を使う)
  • 使う側の実験記録には,バンドルの指紋(データセット名・版・manifest.csv の SHA-256)を残す(Bundle.fingerprint).これにより「どの実験がどの時点のデータ集合を使ったか」を辿れる
  • 版を省略した load("tongue_color") は許さない(暗黙に最新を使うと再現性が崩れるため)