In [1]:
import escape as esc
import numpy as np

esc.require("0.9.8")
Loading material database from C:\dev\escape-core\python\src\escape\scattering\..\data\mdb\materials.db
In [2]:
# --- Shared grids and physical inputs ---
q_min = 0.0
q_max = 1.0
n_1d = 256
n_2d = 256

SAXS. Form-factors. Fuzzy sphere (SasView-aligned)¶

Sphere with a Gaussian-smeared interface of width sigma. This follows the SasView fuzzy_sphere formalism: a standard sphere amplitude multiplied by a Debye-Waller-like Gaussian damping term.

Model reference: fuzzy_sphere — SasView 6.1.3

Parameters¶

Parameter Variable Value
Scale I0 1
Radius (Å) R 60
Fuzziness sigma (Å) sigma 5
Contrast (10⁻⁶ Å⁻²) rho 1
Background (cm⁻¹) bkgr 0

1D and 2D scattering¶

$$I(q)=\frac{\mathrm{scale}}{V}\left[\Delta\rho\,V\,\frac{3(\sin(qR)-qR\cos(qR))}{(qR)^3}\,e^{-\frac{(q\sigma)^2}{2}}\right]^2+\mathrm{background},$$

$$V=\frac{4\pi}{3}R^3,\qquad q=\sqrt{q_x^2+q_y^2}\;(\text{for 2D}).$$

Since the model is isotropic, the same formula applies to 1D and 2D with different definitions of $q$.

References¶

  • SasView fuzzy_sphere
  • L. A. Feigin, D. I. Svergun, Structure Analysis by Small-Angle X-Ray and Neutron Scattering (1987).
In [3]:
q = esc.var("Q")

I0 = esc.par("Scale", 1, scale=1e8, fixed=True)
R = esc.par("Radius", 60, units=esc.angstr)
sigma = esc.par("Fuzziness", 5, units=esc.angstr)
rho = esc.par("Contrast", 1, scale=1e-6, units=f"{esc.angstr}⁻²")
bkgr = esc.par("Background", 0.0, userlim=[0, 0.03])

V = 4.0 / 3.0 * np.pi * esc.pow(R, 3)
QR = q * R

kern = esc.conditional(
    esc.abs(QR) < 1e-10,
    1.0 / 3.0,
    (esc.sin(QR) - QR * esc.cos(QR)) / esc.pow(QR, 3),
)
F_sphere = 3.0 * V * rho * kern
F = F_sphere * esc.exp(-esc.pow(q * sigma, 2) / 2.0)
I1d = I0 / V * esc.pow(F, 2) + bkgr

q1 = np.linspace(q_min, q_max, n_1d)
w1 = I1d.show(coordinates=q1).config(
    title="Fuzzy sphere — 1D",
    xlog=True,
    ylog=True,
    xlabel=f"Q [{esc.angstr}⁻¹]",
    ylabel="I(q) [cm⁻¹]",
)
In [4]:
qx = esc.var("qx")
qy = esc.var("qy")
q2d = esc.sqrt(esc.pow(qx, 2) + esc.pow(qy, 2))
QR2 = q2d * R

kern2 = esc.conditional(
    esc.abs(QR2) < 1e-10,
    1.0 / 3.0,
    (esc.sin(QR2) - QR2 * esc.cos(QR2)) / esc.pow(QR2, 3),
)
F2 = 3.0 * V * rho * kern2 * esc.exp(-esc.pow(q2d * sigma, 2) / 2.0)
I2d = I0 / V * esc.pow(F2, 2) + bkgr

xs = np.linspace(-q_max, q_max, n_2d)
ys = np.linspace(-q_max, q_max, n_2d)
xv, yv = np.meshgrid(xs, ys)
coords_2d = np.column_stack([xv.flatten(), yv.flatten()]).flatten()

w2 = I2d.show(coordinates=coords_2d).config(
    title="Fuzzy sphere — isotropic 2D (qx, qy)",
    xlabel=f"qx [{esc.angstr}⁻¹]",
    ylabel=f"qy [{esc.angstr}⁻¹]",
    cblog=True,
)

sphere_geom = esc.gsphere(radius=R, numslices=64, numstacks=32, color="74A9FF", name="Fuzzy sphere")
w3 = sphere_geom.show()
esc.show(w1, w2, w3)
Out[4]:
In [ ]: