LAMMPS fix graphics/labels 详解:在 dump image 输出中叠加图片、动态文本与色标图例
LAMMPS fix graphics/labels 详解:在 dump image 输出中叠加图片、动态文本与色标图例
fix graphics/labels 是 LAMMPS GRAPHICS 包提供的一条可视化辅助命令(自 11Feb2026 版本引入),它允许直接在 dump image 渲染出的图像上叠加外部位图图片、动态文本标签和颜色刻度(colormap)图例,从而免去后期二次处理图像的繁琐步骤。本文基于当前仓库的官方文档与源码实现,完整讲解其语法、全部关键字参数、与 dump image 的集成方式,并通过动态 matplotlib 嵌入和仓库真实示例演示如何产出带实时标注的科学可视化图像。
功能概述:给 dump image 输出"加标签"
dump image 是 LAMMPS 生成分子结构渲染图的经典命令,而 fix graphics/labels 的作用,是在 dump image 输出图像上叠加三类"标签"对象:
- image:把一张外部图片(JPEG / PNG / TGA / PPM 格式)嵌入可视化场景,常用于插入结构示意图、数据图表等;
- text:把一段文本(支持 LAMMPS 变量展开)渲染成位图后叠加,常用于显示步数、温度、能量等实时信息;
- colorscale:根据同一个
dump image实例的颜色映射生成色标图例(colormap legend),便于读者从图像颜色反查数值。
其位置坐标既可以解释为模拟盒子坐标系中的坐标(此时对象有真实的前后景深,原子或其他图形对象可以位于标签前后),也可以解释为图像自身坐标系中的坐标(此时标签永远浮在顶层)。选择哪种解释方式由 dump image 命令中 fix 关键字的 fflag1 标志决定,详见下文"与 dump image 的集成"一节。无论采用哪种坐标系,标签本身始终平行于图像平面。
命令语法总览
fix ID group-ID graphics/labels Nevery mode keyword args ...
- ID、group-ID 与一般 fix 命令规则一致,其中 group-ID 会被该 fix 忽略;
graphics/labels是该 fix 的样式名;Nevery表示每隔多少个时间步更新一次图形数据,应与对应的 dump image 命令中的 N 参数保持一致,若两者设置不兼容,LAMMPS 会直接报错终止;mode及后续关键字可选image、text、colorscale三类,同一个 fix 命令中可以出现多个 image / text / colorscale 关键字及其参数,也可用续行符&分行书写。
源码实现中,构造函数 FixGraphicsLabels::FixGraphicsLabels(见 fix_graphics_labels.cpp)在解析阶段就强制校验 narg >= 4 且 nevery > 0,随后循环解析所有模式关键字,任何未知关键字都会以 Unknown fix graphics/labels ... keyword 报错;每类对象解析完成后分别存入 pixmaps、texts、scales 三个对象列表,并在 end_of_step() 中统一处理。
image 关键字:嵌入外部图片
*image* filename x y z keyword args
必需参数为图片文件名和图片中心位置 x y z,可选关键字如下:
| 关键字 | 取值 | 说明 |
|---|---|---|
scale |
数值(默认 1.0) | 图片缩放倍数,可写成变量(v_name) |
transcolor |
auto / none / r/g/b |
透明色选择:auto 取图片左下角像素颜色作为透明色;none 完全关闭透明处理(默认);r/g/b 给出 0~255 的三个整数指定 RGB 透明色 |
文档给出的示例:
fix pix all graphics/labels 100 image teapot.png 5.0 -1.0 -2.0 transcolor auto
fix pot all graphics/labels 100 image teapot.ppm 1.0 v_ypos v_zpos scale v_prog transcolor 19/92/192
第二条命令演示了位置 y、z 与缩放 scale 全部由 equal-style 变量 v_ypos、v_zpos、v_prog 驱动(注意变量需以 v_ 前缀传入),实现图片在场景中随运行移动和缩放。
支持的图片格式与读取细节
文件名后缀决定解析器:.jpg/.jpeg 按 JPEG 格式、.png 按 PNG 格式、.tga 按 TGA 格式读取,其余后缀一律按 PPM(NetPBM)格式处理。源码中的 read_image() 函数(见 fix_graphics_labels.cpp)实现如下关键逻辑:
- JPEG:通过 libjpeg 解压,仅支持 8-bit、3 分量(RGB)图像,逐扫描行读入(
jpeg_read_scanlines); - PNG:通过 libpng 读取,校验文件签名(
png_check_sig),会自动把调色板(palette)、灰度、16-bit、带透明通道等变体统一转换为 8-bit RGB(如png_set_gray_to_rgb、png_set_strip_16、png_set_strip_alpha); - TGA:手工解析 TGA 头(
TGAHeader),支持未压缩(类型 2)与 RLE 压缩(类型 10)两种编码,并自动完成 BGR→RGB 通道交换与各种方向标志处理; - PPM:读取 P3(ASCII)与 P6(二进制)两种变体,拒绝超大或非法尺寸。
并非所有变体都与 LAMMPS 的读取器兼容:JPEG 读取依赖 LAMMPS_JPEG 宏、PNG 读取依赖 LAMMPS_PNG 宏(即编译时需链接对应图形库),遇到不兼容、无法识别或损坏的文件时 LAMMPS 会报错终止,且读取失败信息会具体说明原因(例如 JPEG image format not supported in this LAMMPS binary)。
动态重读机制:运行中更新图片
图片文件只在 MPI rank 0 上读取并存储(if (comm->me == 0))。每次 end_of_step() 执行时,LAMMPS 都会用 platform::file_write_time() 获取文件时间戳并与上次对比(见 fix_graphics_labels.cpp);一旦检测到文件内容被修改,就会自动重新读取。这使"边运行边改图"成为可能——例如在模拟过程中用 matplotlib 生成新图表,下一帧 dump image 就会自动叠加最新版本。
缩放与透明处理
- 缩放使用双线性插值算法(bilinear scaling);
- 透明色像素在渲染时被跳过:
auto直接取位图首像素(左下角)作为透明色,none把透明色置为非法值-255.0以完全禁用,r/g/b则通过get_color()(见 fix_graphics_labels.cpp)解析三个通道值并校验 0~255 范围。
text 关键字:叠加动态文本标签
*text* labeltext x y z keyword args
labeltext 是标签文本,若含空白必须加引号;其语法要求与 fix print 一致:支持 equal-style 变量 ${name} 与立即变量 $(expression) 两种写法,变量会在每个 Nevery 时间步被求值并展开。位置 x y z 为中心坐标。
可选关键字:
| 关键字 | 取值 | 说明 |
|---|---|---|
fontcolor |
white(默认)/ black / r/g/b |
文字颜色 |
framecolor |
silver(默认)/ darkgray / white / black / r/g/b |
文字外框颜色 |
backcolor |
silver(默认)/ darkgray / white / black / r/g/b |
文字背景颜色 |
transcolor |
silver(默认)/ darkgray / white / black / none / r/g/b |
透明色 |
size |
数值(默认 24,可变量) | 字符大小(像素,约值),接受 4~512 |
horizontal |
无参数 | 创建水平文本(默认) |
vertical |
无参数 | 创建垂直文本 |
文档示例:
fix lbl all graphics/labels 1000 text "LAMMPS graphics demo" 5.0 -1.0 -2.0 backcolor darkgray framecolor black
fix info all graphics/labels 1000 text "Step: $(step) Angle: ${rot}" 5.0 -1.0 -2.0 size 32
第二条命令把运行步数与角度实时写入标签——$(step) 是立即变量,${rot} 是脚本中预先定义的 equal-style 变量,两者在每个 Nevery 步被 input->substitute() 展开后重新栅格化(见 fix_graphics_labels.cpp)。
颜色语义与透明背景技巧
transcolor 的默认值是 silver,其设计巧妙:如果透明色与字体色、背景色、外框色中的某一项相同,那么这些像素不会被绘制。因此默认设置下,文本会以纯白色渲染、且不带背景和外框。若希望文本有背景框,应把 backcolor/framecolor 设为与 transcolor 不同的颜色。
文档特别提示:渲染透明背景文本时,建议选用与背景相近但略深或略亮的颜色,以减少边缘抗锯齿(anti-aliasing)带来的杂色。源码中也印证了抗锯齿策略:文字先以 2 倍尺寸栅格化再缩放回目标尺寸,size 内部会翻倍(txt.size *= 2.0),超过 128 时先按 128 渲染再由 txt.scale 放大(见 fix_graphics_labels.cpp),因此传入 4~512 的合法范围在内部对应 8~1024。
colorscale 关键字:生成色标图例
*colorscale* dump-ID titletext x y z keyword args
colorscale 会为指定 dump-ID 的 dump image 实例创建颜色映射图例:文本显示在图例中央上方,文本左侧为下限值、右侧为上限值,颜色条由下限到上限线性插值生成。该 fix 直接从对应 dump 实例获取实际数值范围。
必需参数为 dump-ID、图例标题文本(含空白需引号,同样支持变量)与中心位置。可选关键字:
| 关键字 | 取值 | 说明 |
|---|---|---|
size |
数值(默认 24,可变量) | 文字大小(像素,约值),4~512;色条的高宽跟随文字大小 |
length |
数值 | 色标最小长度(近似值,用于决定文字内边距) |
tics |
非负整数(默认 0) | 色条上绘制的分隔刻度线数量,便于对照数值 |
map |
atom(默认)/ grid / bond |
选择展示 dump image 的哪一种颜色映射(见 4Jul2026 版本新增说明) |
fontcolor / framecolor / backcolor / transcolor |
同 text | 颜色设置;其中 fontcolor 同时决定色条边框与刻度的颜色 |
horizontal / vertical |
无参数 | 图例方向,默认水平 |
文档示例(一个 fix 内叠加两个图例):
fix obj all graphics/labels 200 colorscale viz "Atom Velocity" 20.0 6.5 13.0 size 32 length 1000 &
transcolor none framecolor white backcolor darkgray tics 12
fix bnd all graphics/labels 200 colorscale viz "Bond Strain" 20.0 6.5 -13.0 map bond size 32 length 1000
dump image 实例内部实际包含三套独立的颜色映射:原子(由 dump_modify amap 设置)、网格单元(gmap)、键(bmap)。map atom 选择原子映射(默认),map grid 选择网格单元映射,map bond 选择键映射。如果所选映射在该 dump image 中并未真正用于给任何对象上色,LAMMPS 会打印警告,且图例显示该映射(未使用的)默认范围——这一检查在源码 init() 中通过 dump->colormap_active(scale.mapidx) 完成(见 fix_graphics_labels.cpp)。
动态颜色映射的注意点
文档明确警告(Dynamic color maps 提示框):当使用以 min/max 作为上下界的动态颜色映射时,由于 dump 是在 fix 之后执行的,fix 只能取到上一个 dump 输出步的上下界数值。因此叠加 colorscale 图例时一般建议使用固定范围的映射;制作动画电影时尤其如此——固定范围可以防止色标图例因字符宽度变化而伸缩抖动。源码 init() 中也会对动态映射打印警告:Dump ... uses a dynamic color map. Color scale can only use data from previous dump output。
与 dump image 集成:fix 关键字与坐标系统
fix graphics/labels 专为 dump image 的 fix 关键字设计。dump image 中的 fix 关键字格式为(详见 dump_image.rst):
fix fixID color fflag1 fflag2
color取值type/element/const,对该 fix 绘制的标签对象没有影响(标签颜色由 fix 自身参数决定),const时的默认色是白色;fflag1决定标签位置坐标的解释方式:0:使用模拟盒子坐标系(x、y、z 为真实空间坐标)。此时标签与原子、其他图形对象存在真实的前后遮挡关系(依据 z 坐标与相机距离),标签始终平行于图像平面;1:使用图像坐标系。(0,0)为图像左下角,(<图像宽>, <图像高>)为右上角,此时 z 坐标被忽略,标签永远浮在一切对象之上。
fflag2对该 fix 无意义,会被忽略。
图像坐标系下若两个标签重叠,先加入图像的标签显示在上方;同一 fix 内部的次序无法改变,但可以通过多个 fix 命令配合——dump image 命令行中 fix 关键字的出现顺序决定了哪个 fix 的标签绘制在顶层。
另外,该 fix 绘制的图像默认完全不透明,可通过 dump_modify ftrans 调整透明度。dump image 的颜色样式设置对 image / text 标签均无效。
变量驱动:让标签随模拟"动"起来
image 的位置(x、y、z)、缩放 scale 与 text / colorscale 的 size 均可以写成 equal-style 变量,传入时以 v_name 形式书写(name 为变量名)。每个 Nevery 时间步,fix 都会对这些变量重新求值。
源码中通过 PARSE_VARIABLE 宏实现解析(见 fix_graphics_labels.cpp):当参数以 v_ 开头时记录变量名(置 varflag),否则解析为数值;init() 阶段用 CHECK_VARIABLE 宏(L776-L786)校验变量存在且为 equal-style;end_of_step() 中调用 input->variable->compute_equal(...) 实时求值(如 L864-L869)。若检测到任何变量参与,fix 会注册对应的 compute 触发步(modify->addstep_compute_all / addstep_compute),保证依赖的 compute 结果在正确的时间步可用。更详细的变量使用讨论可参考 fix graphics/objects。
实战:运行时用 matplotlib 生成动态图像并嵌入
文档提供了一套完整方案:在模拟运行过程中用 matplotlib 绘制实时图表,由 fix python/invoke 周期性调用,再把生成的 PNG 透明化处理后嵌入 dump image 输出。该方案需要以 PYTHON 包编译 LAMMPS,并安装 LAMMPS Python 模块。核心输入脚本如下:
python source here """
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
from lammps import lammps
"""
python myplot input 2 SELF 0 format pi here """
def myplot(lmpptr, vflag):
lmp = lammps(ptr=lmpptr)
fig, ax = plt.subplots(facecolor=(0.9,0.9,0.9),edgecolor='white')
ax.set_facecolor((0.9,0.9,0.9))
ax.set_title('Demo Plot: LAMMPS version ' + str(lmp.version()) ,color='white')
ax.set_xlabel('Time',color='white')
ax.set_ylabel('Value',color='white')
ax.tick_params(colors='white')
for spine in ax.spines.values():
spine.set_edgecolor('white')
ax.plot([1,2,3,4,5,6],[2,3,2.5,3.1,2.8,3.0],color='white', linestyle='--')
fname = 'myplot.png'
plt.savefig(fname,dpi=180)
plt.close()
"""
fix plot all python/invoke 1000 post_force myplot
fix label all graphics/labels 100 image myplot.png 20.0 9.0 10.0 transcolor auto scale 0.5
dump viz all image 100 image-*.png type type size 800 800 view 80 10 box yes 0.02 &
fsaa yes shiny 0.1 ssao yes 23154 0.8 zoom 1.4 fix label type 0 0
dump_modify viz pad 6 backcolor2 gray backcolor darkgray boxcolor silver
关键设计意图:
- matplotlib 使用非交互式
agg后端,保证无界面环境下也能输出 PNG 文件; myplot()函数接收 LAMMPS 对象指针与整数标志两个参数(符合fix python/invoke的调用约定),通过lammps(ptr=lmpptr)重建对象后查询 LAMMPS 版本号写入标题;- 为了让图像叠加后呈"透明"效果,所有线条与文字设置为白色,背景用很亮的灰色(极小化删除背景像素时的抗锯齿残留);
fix label使用transcolor auto自动以左下角(即背景灰色)作为透明色,配合scale 0.5缩放;- 图表仅在每第 10 帧 dump 图像时更新(两个 fix 的 Nevery 分别为 1000 与 100)。
把上述命令加入 melt 示例后,输出效果如下图所示——渲染结果中既包含原子结构,又叠加了实时绘制的数据图(示例输出图):
仓库内的真实用法示例
除了文档示例,当前仓库的示例脚本也大量使用了该命令:
- examples/GRAPHICS/in.peptide-hbonds:在一个 fix 中同时叠加两个动态文本标签(用
$(c_hb1:%02.0f)格式化氢键数目)和一张hbond-diagram.png示意图,随后 dump image 以fix label const 1 0(fflag1=1即图像坐标系)引入; - examples/GRAPHICS/in.breakable:用
text关键字在场景中叠加标题文本,展示盒子坐标系(fflag1=0)下的用法。
这些示例与文档配合,可作为快速上手的起点。
构建要求与限制
fix graphics/labels属于 GRAPHICS 包(自 11Feb2026 版本新增,dump image、dump movie及多个 fix graphics/... 样式被整合进该包),只有在以该包构建 LAMMPS 时才可用,见 Build package;- 读取 JPEG / PNG 格式图片需要编译时链接对应图形库:CMake 构建通过
-D WITH_JPEG=value与-D WITH_PNG=value开关控制(默认在找到开发文件时自动开启),找不到时可用-D JPEG_INCLUDE_DIR、-D JPEG_LIBRARY、-D PNG_INCLUDE_DIR、-D PNG_LIBRARY手动指定路径,详见 Build_extras.rst 的 GRAPHICS 一节;TGA 与 PPM 格式无需额外依赖; - 该 fix 不写入二进制重启文件,fix_modify 的选项对它也都不适用。
默认值汇总
| 参数 | 默认值 |
|---|---|
image transcolor |
none |
text transcolor |
silver |
image scale |
1.0 |
text / colorscale fontcolor |
white |
text / colorscale backcolor |
silver |
text / colorscale framecolor |
silver |
text / colorscale size |
24 |
| 文本 / 图例方向 | horizontal |
colorscale tics |
0 |
colorscale map |
atom |
相关命令
与可视化、文本输出相关的配套命令:fix print、dump image、fix graphics/arrows、fix graphics/chunk、fix graphics/isosurface、fix graphics/lines、fix graphics/objects、fix graphics/periodic、fix graphics/replica。
