Newer
Older
TIASDataHub / docs / 04_SPEC / SPEC_03_データセットと受け渡し.md

データセットと受け渡し (Datasets & Delivery)

データセットの定義・版の作成・バンドル(manifest +ファイル)の書き出し・計算サーバへの受け渡し・CLI・出力の規則を定める.表の定義は SPEC_02.

データセットの定義 (Dataset Definition)

datasets/<名前>.toml に置く(リポジトリで管理し,PR で変更する).

name = "tongue_color"
description = "舌色 5 分類+程度(TIASJudgeModel の学習データ)"

[select]
asset_kind = "tongue_crop_masked"      # 集めるファイルの種類
require = ["tongue_color"]             # この所見を持つものだけ(撮影に付いた所見を含む)

[columns]                              # manifest に出す所見の列
tongue_color = ["label", "severity"]
  • 条件は「ファイルの種類」と「必須の所見」から始め,必要になったら所見の値による絞り込み等を足す
  • 1 つのファイル・撮影に同じ種類の有効な所見(訂正されていないもの)が 2 つ以上ある場合は,版の作成を止める(どちらを使うかを黙って決めない)

版の作成 (Creating a Version)

tiasdata dataset freeze <名前> で,その時点の目録に定義を当てはめて新しい版を作る.

  1. 定義を検証し,条件に合うファイルと採用する所見を集める
  2. 直前の版と構成(ファイルと所見)が同じなら,版を作らずにその旨を表示する
  3. 構成・定義の内容・本リポジトリのコミット・manifest.csv の SHA-256 を記録する(以後変更しない)
  • 本リポジトリに未コミットの変更がある状態では版を作らない(定義とコードの版を記録できなくなるため)
  • 行の順序は subject_id・capture_id・sha256 の順に並べる(同じ構成なら同じ manifest.csv になるようにする)
  • 未コミットの変更の確認は,目録を見る前に行う(git status --porcelain --untracked-files=all が空でなければ停止).hub_commit は git rev-parse HEAD
  • 構成の比較: 定義の全文が同じで,かつ採用したファイルと所見(所見の行の ID)の組が同じなら版を作らない.そのため,同じ値への訂正でも所見の行が変わるので新しい版になる(manifest の SHA-256 は直前の版と同じになる).定義は説明だけの変更でも新しい版になる
  • 条件に合うファイルのうち撮影にひも付かないもの(subject_id・capture_id を決められない.例: 患者が確定していない要確認のファイル)は除き,「撮影にひも付かないため除いた」件数を報告する(2026-10-08 に「停止」から変更).除いた結果 0 件なら停止する
  • 要確認の印(所見 review)の付いた撮影も版に入れる(除く条件は必要になったら足す)
  • 所見の列は定義の [columns] に書いた順に並べる.値は文字列ならそのまま,無ければ空,それ以外は JSON の表記
  • 定義の description は必須.目録の datasets.description は最初の版のときの値のままにする(版ごとの定義の全文は dataset_versions.definition に残る)
  • 種類との照合(定義の種類・項目が kinds と値の型にあるか)は版を作るときだけ行う.過去の版の manifest の作り直しには使わない(種類の定義が後で変わっても作り直せるようにするため)
  • 版の備考(--note)は dataset show で表示する.備考に患者 ID 等の個人情報を書かない

バンドル (Bundle)

データセットの 1 つの版を,計算サーバ・Python 以外のツールに渡す形にまとめたもの.

<名前>/v<版>/
├── dataset.json          # 名前・版・作成日時・hub_commit・件数・manifest.csv の SHA-256
├── manifest.csv          # 1 行 1 ファイル
├── SHA256SUMS            # files/ の照合用(sha256sum -c で検証できる形式)
└── files/<sha256>.<ext>  # ストアからのコピー
  • dataset.json の項目: format(形式の版.今は 1.読み込み側は知らない形式を拒否し,未知のキーは無視する)・name・version・created_at(版を作った日時)・hub_commit・files(件数)・manifest_sha256.書き出した日時は入れない(同じ版から常に同じバイト列にし,既存のバンドルをバイト単位で照合できるようにするため)
  • SHA256SUMS の 1 行は <sha256> files/<sha256>.<ext>(空白 2 つ・LF・パスの順)
  • バンドルのファイルは読み取り専用にしない(作り直せて,受け渡した後に消す前提のため.2026-10-08 のユーザー判断).改変は verify() と書き出し直しの照合で見つける

書き出し (Export)

tiasdata export <名前> --version <版>(src/tiasdata/export.py).

  1. 版の記録から manifest を作り直し,記録した SHA-256 と一致しなければ停止する(目録が書き換えられた版を書き出さない)
  2. bundles/<名前>/.tmp-v<版>-…/ に files/(ストアからコピーし,読み直して照合)・manifest.csv・SHA256SUMS・dataset.json を書き,開き直して形を確かめてから v<版> に名前を変える(書きかけを正式な名前で残さない.失敗したら一時フォルダを消す)
  3. 既に v<版> があれば,dataset.json・manifest.csv・SHA256SUMS を版の記録から作ったものとバイト比較し,verify() を通して使う.食い違えば上書きせずに停止する(消して書き出し直すのは人間の作業)

manifest.csv の列

列内容
pathバンドルのルートからの相対パス(files/<sha256>.<ext>.区切りは /)
sha256ファイルの SHA-256
kindファイルの種類
subject_id研究用の症例 ID(分割の単位にする)
capture_id撮影 ID
<所見>.<項目>定義の [columns] で指定した所見の値(例: tongue_color.label・tongue_color.severity)
  • 文字コードは UTF-8(BOM なし),改行は LF
  • 実際の患者 ID・元のファイル名は出さない

TIASJudgeModel との互換 (Compatibility)

TIASJudgeModel の manifest(image_path・patient_id・label・severity・note)は,次の対応で同じ情報を持つ.

TIASJudgeModel本基盤
image_pathpath
patient_idsubject_id
labeltongue_color.label
severitytongue_color.severity
  • TIASJudgeModel 側は tiasdata.load() でバンドルを読み,自分の manifest の形に変換して使う(変換は TIASJudgeModel 側の実装).基盤側は使う側ごとの形式を持たない
  • subject_id は患者単位である.TIASJudgeModel の現行の patient_id は画像 ID(「1 患者 1 枚」という誤った前提)のため,切り替えると分割が患者単位に変わり,交差検証の成績が変わりうる(同じ患者の画像が学習と評価に分かれなくなる)

計算サーバへの受け渡し (Delivery)

tiasdata deliver <名前> --version <版> --to <サーバ名> を研究室 PC で実行する(手元 PC からは ssh labpc 経由.データは手元 PC を通らない).

  1. バンドルを書き出す(bundles/<名前>/v<版>/.既にあれば中身を照合して使う)
  2. tar にまとめ,設定ファイルの鍵で scp する
  3. サーバで <root>/<名前>/v<版>/ に展開し,chmod -R u+rwX,go-rwx で自分だけに絞る(Windows で作った tar は tar --delay-directory-restore -xf で展開する.TIASJudgeModel の ENV_03 の実測)
  4. サーバで sha256sum -c SHA256SUMS を実行して照合する(サーバに tiasdata が無くても検証できる)
  5. tar ファイルを両側で削除し,deliveries に記録する
  • 受け渡し先に同じ版が既にあれば,照合だけ行って記録する(上書きしない)
  • 版は凍結されているため,一度渡した版の中身が変わることはない.新しいデータは新しい版として渡す

ライブラリの API (Library API)

import tiasdata

bundle = tiasdata.load("tongue_color", version=1)   # TIASDATA_BUNDLES/<名前>/v<版>/ を開く
bundle.verify()                                     # ハッシュを照合する(任意.時間がかかる)
for row in bundle.rows:                             # manifest の行(pydantic の型)
    row.path, row.subject_id, row.annotations["tongue_color"]["label"]
bundle.fingerprint                                  # {"name", "version", "manifest_sha256"}.実験記録に残す
  • load(name, *, version): 版の指定はキーワードで必須(load("tongue_color", 1) は誤り).置き場所は環境変数 TIASDATA_BUNDLES,無ければ ~/data/tiasdata.dataset.json の名前・版が指定と違えば停止する
  • bundle.rows は BundleRow(path・sha256・kind・subject_id・capture_id・annotations)の並び.annotations は manifest の列 <所見>.<項目> を所見ごとにまとめたもので,値は文字列か None(空欄).文字列以外の型には戻さない
  • bundle.file_path(row) が画像等の絶対パスを返す.bundle.info(BundleInfo)・bundle.root・bundle.name・bundle.version・bundle.manifest_sha256 も使える
  • bundle.verify() は問題が無ければ None を返し,欠け・改変・files/ の余分・SHA256SUMS と manifest の食い違い・開いた後の manifest.csv の書き換えを ValueError で知らせる
  • 読み込み側(tiasdata.bundle)は標準ライブラリ・pydantic・tiasdata.manifest だけを使い,目録(catalog・store・config)を読み込まない.import tiasdata で読み込まれるのは tiasdata・tiasdata.bundle・tiasdata.manifest だけ
  • エラーメッセージにバンドルの場所(パス)を出さない(研究室 PC・計算サーバの出力も Claude が読むため.名前・版・<名前>/v<版>/ の形・環境変数名で示す)
  • tiasdata.open_bundle(path) でパスを直接指定して開くこともできる(テスト・Python 以外との突き合わせ用)
  • 読み込み時に manifest.csv の SHA-256 が dataset.json と一致しなければ停止する

CLI (Commands)

研究室 PC で使う.パスは引数に取らず,名前で指定する(SPEC_01「設定ファイル」).

コマンド役割
tiasdata init設定ファイルに従って目録・ストアを作り,マイグレーションを適用する
tiasdata import <取り込み元>取り込み元を読み,ファイルをストアにコピーして症例・撮影・ファイル・所見・由来を登録する(取り込み元の形ごとに importer を用意する.最初は舌色の 9 フォルダ tongue_color_folders).要確認リストの番号も印を付けて登録する(下記「要確認リスト」)
tiasdata dataset list / show <名前>データセットと版の一覧・件数.定義だけあって版の無いものは「版なし」,定義ファイルを消したものは「(定義ファイルなし)」.show は版ごとの件数・作成日時・hub_commit・manifest の SHA-256・備考
tiasdata dataset freeze <名前> [--note TEXT]新しい版を作る(作った版の番号と件数,または「構成・定義が同じなので版を作らなかった」)
tiasdata export <名前> --version <版>バンドルを bundles/ に書き出す(上記「書き出し」).書き出した件数・合計の大きさ・manifest の SHA-256,または「既にあったバンドルを照合して使った」を表示する
tiasdata deliver <名前> --version <版> --to <サーバ名>計算サーバへ渡す
tiasdata check点検: ストアのファイルのハッシュの照合,目録にあってストアに無いファイル・その逆,所見の参照切れ,凍結した版の構成の欠け,凍結した版の manifest の不一致(全版について記録した定義と構成から manifest を作り直し,記録した SHA-256 と照合する.ファイルの種類や撮影の症例が書き換えられた場合に見つかる),読み取り専用が外れたストアのファイル,書きかけの一時ファイル(.tmp-),ストアの想定外のファイル・フォルダ.件数だけを表示し,問題が 1 件以上なら終了コード 1.撮影にひも付かないファイルは件数を表示するが問題として数えない.対応表は開かない
tiasdata stats症例数(撮影が 2 つ以上の症例数を含む)・撮影数,種類ごとのファイル数,訂正されていない所見の項目ごと・組み合わせごとの件数,訂正された所見の数,撮影にひも付かないファイルの数,要確認の印の数(撮影に付いたもの・ファイルに付いたもの.値ごとの内訳は出さない).対応表は開かない
tiasdata backup目録を <catalog.root>/backups/catalog-<UTC の YYYYmmddTHHMMSSZ>.sqlite に,対応表を対応表のフォルダの backups/identity-<同じ日時>.sqlite に複製する(SQLite のバックアップ API.対応表を目録のフォルダに置かないため).複製に integrity_check をかけてスキーマの版が最新か確かめ,件数を表示する(パスは出さない).同じ名前があれば何も書かずに停止し,上書きしない(一時ファイル → 点検 → 正式な名前).同じドライブの中の複製なので,ドライブの故障には別の媒体への退避が要る(PLAN_02「バックアップ」)
  • 取り込みは何度実行しても同じ結果になるようにする(既に登録済みのファイルは飛ばす)
  • 登録・版の作成は 1 つのトランザクションで行い,途中で失敗したら目録・対応表に何も残さない(取り込みでは対応表を目録の接続に ATTACH して 1 つのトランザクションにする).ストアへのコピーはトランザクションの外なので,失敗時にコピー済みのファイルはストアに残る.これは次に取り込みが成功するまで check が「ストアにあって目録に無いファイル」として報告し,次の取り込みで再利用される
  • 取り込みは,書き込む前に取り込み元の構成・要確認リスト・対応表・同じ中身の画像が複数の番号に無いか(あれば,すべて要確認リストにあるか)をすべて検証する
  • import の出力: 取り込み元の画像の件数,要確認リストの番号の数,対応表で使わない行の件数,登録済みで飛ばした件数,登録した件数(症例・撮影・ファイル・所見・由来),要確認として登録した件数(うち撮影にひも付けないファイル・番号の数),既存の撮影・ファイルに要確認の印を足した件数,要確認リストから外れたが印が残っている件数,ストアにコピーした件数
  • --show-source-names(import)を付けたときだけ,問題のあったファイルの元の名前・番号と,対応表で使わない行の行番号を最大 20 件まで表示する.患者 ID はどの場合も表示しない
  • 取り込みはリポジトリの clone から実行する(要確認リスト reviews/ をパッケージの位置からリポジトリのルートを辿って読むため).openpyxl が要る(研究室 PC では uv sync --no-dev --extra import)
  • 問題を見つけたら黙って飛ばさず,件数と理由を表示して停止する(check・stats は止めずに件数を報告する)

要確認リスト (Review List)

取り込み元のデータに,基盤では正解を決められない問題(同じ写真の重複・患者 ID やラベルの食い違い等)があるとき,その番号を要確認として記録する.受け取ったデータは問題のあるものも含めて受け取ったとおりに目録へ入れ,問題には後で対応する(2026-10-08 のユーザー判断.それまでは「保留」として取り込みで飛ばしていた).推測で片方を選んで正解として固定しないため.

  • reviews/<取り込み元の名前>.toml に置く(リポジトリで管理し,PR で変更する).患者 ID は書かない
  • 1 件ごとに [[review]] に number(取り込み元での番号)・reason(理由)・resolve(確かめる方法)・since(要確認にした日)を書く
  • tiasdata import は要確認の番号も登録し,要確認の印(所見 review.SPEC_02)を付ける.要確認リストにあるのに取り込み元に無い番号は停止する(リストの誤りを見逃さないため)
  • 同じ中身(SHA-256)の画像が複数の番号にあり,その番号がすべて要確認リストにある場合は,ファイルを 1 つだけ登録して撮影(患者)にひも付けない.舌色のラベルと要確認の印はファイルに付け,印の numbers に全番号を入れる.番号どうしでラベルが違えば停止する.要確認リストに無い番号が含まれれば今までどおり停止する
  • 登録済みの撮影・ファイルが要確認リストに載っていて有効な印が無ければ,印を足す(書き足すだけ).要確認リストから外れたのに印が残っているものは件数を報告するだけ(印を外すのは将来の編集のコマンド.PLAN_02「編集のコマンド」)
  • 要確認リストのファイルが無い取り込み元は停止する(設定で取り込み元の名前を誤ったときに要確認が効かずに取り込まれるのを防ぐため).要確認が無い取り込み元には,空の要確認リスト([[review]] が 0 件)を PR で置く
  • 形の誤り(未知のキー・必須キーの欠落・番号が 1 未満・番号の重複・since が日付でない)は停止する
  • 最初の要確認リストは reviews/tiasjudgemodel.toml(舌色データセットの重複 5 組のうち 9 枚.PLAN_02「舌色データセットの重複 5 組の扱い」)

出力の規則 (Output Rules)

CLI の出力・ログ・エラーメッセージに出してよいもの・出さないもの.Claude が SSH 経由で CLI を実行し,その出力を読むことを前提にする.

出してよい出さない
件数・割合・サイズの合計実際の患者 ID・対応表の中身
研究用 ID(S…・C…)・SHA-256画像の画素値・画像そのもの
種類名・所見の値(舌色の slug 等)・版取り込み元のファイルの中身
設定ファイルで付けた名前(取り込み元・サーバ)—
  • 元のファイル名(source_name)は個人をたどれる情報を含まないが,既定では表示しない(エラーの特定に必要な場合だけ表示する)
  • 目録・ストア・対応表・取り込み元のパスは表示しない.例外として,「設定ファイルが見つからない」エラーでは設定ファイル自身のパスを表示する(データの場所ではなく,原因の特定に必要なため)
  • 設定ファイルの検証エラーは「キーの位置: 理由」だけを 1 行で示し,入力された値(パス等)は表示しない
  • 出力は常に UTF-8 で書き出す(Windows でパイプ・SSH 越しに cp932 で書き出されて手元で文字化けするのを防ぐため)