source: sasview/src/sas/qtgui/Plotting/PlotterData.py @ ebf86f1

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since ebf86f1 was a54bbf2b, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Added plot roles to Data1D/Data2D structures to allow for smoother plot logic.

  • Property mode set to 100644
File size: 13.1 KB
Line 
1"""
2Adapters for fitting module
3"""
4import copy
5import numpy
6import math
7from sas.sascalc.data_util.uncertainty import Uncertainty
8
9from sas.qtgui.Plotting.Plottables import PlottableData1D
10from sas.qtgui.Plotting.Plottables import PlottableData2D
11
12from sas.sascalc.dataloader.data_info import Data1D as LoadData1D
13from sas.sascalc.dataloader.data_info import Data2D as LoadData2D
14
15
16class Data1D(PlottableData1D, LoadData1D):
17    """
18    """
19    ROLE_DATA=0
20    ROLE_DEFAULT=1
21    ROLE_DELETABLE=2
22    ROLE_RESIDUAL=3
23    def __init__(self, x=None, y=None, dx=None, dy=None):
24        """
25        """
26        if x is None:
27            x = []
28        if y is None:
29            y = []
30        PlottableData1D.__init__(self, x, y, dx, dy)
31        LoadData1D.__init__(self, x, y, dx, dy)
32        self.id = None
33        self.list_group_id = []
34        self.group_id = None
35        self.is_data = True
36        self.path = None
37        self.xtransform = None
38        self.ytransform = None
39        self.title = ""
40        self.scale = None
41        # plot_role:
42        # 0: data - no reload on param change
43        # 1: normal lifecycle (fit)
44        # 2: deletable on model change (Q(I), S(I)...)
45        # 3: separate chart on Show Plot (residuals)
46        self.plot_role = Data1D.ROLE_DEFAULT
47       
48    def copy_from_datainfo(self, data1d):
49        """
50        copy values of Data1D of type DataLaoder.Data_info
51        """
52        self.= copy.deepcopy(data1d.x)
53        self.= copy.deepcopy(data1d.y)
54        self.dy = copy.deepcopy(data1d.dy)
55       
56        if hasattr(data1d, "dx"):
57            self.dx = copy.deepcopy(data1d.dx)   
58        if hasattr(data1d, "dxl"):
59            self.dxl = copy.deepcopy(data1d.dxl)
60        if hasattr(data1d, "dxw"):
61            self.dxw = copy.deepcopy(data1d.dxw)
62   
63        self.xaxis(data1d._xaxis, data1d._xunit)
64        self.yaxis(data1d._yaxis, data1d._yunit)
65        self.title = data1d.title
66        self.isSesans = data1d.isSesans
67       
68    def __str__(self):
69        """
70        print data
71        """
72        _str = "%s\n" % LoadData1D.__str__(self)
73     
74        return _str
75   
76    def _perform_operation(self, other, operation):
77        """
78        """
79        # First, check the data compatibility
80        dy, dy_other = self._validity_check(other)
81        result = Data1D(x=[], y=[], dx=None, dy=None)
82        result.clone_without_data(length=len(self.x), clone=self)
83        result.copy_from_datainfo(data1d=self)
84        if self.dxw is None:
85            result.dxw = None
86        else:
87            result.dxw = numpy.zeros(len(self.x))
88        if self.dxl is None:
89            result.dxl = None
90        else:
91            result.dxl = numpy.zeros(len(self.x))
92
93        for i in range(len(self.x)):
94            result.x[i] = self.x[i]
95            if self.dx is not None and len(self.x) == len(self.dx):
96                result.dx[i] = self.dx[i]
97            if self.dxw is not None and len(self.x) == len(self.dxw):
98                result.dxw[i] = self.dxw[i]
99            if self.dxl is not None and len(self.x) == len(self.dxl):
100                result.dxl[i] = self.dxl[i]
101           
102            a = Uncertainty(self.y[i], dy[i]**2)
103            if isinstance(other, Data1D):
104                b = Uncertainty(other.y[i], dy_other[i]**2)
105                if other.dx is not None:
106                    result.dx[i] *= self.dx[i]
107                    result.dx[i] += (other.dx[i]**2)
108                    result.dx[i] /= 2
109                    result.dx[i] = math.sqrt(result.dx[i])
110                if result.dxl is not None and other.dxl is not None:
111                    result.dxl[i] *= self.dxl[i]
112                    result.dxl[i] += (other.dxl[i]**2)
113                    result.dxl[i] /= 2
114                    result.dxl[i] = math.sqrt(result.dxl[i])
115            else:
116                b = other
117           
118            output = operation(a, b)
119            result.y[i] = output.x
120            result.dy[i] = math.sqrt(math.fabs(output.variance))
121        return result
122   
123    def _perform_union(self, other):
124        """
125        """
126        # First, check the data compatibility
127        self._validity_check_union(other)
128        result = Data1D(x=[], y=[], dx=None, dy=None)
129        tot_length = len(self.x) + len(other.x)
130        result = self.clone_without_data(length=tot_length, clone=result)
131        if self.dy is None or other.dy is None:
132            result.dy = None
133        else:
134            result.dy = numpy.zeros(tot_length)
135        if self.dx is None or other.dx is None:
136            result.dx = None
137        else:
138            result.dx = numpy.zeros(tot_length)
139        if self.dxw is None or other.dxw is None:
140            result.dxw = None
141        else:
142            result.dxw = numpy.zeros(tot_length)
143        if self.dxl is None or other.dxl is None:
144            result.dxl = None
145        else:
146            result.dxl = numpy.zeros(tot_length)
147
148        result.x = numpy.append(self.x, other.x)
149        #argsorting
150        ind = numpy.argsort(result.x)
151        result.x = result.x[ind]
152        result.y = numpy.append(self.y, other.y)
153        result.y = result.y[ind]
154        if result.dy is not None:
155            result.dy = numpy.append(self.dy, other.dy)
156            result.dy = result.dy[ind]
157        if result.dx is not None:
158            result.dx = numpy.append(self.dx, other.dx)
159            result.dx = result.dx[ind]
160        if result.dxw is not None:
161            result.dxw = numpy.append(self.dxw, other.dxw)
162            result.dxw = result.dxw[ind]
163        if result.dxl is not None:
164            result.dxl = numpy.append(self.dxl, other.dxl)
165            result.dxl = result.dxl[ind]
166        return result
167
168class Data2D(PlottableData2D, LoadData2D):
169    """
170    """
171    def __init__(self, image=None, err_image=None,
172                 qx_data=None, qy_data=None, q_data=None, 
173                 mask=None, dqx_data=None, dqy_data=None, 
174                 xmin=None, xmax=None, ymin=None, ymax=None,
175                 zmin=None, zmax=None):
176        """
177        """
178        PlottableData2D.__init__(self, image=image, err_image=err_image,
179                            xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
180                            zmin=zmin, zmax=zmax, qx_data=qx_data, 
181                            qy_data=qy_data)
182       
183        LoadData2D.__init__(self, data=image, err_data=err_image,
184                            qx_data=qx_data, qy_data=qy_data,
185                            dqx_data=dqx_data, dqy_data=dqy_data,
186                            q_data=q_data, mask=mask)
187        self.id = None
188        self.list_group_id = []
189        self.group_id = None
190        self.is_data = True
191        self.path = None
192        self.xtransform = None
193        self.ytransform = None
194        self.title = ""
195        self.scale = None
196        # Always default
197        self.plot_role = Data1D.ROLE_DEFAULT
198       
199    def copy_from_datainfo(self, data2d):
200        """
201        copy value of Data2D of type DataLoader.data_info
202        """
203        self.data = copy.deepcopy(data2d.data)
204        self.qx_data = copy.deepcopy(data2d.qx_data)
205        self.qy_data = copy.deepcopy(data2d.qy_data)
206        self.q_data = copy.deepcopy(data2d.q_data)
207        self.mask = copy.deepcopy(data2d.mask)
208        self.err_data = copy.deepcopy(data2d.err_data)
209        self.x_bins = copy.deepcopy(data2d.x_bins)
210        self.y_bins = copy.deepcopy(data2d.y_bins)
211        if data2d.dqx_data is not None:
212            self.dqx_data = copy.deepcopy(data2d.dqx_data)
213        if data2d.dqy_data is not None:
214            self.dqy_data = copy.deepcopy(data2d.dqy_data)
215        self.xmin = data2d.xmin
216        self.xmax = data2d.xmax
217        self.ymin = data2d.ymin
218        self.ymax = data2d.ymax
219        if hasattr(data2d, "zmin"):
220            self.zmin = data2d.zmin
221        if hasattr(data2d, "zmax"):
222            self.zmax = data2d.zmax
223        self.xaxis(data2d._xaxis, data2d._xunit)
224        self.yaxis(data2d._yaxis, data2d._yunit)
225        self.title = data2d.title
226       
227    def __str__(self):
228        """
229        print data
230        """
231        _str = "%s\n" % LoadData2D.__str__(self)
232        return _str
233
234    def _perform_operation(self, other, operation):
235        """
236        Perform 2D operations between data sets
237       
238        :param other: other data set
239        :param operation: function defining the operation
240       
241        """
242        # First, check the data compatibility
243        dy, dy_other = self._validity_check(other)
244        result = Data2D(image=None, qx_data=None, qy_data=None,
245                         q_data=None, err_image=None, xmin=None, xmax=None,
246                         ymin=None, ymax=None, zmin=None, zmax=None)
247        result.clone_without_data(len(self.data))
248        result.copy_from_datainfo(data2d=self)
249        result.xmin = self.xmin
250        result.xmax = self.xmax
251        result.ymin = self.ymin
252        result.ymax = self.ymax
253        if self.dqx_data is None or self.dqy_data is None:
254            result.dqx_data = None
255            result.dqy_data = None
256        else:
257            result.dqx_data = numpy.zeros(len(self.data))
258            result.dqy_data = numpy.zeros(len(self.data))
259        for i in range(numpy.size(self.data)):
260            result.data[i] = self.data[i]
261            if self.err_data is not None and \
262                numpy.size(self.data) == numpy.size(self.err_data):
263                result.err_data[i] = self.err_data[i]   
264            if self.dqx_data is not None:
265                result.dqx_data[i] = self.dqx_data[i]
266            if self.dqy_data is not None:
267                result.dqy_data[i] = self.dqy_data[i]
268            result.qx_data[i] = self.qx_data[i]
269            result.qy_data[i] = self.qy_data[i]
270            result.q_data[i] = self.q_data[i]
271            result.mask[i] = self.mask[i]
272           
273            a = Uncertainty(self.data[i], dy[i]**2)
274            if isinstance(other, Data2D):
275                b = Uncertainty(other.data[i], dy_other[i]**2)
276                if other.dqx_data is not None and \
277                        result.dqx_data is not None:
278                    result.dqx_data[i] *= self.dqx_data[i]
279                    result.dqx_data[i] += (other.dqx_data[i]**2)
280                    result.dqx_data[i] /= 2
281                    result.dqx_data[i] = math.sqrt(result.dqx_data[i])     
282                if other.dqy_data is not None and \
283                        result.dqy_data is not None:
284                    result.dqy_data[i] *= self.dqy_data[i]
285                    result.dqy_data[i] += (other.dqy_data[i]**2)
286                    result.dqy_data[i] /= 2
287                    result.dqy_data[i] = math.sqrt(result.dqy_data[i])
288            else:
289                b = other
290           
291            output = operation(a, b)
292            result.data[i] = output.x
293            result.err_data[i] = math.sqrt(math.fabs(output.variance))
294        return result
295   
296    def _perform_union(self, other):
297        """
298        Perform 2D operations between data sets
299       
300        :param other: other data set
301        :param operation: function defining the operation
302       
303        """
304        # First, check the data compatibility
305        self._validity_check_union(other)
306        result = Data2D(image=None, qx_data=None, qy_data=None,
307                         q_data=None, err_image=None, xmin=None, xmax=None,
308                         ymin=None, ymax=None, zmin=None, zmax=None)
309        length = len(self.data)
310        tot_length = length + len(other.data)
311        result.clone_without_data(tot_length)
312        result.xmin = self.xmin
313        result.xmax = self.xmax
314        result.ymin = self.ymin
315        result.ymax = self.ymax
316        if self.dqx_data is None or self.dqy_data is None or \
317                other.dqx_data is None or other.dqy_data is None :
318            result.dqx_data = None
319            result.dqy_data = None
320        else:
321            result.dqx_data = numpy.zeros(len(self.data) + \
322                                         numpy.size(other.data))
323            result.dqy_data = numpy.zeros(len(self.data) + \
324                                         numpy.size(other.data))
325       
326        result.data = numpy.append(self.data, other.data)
327        result.qx_data = numpy.append(self.qx_data, other.qx_data)
328        result.qy_data = numpy.append(self.qy_data, other.qy_data)
329        result.q_data = numpy.append(self.q_data, other.q_data)
330        result.mask = numpy.append(self.mask, other.mask)
331        if result.err_data is not None:
332            result.err_data = numpy.append(self.err_data, other.err_data) 
333        if self.dqx_data is not None:
334            result.dqx_data = numpy.append(self.dqx_data, other.dqx_data)
335        if self.dqy_data is not None:
336            result.dqy_data = numpy.append(self.dqy_data, other.dqy_data)
337
338        return result
339
340def check_data_validity(data):
341    """
342    Return True is data is valid enough to compute chisqr, else False
343    """
344    flag = True
345    if data is not None:
346        if issubclass(data.__class__, Data2D):
347            if (data.data is None) or (len(data.data) == 0)\
348            or (len(data.err_data) == 0):
349                flag = False
350        else:
351            if (data.y is None) or (len(data.y) == 0): 
352                flag = False
353        if not data.is_data:
354            flag = False
355    else:
356        flag = False
357    return flag
Note: See TracBrowser for help on using the repository browser.