mcpField
O
omero-integration

omero-integration

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

omero-integration について

顕微鏡研究者や Python 分析担当者が、omero-py で OMERO に接続して画像データを扱うためのスキルです。ピクセルデータや ROI の取得に加え、分析結果を注釈としてサーバーへ書き戻せます。

主な機能

  1. 01プロジェクト、データセット、画像の階層表示
  2. 02画像プレーンやタイルを NumPy 配列で取得
  3. 03タグとキー・バリュー注釈の管理
  4. 04画像 ROI 形状の読み取り
  5. 05メタデータによる画像検索

活用シーン

  1. 01OMERO から画像を取得して Python 分析
  2. 02画像へ QC タグや結果を一括付与
  3. 03下流の定量分析向けに ROI を読み取り
  4. 04分析パラメーターを注釈として記録

インストール

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

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill omero-integration

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

詳細

omero-integration

概要

OMERO は、顕微鏡施設やコアラボで広く使用されているオープンソースの画像データ管理システムです。omero-py ライブラリは、OMERO サーバーに接続する Python クライアント(BlitzGateway)を提供し、画像、データセット、プロジェクト、タグ、アノテーション、ROI にプログラムからアクセスできるようにします。これを使用して、OMERO から画像を取得し、Python で処理して、結果をアノテーションとして書き戻す自動解析ワークフローを構築できます。

使用する場面

  • OMERO からのプログラムによる画像取得:OMERO Insight GUI を使わずに、後続の解析用に顕微鏡画像を numpy 配列としてダウンロードします。
  • 一括アノテーションとタグ付け:解析結果に基づいて、多数の画像やデータセットにタグ、キーと値のペアのアノテーション、またはコメントを適用します。
  • ROI へのアクセスと管理:後続の定量化やエクスポート用に、OMERO に保存されたセグメンテーション ROI(シェイプ)を読み取ります。
  • OMERO と Python 解析パイプラインの統合:OMERO の画像データを scikit-image、OpenCV、CellPose、その他の画像解析ツールに接続します。
  • 自動 QC ワークフロー:メタデータ(チャネル、取得日、実験者)で画像を検索し、品質基準を満たさない画像にフラグを付けます。
  • データの来歴の追跡:解析の来歴(パラメーター、ツールのバージョン)を、構造化されたキーと値のアノテーションとして画像に付加します。
  • OMERO サーバーを使用しないローカル画像解析には、tifffile、aicsimageio、または imageio を直接使用してください。

前提条件

  • Python パッケージ:omero-py、numpy、Pillow
  • システム:Java 8 以降(omero-py の内部処理に必要)、Ice 3.6(conda 経由で自動的にインストールされます)
  • データ要件:稼働中の OMERO サーバーへのアクセス認証情報(ホスト、ポート、ユーザー名、パスワード)
  • 環境:Conda を強く推奨します。omero-py には複雑な依存関係があります。
conda create -n omero python=3.9
conda activate omero
conda install -c ome -c conda-forge omero-py
pip install numpy Pillow

クイックスタート

import omero
from omero.gateway import BlitzGateway

# Connect to OMERO server
conn = BlitzGateway("username", "password", host="omero.example.org", port=4064)
conn.connect()
print(f"Connected: {conn.isConnected()}, user: {conn.getUser().getName()}")

# Get an image by ID and download as numpy array
image = conn.getObject("Image", 12345)
pixels = image.getPrimaryPixels()
plane = pixels.getPlane(0, 0, 0)   # z=0, c=0, t=0
print(f"Image shape: {plane.shape}, dtype: {plane.dtype}")

conn.close()

コア API

モジュール 1:BlitzGateway — 接続管理

BlitzGateway は、サーバーとのすべてのやり取りの主要なエントリーポイントです。

from omero.gateway import BlitzGateway

# Establish connection
conn = BlitzGateway(
    username="user",
    passwd="password",
    host="omero.example.org",
    port=4064,
    secure=True,
)
success = conn.connect()
print(f"Connected: {success}")
print(f"Server version: {conn.getServerVersion()}")
print(f"Current group: {conn.getGroupFromContext().getName()}")

# Always close when done
conn.close()
# Context manager pattern for automatic cleanup
class OmeroConnection:
    def __init__(self, **kwargs):
        self.conn = BlitzGateway(**kwargs)
    def __enter__(self):
        self.conn.connect()
        return self.conn
    def __exit__(self, *args):
        self.conn.close()

with OmeroConnection(username="user", passwd="pass",
                     host="omero.example.org", port=4064) as conn:
    print(f"Connected as: {conn.getUser().getFullName()}")
モジュール 2:プロジェクト、データセット、画像の検索

OMERO のデータ階層(プロジェクト → データセット → 画像)をたどります。

# List all projects for the current user
for project in conn.listProjects():
    print(f"Project {project.getId()}: {project.getName()}")
    for dataset in project.listChildren():
        print(f"  Dataset {dataset.getId()}: {dataset.getName()}")
        for image in dataset.listChildren():
            print(f"    Image {image.getId()}: {image.getName()}")
# Search for images by name
results = conn.searchObjects(["Image"], "GFP_control")
for img in results:
    print(f"  Found: {img.getId()} - {img.getName()}")

# Get a specific object by ID
image   = conn.getObject("Image",   12345)
dataset = conn.getObject("Dataset", 678)
project = conn.getObject("Project", 90)
print(f"Image: {image.getName()}, size: {image.getSizeX()}x{image.getSizeY()}")
print(f"Channels: {image.getSizeC()}, Z-slices: {image.getSizeZ()}, timepoints: {image.getSizeT()}")
モジュール 3:画像を NumPy 配列としてダウンロード

処理用にピクセルデータを numpy 配列として取得します。

import numpy as np

image  = conn.getObject("Image", 12345)
pixels = image.getPrimaryPixels()

# Get a single 2D plane: getPlane(z_index, channel_index, time_index)
plane = pixels.getPlane(0, 0, 0)
print(f"Plane shape: {plane.shape}, dtype: {plane.dtype}")

# Get all channels at z=0, t=0
planes = [pixels.getPlane(0, c, 0) for c in range(image.getSizeC())]
stack  = np.stack(planes, axis=0)   # shape: (C, Y, X)
print(f"Multi-channel stack: {stack.shape}")
# Efficient bulk download using getTiles (for large images)
image  = conn.getObject("Image", 12345)
pixels = image.getPrimaryPixels()

tile_coords = [(0, 0, 0, (0, 0, 512, 512))]  # (z, c, t, (x, y, w, h))
for tile in pixels.getTiles(tile_coords):
    print(f"Tile shape: {tile.shape}")  # (512, 512) numpy array
モジュール 4:タグとアノテーションの管理

OMERO オブジェクトのタグとキーと値のペアのアノテーションを追加、取得、更新します。

import omero

# Add a tag to an image
tag_ann = omero.gateway.TagAnnotationWrapper(conn)
tag_ann.setValue("passed_QC")
tag_ann.setNs("my.analysis.namespace")
tag_ann.save()

image = conn.getObject("Image", 12345)
image.linkAnnotation(tag_ann)
print(f"Tag '{tag_ann.getValue()}' linked to image {image.getId()}")
# Add key-value pairs (MapAnnotation) to an image
map_ann = omero.gateway.MapAnnotationWrapper(conn)
map_ann.setNs("openmicroscopy.org/omero/client/mapAnnotation")
kv_pairs = [
    ["analysis_tool",    "CellProfiler 4.2"],
    ["cell_count",       "342"],
    ["mean_intensity",   "1847.3"],
    ["analysis_date",    "2026-02-18"],
]
map_ann.setValue(kv_pairs)
map_ann.save()
image.linkAnnotation(map_ann)
print(f"Key-value annotation attached to image {image.getId()}")

# Read existing annotations
for ann in image.listAnnotations():
    print(f"  {ann.OMERO_TYPE}: {ann.getValue()}")
モジュール 5:ROI へのアクセス

後続の定量化用に、OMERO に保存されたセグメンテーション ROI(シェイプ)を読み取ります。

from omero.model import RoiI

# Get all ROIs for an image
roi_service = conn.getRoiService()
result = roi_service.findByImage(12345, None)

for roi in result.rois:
    for shape in roi.copyShapes():
        shape_type = shape.__class__.__name__
        print(f"  ROI {roi.id.val}: {shape_type}")
        if shape_type == "RectangleI":
            print(f"    x={shape.x.val:.1f}, y={shape.y.val:.1f}, "
                  f"w={shape.width.val:.1f}, h={shape.height.val:.1f}")
        elif shape_type == "EllipseI":
            print(f"    cx={shape.x.val:.1f}, cy={shape.y.val:.1f}, "
                  f"rx={shape.radiusX.val:.1f}, ry={shape.radiusY.val:.1f}")
# Convert ROI masks to numpy boolean arrays
import numpy as np
from omero.gateway import BlitzGateway

def roi_to_mask(shape, height, width):
    """Convert a rectangle ROI to a boolean numpy mask."""
    mask = np.zeros((height, width), dtype=bool)
    x  = int(shape.x.val)
    y  = int(shape.y.val)
    w  = int(shape.width.val)
    h  = int(shape.height.val)
    mask[y:y+h, x:x+w] = True
    return mask

image  = conn.getObject("Image", 12345)
height = image.getSizeY()
width  = image.getSizeX()

result = conn.getRoiService().findByImage(12345, None)
for roi in result.rois:
    for shape in roi.copyShapes():
        if shape.__class__.__name__ == "RectangleI":
            mask = roi_to_mask(shape, height, width)
            print(f"ROI mask: {mask.sum()} pixels selected")

主要な概念

OMERO のデータ階層

OMERO はデータをプロジェクト → データセット → 画像として整理します。画像にはピクセルデータとメタデータ(チャネル、Z スライス、タイムポイント)が含まれます。アノテーション(タグ、キーと値のペア、コメント)は、階層のどのレベルにも付加できます。

# Hierarchy navigation
project = conn.getObject("Project", 90)
for dataset in project.listChildren():
    imgs = list(dataset.listChildren())
    print(f"Dataset '{dataset.getName()}': {len(imgs)} images")
ピクセルへのアクセスパターン

OMERO はピクセルを(Z、C、T)のスタックとして保存します。getPlane(z, c, t) は単一の 2D numpy 配列を返します。大きな画像には、getTiles を使用して空間的な部分領域をダウンロードします。ピクセルの型(uint8、uint16、float32)は元の取得形式と一致します。

image  = conn.getObject("Image", 12345)
pixels = image.getPrimaryPixels()
ptype  = pixels.getPixelsType().getValue()
print(f"Pixel type: {ptype}")  # e.g., "uint16"
print(f"Dimensions: XY={image.getSizeX()}x{image.getSizeY()}, "
      f"Z={image.getSizeZ()}, C={image.getSizeC()}, T={image.getSizeT()}")

一般的なワークフロー

ワークフロー 1:一括ダウンロードと解析

目標:データセット内のすべての画像をダウンロードして処理を適用し、結果をキーと値のアノテーションとして保存します。

import numpy as np
from omero.gateway import BlitzGateway, MapAnnotationWrapper

def mean_intensity(plane):
    return float(plane.mean())

conn = BlitzGateway("user", "pass", host="omero.example.org", port=4064)
conn.connect()

dataset = conn.getObject("Dataset", 678)
results = []

for image in dataset.listChildren():
    pixels = image.getPrimaryPixels()
    plane  = pixels.getPlane(0, 0, 0)         # first z, channel 0, t=0
    mi     = mean_intensity(plane)
    results.append((image, mi))

    # Attach mean intensity as key-value annotation
    ann = MapAnnotationWrapper(conn)
    ann.setNs("my.pipeline.v1")
    ann.setValue([["mean_intensity_ch0", f"{mi:.2f}"]])
    ann.save()
    image.linkAnnotation(ann)
    print(f"Image {image.getId()} '{image.getName()}': mean={mi:.2f}")

print(f"\nProcessed {len(results)} images in dataset '{dataset.getName()}'")
conn.close()
ワークフロー 2:タグで画像を取得してエクスポート

目標:"screen_hits" タグが付いたすべての画像を検索し、チャネル 1 を numpy 配列としてダウンロードして、TIFF ファイルとして保存します。

import numpy as np
import tifffile
from omero.gateway import BlitzGateway

conn = BlitzGateway("user", "pass", host="omero.example.org", port=4064)
conn.connect()

# Find images with a specific tag
tag_value = "screen_hits"
tagged_images = []
for ann in conn.getObjects("TagAnnotation", attributes={"textValue": tag_value}):
    for image in ann.listLinkedObjects(["Image"]):
        tagged_images.append(image)

print(f"Found {len(tagged_images)} images tagged '{tag_value}'")

for image in tagged_images:
    pixels = image.getPrimaryPixels()
    # Download DAPI channel (index 0) at z=0, t=0
    plane  = pixels.getPlane(0, 0, 0)
    fname  = f"image_{image.getId()}_DAPI.tif"
    tifffile.imwrite(fname, plane)
    print(f"Saved {fname}: shape={plane.shape}, dtype={plane.dtype}")

conn.close()
print("Export complete")

主要なパラメーター

パラメーターモジュールデフォルト範囲/オプション効果
hostBlitzGateway必須ホスト名または IPOMERO サーバーのアドレス
portBlitzGateway40641024–65535OMERO サーバーのポート(4064 は標準)
secureBlitzGatewayFalseTrue、FalseSSL/TLS で暗号化された接続を使用します
z, c, tgetPlane0, 0, 00 – size-1Z スライス、チャネル、時間点のインデックス
tile_coordsgetTiles—(z,c,t,(x,y,w,h)) のリスト空間部分領域のダウンロード座標
NsannotationsNone任意の URI 文字列アノテーションのフィルタリングに使用する名前空間

ベストプラクティス

  1. 接続は必ず閉じてください:すべての操作の後に conn.close() を呼び出すか、コンテキストマネージャーを使用します。接続を閉じないとサーバーリソースを消費し、セッションタイムアウトの原因になることがあります。

  2. アノテーションには名前空間を使用してください:作成するすべてのアノテーションに一意の Ns(名前空間 URI)を設定すると、プログラムで作成したアノテーションを手動で作成したものや他のツールのものと区別できます。

  3. 必要なプレーンだけをダウンロードしてください:大きなタイムラプス画像や Z スタック画像では、すべてのプレーンをダウンロードするのではなく、特定のインデックスを指定して getPlane(z, c, t) を使用します。空間部分領域には getTiles を使用します。

  4. アノテーションの書き込みをまとめて、サーバーとの往復を減らしてください:画像ごとに個別の RPC 呼び出しを行うのではなく、複数の画像にわたるキーと値のペアを収集し、ループ内で書き込みます。

  5. 処理前に画像の寸法を確認してください:予期しない形状のデータセットでインデックスが範囲外になるエラーを避けるため、ピクセルデータにアクセスする前に必ず getSizeX()、getSizeY()、getSizeC()、getSizeZ()、getSizeT() を読み取ります。

よく使われるレシピ

レシピ:画像上のすべてのタグを一覧表示する

使用場面:重複を避けるため、新しいアノテーションを追加する前に既存のアノテーションを確認します。

image = conn.getObject("Image", 12345)
for ann in image.listAnnotations():
    if ann.OMERO_TYPE == "TagAnnotation":
        print(f"  Tag: '{ann.getValue()}' (ns={ann.getNs()})")
    elif ann.OMERO_TYPE == "MapAnnotation":
        for k, v in ann.getValue():
            print(f"  KV: {k} = {v}")
レシピ:マルチチャネルの最大値投影

使用場面:指定したチャネルについて、すべての Z スライスにわたる最大強度投影を作成します。

import numpy as np

def max_projection(image, channel=0, timepoint=0):
    pixels = image.getPrimaryPixels()
    planes = [pixels.getPlane(z, channel, timepoint)
              for z in range(image.getSizeZ())]
    stack  = np.stack(planes, axis=0)
    return stack.max(axis=0)

image = conn.getObject("Image", 12345)
proj  = max_projection(image, channel=1)
print(f"Max projection shape: {proj.shape}, max value: {proj.max()}")

想定される出力

  • getPlane() からの NumPy 配列:形状 (Y, X)、取得データに応じた dtype(uint8、uint16、float32)
  • マルチチャネルスタック:プレーンをスタックした場合の形状 (C, Y, X)
  • 画像に付加されたアノテーション。OMERO.web および OMERO Insight GUI で表示できます
  • ROI 形状。座標属性を持つ omero.model オブジェクトとして返されます

トラブルシューティング

問題原因解決策
Ice.ConnectionRefusedExceptionホスト/ポートが誤っているか、サーバーが停止していますhost と port=4064 を確認し、サーバーが実行中であることを確認します
omero.SecurityViolationオブジェクトに対する権限が不足していますグループメンバーシップを確認し、サーバー管理者にアクセス権の付与を依頼します
ImportError: omeroconda 経由で omero-py がインストールされていませんconda install -c ome -c conda-forge omero-py を使用します。pip によるインストールは信頼性が低いです
AttributeError: 'NoneType' objectオブジェクト ID がサーバー上に見つかりませんconn.getObject(type, id) が None 以外を返すことを確認し、オブジェクトの存在を確認します
Ice.MemoryLimitException非常に大きな画像を一度にダウンロードしています空間部分領域には getTiles() を、スライスごとの取得には getPlane() を使用します
ダウンロード速度が遅い小さなプレーンを多数、順次ダウンロードしていますすべての座標のリストを指定して getTiles() を使用し、一括でダウンロードします
実行途中にセッションがタイムアウトする長時間の分析がサーバーのアイドルタイムアウトを超えています長いループ内で定期的に conn.keepAlive() を呼び出します

参考資料

コメント