关于 alterlab-jaspar
alterlab-jaspar 是通过 JASPAR REST API 获取整理过的转录因子结合谱的技能。研究人员可用它检索矩阵,开展基序扫描、调控变异评估和富集分析。
主要功能
- 01转录因子谱检索
- 02PFM 矩阵获取
- 03PFM 转 PWM
- 04DNA 序列基序扫描
- 05双链扫描
- 06变异对结合位点影响分析
适用场景
- 01扫描启动子中的转录因子结合位点
- 02评估 SNP 对基序结合的影响
- 03分析 ChIP-seq 或 ATAC-seq 峰的基序富集
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-jaspar安装后在 Claude Code 中输入/alterlab-jaspar确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/api_reference.mdscripts/query_jaspar.py详细介绍
JASPAR 数据库
概述
JASPAR(https://jaspar.elixir.no/)是公认的开放访问数据库,收录经过整理、非冗余的转录因子(TF)结合谱,并以位置频率矩阵(PFM)的形式存储。当前版本 JASPAR 2026 新增了 265 个 CORE 谱,并将 41 个 UNVALIDATED 谱升级为 CORE,因此六个分类群中最新版本的 CORE 谱共计 2,633 个(这是实时 API 返回的数量)。每个谱均来源于实验(ChIP-seq、SELEX、HT-SELEX、蛋白质结合微阵列等)并经过整理。JASPAR 2026 还推出了深度学习(DL)集合,其中包含 1,259 个基于 240 种人类 TF 的 ENCODE ChIP-seq 数据训练的 BPNet 模型;这些模型可在网站上浏览和下载,但不会通过 /api/v1/matrix/ 提供。
关键资源:
- JASPAR 门户:https://jaspar.elixir.no/
- REST API:https://jaspar.elixir.no/api/v1/
- API 文档:https://jaspar.elixir.no/api/v1/docs/
- Python 访问:直接调用 REST(参见
scripts/query_jaspar.py),或使用 Biopython 的Bio.motifs.jaspar模块(PyPI 上没有独立的jaspar软件包)
脚本
scripts/query_jaspar.py — 查询 JASPAR REST API(仅使用标准库,将 JSON 输出到标准输出):
python scripts/query_jaspar.py search --name CTCF --species 9606 # latest-version profiles only
python scripts/query_jaspar.py search --name CTCF --all-versions # include historical versions
python scripts/query_jaspar.py matrix MA0139.1 # fetch a matrix (PFM)
search 默认使用 version=latest(每个谱返回一行);传入 --all-versions 可查看所有历史版本。--species 会映射到 API 的 tax_id 参数(NCBI 分类学 ID)。
何时使用此技能
在以下场景中使用 JASPAR:
- TF 结合位点预测:扫描 DNA 序列,寻找 TF 的潜在结合位点
- 调控变异解读:GWAS/eQTL 变异是否会破坏 TF 结合基序?
- 启动子/增强子分析:哪些 TF 可能结合某个调控元件?
- 基因调控网络构建:通过基序扫描将 TF 与其靶基因关联起来
- TF 家族分析:比较某个 TF 家族的结合谱(例如,所有同源异型框因子)
- ChIP-seq 分析:查找在 ChIP-seq 峰中富集的已知 TF 基序
- ENCODE/ATAC-seq 解读:将开放染色质区域与 TF 结合谱匹配
不适用场景
| 场景 | 改用 |
|---|---|
| 某个变异与已发表 GWAS 中哪些性状相关 | alterlab-gwas |
| 某个变异是否会改变特定组织中的基因表达(eQTL) | alterlab-gtex |
| 获取基因组序列、坐标或 VEP 后果 | alterlab-ensembl |
| 处理 ChIP-seq/ATAC-seq 覆盖度轨迹和热图 | alterlab-deeptools |
| 使用序列进行表达/染色质的深度学习预测 | alterlab-borzoi |
核心功能
1. JASPAR REST API
基础 URL:https://jaspar.elixir.no/api/v1/
import requests
BASE_URL = "https://jaspar.elixir.no/api/v1"
def jaspar_get(endpoint, params=None):
url = f"{BASE_URL}/{endpoint}"
response = requests.get(url, params=params, headers={"Accept": "application/json"})
response.raise_for_status()
return response.json()
2. 搜索 TF 谱
def search_jaspar(
tf_name=None,
species=None,
collection="CORE",
tf_class=None,
tf_family=None,
page=1,
page_size=25
):
"""Search JASPAR for TF binding profiles."""
params = {
"collection": collection,
"page": page,
"page_size": page_size,
"format": "json"
}
if tf_name:
params["name"] = tf_name
if species:
# NCBI taxonomy ID, e.g. "9606". The API silently ignores a `species=` param
# (you get every taxon back), so it must be sent as `tax_id`.
params["tax_id"] = species
if tf_class:
params["tf_class"] = tf_class
if tf_family:
params["tf_family"] = tf_family
return jaspar_get("matrix", params)
# Examples:
# Search for human CTCF profile
ctcf = search_jaspar("CTCF", species="9606")
print(f"Found {ctcf['count']} CTCF profiles")
# Search for all homeobox TFs in human. Class/family strings follow TFClass and
# must match exactly ("Homeodomain" returns 0 rows; the stored class is
# "Homeo domain factors") — read the "class" field of a known matrix to get it.
hox_tfs = search_jaspar(tf_class="Homeo domain factors", species="9606")
# Search for a TF family
nfkb = search_jaspar(tf_family="NF-kappaB")
3. 获取指定矩阵(PFM/PWM)
def get_matrix(matrix_id):
"""Fetch a specific JASPAR matrix by ID (e.g., 'MA0139.1' for CTCF)."""
return jaspar_get(f"matrix/{matrix_id}/")
# Example: Get CTCF matrix
ctcf_matrix = get_matrix("MA0139.1")
# Matrix structure (actual API fields; no "consensus" or "length" key — derive
# motif length from len(pfm["A"])):
# {
# "matrix_id": "MA0139.1",
# "name": "CTCF",
# "base_id": "MA0139",
# "version": 1,
# "collection": "CORE",
# "tax_group": "vertebrates",
# "pfm": { "A": [...], "C": [...], "G": [...], "T": [...] }, # 19 columns for CTCF
# "species": [{"tax_id": 9606, "name": "Homo sapiens"}],
# "class": ["C2H2 zinc finger factors"],
# "family": ["More than 3 adjacent zinc fingers"],
# "type": "ChIP-seq",
# "uniprot_ids": ["P49711"],
# "pubmed_ids": ["17512414"],
# "sequence_logo": "https://jaspar.elixir.no/static/logos/svg/MA0139.1.svg"
# }
4. 将 PFM/PWM 下载为矩阵
import numpy as np
def get_pwm(matrix_id, pseudocount=0.8):
"""
Fetch a PFM from JASPAR and convert to PWM (log-odds).
Returns numpy array of shape (4, L) in order A, C, G, T.
"""
matrix = get_matrix(matrix_id)
pfm = matrix["pfm"]
# Convert PFM to numpy
pfm_array = np.array([pfm["A"], pfm["C"], pfm["G"], pfm["T"]], dtype=float)
# Add pseudocount
pfm_array += pseudocount
# Normalize to get PPM
ppm = pfm_array / pfm_array.sum(axis=0, keepdims=True)
# Convert to PWM (log-odds relative to background 0.25)
background = 0.25
pwm = np.log2(ppm / background)
return pwm, matrix["name"]
# Example
pwm, name = get_pwm("MA0139.1") # CTCF
print(f"PWM for {name}: shape {pwm.shape}")
max_score = pwm.max(axis=0).sum()
print(f"Maximum possible score: {max_score:.2f} bits")
5. 扫描 DNA 序列以查找 TF 结合位点
import numpy as np
from typing import List, Tuple
NUCLEOTIDE_MAP = {'A': 0, 'C': 1, 'G': 2, 'T': 3,
'a': 0, 'c': 1, 'g': 2, 't': 3}
def scan_sequence(sequence: str, pwm: np.ndarray, threshold_pct: float = 0.8) -> List[dict]:
"""
Scan a DNA sequence for TF binding sites using a PWM.
Args:
sequence: DNA sequence string
pwm: PWM array (4 x L) in ACGT order
threshold_pct: Fraction of max score to use as threshold (0-1)
Returns:
List of hits with position, score, and matched sequence
"""
motif_len = pwm.shape[1]
max_score = pwm.max(axis=0).sum()
min_score = pwm.min(axis=0).sum()
threshold = min_score + threshold_pct * (max_score - min_score)
hits = []
seq = sequence.upper()
for i in range(len(seq) - motif_len + 1):
subseq = seq[i:i + motif_len]
# Skip if contains non-ACGT
if any(c not in NUCLEOTIDE_MAP for c in subseq):
continue
score = sum(pwm[NUCLEOTIDE_MAP[c], j] for j, c in enumerate(subseq))
if score >= threshold:
relative_score = (score - min_score) / (max_score - min_score)
hits.append({
"position": i + 1, # 1-based
"score": score,
"relative_score": relative_score,
"sequence": subseq,
"strand": "+"
})
return hits
# Example: Scan a promoter sequence for CTCF binding sites
# (windows containing non-ACGT bases such as N are skipped by scan_sequence)
promoter = "AGCCCGCGAGGTGGCAGTTGCCTGGAGCAGGATCAGCAGATC"
pwm, name = get_pwm("MA0139.1")
hits = scan_sequence(promoter, pwm, threshold_pct=0.75)
for hit in hits:
print(f" Position {hit['position']}: {hit['sequence']} (score: {hit['score']:.2f}, {hit['relative_score']:.0%})")
6. 扫描两条链
def reverse_complement(seq: str) -> str:
complement = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C', 'N': 'N'}
return ''.join(complement.get(b, 'N') for b in reversed(seq.upper()))
def scan_both_strands(sequence: str, pwm: np.ndarray, threshold_pct: float = 0.8):
"""Scan forward and reverse complement strands."""
fwd_hits = scan_sequence(sequence, pwm, threshold_pct)
for h in fwd_hits:
h["strand"] = "+"
rev_seq = reverse_complement(sequence)
rev_hits = scan_sequence(rev_seq, pwm, threshold_pct)
seq_len = len(sequence)
for h in rev_hits:
h["strand"] = "-"
h["position"] = seq_len - h["position"] - len(h["sequence"]) + 2 # Convert to fwd coords
all_hits = fwd_hits + rev_hits
return sorted(all_hits, key=lambda x: x["position"])
7. TF 结合的变异影响
def variant_tfbs_impact(ref_seq: str, alt_seq: str, pwm: np.ndarray,
tf_name: str, threshold_pct: float = 0.7):
"""
Assess impact of a SNP on TF binding by comparing ref vs alt sequences.
Both sequences should be centered on the variant with flanking context.
"""
ref_hits = scan_both_strands(ref_seq, pwm, threshold_pct)
alt_hits = scan_both_strands(alt_seq, pwm, threshold_pct)
max_ref = max((h["score"] for h in ref_hits), default=None)
max_alt = max((h["score"] for h in alt_hits), default=None)
result = {
"tf": tf_name,
"ref_max_score": max_ref,
"alt_max_score": max_alt,
"ref_has_site": len(ref_hits) > 0,
"alt_has_site": len(alt_hits) > 0,
}
if max_ref and max_alt:
result["score_change"] = max_alt - max_ref
result["effect"] = "gained" if max_alt > max_ref else "disrupted"
elif max_ref and not max_alt:
result["effect"] = "disrupted"
elif not max_ref and max_alt:
result["effect"] = "gained"
else:
result["effect"] = "no_site"
return result
查询工作流
工作流 1:查找启动子中的所有 TF 结合位点
import requests, numpy as np
# 1. Get relevant TF matrices (e.g., all human TFs in CORE collection)
# tax_id (not species) filters by organism; page_size is capped at 1000
response = requests.get(
"https://jaspar.elixir.no/api/v1/matrix/",
params={"tax_id": "9606", "collection": "CORE", "version": "latest",
"page_size": 1000, "page": 1, "format": "json"}
)
matrices = response.json()["results"]
# 2. For each matrix, compute PWM and scan promoter
promoter = "CCCGCCCGCCCGCCGCCCGCAGTTAATGAGCCCAGCGTGCC" # Example
all_hits = []
for m in matrices[:10]: # Limit for demo
matrix_data = requests.get(f"https://jaspar.elixir.no/api/v1/matrix/{m['matrix_id']}/").json()
pfm = matrix_data["pfm"]
pfm_arr = np.array([pfm["A"], pfm["C"], pfm["G"], pfm["T"]], dtype=float) + 0.8
ppm = pfm_arr / pfm_arr.sum(axis=0)
pwm = np.log2(ppm / 0.25)
hits = scan_sequence(promoter, pwm, threshold_pct=0.8)
for h in hits:
h["tf_name"] = m["name"]
h["matrix_id"] = m["matrix_id"]
all_hits.extend(hits)
print(f"Found {len(all_hits)} TF binding sites")
for h in sorted(all_hits, key=lambda x: -x["score"])[:5]:
print(f" {h['tf_name']} ({h['matrix_id']}): pos {h['position']}, score {h['score']:.2f}")
工作流 2:SNP 对 TF 结合的影响(调控变异分析)
- 获取 SNP 两侧的基因组序列(每侧 ±20 bp)
- 构建 ref 和 alt 序列
- 使用所有相关 TF PWM 进行扫描
- 报告因该 SNP 而新增或丢失结合位点的 TF
工作流 3:基序富集分析
- 确定一组峰序列(例如,来自 ChIP-seq 或 ATAC-seq)
- 使用 JASPAR PWM 扫描所有峰
- 比较峰序列与背景序列中的命中率
- 报告显著富集的基序(使用 Fisher 精确检验或 FIMO 风格的评分)
可用集合
当前 JASPAR API 提供两个集合(通过 GET /matrix/?collection=...&version=latest 验证数量):
| 集合 | 描述 | 最新版本配置文件(2026-09) |
|---|---|---|
CORE | 非冗余、经整理且经过实验验证的配置文件 | 2,633 |
UNVALIDATED | 推断得出或基于实验数据,但尚未验证 | ~1,030 |
JASPAR 2026 深度学习(DL)集合中的 BPNet 模型托管在网站上(可下载模型;通过 tangermeme 框架扫描基序),不在矩阵 API 中。
旧版集合(PHYLOFACTS、CNE、POLII、FAM、SPLICE)曾出现在较早的 JASPAR 文献中,但当前 API 返回 0 条结果,请勿依赖它们。
最佳实践
- 大多数分析使用 CORE 集合——验证最充分且非冗余
- 阈值选择:从头预测常用最高分数的 80%;高置信度分析使用 90%
- 始终扫描两条链——TF 可以沿任一方向结合
- 变异分析时提供侧翼上下文:每侧至少 (motif_length - 1) bp
- 考虑背景:PWM 分数是相对于均匀(0.25)背景计算的;请根据实际 GC 含量进行调整
- 有 ChIP-seq 数据时进行交叉验证——基序扫描会产生许多假阳性
- 使用 Biopython 的 motifs 模块进行完整功能的扫描:
from Bio import motifs
其他资源
- JASPAR 门户:https://jaspar.elixir.no/
- API 文档:https://jaspar.elixir.no/api/v1/docs/
- JASPAR 2026 论文(当前版本):Ovek Baydar D, et al. (2026) JASPAR 2026: 转录因子结合谱的扩展及深度学习模型的整合。Nucleic Acids Research 54(D1):D184-D193。DOI: 10.1093/nar/gkaf1209。PMID: 41325984
- JASPAR 2024 论文:Rauluseviciute I, et al. (2024) JASPAR 2024: 转录因子结合谱开放获取数据库 20 周年。Nucleic Acids Research 52(D1):D174-D182。DOI: 10.1093/nar/gkad1059。PMID: 37962376
- Biopython motifs:https://biopython.org/docs/latest/Tutorial/chapter_motifs.html
- FIMO 工具(用于大规模扫描):https://meme-suite.org/meme/tools/fimo
- HOMER(基序富集):http://homer.ucsd.edu/homer/
- GitHub:https://github.com/wassermanlab/JASPAR-UCSC-tracks