diff --git a/CLAUDE.md b/CLAUDE.md index 3d2fada..e439f57 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,6 +71,8 @@ ### 02_ENV(環境) +- 技術スタック: docs/02_ENV/ENV_01_技術スタック.md + ### 03_PLAN(計画) diff --git "a/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" "b/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" new file mode 100644 index 0000000..78fcebc --- /dev/null +++ "b/docs/02_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.md" @@ -0,0 +1,67 @@ +# 技術スタック (Tech Stack) + +## 概要 (Overview) + +研究室 PC(Windows)に置いた**目録(SQLite の DB ファイル 1 つ)**と**データ置き場(画像等のファイル)**を,Python のライブラリと CLI で操作する.使う側の Python プロジェクトはライブラリを import し,Python 以外や計算サーバには CLI が書き出した manifest(CSV)を渡す.手元 PC では臨床データの代わりにダミーデータで同じコードを動かす. + +使う側(TIASJudgeModel・TIASjudge)と同じ言語・ツールにそろえ,サブモジュールとして編集可能な形で読み込んだときに依存がぶつからないようにする. + +## 言語・実行環境 (Language & Runtime) + +| 項目 | 採用 | 備考 | +| --- | --- | --- | +| 言語 | Python | 使う側(TIASJudgeModel・TIASjudge)と同じ | +| Python バージョン | 3.12(`.python-version` で固定) | 使う側と同じ.`requires-python = ">=3.12"` | +| パッケージマネージャ | **uv** | 使う側と同じ.`uv.lock` をコミットする | +| パッケージ名 | `tiasdata`(`src/tiasdata/`) | 使う側は `tiasdata = { path = "external/TIASDataHub", editable = true }` で読み込む | +| 手元 OS | Windows 11 | 開発・ダミーデータでのテストのみ | +| 運用環境 | 研究室 PC(Windows) | 目録とデータ置き場を置き,CLI を実行する | + +## 目録とデータ置き場 (Catalog & Storage) + +| 項目 | 採用 | 備考 | +| --- | --- | --- | +| 目録 | **SQLite**(Python 標準の `sqlite3`) | サーバを立てずに DB ファイル 1 つで済む.1 人で使うため同時書き込みの心配がない.C#(DeepTIAS)からも `Microsoft.Data.Sqlite` で読める | +| DB へのアクセス | 標準の `sqlite3` で SQL を直接書く(ORM は使わない) | テーブル数が少なく,SQL がそのまま仕様として読める.依存を増やさない | +| スキーマの変更 | 連番の SQL ファイル(`migrations/0001_*.sql` …)を順に適用し,適用済みの版を DB の `PRAGMA user_version` に記録する | データの種類を足すたびに表・列が増えるため,変更履歴をファイルで残す.Alembic 等は 1 ファイルの SQLite には過大 | +| データ本体 | **ファイルのまま**データ置き場に置き,目録にはデータ置き場からの相対パスを記録する | 画像を DB に入れない(DB が肥大化し,サーバへのコピーや他ツールからの参照がしにくくなる) | +| 同一性の確認 | ファイルの **SHA-256**(標準の `hashlib`) | データセットの版にハッシュを含め,ファイルが差し替わったことを検出する.再現性の根拠にする | +| 置き場所の設定 | 設定ファイル(TOML.標準の `tomllib` で読む)または環境変数で,DB ファイルとデータ置き場のパスを指定する | コードにパスを書かない.設定ファイルはリポジトリの外(研究室 PC のユーザー領域)に置く.具体的なキー・既定の場所は仕様設計で決める | + +## ライブラリ・CLI (Library & CLI) + +| 項目 | 採用 | 備考 | +| --- | --- | --- | +| 設定・入出力の検証 | **pydantic** | 使う側(TIASJudgeModel)と同じ流儀.設定ファイル・manifest の行・登録時の入力を検証する | +| CLI | 標準の `argparse`(エントリポイントは `pyproject.toml` の `[project.scripts]`) | サブコマンド数が少ない.依存を増やさない | +| manifest | CSV(標準の `csv`)+版の情報を書いた JSON | TIASJudgeModel の現行 manifest(`image_path`・`patient_id`・`label`・`severity`・`note`)と互換にできる形にする.列の詳細は仕様設計で決める | +| 画像の読み込み | 使わない(基盤は画像の中身を読まない) | 画素を扱うのは使う側.ダミーデータの生成だけ Pillow を開発用の依存に入れる | + +- 実行時の依存は **pydantic だけ**にする(使う側の依存と衝突しにくくするため) + +## 開発ツール (Development Tools) + +| 項目 | 採用 | 備考 | +| --- | --- | --- | +| テスト | pytest | ダミーデータ(テスト内で一時ディレクトリに作る DB とファイル)で動くテストのみ.臨床データに依存するテストは書かない | +| lint / format | ruff | 使う側と同じ | +| CI | **使わない** | 1 人開発でローカル実行で足りる.必要になれば GitHub Actions を追加する | +| 依存更新 | Dependabot(`uv`・`github-actions` エコシステム) | 週 1 回.CI が無いので更新 PR はローカル検証で確認する | + +## 採用しなかった選択肢 (Rejected Alternatives) + +| 候補 | 却下理由 | +| --- | --- | +| PostgreSQL 等の DB サーバ | 1 人で使う規模に対し,研究室 PC でサービスを常駐・保守する負担が大きい | +| DB を使わず CSV・YAML だけで目録を持つ | 症例 → 撮影 → ラベル・派生データの関係と,データセットの版をファイルの組み合わせで整合させるのが難しい.重複・参照切れを DB の制約で防げない | +| 画像を DB に格納(BLOB) | DB ファイルが巨大になり,計算サーバへのコピー・DeepTIAS 等のファイル前提のツールからの参照がしにくい | +| SQLAlchemy + Alembic | テーブル数が少なく 1 ファイルの SQLite には過大.使う側に余計な依存を持ち込む | +| DVC・git-annex 等のデータのバージョン管理ツール | データ本体をリポジトリの管理下(キャッシュ・リモート)に置く仕組みで,「データをリポジトリに入れない」方針と相性が悪い.必要なのは「どのファイルの集合か」の記録で,目録の版とハッシュで足りる | +| typer・click | `argparse` で足りる規模.依存を増やさない | + +## 未確定事項 (Open Items) + +- 研究室 PC に uv・Python 3.12 が入っているか(環境構築フェーズで確認する) +- 設定ファイルの置き場所・キー,DB ファイルとデータ置き場の具体的なパス(仕様設計・環境構築フェーズで決める.OneDrive の同期対象外に置く) +- DB ファイルのバックアップ方法(環境構築フェーズで決める) +- DeepTIAS(C#)が目録を直接読むか,manifest だけを読むか(仕様設計フェーズで決める.当面は manifest)