mcpField
R
relsa-severity-assessment

relsa-severity-assessment

github.com/kalarislabsその他7343 回インストール4 日前に更新
リポジトリ

relsa-severity-assessment について

動物福祉研究者向けの Python スキルです。複数の測定値から個体ごとの RELSA 重症度スコアを算出し、推移を予測してデータに基づく重症度ゾーンを推定します。予測と閾値は評価の補助であり、判断規則ではありません。

主な機能

  1. 01複数の測定値を RELSA スコアに統合
  2. 02ARIMA によるスコアと区間の予測
  3. 03KDE による重症度ゾーンの推定
  4. 04変数ごとのスコア寄与を出力

活用シーン

  1. 01臨床データやバイオマーカーによる重症度評価
  2. 02人道的エンドポイントに近い動物の把握
  3. 03研究群間の負担の比較
  4. 04動物福祉に関する重症度報告の作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill relsa-severity-assessment

インストール後、Claude Code で/relsa-severity-assessmentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
example_cohort.csv
references/
forecasting.md
relsa-method.md
thresholds-and-zones.md
scripts/
_common.py
forecast_relsa.py
kde_thresholds.py
relsa_score.py

詳細

RELSA の重症度評価と人道的エンドポイントの予測

概要

動物実験における重症度評価は、法的に義務付けられており、科学的にも重要な役割を果たします。 人道的エンドポイントの判断に影響し、動物福祉のモニタリングが不十分だと再現性が損なわれます。 一般的な方法では、それぞれの測定値を個別に評価します。たとえば、体重減少や臨床スコアなどです。 そのため、個々の動物が実際にどの程度苦痛を受けているかを判断するのは困難です。

このスキルでは、この課題に対処するために発表された2つの手法を実装しています。

  • RELSA(Talbot et al., 2022)は、複数のアウトカム指標を組み合わせ、既知の負担を持つ参照セットに対する相対値として、各時点の動物ごとに1つのスコアを算出します。RELSA = 0 はベースライン、RELSA = 1 はその動物が参照セットの最大偏差に達したことを示します。
  • foRcast(Lutscher et al., 2026)は、個々の動物の RELSA の推移に ARIMA モデルを当てはめ、95%予測区間とともに次のスコアを予測します。これにより、人道的エンドポイントに近づいている動物を、到達前に特定できます。RELSA 尺度でのカーネル密度推定により、解釈のための「注意」ゾーンと「危険」ゾーンの候補を設定します。

目的は改善です。リスクのある動物により早く注意を払い、回復する可能性のあった動物の安楽死を避けます。どちらの手法も重症度評価を補助するものであり、判断基準ではありません。報告時の留意事項については、適用範囲を参照してください。

このスキルを使用する場面

  • 体重減少、体温、臨床スコア、バイオマーカー、テレメトリーを統合し、動物ごとの重症度スコアを算出する場合
  • コホート内で人道的エンドポイントに達するリスクのある動物を特定したり、今後の時点での重症度スコアを予測したりする場合
  • 共通の相対尺度で、処置群、介入、動物モデル間の重症度を比較する場合
  • データから重症度尺度の閾値やゾーンを定義する場合
  • 動物福祉報告書、3Rs/改善分析、または EU 指令 2010/63/EU に基づく申請書の重症度評価セクションを作成する場合

重症度スコアではない時系列を一般的に予測するには、timesfm-forecasting または statsmodels を使用してください。研究デザインとサンプルサイズについては、experimental-design と statistical-power を使用してください。

インストール

uv pip install "numpy>=1.26" "pandas>=2.0" "scipy>=1.11" "statsmodels>=0.14" matplotlib

relsa_score.py と kde_thresholds.py は numpy/pandas/scipy のみを必要とします。予測には statsmodels が、図の作成には matplotlib が必要です。

データ形式

CSV では、動物ごと、時点ごとに1行を指定します。

idtreatmentconditiondaytempweightscoreil6
M01treatedendpoint-137.1525.17035.1
M01treatedendpoint037.2625.25039.5
M01treatedendpoint135.8323.124162.0
  • id と時間列(day、time、hour など)が必須です。treatment と condition は任意のラベルで、グループ分けや参照セットの選択に使用します。
  • 時間の単位は日、時間、分のいずれでも構いませんが、動物ごとに単調に推移するようにしてください。RELSA の規約では、ベースライン時点を -1 とします。
  • 動物ごと、時点ごとに1行としてください。 時間単位のテレメトリーは、まず各区間で1つの値に平均化してください(発表されたモデルでは、心拍数、HRV、体温を平均し、活動量を合計します)。
  • 測定値が欠損している場合は空欄にしてください。欠損値はスコアから除外し、補完しません。欠損値を「偏差なし」として扱うと、重症度が過小評価されます。

assets/example_cohort.csv は、すべてのコマンドで使用する小規模な合成コホートです(マウス6匹、9日間、体温、体重、0~8の臨床スコア、IL-6 様バイオマーカー)。そのため、以下の各コマンドは記載どおりに実行できます。

結果を左右する4つの判断

これらを明確に決め、メソッドに記述してください。手順に関して、これ以上に重要なことはありません。

1. 方向性 — 悪化するとどの変数が上昇するか? 低下するのがデフォルトです(体重、活動量、摂餌量、穴掘り行動、回し車での走行)。上昇する変数は --turned として宣言する必要があります。臨床スコア、炎症性バイオマーカー、発熱、頻脈が該当します。これを間違えると、「逆方向」の偏差はゼロに切り下げられるため、その変数は何も寄与しません。しかも、そのことは通知されません。体温の変化はモデルによって異なり、敗血症およびエンドトキシン血症では低下し、発熱モデルでは上昇します。データからこれを判断することはできません。公表済みの敗血症モデルでは、活動量がベースラインを下回るよりも上回る方向に大きく変動することが正当に起こり得ます。そのため、宣言した方向に一度も変化しない変数だけが検出可能であり、build_reference() はまさにそのケースについて警告します。

2. 参照セット — 何を基準にするか? RELSA スコアは、参照セットなしでは意味を持ちません。モデルで最も負荷が大きいと想定されるグループを使用してください(公表済みの研究では、最高用量の治療群、またはエンドポイントに達した治療群が使用されています)。参照セットの負荷が軽すぎると、すべてのスコアが1を上回り、重すぎるとすべてのスコアが0に近づきます。--save-reference で保存し、--load-reference で再利用すれば、後続のコホートも同じ尺度で評価できます。

3. ベースラインがゼロのスコア。 健康な動物の臨床スコアが0の場合、比率による正規化はできません。0/0 は未定義です。代わりに --score-scale score=8 を使ってスコアの尺度を対応付けます(健康状態 → 100%、最悪状態 → 200%)。これにより、そのスコアは上昇するものとしても扱われます。この対応付けは、スコア1点が体重の1パーセントに対してどの程度の価値を持つかというモデル上の選択です。その選択を明記してください。もう1つの方法は、スコアを RELSA から除外し、独立したエンドポイント基準として使用することです。

4. どの変数を全期間にわたって測定するか。 スコアは利用可能な変数の平均を取るため、軌跡の途中で変数が出現したり消失したりすると、それだけでスコアが変化します。公表済みの敗血症データでは、安楽死当日にしか記録されていない体重を追加すると、生物学的な理由がないにもかかわらず、その動物のエンドポイントスコアが0.93から0.83に下がります。relsa_scores() は構成が変化した場合に警告します。全期間を通じて測定されている変数をスコアに使用してください。

ワークフロー

ステップ 1 — RELSA スコアを計算する
python scripts/relsa_score.py assets/example_cohort.csv \
    --variables weight,temp,score,il6 \
    --normalize weight,temp,il6 \
    --turned il6 \
    --score-scale score=8 \
    --baseline-time -1 \
    --reference-group condition=endpoint \
    --save-reference reference.json \
    --out relsa_scores.csv

参照モデルが出力されるため、尺度を監査できます。

reference model: assets/example_cohort.csv [condition=endpoint]
  animals=2  rows=18  baseline_time=-1.0
  variable      turned   max reached   max delta
  weight            no         82.40       17.60
  temp              no         92.79        7.21
  score            yes        187.50       87.50
  il6              yes        797.72      697.72

relsa_scores.csv には各変数の重みとスコアが記録されているため、スコアの根拠を説明できます。ここでは、M01 はエンドポイントまで悪化し、M03 は3日目にピークを迎えて回復しています。

 id  time  weight  temp  score  il6  n_vars  relsa
M01     1    0.46  0.49   0.57 0.52       4   0.51
M01     3    0.84  0.76   1.00 0.89       4   0.88
M01     5    1.00  1.00   1.00 1.00       4   1.00
M03     3    0.56  0.44   0.57 0.54       4   0.53
M03     5    0.35  0.26   0.43 0.32       4   0.35
M03     7    0.12  0.06   0.14 0.11       4   0.11

重みが1.00ということは、その変数が参照セットの最大値に達したことを意味します。n_vars は、その時点でスコアに含まれた変数の数です。

オブジェクトが必要な場合は、Python でも同じ処理を行えます。

import sys; sys.path.insert(0, "scripts")
from _common import read_relsa_table, score_to_percent
from relsa_score import prepare, build_reference, relsa_scores

frame = read_relsa_table("assets/example_cohort.csv")
frame["score"] = score_to_percent(frame["score"], max_score=8)   # 0-8 clinical score
VARS, TURNED = ["weight", "temp", "score", "il6"], ["score", "il6"]

prepared  = prepare(frame, normalize=["weight", "temp", "il6"], baseline_time=-1)
reference = build_reference(prepared[prepared.condition == "endpoint"],
                           variables=VARS, turned=TURNED, baseline_time=-1,
                           label="endpoint-reaching animals")
scores    = relsa_scores(prepared, reference)
ステップ 2 — エンドポイントを予測する

エンドポイントより前の時点までのすべてのデータで学習し、エンドポイント時のスコアを予測して、その予測を評価します:

python scripts/forecast_relsa.py relsa_scores.csv \
    --animals M01,M02 --endpoints M01=5 --endpoints M02=6 \
    --group-col condition --plot-dir figs --endpoint-line 1.0
 id  time  predicted    lower    upper        model  actual
M01   5.0   0.932585 0.670443 1.194728 ARIMA(1,1,0)    1.00
M02   6.0   0.955696 0.748309 1.163084 ARIMA(1,1,0)    0.94

   group             id        model  n   rmse  picp  mpiw
endpoint            M01 ARIMA(1,1,0)  1 0.0674 100.0 0.524
endpoint            M02 ARIMA(1,1,0)  1 0.0157 100.0 0.415
endpoint -- endpoint --               2 0.0489 100.0 0.470
                OVERALL               2 0.0489 100.0 0.470

3 つの指標をまとめて報告します。RMSE は点予測の精度、PICP は実測値が区間内に入る割合、MPIW は RELSA 単位での平均区間幅です。区間を何も示さないほど広くすれば、モデルは PICP = 100% に達する可能性があります。これは、論文の膵臓がんの行(PICP 100%、MPIW 7.35、つまり RELSA の範囲の 735%)が示すとおりです。

ライブモニタリングでは、代わりに各時点で 1 ステップ先を予測します:

python scripts/forecast_relsa.py relsa_scores.csv --mode rolling --animals M03

予測を信頼する前に、次の 2 点を確認してください。

  • 補間はデフォルトで有効です(--interpolate-step 0.1)。1 日あたり 1 回の測定では ARIMA にとってデータが疎すぎるためです。正直な不確実性と引き換えに、実用的なモデル選択と、より狭い区間が得られます。測定頻度が十分な場合は --interpolate-step 0 を設定してください。
  • ARIMA は急激な崩壊を予測できません。 定常性と線形性を仮定するため、エンドポイント直前の数時間に生じる急激な悪化は、滑らかな過去の推移から予測できません。これは論文自体の失敗例でも示されています。区間の 上限 を参考に行動し、体調不良に見える動物について、低い予測値を理由に対応を見送らないでください。
ステップ 3 — 重症度ゾーンでスコアを位置づける
python scripts/kde_thresholds.py relsa_scores.csv \
    --group treatment=treated --n-thresholds 2 --plot zones.png --json zones.json
KDE on 33 RELSA scores  (bandwidth = 0.1502)
  candidate thresholds (density minima): 0.703
  density modes: 0.264, 0.866
  normal    [0.000, 0.703)  n=25 (75.8%)
  danger    >= 0.703  n=8 (24.2%)

しきい値は、スコア密度の 最小値、つまりスコアのクラスター間にあるデータの少ない谷です。エンドポイントに達した動物、生存動物、シャム動物を含めてください。ゾーンはこれらの状態を区別するためのものなので、すべてを含める必要があります。

しきい値を信頼する前に、帯域幅を確認してください。 公開された敗血症データでは、この実装は 0.355 と 0.655 に最小値を検出します(公開値:0.337 と 0.643)。しかし、帯域幅を 10% 大きくすると、どちらの最小値も完全に消失します。references/thresholds-and-zones.md のスイープを実行し、数字を 2 つだけ挙げるのではなく、スイープ結果を報告してください。しきい値のリストが空でも問題ありません。スコアが 1 つのクラスターを形成し、データに基づいて区切れる箇所がないことを意味します。

制約:報告時には次の点を明記してください

  • RELSA は重症度評価を補助するものであり、決定的な指標ではありません。 RELSA スコアが低くても、ほかに苦痛の兆候が見られる動物には、引き続き適切な対応が必要です。どちらの手順も、死亡を予測するための検証済みの方法ではありません。
  • KDE ゾーンは規制上の重症度分類ではありません。 EU 指令 2010/63/EU のカテゴリー(非回復、軽度、中等度、重度)は、別の手順で事前に割り当てられます。論文では、しきい値は「規制上の重症度分類と混同すべきではない」と明記されており、直接対応づけることはできません。
  • スコアは、参照セットやモデルが異なる場合、比較できません。 RELSA はその設計上、相対的な指標であり、臨床スコアリングも研究室間で統一されていません。スコアとともに、必ず参照セットを報告してください。
  • 公開されたエビデンスは概念実証にすぎません。7 つのモデルにまたがる 13 匹の動物が対象で、そのうち 5 つの行は 1 匹または 2 匹の動物に基づいています。全体の RMSE 0.069 と PICP 96% は、13 件のエンドポイント予測に基づいています。
  • スコアの過小評価は危険な誤りです。注意が不十分になり、安楽死の判断が遅れる可能性があります。一方、過大評価の場合は、単に追加のケアを促すだけです。

報告チェックリスト

重症度分析を再現可能にするには、以下のすべてを明記する必要があります。

  1. 評価指標、その単位、および方向性(どの指標の方向を反転したか、その理由)。
  2. ベースラインの時点または期間、および正規化した変数。
  3. 順序変数に適用したスコアマッピングと、その尺度。
  4. 参照セット:対象の動物、グループ、数、および最も大きな負担を示すと仮定する理由。
  5. RELSA スコアとは分けて、研究で実際に適用した人道的エンドポイント基準。
  6. 予測の場合:補間のステップ、動物ごとに選択した ARIMA の次数、RMSE、PICP、 および MPIW。
  7. 閾値の場合:帯域幅、スコア数、および帯域幅の感度分析。
  8. ソフトウェアのバージョン、ならびに閾値はモデル固有であり、規制上の評価ではないという記述。

よくある落とし穴

  1. 方向性の誤り — 上昇する変数が --turned に指定されていない場合、警告は出ず、その変数の寄与は正確に ゼロになります(ただし、一度も低下しない場合を除きます)。参照モデルの表を自分で確認してください。低下する変数では max reached が 100 未満、方向を反転した変数では 100 を超えている必要があり、max delta はその指標として妥当な大きさである必要があります。
  2. パーセンテージの二重正規化 — bwc [%] とマッピング済みスコアはすでにパーセント尺度なので、--normalize に渡すと平坦化されます。
  3. ベースラインがゼロ — 臨床スコアが 0 の場合、比率は未定義になります。この変数は警告とともにすべて NaN になります。--score-scale を使用してください。
  4. 負担を表さない参照セット — その中で変動しない変数は、ゼロ除算の代わりにエラーを発生させ、ほとんど変動しない変数はすべてのスコアを過大にします。
  5. 軌跡に沿った変数構成の変更 — 上記の判断 4 を参照してください。
  6. MPIW を良い指標と見なす — 広い区間は PICP を上げる一方で、予測の有用性を損ないます。
  7. 帯域幅を示さずに KDE 閾値を報告する — 帯域幅を 10% 変更すると、閾値が消えることがあります。
  8. 予測を待機の許可と見なす — モデルは急激な悪化を検知できず、プロトコルの人道的エンドポイント基準が常に優先されます。
  9. モデル間で RELSA スコアを比較する — 1 つの参照フレーム内でのみ有効です。

リソース

スクリプト
  • scripts/relsa_score.py — RELSA の手順:prepare()、build_reference()、 relsa_scores()、relsa_weights()、および JSON にシリアライズする ReferenceModel。 R パッケージの公開済み計算例を小数点以下 2 桁まで再現します。
  • scripts/forecast_relsa.py — foRcast ツール:auto_arima()(Hyndman–Khandakar による AICc のステップワイズ選択)、 forecast_animal()、predict_endpoint()、rolling_forecast()、 forecast_indirect()、summarize()、および Figure 1 形式のプロット。
  • scripts/kde_thresholds.py — 重症度ゾーン:bw_nrd0()(R の帯域幅)、density_curve()、 find_thresholds()、ゾーンの割り当て、および Figure 3 形式の密度プロット。
  • scripts/_common.py — RELSA 形式の I/O、検証、score_to_percent()、 percent_of_baseline()、および forecast_metrics()(RMSE/PICP/MPIW)。
参考資料
  • references/relsa-method.md — 4 つの手順の詳細、スコアとゼロベースラインの問題、 変数構成の落とし穴、R パッケージとの一致に関する注記、ならびに公開済み 7 モデルすべての評価指標とエンドポイント基準。
  • references/forecasting.md — ARIMA の選択、補間が歪みを生む理由、直接予測と間接予測、指標、公開済みの表 1、およびこの移植版で再現される内容。
  • references/thresholds-and-zones.md — KDE の手法、公開済みの閾値、帯域幅の感度分析、規制上の境界、および KDE で結果が得られない場合の代替手段。
アセット
  • assets/example_cohort.csv — 温度、体重、臨床スコア、バイオマーカーを含む、マウス 6 匹の合成コホート。説明用であり、実データではありません。
関連するスキル
  • experimental-design、statistical-power — 研究の設計とグループの規模設定に使用します。
  • statsmodels、timesfm-forecasting — 一般的な時系列モデリングに使用します。
  • statistical-analysis、scientific-visualization — グループ間の比較と図の作成に使用します。
主要な参考文献
  • Talbot, S. R. et al. (2022). RELSA — 多次元的な手順による、実験手順におけるウェルビーイングの比較評価と重症度の定量的判定。Front. Vet. Sci. 9:937711. R パッケージ:https://github.com/mytalbot/RELSA
  • Lutscher, S. et al. (2026). 多変量重症度スコアを用いた時系列予測と閾値の定義による、人道的エンドポイント検出の改善。Front. Physiol. 17:1869563.
  • Hyndman, R. J. & Khandakar, Y. (2008). 自動時系列予測:R 用 forecast パッケージ。J. Stat. Softw. 27, 1–22.
  • EU Commission (2010). 科学目的で使用される動物の保護に関する指令 2010/63/EU。

エージェントの作業手順

  1. 環境を確認します。 研究の目的、制約(予算、時間、倫理)と、ユーザーが下す必要のある判断を明確にします。
  2. 入力を特定します。 データまたはユーザーから、形式、識別子、パラメーターを確認します。結果に影響する値は推測せず、質問してください。
  3. まず小規模に実行します。 選択肢を拡大する前に、前提を明示した短い候補リストを提示します。
  4. 上記の手順と参考文献を使用して、タスク全体を実行します。
  5. 結果を検証します。 前提を明記し、明示した基準で代替案を比較します。また、統計計画には検出力と分析方法の選択を含めます。
  6. 報告します。 実行した内容(バージョン、コマンド、パラメーター)、確認した内容、未解決の不確実性を明記します。
発生した場合対応
設計上の選択が不明な効果量や費用に依存する単一の推測ではなく、シナリオ(楽観的、期待、悲観的)を提示します。
これらの手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンに存在しないインストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認して適宜対応し、ユーザーに伝えます。API を捏造してはいけません。
必須の入力、識別子、パラメーターが曖昧であるユーザーに質問するか、実行前に前提を明示します。

誠実性に関する規則

  • 結果、パラメーター、識別子、引用、統計値を捏造してはいけません。実行または検証できない場合は、その旨を明確に伝えます。
  • 推測には推測であると明記し、確立された根拠と新たな仮説を区別します。
  • ここに記載されたバージョン固有の詳細は古くなっている可能性があるため、インストール済みバージョンの公式ドキュメントで確認します。
  • 費用が発生する操作、共有 GPU またはクラウドのクォータを消費する操作、個人データまたは患者データに触れる操作、取り消せない操作を行う前に、ユーザーに確認します。

コメント