Harvest (DailyMed / PubMed) → CL/V extraction → template generation
Harvest (DailyMed / PubMed) → CL/V extraction → template generation
このリポジトリ(v0.6)では、v0.3の形式(pk.yml / spec / targets)を維持したまま、
- DailyMed (SPL) からラベルを取得
- PubMed / PMC(オープンアクセスがあれば全文XML)からテキスト取得
- テキストから CL / V / t1/2 / F を正規表現で抽出
drugs/<drug>/以下へ テンプレを自動生成
を行うスクリプトを追加しました。
v0.8 ではさらに、取りこぼしの原因を機械可読な理由コードとして EXCLUDED.csv に出力し、
理由別の救済(table行 PKROW: の直接解析/t1/2からの導出)を自動で試します。
重要:論文は抄録にCL/Vが無いことが多く、PMCに全文が無い(=著作権で取得できない)場合は抽出できません。
その場合はjobs.ymlに「確実なソース(PDF/URL)」を追加するか、手で値を入れてください。
1) 依存関係
最小限で動かすなら requests, lxml, pyyaml が必要です。
uv を使うなら例:
uv run --with requests --with lxml --with pyyaml python tools/harvest_and_generate.py --help
PubMed/PMCも使うなら追加は不要です(同じ依存で動きます)。
2) jobs.yml 形式
jobs.yml は 配列、または {jobs: [...]} 形式。
jobs:
- name: aciclovir
route: oral # oral | iv
dose_mg: 100 # 省略時は --default-dose-mg
weight_ref_kg_for_abs: 70
param_basis: auto # auto | apparent | systemic | any
dailymed: true # true なら drug_name で検索して最新っぽいSPLを選びます
pubmed: false # PubMed/PMCも回すなら true
DailyMedのSETIDを固定したい場合:
- name: simvastatin
route: oral
dailymed:
setid: fdbfe194-b845-42c5-bb87-a48118bc72e7
pubmed: false
PubMed側をPMID指定したい場合:
- name: rifampin
route: oral
pubmed:
pmid: "12345678"
dailymed: true
検索クエリを指定したい場合:
- name: caffeine
pubmed:
query: 'caffeine[Title/Abstract] AND (clearance OR "volume of distribution")'
dailymed: true
3) 実行
リポジトリ直下で:
uv run --with requests --with lxml --with pyyaml python tools/harvest_and_generate.py \
--jobs jobs.yml --repo . --default-dose-mg 100
- 成功すると
drugs/<slug>/pk.yml,spec_*.yml,targets.ymlが生成されます - 成果は
reports/harvest_report.jsonに出ます
3.1) EXCLUDED.csv(取りこぼし一覧)
clearance / volume が埋まらなかった、または生成に失敗した薬剤は、リポジトリ直下の
EXCLUDED.csv に行として出力されます。
列:
drug,slug,route_inferred,status,missingreason:;区切りの理由コード(例:MISSING_CLEARANCE;CLEARANCE_KEYWORDS_BUT_NO_CANDIDATES;PUBMED_ABSTRACT_ONLY)reason_json: 詳細(sources / pk / diagnostics / codes)を JSON 文字列で格納remediation_hint: 機械的な対処ヒント
生成後に INDEX.csv を更新するには:
python tools/rebuild_index.py
4) 抽出ロジックの注意点(重要)
- DailyMedはSPL XMLの
CLINICAL PHARMACOLOGY/PHARMACOKINETICSなどのセクションを優先してテキスト化し、そこから抽出します- v0.5 から tableを行単位で整形して付加し、値+単位が崩れにくくなりました
- v0.6 から 表のヘッダ推定(列名→単位列の対応)を軽量に行い、
PKROW: Clearance 5.2 L/hのような“抽出向け正規化行”を追加します - v0.8 から
PKROW:を直接パースする救済パスを追加し、フラット化された表で正規表現が外れるケースを拾いやすくしています - v0.8 から t1/2 と片方(CL/V)が取れたときに、もう片方を導出する救済パスを追加しています(
ke=ln2/t1/2を仮定) - v0.5 から PKセクション→全セクションの2段階抽出で、CL/Vが別セクションにあるケースを拾いやすくしています
- CL/Vの単位はできる範囲で
L/horL/h/kg,LorL/kgへ変換します- 変換した場合は
pk.yml:derived.notesに記録されます
- 変換した場合は
- oralのCL/VはCL/F, V/Fとして載っていることが多いため、テンプレ生成では
theta.F1=1.0をデフォルトにしています- もしソースが「systemic CL/V」と明確なら、
theta.F1とCL/Vを自分で整合させてください - v0.6 では
param_basisにより CL と CL/F(V と V/F)の優先順位を指定できますauto(デフォルト):route: oral→ apparent(CL/F, V/F)を優先 /route: iv→ systemic(CL, V)を優先apparent: 常に CL/F, V/F を優先(両方あるとき)systemic: 常に CL, V を優先(両方あるとき)any: 優先なし(距離やセクション重みで選択)
- もしソースが「systemic CL/V」と明確なら、
5) うまくいかない時の定石
reports/harvest_report.jsonでmissing: ["clearance"]等になっている → ソースにCL/Vが書かれていません- v0.8 では
reason_codesとEXCLUDED.csv:reason_jsonに「なぜ拾えなかったか」が残ります - DailyMedの別SETIDを試す(brand/genericで差がある)
- PubMed/PMCの別論文(PMCIDがあるもの)を指定する
- それでも無理なら手入力(その方が早いケースが多い)
- v0.8 では
5) いちばん速い実行フロー(”除外22”だけ回す)
v0.1相当の「15 selected / 22 excluded」を all_pk_parameters_combined.csv から再現し、 除外22薬剤だけを harvest にかける最短手順です。
5.1 jobs.yml を作る(除外22)
python tools/make_jobs_from_csv_v01.py --in all_pk_parameters_combined.csv --out jobs_excluded22.yml
生成された jobs_excluded22.yml をそのまま使うか、既に用意済みの
jobs/jobs_excluded22_v01.yml を使ってOKです。
5.2 harvest → EXCLUDED集計 → 次の改善ポイント抽出
uv run --with requests --with lxml --with pyyaml python tools/harvest_and_generate.py \
--jobs jobs_excluded22.yml --repo . --default-dose-mg 100
python tools/rebuild_index.py
python tools/summarize_excluded.py --excluded EXCLUDED.csv --out-md reports/excluded_summary.md
EXCLUDED.csvには 理由コード(reason) と 詳細JSON(reason_json) が入りますreports/excluded_summary.mdに 理由コード集計 と 次のパーサ強化候補 がまとまります
5.3 ワンショットで回す
python tools/run_excluded22_flow.py --csv all_pk_parameters_combined.csv --repo .