资讯动态

生物大分子批量仿真开发教程(2):Maestro 的 Python API 到底给了你什么——进程模型、MAE 读写与属性命名规约

发布时间:2026/9/15 9:27:24 来源:尧图企业网站定制
生物大分子批量仿真开发教程2Maestro 的 Python API 到底给了你什么——进程模型、MAE 读写与属性命名规约版本声明块工具/软件Schrödinger Release 2025-4书写基线公开 Python API 文档版次 2025-2 / 2026-1旧版镜像 r2021-1语言/环境Python 3.10由$SCHRODINGER/run提供的内置解释器本文目标让你在不启动图形界面的前提下把.mae/.maegz当成可批量读写的结构化数据来编程一句话结论Maestro 的 Python API 给了你三样东西——一个不依赖 GUI 的结构对象模型schrodinger.structure的StructureReader/StructureWriter/Structure含atom/residue/molecule/bond四个迭代器、一套把自定义数据直接变成项目表列的属性命名规约i_/r_/b_/s_user/m 名字以及一个只能活在 Maestro 进程内的 GUI 控制通道schrodinger.maestro.maestro批量脚本必须只用前两者把第三个留在界面里。〇、本篇要解决的认知问题Maestro 图形界面和$SCHRODINGER/run跑起来的脚本是什么进程关系谁是宿主、谁依赖谁完全不打开 Maestro 时怎么用 Python 读.mae和压缩的.maegz又怎么写回去Structure对象上的st.atom/st.residue/st.molecule/st.bond分别在什么场景用怎么精确定位A 链 26 号残基r_user_energy、b_user_is_carbon这种名字里的前缀是什么规矩为什么不能随便起一个键名为什么schrodinger.maestro.maestro在$SCHRODINGER/run脚本里 import 会报错那 Command Script Editor 和pythonrun又是干什么用的一、机制解析1.1 先画清楚进程模型三个层次别混为一谈绝大多数Schrödinger 脚本莫名其妙不能用的问题都源于把这三层当成一层。┌───────────────────────────────────────────────────────────────┐ │ 层 1 MaestroGUI 进程 │ │ · 有工作区(workspace)、项目表(project table)、命令区 │ │ · 能 import schrodinger.maestro.maestro │ │ · 命令区可执行 pythonimport / pythonrun / pythoneval │ └───────────────▲───────────────────────────────────────────────┘ │ 只有这一层有 GUI 宿主IPC 通道 ┌───────────────┴───────────────────────────────────────────────┐ │ 层 2 $SCHRODINGER/run myscript.py -HOST localhost:4 │ │ · 官方脚本入口独立进程自带内置 Python 与命名空间 │ │ · 可以 import schrodinger.structure / job / utils │ │ · 不能 import schrodinger.maestro.maestro无宿主 → 报错 │ └───────────────┬───────────────────────────────────────────────┘ │ 两条路都通向同一套底层实现 ┌───────────────▼───────────────────────────────────────────────┐ │ 层 3 底层库与文件格式MAE / MAEGZ / 项目文件、各引擎 CLI │ │ · structconvert、desmond、ifd 等命令行为同一文件系统约定 │ └───────────────────────────────────────────────────────────────┘关键机制层 2 和层 1 是平级的两个进程不是脚本跑在界面里。所以你在 Maestro 里能用的maestro模块本质是一条通往 GUI 的遥控器遥控器离开了电视机就没有意义。这就是铁律 3 的来历schrodinger.maestro.maestro只能在 Maestro 进程内 import批量脚本必须走schrodinger.structureschrodinger.job.jobcontrol。为什么这对你重要把这条搞清楚你写出来的流水线就不再是必须有人开着界面才能跑的半成品而能在夜里、在计算节点、在容器里跑——这是吞吐的前提。1.2 MAE 与 MAEGZ文件即数据扩展名即格式契约项说明来源官方 Python API Cookbook / core concepts模块规范名schrodinger.structure不存在schrodinger.struct那是误写读structure.StructureReader(fname)可迭代、structure.StructureReader.read(fname)只取第一条写structure.StructureWriter(out.mae)writer.append(st)格式识别按扩展名自动识别mae/maegz/pdb/sdf双扩展名坑.mae.gz不是普通扩展名要用schrodinger.utils.fileutils的splitext()/get_structure_file_format().maegz是压缩的 Maestro 结构文件Maestro file gzipped。机制上要记住两件事一是读写侧不需要你手工解压扩展名驱动一切二是不要用os.path.splitext()判断类型x.mae.gz会被它切成基底x.mae 扩展.gz你的分支逻辑就把压缩结构文件当成未知类型丢掉了。这正是fileutils存在的理由。MAE 相对于 PDB 的另一个机制优势是属性可以随身带你算出的打分、编号体系、失败原因都能写进结构对象并落盘下游脚本读回来即可PDB/SDF 的字段承载能力有限且structconvert -ipdb in.pdb -omae out.mae这类转换会丢信息第 05 篇详述格式归一化。1.3 Structure 对象模型四个迭代器 一次精确定位Structure是三层容器分子片段molecule→ 残基residue→ 原子atom外加键bond作为原子间的连接关系。Structure st ├── st.molecule 分子片段迭代器一条重链/一条轻链/一个配体各是一个 molecule │ └── st.residue 残基迭代器带 chain 与 resnum │ └── st.atom 原子迭代器带 property 字典 ├── st.bond 键迭代器判断二硫键、成键环境时用 └── st.atom_total 原子总数O(1)做完整性校验最好用批量抗体仿真里molecule层是最常被误用的一条重链和一个配体是两个不同的 molecule任何整个结构算一个口袋的假设都会在复合物上出错。定位则用st.findResidue(A:26)这种链:残基号语法返回对象上有res.chain与res.resnum。注意这里的残基号是文件里写着的号它在抗体语境下可能是 Kabat、IMGT 或 PDB author numbering——不先固定编号体系铁律 1A:26就毫无意义第 04 篇专门处理这件事。1.4 属性命名规约类型_author_名称这是 Maestro API 里最反直觉但一旦理解就回不去的设计。r_user_energy │ └────┬────┘└──┬──┘ │ author 你自己起的名字 └─ 类型前缀i_int r_real(浮点) b_bool s_string前缀含义典型用途在 GUI 里的表现i_整数残基序号、失败重试次数整数列r_实数打分、能量、RMSD、Δλ 类连续量可排序/可画直方图的数值列b_布尔是否含 H、是否通过质控勾选框s_字符串编号体系名、格式名、失败原因分类文本列author user你写的自建流水线一律用它—author mMaestro/官方模块写的只读为主别去覆盖—机制解释为什么必须带类型前缀。因为这套键名同时是文件里的存储类型、是项目表的列类型、也是与 Studio 数据库/下游工具通信的字段名。类型信息不藏在值里而写在键名里意味着一个字符串8.5和一个浮点8.5会被存成s_user_x与r_user_x两个互不相干的字段——排序时前者按字典序、后者按数值序。很多人抱怨我加的分数列在表里排序不对根因就在这里他用s_存了数字。写属性的语法就是一行atom.property[b_user_is_carbon]Trueatom.property[r_user_energy]1.0作用域可以落在原子、残基、分子片段或整个结构上这就是 MAE 能充当轻量结果库的原因第 08 篇展开。为什么这对你重要这条规约是结果库的建表语句。前端项目表、筛选器、直方图与后端你的 Python 汇总脚本读的是同一批键名把分数写成r_还是s_决定了三个月后你能否一行代码把万行结果导出成可排序的表格。1.5 两条 import 路径的对照以及 GUI 内的三个命令入口你在写的东西应该 import能在$SCHRODINGER/run里跑吗批量读写结构、算属性from schrodinger import structure能提交作业到本地/队列from schrodinger.job import jobcontrol能操作工作区、读项目表from schrodinger.maestro import maestro不能会报错需要 GUI 时官方自动化路径是 Maestro 的Command Script Editor与命令区的三条 Python 入口pythonimport my_script # 只导入模块执行顶层代码 pythonrun my_script.func # 调用一个无参函数 pythoneval my_script.func(5, True, [a, 4]) # 传任意字面量参数再加上脚本菜单注释规约#Name:/#Command:就能把一个 Python 函数变成 Maestro 顶部菜单里的一项——这是给不懂代码的同事用的正规做法第 16 篇详述封装。为什么这对你重要正确的分工是批量在层 2 跑人在层 1 看结果。如果你的脚本必须开着 Maestro 才能推进 10000 个变体那它不是流水线只是半自动。二、完整代码与逐行剖析2.1 不开界面读 MAE/MAEGZ 并遍历对象模型#!/usr/bin/env python3inspect_mae.py —— 用 $SCHRODINGER/run inspect_mae.py in.mae 运行importsysfromschrodingerimportstructurefromschrodinger.utilsimportfileutils pathsys.argv[1]# 为什么不用 os.path.splitext.mae.gz 会被切错导致格式判断失败base,extfileutils.splitext(path)print(解析出的格式 ,fileutils.get_structure_file_format(path),基底名 ,base,扩展 ,ext)# StructureReader 是惰性迭代器打开一个含 500 条结构的 maegz 不需要一次性驻留内存forist,stinenumerate(structure.StructureReader(path),1):# atom_total 是 O(1) 的完整性刻度用来做前后处理的一致性断言最省事n_atom,n_res,n_molst.atom_total,0,0for_inst.residue:n_res1# 层级迭代器mol.residue / res.atom与结构级同源写法见官方 Cookbookforimol,molinenumerate(st.molecule,1):n_mol1# 抗体语境重链/轻链/抗原/配体是分开的 molecule混算必然出错resnums[res.resnumforresinmol.residue]print(f molecule#{imol}: 残基数{len(resnums)}f首末号{resnums[0]ifresnumselse-}/{resnums[-1]ifresnumselse-})# 精确定位写法链:残基号编号体系必须由上游写入元数据保证一致铁律 1targetst.findResidue(A:26)iftargetisNone:print(f结构#{ist}: 未找到 A:26 —— 检查链名与编号体系)else:print(f结构#{ist}: A:26 - chain{target.chain}resnum{target.resnum}f原子数{len(list(target.atom))})print(f结构#{ist}: atom_total{n_atom}residues{n_res}molecules{n_mol})写法为什么这样写for st in StructureReader(path)而非read()read()只返回第一条结构批量场景十有八九用错它统计用st.atom_total再手工数 residue/molecule原子总数是属性直取残基/分子需要迭代两者对照能立刻暴露结构被拆碎的问题findResidue(A:26)判空抗体 PDB 常用 author numbering直接假设编号存在会让脚本静默跳过错位结构2.2 计算并写回属性落盘成新 MAE#!/usr/bin/env python3annotate_mae.py —— 给每条结构打三类属性并写出 out.maeimportsysfromschrodingerimportstructure readerstructure.StructureReader(sys.argv[1])writerstructure.StructureWriter(sys.argv[2])# 扩展名决定输出格式.mae / .maegz / .sdfforstinreader:# s_ string把编号体系随结构一起落盘下游任何脚本读回来就知道该信哪个残基号铁律 1st.property[s_user_numbering_scheme]chothia# b_ bool质控闸门用布尔而不是字符串方便项目表里筛选勾选列st.property[b_user_has_hydrogen]any(a.atomic_number1forainst.atom)# i_ int分子片段数是排查复合物被拆成 20 个碎片这类事故的关键刻度st.property[i_user_mol_total]sum(1for_inst.molecule)# r_ real连续打分必须用 r_用 s_ 存数字会让项目表排序变成字典序st.property[r_user_atoms_per_residue](st.atom_total/max(1,sum(1for_inst.residue)))# 残基级标注CDR 判定、突变定位都以 residue 为单位挂数据forresinst.residue:# 这里示范每残基重原子数真实项目里换成你的评分res.property[i_user_heavy_atoms]sum(1forainres.atomifa.atomic_number1)writer.append(st)# 多条结构必须逐条 append而不是重新构造 writerwriter.close()# 显式关闭MAE 尾部索引/压缩流靠关闭时才完整落盘print(written:,sys.argv[2])补充两点不存在schrodinger.struct这个模块写成它只会得到导入错误分子片段级的自定义数据同理挂在mol.property[...]上作用域只是选哪一层前缀规约完全一致。至于StructureWriter对已存在文件的覆盖行为官方 Cookbook 是最权威出处跨版本细节以你安装版内 Help 与 API 文档为准。2.3 Maestro 进程内脚本工作区 项目表 pythonrun下面这段只能在 Maestro 里运行Command Script Editor 里pythonimport或命令区pythonrun。ws_stats.py —— 放在 Maestro 进程内把选中行的结构打分写回项目表fromschrodinger.maestroimportmaestro# 铁律 3这一行在 $SCHRODINGER/run 下会报错fromschrodingerimportproject# 项目表相关对象类型defshow_atom_stats():# 1) 工作区取回当前 workspace遍历结构并把统计量挂成属性wsmaestro.workspace_get()# 返回一个 Project 对象可当 Structure 集合迭代forstinws:st.property[i_user_atom_total]st.atom_total maestro.workspace_set(ws)# 改完必须 set 回去GUI 才会更新# 2) 项目表把结构属性镜像成表列人就能在 GUI 里排序筛选ptmaestro.project_table_get()forrowinpt.selected_rows:# 只处理用户勾选的行GUI 自动化的交互契约strow.getStructure()ifstisNone:continue# 表里可能有文件夹行/非结构行不判空会炸# 读回 2.2 写的 r_user_ 列缺失时用 NaN 而不是 0避免污染排序结果keyr_user_atoms_per_residuerow[r_user_screening_score](st.property[key]ifkeyinst.propertyelsefloat(nan))pt.update()# 批量改完统一 update别在循环里刷 UI# 3) 需要执行 Maestro 命令时用 maestro.commandtry:# 命令关键字与选项随版本变化正规做法是在 GUI 里手工做一次该操作# 从 Command Script Editor 的历史里复制它生成的命令行再粘到这里maestro.command(workspace.map)# ← 示例位实际关键字以本机命令历史/Help 为准exceptExceptionasexc:# 官方文档明示 maestro.command 失败抛 MaestroCommand 异常# 该异常类的具体导入位置跨版本有差异精确写法以安装版内 API 文档为准print(Maestro 命令执行失败,exc)想在菜单里给同事用脚本顶部加官方注释规约即可#Name:统计工作区原子数#Command:pythonrun ws_stats.show_atom_statsGUI 命令语义适用pythonimport ws_stats只导入执行顶层代码注册函数、加载常量pythonrun ws_stats.func调用无参函数菜单项、一键动作pythoneval ws_stats.func(5, True, [a, 4])带字面量参数调用需要传参的一次性操作三、常见报错与排查ModuleNotFoundError: No module named schrodinger根因用了系统 Python。解法$SCHRODINGER/run script.py或把 IDE 解释器指向安装内置的 Python路径以本站安装为准。在批量脚本里from schrodinger.maestro import maestro就报错根因铁律 3该模块需要 Maestro GUI 进程作为宿主。解法删掉这条依赖改用schrodinger.structure读写 schrodinger.job.jobcontrol提交确需界面操作时把逻辑放进 Command Script Editor 用pythonrun触发。StructureReader.read(f)只处理了一条结构根因read()语义就是取第一条。解法批量用for st in structure.StructureReader(f)只要第一条时才用read()。.mae.gz文件被脚本当成未知格式跳过根因用os.path.splitext()判断扩展名。解法改用fileutils.splitext()/fileutils.get_structure_file_format()它们认识双扩展名。属性写了但项目表里没有这一列或排序结果是错的根因键名前缀缺失或类型选错user_score或s_user_score。解法严格类型_author_名称数值一律r_布尔b_文本s_author 用user改完在项目表里刷新/添加列查看列的具体显示操作以安装版内 Help 为准。st.findResidue(H:228)返回 None但你确信有这个残基根因链名与编号体系假设不一致PDB author numbering ≠ Kabat ≠ IMGT。解法不要按号硬猜先遍历st.residue打印chain/resnum分布再按第 04 篇把编号体系固化进元数据。四、动手练习对象模型清点把任意一个抗体-抗原复合物 MAE 用 2.1 跑一遍。判定标准输出的molecules数应等于你预期的链数如重链轻链抗原3若明显偏多说明结构被拆碎或水/离子被当成独立片段。属性往返测试用 2.2 给文件写入s_user_numbering_schemechothia再用 2.1 的读回逻辑断言每条结构该属性非空。判定标准第二轮读取打印出的属性值 100% 为chothia且out.mae的atom_total与输入完全相同没丢原子。GUI 通道验证把 2.3 的前两段放进 Command Script Editor先pythonimport再在命令区执行pythonrun ws_stats对应函数。判定标准项目表出现i_user_atom_total列且其值与终端里st.atom_total打印值逐行一致然后在$SCHRODINGER/run下运行同一文件必须复现第 2 条报错——这个故意失败是你对铁律 3 的最好体检。五、小结与下一篇预告schrodinger.structure让你在无界面条件下把 MAE/MAEGZ 当结构化数据处理惰性StructureReader、四类迭代器、findResidue(链:号)精确定位再加上i_/r_/b_/s_的类型化属性键把自定义分数与元数据随身带到项目表里。schrodinger.maestro.maestro则相反它是只能在 Maestro 进程内使用的遥控器配合 Command Script Editor 的pythonimport/pythonrun/pythoneval和#Name:/#Command:菜单规约服务于人在界面里看结果、一键触发动作。下一篇换平台MOE 的世界没有一等公民 Python它用自研的 SVL 与moebatch而且从 MOE 2024.06 起默认力场已经变成 AmberEHT——这个变更会直接影响你脚本里的能量可比性。本篇认知问题回显FAQQ1Maestro 图形界面和$SCHRODINGER/run脚本是什么进程关系A两个平级进程。$SCHRODINGER/run myscript.py -HOST localhost:4是官方脚本入口自带内置 Python 与schrodinger.*命名空间独立于 GUI 运行Maestro 是另一个持有工作区与项目表的图形进程。因此批量脚本可在无界面节点跑只有需要遥控 GUI 时才必须在 Maestro 进程内执行。Q2Schrödinger 不打开 Maestro 怎么读写 MAE 和 MAEGZ 文件Afrom schrodinger import structure后用structure.StructureReader(fname)迭代读取、structure.StructureWriter(out.mae)配合writer.append(st)写出格式由扩展名自动识别mae/maegz/pdb/sdf。.mae.gz这类双扩展名要用schrodinger.utils.fileutils的splitext()与get_structure_file_format()判断不要用os.path.splitext()。Q3schrodinger.structure 的 Structure 对象有哪些迭代器怎么定位某个残基Ast.atom、st.residue、st.molecule、st.bond四个迭代器加常量st.atom_total。定位用st.findResidue(A:26)链:残基号返回对象带res.chain与res.resnum。注意molecule是分子片段级一条重链、一条轻链、一个配体各是一个 molecule复合物不要当整体算。Q4Maestro 属性名里 i_ r_ b_ s_ 前缀和 user 是什么意思A规约为类型_author_名称类型前缀i_整数、r_实数、b_布尔、s_字符串author 常用user你自己写的与mMaestro/官方模块写的。例atom.property[b_user_is_carbon] True、atom.property[r_user_energy] 1.0。前缀决定存储类型与项目表列类型数值用s_会导致按字典序排序。Q5为什么 schrodinger.maestro.maestro 只能在 Maestro 进程内 importpythonrun 是干什么的A因为它是通往 GUI 进程的遥控通道workspace_get/workspace_set/command/project_table_get离开 Maestro 宿主就没有可连接的对象在$SCHRODINGER/run下 import 会直接报错——这是铁律 3。Command Script Editor 与命令区的pythonimport导入、pythonrun 模块.函数调用无参函数、pythoneval 模块.函数(5, True, [a,4])带参调用就是把 Python 函数挂进界面的入口配合#Name:/#Command:注释可生成菜单项。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价