alterlab-jaspar について
alterlab-jasparは、JASPAR REST APIからキュレーション済み転写因子結合プロファイルを取得するスキルです。行列の検索を通じて、モチーフスキャン、調節変異の評価、濃縮解析を支援します。
主な機能
- 01転写因子プロファイル検索
- 02PFM行列の取得
- 03PFMからPWMへの変換
- 04DNA配列のモチーフスキャン
- 05両鎖のスキャン
- 06変異による結合部位への影響評価
活用シーン
- 01プロモーター内の転写因子結合部位のスキャン
- 02SNPによるモチーフ結合への影響評価
- 03ChIP-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 では、CORE プロファイルが265件追加され、UNVALIDATED から41件が昇格し、6つの分類群にわたる最新バージョンの CORE プロファイルは2,633件となりました(ライブ API が返す件数です)。各プロファイルは、ChIP-seq、SELEX、HT-SELEX、タンパク質結合マイクロアレイなどの実験から得られ、精選されています。JASPAR 2026 では、ディープラーニング(DL)コレクションも公開されました。これは240種類のヒト TF を対象とする ENCODE ChIP-seq で学習した1,259件の 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モジュールを使用(単独のjasparPyPI パッケージはありません)
スクリプト
scripts/query_jaspar.py — JASPAR REST API にクエリを送信します(標準ライブラリのみを使用し、JSON を stdout に出力します)。
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(プロファイルごとに1行)です。過去のすべてのバージョンを表示するには、--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 は、2 つのコレクションを提供しています(GET /matrix/?collection=...&version=latest で件数を確認してください)。
| コレクション | 説明 | 最新バージョンのプロファイル数(2026-09) |
|---|---|---|
CORE | 冗長性がなく、キュレーション済みで、実験的に検証されたプロファイル | 2,633 |
UNVALIDATED | 推定または実験から得られたものの、まだ検証されていないプロファイル | 約1,030 |
BPNet モデルを含む JASPAR 2026 Deep Learning(DL)コレクションは、マトリックス API ではなくウェブサイトで提供されています(モデルはダウンロード可能で、モチーフのスキャンには tangermeme フレームワークを使用します)。
レガシーコレクション(PHYLOFACTS、CNE、POLII、FAM、SPLICE)は以前の JASPAR 関連文献に登場しますが、現在の API では結果が 0 件になるため、これらに依存しないでください。
ベストプラクティス
- ほとんどの解析では CORE コレクションを使用してください — 検証の信頼性が最も高く、冗長性もありません
- 閾値の選択:新規予測では最大スコアの 80%、高信頼度の予測では 90%が一般的です
- 必ず両方の鎖をスキャンしてください — TF はどちらの向きにも結合する可能性があります
- バリアント解析ではフランキング領域を含めてください:両側に少なくとも(モチーフ長 - 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: expansion of transcription factor binding profiles and integration of deep learning models. Nucleic Acids Research 54(D1):D184-D193. DOI: 10.1093/nar/gkaf1209. PMID: 41325984
- JASPAR 2024 論文:Rauluseviciute I, et al. (2024) JASPAR 2024: 20th anniversary of the open-access database of transcription factor binding profiles. 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