source: sasview/park_integration/temp_code_exchange.py @ 6d48919

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 6d48919 was aa36f96, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on documentation

  • Property mode set to 100644
File size: 8.0 KB
RevLine 
[b9d5f88]1"""
[aa36f96]2This file is intended to be a temporary file to communicate in-progress code
3to the developers.
4This file should be removed after its content has been used by the team.
[b9d5f88]5"""
6
7
8# This code belongs in AbstractFitEngine
9class FitData1D:
10    def setFitRange(self,qmin=None,qmax=None):
11        """
[aa36f96]12        Change the fit range.
13        Take into account the fact that if smearing is applied,
14        a wider range in unsmeared Q might be necessary to cover
15        the smeared (observed) Q range.       
[b9d5f88]16        """
17       
18        # Skip Q=0 point, (especially for y(q=0)=None at x[0]).
19        #ToDo: Fix this.
20        if qmin==0.0 and not numpy.isfinite(self.data.y[qmin]):
21            self.qmin = min(self.data.x[self.data.x!=0])
22        elif qmin!=None:                       
23            self.qmin = qmin           
24
25        if qmax !=None:
26            self.qmax = qmax
27           
28        # Range used for input to smearing
29        self._qmin_unsmeared = self.qmin
30        self._qmax_unsmeared = self.qmax   
31       
32        # Determine the range needed in unsmeared-Q to cover
33        # the smeared Q range
34        if self.smearer.__class__.__name__ == 'SlitSmearer':
35            # The entries in the slit smearer matrix remain
36            # large across all bins, so we keep the full Q range.
37            self._qmin_unsmeared = min(self.data.x)
38            self._qmax_unsmeared = max(self.data.x)
39        elif self.smearer.__class__.__name__ == 'QSmearer':
40            # Take 3 sigmas as the offset between smeared and unsmeared space.
41            try:
42                offset = 3.0*max(self.smearer.width)
43                self._qmin_unsmeared = max([min(self.data.x), self.qmin-offset])
44                self._qmax_unsmeared = min([max(self.data.x), self.qmax+offset])
45            except:
46                logging.error("FitData1D.setFitRange: %s" % sys.exc_value)
47       
48
49    def residuals(self, fn):
50        """
[aa36f96]51        Compute residuals.
52       
53        If self.smearer has been set, use if to smear
54        the data before computing chi squared.
55       
56        This is a version based on the current version of residuals.
57       
58        It takes into account the fact that the unsmearing range
59        might need to be wider than the smeared (observed) range.
60       
61        :param fn: function that return model value
62       
63        :return: residuals
64       
[b9d5f88]65        """
66        x,y = [numpy.asarray(v) for v in (self.x,self.y)]
67        if self.dy ==None or self.dy==[]:
68            dy= numpy.zeros(len(y)) 
69        else:
70            dy= numpy.asarray(dy)
71     
72        dy[dy==0]=1
73        idx_unsmeared = (x>=self._qmin_unsmeared) & (x <= self._qmax_unsmeared)
74 
75        # Compute theory data f(x)
76        idx=[]
77        tempy=[]
78        tempfx=[]
79        tempdy=[]
80   
81        _first_bin = None
82        for i_x in range(len(x)):
83            try:
84                if idx_unsmeared[i_x]==True:
85                    if _first_bin is None:
86                        _first_bin = i_x
87                   
88                    value= fn(x[i_x])
89                    idx.append(x[i_x]>=self.qmin and x[i_x]<=self.qmax)
90                    tempfx.append( value)
91                    tempy.append(y[i_x])
92                    tempdy.append(dy[i_x])
93            except:
94                ## skip error for model.run(x)
95                pass
96                 
97        ## Smear theory data
98        # The tempfx array has a length limited by the Q range.
99        if self.smearer is not None:
100            tempfx = self.smearer(tempfx, _first_bin)
101       
102        newy = numpy.asarray(tempy)
103        newfx= numpy.asarray(tempfx)
104        newdy= numpy.asarray(tempdy)
105       
106        ## Sanity check
107        if numpy.size(newdy)!= numpy.size(newfx):
108            raise RuntimeError, "FitData1D: invalid error array %d <> %d" % (numpy.size(newdy), numpy.size(newfx))
109
110        return (newy[idx]-newfx[idx])/newdy[idx]
111     
112     
113    def residuals_alt(self, fn):
114        """
[aa36f96]115        Compute residuals.
116       
117        If self.smearer has been set, use if to smear
118        the data before computing chi squared.
119       
120        This is a more streamlined version of the above. To use this version,
121        the _BaseSmearer class below needs to be modified to have its __call__
122        method have the following signature:
123       
124        __call__(self, iq, first_bin, last_bin)
125       
126        This is because we are storing results in arrays of a length
127        corresponding to the full Q-range.
128       
129        It takes into account the fact that the unsmearing range
130        might need to be wider than the smeared (observed) range.           
131       
132        :param fn: function that return model value
133       
134        :return: residuals
135       
[b9d5f88]136        """
137        # Make sure the arrays are numpy arrays, which are
138        # expected by the fitter.
139        x,y = [numpy.asarray(v) for v in (self.x,self.y)]
140        if self.dy ==None or self.dy==[]:
141            dy= numpy.zeros(len(y)) 
142        else:
143            dy= numpy.asarray(dy)
144     
145        dy[dy==0]=1
146        idx = (x>=self.qmin) & (x <= self.qmax)
147        idx_unsmeared = (x>=self._qmin_unsmeared) & (x <= self._qmax_unsmeared)
148 
149        # Compute theory data f(x)
150        fx= numpy.zeros(len(x))
151   
152        # First and last bins of the array, corresponding to
153        # the Q range to be smeared
154        _first_bin = None
155        _last_bin  = None
156        for i_x in range(len(x)):
157            try:
158                if idx_unsmeared[i_x]==True:
159                    if _first_bin is None:
160                        _first_bin = i_x
161                    else:
162                        _last_bin  = i_x
163                   
164                    value = fn(x[i_x])
165                    fx[i_x] = value
166            except:
167                ## skip error for model.run(x)
168                ## Should properly log the error
169                pass
170                 
171        # Smear theory data
172        if self.smearer is not None:
173            fx = self.smearer(fx, _first_bin, _last_bin)
174       
175        # Sanity check
176        if numpy.size(dy)!= numpy.size(fx):
177            raise RuntimeError, "FitData1D: invalid error array %d <> %d" % (numpy.size(dy), numpy.size(fx))
178
179        # Return the residuals for the smeared (observed) Q range
180        return (y[idx]-fx[idx])/dy[idx]
181     
182# The following code belongs in DataLoader.qsmearing
183class _BaseSmearer(object):
184   
185    def __init__(self):
186        self.nbins = 0
187        self._weights = None
188       
189    def _compute_matrix(self): return NotImplemented
190
191    def __call__(self, iq, first_bin=0):
192        """
[aa36f96]193        Return the smeared I(q) value at the given q.
194        The smeared I(q) is computed using a predetermined
195        smearing matrix for a particular binning.
196   
197        :param q: I(q) array
198        :param first_bin: first bin of the given iq array if shorter than full data length
199       
200        :return: smeared I(q)
[b9d5f88]201       
202        """
203        # Sanity check
204        if len(iq)+first_bin > self.nbins:
205            raise RuntimeError, "Invalid I(q) vector: inconsistent array length %s > %s" % (str(len(iq)+first_bin), str(self.nbins))
206       
207        if self._weights == None:
208            self._compute_matrix()
209           
210        iq_smeared = numpy.zeros(len(iq))
211        # Loop over q-values
212        idwb=[]
213       
214        for q_i in range(len(iq)):
215            sum = 0.0
216            counts = 0.0 
217            for i in range(len(iq)):
218                if iq[i]==0 or self._weights[q_i+first_bin][i+first_bin]==0:
219                    continue
220                else:
221                    sum += iq[i] * self._weights[q_i+first_bin][i+first_bin] 
222                    counts += self._weights[q_i+first_bin][i+first_bin]
223           
224            if counts == 0:
225                iq_smeared[q_i] = 0
226            else:
227                iq_smeared[q_i] = sum/counts
228        return iq_smeared             
Note: See TracBrowser for help on using the repository browser.