8. dynamic — jscatter 0.8.2 documentation

# 8. dynamic

Models describing dynamic processes mainly for inelastic neutron scattering.

- Models in the time domain have a parameter t for time. -> intermediate scattering function I(t,q)
- Models in the frequency domain have a parameter w for frequency and _w appended. -> dynamic structure factor S(w,q)

Models in time domain can be transformed to frequency domain by `time2frequencyFF()` implementing the Fourier transform S(w,q)=F(I(t,q)).

In time domain the combination of processes I_i(t,q) is done by multiplication, including instrument resolution R(t,q):

I(t,q)=I_1(t,q)I_2(t,q)R(t,q).

    # multiplying and creating new dataArray
    I(t,q) = js.dA( np.c[t, I1(t,q,..).Y*I2(t,q,..).Y*R(t,q,..).Y ].T)

In frequency domain it is a convolution, including the instrument resolution.

S(w,q) = S_1(w,q) \otimes S_2(w,q) \otimes R(w,q).

    conv=js.formel.convolve
    S(w,q)=conv(conv(S1(w,q,..),S2(w,q,..)),res(w,q,..),normB=True)      # normB normalizes resolution

FFT from time domain by `time2frequencyFF()` may include the resolution where it acts like a window function to reduce spectral leakage with vanishing values at t_{max}. If not used t_{max} needs to be large (see tfactor) to reduce spectral leakage.

The last step is to shift the model spectrum to the symmetry point of the instrument as found in the resolution measurement. Binning over frequency channels is done by `shiftAndBinning()`.

Example

Let us describe the diffusion of a particle inside a diffusing invisible sphere by mixing time domain and frequency domain.

    start={'s0':5,'m0':0,'a0':1,'bgr':0.00}
    w=np.r_[-100:100:0.5]
    resolution=js.dynamic.resolution_w(w,**start)
    # model
    def diffindiffSphere(w,q,R,Dp,Ds,w0,bgr):
        # time domain with transform to frequency domain
        diff_w=js.dynamic.time2frequencyFF(js.dynamic.simpleDiffusion,resolution,q=q,D=Ds)
        # last convolution in frequency domain, resolution is already included in time domain.
        Sx=js.formel.convolve(js.dynamic.diffusionInSphere_w(w=w,q=q,D=Dp,R=R),diff_w)
        Sxsb=js.dynamic.shiftAndBinning(Sx,w=w,w0=w0)
        Sxsb.Y+=bgr       # add background
        return Sxsb
    #
    Iqw=diffindiffSphere(w=w,q=5.5,R=0.5,Dp=1,Ds=0.035,w0=1,bgr=1e-4)

For more complex systems with different scattering length or changing contributions the fraction of contributing atoms (with scattering length) has to be included.

Accordingly, if desired, the mixture of coherent and incoherent scattering needs to be accounted for by corresponding scattering length. This additionally is dependent on the used instrument e.g. for spin echo only 1/3 of the incoherent scattering contributes to the signal. An example model for protein dynamics is given in Protein incoherent scattering in frequency domain.

A comparison of different dynamic models in frequency domain is given in examples. A comparison of different dynamic models in frequency domain.

For conversion to energy use E=js.dynamic.h*w with h=4.13566 [µeV*ns]

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

## 8.1. Transfom between domains

`shiftAndBinning`(data[, w, dw, w0]) | Shift spectrum and average (binning) in intervals.
`time2frequencyFF`(timemodel, resolution[, w, …]) | Fast Fourier transform from time domain to frequency domain for inelastic neutron scattering.

## 8.2. Time domain

`resolution`(t[, s0, m0, s1, m1, s2, m2, s3, …]) | Resolution in time domain as multiple Gaussians for inelastic measurement as back scattering or time of flight instrument.
`simpleDiffusion`(q, t, D[, amplitude]) | Intermediate scattering function for diffusing particles.
`doubleDiffusion`(q, t, amplitude0, D0[, …]) | Two exponential decaying functions.
`cumulantDiff`(t, q[, k0, k1, k2, k3, k4, k5]) | Cumulant of order ki with cumulants as diffusion coefficients.
`cumulant`(x[, k0, k1, k2, k3, k4, k5]) | Cumulant of order ki k0*(exp(-k1*x+1/2*(k2*x)**2-1/6*(k3*x)**3+1/24*(k4*x)**4-1/120*(k5*x)**5))
`cumulantDLS`(t, A, G, sigma[, skewness, bgr]) | Cumulant analysis for dynamic light scattering
`finiteRouse`(t, q[, NN, pmax, ll, frict, …]) | Rouse dynamics of a finite chain with N beads of bonds length l and internal friction.
`finiteZimm`(t, q[, NN, pmax, ll, Dcm, …]) | Zimm dynamics with internal friction of a finite chain with N beads of bonds length l.
`integralZimm`(t, q[, Temp, viscosity, amp, …]) | Conformational dynamics of an ideal chain with hydrodynamic interaction Integral version Zimm dynamics.
`stretchedExp`(t, gamma, beta[, amp]) | Stretched exponential function.
`jumpDiffusion`(t, Q, t0, l0) | Incoherent intermediate scattering function of translational jump diffusion in the time domain.
`methylRotation`(t, q[, t0, fraction, rhh, beta]) | Incoherent intermediate scattering function of CH3 methyl rotation in the time domain.
`diffusionHarmonicPotential`(t, q, rmsd, tau) | ISF corresponding to the standard OU process for diffusion in harmonic potential for dimension 1,2,3.
`diffusionPeriodicPotential`(t, q, u, rt, Dg) | Fractional diffusion of a particle in a periodic potential.
`rotDiffusion`(t, q, cloud, Dr[, lmax]) | Rotational diffusion of an object (dummy atoms); dynamic structure factor in time domain.
`zilmanGranekBicontinious`(t, q, xi, kappa, eta) | Dynamics of bicontinuous micro emulsion phases.
`zilmanGranekLamellar`(t, q, df, kappa, eta[, …]) | Dynamics of lamellar microemulsion phases.

## 8.3. Frequency domain

`h` | Planck constant in µeV*ns
`getHWHM`(data[, center, gap]) | Find half width at half maximum of a distribution around zero.
`convolve`(A, B[, mode, normA, normB]) | Convolve A and B with proper tracking of the output X axis.
`dynamicSusceptibility`(data, Temp) | Transform from S(w,q) to the imaginary part of the dynamic susceptibility.
`resolution_w`(w[, s0, m0, s1, m1, s2, m2, …]) | Resolution as multiple Gaussians for inelastic measurement as backscattering or time of flight instrument in w domain.
`elastic_w`(w) | Elastic line; dynamic structure factor in w domain.
`transDiff_w`(w, q, D) | Translational diffusion; dynamic structure factor in w domain.
`jumpDiff_w`(w, q, t0, r0) | Jump diffusion; dynamic structure factor in w domain.
`diffusionHarmonicPotential_w`(w, q, tau, rmsd) | Diffusion in a harmonic potential for dimension 1,2,3 (isotropic averaged), dynamic structure factor in w domain.
`diffusionInSphere_w`(w, q, D, R) | Diffusion inside of a sphere; dynamic structure factor in w domain.
`rotDiffusion_w`(w, q, cloud, Dr[, lmax]) | Rotational diffusion of an object (dummy atoms); dynamic structure factor in w domain.
`nSiteJumpDiffusion_w`(w, q, N, t0, r0) | Random walk among N equidistant sites (isotropic averaged); dynamic structure factor in w domain.

Models describing dynamic processes mainly for inelastic neutron scattering.

- Models in the time domain have a parameter t for time. -> intermediate scattering function I(t,q)
- Models in the frequency domain have a parameter w for frequency and _w appended. -> dynamic structure factor S(w,q)

Models in time domain can be transformed to frequency domain by `time2frequencyFF()` implementing the Fourier transform S(w,q)=F(I(t,q)).

In time domain the combination of processes I_i(t,q) is done by multiplication, including instrument resolution R(t,q):

I(t,q)=I_1(t,q)I_2(t,q)R(t,q).

    # multiplying and creating new dataArray
    I(t,q) = js.dA( np.c[t, I1(t,q,..).Y*I2(t,q,..).Y*R(t,q,..).Y ].T)

In frequency domain it is a convolution, including the instrument resolution.

S(w,q) = S_1(w,q) \otimes S_2(w,q) \otimes R(w,q).

    conv=js.formel.convolve
    S(w,q)=conv(conv(S1(w,q,..),S2(w,q,..)),res(w,q,..),normB=True)      # normB normalizes resolution

FFT from time domain by `time2frequencyFF()` may include the resolution where it acts like a window function to reduce spectral leakage with vanishing values at t_{max}. If not used t_{max} needs to be large (see tfactor) to reduce spectral leakage.

The last step is to shift the model spectrum to the symmetry point of the instrument as found in the resolution measurement. Binning over frequency channels is done by `shiftAndBinning()`.

Example

Let us describe the diffusion of a particle inside a diffusing invisible sphere by mixing time domain and frequency domain.

    start={'s0':5,'m0':0,'a0':1,'bgr':0.00}
    w=np.r_[-100:100:0.5]
    resolution=js.dynamic.resolution_w(w,**start)
    # model
    def diffindiffSphere(w,q,R,Dp,Ds,w0,bgr):
        # time domain with transform to frequency domain
        diff_w=js.dynamic.time2frequencyFF(js.dynamic.simpleDiffusion,resolution,q=q,D=Ds)
        # last convolution in frequency domain, resolution is already included in time domain.
        Sx=js.formel.convolve(js.dynamic.diffusionInSphere_w(w=w,q=q,D=Dp,R=R),diff_w)
        Sxsb=js.dynamic.shiftAndBinning(Sx,w=w,w0=w0)
        Sxsb.Y+=bgr       # add background
        return Sxsb
    #
    Iqw=diffindiffSphere(w=w,q=5.5,R=0.5,Dp=1,Ds=0.035,w0=1,bgr=1e-4)

For more complex systems with different scattering length or changing contributions the fraction of contributing atoms (with scattering length) has to be included.

Accordingly, if desired, the mixture of coherent and incoherent scattering needs to be accounted for by corresponding scattering length. This additionally is dependent on the used instrument e.g. for spin echo only 1/3 of the incoherent scattering contributes to the signal. An example model for protein dynamics is given in Protein incoherent scattering in frequency domain.

A comparison of different dynamic models in frequency domain is given in examples. A comparison of different dynamic models in frequency domain.

For conversion to energy use E=js.dynamic.h*w with h=4.13566 [µeV*ns]

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

`jscatter.dynamic.` `cumulant`(x, k0=0, k1=0, k2=0, k3=0, k4=0, k5=0)

  Cumulant of order ki k0*(exp(-k1*x+1/2*(k2*x)**2-1/6*(k3*x)**3+1/24*(k4*x)**4-1/120*(k5*x)**5))

  Parameters: | x : float Wavevector k0,k1, k2,k3,k4,k5 : float Coefficients; units 1/x k2/k1 = relative standard deviation if a gaussian distribution is assumed k3/k1 = relative skewness k3=skewness**3/G**3
  Returns: | dataArray

`jscatter.dynamic.` `cumulantDLS`(t, A, G, sigma, skewness=0, bgr=0.0)

  Cumulant analysis for dynamic light scattering

  A*np.exp(-t/G)*(1+(sigma/G*t)**2/2.-(skewness/G*t)**3/6.)+elastic

  Parameters: | t : array Time A : float Amplitude at t=0; Intercept G : float Mean relaxation time as 1/decay rate in units of t sigma : float relative standard deviation if a gaussian distribution is assumed should be smaller 1 or the Taylor expansion is not valid k2=variance=sigma**2/G**2 skewness : float,default 0 Relative skewness k3=skewness**3/G**3 bgr : float; default 0 Constant background
  Returns: | dataArray

  References

  [1] | Revisiting the method of cumulants for the analysis of dynamic light-scattering data Barbara J. Frisken APPLIED OPTICS 40, 4087 (2001)

`jscatter.dynamic.` `cumulantDiff`(t, q, k0=0, k1=0, k2=0, k3=0, k4=0, k5=0)

  Cumulant of order ki with cumulants as diffusion coefficients.

  means gamma_1 =q^2*D_1 in the linear term k0*(exp(-q**2.*(k1*x+1/2*(k2*x)**2+1/6*(k3*x)**3+1/24*(k4*x)**4+1/120*(k5*x)**5)))

  Parameters: | t : array Time q : float Wavevector k0 : float Amplitude k1 : float Diffusion coefficient in units of 1/([q]*[t]) k2,k3,k4,k5 : float Higher coefficients in same units as k1
  Returns: | dataArray :

`jscatter.dynamic.` `diffusionHarmonicPotential`(t, q, rmsd, tau, ndim=3)

  ISF corresponding to the standard OU process for diffusion in harmonic potential for dimension 1,2,3.

  The intermediate scattering function corresponding to the standard OU process for diffusion in an harmonic potential [1]. It is used for localized translational motion in incoherent neutron scattering [2] as improvement for the diffusion in a sphere model. Atomic motion may be restricted to ndim=1,2,3 dimensions and are isotropic averaged. The correlation is assumed to be exponential decaying.

  Parameters: | t : array Time values in units ns q : float Wavevector in unit 1/nm rmsd : float Root mean square displacement <u**2>**0.5 in potential in units nm. <u**2>**0.5 is the width of the potential According to [2] 5*u**2=R**2 compared to the diffusion in a sphere. tau : float Correlation time in units ns. Diffusion constant in sphere Ds=u**2/tau ndim : 1,2,3, default=3 Dimensionality of the diffusion potential.
  Returns: | dataArray

  References

  [1] | (1, 2) Quasielastic neutron scattering and relaxation processes in proteins: analytical and simulation-based models G. R. Kneller Phys. ChemChemPhys. ,2005, 7,2641–2655

  [2] | (1, 2, 3) Gaussian model for localized translational motion: Application to incoherent neutron scattering F. Volino, J.-C. Perrin and S. Lyonnard, J. Phys. Chem. B 110, 11217–11223 (2006)

  Examples

      import numpy as np
      import jscatter as js
      t=np.r_[0.1:6:0.1]
      p=js.grace()
      p.plot(js.dynamic.diffusionHarmonicPotential(t,1,2,1,1),le='1D ')
      p.plot(js.dynamic.diffusionHarmonicPotential(t,1,2,1,2),le='2D ')
      p.plot(js.dynamic.diffusionHarmonicPotential(t,1,2,1,3),le='3D ')
      p.legend()
      p.yaxis(label='I(Q,t)')
      p.xaxis(label='Q / ns')
      p.subtitle('Figure 2 of ref Volino J. Phys. Chem. B 110, 11217')

`jscatter.dynamic.` `diffusionHarmonicPotential_w`(w, q, tau, rmsd, ndim=3, nmax='auto')

  Diffusion in a harmonic potential for dimension 1,2,3 (isotropic averaged), dynamic structure factor in w domain.

  An approach worked out by Volino et al [1] assuming Gaussian confinement and leads to a more efficient formulation by replacing the expression for diffusion in a sphere with a simpler expression pertaining to a soft confinement in harmonic potential. Ds = ⟨u**2⟩/t0

  Parameters: | w : array Frequencies in 1/ns q : float Wavevector in nm**-1 tau : float Mean correlation time time. In units ns. rmsd : float Root mean square displacement (width) of the Gaussian in units nm. ndim : 1,2,3, default=3 Dimensionality of the potential. nmax : int,’auto’ Order of expansion. ‘auto’ -> nmax = min(max(int(6*q * q * u2),30),1000)
  Returns: | dataArray

  Notes

  Volino et al [1] compared the behaviour of this approach to the well known expression for diffusion in a sphere. Even if the details differ, the salient features of both models match if the radius R**2 ≃ 5*u0**2 and the diffusion constant inside the sphere relates to the relaxation time of particle correlation t0= ⟨u**2⟩/Ds towards the Gaussian with width u0=⟨u**2⟩**0.5.

  ndim=3
    Here we use the Fourier transform of equ 23 with equ. 29a+b in [1]. For order n larger 30 the Stirling approximation for n! in equ 27b of [1] is used.
  ndim=2
    Here we use the Fourier transform of equ 23 with equ. 28a+b in [1].
  ndim=1
    The equation given by Volino seems to be wrong !!!! Dont use this !!!!!!!! Use the model from time domain and use FFT as in example given Here we use the Fourier transform of equ 23 with equ. 29a+b in [1].

  References

  [1] | (1, 2, 3, 4, 5, 6, 7) Gaussian model for localized translational motion: Application to incoherent neutron scattering. Volino, F., Perrin, J. C. & Lyonnard, S. J. Phys. Chem. B 110, 11217–11223 (2006).

  Examples

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100]
      ql=np.r_[1:14.1:1.3]
      p=js.grace()
      iqt3=js.dL([js.dynamic.gaussDiffusion3D_w(w=w,q=q,t0=0.14,u0=0.34,ndim=3) for q in ql])
      iqt2=js.dL([js.dynamic.gaussDiffusion3D_w(w=w,q=q,t0=0.14,u0=0.34,ndim=2) for q in ql])
      # as ndim=1 is a wrong solution use this instead
      iqt1=js.dL([js.dynamic.time2frequencyFF(js.dynamic.diffusionHarmonicPotential,'elastic',w=np.r_[-100:100:0.01],dw=0,q=q, rmsd=u0, tau=t0 ,ndim=1) for q in ql])
      p.plot(iqt2)
      p.plot(iqt3)

`jscatter.dynamic.` `diffusionInSphere_w`(w, q, D, R)

  Diffusion inside of a sphere; dynamic structure factor in w domain.

  Parameters: | w : array Frequencies in 1/ns q : float Wavevector in nm**-1 D : float Diffusion coefficient in units nm**2/ns R : float Radius of the sphere in units nm.
  Returns: | dataArray

  Notes

  Here we use equ 33 in [1] with the first 99 solutions of equ 27 a+b as given in [1]. This is valid for q*R<20 with accuracy of ~0.001 as given in [1]. If we look at a comparison with free diffusion the valid range seems to be smaller.

  References

  [1] | (1, 2, 3, 4) Neutron incoherent scattering law for diffusion in a potential of spherical symmetry: general formalism and application to diffusion inside a sphere. Volino, F. & Dianoux, A. J., Mol. Phys. 41, 271–279 (1980).

  Examples

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100]
      ql=np.r_[1:14.1:1.3]
      p=js.grace()
      iqw=js.dL([js.dynamic.diffusionInSphere_w(w=w,q=q,D=0.14,R=0.2) for q in ql])
      p.plot(iqw)
      p.yaxis(scale='l')

  Compare different kinds of diffusion in restricted geometry.

      import jscatter as js
      import numpy as np
      # compare the HWHM
      ql=np.r_[0.5:15.:0.2]
      D=0.1;R=0.5
      w=np.r_[-js.loglist(0.01,100,100)[::-1],0,js.loglist(0.01,100,100)]
      iqwS=js.dL([js.dynamic.diffusionInSphere_w(w=w,q=q,D=D,R=R) for q in ql])
      iqwD=js.dL([js.dynamic.transDiff_w(w=w,q=q,D=D) for q in ql[:]])
      u0=R/4.33**0.5;t0=R**2/4.33/D
      iqwG3=js.dL([js.dynamic.gaussDiffusion3D_w(w=w,q=q,u0=u0,t0=t0) for q in ql])
      iqwG2=js.dL([js.dynamic.gaussDiffusion2D_w(w=w,q=q,u0=u0,t0=t0) for q in ql])
      p1=js.grace()
      p1.subtitle('Comparison of HWHM for different types of diffusion')
      p1.plot((R*iqwD.wavevector.array)**2,[js.dynamic.getHWHM(dat)[0]/(D/R**2) for dat in iqwD], le='free diffusion')
      p1.plot((R*iqwS.wavevector.array)**2,[js.dynamic.getHWHM(dat)[0]/(D/R**2) for dat in iqwS], le='diffusion in sphere')
      p1.plot([0.1,60],[4.33296]*2,li=[1,1,1])
      p1.plot((R*iqwG3.wavevector.array)**2,[js.dynamic.getHWHM(dat)[0]/(D/R**2) for dat in iqwG3], le='diffusion 3D Gauss')
      p1.plot((R*iqwG2.wavevector.array)**2,[js.dynamic.getHWHM(dat)[0]/(D/R**2) for dat in iqwG2], le='diffusion 2D Gauss')
      r0=.5;t0=r0**2/2./D
      iqwJ=js.dL([js.dynamic.jumpDiff_w(w=w,q=q,r0=r0,t0=t0) for q in ql])
      ii=54;p1.plot((r0*iqwJ.wavevector.array[:ii])**2,[js.dynamic.getHWHM(dat)[0]/(D/r0**2) for dat in iqwJ[:ii]], le='jump diffusion')
      p1.yaxis(min=0.1,max=100,scale='l',label='HWHM/(D/R**2)')
      p1.xaxis(min=0.1,max=100,scale='l',label='(Q*R)\S2')
      p1.legend(x=0.2,y=50)

`jscatter.dynamic.` `diffusionPeriodicPotential`(t, q, u, rt, Dg, gamma=1)

  Fractional diffusion of a particle in a periodic potential.

  The diffusion describes a fast dynamics inside of the potential trap with a mean square displacement before a jump and a fractional long time diffusion. For fractional coefficient gamma=1 normal diffusion is recovered.

  Parameters: | t : array Time points, units ns. q : float Wavevector, units 1/nm u : float Root mean square displacement in the trap, units nm. rt : float Relaxation time of fast dynamics in the trap; units ns (1/lambda in [1] ) gamma : float Fractional exponent gamma=1 is normal diffusion Dg : float Long time fractional diffusion coefficient; units nm**2/ns.
  Returns: | dataArray : [t, Iqt , Iqt_diff, Iqt_trap]

  References

  [1] | (1, 2) Gupta, S.; Biehl, R.; Sill, C.; Allgaier, J.; Sharp, M.; Ohl, M.; Richter, D. Macromolecules 2016, 49 (5), 1941.

  Examples

      # Example similar to protein diffusion in a mesh of high molecular weight PEG as found in [Rc5c671f32804-1]_.
      import jscatter as js
      import numpy as np
      t=js.loglist(0.1,100,100)
      p=js.grace()
      for i,q in enumerate(np.r_[0.1:2:0.3],1):
          iq=js.dynamic.diffusionPeriodicPotential(t,q,0.5,15,0.036)
          p.plot(iq,symbol=[1,0.3,i],legend='q=$wavevector')
          p.plot(iq.X,iq._Iqt_diff,sy=0,li=[1,0.5,i])
      p.title('Diffusion in periodic potential traps')
      p.subtitle('lines show long time diffusion contribution')
      p.yaxis(max=1,min=1e-3,scale='log',label='I(Q,t)/I(Q,0)')
      p.xaxis(min=0,max=150,label='t / ns')
      p.legend(x=110,y=0.8)

`jscatter.dynamic.` `doubleDiffusion`(q, t, amplitude0, D0, amplitude1=0, D1=0)

  Two exponential decaying functions.

  Parameters: | q : float, array Wavevector t : float, array Time list amplitude0,amplitude1 : float Prefactor D0,D1 : float Diffusion coefficient in units [ [q]**-2/[t] ]
  Returns: | dataArray

`jscatter.dynamic.` `dynamicSusceptibility`(data, Temp)

  Transform from S(w,q) to the imaginary part of the dynamic susceptibility.

  \chi (w,q) &= \frac{S(w,q)}{n(w)} (gain side) &= \frac{S(w,q)}{n(w)+1} (loss side)

  with Bose distribution for integer spin particles

  with \ n(w)=\frac{1}{e^{hw/kT}-1}

  Parameters: | data : dataArray Data to transform with w units in 1/ns Temp : float Measurement temperature in K.
  Returns: | dataArray

  Notes

  “Whereas relaxation processes on different time scales are usually hard to identify in S(w,q), they appear as distinct peaks in dynamic susceptibility with associated relaxation times :math:´1/2piw´ [1].”

  References

  [1] | (1, 2) Roh et al. ,Biophys. J. 91, 2573 (2006)

  Examples

      start={'s0':5,'m0':0,'a0':1,'bgr':0.00}
      w=np.r_[-100:100:0.5]
      resolution=js.dynamic.resolution_w(w,**start)
      # model
      def diffindiffSphere(w,q,R,Dp,Ds,w0,bgr):
          diff_w=js.dynamic.transDiff_w(w,q,Ds)
          rot_w=js.dynamic.diffusionInSphere_w(w=w,q=q,D=Dp,R=R)
          Sx=js.formel.convolve(rot_w,diff_w)
          Sxsb=js.dynamic.shiftAndBinning(Sx,w=w,w0=w0)
          Sxsb.Y+=bgr       # add background
          return Sxsb
      #
      q=5.5;R=0.5;Dp=1;Ds=0.035;w0=1;bgr=1e-4
      Iqw=diffindiffSphere(w,q,R,Dp,Ds,w0,bgr)
      IqwR=js.dynamic.diffusionInSphere_w(w,q,Dp,R)
      IqwT=js.dynamic.transDiff_w(w,q,Ds)
      Xqw=js.dynamic.dynamicSusceptibility(Iqw,293)
      XqwR=js.dynamic.dynamicSusceptibility(IqwR,293)
      XqwT=js.dynamic.dynamicSusceptibility(IqwT,293)
      p=js.grace()
      p.plot(Xqw)
      p.plot(XqwR)
      p.plot(XqwT)
      p.yaxis(scale='l',label='X(w,q) / a.u.')
      p.xaxis(scale='l',label='w / ns\S-1')

`jscatter.dynamic.` `elastic_w`(w)

  Elastic line; dynamic structure factor in w domain.

  Parameters: | w : array Frequencies in 1/ns w0 : float Position of elastic line \delta(w=w0)=1
  Returns: | dataArray

`jscatter.dynamic.` `finiteRouse`(t, q, NN=None, pmax=None, ll=None, frict=None, Dcm=None, Wl4=None, Dcmfkt=<function <lambda>>, tintern=0.0, Temp=293)

  Rouse dynamics of a finite chain with N beads of bonds length l and internal friction. Coherent scattering.

  The Rouse model describes the conformational dynamics of an ideal chain. The single chain diffusion is represented by Brownian motion of beads connected by harmonic springs. no excluded volume, random thermal force, drag force with solvent and optional internal friction.

  Parameters: | t : array Time in units nanoseconds q : float, list Scattering vector, units nm^-1 For a list a dataList is returned otherwise a dataArray is returned NN : integer Number of chain beads. ll : float, default 1 Bond length between beads; unit nm. pmax : integer, list of floats integer => maximum mode number list => list of amplitudes>0 for individual modes to allow weighing; not given modes have weight zero frict : float Friction of a single bead, units Pas*m=kg/s=1e-6 g/ns. A sphere with R=1 nm in water = 1.88e-11 kg/s=1.88e-17 g/ns Wl4 : float Needed to calc friction and Dcm. Dcm : float Center of mass diffusion in nm^2/ns. =kT/(NN*f) with f = friction of single bead in solvent =Wl^4/(3*N*l^2)=Wl^4/(3* Re^2) Dcmfkt : function returning array Function to modify Dcm as Dcm(q)=Dcm*Dcmfkt(q) eg for inclusion of structure factor Dcmfkt=lambda q:1/S(q) tintern : float>0 Relaxation time due to internal friction in ns Temp : float Temperature Kelvin = 273+T[°C]
  Returns: | dataArray

  Notes

  Additional Attributes
    - Wl4
    - Re end to end distance Re^2=l^2*N
    - tr1 is rotational correlation time or rouse time tr1 = f*NN^2*ll^2/(3 pi^2*kb*T)= <Re^2>/(3*pi*Dcm) = N**2*f/(pi**2*k)
    - tintern relaxation time due to internal friction
    - t_p characteristic times t_p=tr1*p^2+tintern
  From above the triple Dcm,ll,NN are fixed.
    - If 2 are given 3rd is calculated
    - If all 3 are given the given values are used
  Remind:
    - k=3kT/ll**2 force constant k between beads.
    - f=6pi*eta*R single bead friction f in solvent (e.g. surrounding melt)
    - tintern=fi/k additional relaxation time due to internal friction fi
    - fi=tintern*k=tintern*3kT/ll**2 internal friction per bead

  References

  [1] | Doi Edwards Theory of Polymer dynamics in the appendix the equation is found

  [2] | Nonflexible Coils in Solution: A Neutron Spin-Echo Investigation of Alkyl-Substituted Polynorbonenes in Tetrahydrofuran Michael Monkenbusch et al Macromolecules 2006, 39, 9473-9479 The exponential is missing a “t” http://dx.doi.org/10.1021/ma0618979

  about internal friction

  [3] | Exploring the role of internal friction in the dynamics of unfolded proteins using simple polymer models Cheng et al JOURNAL OF CHEMICAL PHYSICS 138, 074112 (2013) http://dx.doi.org/10.1063/1.4792206

  [4] | Rouse Model with Internal Friction: A Coarse Grained Framework for Single Biopolymer Dynamics Khatri, McLeish| Macromolecules 2007, 40, 6770-6777 http://dx.doi.org/10.1021/ma071175x

`jscatter.dynamic.` `finiteZimm`(t, q, NN=None, pmax=None, ll=None, Dcm=None, Dcmfkt=<function <lambda>>, tintern=0.0, mu=0.5, viscosity=1.0, Temp=293)

  Zimm dynamics with internal friction of a finite chain with N beads of bonds length l. Coherent scattering.

  The Zimm model describes the conformational dynamics of an ideal chain with hydrodynamic interaction between beads. The single chain diffusion is represented by Brownian motion of beads connected by harmonic springs. no excluded volume, random thermal force, drag force with solvent, hydrodynamics between beads and optional internal friction.

  Parameters: | t : array Time in nanoseconds q: float, array Scattering vector in nm^-1 If q is list a dataList is returned otherwise a dataArray is returned NN : integer Number of chain beads ll : float, default 1 Bond length between beads; units nm pmax : integer, list of float, default is NN integer => maximum mode number list => list of amplitudes>0 for individual modes to allow weighing; not given modes have weight zero Dcm : float Center of mass diffusion in nm^2/ns 0.196 kb T/(Re*viscosity) theta solvent with mu=0.6 0.203 kb T/(Re*viscosity) good solvent with mu=0.5 Dcmfkt : function returning array Function to modify Dcm as Dcm(q)=Dcm*Dcmfkt(q) e.g. for inclusion of structure factor Dcmfkt=lambda q:1/S(q) tintern : float>0 Additional relaxation time due to internal friction (if a tuple as (0,1,1,1,) the mode p will get tintern[p]) Automatically extended to length pmax mu : float in range [0.5,0.6] Varies between good solvent 0.6 and theta solvent 0.5 (gaussian chain) viscosity : float cPoise=mPa*s as water 20+273.15 K =1 mPa*s Temp : float Temperature Kelvin = 273+20
  Returns: | dataArray : for single q [wavevector q , Iqt_diff+modes, Iqt_diffusion] dataArray.modecontribution of modes i in sequence dataList : multiple q dataList with dataArrays as for single q as above

  Notes

  Additional attributes defined:
    - Re end to end distance Re^2=l^2*N^2mu
    - tz1 rotational correlation time tz1 = visc*Re^3/(sqrt(3 pi)kb*T)
    - t_p characteristic times t_p=tz1*p^-3mu+tintern
    - modecontribution is modecontribution as in PRL 71, 4158 equ (3)
  From above the triple Dcm,ll,NN are fixed.
    - If 2 are given 3rd is calculated
    - If all 3 are given the given values are used
  Remind:
    - k=3kT/ll**2 force constant between beads.
    - f=6pi*eta*R single bead friction in solvent
    - tintern=fi/k additional relaxation time due to internal friction fi
    - fi=tintern*k=tintern*3kT/ll**2 internal friction per bead

  References

  [1] | Doi Edwards Theory of Polymer dynamics in appendix the equation is found

  [2] | Nonflexible Coils in Solution: A Neutron Spin-Echo Investigation of Alkyl-Substituted Polynorbonenes in Tetrahydrofuran Michael Monkenbusch et al Macromolecules 2006, 39, 9473-9479 The exponential is missing a “t” http://dx.doi.org/10.1021/ma0618979

  about internal friction

  [3] | Exploring the role of internal friction in the dynamics of unfolded proteins using simple polymer models Cheng et al JOURNAL OF CHEMICAL PHYSICS 138, 074112 (2013) http://dx.doi.org/10.1063/1.4792206

  [4] | Rouse Model with Internal Friction: A Coarse Grained Framework for Single Biopolymer Dynamics Khatri, McLeish| Macromolecules 2007, 40, 6770-6777 http://dx.doi.org/10.1021/ma071175x

  mode contribution factors from

  [5] | Onset of Topological Constraints in Polymer Melts: A Mode Analysis by Neutron Spin Echo Spectroscopy D. Richter et al PRL 71,4158-4161 (1993)

`jscatter.dynamic.` `getHWHM`(data, center=0, gap=0)

  Find half width at half maximum of a distribution around zero.

  The hwhm is determined from cubic spline between Y values to find Y.max/2. Requirement Y.max/2>Y.min and increasing X values. If nothing is found an empty list is returned

  Parameters: | data : dataArray Distribution center: float, default=0 Center (symmetry point) of data. If None the position of the maximum is used. gap : float, default 0 Exclude values around center as it may contain a singularity. Excludes values within X<= abs(center-gap).
  Returns: | list of float with hwhm X>0 , X<0 if existing

`jscatter.dynamic.` `h` = 4.135667662340164

  Planck constant in µeV*ns

`jscatter.dynamic.` `integralZimm`(t, q, Temp=293, viscosity=0.001, amp=1, rtol=0.02, tol=0.02, limit=50)

  Conformational dynamics of an ideal chain with hydrodynamic interaction Integral version Zimm dynamics. Coherent scattering.

  The Zimm model describes the conformational dynamics of an ideal chain with hydrodynamic interaction between beads. See [1].

  Parameters: | t : array Time points in ns q : float Wavevector in 1/nm Temp : float Temperature in K viscosity : float Viscosity in cP=mPa*s amp : float Amplitude
  Returns: | dataArray

  References

  [1] | (1, 2) Neutron Spin Echo Investigations on the Segmental Dynamics of Polymers in Melts, Networks and Solutions in Neutron Spin Echo Spectroscopy Viscoelasticity Rheology Volume 134 of the series Advances in Polymer Science pp 1-129 DOI 10.1007/3-540-68449-2_1

  Examples

      t=np.r_[0:10:0.2]
      p=js.grace()
      for q in np.r_[0.26,0.40,0.53,0.79,1.06]:
         iqt=js.dynamic.integralZimm(t=t,q=q,viscosity=0.2e-3)
         p.plot(iqt)
         #p.plot((iqt.X*iqt.q**3)**(2/3.),iqt.Y)

`jscatter.dynamic.` `jumpDiff_w`(w, q, t0, r0)

  Jump diffusion; dynamic structure factor in w domain.

  Jump diffusion as a Markovian random walk. Jump length distribution is a Gaussian with width r0 and jump rate distribution with width G (Poisson). Diffusion coefficient D=r0**2/2t0.

  Parameters: | w : array Frequencies in 1/ns q : float Wavevector in nm**-1 t0 : float Mean residence time in a Poisson distribution of jump times. In units ns. G = 1/tg = Mean jump rate r0 : float Root mean square jump length in 3 dimensions <r**2> = 3*r_0**2
  Returns: | dataArray

  References

  [1] | Incoherent neutron scattering functions for random jump diffusion in bounded and infinite media. Hall, P. L. & Ross, D. K. Mol. Phys. 42, 637–682 (1981).

`jscatter.dynamic.` `jumpDiffusion`(t, Q, t0, l0)

  Incoherent intermediate scattering function of translational jump diffusion in the time domain.

  Parameters: | t : array Times, units ns Q : float Wavevector, units nm t0 : float Residence time, units ns l0 : float Mean square jump length, units nm
  Returns: | dataArray

  References

  [1] | Experimental determination of the nature of diffusive motions of water molecules at low temperatures J. Teixeira, M.-C. Bellissent-Funel, S. H. Chen, and A. J. Dianoux Phys. Rev. A 31, 1913 – Published 1 March 1985

`jscatter.dynamic.` `methylRotation`(t, q, t0=0.001, fraction=1, rhh=0.12, beta=0.8)

  Incoherent intermediate scattering function of CH3 methyl rotation in the time domain.

  Parameters: | t : array List of times, units ns q : float Wavevector, units nm t0 : float, default 0.001 Residence time, units ns fraction : float, default 1 Fraction of protons contributing. rhh : float, default=0.12 Mean square jump length, units nm beta : float, default 0.8 exponent
  Returns: | dataArray

  Notes

  According to [1]:

  I(q,t) = (EISF + (1-EISF) e^{-(\frac{t}{t_0})^{\beta}} )

  EISF=\frac{1}{3}+\frac{2}{3}\frac{sin(qr_{HH})}{qr_{HH}}

  with t_0 residence time, r_{HH} proton jump distance.

  References

  [1] | (1, 2) Bée, Quasielastic Neutron Scattering (Adam Hilger, 1988).

  [2] | Monkenbusch et al. J. Chem. Phys. 143, 075101 (2015)

  Examples

  import jscatter as js import numpy as np # make a plot of the spectrum w=np.r_[-100:100] ql=np.r_[1:15:1] iqwCH3=js.dL([js.dynamic.time2frequencyFF(js.dynamic.methylRotation,’elastic’,w=np.r_[-100:100:0.1],q=q ) for q in ql]) p=js.grace() p.plot(iqwCH3,le=’CH3’) p.yaxis(min=1e-5,max=10,scale=’l’)

`jscatter.dynamic.` `nSiteJumpDiffusion_w`(w, q, N, t0, r0)

  Random walk among N equidistant sites (isotropic averaged); dynamic structure factor in w domain.

  E.g. for CH3 group rotational jump diffusion over 3 sites.

  Parameters: | w : array Frequencies in 1/ns q: float Wavevector in units 1/nm N : int Number of jump sites, jump angle 2pi/N r0 : float Distance of sites from center of rotation. For CH3 eg 0.12 nm. t0 : float Rotational correlation time.
  Returns: | dataArray

  References

  [1] | Incoherent scattering law for neutron quasi-elastic scattering in liquid crystals. Dianoux, A., Volino, F. & Hervet, H., Mol. Phys. 30, 37–41 (1975).

  Examples

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100]
      ql=np.r_[1:14.1:1.3]
      p=js.grace()
      iqw=js.dL([js.dynamic.nSiteJumpDiffusion_w(w=w,q=q,N=3,t0=0.001,r0=0.12) for q in ql])
      p.plot(iqw)

`jscatter.dynamic.` `resolution`(t, s0=1, m0=0, s1=None, m1=None, s2=None, m2=None, s3=None, m3=None, s4=None, m4=None, s5=None, m5=None, a0=1, a1=1, a2=1, a3=1, a4=1, a5=1, bgr=0, resolution_w=None)

  Resolution in time domain as multiple Gaussians for inelastic measurement as back scattering or time of flight instrument.

  Multiple Gaussians define the function to describe a resolution measurement. Use resolution_w to fit with the appropriate normalized Gaussians. See Notes

  Parameters: | t : array Times s0,s1,… : float Width of Gaussian functions representing a resolution measurement. The number of si not None determines the number of Gaussians. m0, m1,…. : float, None Means of the Gaussian functions representing a resolution measurement. a0, a1,…. : float, None Amplitudes of the Gaussian functions representing a resolution measurement. bgr : float, default=0 Background resolution_w : dataArray Resolution in w domain with attributes sigmas, amps which are used instead of si, ai. This represents the Fourier transform of multi gauss resolution from w to t domain. The m0..m5 are NOT used as these result only in a phase shift.
  Returns: | dataArray

  Notes

  In a typical inelastic experiment the resolution is measured by e.g. a vanadium measurement (elastic scatterer). This is described in w domain by a multi Gaussian function as in resw=resolution_w(w,…) with amplitudes ai_w, width si_w and common mean m_w. resolution(t,resolution_w=resw) defines the Fourier transform of resolution_w using the same coefficients. mi_t are set by default to zero as mi_w lead only to a phase shift. It is easiest to shift w values in w domain as it corresponds to a shift of the elastic line.

  The used Gaussians are normalized that they are a pair of Fourier transforms:

  R_t(t,m_i,s_i,a_i)=\sum_i a_i s_i e^{-\frac{1}{2}s_i^2 t^2} \Leftrightarrow R_w(w,m_i,s_i,a_i)=\sum_i a_i e^{-\frac{1}{2}(\frac{w-m_i}{s_i})^2}

  under the Fourier transform defined as

  F(f(t)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(t) e^{-i\omega t} dt

  F(f(w)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(\omega) e^{i\omega t} d\omega

  Examples

      import jscatter as js
      resw=js.dynamic.resolution_w(w, s0=12, m0=0, a0=2) # resolution in w domain
      # representing the Fourier transform of resw as a gaussian transforms to a gaussian
      rest=js.dynamic.resolution(t,resolution=resw)

`jscatter.dynamic.` `resolution_w`(w, s0=1, m0=0, s1=None, m1=None, s2=None, m2=None, s3=None, m3=None, s4=None, m4=None, s5=None, m5=None, a0=1, a1=1, a2=1, a3=1, a4=1, a5=1, bgr=0, resolution=None)

  Resolution as multiple Gaussians for inelastic measurement as backscattering or time of flight instrument in w domain.

  Multiple Gaussians define the function to describe a resolution measurement. Use only a common mi to account for a shift. See resolution for transform to time domain.

  Parameters: | w : array Frequencies s0,s1,… : float Sigmas of several Gaussian functions representing a resolution measurement. The number of si not none determines the number of Gaussians. m0, m1,…. : float, None Means of the Gaussian functions representing a resolution measurement. a0, a1,…. : float, None Amplitudes of the Gaussian functions representing a resolution measurement. bgr : float, default=0 Background resolution : dataArray Resolution in t space with attributes means, sigmas, amps which are used instead of si, mi, ai. This represents the fourier transform of multi gauss resolution from t to w space. The mi are used as mi from resolution_w result in a phase shift.
  Returns: | dataArray .means .amps .sigmas

  Notes

  In a typical inelastic experiment the resolution is measured by e.g. a vanadium measurement (elastic scatterer). This is described in w domain by a multi Gaussian function as in resw=resolution_w(w,…) with amplitudes ai_w, width si_w and common mean m_w. resolution(t,resolution_w=resw) defines the Fourier transform of resolution_w using the same coefficients. mi_t are set by default to zero as mi_w lead only to a phase shift. It is easiest to shift w values in w domain as it corresponds to a shift of the elastic line.

  The used Gaussians are normalized that they are a pair of Fourier transforms:

  R_t(t,m_i,s_i,a_i)=\sum_i a_i s_i e^{-\frac{1}{2}s_i^2 t^2} \Leftrightarrow R_w(w,m_i,s_i,a_i)=\sum_i a_i e^{-\frac{1}{2}(\frac{w-m_i}{s_i})^2}

  under the Fourier transform defined as

  F(f(t)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(t) e^{-i\omega t} dt

  F(f(w)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(\omega) e^{i\omega t} d\omega

  Examples

      import jscatter as js
      # read data
      vana=js.dL('vana_0p2mm.scat') # use your files here
      start={'s0':0.5,'m0':0,'a0':1,'bgr':0.0073}
      dm=5
      vana[0].setlimit(m0=[-dm,dm],m1=[-dm,dm],m2=[-dm,dm],m3=[-dm,dm],m4=[-dm,dm],m5=[-dm,dm])
      vana[0].fit(js.dynamic.resolution_w,start,{},{'w':'X'})

`jscatter.dynamic.` `rotDiffusion`(t, q, cloud, Dr, lmax='auto')

  Rotational diffusion of an object (dummy atoms); dynamic structure factor in time domain.

  A cloud of dummy atoms can be used for coarse graining of a non-spherical object e.g. for amino acids in proteins. On the other hand its just a way to integrate over an object e.g. a sphere or ellipsoid. We use [2] for an objekt of arbitrary shape modified for incoherent scattering.

  Parameters: | t : array Times in ns. q : float Wavevector in units 1/nm cloud : array Nx3, Nx4 or Nx5 or float A cloud of N dummy atoms with positions cloud[:3] that describe an object. If given, cloud[3] is the incoherent scattering length b_{inc}. If given, cloud[4] is the coherent scattering length b_{coh} If cloud[3] not given b_{inc}=b_{coh}=1. If cloud is single float the value is used as radius of a sphere with 10x10x10 grid. Dr : float Rotational diffusion constant in units 1/ns. lmax : int Maximum order of spherical bessel function. ‘auto’ -> lmax > pi*r.max()*q/6.
  Returns: | dataArray with [t;Iqtinc;Iqtcoh] .radiusOfGyration .Iq_coh coherent formfactor .Iq_inc .wavevector .rotDiffusion .lmax

  Notes

  - The incoherent intermediate scattering function is res.Y/res.Iq_inc
  - The coherent intermediate scattering function is res[2]/res.Iq_coh

  References

  [1] | Incoherent scattering law for neutron quasi-elastic scattering in liquid crystals. Dianoux, A., Volino, F. & Hervet, H. Mol. Phys. 30, 37–41 (1975).

  [2] | (1, 2) Effect of rotational diffusion on quasielastic light scattering from fractal colloid aggregates. Lindsay, H., Klein, R., Weitz, D., Lin, M. & Meakin, P. Phys. Rev. A 38, 2614–2626 (1988).

  Examples

      import jscatter as js
      import numpy as np
      R=2;NN=5
      grid= np.mgrid[-R:R:1j*NN, -R:R:1j*NN,-R:R:1j*NN].reshape(3,-1).T
      # points inside of sphere with radius R
      p2=1*2*0.5 # p defines a superball with 1->sphere p=inf cuboid ....
      inside=lambda xyz,R:(np.abs(xyz[:,0])/R)**p2+(np.abs(xyz[:,1])/R)**p2+(np.abs(xyz[:,2])/R)**p2<=1
      insidegrid=grid[inside(grid,R)]
      Drot=js.formel.Drot(R)
      ql=np.r_[0.5:15.:1]
      t=js.loglist(1,200,100)
      p=js.grace()
      p.new_graph(xmin=0.25,xmax=0.55,ymin=0.2,ymax=0.5)
      iqt=js.dL([js.dynamic.rotDiffusion(t,q,insidegrid,Drot) for q in ql])
      for iiqt in iqt:
         #p[0].plot(iiqt.X,iiqt.Y/iiqt.Iq_inc,le='q=%.3g nm\S-1' %(iiqt.wavevector))
         p[0].plot(iiqt.X,iiqt[2]/iiqt.Iq_coh,le='q=%.3g nm\S-1' %(iiqt.wavevector))

      p[1].plot(iqt.wavevector,iqt.Iq_coh,li=1)
      p[0].xaxis(min=1,max=100,scale='l')
      p[0].yaxis(min=0.8,max=1.03,scale='n')
      p[0].legend()
      # Dependent on the contributing spherical harmonics for a given q value positive correlation
      # in the intermediate scattering function may appear.

`jscatter.dynamic.` `rotDiffusion_w`(w, q, cloud, Dr, lmax='auto')

  Rotational diffusion of an object (dummy atoms); dynamic structure factor in w domain.

  A cloud of dummy atoms can be used for coarse graining of a non-spherical object e.g. for amino acids in proteins. On the other hand its just a way to integrate over an object e.g. a sphere or ellipsoid. We use [2] for an objekt of arbitrary shape modified for incoherent scattering.

  Parameters: | w : array Frequencies in 1/ns q : float Wavevector in units 1/nm cloud : array Nx3, Nx4 or Nx5 or float A cloud of N dummy atoms with positions cloud[:3] that describe an object. If given, cloud[3] is the incoherent scattering length b_{inc}. If given, cloud[4] is the coherent scattering length If cloud[3] not given b_{inc}=b_{coh}=1. If cloud is single float the value is used as radius of a sphere with 10x10x10 grid. Dr : float Rotational diffusion constant in units 1/ns. lmax : int Maximum order of spherical bessel function. ‘auto’ -> lmax > pi*r.max()*q/6.
  Returns: | dataArray with [w;Iqwinc;Iqwcoh]

  References

  [1] | Incoherent scattering law for neutron quasi-elastic scattering in liquid crystals. Dianoux, A., Volino, F. & Hervet, H. Mol. Phys. 30, 37–41 (1975).

  [2] | (1, 2) Effect of rotational diffusion on quasielastic light scattering from fractal colloid aggregates. Lindsay, H., Klein, R., Weitz, D., Lin, M. & Meakin, P. Phys. Rev. A 38, 2614–2626 (1988).

  Examples

      import jscatter as js
      import numpy as np
      R=2;NN=5
      grid= np.mgrid[-R:R:1j*NN, -R:R:1j*NN,-R:R:1j*NN].reshape(3,-1).T
      # points inside of sphere with radius R
      p2=1*2 # p defines a superball with 1->sphere p=inf cuboid ....
      inside=lambda xyz,R:(np.abs(xyz[:,0])/R)**p2+(np.abs(xyz[:,1])/R)**p2+(np.abs(xyz[:,2])/R)**p2<=1
      insidegrid=grid[inside(grid,R)]
      Drot=js.formel.Drot(R)
      ql=np.r_[0.5:15.:2]
      w=np.r_[-100:100:0.1]
      p=js.grace()
      iqwR=js.dL([js.dynamic.rotDiffusion_w(w,q,insidegrid,Drot) for q in ql])
      p.plot(iqwR,le='NN=%.1g q=$wavevector nm\S-1' %(NN))
      iqwR=js.dL([js.dynamic.rotDiffusion_w(w,q,2,Drot) for q in ql])
      p.plot(iqwR,li=1,sy=0,le='NN=10 $wavevector nm\S-1')
      p.yaxis(min=-0.001,max=0.001,scale='n')
      p.legend()

`jscatter.dynamic.` `shiftAndBinning`(data, w=None, dw=None, w0=0)

  Shift spectrum and average (binning) in intervals.

  The intention is to shift spectra and average over intervals. It should be used after convolution with the instrument resolution, when singular values at zero are smeared by resolution.

  Parameters: | data : dataArray Data (from model) to be shifted and averaged in intervals to meet experimental data. w : array New X values (e.g. from experiment). If w is None data.X values are used. w0 : float Shift by w0 that wnew=wold+w0 dw : float, default None Average over intervals between [w[i]-dw,w[i]+dw] to average over a detector pixel width. If None dw is half the interval to neighbouring points. If 0 the value is only linear interpolated to w values and not averaged (about 10 times faster).
  Returns: | dataArray

  Notes

  For averaging over intervals scipy.interpolate.CubicSpline is used with integration in the intervals.

  Examples

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100:0.5]
      start={'s0':6,'m0':0,'a0':1,'s1':None,'m1':0,'a1':1,'bgr':0.00}
      resolution=js.dynamic.resolution_w(w,**start)
      p=js.grace()
      p.plot(resolution)
      p.plot(js.dynamic.shiftAndBinning(resolution,w0=5,dw=0))

`jscatter.dynamic.` `simpleDiffusion`(q, t, D, amplitude=1)

  Intermediate scattering function for diffusing particles.

  Parameters: | q : float, array Wavevector t : float, array Times amplitude : float Prefactor D : float Diffusion coefficient in units [ [q]**-2/[t] ]
  Returns: | dataArray

  Notes

  I(q,t)=Ae^{-q^2Dt}

`jscatter.dynamic.` `stretchedExp`(t, gamma, beta, amp=1)

  Stretched exponential function.

  Parameters: | t : array Times gamma : float Relaxation rate in units 1/[unit t] beta : float Stretched exponent amp : float default 1 Amplitude
  Returns: | dataArray

`jscatter.dynamic.` `t2fFF`(timemodel, resolution, w=None, tfactor=7, **kwargs)

  Fast Fourier transform from time domain to frequency domain for inelastic neutron scattering.

  Shortcut t2fFF calls this function.

  Parameters: | timemodel : function, None Model for I(t,q) in time domain. t in units of ns. The values for t are determined from w as t=[0..n_{max}]\Delta t with \Delta t=1/max(|w|) and n_{max}=w_{max}/\sigma_{min} tfactor. \sigma_{min} is the minimal width of the Gaussians given in resolution. If None a constant function (elastic scattering) is used. resolution : dataArray, float, string dataArray that describes the resolution function as multiple Gaussians (use resolution_w). A nonzero bgr in resolution is ignored and needs to be added afterwards. float : value is used as width of a single Gaussian in units 1/ns (w is needed below). Resolution width is in the range of 6 1/ns (IN5 TOF) to 1 1/ns (Spheres BS). string : no resolution (‘elastic’) w : array Frequencies for the result, e.g. from experimental data. If w is None the frequencies resolution.X are used. This allows to use the fit of a resolution to be used with same w values. kwargs : keyword args Additional keyword arguments that are passed to timemodel. tfactor : float, default 7 Factor to determine max time for timemodel to minimize spectral leakage. tmax=1/(min(resolution_width)*tfactor) determines the resolution to decay as e^{-tfactor^2/2}. THe time step is dt=1/max(|w|). A minimum of len(w) steps is used (which might increase tmax). Increase tfactor if artifacts (wobbling) from the limited time window are visible as the limited time interval acts like a window function (box) for the Fourier transform.
  Returns: | dataArray : A symmetric spectrum is returned. .Sq \rightarrow S(q)=\int_{-\omega_{min}}^{\omega_{max}}S(Q,\omega)d\omega\approx\int_{-\infty}^{\infty} S(Q,\omega)d\omega = I(q,t=0) Integration is done by a cubic spline in w domain on the ‘raw’ fourier transform of timemodel. .Iqt timemodel(t,kwargs) dataarray returned from timemodel. Implicitly this is the Fourier transform to time domain after a successful fit in w domain. Using a heuristic model in time domain as multiple Gaussians or stretched exponential allows a convenient transform to time domain of experimental data.

  Notes

  We use Fourier transform with real signals. The transform is defined as

  F(f(t)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(t) e^{-i\omega t} dt

  F(f(w)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(\omega) e^{i\omega t} d\omega

  The resolution function is defined as (see resolution_w)

  R_w(w,m_i,s_i,a_i)&= \sum_i a_i e^{-\frac{1}{2}(\frac{w-m_i}{s_i})^2} = F(R_t(t)) \\ &=\frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} \sum_i{a_i s_i e^{-\frac{1}{2}s_i^2t^2}} e^{-i\omega t} dt

  using the resolution in time domain with same coefficients R_t(t,m_i,s_i,a_i)=\sum_i a_i s_i e^{-\frac{1}{2}s_i^2 t^2}

  The Fourier transform of a timemodel I(q,t) is

  I(q,w) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} I(q,t) e^{-i\omega t} dt

  The integral is calculated by Fast Fourier transform as

  I(q,m\Delta w) = \frac{1}{\sqrt{2\pi}} \Delta t \sum_{n=-N}^{N} I(q,n\Delta t) e^{-i mn/N}

  t_{max}=tfactor/min(s_i). Due to the cutoff at t_{max} a wobbling might appear indicating spectral leakage. Spectral leakage results from the cutoff, which can be described as multiplication with a box function. The corresponding Fourier Transform is a sinc function visible in the frequency spectrum (wobbling). If the resolution is included in time domain, it acts like a window function to reduce spectral leakage with vanishing values at t_{max}=N\Delta t. The second possibility (default) is to increase t_{max} (increase tfactor) to make the sinc sharp and with low wobbling amplitude.

  Mixed domain models

  Associativity and Convolution theorem allow to mix models from frequency domain and time domain. After transformation to frequency domain the w domain models have to be convoluted with the FFT transformed model.

  Examples

  Other usage example with a comparison of w domain and transformed from time domain can be found in A comparison of different dynamic models in frequency domain .

  Compare transDiffusion transform from time domain with direct convolution in w domain.

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100:0.5]
      start={'s0':6,'m0':0,'a0':1,'s1':None,'m1':0,'a1':1,'bgr':0.00}
      resolution=js.dynamic.resolution_w(w,**start)
      p=js.grace()
      D=0.035;qq=3  # diffusion coefficient of protein alcohol dehydrogenase (140 kDa) is 0.035 nm**2/ns
      p.title('Inelastic spectrum IN5 like')
      p.subtitle(r'resolution width about 6 ns\S-1\N, Q=%.2g nm\S-1\N' %(qq))
      # compare diffusion with convolution and transform from time domain
      diff_ffw=js.dynamic.time2frequencyFF(js.dynamic.simpleDiffusion,resolution,q=qq,D=D)
      diff_w=js.dynamic.transDiff_w(w, q=qq, D=D)
      p.plot(diff_w,sy=0,li=[1,3,3],le=r'original diffusion D=%.3g nm\S2\N/ns' %(D))
      p.plot(diff_ffw,sy=[2,0.3,2],le='transform from time domain')
      p.plot(diff_ffw.X,diff_ffw.Y+diff_ffw.Y.max()*1e-3,sy=[2,0.3,7],le=r'transform from time domain with 10\S-3\N bgr')
      # resolution has to be normalized in convolve
      diff_cw=js.dynamic.convolve(diff_w,resolution,normB=1)
      p.plot(diff_cw,sy=0,li=[1,3,4],le='after convolution in w domain')
      p.plot(resolution.X,resolution.Y/resolution.integral,sy=0,li=[1,1,1],le='resolution')
      p.yaxis(min=1e-6,max=5,scale='l',label='S(Q,w)')
      p.xaxis(min=-100,max=100,label='w / ns\S-1')
      p.legend()
      p.text(string=r'convolution edge ==>\nmake broader and cut',x=10,y=8e-6)

  Compare the resolutions direct and from transform from time domain.

      p=js.grace()
      fwres=js.dynamic.time2frequencyFF(None,resolution)
      p.plot(fwres,le='fft only resolution')
      p.plot(resolution,sy=0,li=2,le='original resolution')

`jscatter.dynamic.` `time2frequencyFF`(timemodel, resolution, w=None, tfactor=7, **kwargs)

  Fast Fourier transform from time domain to frequency domain for inelastic neutron scattering.

  Shortcut t2fFF calls this function.

  Parameters: | timemodel : function, None Model for I(t,q) in time domain. t in units of ns. The values for t are determined from w as t=[0..n_{max}]\Delta t with \Delta t=1/max(|w|) and n_{max}=w_{max}/\sigma_{min} tfactor. \sigma_{min} is the minimal width of the Gaussians given in resolution. If None a constant function (elastic scattering) is used. resolution : dataArray, float, string dataArray that describes the resolution function as multiple Gaussians (use resolution_w). A nonzero bgr in resolution is ignored and needs to be added afterwards. float : value is used as width of a single Gaussian in units 1/ns (w is needed below). Resolution width is in the range of 6 1/ns (IN5 TOF) to 1 1/ns (Spheres BS). string : no resolution (‘elastic’) w : array Frequencies for the result, e.g. from experimental data. If w is None the frequencies resolution.X are used. This allows to use the fit of a resolution to be used with same w values. kwargs : keyword args Additional keyword arguments that are passed to timemodel. tfactor : float, default 7 Factor to determine max time for timemodel to minimize spectral leakage. tmax=1/(min(resolution_width)*tfactor) determines the resolution to decay as e^{-tfactor^2/2}. THe time step is dt=1/max(|w|). A minimum of len(w) steps is used (which might increase tmax). Increase tfactor if artifacts (wobbling) from the limited time window are visible as the limited time interval acts like a window function (box) for the Fourier transform.
  Returns: | dataArray : A symmetric spectrum is returned. .Sq \rightarrow S(q)=\int_{-\omega_{min}}^{\omega_{max}}S(Q,\omega)d\omega\approx\int_{-\infty}^{\infty} S(Q,\omega)d\omega = I(q,t=0) Integration is done by a cubic spline in w domain on the ‘raw’ fourier transform of timemodel. .Iqt timemodel(t,kwargs) dataarray returned from timemodel. Implicitly this is the Fourier transform to time domain after a successful fit in w domain. Using a heuristic model in time domain as multiple Gaussians or stretched exponential allows a convenient transform to time domain of experimental data.

  Notes

  We use Fourier transform with real signals. The transform is defined as

  F(f(t)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(t) e^{-i\omega t} dt

  F(f(w)) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(\omega) e^{i\omega t} d\omega

  The resolution function is defined as (see resolution_w)

  R_w(w,m_i,s_i,a_i)&= \sum_i a_i e^{-\frac{1}{2}(\frac{w-m_i}{s_i})^2} = F(R_t(t)) \\ &=\frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} \sum_i{a_i s_i e^{-\frac{1}{2}s_i^2t^2}} e^{-i\omega t} dt

  using the resolution in time domain with same coefficients R_t(t,m_i,s_i,a_i)=\sum_i a_i s_i e^{-\frac{1}{2}s_i^2 t^2}

  The Fourier transform of a timemodel I(q,t) is

  I(q,w) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} I(q,t) e^{-i\omega t} dt

  The integral is calculated by Fast Fourier transform as

  I(q,m\Delta w) = \frac{1}{\sqrt{2\pi}} \Delta t \sum_{n=-N}^{N} I(q,n\Delta t) e^{-i mn/N}

  t_{max}=tfactor/min(s_i). Due to the cutoff at t_{max} a wobbling might appear indicating spectral leakage. Spectral leakage results from the cutoff, which can be described as multiplication with a box function. The corresponding Fourier Transform is a sinc function visible in the frequency spectrum (wobbling). If the resolution is included in time domain, it acts like a window function to reduce spectral leakage with vanishing values at t_{max}=N\Delta t. The second possibility (default) is to increase t_{max} (increase tfactor) to make the sinc sharp and with low wobbling amplitude.

  Mixed domain models

  Associativity and Convolution theorem allow to mix models from frequency domain and time domain. After transformation to frequency domain the w domain models have to be convoluted with the FFT transformed model.

  Examples

  Other usage example with a comparison of w domain and transformed from time domain can be found in A comparison of different dynamic models in frequency domain .

  Compare transDiffusion transform from time domain with direct convolution in w domain.

      import jscatter as js
      import numpy as np
      w=np.r_[-100:100:0.5]
      start={'s0':6,'m0':0,'a0':1,'s1':None,'m1':0,'a1':1,'bgr':0.00}
      resolution=js.dynamic.resolution_w(w,**start)
      p=js.grace()
      D=0.035;qq=3  # diffusion coefficient of protein alcohol dehydrogenase (140 kDa) is 0.035 nm**2/ns
      p.title('Inelastic spectrum IN5 like')
      p.subtitle(r'resolution width about 6 ns\S-1\N, Q=%.2g nm\S-1\N' %(qq))
      # compare diffusion with convolution and transform from time domain
      diff_ffw=js.dynamic.time2frequencyFF(js.dynamic.simpleDiffusion,resolution,q=qq,D=D)
      diff_w=js.dynamic.transDiff_w(w, q=qq, D=D)
      p.plot(diff_w,sy=0,li=[1,3,3],le=r'original diffusion D=%.3g nm\S2\N/ns' %(D))
      p.plot(diff_ffw,sy=[2,0.3,2],le='transform from time domain')
      p.plot(diff_ffw.X,diff_ffw.Y+diff_ffw.Y.max()*1e-3,sy=[2,0.3,7],le=r'transform from time domain with 10\S-3\N bgr')
      # resolution has to be normalized in convolve
      diff_cw=js.dynamic.convolve(diff_w,resolution,normB=1)
      p.plot(diff_cw,sy=0,li=[1,3,4],le='after convolution in w domain')
      p.plot(resolution.X,resolution.Y/resolution.integral,sy=0,li=[1,1,1],le='resolution')
      p.yaxis(min=1e-6,max=5,scale='l',label='S(Q,w)')
      p.xaxis(min=-100,max=100,label='w / ns\S-1')
      p.legend()
      p.text(string=r'convolution edge ==>\nmake broader and cut',x=10,y=8e-6)

  Compare the resolutions direct and from transform from time domain.

      p=js.grace()
      fwres=js.dynamic.time2frequencyFF(None,resolution)
      p.plot(fwres,le='fft only resolution')
      p.plot(resolution,sy=0,li=2,le='original resolution')

`jscatter.dynamic.` `transDiff_w`(w, q, D)

  Translational diffusion; dynamic structure factor in w domain.

  Parameters: | w : array Frequencies in 1/ns q : float Wavevector in nm**-1 D : float Diffusion constant in nm**2/ns
  Returns: | dataArray

  References

  [0] | Scattering of Slow Neutrons by a Liquid Vineyard G Physical Review 1958 vol: 110 (5) pp: 999-1010

`jscatter.dynamic.` `zilmanGranekBicontinious`(t, q, xi, kappa, eta, mt=1, amp=1, eps=1, nGauss=60)

  Dynamics of bicontinuous micro emulsion phases. Zilman-Granek model as Equ B10 in [1]. Coherent scattering.

  On very local scales (however larger than the molecular size) Zilman and Granek represent the amphiphile layer in the bicontinuous network as consisting of an ensemble of independent patches at random orientation of size equal to the correlation length xi. Uses Gauss integration and multiprocessing.

  Parameters: | t : array Time values in ns q : float Scattering vector in 1/A xi : float Correlation length related to the size of patches which are locally planar and determine the width of the peak in static data. unit A A result of the teubnerStrey model to e.g. SANS data. Determines kmin=eps*pi/xi . kappa : float Apparent single membrane bending modulus, unit kT eta : float Solvent viscosity, unit kT*A^3/ns=100/(1.38065*T)*eta[unit Pa*s] Water about 0.001 Pa*s = 0.000243 kT*A^3/ns amp : float, default = 1 Amplitude scaling factor eps : float, default=1 Scaling factor in range [1..1.3] for kmin=eps*pi/xi and rmax=xi/eps. See [1]. mt : float, default 0.1 Membrane thickness in unit A as approximated from molecular size of material. Determines kmax=pi/mt. About 12 Angstrom for tenside C10E4. nGauss : int, default 60 Number of points in Gauss integration
  Returns: | dataList

  Notes

  - For technical reasons, in order to avoid numerical difficulties, the real space upper (rmax integration) cutoff was realized by multiplying the integrand with a Gaussian having a width of eps*xi and integrating over [0,3*eps*xi].

  References

  [1] | (1, 2, 3) Dynamics of bicontinuous microemulsion phases with and without amphiphilic block-copolymers M. Mihailescu, M. Monkenbusch et al J. Chem. Phys. 115, 9563 (2001); http://dx.doi.org/10.1063/1.1413509

  Examples

      import jscatter as js
      import numpy as np
      t=js.loglist(0.1,30,20)
      p=js.grace()
      iqt=js.dynamic.zilmanGranekBicontinious(t=t,q=np.r_[0.03:0.2:0.04],xi=110,kappa=1.,eta=0.24e-3,nGauss=60)
      p.plot(iqt)
      # to use the multiprocessing in a fit of data use memoize
      data=iqt                          # this represent your measured data
      tt=list(set(data.X.flatten))      # a list of all time values
      tt.sort()
      # use correct values from data for q     -> interpolation is exact for q and tt
      zGBmem=js.formel.memoize(q=data.q,t=tt)(js.dynamic.zilmanGranekBicontinious)
      def mfitfunc(t, q, xi, kappa, eta, amp):
         # this will calculate in each fit step for for Q (but calc all) and then take from memoized values
         res= zGBmem(t=t, q=q, xi=xi, kappa=kappa, eta=eta, amp=amp)
         return res.interpolate(q=q,X=t)[0]
      # use mfitfunc for fitting with multiprocessing

`jscatter.dynamic.` `zilmanGranekLamellar`(t, q, df, kappa, eta, mu=0.001, eps=1, amp=1, mt=0.1, nGauss=40)

  Dynamics of lamellar microemulsion phases. Zilman-Granek model as Equ B10 in [1]. Coherent scattering.

  Oriented lamellar phases at the length scale of the inter membrane distance and beyond are performed using small-angle neutrons scattering and neutron spin-echo spectroscopy.

  Parameters: | t : array Time in ns q : float Scattering vector df : float film-film distance. unit A This represents half the periodicity of the structure, generally denoted by d=0.5df which determines the peak position. and determines kmin=eps*pi/df kappa : float Apparent single membrane bending modulus, unit kT mu : float, default 0.001 Angle between q and surface normal in unit rad. For lamellar oriented system this is close to zero in NSE. eta : float Solvent viscosity, unit kT*A^3/ns = 100/(1.38065*T)*eta[unit Pa*s] Water about 0.001 Pa*s = 0.000243 kT*A^3/ns eps : float, default=1 Scaling factor in range [1..1.3] for kmin=eps*pi/xi and rmax=xi/eps amp : float, default 1 Amplitude scaling factor mt : float, default 0.1 Membrane thickness in unit A as approximated from molecular size of material. Determines kmax=pi/mt About 12 Angstrom for tenside C10E4. nGauss : int, default 40 Number of points in Gauss integration
  Returns: | dataList

  Notes

  The integrations are done by nGauss point Gauss quadrature, except for the kmax-kmin integration which is done by adaptive Gauss integration with rtol=0.1/nGauss k< kmax/8 and rtol=1./nGauss k> kmax/8.

  References

  [1] | (1, 2) Neutron scattering study on the structure and dynamics of oriented lamellar phase microemulsions M. Mihailescu, M. Monkenbusch, J. Allgaier, H. Frielinghaus, D. Richter, B. Jakobs, and T. Sottmann Phys. Rev. E 66, 041504 (2002)

  Examples

      import jscatter as js
      import numpy as np
      t=js.loglist(0.1,30,20)
      ql=np.r_[0.08:0.261:0.03]
      p=js.grace()
      iqt=js.dynamic.zilmanGranekLamellar(t=t,q=ql,df=100,kappa=1,eta=2*0.24e-3)
      p.plot(iqt)