pathml について
pathmlは、全スライド画像を扱う計算病理学向けのPythonツールキットです。SlideDataとPipelineの抽象化により、病理画像や機械学習の研究者向けに、読み込みからタイル化、前処理、特徴抽出までをまとめて扱えます。
主な機能
- 01複数の全スライド画像形式の読み込み
- 02スライドのタイル化と組織検出
- 03染色正規化と核セグメンテーション
- 04多重免疫蛍光画像の処理
- 05タイル特徴の抽出とデータ出力
活用シーン
- 01病理画像から学習データセットを作成
- 02H&E画像間の染色を正規化
- 03病理画像内の核をセグメント化
- 04複数の全スライド画像を一括処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill pathmlインストール後、Claude Code で/pathmlを入力して読み込まれたか確認します。
詳細
pathml
概要
PathMLは、ホールスライド画像(WSI)を用いた計算病理学のワークフロー向けに設計されたPythonツールキットです。未処理のスライドファイル(SVS、NDPI、MRXS、TIFF)から、タイルの抽出、前処理(染色正規化、核のセグメンテーション、組織検出)、特徴抽出、機械学習までを一貫したパイプラインで提供します。PathMLは、一般的なPythonの機械学習ライブラリや画像処理ライブラリと連携しながら、SlideDataおよびPipelineの抽象化によってWSIの処理の複雑さを軽減します。
使用する場面
- ホールスライドH&E画像の処理:大きなWSIをタイルに分割し、異なるスキャナーやバッチで取得されたスライド間の染色のばらつきを正規化します。
- 病理スライド上の核のセグメンテーション:組み込みのセグメンテーションパイプラインを使用して、H&EまたはDAPI染色WSI内の核を検出・セグメンテーションします。
- WSIからの機械学習トレーニングデータセットの構築:組織分類器、腫瘍検出器、生存予測モデルのトレーニング用に、対応するラベルとともにタイルを抽出します。
- 多重免疫蛍光(mIF)画像解析:チャンネルごとの前処理と特徴抽出を行い、多チャンネルIFスライドを処理します。
- コホート間の染色正規化:MacenkoまたはVahadaneの染色正規化を適用し、複数の施設からのH&Eスライドを統一します。
- 下流の機械学習向け特徴抽出:患者レベルの予測タスク向けに、タイルから手作り特徴量または深層学習特徴量を抽出します。
- 標準的な2D顕微鏡画像(WSI以外)には、PathMLのオーバーヘッドを避け、
scikit-imageまたはcellposeを直接使用してください。
前提条件
- Pythonパッケージ:
pathml、torch、torchvision、numpy、scikit-image、openslide-python - システム:OpenSlide Cライブラリ(WSIの読み取りに必要)
- データ要件:SVS、NDPI、MRXS、またはTIFF形式のWSIファイル。セグメンテーションにはGPUを推奨します。
- 環境:Python 3.8以降。深層学習の前処理にはCUDA対応GPUが必要です。
# Install system dependency first
conda install -c conda-forge openslide
# Install PathML
pip install pathml
# For GPU support
pip install torch torchvision --extra-index-url https://download.pytorch.org/whl/cu118
クイックスタート
from pathml.core import SlideData
from pathml.preprocessing import Pipeline
from pathml.preprocessing.transforms import BoxBlur, TissueDetectionHE
# Load → build pipeline → tile → preprocess
slide = SlideData("tumor.svs", name="demo")
pipeline = Pipeline([BoxBlur(kernel_size=3), TissueDetectionHE(mask_name="tissue")])
slide.run(pipeline, tile_size=256, tile_stride=256)
# Inspect tiles
from pathml.core import Tile
tiles = [t for t in slide.tiles if t.masks["tissue"].any()]
print(f"Tissue tiles: {len(tiles)} of {len(slide.tiles)}")
ワークフロー
ステップ1:ホールスライド画像を読み込む
from pathml.core import SlideData
# Load an H&E whole-slide image
slide = SlideData("path/to/slide.svs", name="tumor_slide_001")
print(f"Slide name: {slide.name}")
print(f"Slide shape: {slide.slide.shape}")
print(f"Slide properties: {slide.slide.properties}")
ステップ2:前処理パイプラインを定義する
from pathml.preprocessing import Pipeline
from pathml.preprocessing.transforms import (
BoxBlur,
TissueDetectionHE,
HEStainNormalization,
)
# Build a preprocessing pipeline for H&E slides
pipeline = Pipeline([
BoxBlur(kernel_size=5), # smooth image
TissueDetectionHE(mask_name="tissue"), # detect tissue regions
HEStainNormalization(target="normalize"), # normalize H&E staining
])
print(f"Pipeline steps: {len(pipeline.transforms)}")
ステップ3:TileDatasetを作成する
from pathml.core import TileDataset
# Tile the slide into 256x256 patches at 20x magnification
slide.generate_tiles(
shape=(256, 256),
stride=(256, 256),
pad=False,
level=0, # pyramid level 0 = highest resolution
coords_format="fractional",
)
print(f"Total tiles generated: {len(slide.tiles)}")
ステップ4:前処理パイプラインを実行する
# Apply preprocessing pipeline to all tiles
slide.run(pipeline, distributed=False, tile_pad=False)
print("Pipeline complete — tiles preprocessed")
# Inspect a single tile
tile = slide.tiles[0]
print(f"Tile shape: {tile.image.shape}") # (256, 256, 3)
print(f"Tile masks: {list(tile.masks.keys())}")
ステップ5:核のセグメンテーション
from pathml.preprocessing.transforms import NuclearSegmentation
# Run Hematoxylin-channel nuclear segmentation
seg_pipeline = Pipeline([
TissueDetectionHE(mask_name="tissue"),
NuclearSegmentation(mask_name="nuclei"),
])
slide.run(seg_pipeline, distributed=False)
# Count nuclei per tile
for tile in list(slide.tiles)[:5]:
n_nuclei = tile.masks["nuclei"].max()
print(f"Tile {tile.coords}: {n_nuclei} nuclei detected")
ステップ6:特徴抽出
import numpy as np
from pathml.core import SlideDataset
features = []
for tile in slide.tiles:
if "tissue" in tile.masks and tile.masks["tissue"].any():
img = tile.image
feat = {
"mean_r": img[:, :, 0].mean(),
"mean_g": img[:, :, 1].mean(),
"mean_b": img[:, :, 2].mean(),
"std_r": img[:, :, 0].std(),
"n_nuclei": int(tile.masks["nuclei"].max()) if "nuclei" in tile.masks else 0,
"tile_x": tile.coords[0],
"tile_y": tile.coords[1],
}
features.append(feat)
import pandas as pd
df = pd.DataFrame(features)
df.to_csv("slide_features.csv", index=False)
print(f"Extracted features from {len(df)} tissue tiles -> slide_features.csv")
ステップ7:処理済みスライドを保存・エクスポートする
import h5py
# Save slide data (tiles + masks) to HDF5
slide.write("processed_slide.h5")
print("Slide saved to processed_slide.h5")
# Reload for downstream use
from pathml.core import SlideData
slide_loaded = SlideData.read("processed_slide.h5")
print(f"Reloaded: {len(slide_loaded.tiles)} tiles")
主なパラメーター
| パラメーター | デフォルト | 範囲/選択肢 | 効果 |
|---|---|---|---|
shape | (256, 256) | (64,64) – (1024,1024) | タイルのピクセル単位の寸法 |
stride | shapeと同じ | shape以下の任意のタプル | タイル中心間の間隔です。stride < shapeの場合、タイルが重なります。 |
level | 0 | 0~最大ピラミッドレベル | ピラミッドの解像度レベル(0=フル解像度) |
kernel_size | 5 | 奇数 3~21 | BoxBlurの平滑化カーネルサイズ |
mask_name | 必須 | 任意の文字列 | tile.masksに保存される出力マスクの名前 |
distributed | False | True、False | 大きなスライドのDask分散処理を有効にします。 |
pad | False | True、False | 端のタイルをshapeと同じサイズになるようパディングします。 |
よくあるレシピ
レシピ:組織のみを含むタイルのフィルタリング
使用する場面:背景タイルを除外して、下流の処理におけるメモリー使用量と計算量を削減します。
# Filter tiles to only tissue regions after running tissue detection pipeline
tissue_tiles = [t for t in slide.tiles if "tissue" in t.masks and t.masks["tissue"].mean() > 0.5]
print(f"Tissue tiles: {len(tissue_tiles)} / {len(slide.tiles)} total")
レシピ:タイルをPNGファイルとしてエクスポートする
使用する場面:PyTorchでカスタム分類器をトレーニングするための、ラベル付きタイルデータセットを作成します。
from PIL import Image
import numpy as np
from pathlib import Path
output_dir = Path("tiles_png")
output_dir.mkdir(exist_ok=True)
for i, tile in enumerate(slide.tiles):
if "tissue" in tile.masks and tile.masks["tissue"].mean() > 0.5:
img = Image.fromarray(tile.image.astype(np.uint8))
img.save(output_dir / f"tile_{i:05d}_x{tile.coords[0]}_y{tile.coords[1]}.png")
print(f"Saved {i+1} tiles to {output_dir}/")
レシピ:複数のスライドをバッチ処理する
使用する場面:WSIファイルのディレクトリに対して、同じ前処理パイプラインを実行します。
from pathlib import Path
from pathml.core import SlideData
from pathml.preprocessing import Pipeline
from pathml.preprocessing.transforms import TissueDetectionHE, HEStainNormalization
pipeline = Pipeline([
TissueDetectionHE(mask_name="tissue"),
HEStainNormalization(target="normalize"),
])
wsi_dir = Path("slides/")
for wsi_path in sorted(wsi_dir.glob("*.svs")):
slide = SlideData(str(wsi_path), name=wsi_path.stem)
slide.generate_tiles(shape=(256, 256), stride=(256, 256), level=0)
slide.run(pipeline, distributed=False)
slide.write(f"processed/{wsi_path.stem}.h5")
print(f"Processed {wsi_path.name}: {len(slide.tiles)} tiles")
想定される出力
slide.tiles—Tileオブジェクトのイテラブル。それぞれ.image(numpy配列)と.masks(numpy配列の辞書)を含みます。slide_features.csv— タイルごとの表形式の特徴量(色の統計量、核の数、座標)processed_slide.h5— 下流での使用に向けて、タイル、マスク、メタデータを含むHDF5ファイル- PNGタイルファイル(任意)— PyTorchの
ImageFolderデータセットで読み込み可能な形式です。
トラブルシューティング
| 問題 | 原因 | 解決方法 |
|---|---|---|
openslide.lowlevel.OpenSlideUnsupportedFormatError | OpenSlide の C ライブラリがインストールされていないか、WSI 形式がサポートされていません | conda install -c conda-forge openslide を実行します。形式の互換性を確認してください |
セグメンテーション中の CUDA out of memory | タイルサイズが GPU に対して大きすぎます | タイルの shape を (128, 128) に縮小するか、CPU で distributed=False を指定して実行します |
generate_tiles の後も slide.tiles が空です | レベルインデックスが範囲外か、すべてのタイルがフィルタリングされています | level=0 を指定します。slide.slide.level_count でスライドのピラミッドを確認してください |
| 染色の正規化でタイルが黒くなります | 元のスライドのコントラストが低すぎるか、組織の検出に失敗しています | 正規化の前に TissueDetectionHE を適用します。組織マスクのカバー範囲を確認してください |
tile.masks で KeyError: 'nuclei' が発生します | セグメンテーションパイプラインがまだ実行されていません | マスクにアクセスする前に、slide.run() で NuclearSegmentation パイプラインを実行します |
| タイル生成が非常に遅いです | 大きな SVS で高解像度のレベル 0 を使用しています | プロトタイピングを高速化するには、より低いピラミッドレベル(level=1 または level=2)を使用します |
AttributeError: SlideData has no attribute 'write' | PathML のバージョンが古いです | HDF5 の保存/読み込みをサポートするには、pip install --upgrade pathml を実行します |
参考資料
- PathML のドキュメント — チュートリアルを含む公式ドキュメント
- PathML GitHub(Dana-Farber/PathML) — ソースコードと例
- Rosenthal et al. (2022), Cell Systems — PathML 論文 — 原著論文
- OpenSlide のドキュメント — PathML の基盤となる WSI 読み込みライブラリ
コメント
Markdown 対応