codexmagnetic-diffraction-sublattice-selection.py
magnetic-diffraction-sublattice-selection.py
"""Exact two-site selection rules, not historical neutron data.
Python 3.14; matplotlib 3.10.7, numpy 2.3.5. Run from _media with
MPLBACKEND=Agg MPLCONFIGDIR=/tmp/codex-wiki-matplotlib.
Nuclear F=1+exp(i*pi*h); magnetic F=mA-mB*exp(i*pi*h).
Sticks represent squared structure factors, not integrated cross sections.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams.update({'font.size': 11, 'font.family': 'DejaVu Sans'})
fig, axes = plt.subplots(3, 1, figsize=(9, 7.2), sharex=True, facecolor='white')
h = np.arange(1, 7)
phase = np.exp(1j * np.pi * h)
nuclear = np.abs(1 + phase)**2
nuclear[nuclear < 1e-20] = 0
cases = [
('No long-range magnetic order', None),
('Antiferromagnetic order: $m_A=m_B=1$', (1, 1)),
(r'Ferrimagnetic order: $m_A=2,\ m_B=1$', (2, 1)),
]
for ax, (title, moments) in zip(axes, cases):
ax.set_title(title, loc='left', fontsize=12, pad=9)
ax.vlines(h, 0, nuclear, colors='#176b9c', linewidth=5,
label='Nuclear: own arbitrary units')
if moments:
a, b = moments
magnetic = np.abs(a - b * phase)**2
magnetic[magnetic < 1e-20] = 0
ax.vlines(h, 0, magnetic, colors='#bd4828', linewidth=2,
linestyles='--', label='Magnetic: own arbitrary units')
for x, y in zip(h, magnetic):
if y:
ax.text(x + .09, y + .1, f'{y:.0f}', color='#bd4828', fontsize=10)
else:
ax.text(.98, .64, 'Nuclear periodicity retained;\nmagnetic diffuse scattering omitted',
transform=ax.transAxes, ha='right', color='#4e5964')
ax.set(ylim=(0, 10.5), yticks=[0, 4, 9], xlim=(.45, 6.5))
ax.grid(axis='y', color='#e9edf0', linewidth=.7)
ax.set_axisbelow(True)
ax.spines[['top', 'right']].set_visible(False)
axes[1].legend(loc='upper right', fontsize=9, frameon=False)
axes[-1].set(xticks=h, xlabel=r'$h=qa/\pi$ (positive nonzero reciprocal positions)')
fig.text(.015, .5, 'Squared structure factor (separate channel scales)',
rotation=90, va='center', fontsize=11)
fig.suptitle('A doubled magnetic period adds odd-index peaks',
fontsize=16, weight='bold', y=.985)
fig.text(.5, .018, 'Exact toy selection rules • no measured points • not the MnO reflection pattern',
ha='center', fontsize=11, color='#4e5964')
fig.subplots_adjust(left=.10, right=.96, top=.90, bottom=.105, hspace=.52)
fig.savefig(Path.cwd() / (Path(__file__).stem + '.png'), dpi=120,
facecolor='white', transparent=False)