codex/velocity-time-integral-same-peak.py

velocity-time-integral-same-peak.py
"""Same peak speed and duration, different velocity-time integrals.
Python 3.14, NumPy 2.3.5, Matplotlib 3.10.7. Run in output directory.
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

t = np.linspace(0, .4, 801)
triangle = np.interp(t, [0, .2, .4], [0, 100, 0])
trapezoid = np.interp(t, [0, .1, .3, .4], [0, 100, 100, 0])
areas = [np.trapezoid(v, t) for v in [triangle, trapezoid]]
assert np.allclose(areas, [20, 30])
fig, axs = plt.subplots(1, 2, figsize=(7.6, 3.6), dpi=100, facecolor='white', sharey=True)
for ax, v, area, color, title in zip(axs, [triangle, trapezoid], areas,
        ['#286b95', '#ad5d18'], ['Triangular example', 'Trapezoidal example']):
    ax.plot(t, v, color=color, lw=2)
    ax.fill_between(t, v, color=color, alpha=.18)
    ax.text(.2, 37, f'VTI = {area:.0f} cm', ha='center', color=color, fontsize=12)
    ax.set(xlim=(0, .4), ylim=(0, 120), xlabel='Time (s)', title=title)
    ax.set_xticks([0, .1, .2, .3, .4])
    ax.grid(alpha=.16)
    ax.spines[['top', 'right']].set_visible(False)
axs[0].set_ylabel('Representative flow velocity (cm/s)')
fig.suptitle('Same peak and duration do not determine transported volume', fontsize=12)
fig.text(.5, .025, 'Constructed waveforms • equal fixed flow area assumed • not patient traces', ha='center', fontsize=9)
fig.tight_layout(rect=(0, .075, 1, .92))
fig.savefig('velocity-time-integral-same-peak.png', facecolor='white', dpi=100)
plt.close(fig)