mcpField
J
jaspar-database

jaspar-database

github.com/leonchaoxデータ・データベース99470 回インストール15 週間前に更新
リポジトリ

jaspar-database について

jaspar-database は、REST API を通じて JASPAR のキュレーション済み転写因子結合プロファイルを調べるスキルです。行列の取得に加え、DNA 配列のスキャンや、変異が予測結合に与える影響の評価に利用できます。

主な機能

  1. 01転写因子プロファイルの検索
  2. 02PFM 行列の取得
  3. 03PFM から PWM への変換
  4. 04DNA 配列のモチーフスキャン
  5. 05DNA 両鎖のスキャン
  6. 06変異前後の結合予測の比較

活用シーン

  1. 01プロモーター内の結合部位予測
  2. 02変異によるモチーフへの影響評価
  3. 03ChIP-seq ピークのモチーフ解析
  4. 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 を使用します。

  • 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 の影響(調節バリアント解析)
  1. SNP の両側にあるゲノム配列(各側 ±20 bp)を取得します
  2. ref 配列と alt 配列を作成します
  3. 関連するすべての TF PWM でスキャンします
  4. SNP によって結合が生じる、または失われる TF を報告します
ワークフロー 3:モチーフ濃縮解析
  1. ピーク配列のセットを特定します(例:ChIP-seq または ATAC-seq から取得)
  2. JASPAR PWM を使用してすべてのピークをスキャンします
  3. ピークとバックグラウンド配列のヒット率を比較します
  4. 有意に濃縮されたモチーフを報告します(Fisher の正確確率検定または FIMO 形式のスコアリング)

利用可能なコレクション

コレクション説明プロファイル数
CORE冗長性がなく、高品質なプロファイル~1,210
UNVALIDATED実験から得られたものの、検証されていないプロファイル~500
PHYLOFACTS系統学的に保存された部位~50
CNE保存された非コードエレメント~30
POLIIRNA Pol II 結合プロファイル~20
FAMTF ファミリーの代表的なプロファイル~170
SPLICEスプライシング因子のプロファイル~20

ベストプラクティス

  • ほとんどの解析では CORE コレクションを使用します — 最もよく検証され、冗長性もありません
  • しきい値の選択:新規予測では最大スコアの 80%、高信頼度の予測では 90%が一般的です
  • 必ず両方の鎖をスキャンします — TF はどちらの向きにも結合できます
  • バリアント解析ではフランキング配列を含めます:各側に少なくとも(モチーフ長 - 1)bp を含めます
  • バックグラウンドを考慮します:PWM スコアは一様な(0.25)バックグラウンドを基準としています。実際の GC 含量に合わせて調整してください
  • 利用可能な場合は ChIP-seq データで交差検証します — モチーフスキャンでは偽陽性が多く発生します
  • 多機能なスキャンには Biopython の motifs モジュールを使用します:from Bio import motifs

Additional Resources

コメント