jaspar-database について
jaspar-database は、REST API を通じて JASPAR のキュレーション済み転写因子結合プロファイルを調べるスキルです。行列の取得に加え、DNA 配列のスキャンや、変異が予測結合に与える影響の評価に利用できます。
主な機能
- 01転写因子プロファイルの検索
- 02PFM 行列の取得
- 03PFM から PWM への変換
- 04DNA 配列のモチーフスキャン
- 05DNA 両鎖のスキャン
- 06変異前後の結合予測の比較
活用シーン
- 01プロモーター内の結合部位予測
- 02変異によるモチーフへの影響評価
- 03ChIP-seq ピークのモチーフ解析
- 04転写因子ファミリー内のプロファイル比較
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ leonchaox/ qinyan-academic-skills --skill jaspar-databaseインストール後、Claude Code で/jaspar-databaseを入力して読み込まれたか確認します。
同梱ファイルreferences/api_reference.md
詳細
JASPAR データベース
概要
JASPAR(https://jaspar.elixir.no/)は、キュレーション済みで冗長性のない転写因子(TF)結合プロファイルを、位置頻度行列(PFM)として格納した、ゴールドスタンダードのオープンアクセスデータベースです。JASPAR 2024 には、164 種の真核生物を対象とする、冗長性のない TF 結合プロファイルが 1,210 件収録されています。各プロファイルは実験(ChIP-seq、SELEX、HT-SELEX、タンパク質結合マイクロアレイなど)から得られ、厳密に検証されています。
主なリソース:
- JASPAR ポータル:https://jaspar.elixir.no/
- REST API:https://jaspar.elixir.no/api/v1/
- API ドキュメント:https://jaspar.elixir.no/api/v1/docs/
- Python パッケージ:
jaspar(Biopython 経由)または API の直接利用
このスキルを使用する場面
次のような場合に JASPAR を使用します。
- TF 結合部位の予測:DNA 配列をスキャンし、TF の潜在的な結合部位を探します
- 調節バリアントの解釈:GWAS/eQTL バリアントが TF 結合モチーフを破壊するかどうかを調べます
- プロモーター/エンハンサーの解析:調節エレメントに結合すると予測される TF を調べます
- 遺伝子制御ネットワークの構築:モチーフスキャンを通じて、TF と標的遺伝子を関連付けます
- TF ファミリーの解析:TF ファミリー内の結合プロファイルを比較します(例:すべてのホメオボックス因子)
- ChIP-seq 解析:ChIP-seq ピークで濃縮されている既知の TF モチーフを探します
- ENCODE/ATAC-seq の解釈:オープンクロマチン領域を TF 結合プロファイルと照合します
主な機能
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:
params["species"] = species # Use taxonomy ID or name, e.g., "9606" for human
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
hox_tfs = search_jaspar(tf_class="Homeodomain", 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:
# {
# "matrix_id": "MA0139.1",
# "name": "CTCF",
# "collection": "CORE",
# "tax_group": "vertebrates",
# "pfm": { "A": [...], "C": [...], "G": [...], "T": [...] },
# "consensus": "CCGCGNGGNGGCAG",
# "length": 19,
# "species": [{"tax_id": 9606, "name": "Homo sapiens"}],
# "class": ["C2H2 zinc finger factors"],
# "family": ["BEN domain factors"],
# "type": "ChIP-seq",
# "uniprot_ids": ["P49711"]
# }
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
promoter = "AGCCCGCGAGGNGGCAGTTGCCTGGAGCAGGATCAGCAGATC"
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)
response = requests.get(
"https://jaspar.elixir.no/api/v1/matrix/",
params={"species": "9606", "collection": "CORE", "page_size": 500, "page": 1}
)
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
pwm_data = requests.get(f"https://jaspar.elixir.no/api/v1/matrix/{m['matrix_id']}/").json()
pfm = pfm_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:TF 結合に対する SNP の影響(調節バリアント解析)
- SNP の両側にあるゲノム配列(各側 ±20 bp)を取得します
- ref 配列と alt 配列を作成します
- 関連するすべての TF PWM でスキャンします
- SNP によって結合が生じる、または失われる TF を報告します
ワークフロー 3:モチーフ濃縮解析
- ピーク配列のセットを特定します(例:ChIP-seq または ATAC-seq から取得)
- JASPAR PWM を使用してすべてのピークをスキャンします
- ピークとバックグラウンド配列のヒット率を比較します
- 有意に濃縮されたモチーフを報告します(Fisher の正確確率検定または FIMO 形式のスコアリング)
利用可能なコレクション
| コレクション | 説明 | プロファイル数 |
|---|---|---|
CORE | 冗長性がなく、高品質なプロファイル | ~1,210 |
UNVALIDATED | 実験から得られたものの、検証されていないプロファイル | ~500 |
PHYLOFACTS | 系統学的に保存された部位 | ~50 |
CNE | 保存された非コードエレメント | ~30 |
POLII | RNA Pol II 結合プロファイル | ~20 |
FAM | TF ファミリーの代表的なプロファイル | ~170 |
SPLICE | スプライシング因子のプロファイル | ~20 |
ベストプラクティス
- ほとんどの解析では CORE コレクションを使用します — 最もよく検証され、冗長性もありません
- しきい値の選択:新規予測では最大スコアの 80%、高信頼度の予測では 90%が一般的です
- 必ず両方の鎖をスキャンします — TF はどちらの向きにも結合できます
- バリアント解析ではフランキング配列を含めます:各側に少なくとも(モチーフ長 - 1)bp を含めます
- バックグラウンドを考慮します:PWM スコアは一様な(0.25)バックグラウンドを基準としています。実際の GC 含量に合わせて調整してください
- 利用可能な場合は ChIP-seq データで交差検証します — モチーフスキャンでは偽陽性が多く発生します
- 多機能なスキャンには Biopython の motifs モジュールを使用します:
from Bio import motifs
Additional Resources
- JASPAR portal: https://jaspar.elixir.no/
- API documentation: https://jaspar.elixir.no/api/v1/docs/
- JASPAR 2024 paper: Castro-Mondragon et al. (2022) Nucleic Acids Research. PMID: 34875674
- Biopython motifs: https://biopython.org/docs/latest/Tutorial/chapter_motifs.html
- FIMO tool (for large-scale scanning): https://meme-suite.org/meme/tools/fimo
- HOMER (motif enrichment): http://homer.ucsd.edu/homer/
- GitHub: https://github.com/wassermanlab/JASPAR-UCSC-tracks
コメント
Markdown 対応