ワンクリックで
genomics
Genomics and transcriptomics analysis strategies
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Genomics and transcriptomics analysis strategies
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Reference of available Phenix commands for structural biology analysis
Interpret statistical results and decide what to do next
Skills for querying the JGI Dremio Lakehouse containing GOLD and IMG genomics databases. Use this when users want to explore JGI databases, query GOLD (Genomes OnLine Database), IMG (Integrated Microbial Genomes), or run SQL queries against JGI genomics data. Triggers on mentions of JGI, GOLD database, IMG database, genome metadata, or JGI lakehouse queries.
Skills for querying the KBase/BERDL Datalake via the MCP REST API. Use this when users want to explore KBase databases, list tables, get schemas, sample data, or run SQL queries against the KBase data lake. Triggers on mentions of KBase, BERDL, or requests to query biological/microbiome data stored in KBase.
Statistical analysis strategies and data exploration techniques
Metabolomics-specific analysis strategies and domain knowledge
| name | genomics |
| description | Genomics and transcriptomics analysis strategies |
| category | domain |
RNA-seq counts:
Microarray intensities:
Single-cell RNA-seq:
Human genes:
Mouse genes:
Protein names:
Always verify gene symbols - aliases and outdated names are common.
import pandas as pd
import numpy as np
from scipy.stats import ttest_ind
from statsmodels.stats.multitest import multipletests
# Load expression data (genes × samples)
# Rows = genes, Columns = samples
expr_data = pd.read_csv("expression_data.csv", index_col=0)
# Define groups
group1_samples = ["Sample1", "Sample2", "Sample3"]
group2_samples = ["Sample4", "Sample5", "Sample6"]
results = []
for gene in expr_data.index:
group1_expr = expr_data.loc[gene, group1_samples]
group2_expr = expr_data.loc[gene, group2_samples]
# T-test
t_stat, p_value = ttest_ind(group1_expr, group2_expr)
# Fold change
mean1 = group1_expr.mean()
mean2 = group2_expr.mean()
log2fc = np.log2(mean1 / mean2) if mean2 > 0 else np.nan
results.append({
"gene": gene,
"log2FC": log2fc,
"p_value": p_value,
"mean_group1": mean1,
"mean_group2": mean2
})
results_df = pd.DataFrame(results)
# Multiple testing correction
results_df["p_adj"] = multipletests(results_df["p_value"], method="fdr_bh")[1]
# Define significant genes
significant = results_df[
(results_df["p_adj"] < 0.05) &
(abs(results_df["log2FC"]) > 1) # 2-fold change
]
print(f"Significant genes: {len(significant)}")
print(f"Upregulated: {sum(significant['log2FC'] > 0)}")
print(f"Downregulated: {sum(significant['log2FC'] < 0)}")
Visualize differential expression:
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
plt.scatter(
results_df["log2FC"],
-np.log10(results_df["p_adj"]),
alpha=0.5, s=10, c="gray"
)
# Highlight significant genes
sig_mask = (results_df["p_adj"] < 0.05) & (abs(results_df["log2FC"]) > 1)
plt.scatter(
results_df.loc[sig_mask, "log2FC"],
-np.log10(results_df.loc[sig_mask, "p_adj"]),
alpha=0.7, s=20, c="red", label="Significant"
)
plt.xlabel("log2 Fold Change")
plt.ylabel("-log10(adjusted p-value)")
plt.axhline(-np.log10(0.05), linestyle="--", color="black", linewidth=0.5)
plt.axvline(-1, linestyle="--", color="black", linewidth=0.5)
plt.axvline(1, linestyle="--", color="black", linewidth=0.5)
plt.title("Volcano Plot")
plt.legend()
plt.savefig("volcano_plot.png", dpi=300)
⚠️ The most common and most consequential error in single-cell DE. A typical single-cell experiment has many cells (tens of thousands) but few biological samples (a handful of patients or animals per condition). Cells from the same donor are not independent — they share genetic background, batch, dissociation and technical effects. The unit of replication is the sample/donor, not the cell.
Running a per-cell test (t-test, Wilcoxon, naive rank_genes_groups) and treating
each cell as a replicate silently inflates the effective n from ~6 samples to
~60,000 cells. This collapses the variance estimate and produces enormous
false-positive rates — naive cell-level tests call hundreds of "significant" genes
even when comparing two random splits of the same population, with highly
expressed genes flagged most often (Squair et al. 2021; Zimmerman et al. 2021).
When: Comparing a given cell type across conditions in a multi-sample design. This is the field-standard default and the top performer for FDR control in benchmarks (Squair et al. 2021; Murphy & Skene 2022; Junttila et al. 2022).
Sum raw counts across all cells of one cell type within each sample, then run a bulk DE tool (DESeq2/edgeR/limma-voom) on the resulting sample-level matrix. The statistics then reduce to the bulk RNA-seq workflow above, with an honest n.
import anndata as ad
import pandas as pd
# adata: cells × genes; obs has "sample_id", "cell_type", "condition"
adata = ad.read_h5ad("single_cell.h5ad")
# Aggregate raw counts -> one pseudobulk profile per sample, for one cell type
def pseudobulk(adata, cell_type):
sub = adata[adata.obs["cell_type"] == cell_type]
X = sub.X.toarray() if hasattr(sub.X, "toarray") else sub.X
counts = pd.DataFrame(X, index=sub.obs["sample_id"].values, columns=sub.var_names)
# SUM counts within each sample (not mean — DESeq2 expects counts)
return counts.groupby(level=0).sum() # samples × genes
pb = pseudobulk(adata, cell_type="Microglia")
# One metadata row per sample, aligned to the pseudobulk matrix
sample_meta = (
adata.obs[["sample_id", "condition"]]
.drop_duplicates()
.set_index("sample_id")
.loc[pb.index]
)
# DESeq2 on the sample-level matrix (n = number of samples, not cells)
from pydeseq2.dds import DeseqDataSet
from pydeseq2.ds import DeseqStats
dds = DeseqDataSet(counts=pb, metadata=sample_meta, design_factors="condition")
dds.deseq2()
res = DeseqStats(dds, contrast=["condition", "disease", "control"])
res.summary()
print(res.results_df.sort_values("padj").head())
muscat (R/Bioconductor; Crowell et al. 2020) implements this aggregation-based
workflow across all cell types at once if you prefer a turnkey tool.
When: You want to retain cell-level resolution, have a continuous/complex design, or aggregation would discard needed structure. A (generalized) linear mixed model with a random intercept per sample models the within-donor correlation directly (Zimmerman et al. 2021).
import statsmodels.formula.api as smf
# Long dataframe: one row per cell, columns "expression", "condition", "sample_id"
# The random intercept per sample absorbs donor-level correlation.
model = smf.mixedlm("expression ~ condition", data=cell_df, groups=cell_df["sample_id"])
result = model.fit()
print(result.summary()) # the fixed effect of `condition` is the test of interest
Tradeoffs: heavier compute, convergence/fitting fragility, and sensitivity to the assumed count distribution. In benchmarks weighing both sensitivity and specificity, pseudobulk generally matches or beats mixed models (Murphy & Skene 2022) — so prefer pseudobulk unless you have a specific reason.
Metacells (MetaCell, SEACells; Baran et al. 2019; Persad et al. 2023) pool transcriptionally similar cells within a sample to denoise sparse data and resolve fine-grained states. They are a within-sample representation tool and do not create independent biological replicates. Condition-level DE run on metacells still pseudoreplicates — you must still aggregate to the sample level (pseudobulk) or use donor random effects.
Power for condition-level DE scales with the number of independent samples, not the number of cells per sample. Aim for ≥3 samples per condition (more is better); adding cells per donor does not buy replication (Zimmerman et al. 2021; Heumos et al. 2023).
When: You have a list of significant genes and want to know which pathways are affected
# Define gene sets (pathways)
gene_sets = {
"Cell Cycle": ["TP53", "CDK1", "CCNB1", "CDC20", ...],
"Apoptosis": ["TP53", "BAX", "BCL2", "CASP3", ...],
"DNA Repair": ["TP53", "BRCA1", "BRCA2", "ATM", ...],
# ... more pathways
}
# Fisher's exact test for enrichment
from scipy.stats import fisher_exact
all_genes = set(expr_data.index)
sig_genes = set(significant["gene"])
enrichment_results = []
for pathway, pathway_genes in gene_sets.items():
pathway_genes = set(pathway_genes) & all_genes # Only genes in dataset
# 2x2 contingency table
a = len(sig_genes & pathway_genes) # Sig & in pathway
b = len(sig_genes - pathway_genes) # Sig & not in pathway
c = len(pathway_genes - sig_genes) # Not sig & in pathway
d = len(all_genes - sig_genes - pathway_genes) # Not sig & not in pathway
oddsratio, p_value = fisher_exact([[a, b], [c, d]], alternative='greater')
enrichment_results.append({
"pathway": pathway,
"overlap": a,
"pathway_size": len(pathway_genes),
"odds_ratio": oddsratio,
"p_value": p_value
})
enrich_df = pd.DataFrame(enrichment_results)
enrich_df["p_adj"] = multipletests(enrich_df["p_value"], method="fdr_bh")[1]
enrich_df = enrich_df.sort_values("p_adj")
print(enrich_df.head(10))
Common GO categories:
Resources:
KEGG = Kyoto Encyclopedia of Genes and Genomes
Provides curated pathway maps for:
Example pathways:
Observation: Many genes upregulated
Hypothesis: Shared transcription factor (TF)
Test:
# Check if significant genes share TF binding motifs
tf_targets = {
"TP53": ["BAX", "CDKN1A", "MDM2", "GADD45A", ...],
"MYC": ["CDK4", "CCND1", "E2F1", ...],
# ... more TFs
}
# Test for enrichment (same as pathway enrichment)
Interpretation: Enrichment suggests TF is active/inactive in condition
Observation: Genes in same pathway all up/down together
Interpretation: Pathway-level regulation (not individual genes)
Example:
All glycolysis genes ↑↑ → Increased glycolysis
All oxidative phosphorylation genes ↓↓ → Metabolic shift
Observation: Opposite regulation of related pathways
Example:
De novo biosynthesis genes ↓
Salvage pathway genes ↑
→ Metabolic switch to energy-efficient salvage
When: Identify genes that change together
from scipy.stats import pearsonr
# Compute pairwise correlations
genes = significant["gene"].tolist()[:50] # Top 50 for tractability
corr_matrix = expr_data.loc[genes].T.corr()
# Filter high correlations
high_corr = []
for i in range(len(genes)):
for j in range(i+1, len(genes)):
if abs(corr_matrix.iloc[i, j]) > 0.8:
high_corr.append({
"gene1": genes[i],
"gene2": genes[j],
"correlation": corr_matrix.iloc[i, j]
})
print(f"High correlations (|r| > 0.8): {len(high_corr)}")
Interpretation:
import networkx as nx
# Build network
G = nx.Graph()
for item in high_corr:
G.add_edge(item["gene1"], item["gene2"], weight=abs(item["correlation"]))
# Find communities (clusters of co-expressed genes)
from networkx.algorithms import community
communities = community.greedy_modularity_communities(G)
for i, comm in enumerate(communities):
print(f"Community {i}: {list(comm)}")
For gene function:
"[GENE] function"
"[GENE] role in [PROCESS]"
"[GENE] knockout phenotype"
For pathway context:
"[GENE] pathway"
"[GENE] interacting proteins"
"[GENE] regulation"
For disease relevance:
"[GENE] [DISEASE]"
"[GENE] mutation [DISEASE]"
H1: Transcriptional Regulation
"Condition X activates transcription factor [TF], upregulating
target genes [G1, G2, G3] in pathway [P]"
H2: Pathway Activation
"Condition X activates [pathway], evidenced by coordinated
upregulation of pathway genes and increased activity signature"
H3: Epigenetic Regulation
"Condition X alters chromatin state at [locus], changing
expression of genes [G1, G2]"
H4: Post-transcriptional Regulation
"MicroRNA [miR] is upregulated, suppressing target genes [G1, G2],
explaining decreased protein levels despite unchanged mRNA"
Before interpreting results:
❌ Ignoring log transformation
❌ Using nominal p-values for many genes
❌ Overinterpreting small fold changes
❌ Confusing gene expression with protein activity
❌ Cherry-picking genes
❌ Treating single cells as biological replicates (pseudoreplication)
Strategy:
1. Identify differentially expressed metabolic enzymes
2. Map to KEGG pathways
3. Check if corresponding metabolites are changed
4. Build integrated metabolic model
Example:
Gene: PHGDH (phosphoglycerate dehydrogenase) ↑
Metabolite: Serine ↑
→ Integrated finding: Increased serine biosynthesis
Compare mRNA vs protein changes:
Single-cell pseudoreplication and differential expression:
Gene expression is the messenger, not the message.
mRNA changes indicate potential for protein changes. Always consider:
Connect expression changes to phenotype through pathways and functional validation.