source: sasview/theoryview/perspectives/theory/theory.py @ 213892bc

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 213892bc was f53444be, checked in by Gervaise Alina <gervyh@…>, 14 years ago

remove reference of guicomm

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