@nahisaho/satori 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,382 @@
1
+ ---
2
+ name: scientific-advanced-imaging
3
+ description: |
4
+ 高度バイオイメージング解析スキル。CellProfiler によるモフォロジカル
5
+ プロファイリング・Cell Painting 解析、Cellpose による深層学習
6
+ セルセグメンテーション、napari によるインタラクティブ 3D 可視化。
7
+ ---
8
+
9
+ # Scientific Advanced Imaging
10
+
11
+ CellProfiler / Cellpose / napari を活用した高度バイオイメージング
12
+ 解析パイプラインを提供する。セルセグメンテーション、形態学的
13
+ 特徴抽出、Cell Painting アッセイ解析、3D 画像可視化。
14
+
15
+ ## When to Use
16
+
17
+ - Cell Painting アッセイ画像を解析するとき
18
+ - 深層学習によるセルセグメンテーションが必要なとき (Cellpose)
19
+ - 形態学的特徴量 (面積、真円度、テクスチャ等) を定量するとき
20
+ - 蛍光顕微鏡スタック画像を 3D 可視化するとき
21
+ - カスタム Cellpose モデルを微調整するとき
22
+ - 高コンテンツスクリーニング (HCS) データを処理するとき
23
+
24
+ ---
25
+
26
+ ## Quick Start
27
+
28
+ ## 1. Cellpose セルセグメンテーション
29
+
30
+ ```python
31
+ from cellpose import models, io
32
+ import numpy as np
33
+ from pathlib import Path
34
+
35
+
36
+ def cellpose_segmentation(image_path, model_type="cyto2", diameter=None,
37
+ channels=None, gpu=True):
38
+ """
39
+ Cellpose で細胞セグメンテーション。
40
+
41
+ Parameters:
42
+ image_path: str — 画像ファイルパス
43
+ model_type: str — モデル ("cyto", "cyto2", "nuclei")
44
+ diameter: float — 細胞直径 (None で自動)
45
+ channels: list — チャネル [cytoplasm, nuclei]
46
+ gpu: bool — GPU 使用
47
+
48
+ K-Dense: cellpose
49
+ """
50
+ model = models.Cellpose(model_type=model_type, gpu=gpu)
51
+
52
+ if channels is None:
53
+ channels = [0, 0] # grayscale
54
+
55
+ img = io.imread(str(image_path))
56
+ masks, flows, styles, diams = model.eval(
57
+ img, diameter=diameter, channels=channels
58
+ )
59
+
60
+ n_cells = len(np.unique(masks)) - 1 # background除外
61
+ print(f"Cellpose: {n_cells} cells detected (model={model_type})")
62
+ print(f" Auto diameter: {diams:.1f}")
63
+ return masks, flows, styles
64
+ ```
65
+
66
+ ## 2. バッチセグメンテーション
67
+
68
+ ```python
69
+ def batch_segmentation(image_dir, output_dir, model_type="cyto2",
70
+ image_pattern="*.tif", diameter=None):
71
+ """
72
+ ディレクトリ内画像のバッチセグメンテーション。
73
+
74
+ Parameters:
75
+ image_dir: str — 入力画像ディレクトリ
76
+ output_dir: str — 出力ディレクトリ
77
+ model_type: str — Cellpose モデル
78
+ """
79
+ model = models.Cellpose(model_type=model_type, gpu=True)
80
+ image_dir = Path(image_dir)
81
+ output_dir = Path(output_dir)
82
+ output_dir.mkdir(parents=True, exist_ok=True)
83
+
84
+ image_files = sorted(image_dir.glob(image_pattern))
85
+ results = []
86
+
87
+ for img_path in image_files:
88
+ img = io.imread(str(img_path))
89
+ masks, flows, styles, diams = model.eval(
90
+ img, diameter=diameter, channels=[0, 0]
91
+ )
92
+ n_cells = len(np.unique(masks)) - 1
93
+
94
+ # マスク保存
95
+ out_path = output_dir / f"{img_path.stem}_masks.npy"
96
+ np.save(str(out_path), masks)
97
+
98
+ results.append({
99
+ "image": img_path.name,
100
+ "n_cells": n_cells,
101
+ "diameter": float(diams),
102
+ })
103
+
104
+ print(f"Batch: {len(results)} images, "
105
+ f"{sum(r['n_cells'] for r in results)} total cells")
106
+ return results
107
+ ```
108
+
109
+ ## 3. CellProfiler 形態学的プロファイリング
110
+
111
+ ```python
112
+ import skimage.measure as measure
113
+ import pandas as pd
114
+
115
+
116
+ def morphological_profiling(image, masks, channel_names=None):
117
+ """
118
+ CellProfiler スタイルの形態学的特徴量抽出。
119
+
120
+ Parameters:
121
+ image: np.ndarray — 画像 (H, W) or (H, W, C)
122
+ masks: np.ndarray — セグメンテーションマスク
123
+ channel_names: list — チャネル名
124
+
125
+ K-Dense: cellprofiler
126
+ """
127
+ if image.ndim == 2:
128
+ image = image[..., np.newaxis]
129
+ if channel_names is None:
130
+ channel_names = [f"ch{i}" for i in range(image.shape[-1])]
131
+
132
+ props = measure.regionprops(masks, intensity_image=image[..., 0])
133
+
134
+ features = []
135
+ for prop in props:
136
+ feat = {
137
+ "cell_id": prop.label,
138
+ "area": prop.area,
139
+ "perimeter": prop.perimeter,
140
+ "eccentricity": prop.eccentricity,
141
+ "solidity": prop.solidity,
142
+ "major_axis": prop.major_axis_length,
143
+ "minor_axis": prop.minor_axis_length,
144
+ }
145
+ # 真円度
146
+ if prop.perimeter > 0:
147
+ feat["circularity"] = (4 * np.pi * prop.area) / (prop.perimeter ** 2)
148
+ else:
149
+ feat["circularity"] = 0.0
150
+
151
+ # チャネルごと蛍光強度
152
+ for ch_idx, ch_name in enumerate(channel_names):
153
+ ch_props = measure.regionprops(
154
+ masks, intensity_image=image[..., ch_idx]
155
+ )
156
+ for cp in ch_props:
157
+ if cp.label == prop.label:
158
+ feat[f"{ch_name}_mean"] = cp.mean_intensity
159
+ feat[f"{ch_name}_max"] = cp.max_intensity
160
+ feat[f"{ch_name}_min"] = cp.min_intensity
161
+ break
162
+
163
+ features.append(feat)
164
+
165
+ df = pd.DataFrame(features)
166
+ print(f"Morphological profiling: {len(df)} cells, {len(df.columns)} features")
167
+ return df
168
+ ```
169
+
170
+ ## 4. Cell Painting 解析
171
+
172
+ ```python
173
+ def cell_painting_analysis(image_5ch, masks, normalize=True):
174
+ """
175
+ Cell Painting 5 チャネル解析。
176
+
177
+ Channels:
178
+ ch0: DNA (Hoechst), ch1: ER (ConA), ch2: RNA (SYTO14),
179
+ ch3: AGP (Phalloidin), ch4: Mito (MitoTracker)
180
+
181
+ Parameters:
182
+ image_5ch: np.ndarray — (H, W, 5) 画像
183
+ masks: np.ndarray — セグメンテーションマスク
184
+ normalize: bool — Z-score 正規化
185
+ """
186
+ channel_names = ["DNA", "ER", "RNA", "AGP", "Mito"]
187
+
188
+ # 形態 + 蛍光特徴量抽出
189
+ features_df = morphological_profiling(image_5ch, masks, channel_names)
190
+
191
+ # テクスチャ特徴量 (Haralick-like)
192
+ from skimage.feature import graycomatrix, graycoprops
193
+
194
+ texture_features = []
195
+ for prop in measure.regionprops(masks):
196
+ cell_mask = masks == prop.label
197
+ bbox = prop.bbox
198
+ cell_region = image_5ch[bbox[0]:bbox[2], bbox[1]:bbox[3], 0]
199
+ cell_mask_crop = cell_mask[bbox[0]:bbox[2], bbox[1]:bbox[3]]
200
+ cell_region = (cell_region * cell_mask_crop).astype(np.uint8)
201
+
202
+ if cell_region.max() > 0:
203
+ glcm = graycomatrix(cell_region, [1], [0], levels=256, symmetric=True)
204
+ texture_features.append({
205
+ "cell_id": prop.label,
206
+ "contrast": graycoprops(glcm, "contrast")[0, 0],
207
+ "homogeneity": graycoprops(glcm, "homogeneity")[0, 0],
208
+ "energy": graycoprops(glcm, "energy")[0, 0],
209
+ "correlation": graycoprops(glcm, "correlation")[0, 0],
210
+ })
211
+
212
+ texture_df = pd.DataFrame(texture_features)
213
+ combined = features_df.merge(texture_df, on="cell_id", how="left")
214
+
215
+ if normalize:
216
+ numeric_cols = combined.select_dtypes(include=[np.number]).columns
217
+ numeric_cols = [c for c in numeric_cols if c != "cell_id"]
218
+ combined[numeric_cols] = (
219
+ (combined[numeric_cols] - combined[numeric_cols].mean())
220
+ / combined[numeric_cols].std()
221
+ )
222
+
223
+ print(f"Cell Painting: {len(combined)} cells, {len(combined.columns)} features")
224
+ return combined
225
+ ```
226
+
227
+ ## 5. napari 3D 可視化
228
+
229
+ ```python
230
+ def napari_visualization(image, masks=None, points=None, labels=None):
231
+ """
232
+ napari でインタラクティブ 3D 可視化。
233
+
234
+ Parameters:
235
+ image: np.ndarray — 画像 (Z, Y, X) or (Z, Y, X, C)
236
+ masks: np.ndarray — セグメンテーションマスク
237
+ points: np.ndarray — 座標点 (N, 3)
238
+ labels: list — ポイントラベル
239
+
240
+ K-Dense: napari
241
+ """
242
+ import napari
243
+
244
+ viewer = napari.Viewer()
245
+
246
+ # 画像レイヤー
247
+ if image.ndim == 4:
248
+ for ch in range(image.shape[-1]):
249
+ viewer.add_image(
250
+ image[..., ch],
251
+ name=f"Channel-{ch}",
252
+ blending="additive",
253
+ )
254
+ else:
255
+ viewer.add_image(image, name="Image")
256
+
257
+ # マスクレイヤー
258
+ if masks is not None:
259
+ viewer.add_labels(masks, name="Segmentation")
260
+
261
+ # ポイントレイヤー
262
+ if points is not None:
263
+ properties = {"label": labels} if labels else None
264
+ viewer.add_points(
265
+ points,
266
+ properties=properties,
267
+ name="Points",
268
+ size=5,
269
+ )
270
+
271
+ print(f"napari viewer: {image.shape}, "
272
+ f"masks={'Yes' if masks is not None else 'No'}")
273
+ return viewer
274
+ ```
275
+
276
+ ## 6. Cellpose カスタムモデル微調整
277
+
278
+ ```python
279
+ def finetune_cellpose(train_dir, model_type="cyto2", n_epochs=100,
280
+ learning_rate=0.1):
281
+ """
282
+ Cellpose モデルの微調整。
283
+
284
+ Parameters:
285
+ train_dir: str — 訓練データ (画像 + _masks)
286
+ model_type: str — ベースモデル
287
+ n_epochs: int — エポック数
288
+ learning_rate: float — 学習率
289
+ """
290
+ from cellpose import train
291
+
292
+ train_dir = Path(train_dir)
293
+ image_files = sorted(train_dir.glob("*.tif"))
294
+ mask_files = sorted(train_dir.glob("*_masks.tif"))
295
+
296
+ images = [io.imread(str(f)) for f in image_files]
297
+ labels = [io.imread(str(f)) for f in mask_files]
298
+
299
+ model = models.CellposeModel(model_type=model_type, gpu=True)
300
+ model_path = model.train(
301
+ images, labels,
302
+ channels=[0, 0],
303
+ n_epochs=n_epochs,
304
+ learning_rate=learning_rate,
305
+ save_path=str(train_dir / "models"),
306
+ )
307
+
308
+ print(f"Fine-tuned model saved: {model_path}")
309
+ print(f" Base: {model_type}, Epochs: {n_epochs}")
310
+ return model_path
311
+ ```
312
+
313
+ ## 7. 統合イメージングパイプライン
314
+
315
+ ```python
316
+ def imaging_pipeline(image_dir, output_dir, model_type="cyto2",
317
+ channels_5=True):
318
+ """
319
+ セグメンテーション + 特徴量抽出 統合パイプライン。
320
+
321
+ Parameters:
322
+ image_dir: str — 入力画像ディレクトリ
323
+ output_dir: str — 出力ディレクトリ
324
+ model_type: str — Cellpose モデル
325
+ channels_5: bool — 5ch Cell Painting
326
+ """
327
+ output_dir = Path(output_dir)
328
+ output_dir.mkdir(parents=True, exist_ok=True)
329
+
330
+ # 1) バッチセグメンテーション
331
+ seg_results = batch_segmentation(
332
+ image_dir, output_dir / "masks", model_type=model_type
333
+ )
334
+
335
+ # 2) 特徴量抽出
336
+ all_features = []
337
+ for res in seg_results:
338
+ img_path = Path(image_dir) / res["image"]
339
+ mask_path = output_dir / "masks" / f"{img_path.stem}_masks.npy"
340
+
341
+ img = io.imread(str(img_path))
342
+ masks = np.load(str(mask_path))
343
+
344
+ if channels_5 and img.ndim == 3 and img.shape[-1] == 5:
345
+ feats = cell_painting_analysis(img, masks)
346
+ else:
347
+ feats = morphological_profiling(img, masks)
348
+
349
+ feats["image"] = res["image"]
350
+ all_features.append(feats)
351
+
352
+ combined = pd.concat(all_features, ignore_index=True)
353
+ combined.to_csv(output_dir / "features.csv", index=False)
354
+
355
+ print(f"Pipeline complete: {len(seg_results)} images, "
356
+ f"{len(combined)} cells profiled")
357
+ return combined
358
+ ```
359
+
360
+ ---
361
+
362
+ ## パイプライン統合
363
+
364
+ ```
365
+ image-analysis → advanced-imaging → medical-imaging
366
+ (OpenCV/基本) (Cellpose/CellProfiler) (DICOM/MONAI)
367
+ │ │ ↓
368
+ fluorescence-microscopy ──┘ drug-target-profiling
369
+ (蛍光画像取得) │ (Cell Painting hit)
370
+
371
+ cheminformatics
372
+ (Cell Painting → 化合物活性)
373
+ ```
374
+
375
+ ## パイプライン出力
376
+
377
+ | ファイル | 説明 | 次スキル |
378
+ |---------|------|---------|
379
+ | `results/masks/` | セグメンテーションマスク群 | → medical-imaging |
380
+ | `results/features.csv` | 形態学的特徴量マトリクス | → cheminformatics |
381
+ | `results/cell_painting.csv` | Cell Painting プロファイル | → drug-target-profiling |
382
+ | `results/model/` | 微調整 Cellpose モデル | — |