50 分钟数据库计算值已执行的网页阅读版

核对分子式与计算性质

解析八个 PubChem 分子式,重建近似摩尔质量,并比较元素质量分数与计算描述符。

化学 · 第 01 课🔋 离线核心分析⏱ 50 分钟数据库计算值📦 numpy · pandas · matplotlib · IPython

目标与运行方法

本课适合具备 Python 基础的本科生。先阅读每一步的方法与图注,再修改参数。AI 练习为可选部分,不需要 AI 账号即可完成核心课程。数据写在 notebook metadata 中,不需要另下载数据文件。请保持 notebook 已保存到当前工作文件夹。

学习任务是理解本课的研究问题、执行透明的计算、校验结果,并说明结论的边界。

环境与参数

In [1] · Python
from pathlib import Path
import base64, gzip, hashlib, json, platform
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display, HTML
import re
from IPython.display import display as _display
def display(value):
    if isinstance(value,pd.DataFrame):
        table=value.to_html(max_rows=12,escape=True)
        style="<style>.vibeit-readable-table{max-width:100%;overflow-x:auto}.vibeit-readable-table table{width:max-content;max-width:none;border-collapse:collapse}.vibeit-readable-table td,.vibeit-readable-table th{white-space:nowrap!important;word-break:normal!important;overflow-wrap:normal!important}</style>"
        return _display(HTML(style+'<div class="vibeit-readable-table">'+table+'</div>'))
    return _display(value)
RECIPE_ID='ch01-molecular-formulas'
OUTPUT_DIR=Path.cwd()/"results"/RECIPE_ID
plt.rcParams.update({"figure.dpi":120,"font.size":10,"axes.spines.top":False,"axes.spines.right":False,
                      "axes.prop_cycle":plt.cycler(color=["#18785f","#416aa6","#bc6541","#9974a5"])})
print("Python:",platform.python_version(),"; NumPy:",np.__version__,"; Pandas:",pd.__version__)
print("Working folder:",Path.cwd())
print("Core data mode: embedded snapshot; no network requests")
Python: 3.13.13 ; NumPy: 2.5.3 ; Pandas: 3.0.6
Working folder: /Users/zhiluo/Developer/vibeit-cookbook/cookbook/downloads
Core data mode: embedded snapshot; no network requests

读取内嵌快照

In [2] · Python
def load_snapshot(recipe_id, expected_sha256, snapshot_key):
    """Read embedded data from this notebook, including a renamed copy."""
    for path in sorted(Path.cwd().glob("*.ipynb")):
        try:
            notebook = json.loads(path.read_text(encoding="utf-8"))
            metadata = notebook.get("metadata", {}).get("vibeit_cookbook", {})
            blob = metadata.get("snapshots", {}).get(snapshot_key)
            if metadata.get("recipe_id") != recipe_id or not blob:
                continue
            if blob.get("sha256") != expected_sha256:
                continue
            raw = gzip.decompress(base64.b64decode(blob["gzip_base64"], validate=True))
            if hashlib.sha256(raw).hexdigest() != expected_sha256:
                raise ValueError("Embedded snapshot checksum mismatch: " + snapshot_key)
            return json.loads(raw)
        except (OSError, json.JSONDecodeError):
            continue
    raise FileNotFoundError(
        "Save/open the complete .ipynb in the active working folder. "
        "The embedded snapshot could not be located for " + recipe_id)

SNAPSHOT_HASHES={'molecules': '780c5f98bb3b7261465f8330d4b31589d4224cdf21f916b4a1788f11bcc00aac'}
def snapshot(key):
    return load_snapshot(RECIPE_ID,SNAPSHOT_HASHES[key],key)
print("Embedded snapshots:",list(SNAPSHOT_HASHES))
Embedded snapshots: ['molecules']

方法函数

In [3] · Python
def parse_simple_formula(formula):
    """Parse plain elemental formulas; refuse isotopes, groups and charge notation."""
    tokens=re.findall(r'([A-Z][a-z]?)(\d*)',formula)
    if not tokens or ''.join(element+count for element,count in tokens)!=formula:
        raise ValueError('This teaching parser accepts plain elemental formulas only')
    counts={}
    for element,text in tokens:
        count=int(text) if text else 1
        if count<1:raise ValueError('Element counts must be positive')
        counts[element]=counts.get(element,0)+count
    return counts

print("Method ready: parse_simple_formula")
Method ready: parse_simple_formula

数据与模型边界

PubChem 性质与构象是数据库计算字段,不是新实验测量。本课 V2000 解析范围明确限定为原子、来源键型与形式电荷。滴定及校准使用已声明的理想/模拟教学假设;水蒸气压使用署名的 IAPWS 参考关联式。描述符、距离和视觉邻近不能证明生物活性或结合强度。

分步分析

1. 加载计算字段并声明解析边界

来源给出八个声明 CID 的分子式、计算分子量和描述符。可读解析器接受普通元素/数量分子式,拒绝括号、同位素和电荷写法,不静默改义。

In [4] · Python
molecules=snapshot("molecules")
properties=pd.DataFrame(molecules["properties"]).set_index("CID")
assert len(properties)==8 and properties.index.is_unique
display(properties[["name","MolecularFormula","MolecularWeight","TPSA","Charge"]])
atomic_weights={"H":1.008,"C":12.011,"N":14.007,"O":15.999}
counts={int(cid):parse_simple_formula(row.MolecularFormula) for cid,row in properties.iterrows()}
assert all(set(count)<=set(atomic_weights) for count in counts.values())
name MolecularFormula MolecularWeight TPSA Charge
CID
702 ethanol C2H6O 46.070 20.2 0
176 acetic acid C2H4O2 60.050 37.3 0
241 benzene C6H6 78.110 0.0 0
887 methanol CH4O 32.042 20.2 0
180 acetone C3H6O 58.080 17.1 0
2519 caffeine C8H10N4O2 194.190 58.4 0
2244 aspirin C9H8O4 180.160 63.6 0
750 glycine C2H5NO2 75.070 63.3 0

2. 重建近似摩尔质量

使用明确舍入的平均原子量,单位 g/mol;这不是单同位素质量计算。与 PubChem 的微小差异来自舍入及表示方式,应保留原值与重建值。

In [5] · Python
calculated=np.array([sum(atomic_weights[element]*count for element,count in counts[int(cid)].items()) for cid in properties.index])
comparison=properties[["name","MolecularWeight"]].copy();comparison["reconstructed_g_per_mol"]=calculated
comparison["difference_g_per_mol"]=calculated-properties.MolecularWeight
fig,ax=plt.subplots(figsize=(8,4));ax.barh(properties.name,properties.MolecularWeight,label="PubChem")
ax.plot(calculated,np.arange(8),"kx",label="Rounded atomic-weight reconstruction")
ax.set(xlabel="Molar mass (g/mol)",title="Formula-based reconstruction of calculated source masses");ax.legend();plt.tight_layout();plt.show()
Computed figure from this code cell

3. 解读元素质量分数

叠加柱表示在同一舍入原子量约定下 C、H、N、O 的质量百分比。质量分数不同于原子数量分数,氢原子较多不代表总质量占比最高。

In [6] · Python
fraction=pd.DataFrame({element:[atomic_weights[element]*counts[int(cid)].get(element,0)/calculated[j] for j,cid in enumerate(properties.index)] for element in atomic_weights},index=properties.name)
fig,ax=plt.subplots(figsize=(9,4));(100*fraction).plot.bar(stacked=True,ax=ax)
ax.set(ylabel="Elemental mass (%)",xlabel="Declared compound",title="Mass fractions under the stated atomic-weight convention");plt.xticks(rotation=25,ha="right");plt.tight_layout();plt.show()
Computed figure from this code cell

4. 比较第二个计算描述符

TPSA 是计算的拓扑极性表面积,单位平方埃。与摩尔质量的散点仅描述这八个分子,不估计通透性、毒性或药效。

In [7] · Python
fig,ax=plt.subplots(figsize=(8,5));ax.scatter(properties.MolecularWeight,properties.TPSA,s=40)
for row in properties.itertuples():ax.annotate(row.name,(row.MolecularWeight,row.TPSA),fontsize=8,xytext=(4,4),textcoords="offset points")
ax.set(xlabel="Calculated molar mass (g/mol)",ylabel="Calculated TPSA (Ų)",title="Reported descriptors, not a biological assay");plt.tight_layout();plt.show()
Computed figure from this code cell

5. 检查分数守恒及不支持的语法

分数应和为一,重建质量与舍入来源值相差不超过 0.03 g/mol。检查含分组分子式会报错,再随原子量约定导出计算。

In [8] · Python
assert np.allclose(fraction.sum(axis=1),1)
assert np.max(abs(comparison.difference_g_per_mol))<.03
try:parse_simple_formula("Mg(OH)2")
except ValueError:print("Grouped formula rejected by the declared simple parser")
else:raise AssertionError("Unsupported syntax silently accepted")
OUTPUT_DIR.mkdir(parents=True,exist_ok=True);comparison.to_csv(OUTPUT_DIR/"molar-mass-reconciliation.csv")
fraction.to_csv(OUTPUT_DIR/"elemental-mass-fractions.csv")
(OUTPUT_DIR/"atomic-weights.json").write_text(json.dumps(atomic_weights,indent=2))
print("Mass and fraction checks passed; exports:",OUTPUT_DIR)
Grouped formula rejected by the declared simple parser
Mass and fraction checks passed; exports: /Users/zhiluo/Developer/vibeit-cookbook/cookbook/downloads/results/ch01-molecular-formulas

自主练习与参考答案

  1. 比较乙醇的原子分数与质量分数。
  2. 解释为何这不是单同位素质量。

参考解释。 质量分数按声明的平均原子量加权元素数量。本表用舍入平均量,不是特定同位素质量。

先保留当前 notebook 副本,再修改参数。把新图与原图一起比较,并记录改变了哪些输入、哪些计算和哪些结论。

可选的 AI 编程练习

提示词 1

仅用标准库 re、NumPy、Pandas、Matplotlib,为同八个 CID 增加原子分数图。

提示词 2

使用同样的包标注质量重建差,并明确列出不支持的分子式语法。

人工验收。 质量分数和为一,使用保存的原子量表,分组/电荷语法报错。

检查修改后的源代码,再手动运行受影响单元及后续校验。要求助手解释修改的目的、使用的包和数据来源,并用实际输出核对解释。

可选联网扩展

In [9] · Python
RUN_ONLINE_UPDATE=False
if RUN_ONLINE_UPDATE:
    import requests
    try:
        response=requests.get('https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/2519/property/MolecularFormula/JSON',timeout=20)
        response.raise_for_status()
        print("Source:",response.url)
        print(response.text[:700])
    except requests.RequestException as error:
        print("Online extension unavailable:",type(error).__name__,str(error)[:160])
else:
    print("Online extension skipped; embedded core data unchanged")
Online extension skipped; embedded core data unchanged

来源、快照与下一步

  • PubChem calculated molecular properties — NCBI public data; PubChem computed properties only; credit PubChem; no third-party narrative annotations included; retrieved 2026-10-09. SHA-256 b01b092cc8872e14fdab1fdc608c783669131a081c71d9ccee77c0bb9c6ff408. Keep the returned calculated fields for eight declared CIDs; molecular weight converted from API numeric string.

  • PubChem 2D SDF 702 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 5962afc9ee8115dee9d5e63cefeef89cdc47641420b34afe156062d263c9caa7. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 176 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 f51353e1db0a0be8aa3aeb7bea28b6febb1e1f8afdf88fbf298405851f7ee092. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 241 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 3f4698bd6773f5e709184759048c116d106ac392e874676444b64af254e9a189. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 887 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 5cf6d180935f2fe77d20772a4bf2506711d4436762f6c6801157ac748f088530. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 180 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 6ecceacce326b6ecc292dedd946f589e879c999f43242395d995b59a8c8eb128. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 2519 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 47293391d630f44f2a32c3f7702d766744c8f4a4f16f6571d4ae09f04b3daaed. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 2244 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 0dfd04496745032c06410241f91f10fcec77cbc6828cdbede75f4c08da418fbb. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem 2D SDF 750 — NCBI public data; PubChem standardized structure; credit PubChem; retrieved 2026-10-09. SHA-256 e1c2ddd732cea1d052a9426c9a25fef86acd1309748bb2115cf2b56481ba288f. Preserve complete standardized SDF, including CID and explicit hydrogen/bond fields.

  • PubChem caffeine 3D conformer — NCBI public data; PubChem computed conformer; credit PubChem; retrieved 2026-10-09. SHA-256 2a78d98d09d50768fe3f6e6114d7baf3dad9cf88e41835735f96abf5867f5092. Preserve calculated coordinates and conformer identifiers; not an experimental crystal structure.

下一步。 在保留本课的数据检查、参数记录和结果校验之后,将相同方法用于自己的公开或已获授权数据。记录研究设计与方法限制,不把示例结果当成新实验的验证。完整数据许可与生成说明见 cookbook 网页。