Files
extrapolation/model_vectors.py
John Beale 15ea8f8cd5 script dump
2026-02-17 08:52:57 +01:00

104 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}°"
)