source: sasview/sansview/perspectives/fitting/fitting.py @ e84e1e6

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 e84e1e6 was 25e3fc9, checked in by Gervaise Alina <gervyh@…>, 15 years ago

remove raise and pritn statement

  • Property mode set to 100644
File size: 49.2 KB
RevLine 
[5612152]1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2009, University of Tennessee
9"""
[a8088d7]10import  re,copy
[d89f09b]11import sys, wx, logging
[0550752]12import string, numpy, math
[c3b4dcb]13import time
14import thread
[c202d03]15#from danse.common.plottools.plottables import Theory1D
[c3b4dcb]16from danse.common.plottools.PlotPanel import PlotPanel
[d89f09b]17
[c3b4dcb]18from sans.guiframe.dataFitting import Data2D
19from sans.guiframe.dataFitting import Data1D
[c202d03]20from sans.guiframe.dataFitting import Theory1D
[2b63df0]21from sans.guiframe import dataFitting
[c69b6d5]22from sans.guiframe.utils import format_number
[c3b4dcb]23
[d89f09b]24from sans.guicomm.events import NewPlotEvent, StatusEvent 
[848a2ef]25from sans.guicomm.events import EVT_SLICER_PANEL,ERR_DATA,EVT_REMOVE_DATA
26from sans.guicomm.events import EVT_SLICER_PARS_UPDATE
[6ed82c7]27
[c3b4dcb]28from sans.fit.AbstractFitEngine import Model
29from sans.fit.AbstractFitEngine import FitAbort
[848a2ef]30
[4faf4ba]31
[d89f09b]32from fitproblem import FitProblem
33from fitpanel import FitPanel
[e9b4cc4]34from fit_thread import FitThread
[ed2ea6a]35import models
[c77d859]36import fitpage
[ed2ea6a]37
[d250f7d]38DEFAULT_BEAM = 0.005
[6ced1cc]39DEFAULT_QMIN = 0.001
[9be7432]40DEFAULT_QMAX = 0.13
[7b758fd]41DEFAULT_NPTS = 50
[77e23a2]42
[6f023e8]43(PageInfoEvent, EVT_PAGE_INFO)   = wx.lib.newevent.NewEvent()
[c3b4dcb]44
45
[c77d859]46class PlotInfo:
47    """
48        store some plotting field
49    """
50    _xunit = 'A^{-1}'
51    _xaxis= "\\rm{Q}"
52    _yunit = "cm^{-1}"
53    _yaxis= "\\rm{Intensity} "
54    id = "Model"
55    group_id = "Model"
56    title= None
57    info= None
58   
59   
[d89f09b]60class Plugin:
61    """
[dabb633]62        Fitting plugin is used to perform fit
[d89f09b]63    """
64    def __init__(self):
65        ## Plug-in name
66        self.sub_menu = "Fitting"
67       
68        ## Reference to the parent window
69        self.parent = None
[ed2ea6a]70        #Provide list of models existing in the application
[d89f09b]71        self.menu_mng = models.ModelManager()
72        ## List of panels for the simulation perspective (names)
73        self.perspective = []
[ed2ea6a]74        #list of panel to send to guiframe
[568e1a5]75        self.mypanels=[]
[ed2ea6a]76        # reference to the current running thread
[c77d859]77        self.calc_2D= None
78        self.calc_1D= None
79        self.calc_fit= None
80       
[d89f09b]81        # Start with a good default
82        self.elapsed = 0.022
[ed2ea6a]83        # the type of optimizer selected, park or scipy
[d89f09b]84        self.fitter  = None
[c660493]85        #let fit ready
86        self.fitproblem_count = None
[ed2ea6a]87        #Flag to let the plug-in know that it is running stand alone
[d89f09b]88        self.standalone=True
[6f023e8]89        ## dictionary of page closed and id
90        self.closed_page_dict ={}
[d89f09b]91        ## Fit engine
[e9e914f]92        self._fit_engine = 'scipy'
[ed2ea6a]93        #List of selected data
[2a8fac1]94        self.selected_data_list=[]
[c3435b7f]95        ## list of slicer panel created to display slicer parameters and results
96        self.slicer_panels=[]
[d89f09b]97        # Log startup
98        logging.info("Fitting plug-in started")   
[32d802f]99        # model 2D view
100        self.model2D_id=None
[ed2ea6a]101        #keep reference of the simultaneous fit page
[51d47b5]102        self.sim_page=None
[ed2ea6a]103        #dictionary containing data name and error on dy of that data
[484faf7]104        self.err_dy = {}
[2a8fac1]105       
[c77d859]106   
[2a8fac1]107       
[d89f09b]108    def populate_menu(self, id, owner):
109        """
110            Create a menu for the Fitting plug-in
111            @param id: id to create a menu
112            @param owner: owner of menu
113            @ return : list of information to populate the main menu
114        """
115        #Menu for fitting
116        self.menu1 = wx.Menu()
[6f023e8]117       
[b5c537f]118        #Set park engine
[3b19ac9]119        id3 = wx.NewId()
[bb18ef1]120        scipy_help= "Scipy Engine: Perform Simple fit. More in Help window...."
[89ef796]121        self.menu1.AppendCheckItem(id3, "Simple Fit  [Scipy]",scipy_help) 
[bb18ef1]122        wx.EVT_MENU(owner, id3,  self._onset_engine_scipy)
[6f023e8]123       
[bb18ef1]124        id3 = wx.NewId()
125        park_help = "Park Engine: Perform Complex fit. More in Help window...."
[89ef796]126        self.menu1.AppendCheckItem(id3, "Complex Fit  [Park]",park_help) 
[bb18ef1]127        wx.EVT_MENU(owner, id3,  self._onset_engine_park)
[707436d]128       
129        self.menu1.FindItemByPosition(0).Check(True)
130        self.menu1.FindItemByPosition(1).Check(False)
131           
[6f023e8]132        self.menu1.AppendSeparator()
133        id1 = wx.NewId()
134        simul_help = "Allow to edit fit engine with multiple model and data"
[89ef796]135        self.menu1.Append(id1, '&Simultaneous Page',simul_help)
[6f023e8]136        wx.EVT_MENU(owner, id1, self.on_add_sim_page)
[2db1d66]137       
[d89f09b]138        #menu for model
139        menu2 = wx.Menu()
140        self.menu_mng.populate_menu(menu2, owner)
141        id2 = wx.NewId()
142        owner.Bind(models.EVT_MODEL,self._on_model_menu)
[bb18ef1]143     
[d89f09b]144        self.fit_panel.set_owner(owner)
145        self.fit_panel.set_model_list(self.menu_mng.get_model_list())
[c77d859]146        owner.Bind(fitpage.EVT_MODEL_BOX,self._on_model_panel)
[27976fd0]147     
[3b19ac9]148        #create  menubar items
[484faf7]149        return [(id, self.menu1, "Fitting")]
[2db1d66]150               
[51d47b5]151    def on_add_sim_page(self, event):
[ed2ea6a]152        """
[f93dfcb]153            Create a page to access simultaneous fit option
[ed2ea6a]154        """
[05971e1]155        Plugin.on_perspective(self,event=event)
[2140e68]156        if self.sim_page !=None:
157            msg= "Simultaneous Fit page already opened"
158            wx.PostEvent(self.parent, StatusEvent(status= msg))
159            return 
160       
[51d47b5]161        self.sim_page= self.fit_panel.add_sim_page()
[b28717b]162       
[d89f09b]163    def help(self, evt):
164        """
165            Show a general help dialog.
166            TODO: replace the text with a nice image
167        """
[484faf7]168       
169        from help_panel import  HelpWindow
[2268d10]170        frame = HelpWindow(None, -1, 'HelpWindow')   
171        frame.Show(True)
172       
173       
[d89f09b]174    def get_context_menu(self, graph=None):
175        """
[cf76ca74]176            Get the context menu items available for P(r).them allow fitting option
177            for Data2D and Data1D only.
178           
[d89f09b]179            @param graph: the Graph object to which we attach the context menu
180            @return: a list of menu items with call-back function
[cf76ca74]181            @note: if Data1D was generated from Theory1D 
182                    the fitting option is not allowed
[d89f09b]183        """
[7a77859]184        self.graph = graph
[484faf7]185        fit_option = "Select data for fitting"
186        fit_hint =  "Dialog with fitting parameters "
187        invariant_option = "Compute Invariant"
188        invariant_hint =  "A dialog will appears for further computation"
[d89f09b]189        for item in graph.plottables:
[693ab78]190            if item.__class__.__name__ is "Data2D":
[c3b4dcb]191               
[d902cf0]192                if hasattr(item,"is_data"):
193                    if item.is_data:
[484faf7]194                        return [[fit_option, fit_hint, self._onSelect]]
[d902cf0]195                    else:
196                        return [] 
[484faf7]197                return [[fit_option, fit_hint, self._onSelect]]
[6f73a08]198            else:
[2a8fac1]199                if item.name==graph.selected_plottable :
[05971e1]200                    if item.name !="$I_{obs}(q)$" and item.name !="$P_{fit}(r)$":
201                        if hasattr(item, "group_id"):
[cf76ca74]202                            # if is_data is true , this in an actual data loaded
203                            #else it is a data created from a theory model
[05971e1]204                            if hasattr(item,"is_data"):
205                                if item.is_data:
[484faf7]206                                    return [[fit_option, fit_hint,
207                                              self._onSelect],
208                                            [invariant_option, 
209                                    invariant_hint, self._compute_invariant]]
[05971e1]210                                else:
211                                    return [] 
[d902cf0]212                            else:
[484faf7]213                               return [[fit_option, fit_hint, self._onSelect],
214                                       [invariant_option, 
215                                        invariant_hint, self._compute_invariant]]
[d89f09b]216        return []   
217
218
219    def get_panels(self, parent):
220        """
221            Create and return a list of panel objects
222        """
223        self.parent = parent
224        # Creation of the fit panel
225        self.fit_panel = FitPanel(self.parent, -1)
[f93dfcb]226        #Set the manager for the main panel
[d89f09b]227        self.fit_panel.set_manager(self)
228        # List of windows used for the perspective
229        self.perspective = []
230        self.perspective.append(self.fit_panel.window_name)
231        # take care of saving  data, model and page associated with each other
[3b19ac9]232        self.page_finder = {}
233        #index number to create random model name
234        self.index_model = 0
[264df67]235        self.index_theory= 0
[32673ac]236        self.parent.Bind(EVT_SLICER_PANEL, self._on_slicer_event)
[2a8fac1]237        self.parent.Bind( ERR_DATA, self._on_data_error)
[848a2ef]238        self.parent.Bind(EVT_REMOVE_DATA, self._closed_fitpage)
239        self.parent.Bind(EVT_SLICER_PARS_UPDATE, self._onEVT_SLICER_PANEL)
[df4c3ad]240        self.parent._mgr.Bind(wx.aui.EVT_AUI_PANE_CLOSE,self._onclearslicer)   
241
[32d802f]242       
[f93dfcb]243        #Send the fitting panel to guiframe
[568e1a5]244        self.mypanels.append(self.fit_panel)
245        return self.mypanels
[ed2ea6a]246
[888e62c]247       
[ed2ea6a]248     
[d89f09b]249    def get_perspective(self):
250        """
251            Get the list of panel names for this perspective
252        """
253        return self.perspective
254   
255   
256    def on_perspective(self, event):
257        """
258            Call back function for the perspective menu item.
259            We notify the parent window that the perspective
260            has changed.
261        """
262        self.parent.set_perspective(self.perspective)
[9237df4]263   
[d89f09b]264    def post_init(self):
265        """
266            Post initialization call back to close the loose ends
267        """
[5612152]268        # Do not show the fitting perspective immediately and
269        # let the application show the Welcome Page.
270        #self.parent.set_perspective(self.perspective)
271        pass
[cce33b3]272
[9237df4]273    def get_tools(self):
274        """
275            Returns a set of menu entries for tools
276        """
277        id = wx.NewId()
278        sld_help = "Provides computation related to Scattering Length density"
279        return [("SLD Calculator", sld_help, self.on_calculate_sld)]
280       
[d902cf0]281    def copy_data(self, item, dy=None):
[ed2ea6a]282        """
[f93dfcb]283            receive a data 1D and the list of errors on dy
284            and create a new data1D data
285            @param return
[ed2ea6a]286        """
[2db1d66]287        id = None
[60d6c23]288        if hasattr(item,"id"):
[a8088d7]289            id = copy.deepcopy(item.id)
[2a2af47]290
[c202d03]291        data= Data1D(x=item.x, y=item.y,dx=None, dy=None)
[2a2af47]292        data.copy_from_datainfo(item)
[c202d03]293        item.clone_without_data(clone=data)   
294        data.dy=dy
[60d6c23]295        data.name = item.name
296        ## allow to highlight data when plotted
[a8088d7]297        data.interactive = copy.deepcopy(item.interactive)
[60d6c23]298        ## when 2 data have the same id override the 1 st plotted
299        data.id = id
[c3b4dcb]300        data.group_id = item.group_id
[cce33b3]301        return data
[bfe4644]302   
[ca7a626]303    def set_fit_range(self, page, qmin, qmax):
304        """
305            Set the fitting range of a given page
306        """
307        if page in self.page_finder.iterkeys():
308            fitproblem= self.page_finder[page]
309            fitproblem.set_range(qmin= qmin, qmax= qmax)
[2a8fac1]310                   
[ca7a626]311    def schedule_for_fit(self,value=0,page=None,fitproblem =None): 
[948add7]312        """
[f93dfcb]313            Set the fit problem field to 0 or 1 to schedule that problem to fit.
314            Schedule the specified fitproblem or get the fit problem related to
315            the current page and set value.
316            @param value : integer 0 or 1
317            @param fitproblem: fitproblem to schedule or not to fit
[948add7]318        """   
319        if fitproblem !=None:
320            fitproblem.schedule_tofit(value)
321        else:
[ca7a626]322            if page in self.page_finder.iterkeys():
323                fitproblem= self.page_finder[page]
324                fitproblem.schedule_tofit(value)
325         
[d89f09b]326    def get_page_finder(self):
327        """ @return self.page_finder used also by simfitpage.py""" 
328        return self.page_finder
329   
330   
[3b19ac9]331    def set_page_finder(self,modelname,names,values):
[d89f09b]332        """
333             Used by simfitpage.py to reset a parameter given the string constrainst.
334             @param modelname: the name ot the model for with the parameter has to reset
335             @param value: can be a string in this case.
[3b19ac9]336             @param names: the paramter name
[d89f09b]337             @note: expecting park used for fit.
338        """ 
[51d47b5]339        sim_page= self.sim_page
[d89f09b]340        for page, value in self.page_finder.iteritems():
341            if page != sim_page:
342                list=value.get_model()
[f93dfcb]343                model = list[0]
[d89f09b]344                if model.name== modelname:
[3b19ac9]345                    value.set_model_param(names,values)
[d89f09b]346                    break
[2db1d66]347         
[d89f09b]348    def split_string(self,item): 
349        """
[3b19ac9]350            receive a word containing dot and split it. used to split parameterset
351            name into model name and parameter name example:
352            paramaterset (item) = M1.A
353            @return model_name =M1 , parameter name =A
[d89f09b]354        """
355        if string.find(item,".")!=-1:
356            param_names= re.split("\.",item)
[6d91073]357            model_name=param_names[0]           
358            ##Assume max len is 3; eg., M0.radius.width
359            if len(param_names) == 3:
360                param_name=param_names[1]+"."+param_names[2]
361            else:
362                param_name=param_names[1]                   
[d89f09b]363            return model_name,param_name
364       
[51d47b5]365    def stop_fit(self):
[ed2ea6a]366        """
[f93dfcb]367            Stop the fit engine
[ed2ea6a]368        """
[ad6dd4c]369        if self.calc_fit!= None and self.calc_fit.isrunning():
370            self.calc_fit.stop()
[f3113c9]371            wx.PostEvent(self.parent, StatusEvent(status="Fitting  \
[ed2ea6a]372                is cancelled" , type="stop"))
373           
[ca7a626]374    def set_smearer(self,smearer, qmin=None, qmax=None):
[d89f09b]375        """
[ca7a626]376            Get a smear object and store it to a fit problem
377            @param smearer: smear object to allow smearing data
378        """   
[dd2c2ea3]379        self.current_pg=self.fit_panel.get_current_page()
380        self.page_finder[self.current_pg].set_smearer(smearer)
[ca7a626]381        ## draw model 1D with smeared data
[dd2c2ea3]382        data =  self.page_finder[self.current_pg].get_plotted_data()
383        model = self.page_finder[self.current_pg].get_model()
[ca7a626]384        ## if user has already selected a model to plot
385        ## redraw the model with data smeared
[2140e68]386       
[dd2c2ea3]387        smear =self.page_finder[self.current_pg].get_smearer()
[bfe4644]388        if model!= None:
389            self.draw_model( model=model, data= data, smearer= smear,
[ca7a626]390                qmin= qmin, qmax= qmax)
391
392    def draw_model(self, model, data= None,smearer= None,
393                   enable1D= True, enable2D= False,
394                   qmin= DEFAULT_QMIN, qmax= DEFAULT_QMAX, qstep= DEFAULT_NPTS):
395        """
396             Draw model.
397             @param model: the model to draw
398             @param name: the name of the model to draw
399             @param data: the data on which the model is based to be drawn
400             @param description: model's description
401             @param enable1D: if true enable drawing model 1D
402             @param enable2D: if true enable drawing model 2D
403             @param qmin:  Range's minimum value to draw model
404             @param qmax:  Range's maximum value to draw model
405             @param qstep: number of step to divide the x and y-axis
[ed2ea6a]406             
[d89f09b]407        """
[ca7a626]408        ## draw model 1D with no loaded data
409        self._draw_model1D( model= model, data= data,enable1D=enable1D, smearer= smearer,
410                           qmin= qmin, qmax= qmax, qstep= qstep )
411        ## draw model 2D with no initial data
412        self._draw_model2D(model=model,
413                           data = data,
414                           enable2D= enable2D,
415                           qmin=qmin,
416                           qmax=qmax,
417                           qstep=qstep)
[2db1d66]418           
[ca7a626]419    def onFit(self):
420        """
421            perform fit
422        """
[bb18ef1]423        ##  count the number of fitproblem schedule to fit
424        fitproblem_count= 0
425        for value in self.page_finder.itervalues():
426            if value.get_scheduled()==1:
427                fitproblem_count += 1
[2140e68]428               
[bb18ef1]429        ## if simultaneous fit change automatically the engine to park
430        if fitproblem_count >1:
431            self._on_change_engine(engine='park')
[c9a4377]432           
[c660493]433        self.fitproblem_count = fitproblem_count 
434         
[bb18ef1]435        from sans.fit.Fitting import Fit
436        self.fitter= Fit(self._fit_engine)
437       
[ca7a626]438        if self._fit_engine=="park":
[c9a4377]439            engineType="Simultaneous Fit"
[ca7a626]440        else:
441            engineType="Single Fit"
442           
443        fproblemId = 0
[dd2c2ea3]444        self.current_pg=None
[d89f09b]445        for page, value in self.page_finder.iteritems():
446            try:
[948add7]447                if value.get_scheduled()==1:
[f93dfcb]448                    #Get list of parameters name to fit
[d89f09b]449                    pars = []
450                    templist = []
[3b19ac9]451                    templist = page.get_param_list()
[d89f09b]452                    for element in templist:
[513115c]453                        name = str(element[1])
[ca7a626]454                        pars.append(name)
455                    #Set Engine  (model , data) related to the page on
[dd2c2ea3]456                    self._fit_helper( value=value,pars=pars,
[ca7a626]457                                      id=fproblemId, title= engineType ) 
458                    fproblemId += 1 
[dd2c2ea3]459                    self.current_pg= page
[d89f09b]460            except:
[25e3fc9]461                msg= "%s error: %s" % (engineType,sys.exc_value)
462                wx.PostEvent(self.parent, StatusEvent(status= msg ))
463                return 
[464fce54]464           
[dabb633]465        #Do the simultaneous fit
[d89f09b]466        try:
[f93dfcb]467            ## If a thread is already started, stop it
[662da312]468            #if self.calc_fit!= None and self.calc_fit.isrunning():
469            #    self.calc_fit.stop()
[1c1436d]470           
471            wx.PostEvent(self.parent, StatusEvent(status="Start the computation",
472                                        curr_thread=self.calc_fit,type="start"))
[7975f2b]473            time.sleep(0.5)
[1c1436d]474            wx.PostEvent(self.parent, StatusEvent(status="Computing...",
475                                        curr_thread=self.calc_fit,type="progress"))
[7975f2b]476            time.sleep(0.5)
[ca7a626]477            ## perform single fit
[662da312]478            if fitproblem_count == 1:
[7975f2b]479                #qmin, qmax= self.current_pg.get_range()
[662da312]480                print "went here fitproblem_count == 1",fitproblem_count == 1
481                calc_fit=FitThread(parent =self.parent,
[3215d32]482                                        fn= self.fitter,
[dd2c2ea3]483                                       cpage=self.current_pg,
[3215d32]484                                       pars= pars,
[ca7a626]485                                       completefn= self._single_fit_completed,
[1c1436d]486                                       updatefn=self._updateFit)
[662da312]487               
[3215d32]488                     
489            else:
[f93dfcb]490                ## Perform more than 1 fit at the time
[662da312]491                calc_fit=FitThread(parent =self.parent,
[e9b4cc4]492                                        fn= self.fitter,
493                                       completefn= self._simul_fit_completed,
[1c1436d]494                                       updatefn=self._updateFit)
[c660493]495           
[662da312]496            calc_fit.queue()
497            self.ready_fit(calc_fit=calc_fit)
[c660493]498           
[da26c1a]499        except FitAbort:
500            print "in pluging"
[d89f09b]501        except:
[25e3fc9]502            msg= "%s error: %s" % (engineType,sys.exc_value)
503            wx.PostEvent(self.parent, StatusEvent(status= msg ,type="stop"))
504            return 
[464fce54]505       
[662da312]506    def ready_fit(self, calc_fit):
[c660493]507        """
508        Ready for another fit
509        """
510        if self.fitproblem_count != None and self.fitproblem_count > 1:
[662da312]511            calc_fit.ready(2.5)
[c660493]512           
513        else:
514            time.sleep(0.4)
515             
[9237df4]516    def on_calculate_sld(self, event):
517        """
518            Compute the scattering length density of molecula
519        """ 
520       
521        import  sld_panel 
522        frame = sld_panel.SldWindow(base=self.parent)
523        frame.Show(True) 
524     
525         
[848a2ef]526    def _onEVT_SLICER_PANEL(self, event):
527        """
528            receive and event telling to update a panel with a name starting with
529            event.panel_name. this method update slicer panel for a given interactor.
530            @param event: contains type of slicer , paramaters for updating the panel
531            and panel_name to find the slicer 's panel concerned.
532        """
[df4c3ad]533       
[848a2ef]534        for item in self.parent.panels:
[df4c3ad]535            if self.parent.panels[item].window_caption.startswith(event.panel_name):
[848a2ef]536                self.parent.panels[item].set_slicer(event.type, event.params)
[df4c3ad]537               
538        self.parent._mgr.Update()
539               
[484faf7]540    def _compute_invariant(self, event):   
541        """
542            Open the invariant panel to invariant computation
543        """
[2db1d66]544        self.panel = event.GetEventObject()
545        Plugin.on_perspective(self,event=event)
546        for plottable in self.panel.graph.plottables:
547            if plottable.name == self.panel.graph.selected_plottable:
548                data = self.copy_data(item= plottable, dy=plottable.dy)
[9237df4]549               
[2db1d66]550                from invariant_panel import InvariantWindow
[1a2dc10]551                frame = InvariantWindow(base=self.parent, data=plottable, graph=self.panel.graph)   
[2db1d66]552                frame.Show(True)
[9237df4]553             
[848a2ef]554    def _closed_fitpage(self, event):   
555        """
556            request fitpanel to close a given page when its unique data is removed
557            from the plot
558        """   
559        self.fit_panel._close_fitpage(event.data) 
560       
[cfc0913]561    def _add_page_onmenu(self, name,fitproblem=None):
[6f023e8]562        """
563            Add name of a closed page of fitpanel in a menu
564        """
[dcf29d7]565        list = self.menu1.GetMenuItems()
566        for item in list:
567            if name == item.GetItemLabel():
[cfc0913]568                self.closed_page_dict[name][1] = fitproblem
[dcf29d7]569               
570        if not name in self.closed_page_dict.keys():   
571            # Post paramters
[77e23a2]572            event_id = wx.NewId()
573            self.menu1.Append(event_id, name, "Show %s fit panel" % name)
[cfc0913]574            self.closed_page_dict[name]= [event_id, fitproblem]
[dcf29d7]575            wx.EVT_MENU(self.parent,event_id,  self._open_closed_page)
[ca7a626]576       
577       
[6f023e8]578    def _open_closed_page(self, event):   
579        """
580            reopen a closed page
581        """
[cfc0913]582        for name, value in self.closed_page_dict.iteritems():
[dcf29d7]583            if event.GetId() in value:
[cfc0913]584                id,fitproblem = value
[b787e68c]585                if name !="Model":
[cfc0913]586                    data= fitproblem.get_fit_data()
587                    page = self.fit_panel.add_fit_page(data= data,reset=True)
[0f5fe6b]588                    if fitproblem != None:
589                        self.page_finder[page]=fitproblem
[7c845cb]590                        if self.sim_page != None:
591                            self.sim_page.draw_page()
592                           
[0f5fe6b]593                else:
[b787e68c]594                    model = fitproblem
595                    self.fit_panel.add_model_page(model=model, topmenu=True,
596                                                  reset= True)
[0f5fe6b]597                    break
[dcf29d7]598       
[ca7a626]599       
[6f023e8]600    def _reset_schedule_problem(self, value=0):
601        """
602             unschedule or schedule all fitproblem to be fit
603        """
604        for page, fitproblem in self.page_finder.iteritems():
605            fitproblem.schedule_tofit(value)
606           
[dd2c2ea3]607    def _fit_helper(self,pars,value, id, title="Single Fit " ):
[2140e68]608        """
609            helper for fitting
610        """
[ca7a626]611        metadata = value.get_fit_data()
[24cab5d]612        model = value.get_model()
613        smearer = value.get_smearer()
[ca7a626]614        qmin , qmax = value.get_range()
615        self.fit_id =id
[24cab5d]616        #Create list of parameters for fitting used
617        templist=[]
[464fce54]618       
[24cab5d]619        try:
[464fce54]620            #Extra list of parameters and their constraints
621            listOfConstraint= []
622           
[24cab5d]623            param = value.get_model_param()
624            if len(param)>0:
625                for item in param:
626                    ## check if constraint
[464fce54]627                    if item[0] !=None and item[1] != None:
628                        listOfConstraint.append((item[0],item[1]))
629                   
[24cab5d]630            #Do the single fit
[464fce54]631            self.fitter.set_model(model, self.fit_id,
632                                   pars,constraints = listOfConstraint)
[60d6c23]633           
[24cab5d]634            self.fitter.set_data(data=metadata,Uid=self.fit_id,
635                                 smearer=smearer,qmin= qmin,qmax=qmax )
[662da312]636            print "self.fitter.set_data"
[24cab5d]637            self.fitter.select_problem_for_fit(Uid= self.fit_id,
638                                               value= value.get_scheduled())
[60d6c23]639            value.clear_model_param()
[24cab5d]640        except:
[25e3fc9]641            msg= title +" error: %s" % sys.exc_value
642            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
643            return
[2140e68]644       
[c77d859]645    def _onSelect(self,event):
646        """
647            when Select data to fit a new page is created .Its reference is
648            added to self.page_finder
[d89f09b]649        """
[c77d859]650        self.panel = event.GetEventObject()
[05971e1]651        Plugin.on_perspective(self,event=event)
[6ed82c7]652        for plottable in self.panel.graph.plottables:
653            if plottable.name == self.panel.graph.selected_plottable:
[d902cf0]654                #if not hasattr(plottable, "is_data"):
655                   
656                if  plottable.__class__.__name__=="Theory1D":
[6ed82c7]657                    dy=numpy.zeros(len(plottable.y))
658                    if hasattr(plottable, "dy"):
659                        dy= copy.deepcopy(plottable.dy)
[d902cf0]660                       
[6ed82c7]661                    item= self.copy_data(plottable, dy)
662                    item.group_id += "data1D"
663                    item.id +="data1D"
664                    item.is_data= False
665                    title = item.name
666                    wx.PostEvent(self.parent, NewPlotEvent(plot=item, title=str(title)))
667                else:
[d902cf0]668                    item= self.copy_data(plottable, plottable.dy) 
669                    item.is_data=True
670                   
[54a26d65]671                ## put the errors values back to the model if the errors were hiden
672                ## before sending them to the fit engine
[c77d859]673                if len(self.err_dy)>0:
674                    if item.name in  self.err_dy.iterkeys():
675                        dy= self.err_dy[item.name]
676                        data= self.copy_data(item, dy)
[d902cf0]677                        data.is_data= item.is_data
[c77d859]678                    else:
[da26c1a]679                        data= self.copy_data(item, item.dy)
[d902cf0]680                        data.is_data= item.is_data
681                       
682                       
[c77d859]683                else:
684                    if item.dy==None:
685                        dy= numpy.zeros(len(item.y))
686                        data= self.copy_data(item, dy)
[d902cf0]687                        data.is_data=item.is_data
[c77d859]688                    else:
[da26c1a]689                        data= self.copy_data(item,item.dy)
[d902cf0]690                        data.is_data=item.is_data
691                       
[c77d859]692            else:
[3349893]693                if plottable.__class__.__name__ !="Data2D":
694                    return
[6ed82c7]695                ## Data2D case
696                if not hasattr(plottable, "is_data"):
697                    item= copy.deepcopy(plottable)
698                    item.group_id += "data2D"
699                    item.id +="data2D"
700                    item.is_data= False
701                    title = item.name
702                    title += " Fit"
703                    data = item
704                    wx.PostEvent(self.parent, NewPlotEvent(plot=item, title=str(title)))
705                else:
706                    item= copy.deepcopy(plottable )
707                    data= copy.deepcopy(plottable )
[d902cf0]708                    item.is_data=True
709                    data.is_data=True
[813334e]710               
[c3b4dcb]711               
[c77d859]712            ## create anew page                   
713            if item.name == self.panel.graph.selected_plottable or\
714                 item.__class__.__name__ is "Data2D":
[d89f09b]715                try:
[c77d859]716                    page = self.fit_panel.add_fit_page(data)
[9237df4]717                    page.set_data(data)
[c77d859]718                    # add data associated to the page created
[9237df4]719                    if page != None:   
[c77d859]720                        #create a fitproblem storing all link to data,model,page creation
[6ed82c7]721                        if not page in self.page_finder.keys():
722                            self.page_finder[page]= FitProblem()
[c77d859]723                        ## item is almost the same as data but contains
724                        ## axis info for plotting
725                        self.page_finder[page].add_plotted_data(item)
726                        self.page_finder[page].add_fit_data(data)
[813334e]727
[c77d859]728                        wx.PostEvent(self.parent, StatusEvent(status="Page Created"))
729                    else:
730                        wx.PostEvent(self.parent, StatusEvent(status="Page was already Created"))
[d89f09b]731                except:
[27976fd0]732                    wx.PostEvent(self.parent, StatusEvent(status="Creating Fit page: %s"\
733                    %sys.exc_value))
734                    return
735               
736               
[1c1436d]737    def _updateFit(self):
738        """
739            Is called when values of result are available
740        """
741        ##Sending a progess message to the status bar
742        wx.PostEvent(self.parent, StatusEvent(status="Computing..."))
743           
[ca7a626]744    def _single_fit_completed(self,result,pars,cpage, elapsed=None):
[c77d859]745        """
746            Display fit result on one page of the notebook.
747            @param result: result of fit
748            @param pars: list of names of parameters fitted
749            @param current_pg: the page where information will be displayed
750            @param qmin: the minimum value of x to replot the model
751            @param qmax: the maximum value of x to replot model
752         
[7975f2b]753        """     
[c77d859]754        try:
[ad6dd4c]755            if result ==None:
756                msg= "Simple Fitting Stop !!!"
757                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
758                return
[c69b6d5]759            if not numpy.isfinite(result.fitness) or numpy.any(result.pvec ==None )or not numpy.all(numpy.isfinite(result.pvec) ):
[ad6dd4c]760                msg= "Single Fitting did not converge!!!"
[d902cf0]761                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
762                return
[c77d859]763            for page, value in self.page_finder.iteritems():
764                if page==cpage :
[2140e68]765                    model= value.get_model()
[c77d859]766                    break
[6d91073]767            param_name = []
[c77d859]768            i = 0
769            for name in pars:
[6d91073]770                param_name.append(name)
[7975f2b]771
[6d91073]772            cpage.onsetValues(result.fitness,param_name, result.pvec,result.stderr)
[9237df4]773           
[c77d859]774        except:
[25e3fc9]775            msg= "Single Fit completed but Following error occurred:%s"% sys.exc_value
776            wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
777            return
[c77d859]778       
779       
[ca7a626]780    def _simul_fit_completed(self,result,pars=None,cpage=None, elapsed=None):
[c77d859]781        """
782            Parameter estimation completed,
783            display the results to the user
784            @param alpha: estimated best alpha
785            @param elapsed: computation time
786        """
[ca7a626]787        ## fit more than 1 model at the same time
788        try:
[c69b6d5]789            msg = "" 
[ad6dd4c]790            if result ==None:
791                msg= "Complex Fitting Stop !!!"
792                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
793                return
[c69b6d5]794            if not numpy.isfinite(result.fitness) or numpy.any(result.pvec ==None )or not numpy.all(numpy.isfinite(result.pvec) ):
[ad6dd4c]795                msg= "Single Fitting did not converge!!!"
796                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
797                return
[c69b6d5]798             
[ca7a626]799            for page, value in self.page_finder.iteritems():
[edd166b]800                """
[c69b6d5]801                if format_number(result.fitness) == page.get_chi2():
802                    #ToDo: Compare parameter inputs with outputs too.
803                    wx.PostEvent(self.parent, StatusEvent(status="%s " % msg))
[edd166b]804                    break     
805                """             
[ca7a626]806                if value.get_scheduled()==1:
807                    model = value.get_model()
808                    metadata =  value.get_plotted_data()
[6d91073]809                    small_param_name = []
[ca7a626]810                    small_out = []
811                    small_cov = []
812                    i = 0
813                    #Separate result in to data corresponding to each page
814                    for p in result.parameters:
815                        model_name,param_name = self.split_string(p.name) 
816                        if model.name == model_name:
817                            p_name= model.name+"."+param_name
[7975f2b]818                            if p.name == p_name:     
[edd166b]819                                if p.value != None and numpy.isfinite(p.value):
[7975f2b]820                                    small_out.append(p.value )
821                                    small_param_name.append(param_name)
822                                    small_cov.append(p.stderr)
823
[ca7a626]824                    # Display result on each page
[6d91073]825                    page.onsetValues(result.fitness, small_param_name,small_out,small_cov)
[ca7a626]826        except:
[25e3fc9]827             msg= "Simultaneous Fit completed"
828             msg +=" but Following error occurred:%s"%sys.exc_value
829             wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
830             return 
[f93dfcb]831             
[c77d859]832                           
[04edd0d]833       
[c77d859]834    def _on_show_panel(self, event):
835        print "_on_show_panel: fitting"
836     
837     
838    def _onset_engine_park(self,event):
839        """
840            set engine to park
841        """
[484faf7]842        Plugin.on_perspective(self,event=event)
[c77d859]843        self._on_change_engine('park')
844       
845       
846    def _onset_engine_scipy(self,event):
847        """
848            set engine to scipy
849        """
850        self._on_change_engine('scipy')
851       
852    def _on_slicer_event(self, event):
853        """
854            Receive a panel as event and send it to guiframe
855            @param event: event containing a panel
856        """
[c3435b7f]857       
[c77d859]858        if event.panel!=None:
859            new_panel = event.panel
[c3435b7f]860            self.slicer_panels.append(event.panel)
[c77d859]861            # Set group ID if available
862            event_id = self.parent.popup_panel(new_panel)
[3fef0a8]863            #self.menu3.Append(event_id, new_panel.window_caption,
864            #                 "Show %s plot panel" % new_panel.window_caption)
[c77d859]865            # Set UID to allow us to reference the panel later
[df4c3ad]866         
[c77d859]867            new_panel.uid = event_id
868            self.mypanels.append(new_panel) 
[707436d]869        return 
870   
[848a2ef]871    def _onclearslicer(self, event):
872        """
873            Clear the boxslicer when close the panel associate with this slicer
874        """
[df4c3ad]875        name =event.GetPane().caption
[c3435b7f]876   
877        for panel in self.slicer_panels:
878            if panel.window_caption==name:
879               
[df4c3ad]880                for item in self.parent.panels:
[c3435b7f]881                    if hasattr(self.parent.panels[item],"uid"):
882                        if self.parent.panels[item].uid ==panel.base.uid:
[df4c3ad]883                            self.parent.panels[item].onClearSlicer(event)
884                            self.parent._mgr.Update()
885                            break 
[c3435b7f]886                break
[df4c3ad]887       
888       
[848a2ef]889       
890       
[707436d]891    def _return_engine_type(self):
892        """
893            return the current type of engine
894        """
895        return self._fit_engine
896     
897     
[c77d859]898    def _on_change_engine(self, engine='park'):
899        """
900            Allow to select the type of engine to perform fit
901            @param engine: the key work of the engine
902        """
[484faf7]903       
[77e23a2]904        ## saving fit engine name
[c77d859]905        self._fit_engine = engine
[707436d]906        ## change menu item state
907        if engine=="park":
908            self.menu1.FindItemByPosition(0).Check(False)
909            self.menu1.FindItemByPosition(1).Check(True)
910        else:
911            self.menu1.FindItemByPosition(0).Check(True)
912            self.menu1.FindItemByPosition(1).Check(False)
913           
[77e23a2]914        ## post a message to status bar
[c77d859]915        wx.PostEvent(self.parent, StatusEvent(status="Engine set to: %s" % self._fit_engine))
916   
[77e23a2]917        ## Bind every open fit page with a newevent to know the current fitting engine
918        import fitpage
919        event= fitpage.FitterTypeEvent()
920        event.type = self._fit_engine
921        for key in self.page_finder.keys():
922            wx.PostEvent(key, event)
923       
[c77d859]924   
925    def _on_model_panel(self, evt):
926        """
927            react to model selection on any combo box or model menu.plot the model 
928            @param evt: wx.combobox event
929        """
930        model = evt.model
[77e23a2]931       
[9237df4]932        if model == None:
[c77d859]933            return
[7ad6ff5]934        model.origin_name = model.name
[dd2c2ea3]935        self.current_pg = self.fit_panel.get_current_page() 
[c77d859]936        ## make sure nothing is done on self.sim_page
937        ## example trying to call set_panel on self.sim_page
[dd2c2ea3]938        if self.current_pg != self.sim_page :
[c77d859]939           
[dd2c2ea3]940            if self.page_finder[self.current_pg].get_model()== None :
[c77d859]941               
942                model.name="M"+str(self.index_model)
943                self.index_model += 1 
944            else:
[dd2c2ea3]945                model.name= self.page_finder[self.current_pg].get_model().name
[2140e68]946               
[dd2c2ea3]947            metadata = self.page_finder[self.current_pg].get_plotted_data()
[6859338]948           
[2140e68]949            # save the name containing the data name with the appropriate model
[dd2c2ea3]950            self.page_finder[self.current_pg].set_model(model)
951            qmin, qmax= self.current_pg.get_range()
952            self.page_finder[self.current_pg].set_range(qmin=qmin, qmax=qmax)
953            smearer=  self.page_finder[self.current_pg].get_smearer()
[c77d859]954            # save model name
[997131a]955            self.draw_model( model=model,smearer=smearer, 
956                             data= metadata, qmin=qmin, qmax=qmax)
[c77d859]957           
958            if self.sim_page!=None:
[b28717b]959                self.sim_page.draw_page()
[6f73a08]960       
961       
[c77d859]962 
[d89f09b]963    def _on_model_menu(self, evt):
964        """
965            Plot a theory from a model selected from the menu
[f93dfcb]966            @param evt: wx.menu event
[d89f09b]967        """
[c9a4377]968        model = evt.model
[05971e1]969        Plugin.on_perspective(self,event=evt)
[3dc83be]970        # Create a model page. If a new page is created, the model
971        # will be plotted automatically. If a page already exists,
972        # the content will be updated and the plot refreshed
[b787e68c]973        self.fit_panel.add_model_page(model,topmenu=True)
[bb18ef1]974   
[c77d859]975   
976   
[bb18ef1]977   
[c77d859]978    def _update1D(self,x, output):
[bb18ef1]979        """
980            Update the output of plotting model 1D
981        """
[847091f]982        wx.PostEvent(self.parent, StatusEvent(status="Plot \
983        #updating ... ",type="update"))
[c660493]984        self.ready_fit()
985        #self.calc_thread.ready(0.01)
[bb18ef1]986   
[dad49a0]987   
[c77d859]988    def _fill_default_model2D(self, theory, qmax,qstep, qmin=None):
[ed2ea6a]989        """
[c77d859]990            fill Data2D with default value
991            @param theory: Data2D to fill
[ed2ea6a]992        """
[d15c0202]993        from DataLoader.data_info import Detector, Source
[bb18ef1]994       
[d15c0202]995        detector = Detector()
[7b758fd]996        theory.detector.append(detector) 
[d15c0202]997           
[f93dfcb]998        theory.detector[0].distance=1e+32
[d15c0202]999        theory.source= Source()
[f93dfcb]1000        theory.source.wavelength=2*math.pi/1e+32
[c77d859]1001     
[f93dfcb]1002        ## Create detector for Model 2D
1003        xmax=2*theory.detector[0].distance*math.atan(\
1004                            qmax/(4*math.pi/theory.source.wavelength))
1005       
1006        theory.detector[0].pixel_size.x= xmax/(qstep/2-0.5)
1007        theory.detector[0].pixel_size.y= xmax/(qstep/2-0.5)
[ac2cc940]1008        theory.detector[0].beam_center.x= qmax
1009        theory.detector[0].beam_center.y= qmax
[f93dfcb]1010        ## create x_bins and y_bins of the model 2D
[13e120a]1011        distance   = theory.detector[0].distance
1012        pixel      = qstep/2-1
[7b758fd]1013        theta      = pixel / distance / qstep#100.0
[13e120a]1014        wavelength = theory.source.wavelength
1015        pixel_width_x = theory.detector[0].pixel_size.x
1016        pixel_width_y = theory.detector[0].pixel_size.y
1017        center_x      = theory.detector[0].beam_center.x/pixel_width_x
1018        center_y      = theory.detector[0].beam_center.y/pixel_width_y
[d15c0202]1019       
[13e120a]1020       
1021        size_x, size_y= numpy.shape(theory.data)
1022        for i_x in range(size_x):
[f93dfcb]1023            theta = (i_x-center_x)*pixel_width_x / distance
[ac2cc940]1024            qx = 4.0*math.pi/wavelength * math.tan(theta/2.0)
[13e120a]1025            theory.x_bins.append(qx)   
1026        for i_y in range(size_y):
[f93dfcb]1027            theta = (i_y-center_y)*pixel_width_y / distance
[ac2cc940]1028            qy =4.0*math.pi/wavelength * math.tan(theta/2.0)
[13e120a]1029            theory.y_bins.append(qy)
1030           
[20be946]1031        theory.group_id ="Model"
1032        theory.id ="Model"
[f93dfcb]1033        ## determine plot boundaries
1034        theory.xmin= -qmax
1035        theory.xmax= qmax
1036        theory.ymin= -qmax
1037        theory.ymax= qmax
[c77d859]1038       
1039       
1040    def _get_plotting_info(self, data=None):
1041        """
1042            get plotting info from data if data !=None
1043            else use some default
1044        """
1045        my_info = PlotInfo()
1046        if data !=None:
1047            if hasattr(data,"info"):
1048                x_name, x_units = data.get_xaxis() 
1049                y_name, y_units = data.get_yaxis() 
1050               
1051                my_info._xunit = x_units
1052                my_info._xaxis = x_name
1053                my_info._yunit = y_units
1054                my_info._yaxis = y_name
1055               
1056            my_info.title= data.name
1057            if hasattr(data, "info"):
1058                my_info.info= data.info
1059            if hasattr(data, "group_id"):
1060                my_info.group_id= data.group_id
[60d6c23]1061       
[c77d859]1062        return my_info
1063               
[dad49a0]1064               
[c77d859]1065    def _complete1D(self, x,y, elapsed,model,data=None):
1066        """
1067            Complete plotting 1D data
1068        """ 
1069        try:
1070            new_plot = Theory1D(x=x, y=y)
1071            my_info = self._get_plotting_info( data)
1072            new_plot.name = model.name
1073            new_plot.id = my_info.id
1074            new_plot.group_id = my_info.group_id
1075           
1076            new_plot.xaxis( my_info._xaxis,  my_info._xunit)
1077            new_plot.yaxis( my_info._yaxis, my_info._yunit)
[60d6c23]1078            if data!=None:
1079                if new_plot.id == data.id:
1080                    new_plot.id += "Model"
[513115c]1081                new_plot.is_data =False 
[d902cf0]1082           
[c202d03]1083            title= new_plot.name
[2db1d66]1084            #new_plot.perspective = self.get_perspective()
[d902cf0]1085            # Pass the reset flag to let the plotting event handler
1086            # know that we are replacing the whole plot
[c77d859]1087            if title== None:
[6ed82c7]1088                title = "Analytical model 1D "
[a1100c07]1089            if data ==None:
[c77d859]1090                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
[2db1d66]1091                             title=str(title), reset=True))
[c77d859]1092            else:
1093                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1094                             title= str(title)))
[847091f]1095            msg = "Plot 1D  complete !"
1096            wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
[c77d859]1097        except:
1098            msg= " Error occurred when drawing %s Model 1D: "%new_plot.name
1099            msg+= " %s"%sys.exc_value
[847091f]1100            wx.PostEvent( self.parent, StatusEvent(status= msg, type="stop"  ))
[c77d859]1101            return 
[dad49a0]1102                 
[c77d859]1103    def _update2D(self, output,time=None):
1104        """
1105            Update the output of plotting model
1106        """
1107        wx.PostEvent(self.parent, StatusEvent(status="Plot \
1108        #updating ... ",type="update"))
[c660493]1109        self.ready_fit()
1110        #self.calc_thread.ready(0.01)
[c77d859]1111       
1112       
1113    def _complete2D(self, image,data, model,  elapsed,qmin, qmax,qstep=DEFAULT_NPTS):
1114        """
1115            Complete get the result of modelthread and create model 2D
1116            that can be plot.
1117        """
1118        err_image = numpy.zeros(numpy.shape(image))
[a8088d7]1119       
[c77d859]1120        theory= Data2D(image= image , err_image= err_image)
[2140e68]1121        theory.name= model.name
[c77d859]1122       
1123        if data ==None:
1124            self._fill_default_model2D(theory= theory, qmax=qmax,qstep=qstep, qmin= qmin)
[2140e68]1125       
[c77d859]1126        else:
[513115c]1127            theory.id= data.id+"Model"
1128            theory.group_id= data.name+"Model"
[c77d859]1129            theory.x_bins= data.x_bins
1130            theory.y_bins= data.y_bins
1131            theory.detector= data.detector
1132            theory.source= data.source
[513115c]1133            theory.is_data =False 
[c77d859]1134            ## plot boundaries
1135            theory.ymin= data.ymin
1136            theory.ymax= data.ymax
1137            theory.xmin= data.xmin
1138            theory.xmax= data.xmax
[41340860]1139     
[a8088d7]1140       
[f93dfcb]1141        ## plot
[20be946]1142        wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
[32d802f]1143                         title="Analytical model 2D ", reset=True ))
[847091f]1144        msg = "Plot 2D complete !"
1145        wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
[20be946]1146         
[c77d859]1147    def _on_data_error(self, event):
1148        """
1149            receives and event from plotting plu-gins to store the data name and
1150            their errors of y coordinates for 1Data hide and show error
1151        """
1152        self.err_dy= event.err_dy
[dad49a0]1153       
[20be946]1154         
[c77d859]1155    def _draw_model2D(self,model,data=None,description=None, enable2D=False,
[cfc68540]1156                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
[f93dfcb]1157        """
1158            draw model in 2D
1159            @param model: instance of the model to draw
1160            @param description: the description of the model
1161            @param enable2D: when True allows to draw model 2D
1162            @param qmin: the minimum value to  draw model 2D
1163            @param qmax: the maximum value to draw model 2D
1164            @param qstep: the number of division of Qx and Qy of the model to draw
1165           
1166        """
[d15c0202]1167        x=  numpy.linspace(start= -1*qmax,
1168                               stop= qmax,
1169                               num= qstep,
1170                               endpoint=True ) 
1171        y = numpy.linspace(start= -1*qmax,
1172                               stop= qmax,
1173                               num= qstep,
1174                               endpoint=True )
[c77d859]1175        ## use data info instead
1176        if data !=None:
1177            ## check if data2D to plot
1178            if hasattr(data, "x_bins"):
1179                enable2D = True
1180                x= data.x_bins
1181                y= data.y_bins
1182           
1183        if not enable2D:
1184            return
1185        try:
1186            from model_thread import Calc2D
1187            ## If a thread is already started, stop it
1188            if self.calc_2D != None and self.calc_2D.isrunning():
1189                self.calc_2D.stop()
1190            self.calc_2D = Calc2D(  x= x,
1191                                    y= y,
1192                                    model= model, 
1193                                    data = data,
1194                                    qmin= qmin,
1195                                    qmax= qmax,
1196                                    qstep= qstep,
1197                                    completefn= self._complete2D,
1198                                    updatefn= self._update2D )
1199            self.calc_2D.queue()
1200           
1201        except:
[25e3fc9]1202            msg= " Error occurred when drawing %s Model 2D: "%model.name
1203            msg+= " %s"%sys.exc_value
1204            wx.PostEvent( self.parent, StatusEvent(status= msg ))
1205            return 
[c77d859]1206   
1207    def _draw_model1D(self, model, data=None, smearer= None,
1208                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep= DEFAULT_NPTS,enable1D= True):
1209        """
1210            Draw model 1D from loaded data1D
1211            @param data: loaded data
1212            @param model: the model to plot
1213        """
1214        x=  numpy.linspace(start= qmin,
1215                           stop= qmax,
1216                           num= qstep,
1217                           endpoint=True
1218                           )
1219        if data!=None:
1220            ## check for data2D
1221            if hasattr(data,"x_bins"):
1222                return
1223            x = data.x
1224            if qmin == DEFAULT_QMIN :
1225                qmin = min(data.x)
1226            if qmax == DEFAULT_QMAX:
[3370922]1227                qmax = max(data.x) 
1228           
[c77d859]1229       
1230        if not enable1D:
1231            return
[bb18ef1]1232   
[c77d859]1233        try:
1234            from model_thread import Calc1D
1235            ## If a thread is already started, stop it
1236            if self.calc_1D!= None and self.calc_1D.isrunning():
1237                self.calc_1D.stop()
1238            self.calc_1D= Calc1D( x= x,
1239                                  data = data,
1240                                  model= model, 
1241                                  qmin = qmin,
1242                                  qmax = qmax,
1243                                  smearer = smearer,
1244                                  completefn = self._complete1D,
1245                                  updatefn = self._update1D  )
1246            self.calc_1D.queue()
1247           
1248        except:
1249            msg= " Error occurred when drawing %s Model 1D: "%model.name
1250            msg+= " %s"%sys.exc_value
1251            wx.PostEvent( self.parent, StatusEvent(status= msg ))
1252            return 
1253           
[1b001a7]1254
1255def profile(fn, *args, **kw):
1256    import cProfile, pstats, os
1257    global call_result
1258    def call():
1259        global call_result
1260        call_result = fn(*args, **kw)
1261    cProfile.runctx('call()', dict(call=call), {}, 'profile.out')
1262    stats = pstats.Stats('profile.out')
1263    stats.sort_stats('time')
1264    #stats.sort_stats('calls')
1265    stats.print_stats()
1266    os.unlink('profile.out')
1267    return call_result
[d89f09b]1268if __name__ == "__main__":
1269    i = Plugin()
1270   
1271   
1272   
1273   
Note: See TracBrowser for help on using the repository browser.