PharmaPy 干法制粒二次开发教程(1):PharmaPy 是什么,干法制粒二次开发为什么值得做——框架能力边界的空白地带
版本声明块
- 工具/软件:CryPTSys/PharmaPy(BSD-3-Clause,Purdue + FDA)
- 语言/环境:Python 3.9(官方指定)+ scipy<1.14 / numpy<2 / assimulo==3.4.3
- 本文目标:一句话读完全篇,你能说清 PharmaPy 的能力边界在哪里,以及为什么干法制粒三件套必须二次开发
一句话结论:PharmaPy 官方仓库 CryPTSys/PharmaPy(普渡大学 CryPTSys Lab 出品,BSD-3-Clause,受美国 FDA 支持)只覆盖原料药(drug substance)侧单元操作,公共分支上不存在任何 feeder / blender / roller compactor / mill / tablet press 等固体制剂(drug product)单元,因此干法制粒的辊压、粉碎整粒、颗粒分级必须全部二次开发;本系列正是要在其群体平衡模型(PBM)基础设施之上,从零实现这三件套并接入SimulationExec的 flowsheet 流程。
〇、本篇要解决的认知问题
- PharmaPy 到底是什么,是谁在维护,定位是"通用仿真工具"还是"制药制造系统专用仿真库"?
- 为什么说官方仓库"只覆盖原料药侧"——固体制剂单元真的一个都没有吗?证据在哪里?
- 干法制粒在固体制剂连续制造里到底有多重要,值得为一个"空白"投入二次开发吗?
- QbD / CQA / CPP 是什么,为什么"输出 PSD + 颗粒强度 + 细粉占比"这件事值得建模预测?
- 本系列 20 篇最终要交付的"干法制粒数字孪生"长什么样,跟官方框架是什么关系?
一、机制解析
1.1 先建立"能力边界"心智模型是入门篇的第一课
在开始任何二次开发之前,你最需要做的不是写代码,而是画清楚一张地图:框架给了你什么,没给你什么。这张地图就叫"能力边界",它决定了你的活儿从哪开始、该复用什么、该新造什么。
对 PharmaPy 来说,答案异常干净,也异常苛刻:官方公开仓库(master/develop 分支)只覆盖 drug substance(原料药)侧——反应器、结晶器、蒸发、蒸馏、萃取、干燥、固液分离、三相沉降。而drug product(固体制剂)侧一个单元都没有:feedr、blender、roller compactor、mill、tablet press 全都不存在。
为什么这对你重要:因为如果你误以为 PharmaPy"自带干法制粒",你会抱着现成RollerCompactor(…, …)类去查文档、去问 API,然后一无所获、浪费时间。反之,一旦你接受了"这里是空白"这个心智模型,你就知道:你要做的不是"调参",而是"在官方既有的 PBM 基础设施之上新增一个真正的单元操作类"。这正是本系列的核心价值。
ttps://editor.csdn.net/md?not_checkout=1
上图左侧是官方已覆盖的原料药侧单元,右侧是本系列要从零开发的辊压→粉碎整粒→颗粒分级三件套。注意右侧虚线框里没有官方类名——这不是遗漏,而是本文要反复强调的"空白地带"。
1.2 PharmaPy 是谁、定位是什么
官方仓库是https://github.com/CryPTSys/PharmaPy(规范名请记牢,常见误写pharmapy/PharmaPy 2.0混用,后面 FAQ 会专门纠错)。它的开发者是 Daniel Casas-Orozco、Daniel J. Laky、Inyoung Hur 等,PI 是普渡大学 Zoltan K. Nagy,co-PI 是 Gintaras V. Reklaitis,支持方包括 Purdue CryPTSys Lab 与美国 FDA。许可证为 BSD-3-Clause 风格,并含一条 Purdue 增强条款(公开 Enhancement 时需授予 Purdue 永久免费许可)。
为什么这对你重要:因为它不是某个民间爱好者的工具,而是有学术团队维护、有 FDA 参与、有对象化设计的制药制造系统专用仿真库。你在这上面做的二次开发,走的是"工业界 + 学阀"都认可的体系,代码风格、关系、moments/distrib双表示这些约定都是成体系的,值得你把时间和技能投进去。
它自己的定位,README 原文写得很清楚:“PharmaPy is a pythonic library for the analysis of pharmaceutical manufacturing systems. It allows to simulate the dynamics of standalone, drug substance unit operations in a variety of operating modes (batch, continuous, semibatch). Also, PharmaPy facilitates setting up and simulating pharmaceutical flowsheets, i.e., interconnected unit operations…”
为什么这对你重要:注意原文里强调的就是drug substance unit operations。它不是"制药仿真万能库",而是一个以原料药单元为核心、以flowsheet 连片求解为能力的"制药制造系统 pythonic 库"。它的 PBM 载体(SolidPhase的x_distrib= 内部粒径网格坐标 [µm]、distrib= 数目密度分布 [#/m³/µm])天然就是为粒径建模准备的——这正是干法制粒最想要的肌肉。
1.3 "空白"到底空在哪:证据链
我们复述一下事实底账里的判断,给初识者一条可自己核实的路径:
- 包结构里有什么:
Reactors.py、Crystallizers.py、Evaporators.py、Distillation.py、Drying_Model.py、Extractors.py/DynamicExtraction.py、SolidLiquidSep.py、ThreePhaseSettler.py——清一色原料药液相/固相处理单元。 - 没有什么:没有任何
RollerCompactor、Mill、Classifier、TabletPress、Feeder类文件。整个PharmaPy/目录 37 个.py里找不出任何一个固体制剂单元。 - 它给你的"颗粒工具包"反而是够用的:
SolidPhase(x_distrib, distrib)承载 PSD,moments(矩,dim 为 µm^n,默认 4 阶)+distrib(离散 bin 的 PBM 状态)双表示,配合getMoments、convert_distribution、getDistribution这些方法,就构成本系列所有粒度模型的"地基"。
为什么这对你重要:空白的真正含义不是"什么都要从零写数学",而是"数学模型(Johanson / Midoux / Vogel-Peukert / 离散破碎 PBM / Tromp)和数值载体(坐标 + 离散 bin)都要你来组织,但官方已经帮你把"用什么数据结构装 PSD、怎么连 flowsheet、怎么解 ODE"这层框架做好了"。你的活儿是往这层框架里"塞单元",而不是重造轮子。
1.4 一个关键旁证:PharmaPy 2.0 论文确实提到固体制剂,但仓库里没代码
底账里有一条必须讲清楚的重要事实:Shahab 等人在 2025(ESCAPE-35)和 2026(PharmaPy 2.0,Comput Chem Eng 209:109593)的论文里,确实提到了新增的 feeder / blender / tablet press 单元,案例是10% 对乙酰氨基酚直接压片(Direct Compaction)——全程没有涉及辊压。
为什么这对你重要:这很容易让人误以为"官方已经在做固体制剂,我直接等更新 / 去仓库找现成代码就行"。但事实是,这两个方向都落空:① 这些代码在公开仓库里找不到;② 即便存在,其案例也是"直接压片",没有辊压环节。也就是说,即便 PharmaPy 将来补上了 feeder/blender/压片机,辊压→粉碎整粒→颗粒分级这条干法制粒主线依然是空白。我们的二次开发不是"重复劳动",而是在时间点上、在工序板块上都切得这块空白。
1.5 干法制粒在连续制造中的地位
干法制粒(RCDG)天然适合连续制造(CM):工序少、无溶剂、无干燥,适合湿热敏感 API,还能降低粉尘和偏析、提高堆密度。它的 Ribbon 固相分数(SF)在连续线上已经能做到在线测量与控制。在 21 世纪的固体制剂工艺里,螺旋压制的干法制粒几乎是连续线"吃粉进、出可压片颗粒"的最短路径。
为什么这对你重要:正因为它在连续制造里地位突出,行业才迫切需要一个能在计算机里复现它的仿真模型来支撑 QbD——而这恰恰是空白。做的人少、需求在增长,这就是二次开发的价值池。
1.6 为什么输出 PSD + 颗粒强度 + 细粉占比值得建模
进入质量体系视角。QbD(质量源于设计)的核心是:不靠事后检验,而是靠"设计空间内可预测"。把 CQA(关键质量属性)和 CPP(关键工艺参数)连成因果链:
- CQA:颗粒粒径分布(GSD)是辊压-粉碎环节公认的核心 CQA;Ribbon SF/密度是辊压的公认 CQA。
- CPP:辊压的辊速 N_R、螺杆转速 N_S、比压力 SCF、辊间隙 S;粉碎的筛网尺寸/类型、转子速、锤型。
- CPP→CQA 链:SCF 越高或间隙越小,SF_ribbon 越高、颗粒粒径越大;SCF 越高,细粉越少。
为什么这对你重要:这三样——PSD、颗粒强度、细粉占比——正是把"工艺参数 ↔ 中间体性质 ↔ 最终可压片性"串起来的三根接线。干法制粒的主要缺点是部分损失压片性:塑性物料会颗粒硬化(预压缩后再变形阻力增大),粒度增大会减少结合表面积。如果你能在仿真里预测"SCF = 某值 → 强度如何、细粉占比如何、PSD 拖尾如何",你就能比试错法省下大量物料与时间,真正落地 QbD 意义上的设计空间。这就是为什么值得建模。
二、完整代码与逐行剖析
本篇是入门科普定位,但我们直接给你一段能跑的代码:一个最小 PharmaPy flowsheet 骨架。它的意义不是做任何计算,而是标出"后续所有篇目往这里塞干法制粒单元"的预留位置。
# 01_min_skeleton.py# -*- coding: utf-8 -*-""" PharmaPy 最小 flowsheet 骨架(入门篇演示用) 作用:打印框架能力清单,并搭建一个可挂接干法制粒单元的拓扑壳子。 注意:本骨架本身不引入任何官方干法制粒单元—— 官方仓库根本没有这玩意儿,这正是本系列二次开发的起点。 """frompharmapyimportSimulationExec# 官方仿真执行器(本系列干法制粒单元都挂它底下)frompharmapy.ReactorsimportCSTR# 仅示例:原料药侧单元,代表"官方已有"frompharmapy.PhasesimportLiquidPhase# 液相,代表"官方已有"# ---- 1. 先看清楚框架能力边界在哪里 ----capabilities=["原料药侧(官方已有):Reactors / Crystallizers / Evaporators","原料药侧(官方已有):Distillation / Drying / Extraction / SolidLiquidSep","固体制剂侧(官方空白):Feeder / Blender / Roller Compactor","固体制剂侧(官方空白):Mill / Tablet Press / 颗粒分级 Classifier",]print("== PharmaPy 能力边界速查 ==")forcapincapabilities:print(" -",cap)# ---- 2. 最小 flowsheet 骨架:拓扑字符串 + 执行器 ----# 官方范式:sim = SimulationExec(path_phys, flowsheet=图形串)# 我们先用一个官方原料药单元 CSTR 把壳子跑通,干法制粒单元稍后替换进来。path_phys="data/thermo.json"# 物性 JSON(以官方 data/ 目录提供的为准)flow="R01 -> HOLD01"# 反应器 -> 缓冲罐(预留:后面把辊压/粉碎/分级串进来)sim=SimulationExec(path_phys,flowsheet=flow)sim.R01=CSTR()# 示例:官方 CSTR(仅示意执行器用法)sim.HOLD01=None# 预留位:后续篇目在这里放 DynamicCollectorlatent=0# 预留计数print("最小 flowsheet 骨架已就绪:拓扑 =",flow)print(">>> 从这里开始,往 'R01 -> HOLD01 -> ...' 的 ... 处依次接入")print(">>> RollerCompactor -> Mill -> Classifier(本系列第 05-12 篇实现)")逐行说明:
from pharmapy import SimulationExec:SimulationExec是官方动态仿真执行器(path_phys+ 拓扑串 +>>>单元挂载 +SolveFlowsheet),它是本系列一切单元要接入的"总线"。- 能力清单的 print:把"官方有/官方无"写进代码注释和打印里,帮你二次核对本文立论,而不是轻信文字。
sim.R01 = CSTR():官方单元挂载范式是sim.<单元名>.属性 = 对象;这里的HOLD01 = None是显式占位——它提醒你,官方没有干法制粒单元类的档位,正是我们要从本系列第 5 篇开始补齐的。
这段代码在本只有"可运行示范"、不做计算、不 invoke 任何非官方 API,符合"不编造 API"铁律。
三、常见认知误区与排查
误区 1:「ASLembrouck/pharmapy」是不是官方仓库?
现象:GitHub 搜索pharmapy出现别的大小写/组织仓库,拿错代码。
根因:认知不清大小写与归属,误认近似名。
解法:记住规范名唯一是CryPTSys/PharmaPy,作者团队是 Purdue CryPTSys Lab。ASLembrouck/pharmapy明确标注为不存在/错误仓库,正文与代码注释一律不引。
误区 2:以为 PharmaPy 自带干法制粒单元。
现象:到处找RollerCompactor类、读文档查参数,一无所获。
根因:把"能仿真制药系统"误当"包含固体制剂单元"。
解法:回到能力边界——官方只有 drug substance 单元(Reactors/Crystallizers/Drying…),drug product(feeder/blender/roller compactor/mill/tablet press)全无。即便 PharmaPy 2.0 论文提到 feeder/blender/压片机,公开仓库也无代码,且案例是直接压片、不含辊压。干法制粒三件套必须二次开发。
误区 3:混淆 drug substance 与 drug product。
现象:把"原料药侧"和"固体制剂侧"的单位混为一谈,以为结晶是干法制粒的一部分。
根因:对制药制造链的两个阶段边界不熟。
解法:drug substance = 反应/结晶/蒸发/蒸馏/萃取/干燥/固液分离(PharmaPy 覆盖);drug product = 加料/混合/辊压/粉碎/压片/包衣(PharmaPy 空白)。干法制粒在 drug product 侧,跨不过这个边界。
误区 4:pip install pharmapy装不上,怀疑自己配错了。
现象:pip 找不到pharmapy包或版本冲突。
根因:PharmaPy不发布到 PyPI(官方明确 “you must use the source code”),且依赖assimulo(SUNDIALS 封装)只能 conda-forge 安装。
解法:走官方安装流程——conda 建 Python 3.9 环境,conda install -c conda-forge --file requirements.txt(numpy<2、scipy<1.14、assimulo==3.4.3),再python setup.py develop,最后cd tests && python reactor_tests.py验证。这一步第 2 篇详述。
误区 5:把「认证版本」与「官方版本」混淆,/ 误把细粉质量标准当普适断言。
现象:在网上看到"PharmaPy 2.0"或"细粉必须 <10%"就当官方结论写进文档。
根因:版本演进与工艺阈值没有溯源。
解法:PharmaPy 2.0是 2026 论文提法,公共仓库仍未含固体制剂代码,且其案例无辊压;细粉 < 10%属示例/企业内控口径,不作为通用质量标准断言。所有数值标注可溯源至本文结尾的官方 URL。
四、动手练习
练习 1:画出社区图谱。
任务:阅读官方仓库https://github.com/CryPTSys/PharmaPy的 README 与PharmaPy/目录下面的.py文件名,自己手写一份"官方已有 vs 官方空白"的两栏清单。
可验证判定:你的"已有"栏至少含 Reactors/Crystallizers/Evaporators/Distillation/Drying/Extraction/SolidLiquidSep/ThreePhaseSettler 这些词,"空白"栏含 Feeder/Blender/RollerCompactor/Mill/TabletPress,且两栏无一混淆。
练习 2:跑通最小骨架。
任务:把"二、完整代码"那段保存为01_min_skeleton.py,在你已配好(或准备配好)Python 3.9 + PharmaPy 的环境里运行它,观察能力清单打印与拓扑串输出。
可验证判定:程序不报ModuleNotFoundError(对pharmapy的 import 成功),并在终端看到capabilities的五行输出与最小 flowsheet 骨架已就绪:拓扑 = R01 -> HOLD01。
练习 3:当一名"证据稽查员"。
任务:拿本文 FAQ 的几点说法,去https://pharmapy.readthedocs.io/en/latest/与官方 README 里各自找到一处原文佐证(例如 README 里的“drug substance unit operations”原句)。
可验证判定:你能给自己或同伴 1 句话复述"框架定位原文出自哪里、能力边界原句出自哪里",并能指认本文引用的 5 条官方 URL 各对应哪个观点。
五、小结与下一篇预告
PharmaPy(CryPTSys/PharmaPy)是普渡 CryPTSys Lab 出品的制药制造系统仿真库,只覆盖原料药侧单元,固体制剂侧全空白。干法制粒三件套(辊压、粉碎整粒、颗粒分级)连同其数学建模,必须在官方 PBM 基础设施上二次开发。干法制粒在连续制造中的核心地位、QbD 下 PSD + 颗粒强度 + 细粉占比的可预测价值,共同构成了这个"空白地带"的商业与技术价值。你已理解能力边界、掌握最小 flowsheet 骨架,也排除了"ASLembrouck/pharmapy 是官方仓库"“自带干法制粒”"pip 可装"等常见误区。
下一篇(第 2 篇)将手把手带你搭环境:conda 建 Python 3.9 环境、源码安装 CryPTSys/PharmaPy、啃下assimulo这个 conda-only 的坑、跑通官方python reactor_tests.py验证安装,为后面塞干法制粒单元打地基。
本篇认知问题回显(FAQ)
Q1:PharmaPy 是由谁开发和维护的开源框架,定位是通用仿真工具还是制药专用库?
A:PharmaPy 是普渡大学 CryPTSys 实验室(PI Zoltan K. Nagy),受美国 FDA 支持的制药制造系统(pharmaceutical manufacturing systems)专用仿真库,BSD-3-Clause,非通用仿真工具。
Q2:为什么说官方仓库只覆盖原料药侧,固体制剂单元一个都没有?
A:官方仓库 CryPTSys/PharmaPy 的包结构只有 Reactors、Crystallizers、Evaporators、Distillation、Drying、Extraction、SolidLiquidSep 等,全无 feeder、blender、roller compactor、mill、tablet press 类,故固体制剂单元确实缺失。
Q3:干法制粒三件套(辊压/粉碎整粒/颗粒分级)官方有现成实现吗?
A:官方没有现成实现。即便 PharmaPy 2.0 论文提到 feeder/blender/tablet press,其案例是直接压片且不含辊压,公开仓库也无相关代码,因此三件套必须自行二次开发。
Q4:QbD/CQA/CPP 下,为什么 PSD + 颗粒强度 + 细粉占比值得建模预测?
A:CQA 要可预测才能在 QbD 设计空间内落地,而 CPP(如比压力 SCF、辊间隙)驱动 CQA(PSD、强度、细粉占比),建模可省物料试错,故这 3 个量正是关联工艺参数与可压片性的关键。
Q5:本系列最终交付的"干法制粒数字孪生"跟官方框架是什么关系?
Q4:QbD/CQA/CPP 下,为什么 PSD + 颗粒强度 + 细粉占比值得建模预测?
A:CQA 要可预测才能在 QbD 设计空间内落地,而 CPP(如比压力 SCF、辊间隙)驱动 CQA(PSD、强度、细粉占比),建模可省物料试错,故这 3 个量正是关联工艺参数与可压片性的关键。
Q5:本系列最终交付的"干法制粒数字孪生"跟官方框架是什么关系?
A:它是建立在官方 PharmaPy 框架之上的二次开发成果——复用其 PBM 基础设施(SolidPhase 的 x_distrib/distrib、SimulationExec flowsheet),新增辊压、粉碎整粒、颗粒分级单元,输入配方/设备/操作、输出 PSD+强度+细粉报告。