source: sasmodels/sasmodels/sesans.py @ 1c8ff89

Last change on this file since 1c8ff89 was 1c8ff89, checked in by awashington, 5 years ago

Apply Paul's suggested changes

  • Property mode set to 100644
File size: 2.7 KB
Line 
1"""
2Conversion of scattering cross section from SANS (I(q), or rather, ds/dO) in absolute
3units (cm-1)into SESANS correlation function G using a Hankel transformation, then converting
4the SESANS correlation function into polarisation from the SESANS experiment
5
6Everything is in units of metres except specified otherwise (NOT TRUE!!!)
7Everything is in conventional units (nm for spin echo length)
8
9Wim Bouwman (w.g.bouwman@tudelft.nl), June 2013
10"""
11
12from __future__ import division
13
14import numpy as np  # type: ignore
15from numpy import pi  # type: ignore
16from scipy.special import j0
17
18
19class SesansTransform(object):
20    """
21    Spin-Echo SANS transform calculator.  Similar to a resolution function,
22    the SesansTransform object takes I(q) for the set of *q_calc* values and
23    produces a transformed dataset
24
25    *SElength* (A) is the set of spin-echo lengths in the measured data.
26
27    *zaccept* (1/A) is the maximum acceptance of scattering vector in the spin
28    echo encoding dimension (for ToF: Q of min(R) and max(lam)).
29
30    *Rmax* (A) is the maximum size sensitivity; larger radius requires more
31    computation time.
32    """
33    #: SElength from the data in the original data units; not used by transform
34    #: but the GUI uses it, so make sure that it is present.
35    q = None  # type: np.ndarray
36
37    #: q values to calculate when computing transform
38    q_calc = None  # type: np.ndarray
39
40    # transform arrays
41    _H = None   # type: np.ndarray
42    _H0 = None  # type: np.ndarray
43
44    def __init__(self, z, SElength, lam, zaccept, Rmax, log_spacing=1.0003):
45        # type: (np.ndarray, float, float) -> None
46        self.q = z
47        self.log_spacing = log_spacing
48        self._set_hankel(SElength, lam, zaccept, Rmax)
49
50    def apply(self, Iq):
51        # type: (np.ndarray) -> np.ndarray
52        """
53        Apply the SESANS transform to the computed I(q).
54        """
55        G0 = np.dot(self._H0, Iq)
56        G = np.dot(self._H.T, Iq)
57        P = G - G0
58        return P
59
60    def _set_hankel(self, SElength, lam, zaccept, Rmax):
61        # type: (np.ndarray, float, float) -> None
62        SElength = np.asarray(SElength)
63        q_max = 2*pi / (SElength[1] - SElength[0])
64        q_min = 0.1 * 2*pi / (np.size(SElength) * SElength[-1])
65        q = np.exp(np.arange(np.log(q_min), np.log(q_max),
66                             np.log(self.log_spacing)))
67
68        dq = np.diff(q)
69        dq = np.insert(dq, 0, dq[0])
70
71        H0 = dq/(2*pi) * q
72
73        H = np.outer(q, SElength)
74        j0(H, out=H)
75        H *= (dq * q / (2*pi)).reshape((-1, 1))
76
77        reptheta = np.outer(q, lam/2*pi)
78        np.arcsin(reptheta, out=reptheta)
79        mask = reptheta > zaccept
80        H[mask] = 0
81
82        self.q_calc = q
83        self._H, self._H0 = H, H0
Note: See TracBrowser for help on using the repository browser.