codexbarnett-rotation-magnetometry-apparatus.py
barnett-rotation-magnetometry-apparatus.py
"""Original functional diagram; emits its basename PNG in the working directory.
Experimental functions: Ono et al., Phys. Rev. B 92, 174424 (2015),
Section II, Figures 1 and 2. Layout is original, not a scale reconstruction.
Tested with Python 3.14, matplotlib 3.10.7; no additional dependencies.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, FancyBboxPatch, Rectangle
def main():
plt.rcParams.update({"font.size": 11, "font.family": "DejaVu Sans"})
fig, ax = plt.subplots(figsize=(10, 6.6), dpi=120, facecolor="white")
fig.subplots_adjust(left=0.02, right=0.98, top=0.92, bottom=0.035)
ax.set(xlim=(0, 10), ylim=(0, 7.3), aspect="equal")
ax.axis("off")
blue, red, green = "#245b91", "#b03838", "#24704e"
def arrow(a, b, color=blue, **kwargs):
ax.add_patch(FancyArrowPatch(a, b, arrowstyle="-|>",
mutation_scale=15, linewidth=1.8,
color=color, **kwargs))
fig.suptitle("Barnett rotation magnetometry: drive, shield, detect", fontsize=16)
ax.add_patch(FancyBboxPatch((0.3, 2.0), 9.3, 4.2,
boxstyle="round,pad=0.03", facecolor="white",
edgecolor="#727b85", linewidth=2, linestyle="--"))
ax.text(0.55, 5.91, "Magnetic shielding", color="#525b65")
ax.add_patch(FancyBboxPatch((3.05, 2.7), 1.25, 2.9,
boxstyle="round,pad=0.05", facecolor="#f2f5f8",
edgecolor=blue, linewidth=1.5))
ax.add_patch(Rectangle((3.37, 2.95), 0.6, 2.2, facecolor="#a8c5df",
edgecolor=blue, linewidth=1.5))
ax.plot([3.67, 3.67], [2.4, 5.75], color="#909090", linestyle=":")
ax.text(0.55, 4.65, "Gd cylinder\n6 mm diameter\n20 mm long", va="center")
ax.plot([2.0, 3.36], [4.65, 4.45], color="#535353", linewidth=1)
ax.text(0.55, 3.25, "Nonmagnetic rotor\nZirconia capsule\nPolyimide impeller", va="center")
ax.plot([2.6, 3.02], [3.25, 3.25], color="#535353", linewidth=1)
# A straight axial arrow defines positive angular velocity, not gas flow.
arrow((4.7, 4.55), (4.7, 5.48), blue)
ax.text(4.9, 5.1, r"$+z,\ +\Omega$", color=blue, va="center")
arrow((3.67, 4.85), (3.67, 3.35), red)
ax.text(4.4, 3.5, r"$M_z<0$" + "\n" + r"if $\gamma<0$", color=red)
ax.plot([3.67, 7.15], [4.05, 4.05], color="#666666", linestyle=":")
ax.annotate("", xy=(3.67, 4.05), xytext=(7.15, 4.05),
arrowprops={"arrowstyle": "<->", "color": "#666666"})
ax.text(5.65, 4.13, "15 mm from axis", ha="center", va="bottom", fontsize=10,
bbox={"facecolor": "white", "edgecolor": "none", "pad": 1.5})
ax.plot(7.15, 4.05, "o", color=green, markersize=5)
ax.plot([7.15, 7.15], [4.05, 4.45], color=green)
ax.add_patch(FancyBboxPatch((7.1, 4.45), 2.0, 0.8,
boxstyle="round,pad=0.06", facecolor="#eff8f1",
edgecolor=green, linewidth=1.5))
ax.text(8.1, 4.85, "Fluxgate readout", ha="center", color=green)
arrow((7.15, 3.15), (7.15, 3.95), green)
ax.text(7.5, 3.25, r"$B_{z,\mathrm{stray}}>0$", color=green, fontsize=11)
ax.text(5.45, 2.38, "At the equator, stray-field sign opposes M", fontsize=10)
arrow((3.67, 6.92), (3.67, 5.63), blue)
ax.text(4.05, 6.78, "Air drive: reverse flow to reverse rotation", va="center")
ax.text(0.45, 6.68, "Functional schematic\nGeometry simplified", fontsize=10, color="#555555")
boxes = [(0.35, "Reverse rotation", r"Record $+\Omega,\ 0,\ -\Omega$"),
(3.6, "Check background", "Repeat with empty capsule"),
(6.85, "Infer magnetization", "Convert stray field using geometry")]
for x, title, text in boxes:
ax.add_patch(FancyBboxPatch((x, 0.65), 2.8, 0.95,
boxstyle="round,pad=0.08", facecolor="white",
edgecolor="#7d8792"))
ax.text(x+1.4, 1.29, title, ha="center", weight="bold", fontsize=10)
ax.text(x+1.4, 0.94, text, ha="center", fontsize=8.8)
ax.text(5, 0.15, "Arrows define signs; no measured trace is drawn.",
ha="center", fontsize=10, color="#555555")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()