source: sasmodels/sasmodels/sesans.py @ 589b740

core_shell_microgelscostrafo411magnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 589b740 was 589b740, checked in by jhbakker, 8 years ago

test branch for SEsans class in sesans.py

  • Property mode set to 100644
File size: 3.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, exp  # type: ignore
16#from scipy.special import jv as besselj
17from scipy.special import j0
18#from mpmath import j0 as j0
19#from mpmath import besselj
20#from mpmath import mpf
21from src.sas.sascalc.data_util.nxsunit import Converter
22#from sas.sasgui.perspectives.fitting.fitpage import FitPage
23#import direct_model.DataMixin as model
24       
25def make_q(q_max, Rmax):
26    r"""
27    Return a $q$ vector suitable for SESANS covering from $2\pi/ (10 R_{\max})$
28    to $q_max$. This is the integration range of the Hankel transform; bigger range and
29    more points makes a better numerical integration.
30    Smaller q_min will increase reliable spin echo length range.
31    Rmax is the "radius" of the largest expected object and can be set elsewhere.
32    q_max is determined by the acceptance angle of the SESANS instrument.
33    """
34    from sas.sascalc.data_util.nxsunit import Converter
35
36    q_min = dq = 0.1 * 2*pi / Rmax
37    return np.arange(q_min,
38                     Converter(q_max[1])(q_max[0],
39                                         units="1/A"),
40                     dq)
41
42def Hankelconstructor(data):
43    Rmax = 1000000
44    #Rmax = #value in text box?
45    q_calc = make_q(data.sample.zacceptance, Rmax)
46    SElength = Converter(data._xunit)(data.x, "A")
47    dq = q_calc[1] - q_calc[0]
48    H0 = dq / (2 * pi) * q_calc
49    repSE, repq = np.meshgrid(SElength,q_calc)
50    repq=np.array(repq,dtype='f')
51    repSE=np.array(repSE,dtype='f')
52    H = dq / (2 * pi) * j0(repSE*repq)*repq
53    return H0, H, q_calc
54
55def hankeltrafo(H0, H, Iq_calc):
56    G0 = np.dot(H0, Iq_calc)
57    G = np.dot(H.T, Iq_calc)
58    P = G - G0
59    return P  # This is the logarithmic Polarization, not the linear one as found in Andersson2008!
60
61
62class SesansTransform(object):
63    #: Set of spin-echo lengths in the measured data
64    SElength = None  # type: np.ndarray
65    #: Maximum acceptance of scattering vector in the spin echo encoding dimension (for ToF: Q of min(R) and max(lam))
66    zaccept = None # type: float
67    #: Maximum size sensitivity; larger radius requires more computation
68    Rmax = None  # type: float
69    #: q values to calculate when computing transform
70    q = None  # type: np.ndarray
71
72    # transform arrays
73    _H = None  # type: np.ndarray
74    _H0 = None # type: np.ndarray
75
76    def set_transform(self, SE, zaccept, Rmax):
77        if self.SE is None or len(SE) != len(self.SE) or np.any(SE != self.SE) or zaccept != self.zaccept or Rmax != self.Rmax:
78            self.SE, self.zaccept, self.Rmax = SE, zaccept, Rmax
79            self._set_q()
80            self._set_hankel()
81
82    def apply(self, Iq):
83        G0 = np.dot(self._H0, Iq)
84        G = np.dot(self._H.T, Iq)
85        P = G - G0
86        return P
87
88    def _set_q(self):
89        q_min = dq = 0.1 * 2*pi / self.Rmax
90        q_max = self.zaccept
91        q=np.arange(q_min,q_max)
92        self.q = q
93        self.dq = dq
94
95    def _set_hankel(self):
96        #Rmax = #value in text box somewhere in FitPage?
97        q = self.q
98        dq = self.dq
99        SElength = self.SE
100
101        H0 = dq / (2 * pi) * q
102        repSE, repq = np.meshgrid(SElength,q)
103        repq=np.array(repq,dtype='f')
104        repSE=np.array(repSE,dtype='f')
105        H = dq / (2 * pi) * j0(repSE*repq)*repq
106
107        self._H, self._H0 = H, H0
108
Note: See TracBrowser for help on using the repository browser.