Chronaxis用户手册English
本页目录

chronaxis.core.unit_conversion

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""在配置编译时确定版本4的单位转换和数值类型。23输入是声明单位、完整转换系数和dtype,输出系数、校验状态及固定目标类型。4只复用不可变单位注册表;不读取DBC、不处理样本、不创建运行时全局状态。5当前只接受版本4;未知单位仍须明确转换,不隐式回退到旧单位规则。6"""78# 精确分数用于验证配置;数值执行继续使用既有两个独立后端。9from fractions import Fraction1011from .types import SignalDType12from .units import require_number13from .unit_registry import conversion, resolve_unit141516def require_config_version(version: int) -> int:17    """检查已有配置版本选择,不把bool当作整数版本。1819    参数: version为原生整数4。20    返回: 原版本。21    异常: ValueError为未支持的版本或错误类型。22    """23    # 版本在计划内冻结,不能从全局状态隐式切换。24    if type(version) is not int or version != 4:25        raise ValueError('当前仅支持config_version=4;请按当前配置重新填写旧版本')26    return version272829def binding_version(definitions, explicit: int | None = None) -> int:30    """校验所有定义与可选显式版本,仅返回当前版本4。3132    参数: definitions为已检查的定义序列,explicit可省略;空绑定同样使用4。33    返回: 4。异常: ValueError为任一定义或显式参数不支持的版本。34    """35    # 不把空绑定作为旧规则回退入口;逐项校验也拒绝伪造的旧定义。36    for definition in definitions:37        require_config_version(definition.config_version)38    if explicit is not None:39        require_config_version(explicit)40    return 4414243def affine_conversion(input_unit: str, unit: str) -> tuple[int | float, int | float, str]:44    """生成一次源单位到目标单位的完整转换。4546    参数: input_unit为已经解码值的单位,unit为目标单位。47    返回: (scale, offset, status);整数系数保留int,同名未知标签保持1、0、unverified。48    异常: ValueError为已知单位冲突、异名未知关系、非法语法或float倍率不可表示。49    """50    # 未知标签不能据拼写相同假称已验证,也不能猜测隐含工程倍率。51    source, target = resolve_unit(input_unit), resolve_unit(unit)52    if source is None or target is None:53        if input_unit != unit:54            raise ValueError('未知单位之间不能自动推导转换,请填写完整scale/offset')55        return 1, 0, 'unverified'56    scale, offset = conversion(source, target)57    factor = (scale.factor.numerator if scale.pi_power == 0 and scale.factor.denominator == 158              else scale.to_float())59    shift = offset.numerator if offset.denominator == 1 else float(offset)60    return factor, shift, 'verified'616263def validate_conversion_v4(input_unit: str, unit: str, scale: int | float,64                           offset: int | float, direction_factor: int = 1) -> str:65    """验证调用方已经确定的完整转换,不再次叠加单位倍率。6667    参数: input_unit/unit为单位;scale/offset为完整转换;direction_factor为已核实方向。68    返回: verified或unverified。69    异常: TypeError为非原生系数;ValueError为单位或系数冲突。70    """71    # 显式完整系数不得被错误地当成额外标定后再次缩放。72    require_number(scale, 'signal.scale')73    require_number(offset, 'signal.offset')74    source, target = resolve_unit(input_unit), resolve_unit(unit)75    if source is None or target is None:76        return 'unverified'77    expected, shift = conversion(source, target)78    # 有理数检查优先,非终止/含pi倍率接受唯一的float64表示,不使用宽松容差。79    factor_matches = (expected.pi_power == 0 and80                      Fraction(str(scale)) == expected.factor * direction_factor)81    if not factor_matches:82        factor_matches = type(scale) is float and scale == expected.to_float() * direction_factor83    offset_matches = Fraction(str(offset)) == shift or type(offset) is float and offset == float(shift)84    if not factor_matches or not offset_matches:85        raise ValueError(f'已知单位转换系数与{input_unit}→{unit}不一致')86    return 'verified'878889def converted_dtype(dtype: SignalDType, scale: int | float, offset: int | float) -> SignalDType:90    """在编译期决定单位转换是否需要浮点类型。9192    参数: dtype为原声明类型,scale/offset为完整有限转换系数。93    返回: 有分数倍率或偏移的整数提升FLOAT64,其余保持原类型。94    异常: TypeError为错误dtype或系数;ValueError为非有限系数。95    """96    # 提升与样本值无关;大整数是否可精确转float仍由实际数值核检查。97    if not isinstance(dtype, SignalDType):98        raise TypeError('dtype必须为SignalDType')99    require_number(scale, 'scale')100    require_number(offset, 'offset')101    if dtype in (SignalDType.INT64, SignalDType.UINT64):102        if Fraction(str(scale)).denominator != 1 or Fraction(str(offset)).denominator != 1:103            return SignalDType.FLOAT64104    return dtype105
Chronaxis 用户手册 · 离线阅读