chronaxis.execution.record_alarm_duration
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""仅在请求报警累计时,按实际有效区间折算所选周期。23状态变化可能发生在两个驱动报文之间,例如温度在中途过期。每对报文只保4实际已知/报警长度,收到右端后按该对完整跨度折算,不保存逐点轨迹。没有5右端的末段不补固定周期;实际模式则累计已经确认存在的连续观测区间。6"""78from ..core.types import Truth as T9from ..core.integral_sum_reference import ReferenceIntegralSum10from ..core.integral_sum_numpy import NumpyIntegralSum11from ..results.errors import ResultClosedError,AnalysisError12from ..results.spool import _reserve_owned_ram,_release_owned_ram,_cleanup_owner131415class RecordAlarmDuration:16 """拥有一个待完成记录对和有限求和状态,不读取来源或构造明细。"""1718 def __init__(self,budget,step_ns,backend,window):19 """预付统计费用。参数: 共享预算、实际None/正周期、后端。返回: owner。异常: 构造原错附owner。"""20 self._budget,self._step=budget,step_ns21 self._backend=backend22 self._window=window23 self._held_cost=self._fixed_cost=024 self._last=self._driver=None25 self._state=T.UNKNOWN26 self._pair_known=self._pair_active=027 self._known=self._observed=028 self._active_ns=029 self._sum=None30 self._closed=self._finished=False31 try:32 _reserve_owned_ram(self,65536+(4096*256 if step_ns is not None else 0),'_fixed_cost')33 if step_ns is not None:34 self._sum=(ReferenceIntegralSum if backend=='reference' else NumpyIntegralSum)(4096)35 except BaseException as error:36 _cleanup_owner(self,error,'record_alarm_cleanup_owner','报警时长构造')37 raise3839 def consume(self,time_ns,state,driver=False):40 """先结算前态,再记当前态;中途未知只裁剪本对有效部分。4142 参数: 实际时间、已确认报警三态、是否真实驱动更新。返回: None。异常: 顺序/数值/关闭错误。43 """44 if self._closed or self._finished:45 raise ResultClosedError('报警累计已结束')46 if self._last is not None:47 if time_ns<self._last:48 raise ValueError('报警累计时间不能回退')49 length=max(0,min(time_ns,self._window.end_ns)-max(self._last,self._window.start_ns))50 known=length if self._state is not T.UNKNOWN else 051 active=length if self._state is T.TRUE else 052 if self._step is None:53 self._observed+=length54 self._known+=known55 self._active_ns+=active56 elif self._driver is not None:57 self._pair_known+=known58 self._pair_active+=active59 if self._step is not None and driver:60 if self._driver is not None:61 span=time_ns-self._driver62 overlap=max(0,min(time_ns,self._window.end_ns)-max(self._driver,self._window.start_ns))63 self._observed+=overlap64 self._known+=self._pair_known65 seconds=(self._step*self._pair_active)/(span*1_000_000_000)66 if self._backend=='reference':67 self._sum.push_values((seconds,),(True,))68 else:69 import numpy as np70 values=np.array([seconds],dtype=np.float64)71 valid=np.array([True],dtype=np.bool_)72 values.setflags(write=False);valid.setflags(write=False)73 self._sum.push_values(values,valid)74 self._driver=time_ns75 self._pair_known=self._pair_active=076 self._last,self._state=time_ns,state7778 def driver(self,time_ns):79 """接收原始驱动端点,包括请求域两侧用于比例的点。参数: 实际时间。返回: None。异常: 顺序错误。"""80 if self._step is None or self._driver is not None and self._driver>=self._window.end_ns:81 return82 self.consume(time_ns,self._state,True)8384 def finish(self):85 """返回单一秒数及完整性;不结算没有右端的周期。8687 参数: 无。返回: (可核实报警秒数或None,状态)。异常: 求和失败/关闭错误。88 """89 if self._closed:90 raise ResultClosedError('报警累计已关闭')91 if self._sum is None:92 active=self._active_ns/1e993 else:94 result=self._sum.finish('s')95 if result.calculation_failed:96 raise AnalysisError('报警累计数值溢出')97 active=0. if result.value is None else result.value98 status=('no_observation' if not self._observed else 'indeterminate' if not self._known99 else 'partial' if self._known<self._observed else 'complete')100 self._finished=True101 return (active if status in ('complete','partial') else None),status102103 @property104 def closed(self):105 """返回关闭状态。参数: 无。返回: bool。异常: 无。"""106 return self._closed107108 def close(self):109 """丢弃统计状态并归还自己的费用。参数: 无。返回: None。异常: 释放原错可重试。"""110 if self._closed:111 return112 self._sum=None113 _release_owned_ram(self,self._fixed_cost,'_fixed_cost')114 self._closed=True115