mcpField
I
imaging-data-commons

imaging-data-commons

github.com/jaechang-hitsデータ・データベース38467 回インストール1 週間前に更新
リポジトリ

imaging-data-commons について

idc-indexは、NCI Imaging Data Commonsの公開がん画像データを選択・取得する研究者向けPythonクライアントです。内蔵メタデータ索引をDuckDBでローカルSQL検索でき、画像は公開AWSまたはGoogle Cloud Storageバケットから取得します。

主な機能

  1. 01内蔵メタデータのローカルSQL検索
  2. 02コレクション、患者、検査、シリーズの閲覧
  3. 03DICOM識別子によるダウンロードの絞り込み
  4. 04取得前のコホート容量確認
  5. 05OHIFまたはSlimのビューアURL生成

活用シーン

  1. 01DICOMメタデータによるがん画像コホート選択
  2. 02再現可能な機械学習用コホートの構築
  3. 03選択したDICOMシリーズの取得と処理
  4. 04画像シリーズのブラウザーリンク共有

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill imaging-data-commons

インストール後、Claude Code で/imaging-data-commonsを入力して読み込まれたか確認します。

詳細

NCI Imaging Data Commons (idc-index)

概要

NCI Imaging Data Commons(IDC)は、がん画像データの公開コレクションとして最大規模を誇り、175 件を超える DICOM コレクション(CT、MR、PET、スライド顕微鏡画像、セグメンテーション、構造化レポート)をホストしています。idc-index Python クライアントには、IDC のメタデータカタログ全体が pip ホイールに含まれる parquet ファイルとして同梱されています。IDCClient() はこのファイルを DuckDB に読み込むため、sql_query() はネットワークに一切アクセスせず、ローカルで実行されます。

画像は、同梱の s5cmd 実行ファイルを使って、パブリック AWS S3(デフォルト)または Google Cloud Storage のバケットからストリーミングダウンロードされます。GCP/AWS の認証情報、BigQuery の料金、サービスアカウント JSON は不要です。

使用する場面

  • モダリティ、がんの種類、解剖学的部位、DICOM タグを指定して、一般公開されているがん画像データセットを検索する場合
  • バージョン管理された IDC リリースから、再現可能な ML コホート(セグメンテーション、分類、マルチモーダル)を構築する場合
  • ダウンロードせずに、175 件を超えるすべてのコレクションを対象として SQL で大規模な DICOM メタデータをクエリする場合
  • ローカルでの処理やモデルのトレーニング用に、特定の DICOM シリーズをダウンロードする場合
  • OHIF/Slim ビューアーの URL を生成して、ブラウザー上でシリーズを共有または対話的に確認する場合
  • すでにローカルにある DICOM ファイルの読み取り、編集、匿名化だけが必要な場合は、代わりに pydicom-medical-imaging を使用してください
  • ダウンロード後に全スライド病理画像の前処理(タイル分割、染色正規化)を行う場合は、代わりに histolab を使用してください

前提条件

  • Python パッケージ:idc-index(>=0.12)、pandas、pydicom(ダウンロード後の DICOM ファイルの読み取り用)
  • データ要件:クエリには不要です。ダウンロードする場合は、series_size_MB に相当する空きディスク容量が必要です
  • 環境:認証は不要です。すべてのデータに公開アクセスできます。ホイールには parquet インデックスと、高速な S3 転送に使用する s5cmd 実行ファイルの両方が同梱されています
  • レート制限:ローカル SQL クエリ(ローカルの parquet 上で実行する DuckDB)にはありません。一括ダウンロードは API のクォータではなく、ネットワーク帯域幅によって制限されます
# Skip when already provisioned in a pixi or conda env
pip install idc-index pydicom

クイックスタート

from idc_index import IDCClient

client = IDCClient()
print('IDC version:', client.get_idc_version())
print('Collections:', len(client.get_collections()))
print('First 5:', client.get_collections()[:5])
df = client.sql_query("""
    SELECT collection_id, COUNT(DISTINCT SeriesInstanceUID) AS n_series
    FROM index
    WHERE Modality = 'CT'
    GROUP BY collection_id
    ORDER BY n_series DESC LIMIT 5
""")
print(df)

コア API

モジュール 1:クライアントの初期化とコレクション

IDCClient() は唯一のエントリーポイントです。parquet インデックスを読み込み、index という名前の DuckDB テーブルとして登録し、同梱の s5cmd を検証します。get_collections() は、nsclc_radiomics、lidc_idri、tcga_gbm などの小文字のコレクション ID を含む、通常の Python リストを返します。

from idc_index import IDCClient

client = IDCClient()
collections = client.get_collections()
print("total:", len(collections), "type:", type(collections).__name__)
print("lung-related:", [c for c in collections if "lung" in c or "nsclc" in c][:5])
モジュール 2:sql_query(ローカルインデックスに対する DuckDB クエリ)

コホート選択には、この API の使用を推奨します。テーブル名は index です。インストール時に追加テーブル(prior_versions_index、任意の sm_index と clinical_index)も自動登録されます。pandas DataFrame を返します。Modality、BodyPartExamined、series_size_MB、または任意の DICOM タグを使ったフィルタリングには、すべてこの API を使用してください。従来の get_series(collection_id=..., modality=...) シグネチャは、idc-index にはもうありません。

# Cohort: small CT series in NSCLC Radiomics, sorted by size for cheap testing
df = client.sql_query("""
    SELECT SeriesInstanceUID, StudyInstanceUID, PatientID, Modality, series_size_MB
    FROM index
    WHERE collection_id = 'nsclc_radiomics'
      AND Modality = 'CT'
    ORDER BY series_size_MB ASC
    LIMIT 5
""")
print(df[["PatientID", "Modality", "series_size_MB"]])
# Cross-collection lung CT count, using DuckDB ILIKE for case-insensitive matching
df = client.sql_query("""
    SELECT collection_id, COUNT(DISTINCT SeriesInstanceUID) AS n
    FROM index
    WHERE Modality = 'CT' AND BodyPartExamined ILIKE '%LUNG%'
    GROUP BY collection_id
    ORDER BY n DESC LIMIT 5
""")
print(df)
モジュール 3:階層ブラウジング(患者、検査、シリーズ)

DICOM 階層(コレクション -> 患者 -> 検査 -> シリーズ)をたどるには、型指定されたヘルパーを使用してください。各ヘルパーは、dict(デフォルト)、df、または list の outputFormat を受け付けます。注意:get_dicom_series() が受け取るのは studyInstanceUID(collection_id ではありません)です。コレクションまたはモダリティでシリーズをフィルタリングする場合は、sql_query() を使用してください。

patients = client.get_patients('nsclc_radiomics', outputFormat='df')
print("patients:", patients.shape, list(patients.columns)[:5])

# Walk down the hierarchy from one patient
pid = patients["PatientID"].iloc[0]
studies = client.get_dicom_studies(pid, outputFormat='df')
print("studies for", pid, ":", studies.shape)

study_uid = studies["StudyInstanceUID"].iloc[0]
series = client.get_dicom_series(study_uid, outputFormat='df')
print("series in study:", series.shape, "modalities:", series["Modality"].unique().tolist())
モジュール 4:download_from_selection(最新のダウンロード方法)

推奨されるダウンロード方法です。collection_id、patientId、studyInstanceUID、seriesInstanceUID、sopInstanceUID、crdc_series_uuid を任意に組み合わせて受け付けます(それぞれ文字列またはリストを指定できます)。フィルターは順番に適用されます。バイトデータを取得する前にコホートのサイズを確認するには、dry_run=True を使用してください。ファイルは dirTemplate(デフォルト:%collection_id/%PatientID/%StudyInstanceUID/%Modality_%SeriesInstanceUID)の下に保存されます。

import tempfile, glob, os

# Pick the smallest CT series for a fast smoke test (about 40 MB)
df = client.sql_query("""
    SELECT SeriesInstanceUID FROM index
    WHERE collection_id = 'nsclc_radiomics' AND Modality = 'CT'
    ORDER BY series_size_MB ASC LIMIT 1
""")
uid = df["SeriesInstanceUID"].iloc[0]

out = tempfile.mkdtemp(prefix='idc_dl_')
client.download_from_selection(
    downloadDir=out,
    seriesInstanceUID=[uid],
    quiet=True,
    show_progress_bar=False,
    source_bucket_location='aws',  # 'aws' (default) or 'gcs'
)
files = glob.glob(os.path.join(out, "**/*.dcm"), recursive=True)
print(f"downloaded {len(files)} DICOM files to {out}")
# Size a cohort before downloading
client.download_from_selection(
    downloadDir='./preview',
    collection_id='nsclc_radiomics',
    dry_run=True,
)
モジュール 5:download_dicom_series(便利なラッパー)

単一シリーズのダウンロードに使用します。内部では download_from_selection(seriesInstanceUID=...) を呼び出します。UID の文字列またはリストを受け付けます。

import tempfile, glob, os
out = tempfile.mkdtemp(prefix='idc_dl_')
client.download_dicom_series(
    seriesInstanceUID=uid,            # string or list
    downloadDir=out,
    quiet=True,
    show_progress_bar=False,
)
print("files:", len(glob.glob(os.path.join(out, "**/*.dcm"), recursive=True)))
Module 6: get_viewer_URL(ブラウザーでの可視化)

IDC OHIF(放射線科)または Slim(スライド顕微鏡)のビューアーを開く、共有可能な URL を返します。viewer_selector が省略された場合、モダリティに基づいてビューアーを自動選択します。

url = client.get_viewer_URL(seriesInstanceUID=uid)
print("Open in browser:", url)

# Force a specific viewer
url_v2 = client.get_viewer_URL(seriesInstanceUID=uid, viewer_selector='ohif_v2')
print(url_v2)
Module 7: pydicom によるダウンロード済み DICOM の検査

ダウンロード後、ファイルは dirTemplate の下に整理されます。ヘッダーとピクセルの検査には pydicom を使用します。

import pydicom, glob, os
dcm_files = sorted(glob.glob(os.path.join(out, "**/*.dcm"), recursive=True))
ds = pydicom.dcmread(dcm_files[0])
print("PatientID:", ds.PatientID)
print("Modality :", ds.Modality)
print("Rows x Cols:", ds.Rows, "x", ds.Columns)
print("Pixel array:", ds.pixel_array.shape)

重要な概念

ローカル優先、認証不要のアーキテクチャ

IDC クライアントは特殊な設計になっており、client = IDCClient() はクエリに完全オフラインで対応します。parquet インデックス(数百 MB。idc-index-data に同梱)はメモリに読み込まれ、index という名前の DuckDB テーブルとして登録されます。すべての sql_query()、get_collections()、get_patients() などは、ローカルでの pandas/DuckDB 操作です。ネットワーク通信が発生するのは、download_from_selection() / download_dicom_series() の実行時だけです。これらは同梱の s5cmd 実行可能ファイルを使って、公開バケット(デフォルトでは s3://idc-open-data/...。source_bucket_location=gcs に設定すると gcs に切り替わります)からコピーします。そのため、gcloud 認証、GCP プロジェクト ID、BigQuery の課金、API キーは不要です。

DICOM の階層と識別子

IDC は標準の DICOM モデルに従います。Collection(collection_id。nsclc_radiomics のように小文字とアンダースコアを使用)-> Patient(PatientID)-> Study(StudyInstanceUID)-> Series(SeriesInstanceUID)-> Instance(SOPInstanceUID)。デフォルトでは、ダウンロードはシリーズ単位で行われます。crdc_series_uuid は、長期的な参照に適した、変更されない別の識別子です。

バージョン管理

インデックスのバージョンは、インストールされている idc-index-data パッケージのバージョン(client.get_idc_version()、例:v24)に固定されます。再現性を確保するには、環境内で idc-index と idc-index-data の両方のバージョンを固定してください。過去のリリースには、sql_query() 内の prior_versions_index テーブルから引き続きアクセスできます。

よくあるワークフロー

ワークフロー 1:コホート選択 -> マニフェスト -> ダウンロード

目標:ML のプロトタイピング用に小規模な CT シリーズの CSV マニフェストを作成し、ダウンロードします。

from idc_index import IDCClient
import pandas as pd, tempfile, os, glob

client = IDCClient()

# Step 1: SQL cohort: small CTs across three lung collections
cohort = client.sql_query("""
    SELECT SeriesInstanceUID, PatientID, collection_id, Modality, series_size_MB
    FROM index
    WHERE collection_id IN ('nsclc_radiomics', 'tcga_luad', 'tcga_lusc')
      AND Modality = 'CT'
      AND series_size_MB < 60
    ORDER BY series_size_MB ASC
""")
print(f"Cohort: {len(cohort)} series, total {cohort['series_size_MB'].sum():.1f} MB")

# Step 2: Save manifest
cohort.to_csv('ct_lung_manifest.csv', index=False)

# Step 3: Download a small subset
out = tempfile.mkdtemp(prefix='idc_cohort_')
client.download_from_selection(
    downloadDir=out,
    seriesInstanceUID=cohort["SeriesInstanceUID"].head(2).tolist(),
    quiet=True,
    show_progress_bar=False,
)
print("downloaded", len(glob.glob(os.path.join(out, "**/*.dcm"), recursive=True)), "files")
ワークフロー 2:1 人の患者を階層的に検査する

目標:SQL を記述せずに、コレクション -> 患者 -> 検査 -> シリーズ -> DICOM ヘッダーの順に掘り下げて確認します。

from idc_index import IDCClient
import tempfile, glob, os, pydicom

client = IDCClient()

# Pick first patient in the collection
patients = client.get_patients('nsclc_radiomics', outputFormat='df')
pid = patients["PatientID"].iloc[0]

studies = client.get_dicom_studies(pid, outputFormat='df')
series_df = client.get_dicom_series(studies["StudyInstanceUID"].iloc[0], outputFormat='df')
print(f"Patient {pid}: {len(studies)} studies, {len(series_df)} series in first study")
print("modalities:", series_df["Modality"].unique().tolist())

# Pick the smallest image series (CT/MR, not SR/SEG) and download
imaging = series_df[series_df["Modality"].isin(["CT", "MR", "PT"])]
target_uid = imaging.sort_values("series_size_MB").iloc[0]["SeriesInstanceUID"]
out = tempfile.mkdtemp(prefix='idc_one_')
client.download_dicom_series(seriesInstanceUID=target_uid, downloadDir=out,
                             quiet=True, show_progress_bar=False)

ds = pydicom.dcmread(sorted(glob.glob(os.path.join(out, "**/*.dcm"), recursive=True))[0])
print("first slice:", ds.Modality, ds.pixel_array.shape)
print("viewer:", client.get_viewer_URL(seriesInstanceUID=target_uid))

主要なパラメーター

パラメーターモジュール / 関数デフォルト範囲 / オプション効果
outputFormatget_patients / get_dicom_studies / get_dicom_seriesdictdict, df, listアクセサーメソッドの戻り値の型
seriesInstanceUIDdownload_from_selection / download_dicom_seriesNonestr or list[str]DICOM SeriesInstanceUID でフィルター
collection_iddownload_from_selection / get_patientsNone / requirednsclc_radiomics のような小文字の文字列コレクションでフィルター(小文字、アンダースコア区切り)
source_bucket_locationdownload_from_selection / download_dicom_seriesawsaws, gcsデータ取得元の公開バケット
dirTemplatedownload_from_selection%collection_id/%PatientID/%StudyInstanceUID/%Modality_%SeriesInstanceUID%-プレフィックス付き DICOM タグを含むテンプレート文字列。フラットなレイアウトにする場合は Noneディスク上のフォルダー階層
dry_rundownload_from_selection / download_dicom_seriesFalseTrue/Falseダウンロードせずにコホートのサイズを計算
use_s5cmd_syncdownload_from_selection / download_dicom_seriesFalseTrue/Falsecp の代わりに s5cmd sync を使用(部分的なダウンロードを再開)
viewer_selectorget_viewer_URLNone (auto)ohif_v2, ohif_v3, slim特定のブラウザービューアーを指定

ベストプラクティス

  1. 単一の階層ステップを超えるフィルタには sql_query() を使用します:DataFrame を返し、DuckDB を介して約 1,000 万行のインデックス全体を即座に処理でき、任意の DICOM タグにも対応しています。get_patients / get_dicom_studies / get_dicom_series は、親 UID がすでにわかっている場合にのみ使用してください。

  2. 大規模なコホートでは必ずドライランを実行します:download_from_selection(..., dry_run=True) を呼び出すと、データの転送前に合計サイズが表示されます。lidc_idri のような小規模なコレクションでも約 120 GB あり、nlst は 10 TB を超えます。

  3. idc-index と idc-index-data の両方のバージョンを固定します:インデックスのバージョンが再現性を左右します。client.get_idc_version() の値(例:v24)を、データセットカードまたは論文の方法セクションに記録してください。

  4. ほとんどのダウンロードでは AWS を優先します:source_bucket_location=aws がデフォルトであり、ほとんどの学術ネットワークで最速です。GCP の計算環境がバケットと同じ場所にある場合にのみ、gcs に切り替えてください。

  5. 従来の BigQuery の手順をデフォルトとして使わないでください:bigquery-public-data.idc_current.dicom_all は現在も機能しますが、GCP の認証と課金設定が必要で、推奨される方法ではなくなっています。任意のコード例については Recipes を参照してください。

よくあるレシピ

レシピ:異なるモダリティの患者コホート(同一患者の CT と MR)

使用する場面:すべての患者が両方のモダリティを持つマルチモーダル研究を構築する場合。

df = client.sql_query("""
    SELECT PatientID
    FROM index
    WHERE collection_id = 'tcga_gbm'
    GROUP BY PatientID
    HAVING SUM(CASE WHEN Modality = 'CT' THEN 1 ELSE 0 END) > 0
       AND SUM(CASE WHEN Modality = 'MR' THEN 1 ELSE 0 END) > 0
""")
print(f"Patients with both CT and MR in TCGA-GBM: {len(df)}")
レシピ:QA 用のビューアー URL を一括生成する

使用する場面:目視で確認するシリーズの候補一覧を共同研究者に送る場合。

sample = client.sql_query("""
    SELECT SeriesInstanceUID, Modality
    FROM index WHERE collection_id = 'lidc_idri' AND Modality = 'CT'
    LIMIT 5
""")
for _, row in sample.iterrows():
    print(row.Modality, client.get_viewer_URL(seriesInstanceUID=row.SeriesInstanceUID))
レシピ:任意の応用(データセット間の結合に BigQuery を使用)

使用する場面:IDC のメタデータを別の BigQuery 公開データセット(例:TCGA の臨床データ)と結合する必要があり、課金設定済みの GCP プロジェクトがある場合。その他の用途では、sql_query() を優先してください。

# Requires: a google-cloud-bigquery install and gcloud application-default credentials.
from google.cloud import bigquery
bq = bigquery.Client(project='your-gcp-project-id')
df = bq.query("""
    SELECT collection_id, Modality, COUNT(DISTINCT SeriesInstanceUID) AS n
    FROM `bigquery-public-data.idc_current.dicom_all`
    WHERE Modality IN ('CT', 'MR', 'PET')
    GROUP BY collection_id, Modality
    ORDER BY n DESC LIMIT 20
""").to_dataframe()
print(df)

トラブルシューティング

問題原因解決策
ImportError: No module named idc_indexパッケージがインストールされていないpip install idc-index を実行します(認証の設定は不要です)
IDCClient() の初回呼び出しが遅いparquet インデックスをメモリに読み込んでいる(1~3 秒、プロセスごとに一度のみ)クエリ間でクライアントを再利用し、呼び出しごとに再インスタンス化しないでください
sql_query: Catalog Error: Table idc_index does not existテーブル名が間違っているDuckDB のテーブル名は index です。idc_index や dicom_all ではありません
get_dicom_series(collection_id=..., modality=...) が TypeError を発生させるAPI が古く、そのシグネチャは削除されていますcollection_id と Modality のフィルタを WHERE 句に指定して sql_query を使用してください
download_from_selection が s5cmd: command not found で失敗する同梱の s5cmd が PATH にありませんidc-index を再インストールしてください。wheel に s5cmd が同梱されています。NixOS または glibc を使用しないシステムでは、IDC_INDEX_S5CMD_EXE にシステムの s5cmd を設定してください
ダウンロードが停止する、または非常に遅い認証ではなくネットワークのボトルネックGCP 上では source_bucket_location=gcs を試してください。それ以外の場合は use_s5cmd_sync=True を使用して再開してください
ValueError: collection_id ... does not existコレクション ID は大文字と小文字を区別し、アンダースコアを使用します小文字とアンダースコアを使用してください(LIDC-IDRI ではなく lidc_idri)。client.get_collections() で確認してください
pydicom がピクセルデータを読み取れない圧縮転送構文pylibjpeg、pylibjpeg-libjpeg、gdcm をインストールしてから、ds.pixel_array を再試行してください

関連スキル

  • pydicom-medical-imaging - IDC からダウンロードした DICOM ファイルの読み取り、編集、匿名化
  • histolab-wsi-processing - 全スライド画像のタイル化と染色の正規化(IDC SM モダリティ)
  • pathml - IDC のスライドコレクションを使用する、計算病理学向けエンドツーエンド ML パイプライン

参考資料

  • idc-index GitHub - ソース、README、課題トラッカー(正式な API)
  • idc-index on PyPI - 最新リリース
  • learn.canceridc.dev - IDC の公式チュートリアル、ノートブック、概念ガイド
  • IDC portal - コレクションやビューアー URL を探索するためのブラウザー UI
  • IDC BigQuery dataset - 高度な分析や複数データセットをまたぐ SQL(任意、GCP の課金設定が必要)

コメント