"""Create shareable plots from evaluate_mql8_correctness.py evidence (Matplotlib).""" import argparse import json from pathlib import Path import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib import font_manager import numpy as np def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('directory', type=Path) args = parser.parse_args() out = args.directory font = Path('C:/Windows/Fonts/msyh.ttc') if font.exists(): font_manager.fontManager.addfont(str(font)) plt.rcParams['font.family'] = font_manager.FontProperties(fname=str(font)).get_name() plt.rcParams.update({'font.size': 9, 'axes.spines.top': False, 'axes.spines.right': False, 'axes.unicode_minus': False, 'svg.fonttype': 'none', 'figure.facecolor': 'white'}) summary = json.loads((out / 'summary.json').read_bytes()) full = np.load(out / 'full/curves.npz') startup = np.load(out / 'startup/curves.npz') fig, axes = plt.subplots(4, 2, figsize=(13, 13), constrained_layout=True) selected = [ (startup, summary['startup']['groups']['pressure']['worstAbsolute']['key'], '绝对压力', 'kPa', 1e-3, .002, 1000), (startup, summary['startup']['groups']['temperature']['worstAbsolute']['key'], '温度', 'K', 1, .002, 1000), (full, 'amesim_mecmas21_1.x', '1 号质量块位移', 'mm', 1000, 50, 1), (full, summary['full']['groups']['force']['worstAbsolute']['key'], '接触力(最差曲线)', 'kN', .001, 50, 1), ] for (data, key, title, unit, scale, end, ts), (left, right) in zip(selected, axes): mask = data['time'] <= end t = data['time'][mask] * ts native, ame = data['platform|' + key][mask] * scale, data['amesim|' + key][mask] * scale left.plot(t, native, color='#1368a8', linewidth=1.6, label='当前平台') left.plot(t, ame, color='#e07832', linestyle='--', linewidth=1.2, label='本次 Amesim') left.set_title(title + ' · ' + key, fontsize=9) left.legend(fontsize=8) right.plot(t, native - ame, color='#925034', linewidth=1.1) right.axhline(0, color='#888888', linewidth=.6) right.set_title('平台 − Amesim;切换点保留', fontsize=9) for ax in (left, right): ax.set_xlabel('时间 / ' + ('ms' if ts == 1000 else 's')) ax.set_ylabel(unit) ax.grid(alpha=.18) fig.suptitle('八路模型正确性初评 · 当前代码与本次 Amesim 执行\n启动段采样 0.1 ms;循环全程采样 10 ms;曲线重合不等于事件输出一致', fontsize=13) fig.savefig(out / 'comparison.png', dpi=160) fig.savefig(out / 'comparison.svg') plt.close(fig) fig, axes = plt.subplots(3, 2, figsize=(13, 10), constrained_layout=True) # Show each of the eight physical contacts; full curve metrics still include # the large event difference. The second column localizes away from events. for i in range(1, 9): key = f'amesim_lstp00a_{i}.force' t = full['time'] error = full['platform|' + key] - full['amesim|' + key] axes[0, 0].plot(t, error / 1000, linewidth=.8, label=str(i)) quiet = (t >= .1) for event in summary['full']['signalEvents']: quiet &= np.abs(t - event) > .0200001 visible = np.where(quiet, error, np.nan) axes[0, 1].plot(t, visible, linewidth=.8, label=str(i)) axes[0, 0].set(title='8 路接触力差:全部共同采样点', ylabel='差值 / kN') axes[0, 1].set(title='诊断视图:t≥0.1 s,避开切换前后 0.02 s', ylabel='差值 / N') axes[0, 0].legend(title='支路', ncol=4, fontsize=7) for row, (quantity, label) in enumerate([('enthalpy_flow', '节点焓流 / W'), ('mass_flow', '节点质量流 / kg/s')], 1): key = summary['default']['groups'][quantity]['worstRelative']['key'] for column in range(2): ax = axes[row, column] t = full['time'] mask = (t >= .1) & (t <= .5) n, a = full['platform|' + key], full['amesim|' + key] if column == 0: ax.plot(t[mask], n[mask], color='#1368a8', label='当前平台') ax.plot(t[mask], a[mask], '--', color='#e07832', label='本次 Amesim') ax.legend(fontsize=8) ax.set_ylabel(label) ax.set_title(key, fontsize=9) else: ax.plot(t[mask], (n-a)[mask], color='#925034') ax.set_ylabel('绝对差,沿用左侧单位') ax.set_title('小量差异单列,避免峰值归一化掩盖') for ax in axes.flat: ax.grid(alpha=.18) ax.set_xlabel('时间 / s') fig.suptitle('问题定位 · 切换点误差与小流量差异分开评价\n右上筛选只用于诊断;全部采样点仍进入主报告统计', fontsize=13) fig.savefig(out / 'diagnostics.png', dpi=160) fig.savefig(out / 'diagnostics.svg') plt.close(fig) data = np.load(out / 'volume-startup/curves.npz') fig, axes = plt.subplots(1, 2, figsize=(12, 4), constrained_layout=True) for ax, key, label, scale in [(axes[0], 'amesim_pnch012_15.vol', '有效气室容积 / L', 1000), (axes[1], 'amesim_pnch012_15.volume_work', '气室体积功率 / TW', 1e-12)]: mask = data['time'] <= 8e-8 for prefix, name, color, style in [('platform', '当前平台', '#1368a8', '-'), ('amesim', '本次 Amesim', '#e07832', '--')]: ax.plot(data['time'][mask]*1e9, data[prefix+'|'+key][mask]*scale, style, color=color, label=name) ax.set(xlabel='时间 / ns', ylabel=label) ax.grid(alpha=.18) ax.legend() fig.suptitle('最初 80 ns:容积下限与体积功率 · 采样间隔 2 ns', fontsize=13) fig.savefig(out / 'volume-startup.png', dpi=160) fig.savefig(out / 'volume-startup.svg') plt.close(fig) if __name__ == '__main__': main()