关于yt ProjectionPlot自定义调整及Matplotlib兼容性的技术问询
嘿,作为经常用yt做可视化的用户,我来帮你逐个解决这些问题:
一、Matplotlib与yt的兼容性问题
yt本身是基于Matplotlib构建可视化系统的,绝大多数Matplotlib命令都能和yt兼容,但有个小细节需要注意:yt的Plot对象(比如ProjectionPlot)有自己的高层封装方法,如果你直接用Matplotlib修改底层的figure/axes,最好先完成yt自身的设置(比如色标、范围),再做Matplotlib的微调,避免yt的方法覆盖你的修改。
你可以通过prj.plots['字段名'].axes拿到对应的Matplotlib Axes对象,或者prj.plots['字段名'].figure拿到Figure对象,之后就可以用任意Matplotlib命令调整了。
二、5项自定义调整的具体实现
下面是针对你需求的分步代码和解释,我会把所有修改整合到一个完整的代码示例里:
1. 使用派生变量进行投影
yt支持通过yt.add_field()创建自定义派生字段,只要你的变量能从现有字段计算出来就行。比如假设你想计算rho_mean * Tmean作为新的投影字段:
import yt # 定义派生字段 def _rho_Tmean(field, data): # 这里用数据集中的现有字段计算新变量 return data['rho_mean'] * data['Tmean'] # 注册这个字段,指定单位和采样类型(cell表示基于单元格) yt.add_field( ('gas', 'rho_Tmean'), function=_rho_Tmean, units='g*K/cm**3', # 根据实际计算结果设置正确单位 sampling_type='cell' ) # 加载数据集 ds = yt.load("/path/to/data")
2. 对齐原点到射流管道中心上边缘
首先你需要确定这个目标点的坐标(比如通过查看数据或用yt的ds.find_max()找到射流的位置),假设目标点的坐标是(target_x, target_y)(单位:微米),我们可以通过调整坐标轴的范围和刻度标签来让(0,0)对应这个点:
# 假设你已经确定了目标点坐标 target_x = 150.0 # 示例值,替换成你的实际坐标 target_y = 200.0 # 示例值,替换成你的实际坐标
3. 在x=325微米处截断计算域
直接对数据集做切片即可,这样投影计算只会用到截断后的区域,比只在绘图时截断更高效:
# 截断x轴到325微米(确保单位和数据集一致) trunc_ds = ds.r[:325.0, :, :]
4. 刻度单位从微米转米并缩放
1微米 = 1e-6米,我们可以修改坐标轴的刻度标签,把数值乘以1e-6,同时更新轴标签:
# 先创建投影图(这里用派生字段,你也可以继续用Tmean) prj = yt.ProjectionPlot( trunc_ds, 'z', 'rho_Tmean', # 换成你需要的字段,包括派生字段或原Tmean method='integrate', weight_field='rho_mean' )
5. 色条调整(分离、颜色、缩放、垂直顶部标签)
通过yt的方法和Matplotlib的色条对象来调整:
# 调整颜色映射和数据缩放范围(根据你的数据修改min/max) prj.set_cmap('rho_Tmean', 'plasma') # 替换成你喜欢的colormap,比如viridis、inferno prj.set_zlim('rho_Tmean', 1000, 15000) # 设置颜色条的数值范围 # 获取色条对象并调整位置(分离色条,增加间距) cbar = prj.plots['rho_Tmean'].cbar # 调整色条的位置:[left, bottom, width, height],增大left值让色条远离绘图区 cbar.ax.set_position([0.93, 0.15, 0.03, 0.7]) # 设置色条标签为垂直放置在顶部 cbar.set_label( 'ρ·Tmean', # 替换成你的字段名称,比如原字段就是'Tmean' rotation=90, # 垂直方向 labelpad=15, # 标签和色条的间距 y=1.05 # 标签位置在色条顶部上方 )
整合所有调整并处理原点对齐
最后把原点对齐的代码加上,保存图片:
# 获取绘图的Axes对象,调整原点对齐 ax = prj.plots['rho_Tmean'].axes # 调整坐标轴范围,让(target_x, target_y)对应绘图区的(0,0) x_current_min, x_current_max = ax.get_xlim() y_current_min, y_current_max = ax.get_ylim() ax.set_xlim(0, x_current_max - target_x) ax.set_ylim(0, y_current_max - target_y) # 修改刻度标签,将原坐标减去偏移量,同时转换为米 ax.set_xticks(ax.get_xticks()) ax.set_xticklabels([f'{(tick - target_x)*1e-6:.2e}' for tick in ax.get_xticks()]) ax.set_xlabel('X (m)') ax.set_yticks(ax.get_yticks()) ax.set_yticklabels([f'{(tick - target_y)*1e-6:.2e}' for tick in ax.get_yticks()]) ax.set_ylabel('Y (m)') # 保存图片 prj.save('Tmean_prj_custom.png')
内容的提问来源于stack exchange,提问作者anfho

