source: sasview/src/sas/qtgui/Perspectives/Fitting/FittingLogic.py @ 4d457df

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 4d457df was 4d457df, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Minor refactoring in the fitting widget

  • Property mode set to 100755
File size: 6.9 KB
Line 
1import numpy
2
3from sas.sasgui.guiframe.dataFitting import Data1D
4from sas.sasgui.guiframe.dataFitting import Data2D
5from sas.sascalc.dataloader.data_info import Detector
6from sas.sascalc.dataloader.data_info import Source
7
8
9class FittingLogic(object):
10    """
11    All the data-related logic. This class deals exclusively with Data1D/2D
12    No QStandardModelIndex here.
13    """
14    def __init__(self, data=None):
15        self._data = data
16
17    @property
18    def data(self):
19        return self._data
20
21    @data.setter
22    def data(self, value):
23        """ data setter """
24        self._data = value
25        self.data_is_loaded = True
26
27    def createDefault1dData(self, interval, tab_id=0):
28        """
29        Create default data for fitting perspective
30        Only when the page is on theory mode.
31        """
32        self._data = Data1D(x=interval)
33        self._data.xaxis('\\rm{Q}', "A^{-1}")
34        self._data.yaxis('\\rm{Intensity}', "cm^{-1}")
35        self._data.is_data = False
36        self._data.id = str(tab_id) + " data"
37        self._data.group_id = str(tab_id) + " Model1D"
38
39    def createDefault2dData(self, qmax, qstep, tab_id=0):
40        """
41        Create 2D data by default
42        Only when the page is on theory mode.
43        """
44        self._data = Data2D()
45        self._data.xaxis('\\rm{Q_{x}}', 'A^{-1}')
46        self._data.yaxis('\\rm{Q_{y}}', 'A^{-1}')
47        self._data.is_data = False
48        self._data.id = str(tab_id) + " data"
49        self._data.group_id = str(tab_id) + " Model2D"
50
51        # Default detector
52        self._data.detector.append(Detector())
53        index = len(self._data.detector) - 1
54        self._data.detector[index].distance = 8000   # mm
55        self._data.source.wavelength = 6             # A
56        self._data.detector[index].pixel_size.x = 5  # mm
57        self._data.detector[index].pixel_size.y = 5  # mm
58        self._data.detector[index].beam_center.x = qmax
59        self._data.detector[index].beam_center.y = qmax
60        # theory default: assume the beam
61        #center is located at the center of sqr detector
62        xmax = qmax
63        xmin = -qmax
64        ymax = qmax
65        ymin = -qmax
66
67        x = numpy.linspace(start=xmin, stop=xmax, num=qstep, endpoint=True)
68        y = numpy.linspace(start=ymin, stop=ymax, num=qstep, endpoint=True)
69        # Use data info instead
70        new_x = numpy.tile(x, (len(y), 1))
71        new_y = numpy.tile(y, (len(x), 1))
72        new_y = new_y.swapaxes(0, 1)
73
74        # all data required in 1d array
75        qx_data = new_x.flatten()
76        qy_data = new_y.flatten()
77        q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
78
79        # set all True (standing for unmasked) as default
80        mask = numpy.ones(len(qx_data), dtype=bool)
81        # calculate the range of qx and qy: this way,
82        # it is a little more independent
83        # store x and y bin centers in q space
84        x_bins = x
85        y_bins = y
86
87        self._data.source = Source()
88        self._data.data = numpy.ones(len(mask))
89        self._data.err_data = numpy.ones(len(mask))
90        self._data.qx_data = qx_data
91        self._data.qy_data = qy_data
92        self._data.q_data = q_data
93        self._data.mask = mask
94        self._data.x_bins = x_bins
95        self._data.y_bins = y_bins
96        # max and min taking account of the bin sizes
97        self._data.xmin = xmin
98        self._data.xmax = xmax
99        self._data.ymin = ymin
100        self._data.ymax = ymax
101
102    def new1DPlot(self, return_data):
103        """
104        Create a new 1D data instance based on fitting results
105        """
106        # Unpack return data from Calc1D
107        x, y, page_id, state, weight,\
108        fid, toggle_mode_on, \
109        elapsed, index, model,\
110        data, update_chisqr, source = return_data
111
112        # Create the new plot
113        new_plot = Data1D(x=x, y=y)
114        new_plot.is_data = False
115        new_plot.dy = numpy.zeros(len(y))
116        _yaxis, _yunit = data.get_yaxis()
117        _xaxis, _xunit = data.get_xaxis()
118        new_plot.title = data.name
119
120        new_plot.group_id = data.group_id
121        if new_plot.group_id == None:
122            new_plot.group_id = data.group_id
123        #new_plot.id = str(self.tab_id) + " " + data.name
124        new_plot.name = model.name + " [" + data.name + "]"
125        new_plot.xaxis(_xaxis, _xunit)
126        new_plot.yaxis(_yaxis, _yunit)
127
128        # Assign the new Data1D object-wide
129        self._data = new_plot
130
131    def new2DPlot(self, return_data):
132        """
133        Create a new 2D data instance based on fitting results
134        """
135
136        image, data, page_id, model, state, toggle_mode_on,\
137        elapsed, index, fid, qmin, qmax, weight, \
138        update_chisqr, source = return_data
139
140        numpy.nan_to_num(image)
141        new_plot = Data2D(image=image, err_image=data.err_data)
142        new_plot.name = model.name + '2d'
143        new_plot.title = "Analytical model 2D "
144        new_plot.id = str(page_id) + " " + data.name
145        new_plot.group_id = str(page_id) + " Model2D"
146        new_plot.detector = data.detector
147        new_plot.source = data.source
148        new_plot.is_data = False
149        new_plot.qx_data = data.qx_data
150        new_plot.qy_data = data.qy_data
151        new_plot.q_data = data.q_data
152        new_plot.mask = data.mask
153        ## plot boundaries
154        new_plot.ymin = data.ymin
155        new_plot.ymax = data.ymax
156        new_plot.xmin = data.xmin
157        new_plot.xmax = data.xmax
158
159        title = data.title
160
161        new_plot.is_data = False
162        if data.is_data:
163            data_name = str(data.name)
164        else:
165            data_name = str(model.__class__.__name__) + '2d'
166
167        if len(title) > 1:
168            new_plot.title = "Model2D for %s " % model.name + data_name
169        new_plot.name = model.name + " [" + \
170                                    data_name + "]"
171
172        # Assign the new Data2D object-wide
173        self._data = new_plot
174
175    def computeDataRange(self):
176        """
177        Compute the minimum and the maximum range of the data
178        return the npts contains in data
179        """
180        qmin, qmax, npts = None, None, None
181        if isinstance(self.data, Data1D):
182            try:
183                qmin = min(self.data.x)
184                qmax = max(self.data.x)
185                npts = len(self.data.x)
186            except (ValueError, TypeError):
187                msg = "Unable to find min/max/length of \n data named %s" % \
188                            self.data.filename
189                raise ValueError, msg
190
191        else:
192            qmin = 0
193            try:
194                x = max(numpy.fabs(self.data.xmin), numpy.fabs(self.data.xmax))
195                y = max(numpy.fabs(self.data.ymin), numpy.fabs(self.data.ymax))
196            except (ValueError, TypeError):
197                msg = "Unable to find min/max of \n data named %s" % \
198                            self.data.filename
199                raise ValueError, msg
200            qmax = numpy.sqrt(x * x + y * y)
201            npts = len(self.data.data)
202        return qmin, qmax, npts
Note: See TracBrowser for help on using the repository browser.