Chronaxis用户手册English
本页目录

chronaxis.core.rolling_values

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""对已裁剪的有限保持区间求一个滚动网格值。23权重是实际纳秒或原周期按实际重叠分摊的计量纳秒。独立参考路径使用精确4有理数累计,数组路径对当次窗口执行 NumPy 掩码和缩放加权归约。历史维护、5覆盖门槛、网格原点和事件均由调用者处理;本模块不保存上一个窗口。6"""7from fractions import Fraction8from math import frexp, isfinite, ldexp9from .numeric import ScalarValue10from .types import SignalDType as D, QualityFlag as Q111213def rolling_value(operation, backend, values, weights, conversion, dtype):14    """计算选中窗口值。参数: 操作、后端、有效数列、正权重、目标换算、类型。返回: ScalarValue。异常: 配置错误。"""15    if operation in ('rolling_minimum','rolling_maximum'):16        if backend=='reference':17            from .affine import affine_reference18            value=(min if operation=='rolling_minimum' else max)(values)19            return affine_reference(ScalarValue(value,dtype),conversion.factor,conversion.offset,conversion.dtype(dtype))20        import numpy as np21        from .numeric_numpy import DTYPES, NumericArray22        from .affine_numpy import affine_numpy23        col=np.asarray(values,dtype=DTYPES[dtype])24        result=(np.min if operation=='rolling_minimum' else np.max)(col)25        column=NumericArray(dtype,np.array([result],dtype=DTYPES[dtype]),np.ones(1,dtype=bool),np.zeros(1,dtype='uint16'))26        converted=affine_numpy(column,conversion.factor,conversion.offset,conversion.dtype(dtype))27        valid=bool(converted.valid[0])28        return ScalarValue(converted.values[0].item() if valid else None,converted.dtype,valid,Q(int(converted.quality[0])))29    # 整数进入浮点统计须无损。无效样本不能经插值或舍入变为普通值。30    if dtype in (D.INT64,D.UINT64) and any(int(float(v))!=v for v in values):31        return ScalarValue(None,D.FLOAT64,False,Q.PRECISION_LOSS)32    if backend=='reference':33        total=sum(Fraction(v)*w for v,w in zip(values,weights))34        measure=sum(weights) if operation=='rolling_time_mean' else 10**935        exact=total*Fraction(conversion.factor)/measure+Fraction(conversion.offset)36        try:37            number=float(exact)38        except OverflowError:39            return ScalarValue(None,D.FLOAT64,False,Q.NONFINITE)40        lost=number==0 and exact!=041    else:42        import numpy as np43        numbers=np.asarray(values,dtype=np.float64)44        w=np.asarray(weights,dtype=np.float64)45        from .calculations_numpy import _sum_finite_numpy46        total_weight=float(np.sum(w))47        normalized=w/total_weight48        with np.errstate(under='ignore'):49            terms=numbers*normalized50        # 对极小项先放大再乘权重。真实纳秒和原驱动比例均有int64界限,51        # 2^512足以使这些暂存项不会因单项落入次正规范围就丢掉其合计。52        tiny=(np.abs(terms)<np.finfo('float64').tiny)&(numbers!=0)53        total,failed,quality=(_sum_finite_numpy(terms[~tiny]) if np.any(~tiny) else (0.,False,Q.NONE))54        if failed:55            return ScalarValue(None,D.FLOAT64,False,quality)56        extra_exponent=057        if np.any(tiny):58            residual,failed,quality=_sum_finite_numpy(np.ldexp(numbers[tiny],512)*normalized[tiny])59            if failed:60                return ScalarValue(None,D.FLOAT64,False,quality)61            if abs(total)<=1:62                total=ldexp(total,512)+residual63                extra_exponent=-51264            else:65                total+=ldexp(residual,-512)66        mantissa,exponent=frexp(total)67        factor,ef=frexp(conversion.factor)68        scale,es=frexp(1 if operation=='rolling_time_mean' else total_weight/1e9)69        try:70            number=ldexp(mantissa*factor*scale,exponent+extra_exponent+ef+es)+conversion.offset71        except OverflowError:72            return ScalarValue(None,D.FLOAT64,False,Q.NONFINITE)73        lost=number==0 and total!=0 and not conversion.offset74    if not isfinite(number) or lost:75        return ScalarValue(None,D.FLOAT64,False,Q.NONFINITE if not isfinite(number) else Q.PRECISION_LOSS)76    return ScalarValue(number,D.FLOAT64)77
Chronaxis 用户手册 · 离线阅读