一键导入
annotation-validation
annotation-validation skill
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
annotation-validation skill
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Long autonomous task execution with iteration control. Use for multi-hour refactors, TDD workflows, batch operations, or any task requiring sustained autonomous work.
Persistent memory system across Codex sessions. Use when you need to remember facts, recall information, or maintain context between sessions.
Create, manage, and merge git worktrees for parallel development. Use when starting parallel features, running multiple Codex instances, or for isolated development.
3p-updates skill
Web accessibility specialist for WCAG compliance, ARIA implementation, and inclusive design. Use when auditing websites for accessibility issues, implementing WCAG 2.1 AA/AAA standards, testing with screen readers, or ensuring ADA compliance. Expert in semantic HTML, keyboard navigation, and assistive technology compatibility.
Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding assays, expression testing, thermostability measurements, enzyme activity assays, or protein sequence optimization. Also use for submitting experiments via API, tracking experiment status, downloading results, optimizing protein sequences for better expression using computational tools (NetSolP, SoluProt, SolubleMPNN, ESM), or managing protein design workflows with wet-lab validation.
| name | annotation-validation |
| description | annotation-validation skill |
| metadata | {"short-description":"annotation-validation skill","category":"utilities","source":"claude-code-templates"} |
This document covers data curation, validation, schema management, and annotation best practices in LaminDB.
LaminDB's curation process ensures datasets are both validated and queryable through three essential steps:
Schemas define expected data structure, types, and validation rules. LaminDB supports three main schema approaches:
Validates only columns matching Feature registry names, allowing additional metadata:
import lamindb as ln
# Create flexible schema
schema = ln.Schema(
name="valid_features",
itype=ln.Feature # Validates against Feature registry
).save()
# Any column matching a Feature name will be validated
# Additional columns are permitted but not validated
Specifies essential columns while permitting extra metadata:
# Define required features
required_features = [
ln.Feature.get(name="cell_type"),
ln.Feature.get(name="tissue"),
ln.Feature.get(name="donor_id")
]
# Create schema with required features
schema = ln.Schema(
name="minimal_immune_schema",
features=required_features,
flexible=True # Allows additional columns
).save()
Enforces complete control over data structure:
# Define all allowed features
all_features = [
ln.Feature.get(name="cell_type"),
ln.Feature.get(name="tissue"),
ln.Feature.get(name="donor_id"),
ln.Feature.get(name="disease")
]
# Create strict schema
schema = ln.Schema(
name="strict_immune_schema",
features=all_features,
flexible=False # No additional columns allowed
).save()
The typical curation process involves six key steps:
import pandas as pd
import lamindb as ln
# Load data
df = pd.read_csv("experiment.csv")
# Define and save features
ln.Feature(name="cell_type", dtype=str).save()
ln.Feature(name="tissue", dtype=str).save()
ln.Feature(name="gene_count", dtype=int).save()
ln.Feature(name="experiment_date", dtype="date").save()
# Populate valid values (if using controlled vocabulary)
import bionty as bt
bt.CellType.import_source()
bt.Tissue.import_source()
# Link features to schema
features = [
ln.Feature.get(name="cell_type"),
ln.Feature.get(name="tissue"),
ln.Feature.get(name="gene_count"),
ln.Feature.get(name="experiment_date")
]
schema = ln.Schema(
name="experiment_schema",
features=features,
flexible=True
).save()
# Initialize curator
curator = ln.curators.DataFrameCurator(df, schema)
# Validate dataset
validation = curator.validate()
# Check validation results
if validation:
print("✓ Validation passed")
else:
print("✗ Validation failed")
curator.non_validated # See problematic fields
# Fix typos and synonyms in categorical columns
curator.cat.standardize("cell_type")
curator.cat.standardize("tissue")
# View standardization mapping
curator.cat.inspect_standardize("cell_type")
# Map values to ontology terms
curator.cat.add_ontology("cell_type", bt.CellType)
curator.cat.add_ontology("tissue", bt.Tissue)
# Look up public ontologies for unmapped terms
curator.cat.lookup(public=True).cell_type # Interactive lookup
# Add new valid terms to registry
curator.cat.add_new_from("cell_type")
# Or manually create records
new_cell_type = bt.CellType(name="my_novel_cell_type").save()
# Rename columns to match feature names
df = df.rename(columns={"celltype": "cell_type"})
# Re-initialize curator with fixed DataFrame
curator = ln.curators.DataFrameCurator(df, schema)
# Save with schema linkage
artifact = curator.save_artifact(
key="experiments/curated_data.parquet",
description="Validated and annotated experimental data"
)
# Verify artifact has schema
artifact.schema # Returns the schema object
artifact.describe() # Shows validation status
For composite structures like AnnData, use "slots" to validate different components:
# Create schemas for different slots
obs_schema = ln.Schema(
name="cell_metadata",
features=[
ln.Feature.get(name="cell_type"),
ln.Feature.get(name="tissue"),
ln.Feature.get(name="donor_id")
]
).save()
var_schema = ln.Schema(
name="gene_ids",
features=[ln.Feature.get(name="ensembl_gene_id")]
).save()
# Create composite AnnData schema
anndata_schema = ln.Schema(
name="scrna_schema",
otype="AnnData",
slots={
"obs": obs_schema,
"var.T": var_schema # .T indicates transposition
}
).save()
import anndata as ad
# Load AnnData
adata = ad.read_h5ad("data.h5ad")
# Initialize curator
curator = ln.curators.AnnDataCurator(adata, anndata_schema)
# Validate all slots
validation = curator.validate()
# Fix issues by slot
curator.cat.standardize("obs", "cell_type")
curator.cat.add_ontology("obs", "cell_type", bt.CellType)
curator.cat.standardize("var.T", "ensembl_gene_id")
# Save curated artifact
artifact = curator.save_artifact(
key="scrna/validated_data.h5ad",
description="Curated single-cell RNA-seq data"
)
MuData supports multi-modal data through modality-specific slots:
# Define schemas for each modality
rna_obs_schema = ln.Schema(name="rna_obs_schema", features=[...]).save()
protein_obs_schema = ln.Schema(name="protein_obs_schema", features=[...]).save()
# Create MuData schema
mudata_schema = ln.Schema(
name="multimodal_schema",
otype="MuData",
slots={
"rna:obs": rna_obs_schema,
"protein:obs": protein_obs_schema
}
).save()
# Curate
curator = ln.curators.MuDataCurator(mdata, mudata_schema)
curator.validate()
For spatial transcriptomics data:
# Define spatial schema
spatial_schema = ln.Schema(
name="spatial_schema",
otype="SpatialData",
slots={
"tables:cell_metadata.obs": cell_schema,
"attrs:bio": bio_metadata_schema
}
).save()
# Curate
curator = ln.curators.SpatialDataCurator(sdata, spatial_schema)
curator.validate()
For scalable array-backed data:
# Define SOMA schema
soma_schema = ln.Schema(
name="soma_schema",
otype="tiledbsoma",
slots={
"obs": obs_schema,
"ms:RNA.T": var_schema # measurement:modality.T
}
).save()
# Curate
curator = ln.curators.TileDBSOMACurator(soma_exp, soma_schema)
curator.validate()
# Define typed features
ln.Feature(name="age", dtype=int).save()
ln.Feature(name="weight", dtype=float).save()
ln.Feature(name="is_treated", dtype=bool).save()
ln.Feature(name="collection_date", dtype="date").save()
# Coerce types during validation
ln.Feature(name="age_str", dtype=int, coerce_dtype=True).save() # Auto-convert strings to int
# Validate against allowed values
cell_type_feature = ln.Feature(name="cell_type", dtype=str).save()
# Link to registry for controlled vocabulary
cell_type_feature.link_to_registry(bt.CellType)
# Now validation checks against CellType registry
curator = ln.curators.DataFrameCurator(df, schema)
curator.validate() # Errors if cell_type values not in registry
# Look up standardized terms from public sources
curator.cat.lookup(public=True).cell_type
# Returns auto-complete object with public ontology terms
# User can select correct term interactively
# Add synonyms to records
t_cell = bt.CellType.get(name="T cell")
t_cell.add_synonym("T lymphocyte")
t_cell.add_synonym("T-cell")
# Now standardization maps synonyms automatically
curator.cat.standardize("cell_type")
# "T lymphocyte" → "T cell"
# "T-cell" → "T cell"
# Manual mapping
mapping = {
"TCell": "T cell",
"t cell": "T cell",
"T-cells": "T cell"
}
# Apply mapping
df["cell_type"] = df["cell_type"].map(lambda x: mapping.get(x, x))
Issue: Column not in schema
# Solution 1: Rename column
df = df.rename(columns={"old_name": "feature_name"})
# Solution 2: Add feature to schema
new_feature = ln.Feature(name="new_column", dtype=str).save()
schema.features.add(new_feature)
Issue: Invalid values
# Solution 1: Standardize
curator.cat.standardize("column_name")
# Solution 2: Add new valid values
curator.cat.add_new_from("column_name")
# Solution 3: Map to ontology
curator.cat.add_ontology("column_name", bt.Registry)
Issue: Data type mismatch
# Solution 1: Convert data type
df["column"] = df["column"].astype(int)
# Solution 2: Enable coercion in feature
feature = ln.Feature.get(name="column")
feature.coerce_dtype = True
feature.save()
Schemas can be versioned like other records:
# Create initial schema
schema_v1 = ln.Schema(name="experiment_schema", features=[...]).save()
# Update schema with new features
schema_v2 = ln.Schema(
name="experiment_schema",
features=[...], # Updated list
version="2"
).save()
# Link artifacts to specific schema versions
artifact.schema = schema_v2
artifact.save()
Once data is validated and annotated, it becomes queryable:
# Find all validated artifacts
ln.Artifact.filter(is_valid=True).to_dataframe()
# Find artifacts with specific schema
ln.Artifact.filter(schema=schema).to_dataframe()
# Query by annotated features
ln.Artifact.filter(cell_type="T cell", tissue="blood").to_dataframe()
# Include features in results
ln.Artifact.filter(is_valid=True).to_dataframe(include="features")
Create custom validation logic:
def validate_gene_expression(df):
"""Custom validator for gene expression values."""
# Check non-negative
if (df < 0).any().any():
return False, "Negative expression values found"
# Check reasonable range
if (df > 1e6).any().any():
return False, "Unreasonably high expression values"
return True, "Valid"
# Apply during curation
is_valid, message = validate_gene_expression(df)
if not is_valid:
print(f"Validation failed: {message}")
# Curated artifacts track curation lineage
ln.track() # Start tracking
# Perform curation
curator = ln.curators.DataFrameCurator(df, schema)
curator.validate()
curator.cat.standardize("cell_type")
artifact = curator.save_artifact(key="curated.parquet")
ln.finish() # Complete tracking
# View curation lineage
artifact.run.describe() # Shows curation transform
artifact.view_lineage() # Visualizes curation process
Invoke this skill with:
$annotation-validation [arguments]
Or let Codex auto-select based on your prompt.