Chronaxis用户手册English
本页目录

chronaxis.core.affine_numpy

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""按列执行单位的完整仿射转换,保持固定类型和逐位置质量掩码。23输入为 NumericArray、静态倍率/偏移与目标类型;输出形状保持(N,)的独立4只读 NumericArray。整数复用已有数组仿射核的精确逆区间算法;浮点使用5NumPy ufunc与有效掩码,不调用标量参考数值计算,不使用object数组或6逐样本Python回调。无效位置不参与运算,已有质量原因保留;不读写文件、7不改调用方数组、不保存样本历史。单位关系由表达式或结果编译器事先证明。8"""910# 共享静态声明检查;实际数组计算与标量参考分开。11from math import isfinite1213import numpy as np1415from .affine import _validate_affine16from .normalize_numpy import _affine_integer17from .numeric import INTEGER_BOUNDS18from .numeric_numpy import NumericArray, _output, to_float_numpy19from .types import QualityFlag, SignalDType202122def _float_coefficient(value: int | float) -> tuple[float | None, QualityFlag]:23    """仅转换一个编译期系数,不对样本调用Python标量参考。2425    参数: value为已验证的原生整数或有限浮点系数。26    返回: 有限浮点值与NONE,或None与NONFINITE/PRECISION_LOSS。27    异常: 无主动异常;整数超出浮点范围转换成NONFINITE。28    """29    # 配置常量数量固定,与样本数量无关;整数往返不能先舍入原整数。30    try:31        result = float(value)32    except OverflowError:33        return None, QualityFlag.NONFINITE34    if not isfinite(result):35        return None, QualityFlag.NONFINITE36    if type(value) is int and int(result) != value:37        return None, QualityFlag.PRECISION_LOSS38    return result, QualityFlag.NONE394041def affine_numpy(value: NumericArray, scale: int | float, offset: int | float,42                 dtype: SignalDType) -> NumericArray:43    """在有效位置执行value*scale+offset,不以中间回绕或舍入替代结果。4445    参数: value为(N,)数值列;scale、offset为有限静态系数;dtype为目标46        数值类型。整数目标要求整数输入和整数系数;需要小数时应声明float64。47    返回: 同长独立只读NumericArray;无效位置仅存零占位,原因保持或增加48        OVERFLOW、NONFINITE、PRECISION_LOSS。输入和有效/质量列不被修改。49    异常: TypeError/ValueError为声明结构错误;MemoryError等分配异常传播。50    边界: 温度偏移抵消为零有效;只有零偏移、非零因子的非零值变成零时,51        才按纯倍率下溢报告精度损失。全部数值操作按数组执行。52    """53    # 结构与静态目标类型错误不能悄悄当成数据缺失。54    if not isinstance(value, NumericArray):55        raise TypeError('仿射数组转换需要NumericArray')56    _validate_affine(value.dtype, dtype, scale, offset)57    # 整数复用已验数组算法,先求完整仿射的合法输入区间,再执行安全乘加。58    if dtype in INTEGER_BOUNDS:59        values, overflow = _affine_integer(value.values, value.valid, dtype, scale, offset)60        quality = value.quality.copy()61        quality[overflow] |= np.uint16(QualityFlag.OVERFLOW)62        return _output(dtype, values, quality)63    # 输入整数的精度用数组尾位掩码核实,不能先astype再与已舍入值比较。64    converted = to_float_numpy(value)65    quality = converted.quality.copy()66    factor, factor_quality = _float_coefficient(scale)67    shift, shift_quality = _float_coefficient(offset)68    coefficient_quality = factor_quality | shift_quality69    values = np.zeros(len(value.values), dtype=np.float64)70    # 系数精度失败影响原本有效的输入,保留同时发生的输入精度原因。71    if coefficient_quality != QualityFlag.NONE:72        quality[value.valid] |= np.uint16(coefficient_quality)73        return _output(dtype, values, quality)74    # ufunc只触碰通过精度检查的位置;中间浮点异常在完整结果上明确分类。75    selected = converted.valid76    with np.errstate(over='ignore', under='ignore', invalid='ignore'):77        np.multiply(converted.values, factor, out=values, where=selected)78        np.add(values, shift, out=values, where=selected)79    quality[selected & ~np.isfinite(values)] |= np.uint16(QualityFlag.NONFINITE)80    # 偏移抵消为零是合法数值,不将-273.15℃转换到0K标成下溢。81    if shift == 0 and factor != 0:82        underflow = selected & (converted.values != 0) & (values == 0)83        quality[underflow] |= np.uint16(QualityFlag.PRECISION_LOSS)84    return _output(dtype, values, quality)85
Chronaxis 用户手册 · 离线阅读