codexheterodyne-gain-cancellation.py
heterodyne-gain-cancellation.py
"""Deterministic readout-scale effects on a normalized heterodyne amplitude."""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
beat, arm1, arm2 = 6.0, 2.0, 8.0
scale = np.linspace(.8, 1.2, 201)
nominal = beat/(2*np.sqrt(arm1*arm2))
shared = scale*beat/(2*np.sqrt(scale*arm1*scale*arm2))
separate = scale*beat/(2*np.sqrt(arm1*arm2))
mismatch = scale*beat/(2*np.sqrt(scale**.95*arm1*scale**.95*arm2))
assert np.allclose(shared, nominal)
assert np.allclose(mismatch, nominal*scale**.05)
v_d = (.05*.03)**2 + .01**2 + 2*(.5*.004)**2
assert np.isclose(np.sqrt(v_d), .0105)
assert np.isclose(nominal*np.exp(v_d/2), .750041344889558)
fig, ax = plt.subplots(figsize=(7.4, 3.7), dpi=100, layout="constrained")
fig.set_facecolor("white")
ax.plot(scale, separate, color="#b94b16", lw=2, label="Scale only the beat reading")
ax.plot(scale, mismatch, "--", color="#4c8b23", lw=2,
label="Beat sensitivity 1; arm sensitivities 0.95")
ax.plot(scale, shared, color="#1558a0", lw=2,
label="Exactly shared scale: complete cancellation")
ax.scatter([1], [nominal], color="#1558a0", zorder=4)
ax.set(xlabel="Positive readout scale g", ylabel="Normalized beat amplitude",
title="A ratio cancels shared scaling, not every calibration error",
xlim=(.8, 1.2), ylim=(.57, .93))
ax.legend(loc="upper left", fontsize=9)
ax.grid(alpha=.2)
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()