Preformu / tests /test_content_uniformity.py
Kevinshh's picture
feat: 意图保真(intent-fidelity) + 描述性梳理技能 + 相容性引擎升级; 修复转置宽表解析/CQA对账/澄清交互/功能切换串显; .gitignore 排除专利与机密Demo数据
0e6887b
Raw
History Blame Contribute Delete
3.12 kB
"""含量均匀度接受值(AV)计算器测试。
基准校验:直接复算 SL-0010 源表中实验室自报的 A、S、A+2.2S 列,验证与药典
(ChP 0941)一致;并覆盖 USP <905> 常数、限值判定与不臆断退化。
"""
from __future__ import annotations
import math
from skills.descriptive_summary.content_uniformity import acceptance_value
# SL-0010 三规格含量均匀度逐单位含量(相对标示量%)。
_CU_20 = [99.19, 100.0, 97.68, 96.0, 98.81]
_CU_40 = [99.25, 101.43, 99.59, 97.71, 99.48]
_CU_60 = [100.5, 101.01, 99.85, 99.98, 97.23]
def test_chp_matches_lab_reported_20ug():
"""20μg:复算 A/S/AV 应与源表 A=1.664、S=1.5500、A+2.2S=5.074 一致。"""
r = acceptance_value(_CU_20, standard="chp")
assert math.isclose(r.mean, 98.336, abs_tol=1e-3)
assert math.isclose(r.deviation, 1.664, abs_tol=1e-3) # A=|100−X̄|
assert math.isclose(r.std, 1.55000967738914, rel_tol=1e-6) # S
assert math.isclose(r.k, 2.2)
assert math.isclose(r.acceptance_value, 5.074, abs_tol=1e-3) # A+2.2S
assert r.within_spec is True
assert r.limit == 15.0 and r.limit_is_default is True
def test_chp_matches_lab_reported_40ug_60ug():
r40 = acceptance_value(_CU_40, standard="chp")
assert math.isclose(r40.deviation, 0.508, abs_tol=1e-2) # 源 A=0.508
assert math.isclose(r40.acceptance_value, 3.418, abs_tol=1e-2) # 源 A+2.2S=3.418
assert r40.within_spec is True
r60 = acceptance_value(_CU_60, standard="chp")
assert math.isclose(r60.deviation, 0.286, abs_tol=1e-2) # 源 A=0.286
assert math.isclose(r60.acceptance_value, 3.504, abs_tol=1e-2) # 源 A+2.2S=3.504
assert r60.within_spec is True
def test_usp_reference_m_and_constant():
"""USP <905>:X̄ 落在 [98.5,101.5] 内 → M=X̄ → AV=k·s,k=2.4(n≤10)。"""
r = acceptance_value(_CU_20, standard="usp")
assert r.reference_m is not None
# 98.336 < 98.5 → M=98.5;|M−X̄|=0.164
assert math.isclose(r.reference_m, 98.5, abs_tol=1e-9)
assert math.isclose(r.deviation, abs(98.5 - r.mean), abs_tol=1e-6)
assert math.isclose(r.k, 2.4)
assert math.isclose(r.acceptance_value, r.deviation + 2.4 * r.std, rel_tol=1e-9)
def test_usp_mean_within_band_uses_mean_as_m():
vals = [100.0, 100.5, 99.5, 100.2, 99.8] # 均值≈100 落在带内
r = acceptance_value(vals, standard="usp")
assert math.isclose(r.reference_m, r.mean, rel_tol=1e-9)
assert math.isclose(r.deviation, 0.0, abs_tol=1e-9)
def test_explicit_limit_overrides_default():
r = acceptance_value(_CU_20, standard="chp", limit=10.0)
assert r.limit == 10.0 and r.limit_is_default is False
def test_fails_when_av_exceeds_limit():
"""构造高变异样本使 AV>L → 判不合格。"""
vals = [80.0, 120.0, 95.0, 110.0, 90.0]
r = acceptance_value(vals, standard="chp")
assert r.acceptance_value > 15.0
assert r.within_spec is False
def test_insufficient_sample_returns_none():
assert acceptance_value([100.0], standard="chp") is None
assert acceptance_value([], standard="chp") is None