6. formfactor (ff)

Particle form factors for scattering.

If possible the scattering intensity (Iq) of a single particle with real scattering length densities is calculated. It is the normalized particle form factor (Fq) if the scattering length is not unique defined as e.g. for beaucage model.

The scattering per particle is I(q)= I_0 F(q) with particle form factor F(q)=<F_a(q)F^*_a(q)>=<|F_a(q)|^2> and particle scattering amplitude F_a(q). <> indicates the ensemble average.

F_a(q)= \int_V b(r) e^{iqr} \mathrm{d}r / \int_V b(r) \mathrm{d}r = \sum_N b_i e^{iqr} / \sum_N b_i

The forward scattering per particle is I_0=V_p^2(SLD-solventSLD)^2 with particle volume V_p.

In this module units for I(q) and I_0 are nm^2=10^{-14} cm^2 per particle.

The scattering of particles with concentration c in mol/liter in units of \frac{1}{cm} is I_{[1/cm]}(q)=N_A \frac{c}{1000} 10^{-14} I_{[nm^2]}(q).

Some scattering length densities as guide to choose realistic values for SLD and solventSLD:
  • neutron scattering unit nm^-2:
    • protonated polyethylene glycol = 0.640e-6 A^-2 = 0.640e-4 nm^-2
    • SiO2 = 4.186e-6 A^-2 = 4.186e-4 nm^-2
    • D2O = 6.335e-6 A^-2 = 6.335e-4 nm^-2
    • H2O =-0.560e-6 A^-2 =-0.560e-4 nm^-2
    • gold = 4.400e-6 A^-2 = 4.400e-4 nm^-2
  • Xray scattering unit nm^-2:
    • polyethylene glycol = 1.09e-3 nm^-2 = 387 e/nm**3
    • SiO2 = 2.20e-3 nm^-2 = 781 e/nm**3
    • D2O = 0.94e-3 nm^-2 = 332 e/nm**3
    • H2O = 0.94e-3 nm^-2 = 333 e/nm**3
    • protein = 1.20e-3 nm^-2 = 433 e/nm**3
    • gold = 12.9e-3 nm^-2 =4589 e/nm**3

Return values are dataArrays were useful. To get only Y values use .Y

6.1. Form Factors

beaucage(q[, Rg, G, d]) Beaucage introduced a model based on the polymer fractal model.
genGuinier(q[, Rg, A, alpha]) Generalized Guinier approximation for low wavevector q scattering q*Rg< 1-1.3
guinier(q[, Rg, A]) Classical Guinier
gaussianChain(q, Rg) Formfactor of a gaussian polymer chain (Debye model)
sphere(q, radius[, contrast]) Scattering of a single homogeneous sphere.
sphereCoreShell(q, Rc, Rs, bc, bs[, solventSLD]) Scattering of a spherical core shell particle.
ellipsoid(q, Ra, Rb[, SLD, solventSLD, …]) Form factor for a simple ellipsoid (ellipsoid of revolution).
multiShellSphere(q, shellthickness, shellSLD) Scattering of spherical multi shell particle including linear contrast variation in subshells.
multiShellEllipsoid(q, poleshells, …[, …]) Scattering of multi shell ellipsoidal particle with variing shell thickness at pole and equator.
multiShellCylinder(q, L, shellthickness, …) Multi shell cylinder with caps in solvent averaged over axis orientations.
multilamellarVesicles(Q, R, N, phi[, …]) Scattering intensity of a multilamellar vesicle with random displacement of the inner vesicles [R137].
cuboid(q, a[, b, c, SLD, solventSLD, NN]) Formfactor of cuboid.
sphereFuzzySurface(q, R, sigmasurf, contrast) Scattering of a sphere with a fuzzy interface.
sphereGaussianCorona(q, R, Rg, Ncoil, coilequR) Scattering of a sphere surrounded by gaussian coils as model for grafted polymers on particle e.g.
pearlNecklace(Q, Rc, l, N[, A1, A2, A3, ms, mr]) Formfactor of a pearlnecklace (freely jointed chain of pearls connected by rods)
wormlikeChain(q, N, a[, R, SLD, solventSLD, …]) Scattering of a wormlike chain, which correctly reproduces the rigid-rod and random-coil limits.
teubnerStrey(q, xi, d[, eta2]) Phenomenological model for the scattering intensity of a two-component system using the Teubner-Strey model [R147].
ellipsoidFilledCylinder([q, R, L, Ra, Rb, …]) Scattering of a cylinder filled with ellipsoidal particles.
superball(q, R, p[, SLD, solventSLD, nGrid, …]) A superball is a general mathematical shape that can be used to describe rounded cubes, sphere and octahedra.

6.2. Addons

cloudScattering(q, cloud[, relError, V, …]) Scattering of a cloud of scatterers with variable scattering length.
orientedCloudScattering(qxz, cloud[, rms, …]) 2D scattering of an oriented cloud of scatterers with equal or variable scattering length. Using multiprocessing.
scatteringFromSizeDistribution(q, …[, …]) Scattering of a size distribution of objects with form factor fffunction

Particle form factors for scattering.

If possible the scattering intensity (Iq) of a single particle with real scattering length densities is calculated. It is the normalized particle form factor (Fq) if the scattering length is not unique defined as e.g. for beaucage model.

The scattering per particle is I(q)= I_0 F(q) with particle form factor F(q)=<F_a(q)F^*_a(q)>=<|F_a(q)|^2> and particle scattering amplitude F_a(q). <> indicates the ensemble average.

F_a(q)= \int_V b(r) e^{iqr} \mathrm{d}r / \int_V b(r) \mathrm{d}r = \sum_N b_i e^{iqr} / \sum_N b_i

The forward scattering per particle is I_0=V_p^2(SLD-solventSLD)^2 with particle volume V_p.

In this module units for I(q) and I_0 are nm^2=10^{-14} cm^2 per particle.

The scattering of particles with concentration c in mol/liter in units of \frac{1}{cm} is I_{[1/cm]}(q)=N_A \frac{c}{1000} 10^{-14} I_{[nm^2]}(q).

Some scattering length densities as guide to choose realistic values for SLD and solventSLD:
  • neutron scattering unit nm^-2:
    • protonated polyethylene glycol = 0.640e-6 A^-2 = 0.640e-4 nm^-2
    • SiO2 = 4.186e-6 A^-2 = 4.186e-4 nm^-2
    • D2O = 6.335e-6 A^-2 = 6.335e-4 nm^-2
    • H2O =-0.560e-6 A^-2 =-0.560e-4 nm^-2
    • gold = 4.400e-6 A^-2 = 4.400e-4 nm^-2
  • Xray scattering unit nm^-2:
    • polyethylene glycol = 1.09e-3 nm^-2 = 387 e/nm**3
    • SiO2 = 2.20e-3 nm^-2 = 781 e/nm**3
    • D2O = 0.94e-3 nm^-2 = 332 e/nm**3
    • H2O = 0.94e-3 nm^-2 = 333 e/nm**3
    • protein = 1.20e-3 nm^-2 = 433 e/nm**3
    • gold = 12.9e-3 nm^-2 =4589 e/nm**3

Return values are dataArrays were useful. To get only Y values use .Y

jscatter.formfactor.beaucage(q, Rg=1, G=1, d=3)[source]

Beaucage introduced a model based on the polymer fractal model.

Beaucage used the numerical integration form (Benoit, 1957) although the analytical integral form was available [R154]. The Beaucage (1995, 1996) model is characterized by three fitting parameters:

Parameters:

q : array

wavevector

Rg : float

radius of gyration in 1/q units

G : float

Guinier scaling factor, transition between Guinier and Porod

d : float

Porod exponent for large wavevectors

Returns:

dataArray [q,Fq]

Notes

Polymer fractals:

d = 5/3 fully swollen chains,
d = 2 ideal Gaussian chains and
d = 3 collapsed chains. (volume scattering)
d = 4 surface scattering at a sharp interface/surface
d = 6-dim rough surface area with a dimensionality dim between 2-3 (rough surface)
d = 3 Volume scattering
d < r mass fractals (eg gaussian chain)

The Beaucage model is used to analyze small-angle scattering (SAS) data from fractal and particulate systems. It models the Guinier and Porod regions with a smooth transition between them and yields a radius of gyration and a Porod exponent. This model is an approximate form of an earlier polymer fractal model that has been generalized to cover a wider scope. The practice of allowing both the Guinier and the Porod scale factors to vary independently during nonlinear least-squares fits introduces undesired artefacts in the fitting of SAS data to this model.

[R154]Analysis of the Beaucage model Boualem Hammouda J. Appl. Cryst. (2010). 43, 1474–1478 http://dx.doi.org/10.1107/S0021889810033856
jscatter.formfactor.cloudScattering(q, cloud, relError=50, V=0, formfactor=None, rms=0, ffpolydispersity=0, ncpu=0)[source]

Scattering of a cloud of scatterers with variable scattering length. Using multiprocessing.

Cloud can represent any object described by a cloud of scatterers with scattering amplitudes as constant, sphere scattering amplitude, Gaussian scattering amplitude or explicitly given one. The result is normalized by sum(scattering length )**2 to equal one for q=0 (except for polydispersity). Rememeber that the atomic bond length are on the order 0.1-0.2 nm.

Parameters:

q : array, ndim= Nx1

wavevectors in 1/nm

cloud : array Nx3 or Nx4

  • Center of mass positions (in nm) of the N scatterers in the cloud.
  • If given cloud[3] is the scattering length b at positions cloud[:3], otherwise b=1.

relError : float

  • relError>0 Explicit calculation of spherical average with Fibonacci lattice of 2*relError+1 points.
  • 0<relError<1 Monte Carlo integration until relative error is smaller than relError.
    (Monte carlo integratio with pseudo random numbers, see sphereAverage)
  • relError=0 The Debye equation is used.
    (no asymmetry factor beta, no multiprocessing, no rms, no ffpolydispersity).

rms : float, default=0

Root mean square displacement =<u**2>**0.5 of the positions in cloud as random (Gaussian) displacements in units nm. Dispacement u is random for each orientation in sphere scattering. rms can be used to simulate a Debye-Waller factor.

V : float, default=0

Volume of the scatterers for scattering amplitude (see formfactor).

formfactor : None,’gauss’,’sphere’,’cube’

Gridpoint scattering amplitudes F(q) are described by:
  • None : const scattering amplitude.
  • ‘sphere’: Sphere scattering amplitude according to [R157]. The sphere radius is R=(\frac{3V}{4\pi})^{1/3}
  • ‘gauss’ : Gaussian function b_i(q)=bVexp(- \frac{V^{2/3.}}{4\pi}q^2) according to [R156].
  • ‘cube’ : Cube method not yet implemented.
  • Explicit isotropic form factor ff as array with [q,ff] e.g. from multishell. The normalized scattering amplitude fa for each gridpoint is calculated as fa=ff**0.5/fa(0). Missing values are linear intepolated (np.interp), q values outside interval are mapped to qmin or qmax.

ffpolydispersity : float

Polydispersity of the gridpoints in relative units for sphere, gauss, explicit. Assuming F(q*R) for each gridpoint F is scaled as F(q*f*R) with f as normal distribution around 1 and standard deviation ffpolydispersity. The scattering length b is scaled according to the respective volume change by f**3. (f<0 is set to zero . ) This results in a change of the forward scattering because of the stronger weight of larger objects.

ncpu : int, default 0

Number of cpus used in the pool for multiprocessing.
  • not given or 0 : all cpus are used
  • int>0 : min(ncpu, mp.cpu_count)
  • int<0 : ncpu not to use
  • 1 : single core usage for testing or comparing speed to Debye
Returns:

dataArray with columns [q, Pq, beta]

  • .sumblength : Sum of blength with I(q=0)=sumblength**2
  • .formfactoramplitude_q : formfactoramplitude of cloudpoints according to type for all q values.

Notes

We calculate the scattering amplitude F(q) for N atoms in a volume V with scattering length density b(r)

F(q)= \int_V b(r) e^{iqr} \mathrm{d}r / \int_V b(r) \mathrm{d}r = \sum_N b_i e^{iqr} / \sum_N b_i

with the form factor P(Q) after orientational average <>

P(Q)=< F(q) \cdot F^*(q) >=< |F(q)|^2 >

The scattering intensity of a single object represented by the cloud is I(Q)=P(Q) \cdot V^2 \cdot (\int_V b(r) \mathrm{d}r)^2.

beta is the asymmetry factor [R155] beta =|< F(q) >|^2 / < |F(q)|^2 >

One has to expect a peak at q=2\pi/d_{NN} with d_{NN} as the distance between scatterers.

On the other side the cloud scattering can represent the scattering of a cluster of particles with polydispersity and position distortion according to root mean square displacements (rms). Polydispersity and rms displacements are randomly changed within the orientational average to represent an ensemble average (opposite to the time average of a single cluster).

References

[R155](1, 2)
  1. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).1
[R156](1, 2) An improved method for calculating the contribution of solvent to the X-ray diffraction pattern of biological molecules Fraser R MacRae T Suzuki E IUCr Journal of Applied Crystallography 1978 vol: 11 (6) pp: 693-694
[R157](1, 2) X-ray diffuse scattering by proteins in solution. Consideration of solvent influence B. A. Fedorov, O. B. Ptitsyn and L. A. Voronin J. Appl. Cryst. (1974). 7, 181-186 doi: 10.1107/S0021889874009137

Examples

The example compares to the analytic solution for an ellipsoid. For other shapes the grid may be better rotated away from the object symmetry or a random grid should be used. The example shows a good approximation with NN=20. Because of the grid peak at q=2\pi/d_{NN} the grid scatterer distance d_{NN} should be d_{NN} < \frac{1}{3} 2\pi/q_{max} .

Inspecting A nano cube build of different lattices shows that a fcc lattice has a larger Q range valid as formfactor.

import jscatter as js
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# cubic grid points
R=3;NN=20;relError=50
grid= np.mgrid[-R:R:1j*NN, -R:R:1j*NN,-2*R:2*R:2j*NN].reshape(3,-1).T
# points inside of sphere with radius R
p=1;p2=1*2 # p defines a superball with 1->sphere p=inf cuboid ....
inside=lambda xyz,R1,R2,R3:(np.abs(xyz[:,0])/R1)**p2+(np.abs(xyz[:,1])/R2)**p2+(np.abs(xyz[:,2])/R3)**p2<=1
insidegrid=grid[inside(grid,R,R,2*R)]
q=np.r_[0:5:0.1]
p=js.grace()
p.title('compare formfactors of an ellipsoid')
ffe=js.ff.cloudScattering(q,insidegrid,relError=relError)
p.plot(ffe,legend='cloud ff explicit')
ffa=js.ff.ellipsoid(q,2*R,R)
p.plot(ffa.X,ffa.Y/ffa.I0,li=1,sy=0,legend='analytic formula')
p.legend()
#
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# show only each 20th point
pxyz=insidegrid[np.random.randint(len(insidegrid),size=int(relError**3/20))]
#
ax.scatter(pxyz[:,0],pxyz[:,1],pxyz[:,2],color="k",s=20)
ax.set_xlim([-5,5])
ax.set_ylim([-5,5])
ax.set_zlim([-5,5])
ax.set_aspect("equal")
plt.tight_layout()
plt.show(block=False)

An objekt with explicit given formfactor for each gridpoint.

# 5 coreshell particles in line with polydispersity
rod0 = np.zeros([5, 3])
rod0[:, 1] = np.r_[0, 1, 2, 3, 4] * 4
q = js.loglist(0.01, 7, 100)
cs = js.ff.sphereCoreShell(q=q, Rc=1, Rs=2, bc=0.1, bs=1, solventSLD=0)
ffe = js.ff.cloudScattering(q, rod0, formfactor=cs,relError=100,ffpolydispersity=0.1)
p=js.grace()
p.plot(ffe)

Using cloudscattering as fit model.

We have to define a model that parametrizes the building of the cloud that we get fit parameters. As example we use two overlapping spheres. The model can be used to fit some data. The build of the model is important as it describes how the overlapp is treated. Here e.g. as average.

#: test if distance from point on X axis
isInside=lambda x,A,R:((x-np.r_[A,0,0])**2).sum(axis=1)**0.5<R
#: model
def dumbbell(q,A,R1,R2,b1,b2,bgr=0,dx=0.3,relError=100):
    # D sphere distance
    # R1, R2 radii
    # b1,b2  scattering length
    # bgr background
    # dx grid distance not a fit parameter!!
    mR=max(R1,R2)
    # xyz coordinates
    grid=np.mgrid[-A/2-mR:A/2+mR:dx,-mR:mR:dx,-mR:mR:dx].reshape(3,-1).T
    insidegrid=grid[isInside(grid,-A/2.,R1) | isInside(grid,A/2.,R2)]
    # add blength column
    insidegrid=np.c_[insidegrid,insidegrid[:,0]*0]
    # set the corresponding blength; the order is important as here b2 overwrites b1
    insidegrid[isInside(insidegrid[:,:3],-A/2.,R1),3]=b1
    insidegrid[isInside(insidegrid[:,:3],A/2.,R2),3]=b2
    # and maybe a mix ; this depends on your model
    insidegrid[isInside(insidegrid[:,:3],-A/2.,R1) & isInside(insidegrid[:,:3],A/2.,R2),3]=(b2+b1)/2.
    # calc the scattering
    result=js.ff.cloudScattering(q,insidegrid,relError=relError)
    result.Y=result.Y+bgr
    # add attributes for later usage
    result.A=A
    result.R1=R1
    result.R2=R2
    result.dx=dx
    result.insidegrid=insidegrid
    return result
#
# test it
q=np.r_[0.01:10:0.02]
data=dumbbell(q,4,2,2,0.5,1.5)
# show result configuration
js.mpl.scatter3d(data.insidegrid[:,0],data.insidegrid[:,1],data.insidegrid[:,2])
#
# Fit your data like this (I know that b1 abd b2 are wrong).
# It may be a good idea to use not the highest resolution in the beginning because of speed.
# If you have a good set of starting parameters you can decrease dx.
data2=data.prune(number=100)
data2.makeErrPlot(yscale='l')
data2.fit(model=dumbbell,
    freepar={'A':3},
    fixpar={'R1':2,'R2':2,'dx':0.3,'b1':1,'b2':2,'bgr':0},
    mapNames={'q':'X'})

Here we compare explicit calculation with the Debye equation as the later gets quite slow for larger numbers.

import jscatter as js
import numpy as np
R=3;NN=20
grid= np.mgrid[-R:R:1j*NN, -R:R:1j*NN,-R:R:1j*NN].reshape(3,-1).T
p=1;p2=1*2 # p defines a superball with 1->sphere p=inf cuboid ....
inside=lambda xyz,R:(np.abs(xyz[:,0])/R)**p2+(np.abs(xyz[:,1])/R)**p2+(np.abs(xyz[:,2])/R)**p2<=1
insidegrid=grid[inside(grid,R)]
q=np.r_[0:5:0.1]
ffe=js.ff.cloudScattering(q,insidegrid,relError=50)    # takes about 1.9 s on single core
ffd=js.ff.cloudScattering(q,insidegrid,relError=0)       # takes about 47 s on single core
jscatter.formfactor.cuboid(q, a, b=None, c=None, SLD=1, solventSLD=0, NN=300)[source]

Formfactor of cuboid.

Parameters:

q : array

Wavevector in 1/nm

a,b,c : float, None

Edge length, for a=b=c its a cube, Units in nm. If b=None b=a. If c=None c=b.

SLD : float, default =1

Scattering length density of cuboid.unit nm^-2 e.g. SiO2 = 4.186*1e-6 A^-2 = 4.186*1e-4 nm^-2 for neutrons

solventSLD : float, default =0

Scattering length density of solvent. unit nm^-2 e.g. D2O = 6.335*1e-6 A^-2 = 6.335*1e-4 nm^-2 for neutrons

NN : int

Number of gridpoints on Fibonacci lattice is 2*NN+1 for spherical average.

Returns:

dataArray [q,Iq]

.edges

.contrast

.gridpoints

Notes

The orientational average is calculated on Fibonacci lattice.

References

[R158]Analysis of small-angle scattering data from colloids and polymer solutions: modeling and least-squares fitting Pedersen, Jan Skov Advances in Colloid and Interface Science 70, 171 (1997) http://dx.doi.org/10.1016/S0001-8686(97)00312-6
jscatter.formfactor.cylinder(q, L, radius, SLD, solventSLD=0, alpha=[0, 1.5707963267948966])[source]

cylinder form factor (open cap)

see multiShellCylinder

jscatter.formfactor.ellipsoid(q, Ra, Rb, SLD=1, solventSLD=0, alpha=[0, 90], tol=1e-06, beta=False)[source]

Form factor for a simple ellipsoid (ellipsoid of revolution).

Parameters:

q : float

scattering vector unit e.g. 1/A or 1/nm 1/Ra

Ra : float

radius rotation axis units in 1/unit(q)

Rb : float

radius rotated axis units in 1/unit(q)

SLD : float, default =1

Scattering length density of unit nm^-2 e.g. SiO2 = 4.186*1e-6 A^-2 = 4.186*1e-4 nm^-2 for neutrons

solventSLD : float, default =0

Scattering length density of solvent. unit nm^-2 e.g. D2O = 6.335*1e-6 A^-2 = 6.335*1e-4 nm^-2 for neutrons

alpha : [float,float] , default [0,90]

alpha is angle between rotation axis Ra and scattering vector q in unit grad between these angles orientation is averaged alpha=0 axis and q are parallel, other orientation is averaged

beta : True,default False

beta is asymmetry factor according to [R161]. beta = |<F(Q)>|²/<|F(Q)|²> with scattering amplitude F(Q) and form factor P(Q)=<|F(Q)|²>

tol : float

relative tolerance for integration between alpha

Returns:

dataArray with columns [q; Iq; beta ] # if beta=True

.RotationAxisRadius

.RotatedAxisRadius

.EllipsoidVolume

.I0 forward scattering q=0

References

[R159]Structure Analysis by Small-Angle X-Ray and Neutron Scattering Feigin, L. A, and D. I. Svergun, Plenum Press, New York, (1987).
[R160]http://www.ncnr.nist.gov/resources/sansmodels/Ellipsoid.html
[R161](1, 2)
  1. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).
jscatter.formfactor.ellipsoidFilledCylinder(q=1, R=10, L=0, Ra=1, Rb=2, eta=0.1, SLDcylinder=0.1, SLDellipsoid=1, SLDmatrix=0, alpha=90, epsilon=[0, 90], fPY=1, dim=3)[source]

Scattering of a cylinder filled with ellipsoidal particles.

Ellipsoids of revolution with a fluid like distribution and hard core interaction leading to Percus-Yevick structure factor between ellipsoids. Ellipsoids can be oriented along cylinder axis. If cylinders are in a lattice, the .Y component is seen in the diffusive scattering and the dominating cylinder contributes only to the bragg peaks.

Parameters:

q : array

wavevectors in units 1/nm

R : float

Cylinder radius in nm

L : float

Length of the cylinder in nm If zero infinite length is assumed, but absolute intensity is not valid, only relative intensity.

Ra : float

radius rotation axis units in nm

Rb : float

radius rotated axis units in nm

eta : float

Volume fraction of ellipsoids in cylinder for use in PercusYevick structure factor. Radius in PY corresponds to sphere with same Volume as the ellipsoid.

SLDcylinder : float,default 1

Scattering length density cylinder material in nm**-2

SLDellipsoid : float,default 1

Scattering length density of ellipsoids in cylinder in nm**-2

SLDmatrix : float

Scattering length desnity of the matrix outside the cylinder in nm**-2

alpha : float, default 90

orientation of the cylinder axis to wavevector in degrees

epsilon : [float,float], default [0,90]

min,max orientations of ellipsoids rotation axis relative to cylinder axis in degrees

fPY : float

Factor between radius of ellipsoids Rv (equivalent volume) and radius used in structure factor Rpy Rpy=fPY*(Ra*Rb*Rb)**(1/3)

dim : 3,1, default 3

Dimensionality of the PercusYevick structure factor 1 is one dimensional stricture factor, anything else is 3 dimesional (normal PY)

Returns:

dataArray [q,n*conv ellipsoids + cylinder, n *conv ellipsoids, cylinder, n * ellipsoids , structure factor, beta ellipsoids ]

Each contributing formfactor is given with its absolute contribution V**2*contrast**2 (NOT normalized to 1) beta ellipsoids is the asymmetry factor of Chen and Kotlarchyk.

References

to be published

Examples

import jscatter as js
p=js.grace()
q=js.loglist(0.01,5,800)
ff=js.ff.ellipsoidFilledCylinder(q,L=100,R=5,Ra=2,Rb=1.5,eta=0.4,alpha=90,epsilon=[0,90])
p.plot(ff.X,ff[2],legend='convolution cylinder x ellipsoids')
p.plot(ff.X,ff[3],legend='cylinder only')
p.plot(ff.X,ff[4],legend='ellipsoid only')
p.plot(ff.X,ff[5],legend='structure factor ellipsoids')
p.plot(ff.X,ff.Y,legend='conv. ellipsoid + filled cylinder')
p.legend()
p.yaxis(scale='l',label='I(q)')
p.xaxis(scale='l',label='q / nm\S-1')

# an angular averaged formfactor
def averageEFC(q,R,L,Ra,Rb,eta,alpha=[alpha0,alpha1],fPY=fPY)
    res=js.dL()
    alphas=np.deg2rad(np.r_[alpha0:alpha1:13j])
    for alpha in alphas:
        ffe=js.ff.ellipsoidFilledCylinder(q,R=R,L=L,Ra=Ra,Rb=Rb,eta=ata,alpha=alpha,)
        res.append(ffe)
    result=res[0].copy()
    result.Y=scipy.integrate.simps(res.Y,alphas)/(alpha1-alpha0)
    return result
jscatter.formfactor.gaussianChain(q, Rg)[source]

Formfactor of a gaussian polymer chain (Debye model)

Parameters:

q : array

scattering vector unit eg 1/A or 1/nm

Rg : float

radius of gyration units in 1/unit(q)

Returns:

dataArray [q,Fq]

.radiusOfGyration

Notes

for large q ~q**-2

jscatter.formfactor.genGuinier(q, Rg=1, A=1, alpha=0)[source]

Generalized Guinier approximation for low wavevector q scattering q*Rg< 1-1.3

Parameters:

q : array of float

wavevector

Rg : float

radius of gyration in units=1/q

alpha : float

shape [α = 0] spheroid, [α = 1] rod-like [α = 2] plane

A : float

amplitudes

Returns:

dataArray [q,Fq]

Notes

Quantitative analysis of particle size and shape starts with the Guinier approximations.
For three-dimensional objects the Guinier approximation is given by
I(q) = exp( − Rg**2*q**2 / 3)
This approximation can be extended also to rod-like and plane objects by
I(q) =(1 if α=0 or (α*pi*q^-α) if α=(1 or 2) ) * A*exp( − Rg^2q^2 / (3-α))

If the particle has one dimension of length L, that is, much larger than the others (i.e., elongated, rod-like, or worm-like), then there is a q range such that qR_c < 1 << qL, where α = 1.

for more details see http://sasfit.ingobressler.net/manual/Generalized_Guinier_Approximation

jscatter.formfactor.guinier(q, Rg=1, A=1)[source]

Classical Guinier

see genGuinier with alpha=0

Parameters:

q :array

A : float

Rg : float

jscatter.formfactor.multiShellCylinder(q, L, shellthickness, shellSLD, solventSLD=0, alpha=[0, 1.5707963267948966], h=None, nalpha=30, ncap=31)[source]

Multi shell cylinder with caps in solvent averaged over axis orientations.

Each shell has a constant SLD and may have a cap with same SLD sequence. Caps may be globular (barbell) or small (like lenses). For zero length L a lens shaped disc or a double sphere like shape is recovered.

Parameters:

q : array

Wavevectors, units 1/nm

L : float

Length of cylinder, units nm L=0 infinite cylinder if h=None.

shellthickness : list of float or float, all >0

Thickness of shells in sequence, units nm. radii r=cumulativeSum(shellthickness)

shellSLD : list of float or float

Scattering length density of shells in nm^-2. SiO2 = 4.186*1e-6 A^-2 = 4.186*1e-4 nm^-2

solventSLD : float

Scattering length density of surrounding solvent in nm^-2. D2O = 6.335*1e-6 A^-2 = 6.335*1e-4 nm^-2

h : float, default=None

Geometry of the caps with cap radii R=(r**2+h**2)**0.5 h is distance of cap center with radius R from the flat cylinder cap and r as radii of the cylinder shells.

  • None No caps, flat ends as default.
  • 0 cap radii equal cylinder radii (same shellthickness as cylinder shells)
  • >0 cap radius larger cylinder radii as barbell
  • <0 cap radius smaller cylinder radii as lens caps

alpha : float, [float,float] , unit rad

Orientation, angle between the cylinder axis and the scattering vector q. 0 means parallel, pi/2 is perpendicular If alpha =[start,end] is integrated between start,end start > 0, end < pi/2

nalpha : int, default 30

Number of points in Gauss integration along alpha.

ncap : int, default=31

Number of points in Gauss integration for cap.

Returns:

dataArray [q ,Iq ]

.outerCylinderVolume

.Radius

.cylindeLength

.alpha

.shellthickness

.shellSLD

.solventSLD

.modelname

.contrastprofile

.capRadii

Notes

Multishell of types:
  • flat cap cylinder L>0, radii>0, h=None
  • lens cap cylinder L>0, radii>0, h<0
  • globular cap cylinder L>0, radii>0, h>0
  • lens L=0, radii>0, h<0
  • barbell no cylinder L=0, radii>0, h>0
  • infinite flat disc L=0. h=None
Image of barbell

References

Single cylinder

[R162]Guinier, A. and G. Fournet, “Small-Angle Scattering of X-Rays”, John Wiley and Sons, New York, (1955)
[R163]http://www.ncnr.nist.gov/resources/sansmodels/Cylinder.html

Double cylinder

[R164]Use of viscous shear alignment to study anisotropic micellar structure by small-angle neutron scattering, J. B. Hayter and J. Penfold J. Phys. Chem., 88:4589–4593, 1984
[R165]http://www.ncnr.nist.gov/resources/sansmodels/CoreShellCylinder.html

Barbell, cylinder with small end-caps, circular lens

[R166]Scattering from cylinders with globular end-caps Kaya (2004). J. Appl. Cryst. 37, 223-230] DOI: 10.1107/S0021889804000020 Scattering from capped cylinders. Addendum H. Kaya and Nicolas-RaphaeÈl de Souza J. Appl. Cryst. (2004). 37, 508-509 DOI: 10.1107/S0021889804005709

Examples

Alternating shells with different thickness 0.3 nm h2o and 0.2 nm d2o in vacuum:

x=np.r_[0.0:10:0.01]
ashell=js.ff.multiShellCylinder(x,20,[0.4,0.6]*5,[-0.56e-4,6.39e-4]*5)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(ashell)
p[1].plot(ashell.contrastprofile,li=1) # a contour of the SLDs

Double shell with exponential decreasing exterior shell to solvent scattering:

x=np.r_[0.0:10:0.01]
def doubleexpshells(q,L,d1,d2,e3,sd1,sd2,sol):
   return js.ff.multiShellCylinder(q,L,[d1,d2,e3*3],[sd1,sd2,((sd2-sol)*np.exp(-np.r_[0:3:9j])+sol)],solventSLD=sol)
dde=doubleexpshells(x,10,0.5,0.5,1,1e-4,2e-4,0)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(dde)
p[1].plot(dde.contrastprofile,li=1) # a countour of the SLDs

Cylinder with cap:

x=np.r_[0.1:10:0.01]
p=js.grace()
p.title('Comaprison of dumbell cylinder with simple models')
p.subtitle('thin lines correspnd to simple models as sphere and dshell sphere')
p.plot(js.ff.multiShellCylinder(x,0,[10],[1],h=0),sy=[1,0.5,2],le='simple sphere')
p.plot(js.ff.sphere(x,10),sy=0,li=1)
p.plot(js.ff.multiShellCylinder(x,0,[2,1],[1,2],h=0),sy=[1,0.5,3],le='double shell sphere')
p.plot(js.ff.multiShellSphere(x,[2,1],[1,2]),sy=0,li=1)
p.plot(js.ff.multiShellCylinder(x,10,[3],[20],h=-5),sy=[1,0.5,4],le='thin lens cap cylinder=flat cap cylinder')
p.plot(js.ff.multiShellCylinder(x,10,[3],[20],h=None),sy=0,li=[1,2,1],le='flat cap cylinder')
p.plot(js.ff.multiShellCylinder(x,10,[3],[20],h=-0.5),sy=0,li=[3,2,6],le='thick lens cap cylinder')
p.yaxis(scale='l')
p.xaxis(scale='l')
p.legend(x=0.15,y=0.01)
jscatter.formfactor.multiShellEllipsoid(q, poleshells, equatorshells, shellSLD, solventSLD=0, alpha=[0, 90], tol=1e-06)[source]

Scattering of multi shell ellipsoidal particle with variing shell thickness at pole and equator.

Shell thicknesses add up to form complex particles with any combination of axial ratios and shell thickness. A const axial ratio means different shell thickness at equator and pole.

Parameters:

q : array

Wavevectors, unit 1/nm

equatorshells : list of float

Thickness of shells starting from inner most for rotated axis Re making the equator. unit nm. The absolute values are used.

poleshells : list of float

Thickness of shells starting from inner most for rotating axis Rp pointing to pole. unit nm. The absolute values are used.

shellSLD : list of float

List of scattering length densities of the shells in sequence corresponding to shellthickness. unit nm^-2.

solventSLD : float, default=0

Scattering length density of the surrounding solvent. unit nm^-2

Returns:

dataArray [q, Iq]

Iq, scattering cross section in units nm**2

.contrastprofile as radius and contrast values at edge points of equatorshells

.equatorshellthicknes consecutive shell thickness

.poleshellthickness

.shellcontrast contrast of the shells to the solvent

.equatorshellradii outer radius of the shells

.poleshellradii

.outerVolume Volume of complete sphere

.I0 forward scattering for Q=0

References

[R167]Structure Analysis by Small-Angle X-Ray and Neutron Scattering Feigin, L. A, and D. I. Svergun, Plenum Press, New York, (1987).
[R168]http://www.ncnr.nist.gov/resources/sansmodels/Ellipsoid.html
[R169]
  1. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).

Examples

Simple ellipsoid in vacuum:

x=np.r_[0.0:10:0.01]
Rp=2.
Re=1.
ashell=js.ff.multiShellEllipsoid(x,Rp,Re,1)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(ashell)
p[1].plot(ashell.contrastprofile,li=1) # a contour of the SLDs

Alternating shells with thickness 0.3 nm h2o and 0.2 nm d2o in vacuum:

x=np.r_[0.0:10:0.01]
shell=np.r_[[0.3,0.2]*3]
sld=[-0.56e-4,6.39e-4]*3
# constant axial ratio for all shells but nonconstant shell thickness
axialratio=2
ashell=js.ff.multiShellEllipsoid(x,axialratio*shell,shell,sld)
# shell with constant shellthickness of one component and other const axialratio
pshell=shell[:]
pshell[0]=shell[0]*axialratio
pshell[2]=shell[2]*axialratio
pshell[4]=shell[4]*axialratio
bshell=js.ff.multiShellEllipsoid(x,pshell,shell,sld)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(ashell,le='const. axial ratio')
p[1].plot(ashell.contrastprofile,li=2) # a contour of the SLDs
p[0].plot(bshell,le='const shell thickness')
p[1].plot(bshell.contrastprofile,li=2) # a contour of the SLDs
p[0].legend()

double shell with exponential decreasing exterior shell to solvent scattering:

x=np.r_[0.0:10:0.01]
def doubleexpshells(q,d1,ax,d2,e3,sd1,sd2,sol):
   shells =[d1   ,d2]+[e3]*9
   shellsp=[d1*ax,d2]+[e3]*9
   sld=[sd1,sd2]+list(((sd2-sol)*np.exp(-np.r_[0:3:9j])))
   return js.ff.multiShellEllipsoid(q,shellsp,shells,sld,solventSLD=sol)
dde=doubleexpshells(x,0.5,1,0.5,1,1e-4,2e-4,0)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(dde)
p[1].plot(dde.contrastprofile,li=1) # a countour of the SLDs
jscatter.formfactor.multiShellSphere(q, shellthickness, shellSLD, solventSLD=0)[source]

Scattering of spherical multi shell particle including linear contrast variation in subshells.

The results needs to be multiplied with the concentration to get the measured scattering.

Parameters:

q : array

wavevectors to calculate form factor unit e.g. 1/nm

shellthickness : list of float

thickness of shells starting from inner most unit in 1/[q units]

shellSLD : list of float or list

List of scattering length densities of the shells in sequence corresponding to shellthickness. unit in nm**-2
  • Innermost shell needs to be constant shell.
  • If an element of the list is itself a list of SLD values it is interpreted as equal thick subshells with linear progress between SLD values in sum giving shellthickness.
  • If subshell list has only one float e.g. [1e.4] the second value is the SLD of the following shell.
  • If empty list is given as [] the SLD of the previous and following shells are used as smooth transition.

solventSLD : float, default=0

Scattering length density of the surrounding solvent. If equal to zero (default) then in profile the contrast is given. Unit in [q unit]**2 e.g. 1/nm**2

Returns:

dataArray [wavevector, Iq]

Iq scattering cross section in units nm**2

.contrastprofile as radius and contrast values at edge points

.shellthickness consecutive shell thickness

.shellcontrast contrast of the shells to the solvent

.shellradii outer radius of the shells

.slopes slope of linear increase of each shell

.outerVolume Volume of complete sphere

.I0 forward scattering for Q=0

Notes

The solution is unstable (digital resolution) for really low QR values, which are set to the I0 scattering.

Examples

Alternating shells with 5 alternating thickness 0.4 nm and 0.6 nm with h2o, d2o scatetring contrast in vacuum:

x=np.r_[0.0:10:0.01]
ashell=js.ff.multiShellSphere(x,[0.4,0.6]*5,[-0.56e-4,6.39e-4]*5)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(ashell)
p[1].plot(ashell.contrastprofile,li=1) # a contour of the SLDs

Double shell with exponential decreasing exterior shell to solvent scattering:

x=np.r_[0.0:10:0.01]
def doubleexpshells(q,d1,d2,e3,sd1,sd2,sol):
   return js.ff.multiShellSphere(q,[d1,d2,e3*3],[sd1,sd2,((sd2-sol)*np.exp(-np.r_[0:3:9j]))],solventSLD=sol)
dde=doubleexpshells(x,0.5,0.5,1,1e-4,2e-4,0)
#plot it
p=js.grace()
p.multi(2,1)
p[0].plot(dde)
p[1].plot(dde.contrastprofile,li=1) # a countour of the SLDs
jscatter.formfactor.multilamellarVesicles(Q, R, N, phi, displace=0, dR=0, dN=0, shellthickness=0, ds=0, SLD=1, solventSLD=0, nGauss=100)[source]

Scattering intensity of a multilamellar vesicle with random displacement of the inner vesicles [R170].

The result contains the full scattering, the structure factor of the shells and a multilayer formfactor of the lamellar layer structure. Other layer structures as mentioned in [2]

Parameters:

Q : float

Wavevector in 1/nm.

R : float

Outer radius of the Vesicle in units nm.

dR : float

Width of outer radius distribution in units nm.

displace : float

Displacements of the vesicles centers in units nm. This describes the displacement steps in a random walk of the centers. displace=0 it is concentric, all have same center. displace< R/N.

N : int

Number of layers.

dN : int, default=0

Width of distribution for number of layers. (dN< 0.4 is single N) A zero truncated normal distribution is used with N>0 and N<R/displace. Check .Ndistribution and .Nweight = Nweigth for the used distribtion.

shellthickness: float,list of float,default=0

Thickness of shells in symetric layer in units nm. Zero assumes infinit thin layer with constant formfactor. List gives consecutive layer thickness from center to outside. [4,1] result in a [1,4,1] symmetric layer.

ds : float, not working , set to zero

Thickness fluctuation of the innermost layer in shellthickness. unit is nm. A Gaussian is used which is cut at 0.1*shellthickness[0]. ds should be significant smaller than shellthickness[0].

phi : float

Volume fraction \phi of layers inside of vesicle.

SLD : float

Scattering length density of shells in nm^-2.

solventSLD

Solvent scattering length density in nm^-2.

Returns:

dataArray with [q,I(q),S(q),F(q)]

.columnname=’q;Iq;Sq;Fq’ .outerShellVolume .Ndistribution .Nweight .displace .phi .shellthickness .SLD .solventSLD .shellfluctuations=ds .preFactor=phi*Voutershell**2

Notes

The left shows a concentric lamellar structure. The right shows the random path of the consecutive centers of the spheres. See Multilamellar Vesicles for resulting scattering curves.

Image of MultiLamellarVesicles

The function returns I(Q) as (see [R170] equ. 17 )

I(Q)=\phi V_{outershell} S(Q) F(Q)

F(Q)= ( \sum_i d \rho_i sinc( Q d_i) )^2

with d\rho as scattering length density difference to next layer with thickness d_i and the shell structure factor S(Q) as described in equ. A2 in [R170].

  • The amphiphile concentration phi is roughly given by phi = d/a, with d being the bilayer thickness and a being the spacing of the shells. The spacing of the shells is given by the scattering vector of the first correlation peak, i.e., a = 2pi/Q. Once the MLVs leave considerable space between each other then phi < d/a holds. This condition coincides with the assumption of dilution of the Guinier law. (from [R170])

  • Structure factor part is normalized that S(0)=\sum_{j=1}^N (j/N)^2

  • To use a different shell form factor the structure factor is given explicitly.

  • Comparing a unilamellar vesicle (N=1) with multiShellSphere shows that R is located in the center of the shell:

    Q=js.loglist(0.0001,5,1000)#np.r_[0.01:5:0.01]
    ffmV=js.ff.multilamellarVesicles
    p=js.grace()
    # comparison double sphere
    mV=ffmV(Q=Q, R=100., displace=0, dR=0,N=1,dN=0, phi=1,shellthickness=6, SLD=1e-4,nGauss=20)
    p.plot(mV)
    p.plot(js.ff.multiShellSphere(Q,[97,6],[0,1e-4]),li=1)
    p.yaxis(label='S(Q)',scale='l',min=1e-10,max=1e6,ticklabel=['power',0])
    p.xaxis(label='Q / nm\S-1',scale='l',min=1e-3,max=5,ticklabel=['power',0])
    

References

[R170](1, 2, 3, 4, 5) Small-angle scattering model for multilamellar vesicles H. Frielinghaus PHYSICAL REVIEW E 76, 051603 (2007)
[R171]Small-Angle Scattering from Homogenous and Heterogeneous Lipid Bilayers NorbertKučerka Advances in Planar Lipid Bilayers and Liposomes 12, 201-235 (2010)

Examples

See Multilamellar Vesicles

import jscatter as js
import numpy as np

ffmV=js.ff.multilamellarVesicles
Q=js.loglist(0.01,5,500)
dd=1.5
dR=5
nG=100
ds=0
R=50
N=5
st=[3.5,(6.5-3.5)/2]
p=js.grace(1,1)
p.title('Lipid bilayer in SAXS/SANS')
# SAXS
saxm=ffmV(Q=Q, R=R, displace=dd, dR=dR,N=N,dN=0, phi=0.2,shellthickness=st,ds=ds, SLD=[0.6e-3,0.07e-3],solventSLD=0.94e-3,nGauss=nG)
p.plot(saxm,sy=[1,0.3,1],le='SAXS multilamellar')
saxu=ffmV(Q=Q, R=R, displace=0, dR=dR,N=1,dN=0, phi=0.2,shellthickness=st,ds=ds,SLD=[0.6e-3,0.07e-3],solventSLD=0.94e-3,nGauss=100)
p.plot(saxu,sy=0,li=[3,2,1],le='SAXS unilamellar')
# SANS
sanm=ffmV(Q=Q, R=R, displace=dd, dR=dR,N=N,dN=0, phi=0.2,shellthickness=st,ds=ds, SLD=[1.5e-4,0.3e-4],solventSLD=6.335e-4,nGauss=nG)
p.plot( sanm,sy=[1,0.3,2],le='SANS multilamellar')
sanu=ffmV(Q=Q, R=R, displace=0, dR=dR,N=1,dN=0, phi=0.2,shellthickness=st,ds=ds,SLD=[1.5e-4,0.3e-4],solventSLD=6.335e-4,nGauss=100)
p.plot(sanu,sy=0,li=[3,2,2],le='SANS unilamellar')
#
p.legend(x=0.015,y=1e-1)
p.subtitle('R=50 nm, N=5, shellthickness=[1.5,3.5,1.5] nm, dR=5, ds=0.')
p.yaxis(label='S(Q)',scale='l',min=1e-6,max=1e4,ticklabel=['power',0])
p.xaxis(label='Q / nm\S-1',scale='l',min=1e-2,max=5,ticklabel=['power',0])
jscatter.formfactor.orientedCloudScattering(qxz, cloud, rms=0, coneangle=10, nCone=50, V=0, formfactor=None, ncpu=0)[source]

2D scattering of an oriented cloud of scatterers with equal or variable scattering length. Using multiprocessing.

Cloud can represent an object described by a cloud of isotropic scatterers with orientation averaged in a cone. Scattering amplitudes may be constant, sphere scattering amplitude, Gaussian scattering amplitude or explicitly given form factor. Rememeber that the atomic bond length are on the order 0.1-0.2 nm and one expects Bragg peaks.

Parameters:

qxz : array, ndim= Nx3

wavevectors in 1/nm

cloud : array Nx3 or Nx4

  • Center of mass positions (in nm) of the N scatterers in the cloud.
  • If given cloud[3] is the scattering length b at positions cloud[:3], otherwise b=1.

coneangle : float

Coneangle in units degrees.

rms : float, default=0

Root mean square displacement =<u**2>**0.5 of the positions in cloud as random (Gaussian) displacements in units nm. Dispacement u is random for each orientation nCone. rms can be used to simulate a Debye-Waller factor. Larger nCone is advised to smooth data.

nCone : int

Cone average as average over nCone Fibonacci lattice points in cone.

V : float, default=0

Volume of the scatterers for formfactor ‘gauss’ and ‘sphere’.

formfactor : ‘gauss’,’sphere’,array 2xN,default=None

Gridpoint scattering amplitudes are described by:
  • None : const scattering amplitude, point like particle.
  • ‘sphere’: Sphere scattering amplitude according to [3]_. The sphere radius is R=(\\frac{3V}{4\\pi})^{1/3}
  • ‘gauss’ : Gaussian function b_i(q)=bVexp(- \\frac{V^{2/3.}}{4\pi}q^2) according to [2]_.
  • explicit isotropic form factor ff as array with [q,ff] e.g. from multishell. The normalized scattering amplitude fa for each gridpoint is calculated as fa=ff**0.5/fa(0). Missing values are linear intepolated (np.interp), q values outside interval are mapped to qmin or qmax.

ncpu : int, default 0

Number of cpus used in the pool for multiprocessing.
  • not given or 0 : all cpus are used
  • int>0 : min(ncpu, mp.cpu_count)
  • int<0 : ncpu not to use
  • 1 : single core usage for testing or comparing speed to Debye
Returns:

dataArray [qx,qz, Pq]

  • The forward scattering is Pq(q=0)= sumblength**2
  • .sumblength : Sum of blength with sumblength**2
  • .formfactoramplitude : formfactoramplitude of cloudpoints according to type for all q values.
  • .formfactoramplitude_q :corresponding q values.

Examples

How to use orientedCloudScattering for fitting see last Example in cloudScattering.

import jscatter as js
import numpy as np
# two points along y result in pattern independent of x but cos**2 for z
# with larger coneangle Ix becomes qx dependent
rod0=np.zeros([2,3])
rod0[:,1]=np.r_[0,np.pi]
qxz=np.mgrid[-6:6:50j, -6:6:50j].reshape(2,-1).T
ffe=js.ff.orientedCloudScattering(qxz,rod0,coneangle=5,nCone=10,rms=0)
fig=js.mpl.surface(ffe.X,ffe.Z,ffe.Y)
fig.axes[0].set_title(r'cos**2 for Z and slow decay for X due to 5 degree cone')
fig.show()
# noise in positions
ffe=js.ff.orientedCloudScattering(qxz,rod0,coneangle=5,nCone=100,rms=0.1)
fig=js.mpl.surface(ffe.X,ffe.Z,ffe.Y)
fig.axes[0].set_title('cos**2 for Y and slow decay for X with position noise')
fig.show()
#
# two points along z result in symmetric pattern around zero
# asymetry reflects fibonacci lattice -> increase nCone
rod0=np.zeros([2,3])
rod0[:,2]=np.r_[0,np.pi]
ffe=js.ff.orientedCloudScattering(qxz,rod0,coneangle=45,nCone=10,rms=0.005)
fig2=js.mpl.surface(ffe.X,ffe.Z,ffe.Y)
fig2.axes[0].set_title('symmetric because of orientation along z; \n nCone needs to be larger for large cones')
fig2.show()
#
# 5 spheres in line with small position distortion
rod0 = np.zeros([5, 3])
rod0[:, 1] = np.r_[0, 1, 2, 3, 4] * 3
qxz = np.mgrid[-6:6:50j, -6:6:50j].reshape(2, -1).T
ffe = js.ff.orientedCloudScattering(qxz, rod0, formfactor='sphere', V=4/3.*np.pi*2**3, coneangle=20, nCone=30, rms=0.02)
fig4 = js.mpl.surface(ffe.X, ffe.Z, np.log10(ffe.Y), colorMap='gnuplot')
fig4.axes[0].set_title('5 spheres with R=2 along Z with noise (rms=0.02)')
fig4.show()
#
# 5 core shell particles in line with small position distortion (Gaussian)
rod0 = np.zeros([5, 3])
rod0[:, 1] = np.r_[0, 1, 2, 3, 4] * 3
qxz = np.mgrid[-6:6:50j, -6:6:50j].reshape(2, -1).T
# only as demo : extract q from qxz
qxzy = np.c_[qxz, np.zeros_like(qxz[:, 0])]
qrpt = js.formel.xyz2rphitheta(qxzy)
q = np.unique(sorted(qrpt[:, 0]))
# or use interpolation
q = js.loglist(0.01, 7, 100)
cs = js.ff.sphereCoreShell(q=q, Rc=1, Rs=2, bc=0.1, bs=1, solventSLD=0)
ffe = js.ff.orientedCloudScattering(qxz, rod0, formfactor=cs, coneangle=20, nCone=100, rms=0.05)
fig4 = js.mpl.surface(ffe.X, ffe.Z, np.log10(ffe.Y), colorMap='gnuplot')
fig4.axes[0].set_title('5 core shell particles with R=2 along Z with noise (rms=0.05)')
fig4.show()

Make a slice for an angular region but with higher resolution to see the additional peaks due to allignement

rod0 = np.zeros([5, 3])
rod0[:, 1] = np.r_[0, 1, 2, 3, 4] * 3
qxz = np.mgrid[-4:4:150j, -4:4:150j].reshape(2, -1).T
# only as demo : extract q from qxz
qxzy = np.c_[qxz, np.zeros_like(qxz[:, 0])]
qrpt = js.formel.xyz2rphitheta(qxzy)
q = np.unique(sorted(qrpt[:, 0]))
# or use interpolation
q = js.loglist(0.01, 7, 100)
cs = js.ff.sphereCoreShell(q=q, Rc=1, Rs=2, bc=0.1, bs=1, solventSLD=0)
ffe = js.ff.orientedCloudScattering(qxz, rod0, formfactor=cs, coneangle=20, nCone=100, rms=0.05)
fig4 = js.mpl.surface(ffe.X, ffe.Z, np.log10(ffe.Y), colorMap='gnuplot')
fig4.axes[0].set_title('5 core shell particles with R=2 along Z with noise (rms=0.05)')
fig4.show()
#
# transform X,Z to spherical coordinates
qphi=js.formel.xyz2rphitheta([ffe.X,ffe.Z,abs(ffe.X*0)],transpose=True )[:,:2]
# add qphi or use later rp[1] for selection
ffb=ffe.addColumn(2,qphi.T)
# select a portion of the phi angles
phi=np.pi/2
dphi=0.2
ffn=ffb[:,(ffb[-1]<phi+dphi)&(ffb[-1]>phi-dphi)]
ffn.isort(-2)    # sort along radial q
p=js.grace()
p.plot(ffn[-2],ffn.Y,le='oriented spheres form factor')
# compare to coreshell formfactor scaled
p.plot(cs.X,cs.Y/cs.Y[0]*25,li=1,le='coreshell form factor')
p.yaxis(label='F(Q,phi=90°+-11°)', scale='log')
p.title('5 alligned core shell particle with additional interferences',size=1.)
p.subtitle(' due to sphere allignement dependent on observation angle')

# 2: direct way with 2D q in xz plane
rod0 = np.zeros([5, 3])
rod0[:, 1] = np.r_[0, 1, 2, 3, 4] * 3
x=np.r_[0.0:6:0.05]
qxzy = np.c_[x, x*0,x*0]
for alpha in np.r_[0:91:30]:
    R=js.formel.rotationMatrix(np.r_[0,0,1],np.deg2rad(alpha)) # rotate around Z axis
    qa=np.dot(R,qxzy.T).T[:,:2]
    ffe = js.ff.orientedCloudScattering(qa, rod0, formfactor=cs, coneangle=20, nCone=100, rms=0.05)
    p.plot(x,ffe.Y,li=[1,2,-1],sy=0,le='alpha=%g' %alpha)
p.xaxis(label=r'Q / nm\S-1')
p.legend()
jscatter.formfactor.pearlNecklace(Q, Rc, l, N, A1=None, A2=None, A3=None, ms=None, mr=None)[source]

Formfactor of a pearlnecklace (freely jointed chain of pearls connected by rods)

The formfactor is normalized that the pearls contribution equals 1.

Parameters:

Q : array

wavevector in nm

Rc : float

pearl radius in nm

N : float

number of pearls (homogeneous spheres)

l : float

physical length of the rods

A1, A2, A3 : float

Amplitudes of pearl-pearl, rod-rod and pearl-rod scattering. Can be calculated with the number of chemical monomers in a pearl ms and rod mr (see below for further information) If ms and mr are given A1,A2,A3 are calculated from these.

ms : float, default None

number of chemical monomers in each pearl

mr : float, default None

number of chemical monomers in rod like strings

Returns:

dataarray [q, Iq]

.pearlRadius

.A1

.A2

.A3

.numberPearls

.mr

.ms

.stringLength

Notes

  • M : number of rod like strings (M=N-1)
  • A1 = ms²/(M*mr+N*ms)²
  • A2 = mr²/(M*mr+N*ms)²
  • A3 = (mr*ms)/(M*mr+N*ms)²

References

[R172]
  1. Schweins, K. Huber, Macromol. Symp., 211, 25-42, 2004.
jscatter.formfactor.scatteringFromSizeDistribution(q, sizedistribution, fffunction=<function beaucage>, fffkwargs={'G': 1, 'd': 3}, scatteringlength=<function <lambda>>)[source]

Scattering of a size distribution of objects with form factor fffunction

scattering of a single size:
I(q) = n * drho^2 * V^2 * P(q)*S(q)
n number density
drho difference in scattering length density (contrast)
V scattering Volume of particle ~r³ ~ mass
P(q) formfactor with P(0)=1; here fffunction
S(q) structure factor with S(inf)=>1 for simplicity

size distribution
I(q)= sum_over_sizes[ scatteringlength(size) * probability(size) * fffunction(q,size,**fffkwargs).Y ] with S(q)=1
Parameters:

q : list/array of float; unit = 1/unit(size distribution)

wavevectors to calculate scattering

sizedistribution : dataArray or array

distribution.T[i] should give pairs [size,probability,…] (X or dimension 0) -> list of sizes; (Y or dimension 1) list of probability eg. from DLS measurement

fffunction : lambda or function

function that describes the form factor like a beaucage (default) first arguments (q,R,… should return dataArray with .Y as result

fffkwargs : args

any additional keyword arguments for fffunction as dictionary eg. {‘d’:3}

scatteringlength : function

scattering_length(r)**2= drho**2 * V**2 volume objects dimension 3 with scattering length density constant for number distribution: scatteringlength per particle ~R**6 for volume distribution: scatteringlength per particle ~R**2 because V=r**3 for intensity distribution: scatteringlength per particle const because V=r**3

Returns:

dataArray [q,Iq or Fq]

Notes

To look at the contribution of aggregates of size 70 to 12 nm particles:

# equal concentration
p.plot(s.formel.scatteringFromSizeDistribution(s.loglist(0.01,6,100),[[12,70],[1,1]]),legend='with aggregates')
# 2:1 concentration
p.plot(s.formel.scatteringFromSizeDistribution(s.loglist(0.01,6,100),[[12,70],[2,1]]),legend='no aggregates')

To look at a part of the distribution use sizedistribution.prune(min,max)

If size,probability is not in column 0,1 use as for the Malvern frequencydistribution: sizedistribution=frequencydistribution[np.r_[4,1]] if probability is column 1 and soze column 4

It is instructive to plot the result together with q*R~const p.plot(1/sizedistribution[0],sizedistribution[1])

jscatter.formfactor.sphere(q, radius, contrast=1)[source]

Scattering of a single homogeneous sphere.

Parameters:

q : float

wavevector in units of 1/nm

radius : float

radius in units nm

contrast : float, default=1

difference in scattering length to the solvent = contrast

Returns:

dataArray [q,Iq]

Iq scattering intensity

.I0 forward scattering

Notes

The first minimum of the form factor is at q*R=4.493

www.ncnr.nist.gov/resources/sansmodels/Sphere.html

jscatter.formfactor.sphereCoreShell(q, Rc, Rs, bc, bs, solventSLD=0)[source]

Scattering of a spherical core shell particle.

Parameters:

q : float

wavevector in units of 1/(R units)

Rc,Rs : float

radius core and radius of shell Rs>Rc

bc,bs : float

contrast to solvent scattering length density of core and shell

solventSLD : float, default =0

scattering length density of the surrounding solvent if equal to zero (default) then in profile the contrast is given

Returns:

dataArray [wavevector ,Iq ]

Notes

Calls multiShellSphere.

jscatter.formfactor.sphereFuzzySurface(q, R, sigmasurf, contrast)[source]

Scattering of a sphere with a fuzzy interface.

Parameters:

q : float

wavevector in units of 1/(R units)

R : float

The particle radius R represents the radius of the particle where the scattering length density profile decreased to 1/2 of the core density.

sigmasurf : float

sigmasurf is the width of the smeared particle surface.

contrast : float

difference in scattering length to the solvent = contrast

Returns:

dataArray [q, Iq]

Iq scattering intensity related to sphere volume.

.I0 forward scattering

Notes

The “fuzziness” of the interface is defined by the parameter sigmasurf. The particle radius R represents the radius of the particle where the scattering length density profile decreased to 1/2 of the core density. sigmasurf is the width of the smeared particle surface. The inner regions of the microgel that display a higher density are described by the radial box profile extending to a radius of approximately Rbox ~ R - 2(sigma). In dilute solution, the profile approaches zero as Rsans ~ R + 2(sigma).

References

[R173]
  1. Stieger, J. S. Pedersen, P. Lindner, W. Richtering, Langmuir 20 (2004) 7283-7292
jscatter.formfactor.sphereGaussianCorona(q, R, Rg, Ncoil, coilequR, coilSLD=6.4e-05, sphereSLD=0.0004186, solventSLD=0.0006335, d=1)[source]

Scattering of a sphere surrounded by gaussian coils as model for grafted polymers on particle e.g. a micelle.

The additional scattering is uniformly distributed at the surface, which might fail for lower aggregation numbers as 1, 2, 3. Instead of aggregation number in [R174] we use sphere volume and a equivalent volume of the gaussian coils.

Parameters:

q: array of float

wavevectors in units 1/nm

R : float

sphere radius unit nm

Rg : float

radius of gyration of coils unit nm

d : float, default 1

Coils centre loacated d*Rg away from the sphere surface

Ncoil : float

number of coils at the surface (aggregation number)

coilequR : float

Equivalent radius to calc volume of the coil mass if densely packed as a sphere. Needed to calculate absolute scattering of the coil.

coilSLD : float

Scattering length density of coil. unit nm^-2. default hPEG = 0.64*1e-6 A^-2 = 0.64*1e-4 nm^-2

sphereSLD : float

Scattering length density of sphere.unit nm^-2. default SiO2 = 4.186*1e-6 A^-2 = 4.186*1e-4 nm^-2

solventSLD : float

Scattering length density of solvent. unit nm^-2. default D2O = 6.335*1e-6 A^-2 = 6.335*1e-4 nm^-2

Returns:

dataArray [q,Iq]

.coilRg

.sphereRadius

.numberOfCoils

.coildistancefactor

.coilequVolume

.coilSLD

.sphereSLD

.solventSLD

Notes

The defaults result in a silica sphere with hPEG grafted at the surface in D2O.
  • Rg=N**0.5*b with N monomers of length b
  • Vcoilsphere=4/3.*np.pi*coilequR**3
  • Vcoilsphere=N*monomerVolume
  • coilequR=(N*monomerVolume/(4/3.*np.pi))**(1/3.)

References

[R174](1, 2) Form factors of block copolymer micelles with spherical, ellipsoidal and cylindrical cores Pedersen J Journal of Applied Crystallography 2000 vol: 33 (3) pp: 637-640
[R175]Hammouda, B. (1992).J. Polymer Science B: Polymer Physics30 , 1387–1390
jscatter.formfactor.superball(q, R, p, SLD=1, solventSLD=0, nGrid=15, returngrid=False)[source]

A superball is a general mathematical shape that can be used to describe rounded cubes, sphere and octahedra.

The numerical integration is done by a grid of scatterers, refined at the surface with an insidegrid and an outsidegrid averaged.

Parameters:

q : array

Wavevector in 1/nm

R : float, None

2R = edge length

p : float, 0<p<100

parameter that descibes rounding | p=0 empty space | p<0.5 concave octahedra | p=0.5 octahedra | 0.5<p<1 convex octahedra | p=1 spheres | p>1 rounded cubes | p->inf cubes

SLD : float, default =1

Scattering length density of cuboid.unit nm^-2

solventSLD : float, default =0

Scattering length density of solvent. unit nm^-2

nGrid : int

Number of gridpoints in start lattice is nGrid**3. This is refined at the surface.til griddistance/3. relError=nGrid*4 is used for Fibonacci lattice with 2*relError+1 orientations in spherical average.

Returns:

dataArray [q,Iq, beta]

Notes

For large Q we observe a peak corresponding to the grid that is used for the integration. This is a sign that the density of the grid is not high enough as we see something like internal grid structure. The same happens in standard integration routines if you integrate for the Q values with a fixed resolution. In these cases please choose a smaller grid and wait. :-) Use the time to think about the advantages of an analytical solution if it is availible and atomic resolution.

References

[R176]Periodic lattices of arbitrary nano-objects: modeling and applications for self-assembled systems Yager, K.G.; Zhang, Y.; Lu, F.; Gang, O. Journal of Applied Crystallography 2014, 47, 118–129. doi: 10.1107/S160057671302832X
[R177]http://gisaxs.com/index.php/Form_Factor:Superball

Examples

import jscatter as js
import numpy as np
#
q=np.r_[0:5:0.02]
R=6;
p=js.grace()
p.multi(2,1)
p[0].yaxis(scale='l')
ss=js.ff.superball(q,R,p=1,)
p[0].plot(ss,legend='superball p=1')
p[0].plot(js.ff.sphere(q,R),li=1,sy=0,legend='sphere ff')
p[0].legend(x=1,y=1e-1)
#
p[1].yaxis(scale='l')
cc=js.ff.superball(q,R,p=100)
p[1].plot(cc,sy=[1,0.3,4],legend='superball p=100')
p[1].plot(js.ff.cuboid(q,2*R),li=4,sy=0,legend='cuboid, but never reached')
p[1].legend(x=1,y=1e6)
p[1].text('internal structure of grid',x=3.5,y=4e4)
#
# visualisation
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# cubic grid points
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
q=np.r_[0:5:0.1]
R=3
pxyz=js.ff.superball(q,R,p=200,nGrid=10,returngrid=True).grid
pxyz=pxyz[pxyz[:,0]>0]
ax.scatter(pxyz[:,0],pxyz[:,1],pxyz[:,2],color="k",s=20)
ax.set_xlim([-3,3])
ax.set_ylim([-3,3])
ax.set_zlim([-3,3])
ax.set_aspect("equal")
plt.tight_layout()
plt.show(block=False)
jscatter.formfactor.teubnerStrey(q, xi, d, eta2=1)[source]

Phenomenological model for the scattering intensity of a two-component system using the Teubner-Strey model [R178].

Often used for bi-continuous micro-emulsions.

Parameters:

q : array

wavevectors

xi : float

correlation length

d : float

characteristic domain size, periodicity

eta2 : float, default=1

squared scattering length density contrast

Returns:

dataArray [q, Iq]

Notes

  • q_{max}=((2\pi/d)^2-\xi^{-2})^{1/2}

References

[R178](1, 2) M. Teubner and R. Strey, Origin of the scattering peak in microemulsions, J. Chem. Phys., 87:3195, 1987
[R179]K. V. Schubert, R. Strey, S. R. Kline, and E. W. Kaler, Small angle neutron scattering near lifshitz lines: Transition from weakly structured mixtures to microemulsions, J. Chem. Phys., 101:5343, 1994

Examples

Fit Teubner-Strey with background and a power law for low Q

#import jscatter as js
#import numpy as np

def tbpower(q,B,xi,dd,A,beta,bgr):
    # Model Teubner Strey  + power law and background
    tb=js.ff.teubnerStrey(q=q,xi=xi,d=dd)
    # add power law and background
    tb.Y=B*tb.Y+A*q**beta+bgr 
    tb.A=A
    tb.bgr=bgr
    tb.beta=beta
    return tb

# simulate some data
q=js.loglist(0.01,5,600)
data=tbpower(q,1,10,20,0.002,-3,0.1)
# or read them
# data=js.dA('filename.chi')

# plot data
p=js.grace()
p.plot(data,legend='simulated data')
p.xaxis(scale='l',label=r'Q / nm\S-1')
p.yaxis(scale='l',label='I(Q) / a.u.')
p.title('TeubnerStrey model with power and background')
jscatter.formfactor.wormlikeChain(q, N, a, R=None, SLD=1, solventSLD=0, rtol=0.02)[source]

Scattering of a wormlike chain, which correctly reproduces the rigid-rod and random-coil limits.

The forward scattering is :math:´I0=V^2(SLD-solventSLD)^2´ volume :math:´V=piR^2N´.

Parameters:

q : array

wavevectors in 1/nm

N : float

Chain length, units of 1/q

a : float

Persistence length with l=2a l=Kuhn length (segment length), units of nm.

R : float

Radius in units of nm.

SLD : float

Scattering length density segments.

solventSLD :

Solvent scattering length density.

rtol : float

Maximum relative tolerance in integration.

Returns:

dataArray [q, Iq]

.chainRadius

.chainLength

.persistenceLength

.Rg

.volume

.contrast

Notes

From [R180] :
The Kratky plot (Figure 4 ) is not the most convenient way to determine a as was pointed out in ref 20. Figure 5 provides an alternative way of measuring a by plotting the experimentally measurable combination Nk2S(k) versus a for fixed wavelength k. As Figure 5 indicates, this plot is rather insensitive to the chain length N and therefore is universal. The numerical analysis of eq 17 shows that this remains true for as long as k is not too small. Taking into account that the excluded-volume effects leave S(k) practically unchanged (e.g., see Figures 2 and 4 of ref 231, the plot of Figure 5 can serve as a useful alternative to the Kratky plot which, in addition, does not suffer from the polydispersity effects
  • Rg is calculated according to equ 20 in [R181] and [R182].

References

[R180](1, 2) Analytical calculation of the scattering function for polymers of arbitrary flexibility using the dirac propagator, A. L. Kholodenko, Macromolecules, 26:4179–4183, 1993
[R181](1, 2) The structure factor of a wormlike chain and the random-phase-approximation solution for the spinodal line of a diblock copolymer melt Zhang X et. al. Soft Matter 10, 5405 (2014)
[R182](1, 2) Models of Polymer Chains Teraoka I. in Polymer Solutions: An Introduction to Physical Properties pp: 1-67, New York, John Wiley & Sons, Inc.

Examples

import jscatter as js
p=js.grace()
p.multi(2,1)
p.title('figure 3 (2 scaled) of ref Kholodenko Macromolecules 26, 4179 (1993)',size=1)
q=js.loglist(0.01,10,100)
for a in [1,2.5,5,20,50,1000]:
    ff=js.ff.wormlikeChain(q,200,a)
    p[0].plot(ff.X,200*ff.Y*ff.X**2,legend='a=%.4g' %ff.persistenceLength)
    p[1].plot(ff.X,ff.Y,legend='a=%.4g' %ff.persistenceLength)
p[0].legend()
p[0].yaxis(label='Nk\S2\NS(k)')
p[1].xaxis(label='k',scale='l')
p[1].yaxis(label='S(k)',scale='l')
#
p=js.grace()
p.multi(2,1)
p.title('figure 4 of ref Kholodenko Macromolecules 26, 4179 (1993)',size=1)
# fig 4 seems to be wrong scale in [R180]_ as for large N with a=1 fig 2 and 4 should have same plateau.
a=1
q=js.loglist(0.01,4./a,100)
for NN in [1,20,50,150,500]:
    ff=js.ff.wormlikeChain(q,NN,a)
    p[0].plot(ff.X*a,NN*a*ff.Y*ff.X**2,legend='N=%.4g' %ff.chainLength)
    p[1].plot(ff.X,ff.Y,legend='a=%.4g' %ff.persistenceLength)
p[0].legend()
p[0].yaxis(label='(N/a)(ka)\S2\NS(k)')
p[0].xaxis(label='ka')
p[1].xaxis(label='k',scale='l')
p[1].yaxis(label='S(k)',scale='l')