Chronaxis用户手册English
本页目录

chronaxis.core.enum_codes

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""在 v4 表达式中读取按需保留的枚举原始整数列,标签索引没有原码含义。"""23from .numeric import INTEGER_BOUNDS, ScalarValue4from .types import QualityFlag as Q, SignalDType as D5from math import isfinite678def validate_code_dtype(dtype, choices):9    """检查声明的整数存储类型及其可表示的 choices 键。1011    参数: dtype 为 INT64 或 UINT64,choices 为原代码到逻辑标签的映射对。12    返回: None。异常: ValueError 为非整数类型、非整数键或定宽范围不符。13    同一标签可由多个不同代码表示,此处不反向查找标签。14    """15    if dtype not in (D.INT64, D.UINT64):16        raise ValueError('枚举 code_dtype 必须是 int64 或 uint64')17    lower, upper = INTEGER_BOUNDS[dtype]18    if any(type(code) is not int or not lower <= code <= upper for code, _ in choices):19        raise ValueError('枚举 choices 原码必须是 code_dtype 可表示的整数')202122def compile_enum_code(compiler, call):23    """从已编译的枚举来源取得原码 dtype 并登记本节点的真实依赖。2425    参数: compiler 为 v4 编译器,call 为 enum_code 的 AST 调用。26    返回: 输出单位 1 的整数节点。异常: 参数数量、来源或原码类型不明时报编译错误。27    """28    from .expression import _node29    if len(call.args) != 1 or call.keywords:30        compiler._error(call, 'enum_code 需要一个枚举信号参数')31    operand = compiler.visit(call.args[0])32    if operand.operator != 'name' or operand.dtype is not D.ENUM:33        compiler._error(call, 'enum_code 需要来自声明信号的枚举值')34    dtype = compiler.signals[operand.name].code_dtype35    if dtype is None:36        compiler._error(call, 'enum_code 需要已核实的整数原码类型,请声明 code_dtype: int64 或 uint64')37    return _node('enum_code', dtype, '1', (operand,))383940def code_dependencies(root):41    """收集参与本次计算或其派生子树的枚举原码,忽略单纯使用标签的名称。4243    参数: root 为已编译表达式根。返回: 需要同时读取原码的别名集合。44    异常: 输入不是表达式节点时传播属性错误。45    """46    found, seen, pending = set(), set(), [root]47    while pending:48        node = pending.pop()49        if id(node) in seen:50            continue51        seen.add(id(node))52        if node.operator == 'enum_code':53            found.add(node.args[0].name)54        pending.extend(node.args)55    return frozenset(found)565758def original_code(definition, original, quality=Q.NONE):59    """把已解码原整数装入声明的定宽类型,不经标签或浮点中转。6061    参数: definition 为有 code_dtype 的枚举,original 为映射前原值,quality 为来源质量。62    返回: 整数 ScalarValue。异常: 缺少有效类型声明时报错。未知映射不使整数本身无效。63    """64    dtype = definition.code_dtype65    lower, upper = INTEGER_BOUNDS[dtype]66    if quality == Q.NONE:67        if original is None:68            quality = Q.MISSING69        elif type(original) is float and not isfinite(original):70            quality = Q.NONFINITE71        elif type(original) is not int:72            quality = Q.DECODE_ERROR73        elif not lower <= original <= upper:74            quality = Q.OVERFLOW75        elif any(type(value) is int and value == original for value in definition.invalid_values):76            quality = Q.OUT_OF_RANGE77    return ScalarValue(original if not quality else None, dtype, not quality, quality)787980def code_column(definition, originals):81    """按原生输入类型装箱有限原码批;未请求不分配列。8283    参数: definition 为运行投影,originals 为映射前异构 Python 输入。84    返回: None 或只读的定宽整数 NumericArray。异常: 声明或输入违反模型时传播。85    """86    if not definition.capture_code:87        return None88    import numpy as np89    from .numeric_numpy import NumericArray, DTYPES90    values = np.zeros(len(originals), dtype=DTYPES[definition.code_dtype])91    quality = np.zeros(len(originals), dtype=np.uint16)92    for index, original in enumerate(originals):93        code = original_code(definition, original)94        if code.valid:95            values[index] = code.value96        quality[index] = int(code.quality)97    return NumericArray(definition.code_dtype, values, quality == 0, quality)9899100def memory_histories(compiled, names, factory, condition=None):101    """只为实际消费码视图的表达式建立附原码的历史。102103    参数: compiled/condition 为值和可选条件,names 为实际联合依赖,factory 为独立后端。104    返回: 名称到 SignalSeries 的映射。异常: 原输入转换或绑定错误直接传播。105    """106    required = code_dependencies(compiled.root)107    if condition is not None:108        required |= code_dependencies(condition.root)109    return {name: factory(compiled.bindings, name, capture_code=name in required) for name in names}110111112def aligned_scalar(definition, state):113    """恢复对齐点的标签和独立原码,过期和域外状态同时作用于两者。114115    参数: definition 为信号声明,state 为参考保持结果。116    返回: ScalarValue。异常: 质量或输入布局非法时传播。117    """118    labels = tuple(dict.fromkeys(label for _, label in definition.choices)) if definition.dtype is D.ENUM else ()119    code = state.sample.code if state.sample is not None else None120    boundary = state.quality & (Q.MISSING | Q.STALE)121    if code is not None and boundary:122        code = ScalarValue(None, code.dtype, False, code.quality | boundary)123    return ScalarValue(state.value, definition.dtype, state.valid, state.quality, labels, code)124125126def expire_value(value, reason):127    """把同一观测边界分别施加到值及附带原码,各自保留独立质量。128129    参数: value 为保存的最新值,reason 为本次缺观测或过期原因。130    返回: 当前时刻无效的 ScalarValue。异常: 错误 dtype 或质量组合由模型拒绝。131    """132    code = value.code133    if code is not None:134        code = ScalarValue(None, code.dtype, False, code.quality | reason)135    return ScalarValue(None, value.dtype, False, value.quality | reason, value.labels, code)136137138def aligned_column(state):139    """使用数组保持的相同样本索引同步原码及其自身质量。140141    参数: state 为 AlignedArray。返回: NumericArray;标签单独使用时不分配码列。142    异常: 不一致的历史布局或整数存储错误。143    """144    import numpy as np145    from .numeric_numpy import DTYPES, NumericArray146    history = state.history147    samples = history.series.samples148    definition = history.series.bindings.resolve(history.series.name)149    code = None150    if samples and samples[0].code is not None:151        dtype = definition.code_dtype152        source = np.asarray([s.code.value if s.code.valid else 0 for s in samples], dtype=DTYPES[dtype])153        reasons = np.asarray([int(s.code.quality) for s in samples], dtype=np.uint16)154        present = state.sample_indices >= 0155        values = np.zeros(state.values.shape, dtype=DTYPES[dtype])156        quality = state.quality & int(Q.MISSING | Q.STALE)157        indices = state.sample_indices[present]158        values[present] = source[indices]159        quality[present] |= reasons[indices]160        code = NumericArray(dtype, values, quality == 0, quality)161    return NumericArray(definition.dtype, state.values, state.valid, state.quality, history.labels, code)162163164def history_code(definition, sample):165    """读取历史中单独保存的原码,从原数据重查标签映射无关的质量。166167    参数: definition 为枚举声明,sample 为原历史观测,None 表示从未观测。168    返回: 原码 ScalarValue。异常: 缺少必要历史投影时明确失败。169    """170    if sample is None:171        return ScalarValue(None, definition.code_dtype, False, Q.MISSING)172    if sample.value.code is not None:173        return sample.value.code174    if not sample.original_present:175        raise ValueError('enum_code 需要回读时保留枚举原始整数')176    quality = sample.value.quality177    if sample.original_value is not None:178        quality &= ~Q.OUT_OF_RANGE179    return original_code(definition, sample.original_value, quality)180181182def historical_column(definition, arrays):183    """沿历史保持的有样本掩码及时间质量构建请求的原码列。184185    参数: definition 为枚举声明,arrays 为同一历史快照的有限保持批。186    返回: 与该批同长的整数 NumericArray。异常: 缺少原码投影或布局错误。187    """188    import numpy as np189    from .numeric_numpy import NumericArray, DTYPES190    code = history_code(definition, arrays.sample)191    quality = arrays.quality & int(Q.MISSING | Q.STALE)192    quality[arrays.has_sample] |= int(code.quality)193    values = np.full(arrays.values.shape, code.value if code.valid else 0, dtype=DTYPES[code.dtype])194    return NumericArray(code.dtype, values, quality == 0, quality)195196197def enum_code_reference(node, operand):198    """读取一条原码及其独立质量,保持有效的未映射代码。199200    参数: node 为已检查的 enum_code 节点,operand 为对应 ENUM 的 ScalarValue。201    返回: 整数 ScalarValue。异常: 已有观测却缺原码投影或类型不一致时报错。202    """203    if operand.code is not None and operand.code.dtype is node.dtype:204        return operand.code205    if operand.code is None and operand.quality & (Q.MISSING | Q.STALE):206        return ScalarValue(None, node.dtype, False, operand.quality)207    raise ValueError('枚举缺少与声明一致的原码投影,无法从标签还原代码')208209210def enum_code_numpy(node, operand):211    """读取当前批的原码列及独立有效性,原码与枚举有效性分别判断。212213    参数: node 为已检查的 enum_code 节点,operand 为形状 (N,) 的 ENUM 列。214    返回: 同形状整数 NumericArray。异常: 有观测而原码投影缺失或类型错误时报错。215    """216    import numpy as np217    from .numeric_numpy import NumericArray, DTYPES218    if operand.code is not None and operand.code.dtype is node.dtype:219        return operand.code220    if operand.code is None and np.all((operand.quality & int(Q.MISSING | Q.STALE)) != 0):221        return NumericArray(node.dtype, np.zeros(len(operand.values), dtype=DTYPES[node.dtype]),222                            operand.valid, operand.quality)223    raise ValueError('枚举缺少与声明一致的原码投影,无法从标签还原代码')224
Chronaxis 用户手册 · 离线阅读