"""Plot an original ideal 3-bit converter model into the current directory. Build with ``make _media/ideal-converter-midpoint-quantization.png``. The midpoint reconstruction convention is explicit; no hardware data is used. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np def main(): bits, full_scale = 3, 1.0 levels = 2**bits step = full_scale / levels edges = np.linspace(0.0, full_scale, levels + 1) midpoints = (np.arange(levels) + .5) * step fig, axes = plt.subplots(1, 2, figsize=(9, 4), layout="constrained") fig.patch.set_facecolor("white") left, right = axes left.plot([0, full_scale], [0, full_scale], "--", color="#c16b29", label="Equal input and output") left.stairs(midpoints, edges, baseline=None, color="#176b91", lw=2, label="Midpoint reconstruction") for code, value in enumerate(midpoints): left.text(value, value + .025, f"{code:03b}", color="#176b91", ha="center", va="bottom", fontsize=9) left.set(xlim=(0, full_scale), ylim=(0, full_scale + .04), xlabel="Input V (V)", ylabel="Reconstructed value (V)", title="Eight input intervals and their codes") left.legend(loc="lower right", fontsize=8) for lo, hi, midpoint in zip(edges[:-1], edges[1:], midpoints): right.plot([lo, hi], [midpoint - lo, midpoint - hi], color="#176b91", lw=2) right.plot(lo, step / 2, "o", color="#176b91", ms=3) right.plot(hi, -step / 2, "o", markerfacecolor="white", markeredgecolor="#176b91", ms=3) for bound in (-step / 2, step / 2): right.axhline(bound, ls="--", lw=1, color="#c16b29") right.set(xlim=(0, full_scale), ylim=(-.08, .08), xlabel="Input V (V)", ylabel="Reconstruction error (V)", title=r"Error bound: $|e|\leq\Delta/2$") right.set_yticks([-.0625, 0, .0625], ["−0.0625", "0", "+0.0625"]) for ax in axes: ax.grid(alpha=.2) fig.suptitle("Ideal 3-bit model: full scale = 1 V; step Δ = 0.125 V", fontsize=12) fig.savefig(Path("ideal-converter-midpoint-quantization.png"), dpi=100, facecolor="white") plt.close(fig) if __name__ == "__main__": main()