7. structurefactor (sf) — Jscatter 1.2.6 documentation

# 7. structurefactor (sf)

Fluid like and crystal like structure factors (sf) and directly related functions for scattering related to interaction potentials between particles.

Fluid like include hard core SF or charged sphere sf and more. For RMSA an improved algorithm is used based on the original idea (see Notes in RMSA).

For lattices of ordered mesoscopic materials (see Lattice) the analytic sf can be calculated in powder average or as oriented lattice with domain rotation.

Additional the structure factor of atomic lattices can be calculated using atomic scattering length. Using coordinates from CIF (Crystallographic Information Format) file allow calculation of atomic crystal lattices.

## 7.1. Structure Factors

fluid like

`RMSA`(q, R, scl, gamma[, molarity, eta, useHP]) | Structure factor for a screened coulomb interaction in rescaled mean spherical approximation (RMSA).
`PercusYevick`(q, R[, molarity, eta]) | The Percus-Yevick structure factor.
`PercusYevick1D`(q[, R, eta]) | The PercusYevick structure factor in 1D
`PercusYevick2D`(q[, R, eta, a]) | The PercusYevick structure factor in 2D
`stickyHardSphere`(q, R, width, depth[, …]) | Structure factor of a square well potential with depth and width (sticky hard spheres).
`adhesiveHardSphere`(q, R, tau, delta[, …]) | structure factor of a adhesive hard sphere potential (a square well potential)
`criticalSystem`(q, corrlength, isothermalcompress) | Structure factor of a critical system should take the Ornstein-Zernike form.
`weakPolyelectrolyte`(q, cp, l, f, cs[, ioc, …]) | Monomer-monomer structure factor S(q) of a weak polyelectrolyte according to Borue and Erukhimovich [3].
`fractal`(q, clustersize, particlesize[, df]) | Structure factor of a fractal cluster of particles following Teixeira (mass fractal).

lattices

`latticeStructureFactor`(q[, lattice, …]) | Radial structure factor S(q) in powder average of a crystal lattice with particle asymmetry, DebyeWaller factor, diffusive scattering and broadening due to domain size.
`radial3DLSF`(qxyz[, lattice, domainsize, …]) | 3D structure factor S(q) in powder average of a crystal lattice with particle asymmetry, DebyeWaller factor, diffusive scattering and broadening due to domain size.
`orientedLatticeStructureFactor`(qxyz, lattice) | 2D structure factor S(q) of an oriented crystal lattice including particle asymmetry, DebyeWaller factor, diffusive scattering, domain rotation and domain size.
`radialorientedLSF`(*args, **kwargs) | Radial averaged structure factor S(q) of an oriented crystal lattice calculated as orientedLatticeStructureFactor.

## 7.2. Hydrodynamics

`hydrodynamicFunct`(wavevector, Rh, molarity) | Hydrodynamic function H(q) from hydrodynamic pair interaction of spheres in suspension.

## 7.3. Pair Correlation

`sq2gr`(Sq, R[, interpolatefactor]) | Radial distribution function g(r) from structure factor Sq.

## 7.4. Lattice

Lattices to describe atomic crystals or mesoscopic materials as ordered structures of spheres, ellipsoids, cylinders or planes in 3D (fcc, bcc, hcp, sc), 2D (hex, sq) and lamellar structures. For the later it is assumed that particles share the same normalised formfactor but allow particle specific scattering amplitude.

The small angle scattering of a nano particle build from a lattice may be calculated by `cloudScattering()` or `orientedCloudScattering()`.

The crystal structure factor of a lattice may be calculated by `latticeStructureFactor()` and related functions (see above).

Methods

`latticeFromCIF`(structure[, size, typ]) | Create lattice as defined in CIF (Crystallographic Information Format) file or a pymatgen structure.
`latticeVectorsFromLatticeConstants`(A, B, C, …) | Lattice vectors from lattice constants.

Lattices with specific structure :

3D

`bravaisLattice`(latticeVectors, size[, b]) | Create a Bravais lattice.
`scLattice`(abc, size[, b]) | Simple Cubic lattice.
`bccLattice`(abc, size[, b]) | Body centered cubic lattice.
`fccLattice`(abc, size[, b]) | Face centered cubic lattice.
`hexLattice`(ab, c, size[, b]) | Hexagonal lattice.
`hcpLattice`(ab, size[, b]) | Hexagonal closed packed lattice.
`diamondLattice`(abc, size[, b]) | Diamond cubic lattice with 8 atoms in unit cell.
`rhombicLattice`(latticeVectors, size[, …]) | Create a rhombic lattice with specified unit cell atoms.
`randomLattice`(size, numberOfPoints[, b, seed]) | Create a lattice with a random distribution of points.
`pseudoRandomLattice`(size, numberOfPoints[, …]) | Create a lattice with a pseudo random distribution of points.

2D

`sqLattice`(ab, size[, b]) | Simple 2D square lattice.
`hex2DLattice`(ab, size[, b]) | Simple 2D hexagonal lattice.

1D

`lamLattice`(a, size[, b]) | 1D lamellar lattice.

lattice methods :

`lattice.X` | X coordinates for b!=0
`lattice.Xall` | X coordinates
`lattice.Y` | Y coordinates for b!=0
`lattice.Yall` | Y coordinates
`lattice.Z` | Z coordinates for b!=0
`lattice.Zall` | Z coordinates
`lattice.XYZ` | X,Y,Z coordinates array Nx3 for b!=0
`lattice.XYZall` | X,Y,Z coordinates array Nx3
`lattice.b` | Scattering length for points with b!=0
`lattice.ball` | Scattering length all points
`lattice.array` | Coordinates and scattering length as array for b!=0
`lattice.points` | Points with scattering length !=0
`lattice.set_b`(self, b) | Set all points to given scattering length.
`lattice.set_bsel`(self, b, select) | Set b of all points (including points with b==0) according to selection.
`lattice.type` | Returns type of the lattice
`lattice.move`(self, vector) | Move all points by vector.
`lattice.centerOfMass`(self) | Center of mass as center of geometry.
`lattice.numberOfAtoms`(self) | Number of Atoms
`lattice.show`(self[, R, cmap, fig, ax, atomsize]) | Show the lattice in matplotlib with scattering length color coded.
`lattice.filter`(self, funktion) | Set lattice points scattering length according to a function.
`lattice.prune`(self, select) | Prune lattice to reduced number of points (in place)
`lattice.planeSide`(self, vector[, center, b, …]) | Set scattering length for points on one side of a plane.
`lattice.inSphere`(self, R[, center, b, invert]) | Set scattering length for points in sphere.
`lattice.inParallelepiped`(self, v1, v2, v3[, …]) | Set scattering length for points in parallelepiped.
`lattice.alongLine`(self, v, R[, a, …]) | Set scattering length for points within a long cylinder.
`rhombicLattice.unitCellAtomPositions` | Absolute positions of unit cell atoms.
`rhombicLattice.getReciprocalLattice`(self[, …]) | Reciprocal lattice of given size with peak scattering intensity.
`rhombicLattice.getRadialReciprocalLattice`(…) | Get radial distribution of Bragg peaks with unit cell structure factor and multiplicity.
`rhombicLattice.getScatteringAngle`(self[, …]) | Get scattering angle \theta=2arcsin(q_{hkl}\lambda/4\pi) in degrees.
`rhombicLattice.rotatePlane2hkl`(self, plane, hkl) | Rotate plane points that plane is perpendicular to hkl direction.
`rhombicLattice.rotatePlaneAroundhkl`(self, …) | Rotate plane points around hkl direction.
`rhombicLattice.rotatehkl2Vector`(self, hkl, …) | Rotate lattice that hkl direction is parallel to vector.
`rhombicLattice.rotateAroundhkl`(self, hkl[, …]) | Rotate lattice around hkl direction by angle or to align to vector.
`rhombicLattice.vectorhkl`(self, hkl) | Get vector corresponding to hkl direction.

Lattice objects describing a lattice of points.

Included are methods to select sublattices as parallelepiped, sphere or side of planes.

The small angle scattering is calculated by js.ff.cloudScattering.

The same method can be used to calculate the wide angle scattering with bragg peaks using larger scattering vectors to get crystalline bragg peaks of nanoparticles.

Examples

A hollow sphere cut to a wedge.

    import jscatter as js
    import numpy as np
    grid= js.lattice.scLattice(1/2.,2*8,b=[0])
    grid.inSphere(6,b=1)
    grid.inSphere(4,b=0)
    grid.planeSide([1,1,1],b=0)
    grid.planeSide([1,-1,-1],b=0)
    grid.show()

    q=js.loglist(0.01,5,600)
    ffe=js.ff.cloudScattering(q,grid.points,relError=0.02,rms=0.1)
    p=js.grace()
    p.plot(ffe)

A cube decorated with spheres.

    import jscatter as js
    import numpy as np
    grid= js.lattice.scLattice(0.2,2*15,b=[0])
    v1=np.r_[4,0,0]
    v2=np.r_[0,4,0]
    v3=np.r_[0,0,4]
    grid.inParallelepiped(v1,v2,v3,b=1)
    grid.inSphere(1,center=[0,0,0],b=2)
    grid.inSphere(1,center=v1,b=3)
    grid.inSphere(1,center=v2,b=4)
    grid.inSphere(1,center=v3,b=5)
    grid.inSphere(1,center=v1+v2,b=6)
    grid.inSphere(1,center=v2+v3,b=7)
    grid.inSphere(1,center=v3+v1,b=8)
    grid.inSphere(1,center=v3+v2+v1,b=9)
    grid.show()

    q=js.loglist(0.01,5,600)
    ffe=js.ff.cloudScattering(q,grid.points,relError=0.02,rms=0.)
    p=js.grace()
    p.plot(ffe)

A comparison of sc, bcc and fcc nanoparticles (takes a while )

    import jscatter as js
    import numpy as np
    q=js.loglist(0.01,35,1500)
    q=np.r_[js.loglist(0.01,3,200),3:40:800j]
    unitcelllength=1.5
    N=8

    scgrid= js.lattice.scLattice(unitcelllength,N)
    sc=js.ff.cloudScattering(q,scgrid.points,relError=50,rms=0.05)
    bccgrid= js.lattice.bccLattice(unitcelllength,N)
    bcc=js.ff.cloudScattering(q,bccgrid.points,relError=50,rms=0.05)
    fccgrid= js.lattice.fccLattice(unitcelllength,N)
    fcc=js.ff.cloudScattering(q,fccgrid.points,relError=50,rms=0.05)

    p=js.grace(1.5,1)
    # smooth with Gaussian to include instrument resolution
    p.plot(sc.X,js.formel.smooth(sc,10, window='gaussian'),legend='sc')
    p.plot(bcc.X,js.formel.smooth(bcc,10, window='gaussian'),legend='bcc')
    p.plot(fcc.X,js.formel.smooth(fcc,10, window='gaussian'),legend='fcc')

    q=q=js.loglist(1,35,100)
    p.plot(q,(1-np.exp(-q*q*0.05**2))/scgrid.shape[0],li=1,sy=0,le='sc diffusive')
    p.plot(q,(1-np.exp(-q*q*0.05**2))/bccgrid.shape[0],li=2,sy=0,le='bcc diffusive')
    p.plot(q,(1-np.exp(-q*q*0.05**2))/fccgrid.shape[0],li=3,sy=0,le='fcc diffusive')

    p.title('Comparison sc, bcc, fcc lattice for a nano cube')
    p.yaxis(scale='l',label='I(Q)')
    p.xaxis(scale='l',label='Q / A\S-1')
    p.legend(x=0.03,y=0.001,charsize=1.5)
    p.text('cube formfactor',x=0.02,y=0.05,charsize=1.4)
    p.text('Bragg peaks',x=4,y=0.05,charsize=1.4)
    p.text('diffusive scattering',x=4,y=1e-6,charsize=1.4)

Fluid like and crystal like structure factors (sf) and directly related functions for scattering related to interaction potentials between particles.

Fluid like include hard core SF or charged sphere sf and more. For RMSA an improved algorithm is used based on the original idea (see Notes in RMSA).

For lattices of ordered mesoscopic materials (see Lattice) the analytic sf can be calculated in powder average or as oriented lattice with domain rotation.

Additional the structure factor of atomic lattices can be calculated using atomic scattering length. Using coordinates from CIF (Crystallographic Information Format) file allow calculation of atomic crystal lattices.

`jscatter.structurefactor.` `PercusYevick`(q, R, molarity=None, eta=None)

  The Percus-Yevick structure factor.

  Structure factor for the potential U(r)= (inf for 0<r<R) and (0 for R<r).

  Parameters
    qarray; N dim

      scattering vector; units 1/(R[unit])

    Rfloat

      Radius of the object

    etafloat

      volume fraction as eta=4/3*pi*R**3*n with number density n in units or R

    molarityfloat

      number density in mol/l and defines q and R units to 1/nm and nm to be correct preferred over eta if both given

  Returns
    dataArray

      structure factor for given q

  Notes

  Problem is given in [1]; solution in [2] and best description of the solution is in [3].

  References

  1

    10. 11. Percus and G. J. Yevick, Phys. Rev. 110, 1 (1958).

  2

    13. 19. Wertheim, Phys. Rev. Lett. 10, 321 (1963).

  3

    4. 10. Kinning and E. L. Thomas, Macromolecules 17, 1712 (1984).

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 2, 200)
      p = js.grace(1,1)
      for eta in [0.005,0.01,0.03,0.05,0.1,0.2,0.3,0.4]:
          py = js.sf.PercusYevick(q, R, eta=eta)
          p.plot(py, symbol=0, line=[1, 3, -1], legend=f'eta ={eta:.3f}')
      p.yaxis(min=0.0, max=2.2, label='S(Q)', charsize=1.5)
      p.legend(x=1, y=0.9)
      p.xaxis(min=0, max=1.5)
      p.title('3D Percus-Yevick structure factor')
      #p.save(js.examples.imagepath+'/PercusYevick.jpg')

`jscatter.structurefactor.` `PercusYevick1D`(q, R=1, eta=0.1)

  The PercusYevick structure factor in 1D

  Structure factor for the potential U(r)= (inf for 0<r<R) and (0 for R<r).

  Parameters
    qarray; N dim

      scattering vector; units 1/(R[unit])

    Rfloat

      Radius of the object

    etafloat

      packing fraction as eta=2*R*n with number density n

  Returns
    dataArray

      [q,structure factor]

  References

  1

    Exact solution of the Percus-Yevick equation for a hard-core fluid in odd dimensions Leutheusser E Physica A 1984 vol: 127 (3) pp: 667-676

  2

    On the equivalence of the Ornstein–Zernike relation and Baxter’s relations for a one-dimensional simple fluid Chen M Journal of Mathematical Physics 1975 vol: 16 (5) pp: 1150

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 2, 200)
      p = js.grace(1,1)
      for eta in [0.005,0.01,0.03,0.05,0.1,0.2,0.3,0.4]:
          py = js.sf.PercusYevick1D(q, R, eta=eta)
          p.plot(py, symbol=0, line=[1, 3, -1], legend=f'eta ={eta:.3f}')
      p.yaxis(min=0.0, max=2.2, label='S(Q)', charsize=1.5)
      p.legend(x=1, y=0.9)
      p.xaxis(min=0, max=1.5)
      p.title('1D Percus-Yevick structure factor')
      #p.save(js.examples.imagepath+'/PercusYevick1D.jpg')

`jscatter.structurefactor.` `PercusYevick2D`(q, R=1, eta=0.1, a=None)

  The PercusYevick structure factor in 2D

  Structure factor for the potential U(r)= (inf for 0<r<R) and (0 for R<r).

  Parameters
    qarray; N dim

      scattering vector; units 1/(R[unit])

    Rfloat, default 1

      Radius of the object

    etafloat, default 0.1

      packing fraction as eta=pi*R**2*n with number density n maximum hexagonal closed = (np.pi*R**2)/(3/2.*3**0.5*a**2) Rmax=a*3**0.5/2. with max packing of 0.9069

    afloat, default None

      hexagonal lattice constant if not None the packing fraction in hexagonal lattice as eta=(np.pi*R**2)/(3/2.*3**0.5*a**2) is used

  Returns
    dataArray

  References

  1

    Free-energy model for the inhomogeneous hard-sphere fluid in D dimensions: Structure factors for the hard-disk (D=2) mixtures in simple explicit form Yaakov Rosenfeld Phys. Rev. A 42, 5978

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 2, 200)
      p = js.grace(1,1)
      for eta in [0.005,0.01,0.03,0.05,0.1,0.2,0.3,0.4]:
          py = js.sf.PercusYevick2D(q, R, eta=eta)
          p.plot(py, symbol=0, line=[1, 3, -1], legend=f'eta ={eta:.3f}')
      p.yaxis(min=0.0, max=2.2, label='S(Q)', charsize=1.5)
      p.legend(x=1, y=0.9)
      p.xaxis(min=0, max=1.5)
      p.title('2D Percus-Yevick structure factor')
      #p.save(js.examples.imagepath+'/PercusYevick2D.jpg')

`jscatter.structurefactor.` `RMSA`(q, R, scl, gamma, molarity=None, eta=None, useHP=False)

  Structure factor for a screened coulomb interaction in rescaled mean spherical approximation (RMSA).

  Structure factor according to Hayter-Penfold [1] [2] . Consider a scattering system consisting of macro ions, counter ions and solvent. Here an improved algorithm [Rb696f496a7a7-3] is used based on the original idea described in [1] (see Notes).

  Parameters
    qarray; N dim

      Scattering vector; units 1/nm

    Rfloat

      Radius of the object; units nm

    molarityfloat

      Number density n in units mol/l. Overrides eta, if both given.

    sclfloat>0

      Screening length; units nm; negative values evaluate to scl=0.

    gammafloat
      contact potential; units kT
      gamma=Zm/(pi*e0*e*R*(2+k*R))
      Zm = Z* effective surface charge
      e0,e free permittivity and dielectric constant
      k=1/scl inverse screening length of Debye-Hückel potential
    etafloat

      Volume fraction as eta=4/3*pi*R**3*n with number density n.

    useHPTrue, default False

      To use the original Hayter/Penfold algorithm. This gives wrong results for some parameter conditions. It should ONLY be used for testing. See example examples/test_newRMSAAlgorithm.py for a direct comparison.

  Returns
    dataArray

      - .volumeFraction = eta

      - .rescaledVolumeFraction

      - .screeningLength

      - .gamma=gamma

      - .contactpotential

      - .S0 structure factor at q=0

      - .scalingfactor factor for rescaling to get g+1=0; if =1 nothing was scaled and it is MSA

  Notes

  Improved algorithm (see [Rb696f496a7a7-3] fig. 6)

    The Python code is deduced from the original Hayter-Penfold Fortran code (1981, ILL Grenoble). This is also used in other common SAS programs as SASfit or SASview (translated to C). The original algorithm determines the root of a quartic F(w1,w2,w3,w4) by an estimate (named PW estimate), refining it by a Newton algorithm. As the PW estimate is sometimes not good enough this results in an arbitrary root of the quartic in the Newton algorithm. The solution therefore jumps between different possibilities by small changes of the parameters. We use here the original idea from [1] to calculate G(r<0) for all four roots of F(w1,w2,w3,w4) and use the physical solution with G(r<R)=0. See examples/test_newRMSAAlgorithm.py for a direct comparison or [Rb696f496a7a7-3] fig. 6.

  Validity

    The calculation of charge at the surface or screening length from a solute ion concentration is explicitly dedicate to the user. The Debye-Hückel theory for a macro ion in screened solution is a far field theory as a linearization of the Poisson-Boltzmann (PB) theory and from limited validity (far field or low charge -> linearization). Things like reverting charge layer, ion condensation at the surface, pH changes at the surface or other things might appear. Before calculating please take these things into account. Close to the surface the PB has to be solved. The DH theory can still be used if the charge is thus an effective charge named Z*, which might be different from the real surface charge. See Ref [Rb696f496a7a7-3] for details.

  References

  1(1,2,3)

    10. 2. Hayter and J. Penfold, Mol. Phys. 42, 109 (1981).

  2

    J.-P. Hansen and J. B. Hayter, Mol. Phys. 46, 651 (2006).

  3

    Jscatter, a program for evaluation and analysis of experimental data R.Biehl, PLOS ONE, 14(6), e0218789, 2019, https://doi.org/10.1371/journal.pone.0218789

  3

    12. Belloni, J. Phys. Condens. Matter 12, R549 (2000).

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 5, 200)
      p = js.grace(1,1)
      p.multi(2,1)
      for scl in [0.1,1,5,10,20]:
          rmsa = js.sf.RMSA(q, R, scl=scl, gamma=depth, eta=phi)
          p[0].plot(rmsa, symbol=0, line=[1, 2, -3], legend=f'screening length ={scl:.1f}')
      for eta in [0.01,0.05,0.1,0.2,0.3,0.4]:
          rmsa = js.sf.RMSA(q, R, scl=5, gamma=depth, eta=eta)
          p[1].plot(rmsa, symbol=0, line=[1, 2, -3], legend=f'eta ={eta:.1f}')
      p[0].yaxis(min=0.0, max=1.5, label='S(Q)', charsize=1.5)
      p[0].legend(x=1, y=0.9)
      p[0].xaxis(min=0, max=1.5)
      p[1].yaxis(min=0.0, max=2.2, label='S(Q)', charsize=1.5)
      p[1].legend(x=1.3, y=1.2)
      p[1].xaxis(min=0, max=1.5, label=r'Q / nm\S-1')
      p[0].title('RMSA structure factor')
      p[0].subtitle(f'R={R:.1f} gamma={depth:.1f} eta={phi:.2f} ')
      #p.save(js.examples.imagepath+'/rmsa.jpg')

`jscatter.structurefactor.` `adhesiveHardSphere`(q, R, tau, delta, molarity=None, eta=None)

  structure factor of a adhesive hard sphere potential (a square well potential)

  Parameters
    qarray; N dim

      scattering vector; units 1/(R[unit])

    Rfloat

      radius of the hard core

    etafloat

      volume fraction of the hard core particles

    molarityfloat

      number density in mol/l and defines q and R units to 1/nm and nm to be correct preferred over eta if both given

    taufloat

      stickiness

    deltafloat

      width of the square well

  Notes

  The potential U(r) is defined as

  U(r) &= \infty & r<2R \\ &=-depth=ln(12*tau*delta/(2R+delta)) & 2R<r<2R+width \\ &= 0 & r>2R+width

  References

  1

    3. Regnaut and J. C. Ravey, J. Chem. Phys. 91, 1211 (1989).

  2

    3. Regnaut and J. C. Ravey, J. Chem. Phys. 92 (5) (1990), 3250 Erratum

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 2, 200)
      p = js.grace(1,1)
      for eta in [0.005,0.01,0.03,0.05,0.1,0.2]:
          shs = js.sf.adhesiveHardSphere(q, R, 1, 3, eta=eta)
          p.plot(shs, symbol=0, line=[1, 3, -1], legend=f'eta ={eta:.3f}')
      p.yaxis(min=0.0, max=3.2, label='S(Q)', charsize=1.5)
      p.legend(x=1, y=3)
      p.xaxis(min=0, max=1.5)
      p.title('adhesive hard sphere structure factor')
      #p.save(js.examples.imagepath+'/adhesiveHardSphere.jpg')

`jscatter.structurefactor.` `criticalSystem`(q, corrlength, isothermalcompress)

  Structure factor of a critical system should take the Ornstein-Zernike form.

  Parameters
    qarray; N dim

      scattering vector; units 1/(R[unit])

    corrlengthfloat

      correlation length

    isothermalcompressfloat

      isothermal compressibility of the system

  Notes

  The peaking of the structure factor near Q=0 region is due to attractive interaction. Away from it the structure factor should be close to the hard sphere structure factor. Near the critical point we should find S(Q)=S_PY(Q)+S_OZ(Q) S_PY Percus Yevick structure factor S_OZ this function

  References

  1

    Analysis of Critical Scattering Data from AOT/D2O/n-Decane Microemulsions S. H. Chen, T. L. Lin, M. Kotlarchyk Surfactants in Solution pp 1315-1330

`jscatter.structurefactor.` `fractal`(q, clustersize, particlesize, df=2)

  Structure factor of a fractal cluster of particles following Teixeira (mass fractal).

  To include the shape/structure of a particle with formfactor F(q) use S(q)*F(q) with particlesize related to the specific formfactor.

  Parameters
    qarray

      Wavevectors in units 1/nm.

    clustersizefloat

      Clustersize \xi in units nm. May be correlated to Rg (see Notes). From [1]: The meaning of \xi is only qualitative and has to be made precise in any particular situation. Generally speaking, it represents the characteristic distance above which the mass distribution in the sample is no longer described by the fractal law. In practice, it can represent the size of an aggregate or a correlation length in a disordered material.

    particlesizefloat

      Particle size in units nm. In [1] it is described as characteristic dimension of individual scatterers. See Notes.

    dffloat, default=2

      Hausdorff dimension, d_f defined as the exponent of the linear dimension R in the relation M(R) \propto (R/r_0)^{d_f} where M represents the mass and r_0 is the gauge of measurement. See [1].

  Returns
    dataArray[q, Sq]
      input parameters as attributes

        - .Rg Rg = d_f(d_f+1) \xi^2/2 See [1] after equ. 17

        - .Sq0 S(q=0) = 1 + (\xi/r_0)^{d_f} \Gamma(d_f+1) see [1] equ. 17

  Notes

  - The structure factor [1] equ 16 is

    S(q) = 1 + \frac{d_f\ \Gamma\!(d_f-1)}{[1+1/(q \xi)^2\ ]^{(d_f -1)/2}} \frac{\sin[(d_f-1) \tan^{-1}(q \xi) ]}{(q R_0)^{d_f}}

  - At large q the unity term becomes dominant and we get S(q)=1. Accordingly the formfactor of the particles becomes visible.

  - At intermediate q \xi^{-1} < q < r_0^{-1} the structure factor reduces to S(q)=q^{-d_f}

  - The radius of gyration is related to the cluster size \xi as Rg = d_f(d_f+1) \xi^2/2 See [1] after equ. 17.

  - According to [1] the particlesize relates to a characteristic dimension of the particles. The particlesize determines the intersection of the extrapolated power law region with 1 thus the region where the particle structure gets important. The particlesize can be something like the radius of gyration of a Gaussian or collapsed chain, a sphere radius or the mean radius of a protein. It might also be the clustersize of a fractal particle.

  - In SASview the particlesize is related to the radius of aggregating spheres (or core shell sphere) including a respective formfactor.

  References

  1(1,2,3,4,5,6,7,8)

    Small-Angle Scattering by Fractal Systems J. Teixeira, J. Appl. Cryst. (1988). 21,781-785

  Examples

  Here a fractal structure of a cluster of spheres is shown. The size of the spheres is the particlesize on the cluster. The typical scheme I(q)=P(q)S(Q) with particle formfactor P(q) and structure factor S(Q) is used. The volume and contrast is included in P(q). Add a background if needed or use a different particle as core-shell sphere.

      import jscatter as js
      import numpy as np
      q=js.loglist(0.01,5,300)

      p=js.grace(1.5,1)
      p.multi(1,2)
      clustersize = 20
      particlesize = 2

      fq=js.ff.sphere(q,particlesize)
      for df in np.r_[0:3:7j]:
          Sq=js.sf.fractal(q, clustersize, particlesize, df=df)
          p[0].plot(Sq,le=f'df={df:.2f}')
          p[1].plot(Sq.X,Sq.Y*fq.Y,li=-1,le=f'df={df:.2f}')

      p[0].yaxis(scale='log',label='I(q) ',min=0.1,max=1e4)
      p[0].xaxis(scale='log',min=0.01,max=4,label='q / nm\S-1')
      p[0].title(r'Fractal structure factor')
      p[0].subtitle('df is fractal dimension')
      p[0].legend(x=0.5,y=1000)
      p[1].yaxis(scale='log',min=0.1,max=1e8,label=['I(q)',1.0,'opposite'],ticklabel=['power',0,1,'opposite'])
      p[1].xaxis(scale='log',min=0.01,max=4,label='q / nm\S-1')
      p[1].title(r'Fractal structure factor of spheres')
      p[1].subtitle('sphere formfactor is added')
      p[1].legend(x=0.5,y=1e7)
      #p.save(js.examples.imagepath+'/fractalspherecluster.png')

`jscatter.structurefactor.` `hydrodynamicFunct`(wavevector, Rh, molarity, intrinsicVisc=None, DsoverD0=None, structureFactor=None, structureFactorArgs=None, numberOfPoints=50, ncpu=- 1)

  Hydrodynamic function H(q) from hydrodynamic pair interaction of spheres in suspension.

  This allows the correction D_T(q)=D_{T0}H(q)/S(q) for the translational diffusion D_T(q) coefficient at finite concentration. We use the theory from Beenakker and Mazur [2] as given by Genz [1]. The \delta\gamma-expansion of Beenakker expresses many body hydrodynamic interaction within the renormalization approach dependent on the structure factor S(q).

  Parameters
    wavevectorarray

      scattering vector q in units 1/nm

    Rhfloat

      effective hydrodynamic radius of particles in nm.

    molarityfloat
      molarity in mol/l
      This overrides a parameter ‘molarity’ in the structureFactorArgs.
      Rh and molarity define the hydrodynamic interaction, the volume fraction and Ds/D0 for H(Q).
      The structure factor may have a radius different from Rh e.g. for attenuated hydrodynamic interactions.
    DsoverD0float
      The high Q limit of the hydrodynamic function is for low volume fractions
      Ds/D0= 1/(1+intrinsicVisc * volumeFraction ) with self diffusion Ds.
      Ds is calculated from molarity and Rh.
      This explicit value overrides intrinsic viscosity and calculated Ds/D0.
    structureFactorfunction, None
      Structure factor S(q) with S(q=inf)=1.0 recommended.
      1: If structurefactor is None a Percus-Yevick is assumed with molarity and R=Rh.
      2: A function S(q,…) is given as structure factor, which might be an
      empirical function (e.g. polynominal fit of a measurement)
      First parameter needs to be wavevector q .
      If “molarity” parameter is present it is overwritten by molarity above.
    structureFactorArgsdictionary

      Any extra arguments to structureFactor e.g. structFactorArgs={‘x’:0.123,R=3,….}

    intrinsicViscfloat
      Defines the high q limit for the hydrodynamic function.
      effective_viscosity= eta_solvent * (1-intrinsicVisc*Volumefraction )
      intrinsicVisc = 2.5 Einstein hard sphere density 1 g/cm**3
      For proteins instead of volume fraction the protein concentration in g/ml with typical
      protein density 1.37 g/cm^3 is often used.
      Intrinsic Viscosity depends on protein shape (see HYDROPRO).
      Typical real values for intrinsicVisc in practical units cm^3/g
      sphere 1.76 cm^3/g= 2.5 sphere with protein density
      ADH 3.9 = 5.5 a tetrameric protein
      PGK 4.0 = 5.68 two domains with hinge-> elongated
      Rnase 3.2 = 4.54 one domain
      eta_solvent/effective_viscosity = (1-intrinsicVisc * Volumefraction )=Dself/D0
    numberOfPointsinteger, default 50

      Determines number of integration points in equ 5 of ref [1] and therefore accuracy of integration. The typical accuracy of this function is <1e-4 for (H(q) -highQLimit) and <1e-3 for Ds/D0.

    ncpuint, optional
      Number of cpus in the pool.

        - not given or 0 -> all cpus are used

        - int>0 min (ncpu, mp.cpu_count)

        - int<0 ncpu not to use

  Returns
    dataArray
      Columns [q, HydDynFun, DsoverD0, structureFactor]

        - q values

        - hydrodynamic function

        - hydrodynamic function only Q dependent part = H(q) -highQLimit

        - structure factor for H(q) calculation

        - .selfdiffusion Ds

  Notes

  Ds is calculated according to equ 11 in [1] which is valid for volume fractions up to 0.5. With this assumption the deviation of self diffusion Ds from Ds=Do*[1-1.73*phi+0.88*phi**2+ O(phi**3)] is smaller 5% for phi<0.2 (10% for phi<0.3)

  References

  1(1,2,3)

    21. Genz and R. Klein, Phys. A Stat. Mech. Its Appl. 171, 26 (1991).

  2

    3. 23. 10. Beenakker and P. Mazur, Phys. A Stat. Mech. Its Appl. 126, 349 (1984).

  3

    3. 23. 10. Beenakker and P. Mazur, Phys. A Stat. Mech. Its Appl. 120, 388 (1983).

`jscatter.structurefactor.` `latticeStructureFactor`(q, lattice=None, domainsize=1000, asym=0, lg=1, rmsd=0.02, beta=None, hklmax=7, c=1.0, wavelength=None, corrections=[])

  Radial structure factor S(q) in powder average of a crystal lattice with particle asymmetry, DebyeWaller factor, diffusive scattering and broadening due to domain size.

  To get the full scattering the formfactor needs to be included (See Notes and Examples). 1-3 dimensional lattice structures with basis containing multiple atoms (see lattice). Self absorption and self extinction are not included. Polarisation and Lorentz correction are optional.

  Parameters
    qarray float

      Norm of wavevectors in inverse units of lattice constant, units 1/nm

    domainsizefloat

      Domainsize of the crystal, units as lattice constant of lattice. According to Debye-Scherrer equation fwhm=2\pi/domainsize the peak width is determined [2].

    latticelattice object

      The crystal structure as defined in a lattice object. The size of the lattice is ignored. One of rhombicLattice, bravaisLattice, scLattice, bccLattice, fccLattice, diamondLattice, hexLattice, hcpLattice. See respective definitions.

    lgfloat, default = 1

      Lorenzian/gaussian fraction describes the contributions of gaussian and lorenzian shape in peak shape (Voigt function).

      > - lorenzian/gaussian >> 1 lorenzian,

      > - lorenzian/gaussian ~ 1 central part gaussian, outside lorenzian wings

      > - lorenzian/gaussian << 1 gaussian

    asymfloat, default=0

      Asymmetry factor in sigmoidal as 2fwhm/(1+e^{asym*(x-center)}) For asym=0 the Voigt is symmetric with fwhm. See formel.voigt .

    rmsdfloat, default=0.02

      Root mean square displacement rmsd=<u^2>^{0.5} determining the Debye Waller factor. Units as domainsize and lattice units. Here Debye Waller factor is used as DW(q)=e^{-q^2 rmsd^2 }

    betafloat, None, dataArray
      Asymmetry factor of the formfactor or reduction due to polydispersity.

        - None beta=1, No beta assumed (spherical symmetric formfactor, no polydispersity)

        - dataArray explicitly given as dataArray with beta in .Y column. Missing values are interpolated.

        - An approximation for polydisperse beta can be found in [1] equ.17. This can be realized by beta=js.dA(np.vstack(q,np.exp(-(q*sr*R)**2))) with sr as relative standard deviation of gaussian distribution of the size R.

        - See .formfactor for different formfactors which explicit calculation of beta.

    hklmaxint

      Maximum order of the Bragg peaks to include.

    cfloat, default=1

      Porod constant. See 3.8 in [1].

    wavelengthfloat, default = None

      Wavelength of the measurement in units nm. If None .Braggtheta is not calculated. For Xray Cu K_a it is 0.15406 nm.

    correctionslist, default=[]

      List of corrections to apply, which depend on the measurement type/geometry [5]. \theta is here the scattering angle (not 2\theta as in diffraction is used)

      > - ‘TP’ Thompson polarisation correction (1+cos^2(\theta)/2) for electromagnetic scattering as Xrays [4]. For small angle scattering this is negligible but valid. For polarised beams the polarisation has to be included.

      > - ‘lh’ likelihood of a crystallite being in diffraction position cos(\theta/2).

      > - ‘LC’ Lorentz correction \sin(\theta)^{-1} due to integration

      >     over the width of reciprocal Bragg peaks due to lattice imperfections and the width of the incoming beam. Use for Debye-Scherrer (powder of crystallites) diffraction.

      > - ‘area’ the intensity for a given diffraction peak is recorded on a narrow strip of

      >     photographic film instead of over the entire diffraction cone \sin(\theta)^{-1}.

      > - ‘all’ common Lorentz and polarisation correction powder measurements of crystalline material.

      >     Use all from above. NOT for flat transmission geometry (typical SAS) or non crystallite .

      >   Corresponds to (1+cos^2(\theta)/2)/sin^2(\theta/2)/sin(\theta/2).

      The correction for the pixel area presented to scattering solid angle is included in sasImage in 2D also correcting for offset detector positions of a flat detector, which cannot use the scattering angle \theta as the geometry changes.

  Returns
    dataArray
      Columns [q, Sq, DW, beta, Z0q, correction, theta]

        - q wavevector

        - Sq = S(q) = (1+beta(q)*(Z0(q)-1)*DW(q))*correction structure factor

        - DW(q) Debye-Waller factor with (1-DW)=diffusive scattering.

        - beta(q) asymmetry factor of the formfactor.

        - Z0q lattice factor Z0(q)

        optional - correction [optional] factor polarisation from Thompson scattering - theta scattering angle

      Attributes

        - .q_hkl peak positions

        - .fhkl symmetry factor

        - .mhkl multiplicity

        - .Braggtheta Bragg angles

  Notes

  Analytical expressions for the scattering functions of atomic crystals and ordered mesoscopic materials . Ordered structures in 3D (fcc, bcc, hcp, sc), 2D (hex, sq) and lamellar structures are considered. The expressions take into account particle size distributions and lattice point deviations, domain size, core/shell structures, as well as peak shapes varying analytically between Lorentzian and Gaussian functions. The expressions allow one to quantitatively describe high-resolution synchrotron small-angle X-ray (SAXS) and neutron scattering (SANS) curves from lipid and block copolymer lyotropic phases, core/shell nanoparticle superstructures, ordered nanocomposites, ordered mesoporous materials and atomic crystal structures (see AgBe example).

  - The scattering intensity of a crystal domain in powder average is

    I(q)={\Delta\rho}^2 n P(q) S(q)

    with

      - \Delta\rho scattering length difference between matrix and particles

      - n number density (of elementary cells)

      - P(q) form factor

      - S(q) structure factor S(q)

    For inhomogeneous particles or atoms with different scattering length we can incorporate \Delta\rho(r) in the formfactor P(q) if this includes the integrated scattering length differences.

  - The structure factor is [1] :

    S(q)=1+ \beta(q)(Z_0(q)-1)*DW(Q)

    with

      - \beta(q)=<F(q)>^2/<F(q)^2> as asymmetry factor [3] dependent on the scattering amplitude F(q) and particle polydispersity

      - DW(q) Debye Waller factor

  - The lattice factor is [1] :

    Z_0(q) = \frac{(2\pi)^{d-1}c}{nv_dq^{d-1}} \sum\limits_{hkl}m_{hkl}f_{hkl}^2L_{hkl}(q)

    with

      - n number of particles per unit cell

      - f_{hkl} unit cell structure factor that takes into account symmetry-related extinction rules

      - v_d volume of the d-dimensional unit cell

      - hkl reflections

      - m_{hkl} peak multiplicity

      - c Porod constant \simeq 1

  - Unit cell structure factors f_{hkl} are normalised that the lattice factor is normalised for infinite q to 1. With i as unit cell atoms at fractional position in the unit cell [x_i,y_i,z_i] and scattering amplitude b_i we get :

    f_{hkl}^2 = \big(\sum_i b_i e^{-2\pi (hx_i+ky_i+lz_i)}\big)^2 / \sum_i b_i^2

  - We use a Voigt function for the peak shape L_{hkl}(q) (see formel.voigt).

  - DW is a Debye Waller like factor as DW(q)=e^{-q^2<u^2>} leading to a reduction of scattered intensity and diffusive scattering. It has contributions from thermal lattice disorder ( DW factor with 1/3 factor in 3D), surface roughness and size polydispersity.

  - For the limiting behaviour q->0 see the discussion in [1] in 3.9. :

      “… The zero-order peak is not explicitly considered because of the q^(1-dim) singularity and because its intensity depends also on the scattering length difference between the lattice inside and outside… Due to the singularity and since structural features on length scales d > a, such as packing defects, grain boundaries or fluctuations decaying on larger length scales are only indirectly considered via the domain size D, eq 30 is not expected to give good agreement with experimentally determined scattering curves in the range of scattering vectors q < 2π/a. However, for q > 2π/a, this approach describes remarkably well experimentally measured high-resolution scattering curves….”

    A good description of the real scattering for low Q is shown in example A nano cube build of different lattices.

  References

  1(1,2,3,4,5)

    Scattering curves of ordered mesoscopic materials. Förster, S. et al. J. Phys. Chem. B 109, 1347–1360 (2005).

  2

    Patterson, A. The Scherrer Formula for X-Ray Particle Size Determination Phys. Rev. 56 (10): 978–982 (1939) doi:10.1103/PhysRev.56.978.

  3

    13. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).1

  4

    https://en.wikipedia.org/wiki/Thomson_scattering

  5

    Modern Physical Metallurgy chapter 5 Characterization and Analysis R.E.SmallmanA.H.W.Ngan https://doi.org/10.1016/B978-0-08-098204-5.00005-5

  Examples

  Structure factor for hexagonal lattice dependent on rmsd

      import jscatter as js
      import numpy as np
      q = np.r_[0.02:1:800j]
      a = 50.
      R=15
      sr=0.1
      p = js.grace()
      beta=js.dA(np.vstack([q,np.exp(-(q*sr*R)**2)]))
      p.title('structure factor for hexagonal 2D lattice with a={0} nm'.format(a))
      p.subtitle('with diffusive scattering and asymmetry factor beta')
      for i,rmsd in enumerate([1., 3., 10., 30.],1):
          grid=js.sf.scLattice(50,5)
          hex = js.sf.latticeStructureFactor(q, rmsd=rmsd, domainsize=500., beta=beta,lattice=grid)
          p.plot(hex, li=[1, 2, i], sy=0, le='rmsd=$rmsd')
          p.plot(hex.X,1-hex._DW, li=[3, 2, i], sy=0)
      p.plot(hex.X, hex._beta, li=[2, 2, i], sy=0, le='beta')
      p.text(r'broken lines \nshow diffusive scattering',x=0.4,y=6)
      p.yaxis(label='S(q)')
      p.xaxis(label='q / nm')
      p.legend(x=0.6,y=4)

  Comparison of sc, bcc, fcc for same cubic unit cell size to demonstrate selection rules.

      import jscatter as js
      import numpy as np
      q=np.r_[js.loglist(0.1,3,200),3:40:800j]
      unitcelllength=1.5
      N=2
      R=0.5
      sr=0.1
      beta=js.dA(np.vstack([q,np.exp(-(q*sr*R)**2)]))
      rmsd=0.02
      #
      scgrid= js.lattice.scLattice(unitcelllength,N)
      sc=js.sf.latticeStructureFactor(q, rmsd=rmsd, domainsize=50., beta=beta,lattice=scgrid)
      bccgrid= js.lattice.bccLattice(unitcelllength,N)
      bcc=js.sf.latticeStructureFactor(q, rmsd=rmsd, domainsize=50., beta=beta,lattice=bccgrid)
      fccgrid= js.lattice.fccLattice(unitcelllength,N)
      fcc=js.sf.latticeStructureFactor(q, rmsd=rmsd, domainsize=50., beta=beta,lattice=fccgrid)
      #
      p=js.grace()
      p.plot(sc,legend='sc')
      p.plot(bcc,legend='bcc')
      p.plot(fcc,legend='fcc')
      p.yaxis(label='S(q)',scale='l',max=50,min=0.05)
      p.xaxis(label='q / nm',scale='l',max=50,min=0.5)
      p.legend(x=1,y=30,charsize=1.5)
      # p.save(js.examples.imagepath+'/latticeStructureFactor2.jpg')

  A realistic example of a calibration measurement with AgBe. We load the cif file of the crystal structure to build the lattice and find good agreement. According to materialsproject.org calculated XRD tends to underestimate lattice parameters. For AgBe the first peak is found at 1.07

      import jscatter as js
      #
      # Look at raw calibration measurement
      calibration = js.sas.sasImage(js.examples.datapath+'/calibration.tiff')
      bc=calibration.center
      calibration.mask4Polygon([bc[0]+8,bc[1]],[bc[0]-8,bc[1]],[bc[0]-8+60,0],[bc[0]+8+60,0])
      # mask center
      calibration.maskCircle(calibration.center, 18)
      # mask outside shadow
      calibration.maskCircle([500,320], 280,invert=True)
      # calibration.show(axis='pixel',scale='log')
      cal=calibration.radialAverage()
      # lattice from crystallographic data in cif file.
      agbe=js.sf.latticeFromCIF(js.examples.datapath + '/1507774.cif',size=[0,0,0])
      sfagbe=js.sf.latticeStructureFactor(cal.X, lattice=agbe,
                                         domainsize=50, rmsd=0.001, lg=1, hklmax=17,wavelength=0.15406)

      p=js.grace()
      p.plot(cal)
      # add scaling and background (because of unscaled raw data)
      p.plot(sfagbe.X,190*sfagbe.Y+1.9,sy=0,li=[1,3,4])
      p.yaxis(scale='log',label='I(q) / counts/pixel')
      p.xaxis(scale='log',label='q / nm|S-1',min=0.7,max=20)
      p.title('AgBe reference measurements')
      # p.save(js.examples.imagepath+'/latticeStructureFactor.jpg')

`jscatter.structurefactor.` `orientedLatticeStructureFactor`(qxyz, lattice, rotation=None, domainsize=1000, rmsd=0.02, beta=None, hklmax=3, nGauss=13, ncpu=0, wavelength=None, corrections=[])

  2D structure factor S(q) of an oriented crystal lattice including particle asymmetry, DebyeWaller factor, diffusive scattering, domain rotation and domain size.

  To get the full scattering the formfactor needs to be included (See Notes and Examples). 1-3 dimensional lattice structures with basis containing multiple atoms (see lattice). To orient the crystal lattice use lattice methods .rotatehkl2Vector and .rotateAroundhkl

  Parameters
    qxyzarray 3xN

      Wavevector array representing a slice/surface in q-space (3D), units 1/A or 1/nm. This can describe a detector plane, section of the Ewald sphere or a line in reciprocal space.

    latticelattice object

      Lattice object with arbitrary atoms particles in unit cell, or predefined lattice from rhombicLattice, bravaisLattice, scLattice,bccLattice, fccLattice, diamondLattice, hexLattice, hcpLattice with scattering length of unit cell atoms. See lattices for examples.

    rotation4x float as [h,k,l,sigma], None

      Average over rotation of the crystal around axis hkl with Gaussian distribution of width sigma (units rad) around actual orientation.

    domainsizefloat,list, list of directions

      Domainsize of the crystal, units as lattice constant of lattice. According to Debye-Scherrer equation fwhm=2\pi/domainsize the peak width is determined [2].

      > - float : assume same domainsize in all directions.

      > - list 3 float : domainsize in directions of latticeVectors.

      > - list 4 x 33 times domainsize in hkl direction as [[size,h,k,l] ,[..],[..] ]

      >     [[3,1,1,1],[100,1,-1,0],[100,1,1,-2]] is thin in 111 direction and others are thick The user should take care that the directions are nearly orthogonal.

    rmsdfloat, default=0.02

      Root mean square displacement <u^2>^{0.5} determining the Debye Waller factor. Units as lattice constant.

    betafloat, None, dataArray
      Asymmetry factor of the formfactor or reduction due to polydispersity.

        - None beta=1, No beta assumed (spherical symmetric formfactor, no polydispersity)

        - dataArray beta explicitly given as dataArray with beta in .Y column. Missing values are interpolated.

        - An approximation for polydisperse beta can be found in [1] equ.17. This can be realized by beta=js.dA(np.vstack(q,np.exp(-(q*sr*R)**2))) with sr as relative standard deviation of gaussian distribution of the size R.

        - See .formfactor for different formfactors which explicit calculation of beta.

    hklmaxint

      Maximum order of the Bragg peaks.

    wavelengthfloat, default = None

      Wavelength of the measurement in units nm. For Xray Cu K_a it is 0.15406 nm.

    correctionslist, default=[]

      List of corrections to apply, which depend on the measurement type/geometry. See `latticeStructureFactor()`

    nGaussint, default 13

      Number of points in integration over Gaussian for rotation width sigma.

    ncpuint, optional

      Number of cpus in the pool. Set this to 1 if the integrated function uses multiprocessing to avoid errors.

      > - not given or 0 -> all cpus are used

      > - int>0 min (ncpu, mp.cpu_count)

      > - int<0 ncpu not to use

  Returns
    dataArray
      Columns [qx,qy,qz,Sq,DW,beta,Z0q]

        - q wavevector

        - Sq = S(q) = (1+beta(q)*(Z0(q)-1)*DW(q))*correction structure factor

        - DW(q) Debye-Waller factor with (1-DW)=diffusive scattering.

        - beta(q) asymmetry factor of the formfactor.

        - Z0q lattice factor Z0(q)

      optional

        - correction [optional] factor polarisation from Thompson scattering

        - theta scattering angle

      Attributes (+ input parameters)

        - .q_hkl peak positions

        - .hkl Miller indices

        - .peakFWHM full width half maximum

  Notes

  - The scattering intensity of a crystal domain is

    I(q)={\Delta\rho}^2 n P(q) S(q)

    with

      - \Delta\rho scattering length difference between matrix and particles

      - n number density (of elementary cells)

      - P(q) form factor

      - S(q) structure factor S(q)

    For inhomogeneous particles we can incorporate \Delta\rho(r) in the formfactor P(q) if this includes the integrated scattering length differences.

  - The structure factor is [1] :

    S(q)=1+ \beta(q)(Z_0(q)-1)*DW(Q)

    with

      - \beta(q)=<F(q)>^2/<F(q)^2> as asymmetry factor [3] dependent on the scattering amplitude F(q) and particle polydispersity

      - DW(q) Debye Waller factor

  - The lattice factor is [1] :

    Z_0(q) = \frac{(2\pi)^3}{mv} \sum\limits_{hkl}f_{hkl}^2L_{hkl}(q,g_{hkl})

    with

      - g_{hkl} peak positions

      - m number of particles per unit cell

      - f_{hkl} unit cell structure factor that takes into account symmetry-related extinction rules

      - v volume of the unit cell

      - hkl reflections

  - Unit cell structure factors f_{hkl} are normalised that the lattice factor is normalised for infinite q to 1. With i as unit cell atoms at fractional position in the unit cell [x_i,y_i,z_i] and scattering amplitude b_i we get :

    f_{hkl}^2 = \big(\sum_i b_i e^{-2\pi (hx_i+ky_i+lz_i)}\big)^2 / \sum_i b_i^2

  - The peak shape function is

    L_{hkl}(q,g_{hkl}) = \frac{1}{ \sqrt{2\pi} \sigma} e^{-\frac{(q-g_{hkl})^2}{2\sigma^2}}

    with \sigma=fwhm/2\sqrt{2log(2)} related to the domainsize.

    Correspondingly \sigma is a vector describing the peak shapes in all directions.

  - Distributions of domain orientation are included by the parameter rotation that describes gaussian distributions with mean and sigma around an axis defined by the corresponding hkl indices.

  - DW is a Debye Waller like factor as DW(q)=e^{-q^2<u^2>} leading to a reduction of scattered intensity and diffusive scattering. It has contributions from thermal lattice disorder ( DW factor with 1/3 factor in 3D).

  - To get the scattering of a specific particle shape the formfactor has to be included. The above is valid for isotropic scatterers (symmetric or uncorrelated to the crystal orientation) as only in this case we can separate structure factor and form factor.

  References

  1(1,2,3)

    Order causes secondary Bragg peaks in soft materials Förster et al Nature Materials doi: 10.1038/nmat1995

  2

    Patterson, A. The Scherrer Formula for X-Ray Particle Size Determination Phys. Rev. 56 (10): 978–982 (1939) doi:10.1103/PhysRev.56.978.

  3

    13. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).1

  Examples

  Comparison fcc and sc to demonstrate selection rules

      import jscatter as js
      import numpy as np
      R=8
      N=50
      ds=10
      fcclattice= js.lattice.fccLattice(3.1, 5)
      qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
      qxyz=np.c_[qxy,np.zeros(qxy.shape[0])].T
      fcclattice.rotatehkl2Vector([1,1,1],[0,0,1])
      ffe=js.sf.orientedLatticeStructureFactor(qxyz,fcclattice,domainsize=ds,rmsd=0.1,hklmax=4)
      fig=js.mpl.surface(ffe.X,ffe.Z,ffe.Y)
      sclattice= js.lattice.scLattice(3.1, 5)
      sclattice.rotatehkl2Vector([1,1,1],[0,0,1])
      ffs=js.sf.orientedLatticeStructureFactor(qxyz,sclattice,domainsize=ds,rmsd=0.1,hklmax=4)
      fig=js.mpl.surface(ffs.X,ffs.Z,ffs.Y)

  Comparison of different domainsizes dependent on direction of scattering

      import jscatter as js
      import numpy as np
      R=8
      N=50
      qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
      qxyz=np.c_[qxy,np.zeros(qxy.shape[0])].T
      sclattice= js.lattice.scLattice(2.1, 5)
      sclattice.rotatehkl2Vector([1,0,0],[0,0,1])
      ds=[[20,1,0,0],[5,0,1,0],[5,0,0,1]]
      ffs=js.sf.orientedLatticeStructureFactor(qxyz,sclattice,domainsize=ds,rmsd=0.1,hklmax=2)
      fig=js.mpl.surface(ffs.X,ffs.Z,ffs.Y)
      fig.axes[0].set_title('symmetric peaks: thinner direction perpendicular to scattering plane')
      fig.show()
      sclattice= js.lattice.scLattice(2.1, 5)
      sclattice.rotatehkl2Vector([0,1,0],[0,0,1])
      ffs=js.sf.orientedLatticeStructureFactor(qxyz,sclattice,domainsize=ds,rmsd=0.1,hklmax=2)
      fig2=js.mpl.surface(ffs.X,ffs.Z,ffs.Y)
      fig2.axes[0].set_title('asymmetric peaks: thin direction is parallel to scattering plane')
      fig2.show()

  Rotation along [1,1,1] axis. It looks spiky because of low number of points in xy plane. To improve this the user can use more points, which needs longer computing time

      import jscatter as js
      import numpy as np
      # make xy grid in q space
      R=8    # maximum
      N=800  # number of points
      ds=15;
      qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
      # add z=0 component
      qxyz=np.c_[qxy,np.zeros(qxy.shape[0])].T # as position vectors
      # create sc lattice which includes reciprocal lattice vectors and methods to get peak positions
      sclattice= js.lattice.scLattice(2.1, 5)
      # Orient 111 direction perpendicular to qxy plane
      sclattice.rotatehkl2Vector([1,1,1],[0,0,1])
      # rotation by 15 degrees to be aligned to xy plane
      sclattice.rotateAroundhkl([1,1,1],np.deg2rad(15))
      ffs=js.sf.orientedLatticeStructureFactor(qxyz,sclattice, rotation=[1,1,1,np.deg2rad(10)],
                                              domainsize=ds,rmsd=0.1,hklmax=2,nGauss=23)
      fig=js.mpl.surface(ffs.X,ffs.Z,ffs.Y)
      #fig.savefig(js.examples.imagepath+'/orientedlatticeStructureFactor.jpg')

`jscatter.structurefactor.` `radial3DLSF`(qxyz, lattice=None, domainsize=1000, asym=0, lg=1, rmsd=0.02, beta=None, hklmax=7, c=1.0, wavelength=None, corrections=[])

  3D structure factor S(q) in powder average of a crystal lattice with particle asymmetry, DebyeWaller factor, diffusive scattering and broadening due to domain size.

  The qxyz can be an arbitrary composition of points in reciprocal space. Uses latticeStructureFactor. The peak shape is a Voigt function.

  Parameters
    qxyz3xN array

      Wavevector plane in inverse units of lattice constant, units 1/A or 1/nm.

    domainsizefloat

      Domainsize of the crystal, units as lattice constant of lattice. According to Debye-Scherrer equation fwhm=2\pi/domainsize the peak width is determined [2].

    latticelattice object

      The crystal structure as defined in a lattice object. The size of the lattice is ignored. One of rhombicLattice, bravaisLattice, scLattice, bccLattice, fccLattice, diamondLattice, hexLattice, hcpLattice. See respective definitions.

    lgfloat, default = 1
      Lorenzian/gaussian fraction describes the contributions of gaussian and lorenzian shape in peak shape.

        - lorenzian/gaussian >> 1 lorenzian,

        - lorenzian/gaussian ~ 1 central part gaussian, outside lorenzian wings

        - lorenzian/gaussian << 1 gaussian

    asymfloat, default=0

      Asymmetry factor in sigmoidal as 2fwhm/(1+e^{asym*(x-center)}) For asym=0 the Voigt is symmetric with fwhm. See formel.voigt .

    rmsdfloat, default=0.02

      Root mean square displacement rmsd=<u^2>^{0.5} determining the Debye Waller factor. Units as domainsize and lattice units. Here Debye Waller factor is used as DW(q)=e^{-q^2 rmsd^2 }

    betafloat, None, dataArray
      Asymmetry factor of the formfactor or reduction due to polydispersity.

        - None beta=1, No beta assumed (spherical symmetric formfactor, no polydispersity)

        - dataArray explicitly given as dataArray with beta in .Y column. Missing values are interpolated.

        - An approximation for polydisperse beta can be found in [1] equ.17. This can be realized by beta=js.dA(np.vstack(q,np.exp(-(q*sr*R)**2))) with sr as relative standard deviation of gaussian distribution of the size R.

        - See .formfactor for different formfactors which explicit calculation of beta.

    hklmaxint

      Maximum order of the Bragg peaks to include.

    cfloat, default=1

      Porod constant. See 3.8 in [1].

    wavelengthfloat, default = None

      Wavelength of the measurement in units nm. If None .Braggtheta is not calculated. For Xray Cu K_a it is 0.15406 nm.

    correctionslist, default=[]

      List of corrections to apply, which depend on the measurement type/geometry. See `latticeStructureFactor()`

  Returns
    dataArray
      Columns [qx,qz,qw,Sq]

        - Sq = S(q) = 1+beta(q)*(Z0(q)-1)*DW(q) structure factor

      Attributes

        - .q_hkl peak positions

        - .fhkl symmetry factor

        - .mhkl multiplicity

  Notes

  See latticeStructureFactor.

  References

  1(1,2)

    Scattering curves of ordered mesoscopic materials. Förster, S. et al. J. Phys. Chem. B 109, 1347–1360 (2005).

  2

    Patterson, A. The Scherrer Formula for X-Ray Particle Size Determination Phys. Rev. 56 (10): 978–982 (1939) doi:10.1103/PhysRev.56.978.

  3

    13. Kotlarchyk and S.-H. Chen, J. Chem. Phys. 79, 2461 (1983).1

  Examples

      import jscatter as js
      import numpy as np
      import matplotlib.pyplot as pyplot
      from matplotlib import cm
      from matplotlib import colors
      norm=colors.LogNorm(clip=True)

      # create lattice
      sclattice = js.lattice.scLattice(2.1, 1)
      ds = 50

      # add flat detector xy plane
      xzw = np.mgrid[-8:8:500j, -8:8:500j]

      qxzw = np.stack([np.zeros_like(xzw[0]), xzw[0], xzw[1]], axis=0)
      ff1 = js.sf.radial3DLSF(qxzw.reshape(3, -1).T, sclattice, domainsize=ds, rmsd=0.03, hklmax=7)
      norm.autoscale(ff1.Y)
      fig = pyplot.figure()
      ax = fig.add_subplot(1, 1, 1)
      im = ax.imshow(ff1.Y.reshape(500,-1),norm=norm)
      fig.colorbar(im, shrink=0.8)
      js.mpl.show()

  Note that for to low number of points in the xzw plane moire patterns appear.

      import jscatter as js
      import numpy as np

      import matplotlib.pyplot as pyplot
      from matplotlib import cm

      # Set the aspect ratio to 1 so our sphere looks spherical
      fig = pyplot.figure(figsize=pyplot.figaspect(1.))
      ax = fig.add_subplot(111, projection='3d')

      # create lattice
      sclattice = js.lattice.scLattice(2.1, 1)
      ds = 50

      # add flat detector xy plane
      xzw = np.mgrid[-8:8:250j, -8:8:250j]

      qxzw = np.stack([np.zeros_like(xzw[0]), xzw[0], xzw[1]], axis=0)
      ff1 = js.sf.radial3DLSF(qxzw.reshape(3, -1).T, sclattice, domainsize=ds, rmsd=0.03, hklmax=7)
      ffs1 = ff1.Y # np.log(ff1.Y)
      fmax, fmin = ffs1.max(), ffs1.min()
      ff1Y = (np.reshape(ffs1, xzw[0].shape) - fmin) / (fmax - fmin)
      ax.plot_surface(qxzw[0], qxzw[1], qxzw[2], rstride=1, cstride=1, facecolors=cm.gist_ncar(ff1Y), alpha=0.3)

      qxzw = np.stack([xzw[0]+8, np.zeros_like(xzw[0])+8,  xzw[1]], axis=0)
      ff2 = js.sf.radial3DLSF(qxzw.reshape(3, -1).T, sclattice, domainsize=ds, rmsd=0.03, hklmax=7)
      ffs2 = ff2.Y #np.log(ff2.Y)
      fmax, fmin = ffs2.max(), ffs2.min()
      ff2Y = (np.reshape(ffs2, xzw[0].shape) - fmin) / (fmax - fmin)
      ax.plot_surface(qxzw[0], qxzw[1], qxzw[2], rstride=1, cstride=1, facecolors=cm.gray(ff2Y), alpha=0.3)

      ax.set_xlabel('x axis')
      ax.set_ylabel('y axis')
      ax.set_zlabel('z axis')
      fig.suptitle('Scattering planes of simple cubic lattice \nin powder average')
      pyplot.show(block=False)

`jscatter.structurefactor.` `radialorientedLSF`(*args, **kwargs)

  Radial averaged structure factor S(q) of an oriented crystal lattice calculated as orientedLatticeStructureFactor.

  For a detailed description and parameters see orientedLatticeStructureFactor. Additionally the qxyz plane according to orientedLatticeStructureFactor is radial averaged over qxyz.

  Parameters
    qint, array

      Explicit list of q values or number of points between min and max wavevector values To large number results in noisy data as the average gets artificial. Each q points will be averaged in intervals around q neighbors from values in qxyz plane.

  Returns
    dataArray
      Columns [q,Sq,DW,beta,Z0q]

        - q wavevector as norm(qx,qy,qz)

        - Sq = S(q) = 1+beta(q)*(Z0(q)-1)*DW(q) structure factor

        - DW(q) Debye-Waller factor with (1-DW)=diffusive scattering.

        - beta(q) asymmetry factor of the formfactor.

        - Z0q lattice factor Z0(q)

      Attributes (+ input parameters)

        - .q_hkl peak positions

        - .hkl Miller indices

        - .peakFWHM full width half maximum

  Notes

  qxyz might be any number and geometrical distribution as plane or 3D cube. 3D qxyz points will be converted to qr=norm(qxyz) and averaged.

  Examples

      import jscatter as js
      import numpy as np

      R=12
      N=200
      ds=10
      fcclattice= js.lattice.fccLattice(3.1, 5)
      qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
      qxyz=np.c_[qxy,np.zeros(N**2)].T
      q=np.r_[0.1:16:100j]
      p=js.grace()
      for rmsd in [0.07,0.03,0.01]:
          ffe=js.sf.radialorientedLSF(q=q,qxyz=qxyz,lattice=fcclattice,rotation=[1,1,1,np.deg2rad(10)],domainsize=ds,rmsd=rmsd,hklmax=6)
          p.plot(ffe,li=1,le=f'rmsd {rmsd}')
      p.legend(x=8,y=1.8)
      p.yaxis(label='S(Q)',min=0,max=2.2)
      p.xaxis(label='Q / nm\S-1')
      #p.save(js.examples.imagepath+'/radialorientedLSF.jpg')

`jscatter.structurefactor.` `sq2gr`(Sq, R, interpolatefactor=2)

  Radial distribution function g(r) from structure factor Sq.

  The result strongly depends on quality of S(Q) (number of data points, Q range, smoothness). Read [2] for details of this inversion problem and why it may fail.

  Parameters
    SqdataArray
      Structure factor e.g. in units as [Q]=1/nm

        - .X wavevector

        - .Y structure factor

    Rfloat

      Estimate for the radius of the particles.

    interpolatefactorint

      Number of points between points in interpolation for rfft. 2 doubles the points

  Returns
    dataArray

      .n0 approximated from 2\pi^2 n_0=\int_0^{Q_{max}} [S(Q) -1]Q^2 dQ

  Notes

  One finds that

  g(r)-1=(2\pi^2 n_0 r)^{-1} \int_0^\infty [S(Q) -1]Qsin(qr)dQ

  with 2\pi^2 n_0=\int_0^\infty [S(Q) -1]Q^2 dQ defining n_0.

  As we have only a limited Q range (0 < Q < \infty ), limited accuracy and number of Q values we require that mean(g(R/2<r<R3/4))=0.

  References

  1

    Yarnell, J. L., Katz, M. J., Wenzel, R. G., & Koenig, S. H. (1973). Structure factor and radial distribution function for liquid argon at 85 K. Physical Review A, 7(6), 2130.

  2

    On the determination of the pair correlation function from liquid structure factor measurements A.K. Soper Chemical Physics 107, 61-74, (1986)

  Examples

      import jscatter as js
      import numpy as np
      p=js.grace()
      p.multi(2,1)
      q=js.loglist(0.01,100,2**13)
      p[0].clear();p[1].clear()
      R=2.5
      eta=0.3;scl=5
      n=eta/(4/3.*np.pi*R**3)   # unit 1/nm**3
      sf=js.sf.RMSA(q=q,R=R,scl=scl, gamma=50, eta=eta)
      gr=js.sf.sq2gr(sf,R,interpolatefactor=1)
      sfcut=js.sf.RMSA(js.loglist(0.01,10,2**10),R=R,scl=scl, gamma=50, eta=eta)
      grcut=js.sf.sq2gr(sfcut,R,interpolatefactor=5)
      p[0].plot(sf.X*2*R,sf.Y,le=r'\xG=50')
      p[1].plot(gr.X/2/R,gr[1],le=r'\xG=50')
      p[1].plot(grcut.X/2/R,grcut[1],le=r'\xG=50 \f{}Q\smax\N=10')
      sfh=js.sf.RMSA(q=q,R=R,scl=scl, gamma=0.01, eta=eta)
      grh=js.sf.sq2gr(sfh,R,interpolatefactor=1)
      p[0].plot(sfh.X*2*R,sfh.Y,le=r'\xG=0.01')
      p[1].plot(grh.X/2/R,grh[1],le=r'\xG=0.01')
      p[0].xaxis(max=20,label='2RQ')
      p[1].xaxis(max=4*R,label='r/(2R)')
      p[0].yaxis(max=2,min=0,label='S(Q)')
      p[1].yaxis(max=2.5,min=0,label='g(r)')
      p[0].legend(x=10,y=1.8)
      p[1].legend(x=4,y=2.2)
      p[0].title('Comparison RMSA')
      p[0].subtitle('R=%.2g, eta=%.2g, scl=%.2g' %(R,eta,scl))
      p.save(js.examples.imagepath+'/sq2gr.jpg')

`jscatter.structurefactor.` `stickyHardSphere`(q, R, width, depth, molarity=None, phi=None)

  Structure factor of a square well potential with depth and width (sticky hard spheres).

  Sticky hard sphere model is derived using a perturbative solution of the factorized form of the Ornstein-Zernike equation and the Percus-Yevick closure relation. The perturbation parameter is width/(width+2R)

  Parameters
    qarray; N dim

      Scattering vector; units 1/(R[unit])

    Rfloat

      Radius of the hard sphere

    phifloat

      Volume fraction of the hard core particles

    molarityfloat

      Number density in mol/l and defines q and R units to 1/nm and nm to be correct Preferred over phi if both given.

    depthfloat

      Potential well depth in kT depth >0 (U<0); positive potential allowed (repulsive) see [1].

    widthfloat

      Width of the square well

  Notes

  The potential U(r) is defined as

  U(r) &= \infty & r<2R \\ &= -depth[kT] & 2R<r<2R+width \\ &= 0 & r>2R+width

  Other definitions include

    - eps=width/(2*R+width)

    - stickiness=exp(-depth)/12./eps

  References

  1

    S.V. G. Menon, C. Manohar, and K. S. Rao, J. Chem. Phys. 95, 9186 (1991)

  2

    13. Sztucki, T. Narayanan, G. Belina, A. Moussaïd, F. Pignon, and H. Hoekstra, Phys. Rev. E 74, 051504 (2006)

  3

    W.-R. Chen, S.-H. Chen, and F. Mallamace, Phys. Rev. E 66, 021403 (2002)

  4

    7. Foffi, E. Zaccarelli, F. Sciortino, P. Tartaglia, and K. A. Dawson, J. Stat. Phys. 100, 363 (2000)

  Examples

      import jscatter as js
      R = 6
      phi = 0.05
      depth = 15
      q = js.loglist(0.01, 2, 200)
      p = js.grace(1,1)
      for eta in [0.005,0.01,0.03,0.05,0.1,0.2]:
          shs = js.sf.stickyHardSphere(q, R, 1, 3, phi=eta)
          p.plot(shs, symbol=0, line=[1, 3, -1], legend=f'eta ={eta:.3f}')
      p.yaxis(min=0.0, max=3.2, label='S(Q)', charsize=1.5)
      p.legend(x=1, y=3)
      p.xaxis(min=0, max=1.5)
      p.title('sticky hard sphere structure factor')
      #p.save(js.examples.imagepath+'/stickyHardSphere.jpg')

`jscatter.structurefactor.` `weakPolyelectrolyte`(q, cp, l, f, cs, ioc=None, eps=None, Temp=293.15, contrast=None, molarVolume=None)

  Monomer-monomer structure factor S(q) of a weak polyelectrolyte according to Borue and Erukhimovich [3].

  Polyelectrolyte models based on [3] are valid above “the critical concentration when electrostatic blobs begin to overlap”, see equ. 2 in [3] and above where we dont see isolated chains. The used RPA is valid only at high polymer concentrations where concentration fluctuations are weak [4].

  Parameters
    qarray

      Scattering vector in units 1/nm.

    cpfloat

      Monomer concentration c_p in units mol/l. The monomer concentration is :math:`N c_{p}.

    lfloat

      Monomer length in units nm.

    ffloat

      Fraction of charged monomers f. The abs(f) values is used.

    csfloat

      Monovalent salt concentration c_s in the solvent in units mol/l. This may include ions from water dissociation.

    iocfloat, default 0

      Additional contribution to the inverse osmotic compressibility Dm of neutral polymer solution in units nm^3. Inverse osmotic compressibility is Dm=1/(Nc)+v+w^2c (see [2]) The additional contribution is ioc=v+w^2c as used in [1] and can be positive or negative. v and w are the second and third virial coefficients [1].

    epsfloat

      Dielectric constant of the solvent to determine the Bjerum length. Default is H2O at given temperature. Use formel.dielectricConstant to determine the constant for your water based solvent including salt. For H2O at 293.15 K = 80.08 . Added 1M NaCl = 91.08

    Tempfloat, default 273.15+20

      Temperature in units Kelvin.

    contrastfloat, default None

      Contrast of the polymer \rho_{monomer} relative to the solvent as difference of scattering length densities in units nm^{-2}. See Notes for determination of absolute scattering. contrast and molarVolume need to be given.

    molarVolumefloat, default None

      Molar volume V_{monomer} of the polymer in nm^{3}. See Notes for determination of absolute scattering. contrast and molarVolume need to be given.

  Returns
    dataArray2 x N
      Columns [q, Sq]

        - .epsilon

        - .kappa in 1/nm

        - .screeninglength in nm

        - .r0 characteristic screening length without salt in units nm.

        - .c_monomer Monomer concentration in mol/l

        - .c_salt Salt concentration in mol/l

        - .c_ions Ion concentration as 2c_s + fc_p in mol/l

        - .monomerscatteringlength c = V_{monomer}\rho_{monomer}. If contrast or molarVolume are None then c=1.

      Sq units is 1/nm = 1/(1e-7 cm) = 1e7 1/cm. (multiply by 1e7 to get units 1/cm)

  Notes

  Borue and Erukhimovich [3] describe the polyelectrolyte scattering in reduced variables (see [3] equ 39). Rewriting this equation expressing the reduced variables s and t in terms of r_0 yields :

  S(q) = c^2 \frac{1}{4\pi l_b f^2} \frac{q^2+\kappa^2}{1+r_0^4(q^2+\kappa^2)(q^2-12hc_p/l^2)}

  with

    - r_0^2 = \frac{l}{f\sqrt{48c_p\pi l_b} } characteristic scale of screening without salt

    - c=V_{monomer}\rho_{monomer} scattering length monomer.

    - l_b = e^2/4\pi\epsilon kT \approx 0.7 nm Bjerum length.

    - \kappa^2=4\pi l_b (\sum_s{2c_s} + fc_p) Debye-Hückel inverse screening length from salt ions and polymer.

    - h=ioc Additional contribution to inverse compressibility.

    - v and w are the second and third virial coefficients between monomers \rightarrow ioc=v+w^2c [1].

  For low salt concentration (\kappa < r_0) the peak is expected at (q^{*2}+\kappa^2)^2 = r_0^{-4} (see [1] and [2] after euq. 14) and vanishes for \kappa > r_0 (see [2]).

  References

  1(1,2,3,4)

    Annealed and quenched polyelectrolytes. Raphael, E., & Joanny, J. F. (1990). EPL, 13(7), 623–628. https://doi.org/10.1209/0295-5075/13/7/009

  2(1,2,3)

    Weakly charged polyelectrolytes in a poor solvent J.F. Joanny, L. Leibler J. Phys. France 51, 545-557 (1990) DOI: 10.1051/jphys:01990005106054500

  3(1,2,3,4,5,6)

    A statistical theory of weakly charged polyelectrolytes: fluctuations, equation of state and microphase separation V. Yu. Borue, I. Ya. Erukhimovich, Macromolecules (1988) 21, 11, 3240-3249

  4

    50th Anniversary Perspective: A Perspective on Polyelectrolyte Solutions M. Muthukumar Macromolecules201750249528-9560 See p 9537 Pitfall of RPA for Polyelectrolyte solution

  Examples

  Poly(sodium 4-styrenesulfonate)(PSS-Na) with a bulk density of 0.801 g/mL. Monomer MW = 184 g/mol, monomer length 2 C-C bonds = 2 * 0.15 nm

      import jscatter as js
      import numpy as np
      q=js.loglist(0.01,4,100)

      Vm=184/0.801/6.022140857e+23/1e-21  # partial molar volume of the polymer in nm**3
      c=0.000698-0.000942 # PSS in H2O for X-ray scattering has negative contrast
      p=js.grace(1.2,1)
      for i,cp in enumerate([5, 10, 20, 30, 60],1): # conc in g/l
         c17=cp/184 # conc in mol/l
         Sq=js.sf.weakPolyelectrolyte(q=q, l=0.3, cp=c17, f=0.05, cs=0.005,ioc=0,contrast=c,molarVolume=Vm)
         Sq.Y*=1e7  # conversion to 1/cm
         p.plot(Sq,sy=[i,0.4,i],li=0,le='c={0:.3} mg/ml'.format(c17))
         Sqi=js.sf.weakPolyelectrolyte(q=q, l=0.3, cp=c17, f=0.05, cs=0.005,ioc=-0.02,contrast=c,molarVolume=Vm)
         Sqi.Y*=1e7
         p.plot(Sqi,li=[1,1,i],sy=0,le='ioc=-0.02 c={0:.3} mg/ml'.format(c17))

      p.yaxis(scale='log',min=Sq.Y.min()/15,max=Sq.Y.max(),label='I(q) / 1/cm')
      p.xaxis(scale='log',min=0.01,max=4,label=r'q / nm\S-1')
      p.title('A polyelectrolyte at low salt')
      p.legend(x=0.02,y=1.5e-1)
      #p.save(js.examples.imagepath+'/weakPolyelectrolyte.png')

class `jscatter.structurefactor.` `lattice`

  Create an arbitrary lattice.

  Please use one of the subclasses below for creation.

  pseudorandom, rhombicLattice, bravaisLattice scLattice, bccLattice, fccLattice, diamondLattice, hexLattice, hcpLattice, sqLattice, hexLattice, lamLattice

  This base class defines methods valid for all subclasses.

  property `X`

    X coordinates for b!=0

  property `XYZ`

    X,Y,Z coordinates array Nx3 for b!=0

  property `XYZall`

    X,Y,Z coordinates array Nx3

  property `Xall`

    X coordinates

  property `Y`

    Y coordinates for b!=0

  property `Yall`

    Y coordinates

  property `Z`

    Z coordinates for b!=0

  property `Zall`

    Z coordinates

  `alongLine`(self, v, R, a=None, direction=0, b=1, invert=False)

    Set scattering length for points within a long cylinder.

    Parameters
      a3 x float, default [0,0,0]

        Point on cylinder axis.

      Rfloat

        Radius of cylinder.

      v3 x float

        Normal vector along cylinder axis.

      direction :

        Which direction along normal vector. - 0 both - <0 negative direction - >0 positive direction

      b: float

        Scattering length for selected points.

      invertbool

        True to invert selection.

    Examples

        import jscatter as js
        sc=js.sf.scLattice(1,15,b=[0])
        sc.alongLine(v=[1,1,1],a=[5,0,0],R=3)
        sc.alongLine(v=[1,-1,1],a=[0,5,0],R=2)
        sc.alongLine(v=[1,1,-1],a=[0,0,5],direction =1,R=1)
        sc.alongLine(v=[1,0,0],a=[0,0,0],direction =-1,R=1)
        sc.show()

  property `array`

    Coordinates and scattering length as array for b!=0

  property `b`

    Scattering length for points with b!=0

  property `ball`

    Scattering length all points

  `centerOfMass`(self)

    Center of mass as center of geometry.

  `filter`(self, funktion)

    Set lattice points scattering length according to a function.

    All points in the lattice are changed for which funktion returns value !=0 (tolerance 1e-12).

    Parameters
      funktionfunction returning float

        Function to set lattice points scattering length. The function is applied with each i point coordinates (array) as input as .points[i,:3]. The return value is the corresponding scattering length.

    Examples

        # To select points inside of a sphere with radius 5 around [1,1,1]:
        from numpy import linalg as la
        sc=js.sf.scLattice(0.9,10)
        sc.set_b(0)
        sc.filter(lambda xyz: 1 if la.norm(xyz-np.r_[1,1,1])<5 else 0)

        # sphere with  increase from center
        from numpy import linalg as la
        sc=js.sf.scLattice(0.9,10)
        sc.set_b(0)
        sc.filter(lambda xyz: 2*(la.norm(xyz)) if la.norm(xyz)<5 else 0)
        fig=sc.show()

  `inParallelepiped`(self, v1, v2, v3, corner=None, b=1, invert=False)

    Set scattering length for points in parallelepiped.

    Parameters
      corner3x float

        Corner of parallelepiped

      v1,v2,v3each 3x float

        Vectors from origin to 3 corners that define the parallelepiped.

      b: float

        Scattering length for selected points.

      invertbool

        Invert selection

    Examples

        import jscatter as js
        sc=js.sf.scLattice(0.2,10,b=[0])
        sc.inParallelepiped([1,0,0],[0,1,0],[0,0,1],[0,0,0],1)
        sc.show()
        sc=js.sf.scLattice(0.1,30,b=[0])
        sc.inParallelepiped([1,1,0],[0,1,1],[1,0,1],[-1,-1,-1],2)
        sc.show()

  `inSphere`(self, R, center=None, b=1, invert=False)

    Set scattering length for points in sphere.

    Parameters
      center3 x float, default [0,0,0]

        Center of the sphere.

      R: float

        Radius of sphere around origin.

      b: float

        Scattering length for selected points.

      invertbool

        True to invert selection.

    Examples

        import jscatter as js
        sc=js.sf.scLattice(1,15,b=[0])
        sc.inSphere(6,[2,2,2],b=1)
        sc.show()
        sc.inSphere(6,[-2,-2,-2],b=2)
        sc.show()

        sc=js.sf.scLattice(0.8,20,b=[0])
        sc.inSphere(3,[2,2,2],b=1)
        sc.inSphere(3,[-2,-2,-2],b=1)
        sc.show()

        sc=js.sf.scLattice(0.8,20,b=[0])
        sc.inSphere(3,[2,2,2],b=1)
        sc.inSphere(4,[0,0,0],b=2)
        sc.show()

  `move`(self, vector)

    Move all points by vector.

    Parameters
      vectorlist of 3 float or array

        Vector to shift the points.

  `numberOfAtoms`(self)

    Number of Atoms

  `planeSide`(self, vector, center=None, b=1, invert=False)

    Set scattering length for points on one side of a plane.

    Parameters
      center3x float, default [0,0,0]

        Point in plane.

      vectorlist 3x float

        Vector perpendicular to plane.

      b: float

        Scattering length for selected points.

      invertbool

        False choose points at origin side. True other side.

    Examples

        sc=js.sf.scLattice(1,10,b=[0])
        sc.planeSide([1,1,1],[3,3,3],1)
        sc.show()
        sc.planeSide([-1,-1,0],3)
        sc.show()

  property `points`

    Points with scattering length !=0

    grid._points contains all Nx[x,y,z,b]

  `prune`(self, select)

    Prune lattice to reduced number of points (in place)

    Parameters
      selectbool array or function

        A bool array to select points (shape N = len(grid.ball)) or a bool function that is evaluated for each [x,y,z,b]

    Examples

        grid.prune(grid.ball>0)
        grid.prune(lambda a:a[3]>0)

  `rotate`(self, axis, angle)

    Rotate points in lattice around axis by angle.

    Parameters
      axislist 3xfloat

        Axis of rotation

      angle :

        Rotation angle in rad

  `set_b`(self, b)

    Set all points to given scattering length.

    Parameters
      bfloat or array length points
  `set_bsel`(self, b, select)

    Set b of all points (including points with b==0) according to selection.

    To access all points us the properties grid.??all which contains all coordinates and b.

    Parameters
      bfloat or array length _points

        Scattering length

      selectbool array

        Selection array of len(grid.ball)

    Examples

        grid.set_ball(1, grid.Xall > 0)

  property `shape`

    Shape for points with b!=0

  property `shapeall`

    Shape for points with b!=0

  `show`(self, R=None, cmap='rainbow', fig=None, ax=None, atomsize=6)

    Show the lattice in matplotlib with scattering length color coded.

    Parameters
      Rfloat,None

        Radius around origin to show.

      cmapcolormap

        Colormap. E.g. ‘rainbow’, ‘winter’,’autumn’,’gray’ to color atoms according to their scattering length b. Use js.mpl.showColors() for all possibilities.

      figmatplotlib Figure

        Figure to plot in. If None a new figure is created.

      axAxes

        If given this axes is used for plotting.

      atomsizefloat

        Sphere size of the atoms with the smallest scattering length b. Other sizes (radius) will be scaled according to b. Unfortunately matplotlib does not scale the point size when zooming.

    Returns
      fig handle

    Notes

    If the three dimensional overlap is wrong this is due to matplotlib. matplotlib is not a real 3D graphic program.

  property `type`

    Returns type of the lattice

class `jscatter.structurefactor.` `rhombicLattice`(latticeVectors, size, unitCellAtoms=None, b=None)

  Create a rhombic lattice with specified unit cell atoms.

  Allows to create 1D, 2D or 3D latices by using 1, 2 or 3 latticeVectors.

  Parameters
    latticeVectorslist of array 3x1

      Lattice vectors defining the translation of the unit cell along its principal axes.

    size :list of integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1.

    unitCellAtomslist of 3x1 array, None=[0,0,0]

      Position vectors vi of atoms in the unit cell in relative units of the lattice vectors [0<x<1]. For 2D and 1D the unit cell atoms vectors are len(vi)=2 and len(vi)=1.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array : grid points as numpy array .unitCellVolume : V = a1*a2 x a3 with latticeVectors a1, a2, a3; if existing. .dim : dimensionality .unitCellAtoms : Unit cell atoms in relative coordinates .unitCellAtoms_b : Scattering length of specific unit cell atoms

  Examples

      import jscatter as js
      # cubic lattice with diatomic base
      grid=js.sf.rhombicLattice([[1,0,0],[0,1,0],[0,0,1]],[3,3,3],[[-0.1,-0.1,-0.1],[0.1,0.1,0.1]],[1,2])
      grid.show(1.5)

  `getRadialReciprocalLattice`(self, size, includeZero=False)

    Get radial distribution of Bragg peaks with unit cell structure factor and multiplicity.

    To get real Bragg peak intensities the dimension in lattice directions has to be included (+ Debye-Waller factor and diffusive scattering). Use latticeStructureFactor to include these effects.

    Parameters
      sizeint

        Size of the lattice as maximum included Miller indices.

      includeZerobool

        Include q=0 peak

    Returns
      3x list of [unique q values, structure factor fhkl(q)**2, multiplicity mhkl(q)]
  `getReciprocalLattice`(self, size=2, threshold=0.001)

    Reciprocal lattice of given size with peak scattering intensity.

    Parameters
      size3x int or int, default 2

        Number of reciprocal lattice points in each direction (+- direction).

      thresholdfloat

        Threshold for selection rule as select if (f2_hkl > max(f2_hkl)*threshold)

    Returns
      Array [N x 7] with

        reciprocal lattice vectors [:,:3] corresponding structure factor fhkl**2>0 [:, 3] corresponding indices hkl [:,4:]

  `getScatteringAngle`(self, wavelength=None, size=13)

    Get scattering angle \theta=2arcsin(q_{hkl}\lambda/4\pi) in degrees.

    Parameters
      wavelengthfloat, 0.15406

        Wavelength \lambda in unit nm, default is Cu K-alpha 0.15406 nm.

      sizeint

        Maximum size of reciprocal lattice.

    Returns
      array in degrees
  `rotateAroundhkl`(self, hkl, angle=None, vector=None, hkl2=None)

    Rotate lattice around hkl direction by angle or to align to vector.

    Uses angle or aligns hkl2 to vector. Includes rotation of latticeVectors.

    Parameters
      hkl3x float

        Direction given as Miller indices.

      anglefloat

        Rotation angle in rad.

      vector3x float

        Vector to align hkl2 to. Overrides angle. Should not be parallel to hkl direction.

      hkl23x float

        Direction to align along vector. Overrides angle. Should not be parallel to hkl direction.

    Examples

        import jscatter as js
        import numpy as np
        R=8
        N=10
        qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
        qxyz=np.c_[qxy,np.zeros(N**2)]
        fccgrid = js.lattice.fccLattice(2.1, 1)
        fig=js.mpl.figure( )
        # create subplot to define geometry
        fig.add_subplot(2,2,1,projection='3d')
        fccgrid.show(fig=fig,ax=1)
        fccgrid.rotatehkl2Vector([1,1,1],[1,0,0])
        fccgrid.show(fig=fig,ax=2)
        fccgrid.rotateAroundhkl([1,1,1],np.deg2rad(30))
        fccgrid.show(fig=fig,ax=3)
        fccgrid.rotateAroundhkl([1,1,1],[1,0,0],[1,0,0])
        fccgrid.show(fig=fig,ax=4)

  `rotatePlane2hkl`(self, plane, hkl)

    Rotate plane points that plane is perpendicular to hkl direction.

    Parameters
      planearray Nx3

        3D points of plane

      hkllist of int, float

        Miller indices as [1,1,1] indicating the lattice direction where to rotate to.

    Returns
      plane points array 3xN

    Examples

        import jscatter as js
        import numpy as np
        R=8
        N=10
        qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
        qxyz=np.c_[qxy,np.zeros(N**2)]
        fccgrid = js.lattice.fccLattice(2.1, 3)
        xyz=fccgrid.rotatePlane2hkl(qxyz,[1,1,1])
        p=js.mpl.scatter3d(xyz[:,0],xyz[:,1],xyz[:,2])
        p.axes[0].scatter(fccgrid.X,fccgrid.Y,fccgrid.Z)

  `rotatePlaneAroundhkl`(self, plane, hkl, angle)

    Rotate plane points around hkl direction.

    Parameters
      planearray Nx3

        3D points of plane

      hkllist of int, float

        Miller indices as [1,1,1] indicating the lattice direction to rotate around.

      anglefloat

        Angle in rad

    Returns
      plane points array 3xN

    Examples

        import jscatter as js
        import numpy as np
        R=8
        N=10
        qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
        qxyz=np.c_[qxy,np.zeros(N**2)]
        fccgrid = js.lattice.fccLattice(2.1, 1)
        xyz=fccgrid.rotatePlane2hkl(qxyz,[1,1,1])
        xyz2=fccgrid.rotatePlaneAroundhkl(xyz,[1,1,1],np.deg2rad(30))
        p=js.mpl.scatter3d(xyz[:,0],xyz[:,1],xyz[:,2])
        p.axes[0].scatter(xyz2[:,0],xyz2[:,1],xyz2[:,2])
        p.axes[0].scatter(fccgrid.X,fccgrid.Y,fccgrid.Z)

  `rotatehkl2Vector`(self, hkl, vector)

    Rotate lattice that hkl direction is parallel to vector.

    Includes rotation of latticeVectors.

    Parameters
      hkl3x float

        Direction given as Miller indices.

      vector3x float

        Direction to align to.

    Examples

        import jscatter as js
        import numpy as np
        R=8
        N=10
        qxy=np.mgrid[-R:R:N*1j, -R:R:N*1j].reshape(2,-1).T
        qxyz=np.c_[qxy,np.zeros(N**2)]
        fccgrid = js.lattice.fccLattice(2.1, 1)
        p=js.mpl.scatter3d(fccgrid.X,fccgrid.Y,fccgrid.Z)
        fccgrid.rotatehkl2Vector([1,1,1],[1,0,0])
        p.axes[0].scatter(fccgrid.X,fccgrid.Y,fccgrid.Z)
        fccgrid.rotateAroundhkl([1,1,1],np.deg2rad(30))
        p.axes[0].scatter(fccgrid.X,fccgrid.Y,fccgrid.Z)

  property `unitCellAtomPositions`

    Absolute positions of unit cell atoms.

  `vectorhkl`(self, hkl)

    Get vector corresponding to hkl direction.

    Parameters
      hkl3x float

        Miller indices

    Returns
      array 3x float

class `jscatter.structurefactor.` `bravaisLattice`(latticeVectors, size, b=None)

  Create a Bravais lattice. Lattice with one atom in the unit cell.

  See rhombicLattice for methods and attributes.

  Parameters
    latticeVectorslist of array 1x3

      Lattice vectors defining the translation of the unit cell along its principal axes.

    size :3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

class `jscatter.structurefactor.` `scLattice`(abc, size, b=None)

  Simple Cubic lattice.

  See rhombicLattice for methods.

  Parameters
    abcfloat

      Point distance.

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.bccLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `bccLattice`(abc, size, b=None)

  Body centered cubic lattice.

  See rhombicLattice for methods.

  Parameters
    abcfloat

      Point distance.

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.bccLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `fccLattice`(abc, size, b=None)

  Face centered cubic lattice.

  See rhombicLattice for methods.

  Parameters
    abcfloat

      Point distance.

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.fccLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `hexLattice`(ab, c, size, b=None)

  Hexagonal lattice.

  See rhombicLattice for methods.

  Parameters
    ab,cfloat

      Point distance. ab is distance in hexagonal plane, c perpendicular. For c/a = (8/3)**0.5 the hcp structure

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.hexLattice(1.,2,[2,2,2])
      grid.show(2)

class `jscatter.structurefactor.` `hcpLattice`(ab, size, b=None)

  Hexagonal closed packed lattice.

  See rhombicLattice for methods.

  Parameters
    abfloat

      Point distance. ab is distance in hexagonal plane, c = ab* (8/3)**0.5

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.hcpLattice(1.2,[3,3,1])
      grid.show(2)

class `jscatter.structurefactor.` `diamondLattice`(abc, size, b=None)

  Diamond cubic lattice with 8 atoms in unit cell.

  See rhombicLattice for methods.

  Parameters
    abcfloat

      Point distance.

    size3x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.diamondLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `pseudoRandomLattice`(size, numberOfPoints, b=None, seed=None)

  Create a lattice with a pseudo random distribution of points.

  Allows to create 1D, 2D or 3D pseudo random latices. The Halton sequence is used with skipping the first seed elements of the Halton sequence.

  Parameters
    size :3x float

      Size of the lattice for each dimension relative to origin.

    numberOfPointsint

      Number of points.

    bfloat,array

      Scattering length of atoms. If array the sequence is repeated to fill N atoms.

    seedNone, int

      Seed for the Halton sequence by skipping the first seed elements of the sequence. If None an random integer between 10 and 1e6 is chosen.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.pseudoRandomLattice([5,5,5],3000)
      fig=grid.show()

class `jscatter.structurefactor.` `randomLattice`(size, numberOfPoints, b=None, seed=None)

  Create a lattice with a random distribution of points.

  Allows to create 1D, 2D or 3D random lattices. Uses numpy.random.random.

  Parameters
    size :3x float

      Size of the lattice for each dimension relative to origin.

    numberOfPointsint

      Number of points.

    bfloat,array

      Scattering length of atoms. If array the sequence is repeated to fill N atoms.

    seedNone, int

      Seed for random.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.randomLattice([5,5,5],3000)
      fig=grid.show()

class `jscatter.structurefactor.` `sqLattice`(ab, size, b=None)

  Simple 2D square lattice.

  See rhombicLattice for methods.

  Parameters
    abfloat

      Point distance.

    size2x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.sqLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `hex2DLattice`(ab, size, b=None)

  Simple 2D hexagonal lattice.

  See rhombicLattice for methods.

  Parameters
    abfloat

      Point distance.

    size2x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.hexLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `lamLattice`(a, size, b=None)

  1D lamellar lattice.

  See rhombicLattice for methods.

  Parameters
    afloat

      Point distance.

    size1x integer, integer

      A list of integers describing the size in direction of the respective latticeVectors. Size is symmetric around zero in interval [-i,..,i] with length 2i+1. If one integer is given it is used for all 3 dimensions.

    blist of float

      Corresponding scattering length of atoms in the unit cell.

  Returns
    lattice object

      .array grid points as numpy array

  Examples

      import jscatter as js
      grid=js.sf.lamLattice(1.2,1)
      grid.show(2)

class `jscatter.structurefactor.` `latticeFromCIF`(structure, size=[1, 1, 1], typ='x')

  Create lattice as defined in CIF (Crystallographic Information Format) file or a pymatgen structure.

  Parameters
    structurestr, pymatgen.structure

      Filename of the CIF file or structure read by pymatgen as `structure = pymatgen.Structure.from_file(js.examples.datapath+'/1011053.cif')`

    typ‘xray’,’neutron’

      scattering length for coherent xray or neutron scattering.

    size3x int

      Size of the lattice in direction of lattice vectors

  Notes

  - If Bragg peaks or reciprocal lattice points are missing try to increase the size parameter as these points might belong to higher order lattice planes. E.g. for SiC (silicon carbide) the second peak at 2\theta=35.6^{\circ} belongs to hkl = 006 or the 8th order peak at 2\theta=60.1^{\circ} belongs to hkl = 108 .

  - CIF files can be found in the Crystallography Open Database

  - Pymatgen (Python Materials Genomics) is a robust, open-source Python library for materials analysis [1]. See Pymatgen

        # Simply install by
        pip install pymatgen

  - Pymatgen allows reading of CIF files or to get directly a structure from Materials Project or Crystallography Open Database .

    Look at Examples

        from pymatgen.ext.cod import COD
        cod = COD()
        # SiC silicon carbide (carborundum or Moissanite)
        sic = cod.get_structure_by_id(1011053)
        sicc=js.sf.latticeFromCIF(sic)
        # silicon
        si = cod.get_structure_by_id(9008566)

  References

  1

    Python Materials Genomics (pymatgen) : A Robust, Open-Source Python Library for Materials Analysis. Ong et al Computational Materials Science, 2013, 68, 314–319. doi:10.1016/j.commatsci.2012.10.028

  Examples

  The example is for silicon carbide. Please compare to Moissanite

      import jscatter as js
      import pymatgen
      siliconcarbide = pymatgen.Structure.from_file(js.examples.datapath+'/1011053.cif')
      sic=js.sf.latticeFromCIF(siliconcarbide)
      sic.getScatteringAngle(wavelength=0.13141,size=13)

      from pymatgen.ext.cod import COD
      cod = COD()
      # 3C-SiC silicon carbide (carborundum or Moissanite)
      siliconcarbide = cod.get_structure_by_id(1011031)
      sic=js.sf.latticeFromCIF(siliconcarbide)
      sic.getScatteringAngle(size=13)

— Lattice objects describing a lattice of points.

Included are methods to select sublattices as parallelepiped, sphere or side of planes.

The small angle scattering is calculated by js.ff.cloudScattering.

The same method can be used to calculate the wide angle scattering with bragg peaks using larger scattering vectors to get crystalline bragg peaks of nanoparticles.

Examples

A hollow sphere cut to a wedge.

    import jscatter as js
    import numpy as np
    grid= js.lattice.scLattice(1/2.,2*8,b=[0])
    grid.inSphere(6,b=1)
    grid.inSphere(4,b=0)
    grid.planeSide([1,1,1],b=0)
    grid.planeSide([1,-1,-1],b=0)
    grid.show()

    q=js.loglist(0.01,5,600)
    ffe=js.ff.cloudScattering(q,grid.points,relError=0.02,rms=0.1)
    p=js.grace()
    p.plot(ffe)

A cube decorated with spheres.

    import jscatter as js
    import numpy as np
    grid= js.lattice.scLattice(0.2,2*15,b=[0])
    v1=np.r_[4,0,0]
    v2=np.r_[0,4,0]
    v3=np.r_[0,0,4]
    grid.inParallelepiped(v1,v2,v3,b=1)
    grid.inSphere(1,center=[0,0,0],b=2)
    grid.inSphere(1,center=v1,b=3)
    grid.inSphere(1,center=v2,b=4)
    grid.inSphere(1,center=v3,b=5)
    grid.inSphere(1,center=v1+v2,b=6)
    grid.inSphere(1,center=v2+v3,b=7)
    grid.inSphere(1,center=v3+v1,b=8)
    grid.inSphere(1,center=v3+v2+v1,b=9)
    grid.show()

    q=js.loglist(0.01,5,600)
    ffe=js.ff.cloudScattering(q,grid.points,relError=0.02,rms=0.)
    p=js.grace()
    p.plot(ffe)

A comparison of sc, bcc and fcc nanoparticles (takes a while )

    import jscatter as js
    import numpy as np
    q=js.loglist(0.01,35,1500)
    q=np.r_[js.loglist(0.01,3,200),3:40:800j]
    unitcelllength=1.5
    N=8

    scgrid= js.lattice.scLattice(unitcelllength,N)
    sc=js.ff.cloudScattering(q,scgrid.points,relError=50,rms=0.05)
    bccgrid= js.lattice.bccLattice(unitcelllength,N)
    bcc=js.ff.cloudScattering(q,bccgrid.points,relError=50,rms=0.05)
    fccgrid= js.lattice.fccLattice(unitcelllength,N)
    fcc=js.ff.cloudScattering(q,fccgrid.points,relError=50,rms=0.05)

    p=js.grace(1.5,1)
    # smooth with Gaussian to include instrument resolution
    p.plot(sc.X,js.formel.smooth(sc,10, window='gaussian'),legend='sc')
    p.plot(bcc.X,js.formel.smooth(bcc,10, window='gaussian'),legend='bcc')
    p.plot(fcc.X,js.formel.smooth(fcc,10, window='gaussian'),legend='fcc')

    q=q=js.loglist(1,35,100)
    p.plot(q,(1-np.exp(-q*q*0.05**2))/scgrid.shape[0],li=1,sy=0,le='sc diffusive')
    p.plot(q,(1-np.exp(-q*q*0.05**2))/bccgrid.shape[0],li=2,sy=0,le='bcc diffusive')
    p.plot(q,(1-np.exp(-q*q*0.05**2))/fccgrid.shape[0],li=3,sy=0,le='fcc diffusive')

    p.title('Comparison sc, bcc, fcc lattice for a nano cube')
    p.yaxis(scale='l',label='I(Q)')
    p.xaxis(scale='l',label='Q / A\S-1')
    p.legend(x=0.03,y=0.001,charsize=1.5)
    p.text('cube formfactor',x=0.02,y=0.05,charsize=1.4)
    p.text('Bragg peaks',x=4,y=0.05,charsize=1.4)
    p.text('diffusive scattering',x=4,y=1e-6,charsize=1.4)

END

`jscatter.lattice.` `latticeVectorsFromLatticeConstants`(A, B, C, a, b, c)

  Lattice vectors from lattice constants.

  Parameters
    A,B,Cfloat

      Lattice vector length in units nm.

    a,b,cfloat
      Angles between lattice vectors in degrees.

        - a=\alpha=\measuredangle BC

        - a=\beta=\measuredangle AC

        - a=\gamma=\measuredangle AB

  Notes

  See https://en.wikipedia.org/wiki/Lattice_constant