ophyd - 架构
硬件抽象层Ophyd 是硬件抽象层它在底层控制通信协议和 bluesky 之间提供一致的接口。这是通过将底层过程变量的集合捆绑成分层设备并以控制系统原语的形式公开语义 API 来实现的。本文将通篇使用两个术语信号代表一个原子的“过程变量”。它名义上是一个“标量”值不能被 Ophyd 以上的层进一步分解。在此上下文中数组wavefrom或字符串被视为标量因为没有 Ophyd API 可以仅读取其中的一部分。设备由信号和其他设备组成的层次结构。Ophyd 以上的层可以检查设备的组件并可将其最终分解为底层的信号。换句话说如果将分层设备视为一棵树信号就是叶子节点设备则是中间节点。名称在 Ophyd 中我们可以将设备视为子设备组成的树最终到达“叶子”节点——信号映射到 1 或 2 个 PV。在树的底部每个信号叶子节点关联着三个名称PV 名称它将与之通信的 PV 名称。通常此名称在您使用的控制系统中必须是全局唯一的。这可能导致它们既冗长又晦涩。从 Ophyd 的角度来看按指定的接收这些字符串在命名中不需要任何特定的模式、方案或命名规则。Python 属性名称这些是设备组件的名称允许以属性方式访问子组件如 dev.cpt_name。这些名称在 ophyd.Device 子类定义中设置。它们必须是有效的 Python 标识符由 Python 强制要求并且应当选择对直接使用 Ophyd 实例的人员有意义的名称。它们在一个 ~ophyd.Device 内必须是唯一的因此 Python 确保完全合格的名称在命名空间内是唯一的。obj.name 属性此名称将用于 ~ophyd.Device.read 返回的数据中并最终流经 bluesky 进入 databroker在分析时呈现给用户。默认情况下这些名称派生自子设备的 Python 属性名称及其父设备的名称但也可以在运行时设置。这些名称应当选择在分析时具有科学意义并且在同时使用的设备中必须是唯一的。统一的高级接口所有 Ophyd 对象都实现了一小组方法这些方法被 bluesky 计划使用。Ophyd 对象有责任根据底层控制系统正确实现这些方法。可读接口一个对象必须是实现的最小组方法trigger()触发设备并且返回状态对象read()从设备读取数据describe()为read()提供模式和元数据以及三个属性:name设备名称parentophyd对象的父对象root遍历父级以找到最终祖先父级的父级……。有两种可选方法计划可能会使用它们来“启用”或“禁用”设备以进行数据采集。例如一个束流位置监测器在不采集数据时可能处于连续模式但在扫描时会切换到触发模式。按照惯例unstage会撤销stage对底层硬件状态所做的任何更改并应将其恢复到调用stage之前的状态。stage()预备设备以进行数据采集。unstage()撤销预备设备还有两个可选方法用于在扫描期间运行被暂停时通知设备。这些方法的语义与 RunEngine 耦合。pause()尝试暂停设备resume()从暂停状态恢复设备可设置接口当然对硬件最有趣的用法通常是命令它执行操作而不仅仅是读取数据为了实现这一点高级 API 提供了set方法以及相应的stop方法用于在运动完成前停止它。set方法会返回一个Status对象可用于判断运动何时完成。ophyd对象的职责是基于底层控制系统来实现此功能。因此从 bluesky 的角度来看一个电机、一个温度控制器、一个闸阀以及一个软件虚拟定位器都可以被同等对待。set(new_position, *, timeout, moved_cb, wait)设置一个值,并且返回一个Status对象stop(*, success)停止运行配置除了我们希望作为“数据”读取或作为“位置”设定的值之外通常还有许多与硬件配置相关的值。例如电机的速度、反馈回路的 PID 环路参数或者探测器的芯片温度。总的来说这些测量值与我们的目标测量没有直接关系但是可能对理解测量数据是必需的。函数/方法描述configure (d, typing.Any)为扫描过程中每个东西配置设备read_configuration ()将名称映射到包含键为value和timestamp的值字典describe_configuration ()为read_configure()提供模式和元数据可飞行接口有些硬件设备无法通过set、trigger和read进行精细控制我们只想告诉它“开始”然后过段时间再来检查它是否完成。通常在需要协调运动或触发速率超出 EPICS/Python 合理处理范围时会采用这种方式这类操作往往被称为“飞扫”。flyable接口提供了四种方法:函数/方法描述kickoff ()启动飞行器complete ()等待飞扫完成describe_collect ()提供来自collect()的模式和元数据collect ()从飞扫设备中检索数据并以原始事件proto-events的形式返回。异步状态硬件控制和数据采集本质上是一个异步活动。光束线上的众多设备通常是相互解耦的可以独立地进行运动和读取。这一点在 API 中有所体现BlueskyInterface 中的大多数方法都会返回 Status 对象同时这也是 OphydObject 核心中回调注册表的基础。StatusBase 对象是连接底层控制系统异步行为与 RunEngine 异步行为之间的桥梁。状态对象的核心 API 由一个属性和一个私有方法组成status.StatusBase.finished_cbstatus.StatusBasse._finished告知状态对象操作已完成及其是否成功。bluesky 端会为 status.StatusBase.finished_cb 分配一个回调函数当调用 status.StatusBase._finished() 方法时该回调会被触发。这个状态对象不仅传递了该操作“已完成”的信号还表明了操作是否成功。回调函数在ophyd中几乎所有对象的基类是OphydObject回调注册表OphydObjectOphyd中所有对象的基类OphydObject.event_types通过obj.subscribe可以被订阅的事件OphydObject.subscribe订阅这个event_type产生的事件OphydObject.unsubscribe移除一个订阅OphydObject.clear_sub传递原来的回调函数移除一个订阅OphydObject._run_subs运行一组订阅回调OphydObject._reset_sub移除一个事件类型中所有订阅这个注册表用于连接来自底层控制系统的事件并通过 ~status.StatusBase 对象或 从RunEngine 的直接订阅将这些事件向上传播到 bluesky。