protocolsio-integration について
実験プロトコルを検索・取得する protocols.io REST API を、生命科学研究者やラボ自動化の開発者向けに解説するスキルです。バージョン履歴や材料の抽出に加え、非公開コンテンツや編集に必要な OAuth2 も扱います。
主な機能
- 01キーワード、手法、DOI による検索
- 02全手順と材料の取得
- 03プロトコルのバージョン履歴確認
- 04プロトコルカテゴリの閲覧
- 05非公開プロトコルと編集の OAuth2 利用
活用シーン
- 01実験手法の引用可能なプロトコルを検索
- 02自動化ワークフロー向けに手順と試薬を抽出
- 03プロトコルの版と DOI を確認
- 04特定の試薬や機器を使う手順を検索
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill protocolsio-integrationインストール後、Claude Code で/protocolsio-integrationを入力して読み込まれたか確認します。
詳細
protocols.io 連携
概要
protocols.io は、分子生物学、細胞生物学、バイオインフォマティクス、臨床研究、ラボ自動化を網羅する 90,000 件以上のオープンアクセス実験プロトコルを提供する、ライフサイエンス分野をリードするプロトコルリポジトリです。REST API を使用すると、プロトコルの検索、プロトコル全体の取得(手順、試薬、材料、機器)、プロトコルのバージョン管理、ワークスペース管理、プロトコルの公開をプログラムから実行できます。公開プロトコルは無料で利用できます。非公開プロトコルへのアクセスや作成・編集には認証(OAuth2 トークン)が必要です。
使用する場面
- キーワード、手法、または論文の DOI で、検証済みのウェットラボプロトコルを検索する
- 自動化や分析のために、プロトコルの手順、試薬、所要時間、容量、注記を含む完全な内容を取得する
- 特定の試薬、キット、または機器に関連するプロトコルを見つける
- プロトコルの手順や試薬リストをプログラムで抽出し、ラボ自動化ワークフローを構築する
- プロトコルのバージョンを確認し、方法のセクションで正しい DOI を引用する
- 独自の手法に代わる、コミュニティで検証済みのプロトコルを見つける
opentrons-protocol-apiまたはbenchling-integrationと併用し、ダウンロードしたプロトコルを自動化ワークフローに実装する
前提条件
- Python パッケージ:
requests、pandas - データ要件:プロトコルのキーワード、DOI、または protocols.io のプロトコル ID
- 環境:インターネット接続。公開プロトコルには認証不要。非公開プロトコルには https://www.protocols.io/developers で取得する OAuth2 トークンが必要
- レート制限:公開 API は 1 秒あたり 10 リクエスト。公開プロトコルへの未認証リクエストが許可されています
pip install requests pandas
# For private protocol access or publishing:
# Register at https://www.protocols.io/developers to obtain an API token
クイックスタート
import requests
BASE = "https://www.protocols.io/api/v4"
# For public protocols, no token needed (but add for higher rate limits)
HEADERS = {"Authorization": "Bearer YOUR_TOKEN_HERE"} # Optional for public
# Search for CRISPR protocols
r = requests.get(f"{BASE}/protocols",
params={"q": "CRISPR guide RNA design", "order_field": "views",
"page_size": 5},
headers=HEADERS)
r.raise_for_status()
data = r.json()
print(f"Total CRISPR protocols: {data['pagination']['total_results']}")
for p in data["items"][:3]:
print(f"\n {p['title']}")
print(f" DOI: {p.get('doi')} | Views: {p.get('stats', {}).get('number_of_views')}")
print(f" Authors: {', '.join(a['name'] for a in p.get('creators', [])[:3])}")
主要 API
クエリ 1:プロトコル検索
キーワード、手法、または全文で protocols.io の公開ライブラリを検索します。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def search_protocols(query, page_size=20, order_field="relevance", category_id=None):
params = {"q": query, "page_size": page_size, "order_field": order_field}
if category_id:
params["filter[categories_ids][]"] = category_id
r = requests.get(f"{BASE}/protocols", params=params)
r.raise_for_status()
return r.json()
data = search_protocols("RNA extraction tissue", page_size=10, order_field="views")
total = data["pagination"]["total_results"]
print(f"RNA extraction protocols: {total}")
rows = []
for p in data["items"][:10]:
rows.append({
"id": p.get("id"),
"title": p.get("title"),
"doi": p.get("doi"),
"views": p.get("stats", {}).get("number_of_views", 0),
"created": p.get("created_on"),
"category": p.get("categories", [{}])[0].get("name", "n/a"),
})
df = pd.DataFrame(rows).sort_values("views", ascending=False)
print(df.to_string(index=False))
# Search with category filter (get category IDs from /categories endpoint)
data_pcr = search_protocols("qPCR primer design", order_field="views")
print(f"\nqPCR protocols: {data_pcr['pagination']['total_results']}")
for p in data_pcr["items"][:3]:
print(f" {p['title'][:70]} (DOI: {p.get('doi', 'n/a')})")
クエリ 2:プロトコル全体の内容を取得
手順、試薬、材料、機器を含むプロトコル全体を取得します。
import requests
BASE = "https://www.protocols.io/api/v4"
def get_protocol(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
return r.json()
# Retrieve protocol by ID (from search results or DOI lookup)
protocol_id = 45979 # Example: a public protocol
data = get_protocol(protocol_id)
protocol = data.get("payload", data) # Handle API response structure
print(f"Title: {protocol.get('title')}")
print(f"DOI: {protocol.get('doi')}")
print(f"Authors: {', '.join(a['name'] for a in protocol.get('creators', []))}")
print(f"Steps: {len(protocol.get('steps', []))}")
print(f"Materials: {len(protocol.get('materials', []))}")
print(f"Abstract: {protocol.get('description', '')[:200]}")
# Parse protocol steps
protocol_steps = protocol.get("steps", [])
for i, step in enumerate(protocol_steps[:5], 1):
step_desc = step.get("description", "")
duration = step.get("duration", {})
print(f"\nStep {i}: {step_desc[:120]}")
if duration:
print(f" Duration: {duration.get('duration')} {duration.get('unit_label', '')}")
クエリ 3:DOI からプロトコルを取得
正確な引用情報に基づいて取得するため、DOI を使ってプロトコルを取得します。
import requests, json
BASE = "https://www.protocols.io/api/v4"
def get_protocol_by_doi(doi):
"""Retrieve protocol using its DOI."""
# URL-encode the DOI for the query
r = requests.get(f"{BASE}/protocols",
params={"q": doi, "page_size": 5})
r.raise_for_status()
items = r.json()["items"]
for item in items:
if item.get("doi") == doi:
return item
return None
doi = "10.17504/protocols.io.bvb3n2qn" # Example protocols.io DOI
protocol = get_protocol_by_doi(doi)
if protocol:
print(f"Found: {protocol['title']}")
print(f" ID: {protocol['id']}")
print(f" Version: {protocol.get('version_id')}")
クエリ 4:試薬と材料を抽出
取得したプロトコルから材料リストを解析して抽出します。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def get_reagents(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
data = r.json()
protocol = data.get("payload", data)
return protocol.get("materials", [])
# Get reagents list
materials = get_reagents(45979) # Example protocol ID
print(f"Materials ({len(materials)} items):")
rows = []
for m in materials[:10]:
rows.append({
"name": m.get("name"),
"quantity": m.get("quantity"),
"unit": m.get("unit", {}).get("name", ""),
"supplier": m.get("supplier", {}).get("name", ""),
"catalog": m.get("sku"),
})
df = pd.DataFrame(rows)
print(df.to_string(index=False))
クエリ 5:プロトコルのカテゴリを閲覧
対象を絞った検索に利用できるプロトコルのカテゴリを一覧表示します。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
r = requests.get(f"{BASE}/categories")
r.raise_for_status()
data = r.json()
categories = data.get("items", data.get("payload", []))
print(f"protocols.io categories: {len(categories)}")
df = pd.DataFrame(categories)[["id", "name"]].head(20)
print(df.to_string(index=False))
クエリ 6:プロトコルのバージョン一覧を取得
プロトコルの更新を追跡するため、バージョン履歴を取得します。
import requests
BASE = "https://www.protocols.io/api/v4"
def get_protocol_versions(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
protocol = r.json().get("payload", r.json())
return {
"title": protocol.get("title"),
"version": protocol.get("version_id"),
"published": protocol.get("published_on"),
"doi": protocol.get("doi"),
"parent_doi": protocol.get("parent_publication", {}).get("doi"),
}
info = get_protocol_versions(45979)
for k, v in info.items():
print(f" {k}: {v}")
主な概念
プロトコルの DOI とバージョン管理
protocols.io で公開された各プロトコルには、引用可能な DOI(形式:10.17504/protocols.io.XXXXX)が付与されます。プロトコルが更新されると、新しい DOI を持つ新バージョンが作成されますが、元の DOI も引き続き有効です。再現性を確保するため、方法のセクションでは必ず特定のバージョンの DOI を引用してください。
API 認証
公開プロトコルは認証なしでアクセスできます。非公開プロトコル、ワークスペース管理、プロトコルの作成・編集、ユーザー固有のクエリには、OAuth2 Bearer トークンが必要です。トークンは https://www.protocols.io/developers で取得してください。
一般的なワークフロー
ワークフロー 1:プロトコルの検索と比較
目的:手法に合致するプロトコルを検索、比較し、応用に最適なものを選択します。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def search_and_rank(query, top_n=20):
"""Search protocols and return ranked by views + forks."""
r = requests.get(f"{BASE}/protocols",
params={"q": query, "page_size": top_n, "order_field": "views"})
r.raise_for_status()
data = r.json()
rows = []
for p in data["items"]:
stats = p.get("stats", {})
rows.append({
"id": p.get("id"),
"title": p.get("title"),
"doi": p.get("doi"),
"views": stats.get("number_of_views", 0),
"forks": stats.get("number_of_forks", 0),
"steps": p.get("number_of_steps"),
"created": p.get("created_on")[:10] if p.get("created_on") else "n/a",
"category": p.get("categories", [{}])[0].get("name", "n/a"),
})
df = pd.DataFrame(rows)
df["popularity_score"] = df["views"] * 0.7 + df["forks"] * 0.3 * 100
return df.sort_values("popularity_score", ascending=False)
# Compare western blotting protocols
df = search_and_rank("western blot protein detection", top_n=15)
df.to_csv("western_blot_protocols.csv", index=False)
print("Top western blot protocols:")
print(df[["title", "views", "forks", "steps"]].head(8).to_string(index=False))
ワークフロー 2:自動化に向けたプロトコル手順の抽出
目的:後続の自動化スクリプト作成に向けて、プロトコルの手順、所要時間、試薬の容量を抽出します。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def extract_protocol_steps(protocol_id):
"""Extract structured step data from a protocol."""
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
protocol = r.json().get("payload", r.json())
steps = []
for i, step in enumerate(protocol.get("steps", []), 1):
duration = step.get("duration", {})
steps.append({
"step_number": i,
"description": step.get("description", ""),
"duration_value": duration.get("duration"),
"duration_unit": duration.get("unit_label", ""),
"temperature": step.get("temperature", {}).get("value"),
"temp_unit": step.get("temperature", {}).get("unit_label", ""),
})
materials = [{
"name": m.get("name"),
"quantity": m.get("quantity"),
"unit": m.get("unit", {}).get("name", ""),
} for m in protocol.get("materials", [])]
return {
"title": protocol.get("title"),
"doi": protocol.get("doi"),
"steps": pd.DataFrame(steps),
"materials": pd.DataFrame(materials),
}
result = extract_protocol_steps(45979)
print(f"Protocol: {result['title']}")
print(f"\nSteps ({len(result['steps'])}):")
print(result["steps"][["step_number", "description", "duration_value", "duration_unit"]].head(5).to_string(index=False))
print(f"\nMaterials ({len(result['materials'])}):")
print(result["materials"].head(5).to_string(index=False))
# Export for automation
result["steps"].to_csv("protocol_steps.csv", index=False)
result["materials"].to_csv("protocol_materials.csv", index=False)
主なパラメーター
| パラメーター | モジュール | デフォルト | 範囲/選択肢 | 効果 |
|---|---|---|---|---|
q | 検索 | — | キーワード文字列 | 全文検索クエリ |
order_field | 検索 | "relevance" | "relevance"、"views"、"date"、"activity" | 結果の並べ替え順 |
page_size | 検索 | 10 | 1–50 | 1 ページあたりの結果数 |
page_id | 検索 | 1 | 整数 | ページ番号 |
filter[categories_ids][] | 検索 | — | カテゴリの整数 ID | プロトコルのカテゴリで絞り込み |
| Protocol ID | 取得 | 必須 | 整数 | 取得する特定のプロトコル |
ベストプラクティス
-
品質を判断するために閲覧数順で並べ替える:十分に検証されたプロトコルを検索する場合は、
order_field=viewsを使用してください。閲覧数の多いプロトコルは、多くのグループでテストされています。 -
必ず特定のDOIを引用する:protocols.ioのDOIにはバージョンが付与されています。読者が同じプロトコルを再現できるように、メソッドのセクションではプロトコル名だけでなく、正確なバージョンのDOIを引用してください。
-
使用前にライセンスを確認する:protocols.ioで公開されているプロトコルは、デフォルトですべてCC-BY 4.0です。商用利用する場合は、各プロトコルのライセンスを確認してください。
-
試薬の注文用に材料リストを抽出する:材料APIはカタログ番号とサプライヤー名を返すため、調達リストを直接作成できます。
-
再現性のためにプロトコルIDとDOIを保存する:プロジェクトでプロトコルを選択する際は、APIアクセス用の整数IDと、安定した引用に使うDOIの両方を記録してください。
よくあるレシピ
レシピ:試薬名で検索する
使用する場面:特定の市販キットや試薬を使うプロトコルを探す場合。
import requests
r = requests.get("https://www.protocols.io/api/v4/protocols",
params={"q": "RNeasy Mini Kit RNA extraction", "page_size": 5,
"order_field": "views"})
data = r.json()
print(f"Protocols using RNeasy: {data['pagination']['total_results']}")
for p in data["items"][:3]:
print(f" {p['title'][:70]} ({p.get('doi', 'n/a')})")
レシピ:メソッドのセクション用にプロトコルの引用情報を取得する
使用する場面:メソッドのセクション用の引用文字列を生成する場合。
import requests
protocol_id = 45979
r = requests.get(f"https://www.protocols.io/api/v4/protocols/{protocol_id}")
p = r.json().get("payload", r.json())
authors = "; ".join(a["name"] for a in p.get("creators", [])[:3])
print(f"Citation: {authors} ({p.get('created_on', '')[:4]}). ")
print(f"{p.get('title')}. protocols.io. https://doi.org/{p.get('doi')}")
レシピ:フォーク数が最も多いプロトコルを探す
使用する場面:広く応用されているプロトコル(フォーク数が多いほど、多くのラボで応用されています)を特定する場合。
import requests, pandas as pd
r = requests.get("https://www.protocols.io/api/v4/protocols",
params={"q": "ChIP-seq chromatin", "page_size": 20})
data = r.json()
df = pd.DataFrame([{
"title": p["title"][:60],
"forks": p.get("stats", {}).get("number_of_forks", 0),
"views": p.get("stats", {}).get("number_of_views", 0),
} for p in data["items"]])
print(df.sort_values("forks", ascending=False).head(5).to_string(index=False))
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
検索結果のitemsが空 | クエリが具体的すぎる、または一致する項目がない | クエリの範囲を広げる。特殊文字を削除する |
プロトコルへのアクセス時にHTTP 401が発生する | 認証なしで非公開プロトコルにアクセスしている | OAuth2トークンを取得する。公開プロトコルには認証は不要 |
| プロトコルの手順説明が空 | プロトコルでリッチテキスト形式が使われている | re.sub(r'<[^>]+>', '', text)でdescriptionからHTMLタグを削除する |
materialsリストが空 | プロトコルに構造化された材料情報がない | 材料情報が手順の説明文にプレーンテキストで埋め込まれている可能性がある |
| DOI検索で間違ったプロトコルが返される | DOIではなく、類似したタイトルで一致している | DOIフィールドを正確に比較する。文字列の等価性チェックif item.get("doi") == doiを使用する |
| レート制限エラーが発生する | リクエスト数が1秒あたり10件を超えている | リクエストの間にtime.sleep(0.15)を追加する |
関連スキル
opentrons-protocol-api— このスキルで抽出した手順を使って、Opentronsの液体ハンドリングロボットでプロトコルを実行しますbenchling-integration— 試薬の追跡とともに、取得したプロトコルをBenchling ELNに保存しますscientific-manuscript-writing— protocols.ioのDOIを使って、メソッドのセクションでプロトコルを正しく引用します
参考資料
- protocols.io APIドキュメント — REST APIの公式リファレンス
- protocols.ioプラットフォーム — 公開プロトコルライブラリと検索
- protocols.io引用ガイド — 論文でprotocols.ioを引用する方法
- Teytelman et al. (2016) Nature Methods — protocols.ioプラットフォームの解説論文