Skip to content
Data
Skill

/bio-imaging-mass-cytometry-interactive-annotation

Interactive cell type annotation for IMC data. Covers napari-based annotation, marker-guided labeling, training data generation, and annotation validation. Use when manually annotating cell types for training classifiers or validating automated phenotyping results.

From plugin
openclaw-medical-skills
2.9k200 skills
Install
$ npx -y skills add FreedomIntelligence/OpenClaw-Medical-Skills --skill bio-imaging-mass-cytometry-interactive-annotation --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/bio-imaging-mass-cytometry-interactive-annotation

Context preview

The summary Claude sees to decide when to auto-load this skill.

Interactive cell type annotation for IMC data. Covers napari-based annotation, marker-guided labeling, training data generation, and annotation validation. Use when manually annotating cell types for training classifiers or validating automated phenotyping results.

SKILL.md

bio-imaging-mass-cytometry-interactive-annotation.SKILL.md
name: bio-imaging-mass-cytometry-interactive-annotation
description: Interactive cell type annotation for IMC data. Covers napari-based annotation, marker-guided labeling, training data generation, and annotation validation. Use when manually annotating cell types for training classifiers or validating automated phenotyping results.
tool_type: python
primary_tool: napari

Version Compatibility

Reference examples tested with: matplotlib 3.8+, numpy 1.26+, pandas 2.2+, scikit-learn 1.4+

Before using code patterns, verify installed versions match. If versions differ:

  • Python: `pip show <package>` then `help(module.function)` to check signatures

If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.

Interactive Annotation

**"Manually annotate cell types in my IMC data"** → Interactively label cells using napari visualization with marker overlays for training classifiers or validating automated phenotyping results.

  • Python: `napari.Viewer()` with label layer for interactive annotation

Napari-Based Annotation

import napari
import numpy as np
from skimage import io
import pandas as pd

# Load IMC image stack
image_stack = io.imread('imc_image.tiff')  # (C, H, W)
segmentation_mask = io.imread('cell_segmentation.tiff')

# Create napari viewer
viewer = napari.Viewer()

# Add channels as separate layers for visualization
channel_names = ['CD45', 'CD3', 'CD68', 'panCK', 'DNA']
for i, name in enumerate(channel_names):
    viewer.add_image(image_stack[i], name=name, visible=False, colormap='gray', blending='additive')

# Add segmentation
viewer.add_labels(segmentation_mask, name='Cells')

# Add annotation layer (start empty)
annotation_layer = viewer.add_labels(
    np.zeros_like(segmentation_mask),
    name='Cell_Types'
)

# Define cell types
cell_type_mapping = {1: 'T_cell', 2: 'Macrophage', 3: 'Epithelial', 4: 'Stromal', 5: 'Other'}

Marker-Guided Annotation

def create_marker_overlay(image_stack, channel_indices, colors):
    '''Create RGB overlay of selected markers for easier annotation.'''
    h, w = image_stack.shape[1:]
    overlay = np.zeros((h, w, 3), dtype=np.float32)

    for idx, color in zip(channel_indices, colors):
        channel = image_stack[idx].astype(np.float32)
        channel = (channel - channel.min()) / (channel.max() - channel.min() + 1e-8)
        for c, weight in enumerate(color):
            overlay[:, :, c] += channel * weight

    overlay = np.clip(overlay, 0, 1)
    return overlay

# Create T cell overlay (CD3=green, CD45=blue)
t_cell_overlay = create_marker_overlay(
    image_stack,
    channel_indices=[0, 1],  # CD45, CD3
    colors=[[0, 0, 1], [0, 1, 0]]  # Blue, Green
)

# Create tumor overlay (panCK=red)
tumor_overlay = create_marker_overlay(
    image_stack,
    channel_indices=[3],  # panCK
    colors=[[1, 0, 0]]  # Red
)

# Add overlays to viewer
viewer.add_image(t_cell_overlay, name='T_cell_markers', visible=True)
viewer.add_image(tumor_overlay, name='Tumor_markers', visible=False)

Training Data Generation

def extract_training_data(image_stack, segmentation_mask, annotation_mask, channel_names):
    '''Extract mean marker intensities per cell with annotations.'''
    from skimage.measure import regionprops_table

    cells = []
    for cell_id in np.unique(segmentation_mask):
        if cell_id == 0:
            continue

        cell_mask = segmentation_mask == cell_id
        annotation = annotation_mask[cell_mask]
        annotation = annotation[annotation > 0]

        if len(annotation) == 0:
            continue

        cell_type = int(np.median(annotation))

        cell_data = {'cell_id': cell_id, 'cell_type': cell_type}
        for i, name in enumerate(channel_names):
            cell_data[name] = np.mean(image_stack[i][cell_mask])

        cells.append(cell_data)

    return pd.DataFrame(cells)

# After manual annotation in napari
annotation_data = annotation_layer.data
training_df = extract_training_data(image_stack, segmentation_mask, annotation_data, channel_names)
training_df.to_csv('training_annotations.csv', index=False)
print(f'Annotated {len(training_df)} cells')
print(training_df['cell_type'].value_counts())

Semi-Automated Annotation

**Goal:** Propagate a small set of manual cell type annotations to all unannotated cells using marker expression similarity.

**Approach:** Train a k-nearest-neighbors classifier on manually annotated cells' marker intensities, predict labels for remaining cells, and report classification confidence to flag uncertain assignments for review.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

def propagate_annotations(training_df, all_cells_df, marker_columns):
    '''Use annotated cells to classify unannotated cells.'''
    X_train = training_df[marker_columns].values
    y_train = training_df['cell_type'].values

    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)

    knn = KNeighborsClassifier(n_neighbors=5)
    knn.fit(X_train_scaled, y_train)

    unannotated = all_cells_df[~all_cells_df['cell_id'].isin(training_df['cell_id'])]
    X_test = scaler.transform(unannotated[marker_columns].values)

    predictions = knn.predict(X_test)
    probabilities = knn.predict_proba(X_test)
    confidence = np.max(probabilities, axis=1)

    unannotated = unannotated.copy()
    unannotated['predicted_type'] = predictions
    unannotated['confidence'] = confidence

    return unannotated

marker_cols = ['CD45', 'CD3', 'CD68', 'panCK']
predictions = propagate_annotations(training_df, all_cells_df, marker_cols)

high_conf = predictions[predictions['confidence'] > 0.8]
print(f'{len(high_conf)} cells classified with high confidence')

Annotation Validation

def validate_annotations(annotation_df, image_stack, segmentation_mask, channel_name
Read more
Ships withopenclaw-medical-skills

The largest open-source medical AI skill library for OpenClaw.

Get the whole plugin
Stats
2,921
Stars
410
Forks
Active
Maintenance
Python
Language
20d ago
Last commit
5mo ago
Created

Repo: FreedomIntelligence/OpenClaw-Medical-Skills