生物医学网络科学Biomedical Network Science
Example08 / 08

运行清单(provenance manifest)——记录环境、参数、种子与输入输出的哈希

所属专题
研究问题、可复现分析与敏感性分析
下载
Notebook · .py

把一次网络分析需要复算的信息写进 JSON:Python 与关键包版本、平台、参数、随机种子、 输入文件与输出结果的 SHA-256。然后用同样的设置重跑一次,比较输出哈希是否一致。 解读:哈希一致说明在同一环境下可复算;换机器或升级包后若哈希改变,可据清单逐项排查。 浮点运算在不同平台或并行设置下可能有末位差异,此时应比较数值容差而非字节哈希。

Output文字输出

{
  "python": "3.15.0",
  "platform": "macOS-27.2-arm64-arm-64bit-Mach-O",
  "packages": {
    "networkx": "3.7",
    "numpy": "2.5.4",
    "scipy": "1.18.1"
  },
  "parameters": {
    "algorithm": "louvain",
    "resolution": 1.0,
    "seed": 20261115
  },
  "inputs": {
    "network.edgelist": "1b72d131cad3ad359a30ff4141707c9dc374606e59cd93bae6ef3a018ebdea95"
  },
  "outputs": {
    "result_run0.json": "8ec16652fa98ccdd7a847a304721a36121b25596ffe0ec4ace3c723093c7d7d6"
  },
  "modularity_Q": 0.5025
}
两次运行输出哈希一致: True

Code代码

# 把一次网络分析需要复算的信息写进 JSON:Python 与关键包版本、平台、参数、随机种子、
# 输入文件与输出结果的 SHA-256。然后用同样的设置重跑一次,比较输出哈希是否一致。
# 解读:哈希一致说明在同一环境下可复算;换机器或升级包后若哈希改变,可据清单逐项排查。
# 浮点运算在不同平台或并行设置下可能有末位差异,此时应比较数值容差而非字节哈希。
import hashlib, json, platform, sys, tempfile
from pathlib import Path
import numpy as np
import networkx as nx
import scipy

def sha256(path):
    return hashlib.sha256(Path(path).read_bytes()).hexdigest()

def run_analysis(edge_file, out_file, seed, resolution):
    G = nx.read_edgelist(edge_file, nodetype=int)
    comms = nx.community.louvain_communities(G, seed=seed, resolution=resolution)
    Q = nx.community.modularity(G, comms)
    labels = {v: i for i, c in enumerate(sorted(comms, key=min)) for v in c}
    Path(out_file).write_text(json.dumps({"Q": round(Q, 10), "labels": [labels[v] for v in sorted(G)]}))
    return Q

workdir = Path(tempfile.mkdtemp())
edge_file = workdir / "network.edgelist"                      # 模拟的“原始数据”
nx.write_edgelist(nx.random_partition_graph([20, 20, 20], 0.3, 0.03, seed=5), edge_file, data=False)

params = {"algorithm": "louvain", "resolution": 1.0, "seed": 20261115}
hashes = []
for run in range(2):
    out = workdir / f"result_run{run}.json"
    Q = run_analysis(edge_file, out, params["seed"], params["resolution"])
    hashes.append(sha256(out))

manifest = {
    "python": sys.version.split()[0], "platform": platform.platform(),
    "packages": {"networkx": nx.__version__, "numpy": np.__version__, "scipy": scipy.__version__},
    "parameters": params,
    "inputs": {edge_file.name: sha256(edge_file)},
    "outputs": {"result_run0.json": hashes[0]},
    "modularity_Q": round(Q, 4),
}
(workdir / "manifest.json").write_text(json.dumps(manifest, indent=2, ensure_ascii=False))
print(json.dumps(manifest, indent=2, ensure_ascii=False))
print("两次运行输出哈希一致:", hashes[0] == hashes[1])

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

运行清单(provenance manifest)——记录环境、参数、种子与输入输出的哈希