script dump

This commit is contained in:
John Beale
2026-02-17 08:52:57 +01:00
parent a666b31f25
commit 15ea8f8cd5
11 changed files with 2013 additions and 0 deletions

104
model_vectors.py Normal file
View File

@@ -0,0 +1,104 @@
import gemmi
import numpy as np
import matplotlib.pyplot as plt
# -----------------------------
# User inputs
# -----------------------------
apo_pdb = "../data/hewl_apo.pdb"
occ100_pdb = "../data/hewl_1.0-I.pdb"
occb_pdb = "../data/hewl_0.5-I.pdb"
b = 0.5
a = 1.0 - b
dmin = 2.0 # resolution cutoff (Å)
# -----------------------------
# Compute structure factors
# -----------------------------
def compute_sf(pdb_file, dmin):
# Read structure
st = gemmi.read_structure(pdb_file)
st.setup_entities()
st.assign_label_seq_id()
st.remove_alternative_conformations()
model = st[0]
cell = st.cell
# Space group
sg = st.find_spacegroup()
if sg is None:
if st.spacegroup_hm:
sg = gemmi.SpaceGroup(st.spacegroup_hm)
else:
raise RuntimeError("No space group found")
# Generate HKLs
hkl = gemmi.make_miller_array(
cell=cell,
spacegroup=sg,
dmin=dmin,
unique=True
)
# Structure factor calculator
calc = gemmi.StructureFactorCalculatorX(cell)
# Compute SFs ONE reflection at a time (this is required)
F = np.array([
calc.calculate_sf_from_model(model, [int(h), int(k), int(l)])
for h, k, l in hkl
], dtype=np.complex128)
return hkl, F
hkl, Fa = compute_sf(apo_pdb, dmin)
_, F100 = compute_sf(occ100_pdb, dmin)
_, Fb_model = compute_sf(occb_pdb, dmin)
# -----------------------------
# Sanity: same HKLs?
# -----------------------------
assert len(Fa) == len(F100) == len(Fb_model)
# -----------------------------
# Test forward relation:
# Fab = a Fa + b F100
# -----------------------------
Fab = a * Fa + b * F100
print(Fab)
# Compare to model b-occupancy SFs
delta_forward = Fab - Fb_model
print("FORWARD TEST: Fab = aFa + bF100")
print("Mean |ΔF|:", np.mean(np.abs(delta_forward)))
print("Mean phase Δ (deg):",
np.mean(np.abs(np.angle(Fab / Fb_model, deg=True))))
# -----------------------------
# Test inverse relation:
# F100 = (Fab Fa) / b
# -----------------------------
F100_recon = (Fb_model - Fa) / b + Fa
delta_inverse = F100_recon - F100
print("\nINVERSE TEST: F100 = (Fab Fa)/b + Fa")
print("Mean |ΔF|:", np.mean(np.abs(delta_inverse)))
print("Mean phase Δ (deg):",
np.mean(np.abs(np.angle(F100_recon / F100, deg=True))))
# -----------------------------
# Optional: inspect worst reflections
# -----------------------------
idx = np.argsort(np.abs(delta_inverse))[-5:]
print("\nWorst reflections (inverse):")
for i in idx:
print(
f"|F100|={abs(F100[i]):.2f} "
f"|ΔF|={abs(delta_inverse[i]):.2f} "
f"Δφ={np.angle(F100_recon[i]/F100[i],deg=True):.1f}°"
)