source: sasview/DataLoader/qsmearing.py @ a96d246

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since a96d246 was a3f8d58, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

dataloader: converted smearing to C and allowed for partial Q range

  • Property mode set to 100644
File size: 9.3 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2009, University of Tennessee
9"""
10
11import DataLoader.extensions.smearer as smearer
12import numpy
13import math
14import scipy.special
15
16def smear_selection(data1D):
17    """
18        Creates the right type of smearer according
19        to the data.
20   
21        The canSAS format has a rule that either
22        slit smearing data OR resolution smearing data
23        is available.
24       
25        For the present purpose, we choose the one that
26        has none-zero data. If both slit and resolution
27        smearing arrays are filled with good data
28        (which should not happen), then we choose the
29        resolution smearing data.
30       
31        @param data1D: Data1D object
32    """
33    # Sanity check. If we are not dealing with a SANS Data1D
34    # object, just return None
35    if  data1D.__class__.__name__ != 'Data1D':
36        return None
37   
38    if  not hasattr(data1D, "dx") and not hasattr(data1D, "dxl") and not hasattr(data1D, "dxw"):
39        return None
40   
41    # Look for resolution smearing data
42    _found_resolution = False
43    if data1D.dx is not None and len(data1D.dx)==len(data1D.x):
44       
45        # Check that we have non-zero data
46        if data1D.dx[0]>0.0:
47            _found_resolution = True
48            #print "_found_resolution",_found_resolution
49            #print "data1D.dx[0]",data1D.dx[0],data1D.dxl[0]
50    # If we found resolution smearing data, return a QSmearer
51    if _found_resolution == True:
52        return QSmearer(data1D)
53
54    # Look for slit smearing data
55    _found_slit = False
56    if data1D.dxl is not None and len(data1D.dxl)==len(data1D.x) \
57        and data1D.dxw is not None and len(data1D.dxw)==len(data1D.x):
58       
59        # Check that we have non-zero data
60        if data1D.dxl[0]>0.0 or data1D.dxw[0]>0.0:
61            _found_slit = True
62       
63        # Sanity check: all data should be the same as a function of Q
64        for item in data1D.dxl:
65            if data1D.dxl[0] != item:
66                _found_resolution = False
67                break
68           
69        for item in data1D.dxw:
70            if data1D.dxw[0] != item:
71                _found_resolution = False
72                break
73    # If we found slit smearing data, return a slit smearer
74    if _found_slit == True:
75        return SlitSmearer(data1D)
76   
77    return None
78           
79
80class _BaseSmearer(object):
81   
82    def __init__(self):
83        self.nbins = 0
84        self._weights = None
85        ## Internal flag to keep track of C++ smearer initialization
86        self._init_complete = False
87        self._smearer = None
88       
89    def __deepcopy__(self, memo={}):
90        """
91            Return a valid copy of self.
92            Avoid copying the _smearer C object and force a matrix recompute
93            when the copy is used. 
94        """
95        result = _BaseSmearer()
96        result.nbins = self.nbins
97        return result
98
99       
100    def _compute_matrix(self): return NotImplemented
101
102    def __call__(self, iq_in, first_bin=0, last_bin=None):
103        """
104            Perform smearing
105        """
106        # If this is the first time we call for smearing,
107        # initialize the C++ smearer object first
108        if not self._init_complete:
109            self._initialize_smearer()
110             
111        # Get the max value for the last bin
112        if last_bin is None or last_bin>=len(iq_in):
113            last_bin = len(iq_in)-1
114        # Check that the first bin is positive
115        if first_bin<0:
116            first_bin = 0
117           
118        # Sanity check
119        if len(iq_in) != self.nbins:
120            raise RuntimeError, "Invalid I(q) vector: inconsistent array length %d != %s" % (len(iq_in), str(self.nbins))
121             
122        # Storage for smeared I(q)   
123        iq_out = numpy.zeros(self.nbins)
124        smearer.smear(self._smearer, iq_in, iq_out, first_bin, last_bin)
125        return iq_out
126   
127class _SlitSmearer(_BaseSmearer):
128    """
129        Slit smearing for I(q) array
130    """
131   
132    def __init__(self, nbins=None, width=None, height=None, min=None, max=None):
133        """
134            Initialization
135           
136            @param iq: I(q) array [cm-1]
137            @param width: slit width [A-1]
138            @param height: slit height [A-1]
139            @param min: Q_min [A-1]
140            @param max: Q_max [A-1]
141        """
142        _BaseSmearer.__init__(self)
143        ## Slit width in Q units
144        self.width  = width
145        ## Slit height in Q units
146        self.height = height
147        ## Q_min (Min Q-value for I(q))
148        self.min    = min
149        ## Q_max (Max Q_value for I(q))
150        self.max    = max
151        ## Number of Q bins
152        self.nbins  = nbins
153        ## Number of points used in the smearing computation
154        self.npts   = 10000
155        ## Smearing matrix
156        self._weights = None
157       
158    def _initialize_smearer(self):
159        """
160            Initialize the C++ smearer object.
161            This method HAS to be called before smearing
162        """
163        self._smearer = smearer.new_slit_smearer(self.width, self.height, self.min, self.max, self.nbins)
164        self._init_complete = True
165
166
167class SlitSmearer(_SlitSmearer):
168    """
169        Adaptor for slit smearing class and SANS data
170    """
171    def __init__(self, data1D):
172        """
173            Assumption: equally spaced bins of increasing q-values.
174           
175            @param data1D: data used to set the smearing parameters
176        """
177        # Initialization from parent class
178        super(SlitSmearer, self).__init__()
179       
180        ## Slit width
181        self.width = 0
182        if data1D.dxw is not None and len(data1D.dxw)==len(data1D.x):
183            self.width = data1D.dxw[0]
184            # Sanity check
185            for value in data1D.dxw:
186                if value != self.width:
187                    raise RuntimeError, "Slit smearing parameters must be the same for all data"
188               
189        ## Slit height
190        self.height = 0
191        if data1D.dxl is not None and len(data1D.dxl)==len(data1D.x):
192            self.height = data1D.dxl[0]
193            # Sanity check
194            for value in data1D.dxl:
195                if value != self.height:
196                    raise RuntimeError, "Slit smearing parameters must be the same for all data"
197       
198        ## Number of Q bins
199        self.nbins = len(data1D.x)
200        ## Minimum Q
201        self.min = data1D.x[0]
202        ## Maximum
203        self.max = data1D.x[len(data1D.x)-1]       
204
205        #print "nbin,npts",self.nbins,self.npts
206
207class _QSmearer(_BaseSmearer):
208    """
209        Perform Gaussian Q smearing
210    """
211       
212    def __init__(self, nbins=None, width=None, min=None, max=None):
213        """
214            Initialization
215           
216            @param nbins: number of Q bins
217            @param width: array standard deviation in Q [A-1]
218            @param min: Q_min [A-1]
219            @param max: Q_max [A-1]
220        """
221        _BaseSmearer.__init__(self)
222        ## Standard deviation in Q [A-1]
223        self.width  = width
224        ## Q_min (Min Q-value for I(q))
225        self.min    = min
226        ## Q_max (Max Q_value for I(q))
227        self.max    = max
228        ## Number of Q bins
229        self.nbins  = nbins
230        ## Smearing matrix
231        self._weights = None
232       
233    def _initialize_smearer(self):
234        """
235            Initialize the C++ smearer object.
236            This method HAS to be called before smearing
237        """
238        self._smearer = smearer.new_q_smearer(numpy.asarray(self.width), self.min, self.max, self.nbins)
239        self._init_complete = True
240       
241class QSmearer(_QSmearer):
242    """
243        Adaptor for Gaussian Q smearing class and SANS data
244    """
245    def __init__(self, data1D):
246        """
247            Assumption: equally spaced bins of increasing q-values.
248           
249            @param data1D: data used to set the smearing parameters
250        """
251        # Initialization from parent class
252        super(QSmearer, self).__init__()
253       
254        ## Resolution
255        self.width = numpy.zeros(len(data1D.x))
256        if data1D.dx is not None and len(data1D.dx)==len(data1D.x):
257            self.width = data1D.dx
258       
259        ## Number of Q bins
260        self.nbins = len(data1D.x)
261        ## Minimum Q
262        self.min = data1D.x[0]
263        ## Maximum
264        self.max = data1D.x[len(data1D.x)-1]       
265
266
267if __name__ == '__main__':
268    x = 0.001*numpy.arange(1,11)
269    y = 12.0-numpy.arange(1,11)
270    print x
271    #for i in range(10): print i, 0.001 + i*0.008/9.0
272    #for i in range(100): print i, int(math.floor( (i/ (100/9.0)) ))
273
274   
275    s = _SlitSmearer(nbins=10, width=0.0, height=0.005, min=0.001, max=0.010)
276    #s = _QSmearer(nbins=10, width=0.001, min=0.001, max=0.010)
277    s._compute_matrix()
278
279    sy = s(y)
280    print sy
281   
282    if True:
283        for i in range(10):
284            print x[i],y[i], sy[i]
285            #print q, ' : ', s.weight(q), s._compute_iq(q)
286            #print q, ' : ', s(q), s._compute_iq(q)
287            #s._compute_iq(q)
288
289
290
291
Note: See TracBrowser for help on using the repository browser.