source: sasview/theoryview/perspectives/theory/theory.py @ e4957fb

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 e4957fb was 946d1b1, checked in by Gervaise Alina <gervyh@…>, 14 years ago

make model panel inheriting from panelbase

  • Property mode set to 100644
File size: 15.3 KB
Line 
1
2import wx
3import sys
4import numpy
5import math
6import logging
7
8import models
9import model_panel
10from model_panel import ModelPanel
11from sans.guiframe.events import NewPlotEvent
12from sans.guiframe.events import StatusEvent
13from sans.guiframe.dataFitting import Data2D
14from sans.guiframe.dataFitting import Theory1D
15
16DEFAULT_BEAM = 0.005
17DEFAULT_QMIN = 0.001
18DEFAULT_QMAX = 0.13
19DEFAULT_NPTS = 50
20
21
22class PlotInfo:
23    """
24    store some plotting field
25   
26    """
27    _xunit = 'A^{-1}'
28    _xaxis= "\\rm{Q}"
29    _yunit = "cm^{-1}"
30    _yaxis= "\\rm{Intensity} "
31    id = "Model"
32    group_id = "Model"
33    title= None
34    info= None
35   
36from sans.guiframe.plugin_base import PluginBase 
37
38class Plugin(PluginBase):
39    """
40    This class defines the interface for a Plugin class
41    for calculator perspective
42   
43    """
44   
45    def __init__(self, standalone=True):
46        PluginBase.__init__(self, name="Theory", standalone=standalone)
47       
48        # Log startup
49        logging.info("Theory plug-in started")   
50       
51        #Provide list of models existing in the application
52        self.menu_mng = models.ModelManager()
53        # reference to the current running thread
54        self.calc_2D = None
55        self.calc_1D = None
56   
57    def use_data(self):
58        """
59        return True if these plugin use data
60        """
61        return False
62   
63    def get_panels(self, parent):
64        """
65        Create and return the list of wx.Panels for your plug-in.
66        Define the plug-in perspective.
67       
68        Panels should inherit from DefaultPanel defined below,
69        or should present the same interface. They must define
70        "window_caption" and "window_name".
71       
72        :param parent: parent window
73       
74        :return: list of panels
75        """
76        ## Save a reference to the parent
77        self.parent = parent
78        # Define a panel
79        self.model_panel= ModelPanel(self.parent, page_info =None,
80                model_list_box= self.menu_mng.get_model_list().get_list())
81        self.model_panel.set_manager(self)
82        # If needed, add its name to the perspective list
83        self.perspective.append(self.model_panel.window_name)
84        self.parent.Bind(model_panel.EVT_MODEL_BOX,self._on_model_panel)
85        # Return the list of panels
86        return [self.model_panel]
87   
88   
89    def draw_model(self, model, data= None,smearer= None,
90                   enable1D= True, enable2D= False,
91                   qmin= DEFAULT_QMIN, qmax= DEFAULT_QMAX, qstep= DEFAULT_NPTS):
92        """
93        Draw model.
94         
95        :param model: the model to draw
96        :param name: the name of the model to draw
97        :param data: the data on which the model is based to be drawn
98        :param description: model's description
99        :param enable1D: if true enable drawing model 1D
100        :param enable2D: if true enable drawing model 2D
101        :param qmin:  Range's minimum value to draw model
102        :param qmax:  Range's maximum value to draw model
103        :param qstep: number of step to divide the x and y-axis
104             
105        """
106        ## draw model 1D with no loaded data
107        self._draw_model1D( model= model, data= data,enable1D=enable1D, smearer= smearer,
108                           qmin= qmin, qmax= qmax, qstep= qstep )
109        ## draw model 2D with no initial data
110        self._draw_model2D(model=model,
111                           data = data,
112                           enable2D= enable2D,
113                           qmin=qmin,
114                           qmax=qmax,
115                           qstep=qstep)
116       
117    def _on_model_panel(self, evt):
118        """
119        react to model selection on any combo box or model menu.plot the model
120         
121        :param evt: wx.combobox event
122       
123        """
124        model = evt.model
125        qmin = evt.qmin
126        qmax = evt.qmax
127        qstep = evt.qstep
128        if model ==None:
129            return
130        # save model name
131        self.draw_model(model=model, qmin=qmin, qmax=qmax, qstep=qstep)
132       
133    def _draw_model2D(self,model,data=None, enable2D=False,
134                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
135        """
136        draw model in 2D
137       
138        :param model: instance of the model to draw
139        :param enable2D: when True allows to draw model 2D
140        :param qmin: the minimum value to  draw model 2D
141        :param qmax: the maximum value to draw model 2D
142        :param qstep: the number of division of Qx and Qy of the model to draw
143       
144        """
145        x=  numpy.linspace(start= -1*qmax,
146                               stop= qmax,
147                               num= qstep,
148                               endpoint=True ) 
149        y = numpy.linspace(start= -1*qmax,
150                               stop= qmax,
151                               num= qstep,
152                               endpoint=True )
153         
154        ## use data info instead
155        if data !=None:
156            ## check if data2D to plot
157            if hasattr(data, "x_bins"):
158                enable2D = True
159                x= data.x_bins
160                y= data.y_bins
161
162        if not enable2D:
163            return
164        try:
165            from model_thread import Calc2D
166            ## If a thread is already started, stop it
167            if self.calc_2D != None and self.calc_2D.isrunning():
168                self.calc_2D.stop()
169            self.calc_2D = Calc2D(  x= x,
170                                    y= y,
171                                    model= model, 
172                                    data = data,
173                                    qmin= qmin,
174                                    qmax= qmax,
175                                    qstep= qstep,
176                                    completefn= self._complete2D,
177                                    updatefn= self._update2D )
178            self.calc_2D.queue()
179           
180        except:
181            raise
182            #msg= " Error occurred when drawing %s Model 2D: "%model.name
183            #msg+= " %s"%sys.exc_value
184            #wx.PostEvent( self.parent, StatusEvent(status= msg ))
185            #return 
186   
187    def _draw_model1D(self, model, data=None, smearer= None,
188                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep= DEFAULT_NPTS,
189                enable1D= True):
190        """
191        Draw model 1D from loaded data1D
192       
193        :param data: loaded data
194        :param model: the model to plot
195       
196        """
197        x=  numpy.linspace(start= qmin,
198                           stop= qmax,
199                           num= qstep,
200                           endpoint=True
201                           )
202        if data!=None:
203            ## check for data2D
204            if hasattr(data,"x_bins"):
205                return
206            x = data.x
207            if qmin == DEFAULT_QMIN :
208                qmin = min(data.x)
209            if qmax == DEFAULT_QMAX:
210                qmax = max(data.x) 
211           
212       
213        if not enable1D:
214            return
215   
216        try:
217            from model_thread import Calc1D
218            ## If a thread is already started, stop it
219            if self.calc_1D!= None and self.calc_1D.isrunning():
220                self.calc_1D.stop()
221            self.calc_1D= Calc1D( x= x,
222                                  data = data,
223                                  model= model, 
224                                  qmin = qmin,
225                                  qmax = qmax,
226                                  smearer = smearer,
227                                  completefn = self._complete1D,
228                                  updatefn = self._update1D  )
229            self.calc_1D.queue()
230           
231        except:
232            msg = " Error occurred when drawing %s Model 1D: "%model.name
233            msg += " %s"%sys.exc_value
234            wx.PostEvent(self.parent, StatusEvent(status=msg))
235           
236    def _update1D(self,x, output):
237        """
238        Update the output of plotting model 1D
239       
240        """
241        wx.PostEvent(self.parent, StatusEvent(status="Plot \
242        #updating ... ",type="update"))
243        self.ready_fit()
244        #self.calc_thread.ready(0.01)
245
246    def _fill_default_model2D(self, theory, qmax,qstep, qmin=None):
247        """
248        fill Data2D with default value
249       
250        :param theory: Data2D to fill
251       
252        """
253        from DataLoader.data_info import Detector, Source
254       
255        detector = Detector()
256        theory.detector.append(detector)         
257        theory.source= Source()
258       
259        ## Default values   
260        theory.detector[0].distance= 8000   # mm       
261        theory.source.wavelength= 6         # A     
262        theory.detector[0].pixel_size.x= 5  # mm
263        theory.detector[0].pixel_size.y= 5  # mm
264       
265        theory.detector[0].beam_center.x= qmax
266        theory.detector[0].beam_center.y= qmax
267       
268       
269        ## create x_bins and y_bins of the model 2D
270        pixel_width_x = theory.detector[0].pixel_size.x
271        pixel_width_y = theory.detector[0].pixel_size.y
272        center_x      = theory.detector[0].beam_center.x/pixel_width_x
273        center_y      = theory.detector[0].beam_center.y/pixel_width_y
274
275        # theory default: assume the beam center is located at the center of sqr detector
276        xmax = qmax
277        xmin = -qmax
278        ymax = qmax
279        ymin = -qmax
280       
281        x=  numpy.linspace(start= -1*qmax,
282                               stop= qmax,
283                               num= qstep,
284                               endpoint=True ) 
285        y = numpy.linspace(start= -1*qmax,
286                               stop= qmax,
287                               num= qstep,
288                               endpoint=True )
289         
290        ## use data info instead
291        new_x = numpy.tile(x, (len(y),1))
292        new_y = numpy.tile(y, (len(x),1))
293        new_y = new_y.swapaxes(0,1)
294       
295        # all data reuire now in 1d array
296        qx_data = new_x.flatten()
297        qy_data = new_y.flatten()
298       
299        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data)
300        # set all True (standing for unmasked) as default
301        mask    = numpy.ones(len(qx_data), dtype = bool)
302       
303        # calculate the range of qx and qy: this way, it is a little more independent
304        x_size = xmax- xmin
305        y_size = ymax -ymin
306       
307        # store x and y bin centers in q space
308        x_bins  = x
309        y_bins  = y
310        # bin size: x- & y-directions
311        xstep = x_size/len(x_bins-1)
312        ystep = y_size/len(y_bins-1)
313       
314        #theory.data = numpy.zeros(len(mask))
315        theory.err_data = numpy.ones(len(mask))
316        theory.qx_data = qx_data
317        theory.qy_data = qy_data 
318        theory.q_data = q_data
319        theory.mask = mask           
320        theory.x_bins = x_bins 
321        theory.y_bins = y_bins   
322       
323        # max and min taking account of the bin sizes
324        theory.xmin= xmin
325        theory.xmax= xmax
326        theory.ymin= ymin
327        theory.ymax= ymax
328        theory.group_id = "Model"
329        theory.id = "Model"
330       
331    def _get_plotting_info(self, data=None):
332        """
333        get plotting info from data if data !=None
334        else use some default
335       
336        """
337        my_info = PlotInfo()
338        if data !=None:
339            if hasattr(data,"info"):
340                x_name, x_units = data.get_xaxis() 
341                y_name, y_units = data.get_yaxis() 
342               
343                my_info._xunit = x_units
344                my_info._xaxis = x_name
345                my_info._yunit = y_units
346                my_info._yaxis = y_name
347               
348            my_info.title= data.name
349            if hasattr(data, "info"):
350                my_info.info= data.info
351            if hasattr(data, "group_id"):
352                my_info.group_id= data.group_id
353       
354        return my_info
355               
356    def _complete1D(self, x,y, elapsed,model,data=None):
357        """
358        Complete plotting 1D data
359       
360        """ 
361       
362        try:
363            new_plot = Theory1D(x=x, y=y)
364            my_info = self._get_plotting_info( data)
365            new_plot.name = model.name
366            new_plot.id = my_info.id
367            new_plot.group_id = my_info.group_id
368           
369            new_plot.xaxis( my_info._xaxis,  my_info._xunit)
370            new_plot.yaxis( my_info._yaxis, my_info._yunit)
371            if data!=None:
372                if new_plot.id == data.id:
373                    new_plot.id += "Model"
374                new_plot.is_data =False 
375           
376            # Pass the reset flag to let the plotting event handler
377            # know that we are replacing the whole plot
378           
379            title = "Analytical model 1D "
380            if data ==None:
381                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
382                             title= str(title), reset=True ))
383            else:
384                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
385                             title= str(title)))
386            msg = "Plot 1D  complete !"
387            wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
388        except:
389            msg= " Error occurred when drawing %s Model 1D: "%new_plot.name
390            msg+= " %s"%sys.exc_value
391            wx.PostEvent( self.parent, StatusEvent(status= msg, type="stop"  ))
392            return 
393                 
394    def _update2D(self, output,time=None):
395        """
396        Update the output of plotting model
397       
398        """
399        wx.PostEvent(self.parent, StatusEvent(status="Plot \
400        #updating ... ",type="update"))
401        self.ready_fit()
402        #self.calc_thread.ready(0.01)
403       
404    def _complete2D(self, image,data, model,  elapsed,qmin, qmax,qstep=DEFAULT_NPTS):
405        """
406        Complete get the result of modelthread and create model 2D
407        that can be plot.
408       
409        """
410        err_image = numpy.zeros(numpy.shape(image))
411       
412        theory= Data2D(image= image , err_image= err_image)
413        theory.name= model.name
414
415        if data ==None:
416            self._fill_default_model2D(theory= theory, qmax=qmax,qstep=qstep, qmin= qmin)
417       
418        else:
419            theory.id= data.id+"Model"
420            theory.group_id= data.name+"Model"
421            theory.x_bins= data.x_bins
422            theory.y_bins= data.y_bins
423            theory.detector= data.detector
424            theory.source= data.source
425            theory.is_data =False 
426            theory.qx_data = data.qx_data
427            theory.qy_data = data.qy_data
428            theory.q_data = data.q_data
429            theory.err_data = err_image#numpy.zeros(len(data.err_data))
430            theory.mask = data.mask
431            ## plot boundaries
432            theory.ymin= data.ymin
433            theory.ymax= data.ymax
434            theory.xmin= data.xmin
435            theory.xmax= data.xmax
436       
437        ## plot
438        wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
439                         title="Analytical model 2D ", reset=True ))
440        msg = "Plot 2D complete !"
441        wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
442     
Note: See TracBrowser for help on using the repository browser.