Plotly滑块仅更新单图问题:柴油循环TS图不随压缩比变化
柴油循环可视化:滑块仅更新P-V图的解决方案
问题
制作柴油循环的P-V(压力-体积)和T-S(温度-熵)双图,期望调节压缩比(rk)的滑块仅更新左侧P-V图,右侧T-S图保持静态。但当前移动滑块时,T-S图会变成P-V图的副本。
问题根源
原代码中滑块的update方法未指定更新范围,args=[{"y": [P], "x": [V]}]会全局替换所有子图的x/y数据,导致第二个子图(T-S图)的轨迹被P-V数据覆盖。
修复方案
- 使用
restyle方法替代update,仅修改指定轨迹的属性 - 通过
selector参数指定只更新P-V图的轨迹(按名称或索引定位) - 确保T-S图的初始数据仅计算一次,后续不再修改
完整修复代码
import numpy as np import math import plotly.io as pio from plotly.subplots import make_subplots pio.renderers.default='browser' # Constants and assumptions bore = .078 stroke = .062 vd = math.pi * (bore/2)**(2) * stroke rk = 15 #typical compression ratio for small diesel engines V2 = vd / (rk - 1) V1 = rk * V2 T1 = 300 #kelvin assumed atmospheric P1 = 101.325 #kpa assumed athmospheric k = 1.4 #assumed ideal gas rc = 2.5 #for high efficiency operation S1 = 10 #change. for testing cp = 1.0038 cv = 0.717 # 初始计算T-S图静态数据 P2 = P1 * (rk)**k T2 = T1 * (rk)**(k-1) P3 = P2 T3 = rc * T2 V3 = V2 * rc V4 = V1 P4 = P3 * (V3 / V4)**k T4 = T3 * (P4 / P3)**((k-1)/k) m = (P1*V1)/(0.287*T1) S3 = S1 + m * cp * np.log(T3/T2) # 初始化P-V和T-S的轨迹数据 V = [V1] P = [P1] T = [T1] S = [S1] points12 = 100 points34 = 100 points23 = 100 points41 = 100 # 计算初始P-V图的所有点 for i in range(1, points12 + 1): Vi = V1 * (V2 / V1) ** (i / points12) Pi = P1 * (V1 / Vi) ** k V.append(Vi) P.append(Pi) # 计算初始T-S图的所有点(静态,后续不再修改) for i in range(0, points23 + 1): Ti = T2 * (T3 / T2) ** (i / points23) Si = S1 + m * cp * np.log(Ti / T2) T.append(Ti) S.append(Si) for i in range(0, points34 + 1): Vi = V3 * (V4 / V3) ** (i / points34) Pi = P3 * (V3 / Vi) ** k V.append(Vi) P.append(Pi) for i in range(0, points41 + 1): Ti = T4 * (T1 / T4) ** (i / points41) Si = S3 + m * cv * np.log(Ti / T4) T.append(Ti) S.append(Si) V.extend([V1, V1]) P.extend([P1, P1]) T.extend([T1, T1]) S.extend([S1, S1]) fig = make_subplots(cols=2, subplot_titles=("P-V Diagram", "T-S Diagram")) # 生成滑块步骤 slider_steps = [] for rk_val in range(10, 31): V2_val = vd / (rk_val - 1) V1_val = rk_val * V2_val P2_val = P1 * (rk_val)**k P3_val = P2_val V3_val = V2_val * rc V4_val = V1_val P4_val = P3_val * (V3_val / V4_val)**k # 重新计算P-V图的所有点 V_new = [V1_val] P_new = [P1] for i in range(1, points12 + 1): Vi = V1_val * (V2_val / V1_val) ** (i / points12) Pi = P1 * (V1_val / Vi) ** k V_new.append(Vi) P_new.append(Pi) for i in range(0, points34 + 1): Vi = V3_val * (V4_val / V3_val) ** (i / points34) Pi = P3_val * (V3_val / Vi) ** k V_new.append(Vi) P_new.append(Pi) V_new.extend([V1_val, V1_val]) P_new.extend([P1, P1]) # 计算效率等信息用于滑块标签 effi = (1-(1/(rk_val**(k-1)))*((((rc)**k)-1)/(k*(rc-1))))*100 clr= V2_val*1000000 # 定义滑块步骤:仅更新P-V图(通过轨迹名称选择) step = dict( method="restyle", label=f"rk = {rk_val} | 效率: {effi:.1f}% | 燃烧室容积: {clr:.1f}cm³ | 截断比: {rc}", args=[{"x": [V_new], "y": [P_new]}], selector=dict(name="Diesel Cycle PV") # 指定要更新的轨迹名称 ) slider_steps.append(step) sliders = [ dict( active=5, # 对应rk=15的初始位置(10-30中第6个元素,索引5) currentvalue={"prefix": "压缩比 (rk): "}, pad={"t": 50}, steps=slider_steps, ) ] # 添加两个子图的轨迹 fig.add_scatter(x=V, y=P, mode='lines+markers', name='Diesel Cycle PV', row=1, col=1) fig.add_scatter(x=S, y=T, mode='lines+markers', name='Diesel Cycle TS', row=1, col=2) # 配置布局和轴标签 fig.update_layout( sliders=sliders, title='柴油循环可视化', xaxis=dict(title='Volume (m³)'), yaxis=dict(title='Pressure (kPa)'), xaxis2=dict(title='Entropy'), yaxis2=dict(title='Temperature (K)') ) fig.show()
关键修改说明
- 轨迹选择:通过
selector=dict(name="Diesel Cycle PV")精准指定只更新P-V图的轨迹,避免影响T-S图 - 方法替换:用
restyle替代update,restyle专门用于修改现有轨迹的属性(如x/y数据),不会全局替换所有内容 - 静态数据分离:T-S图的初始数据仅计算一次,滑块循环中不再处理T-S相关计算,确保其始终保持初始状态
- 滑块初始位置修正:
active=5对应rk=15(因为循环从10开始,15是第6个值,索引为5),与初始计算的rk一致
内容的提问来源于stack exchange,提问作者wisn
相关产品推荐
相关产品推荐

