di-omics/autonomous-lab

GitHub: di-omics/autonomous-lab

基于 PyLabRobot 生态的实验室自动化程度评估工具,通过逐步核算实验协议的真实可执行状态来揭示无人值守运行的瓶颈所在。

Stars: 0 | Forks: 0

# autonomous-lab 在一次端到端的实验室运行中,有多少环节是在无人工干预下完成的,以及是什么阻碍了全程自动化。 [plr-reverse-engineer](https://github.com/di-omics/plr-reverse-engineer) 致力于逐一将实验室仪器置于 PyLabRobot 的控制之下。 [plr-tested](https://github.com/di-omics/plr-tested) 是已在真实硬件上实际运行过的 PyLabRobot 代码。这就引出了一个只有将它们综合起来考量才有意义的问题:鉴于实验台上的仪器以及目前已被解码的命令集,一个真实的 protocol 有多少能在无人值守的情况下运行,而到底是什么在阻碍剩余的部分? 它通过对代码的实际状态进行每一步的消耗评估来回答这个问题。这里没有任何主观断言。注册表派生自 `plr_re.protocolmap.SEEDS`,判定结果由解析后的 `ProtocolMap` 计算得出,而且只有当其命令被真正解码时,该步骤才算作已自动化。protocol 作者无法通过设置某个字段来将其声明为已自动化。 ``` pip install 'autonomous-lab @ git+https://github.com/di-omics/autonomous-lab' autonomous-lab stock # every instrument, its role, how far its map is autonomous-lab ledger single_cell_genomics # cost a protocol step by step autonomous-lab gaps # the RE queue, ranked by steps freed autonomous-lab doctor --plr-tested ../plr-tested # check my claims against your checkout autonomous-lab run single_cell_genomics # run it as far as it honestly goes ``` ## 目前它能报告的内容 | | 步骤 | | | --- | --- | --- | | 已自动化 | 18 步中的 3 步 | 目前可脱离界面运行:两个链接预检和 AVITI 的 run-folder 读取 | | 受监督运行 | 18 步中的 2 步 | 在 plr-tested 中存在经验证的 run card,受限于确认 token 和操作员指令 | | 被阻塞 | 18 步中的 8 步 | 命令未被解码;覆盖率门槛拒绝执行运行 | | 人工操作 | 18 步中的 4 步 | 安装 cartridge、装载 flow cell,以及两个目前无人为其编写验证脚本的 STAR 步骤 | | 异常故障 | 18 步中的 1 步 | run card 存在,在仪器上运行过,但失败了 | **无人值守的运行在停止前只能到达第 1 步(共 18 步)。** 这个数字,而不是那 17% 的自动化率,才是“这个实验室的自动化程度有多高”的真正含义:只有在它之前的所有步骤也都运行成功的情况下,才能执行到接近末尾的只读步骤。此外还有 5 次物理 plate 转移,再多的解码工作也无法省去——只有 plate 搬运臂才能做到。 将 `broken` 单独列为一行是刻意为之。Tecan 酶标仪的吸光度 run card 已经写好并在仪器上运行过,但在运行时确定性地失败了:在执行 `ABSOLUTE MTP,Y=` 时发生 `TimeoutError`,两次尝试全部失败(2 of 2),而且该读数仪从未返回过 OD 矩阵。如果将其称为 `manual`(人工操作),言下之意就是“需要有人先编写并验证那个脚本”,但这与事实不符;这反而会让一个已知的缺陷看起来像是一项未完成的工作。一个意味着需要进行逆向工程;另一个则意味着需要调试一个真实的故障。规划器必须清楚两者之间的区别。 这些数据如此之低的原因很实在。在所有六台经过逆向工程的仪器中,**54 个种子命令中没有一个被解码**。其中没有一台仪器能够脱离界面被驱动,而且 plr-re 自身的覆盖率门槛会拒绝针对不完整映射表执行实弹运行。目前唯一能够进行的真实仪器交互是 AVITI 的 run-folder 读取、USB 枚举以及两次 socket 探测。这个工具的存在就是为了精确地说明这一点,并说明改变现状需要做什么。 ## RE(逆向工程)队列是计算出来的,而非争论出来的 ``` $ autonomous-lab gaps namocell frees 5 step(s), needs 9 command(s) decoded element_aviti frees 3 step(s), needs 8 command(s) decoded biotage_v10 frees 3 step(s), needs 9 command(s) decoded agilent6530 frees 2 step(s), needs 10 command(s) decoded ``` 队列按仪器而非命令进行排序,这是由代码强制决定的,而非出于展示选择:plr-re 的覆盖率门槛对于整个映射表来说是全有或全无的,因此解码单个命令能释放的步骤数恰好为零。衡量进度的单位是一个完整的映射表,而针对单个命令的队列只不过是没人能采取行动的纸上谈兵。 ## 不要盲目相信关于硬件的声明 仪器注册表派生自 `SEEDS`,因此不会产生数据漂移。联邦化的声明则没有这种待遇:`validated_ops` 是手写的路径和文字说明,且针对的是本包无法控制的另一个代码库,这使得它恰恰属于本包拒绝从其他任何人那里接受的断言类型。因此,本包内置了一个检查器。 ``` $ autonomous-lab doctor --plr-tested ../plr-tested [ok ] star.pta_wga_lysis run card exists: hamilton-star/starlab_live/00_pta_wga_1col_src1lysis_src3rxn_dst1_hhs_DRY.py [ok ] star.pta_wga_lysis confirm token appears in the run card: RUN_SINGLE_COL_PTA_HHS ... all 16 checkable claims hold. ``` 对于本包声明为已验证的每一项操作,`doctor` 会确认 run card 在你的 plr-tested 检出代码库的对应路径下确实存在,并且确认账本要求你输入的 token 确实出现在了该脚本中。如果发现数据不一致,它将以非零状态退出。这在开发过程中捕获了一个真实的 bug:每个 STAR 步骤都在引用 `RUN_TARGETED_PCR_ODTC_LIDDED_FULL`,而实际上 PTA/WGA 的 run card 是受 `RUN_SINGLE_COL_PTA_HHS` 控制的。账本原本会指示操作员输入一个会导致运行被拒绝的 token。 它刻意**无法**检查的内容是 `evidence`(证据)——即操作员是否真的在现场观看了运行过程。这是对物理世界的文字描述,没有任何检查器能够触及,这也是为什么证据字符串保持简短且自带警示说明的原因。 ## 它拒绝做的三件事 1. **让仪器的声誉转移到某个步骤上。** plr-tested 具有经过验证的 PTA/WGA 加样操作和经过验证的目标 PCR 编排;但它没有经过验证的 bead cleanup(磁珠纯化),也没有经过验证的 library pooling(文库 pooling)。因此,即使它们指向了一台已验证的仪器,在核算时也会被记为人工操作。只有当特定步骤的 run card 被证明有效时,该联邦化步骤才算作受监督运行。确实计算在内的全基因组测序环节只是通过了干实验验证,账本在同一时间也说明了这一点:其湿实验版本从未运行过。 2. **仅对可能导致运行被拒绝的部分情况进行建模。** `GuardedReplayer.setup()` 有三个先决条件,而不是一个:覆盖率、一个 endpoint,以及一种可由连接类打开的 transport。`DEFAULT_TRANSPORT` 在设计上对其中三台仪器设置为 UNKNOWN,因此仅靠解码并不能使其成为可拨号连接的设备。 3. **越级跳步。** 执行器会执行不需要解码的只读操作,并在第一个需要人工干预的步骤处停止,同时附带一张卡片说明需要完成哪些实验台操作才能解除该停止状态。一个伪造分拣步骤、随后却真实读取 run folder 的运行结果比无用更糟糕——它看起来会像是一条正常工作的 pipeline。 ## 注册表会自动派生 这里没有手动列出仪器。它们是从 `plr_re.protocolmap.SEEDS` 读取的,因此本包不会与实际进行逆向工程的代码库产生不同步,而且新的 playbook 无需任何编辑即可加入实验室。只要安装一个包含 Integra VIAFLO 96 playbook 的 plr-re,它就会自动注册其角色等所有信息,并出现在队列中。 这也意味着你看到的内容取决于你安装的 plr-re 版本:目前 `main` 分支有五台仪器,而包含未合并 playbook 的分支则有六台。本包已知但你的 plr-re 未知的一台仪器,在核算时会被标记为不可用,而不会导致程序崩溃。 ## 参考 protocol 基因组学 protocol 会在 pooling 和测序之前,使用酶标仪对 plate 上的文库进行定量,因为这是实际操作中的必经步骤,而且如果跳过这一步,得分反而会更高,但其实际价值却更低。 这两种 protocol 的编写都力求客观不夸张。它们包含了在演示中往往会被悄悄略去的 cartridge 装载和 flow cell 加载步骤,因为省略了它们的计划会得出更好的数值,但其实毫无意义。 你可以通过声明 `Step` 以及它们所移动的 `Artifact` 来编写自己的 protocol;标记为物理操作的 artifact 会被计入 plate 转移次数。如果一个 protocol 引用了它未声明的 artifact,或者消耗了没有任何步骤产出的 artifact,它在进入成本核算之前就会被拒绝执行。 ## 安全性 本包仅负责调度和报告。它绝不执行驱动操作。`run --armed` 仅执行只读操作——枚举 USB 总线、探测端口、读取 run folder——不存在任何可以移动仪器的标志。任何实际驱动仪器的操作都必须通过 plr-re 的控制器进行,受控于其自身的 `armed` 和 `allow_actuation` 开关,并且必须在有人员在场监督的情况下执行。 还要注意 plr-tested 的硬性约束,任何基于此构建的调度器都必须遵守:每台仪器只能对应一个驱动进程。两个 STAR 客户端会引发 `USBError [Errno 16] Resource busy`,而在 ODTC 上这种冲突更为隐蔽,因为第二个进程会重新注册事件接收器,并无声无息地窃取第一个进程的 callback。 ## 测试 ``` pip install -e '.[dev]' && pytest ``` 46 个无需连接设备的测试。最重要的测试旨在揭穿账本可能撒的谎:在某步骤的命令未解码时声称该步骤已自动化,声称已解码的命令是可运行的而其同级命令却不可运行,声称某项联邦化分支可以运行但其实从未为其证明过任何 run card。doctor 相关的测试用于证明检查器本身能够捕获被重命名的 run card 和过期的 token,因为如果一个检查器无条件通过,那只不过是给主观断言洗白罢了。
标签:文档结构分析, 逆向工具