将 Melo-1 结构预测结果生成为交互报告,即可在浏览器中查看三维结构、比较不同结构样本的评分与置信度,并导出结果。报告保存为一个 HTML 文件,支持离线打开和分享。
准备好报告模板和完整结果 ZIP,即可按下方步骤生成报告。
下载模板
本模板支持 Melo-1 的完整结构预测结果 ZIP。整批虚拟筛选结果请使用虚拟筛选报告模板。
也可以通过命令行下载模板:
curl --fail --location \
'https://www.atomelody.com/templates/atomelody-structure-prediction-report-template.html' \
--output atomelody-structure-prediction-report-template.html
生成报告
- 按结构预测使用指南获取任务结果,通过
output_url下载完整 ZIP,保存为<任务 ID>-output.zip。下载地址过期时,请重新查询任务。 - 下载上方报告模板,与结果 ZIP 放在同一目录。
- 运行下方 Python 示例,生成
<任务 ID>-report.html。如需显示模型、任务名称和输入,可同时准备任务详情。 - 用浏览器打开生成的 HTML,确认结构和置信度展示正常后即可分享。
分享报告会同时分享其中的结果和已添加的任务信息。请勿将 API Key 或临时下载地址写入报告。
数据槽约定
以下约定供自行编写生成脚本时参考;直接使用下方 Python 示例时,无需手动修改模板。
模板中只有一个空数据槽:
<script id="reportData" type="application/json">null</script>
保留标签,把 null 替换为 JSON 对象即可。最小内容只需一个字段:
{"archiveBase64":"完整 ZIP 的 Base64 内容"}
以下字段均为可选;不需要的字段直接省略:
| 字段 | 用途 | 省略时的行为 |
|---|---|---|
taskId | 任务 ID,建议填写查询接口返回的值 | 不显示任务 ID |
taskName | 任务名称,显示为报告顶部标题 | 使用 ZIP 内的任务名称 |
model | 模型名称,显示在报告顶部 | 不显示模型名称 |
input | 原始任务输入 JSON 对象,默认收起,可在报告中展开查看 | 不显示输入折叠区 |
archiveName | 从报告导出 ZIP 时的文件名,不包含目录 | 使用 <taskId>-output.zip;无有效任务 ID 时使用 output.zip |
generatedAt | ISO 8601 格式的报告生成时间 | 不显示生成时间 |
如需自行编写生成脚本,请将完整 ZIP 编码为无换行的标准 Base64,并使用 JSON 序列化工具生成报告数据。写入 HTML 前,将 JSON 中的 < 替换为 \u003c,其余模板内容保持原样。下方 Python 示例已包含这些处理。
添加任务输入
如需在报告中显示模型、任务名称和输入,请查询同一任务的详情,将响应保存为 task-details.json,并把下方脚本中的 task_details_path 改为 Path("task-details.json")。未提供详情时,也可以生成报告。
脚本会读取 model、input,并将 task_name 转为报告使用的 taskName。自行生成时,也可使用保存的原始提交参数;请确保它们与结果属于同一任务。
任务输入默认收起,点击「任务输入」即可展开。收起不会移除输入数据,分享报告时仍会包含这些内容。
Python 示例
需要 Python 3.9 或更新版本,无需安装第三方包。将模板与 <任务 ID>-output.zip 放在当前目录,修改下面的 task_id 后执行。
python3 - <<'PY'
import base64
import json
from pathlib import Path
import re
import zipfile
task_id = "tk-example" # 改为实际任务 ID
if not re.fullmatch(r"[a-zA-Z0-9][a-zA-Z0-9_-]{0,159}", task_id):
raise ValueError("请填写有效的任务 ID")
template = Path("atomelody-structure-prediction-report-template.html")
archive = Path(f"{task_id}-output.zip")
output = Path(f"{task_id}-report.html")
html = template.read_text(encoding="utf-8")
slot = '<script id="reportData" type="application/json">null</script>'
if html.count(slot) != 1 or 'data-viewer-mode="report"' not in html:
raise ValueError("请使用未填充数据的报告模板")
if archive.stat().st_size > 200 * 1024 * 1024:
raise ValueError("结果 ZIP 不能超过 200 MiB")
with zipfile.ZipFile(archive) as z:
if sum(item.file_size for item in z.infolist()) > 800 * 1024 * 1024:
raise ValueError("结果包解压后的总大小不能超过 800 MiB")
report = {
"taskId": task_id,
"archiveBase64": base64.b64encode(archive.read_bytes()).decode("ascii"),
}
# 可选:report["taskName"] = "我的结构预测任务"
# 可选:改为 Path("task-details.json"),嵌入同一任务的模型、名称和输入。
task_details_path = None
if task_details_path is not None:
details = json.loads(task_details_path.read_text(encoding="utf-8"))
if not isinstance(details, dict):
raise ValueError("任务详情必须是 JSON 对象")
details = details.get("data", details)
if not isinstance(details, dict):
raise ValueError("任务详情 data 必须是 JSON 对象")
# API 使用下划线命名,报告数据槽统一使用驼峰命名。
for key, report_key in (("model", "model"), ("task_name", "taskName"), ("input", "input")):
if key in details:
expected = dict if key == "input" else str
if not isinstance(details[key], expected):
raise ValueError(f"任务详情字段 {key} 类型不正确")
report[report_key] = details[key]
payload = json.dumps(report, ensure_ascii=True).replace("<", "\\u003c")
filled = '<script id="reportData" type="application/json">' + payload + '</script>'
with output.open("x", encoding="utf-8") as file:
file.write(html.replace(slot, filled))
print(f"报告已生成:{output.resolve()}")
PY
脚本不会覆盖已有报告。重新生成时,请修改输出文件名或移走旧文件。查看报告不需要安装 Python。
打开与检查
双击 HTML 即可离线打开,三维展示需要浏览器支持 WebGL。分享前,建议确认:
- 可以切换结构样本,三维结构与置信度指标正常显示。
- 添加的任务信息正确,任务输入可展开查看。
- 可以导出结果 ZIP 和当前结构的 CIF 文件。
请使用下载的完整结果 ZIP,保留其中的结构与置信度文件。仅有 CIF 或单个最佳结构的精简包不适用于本模板。
结果 ZIP 最大支持 200 MiB,解压后总大小不超过 800 MiB。较大的报告需要更长的加载时间和更多浏览器内存。置信度指标用于辅助评估,不能替代实验验证。
报告支持通过「打开其他结果」临时查看另一份 ZIP。此操作不会保存新结果;如需分享,请为该任务重新生成报告。