source: sasview/sansview/perspectives/fitting/fitting.py @ 3e943e8

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 3e943e8 was 58e0c83, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on fit stop

  • Property mode set to 100644
File size: 57.0 KB
Line 
1
2
3################################################################################
4#This software was developed by the University of Tennessee as part of the
5#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
6#project funded by the US National Science Foundation.
7#
8#See the license text in license.txt
9#
10#copyright 2009, University of Tennessee
11################################################################################
12
13
14import re
15import sys
16import wx
17import logging
18import numpy
19import string
20import time
21from copy import deepcopy
22import models
23import fitpage
24
25
26from DataLoader.loader import Loader
27from sans.guiframe.dataFitting import Data2D
28from sans.guiframe.dataFitting import Data1D
29from sans.guiframe.events import NewPlotEvent
30from sans.guiframe.events import StatusEvent 
31from sans.guiframe.events import EVT_SLICER_PANEL
32from sans.guiframe.events import EVT_REMOVE_DATA
33from sans.guiframe.events import EVT_SLICER_PARS_UPDATE
34from sans.guiframe.gui_style import GUIFRAME_ID
35from sans.guiframe.plugin_base import PluginBase
36
37from .console import ConsoleUpdate
38from .fitproblem import FitProblem
39from .fitpanel import FitPanel
40from .fit_thread import FitThread
41from .pagestate import Reader
42from .fitpage import Chi2UpdateEvent
43
44DEFAULT_BEAM = 0.005
45DEFAULT_QMIN = 0.001
46DEFAULT_QMAX = 0.13
47DEFAULT_NPTS = 50
48MAX_NBR_DATA = 4
49
50
51(PageInfoEvent, EVT_PAGE_INFO)   = wx.lib.newevent.NewEvent()
52
53   
54
55class Plugin(PluginBase):
56    """
57    Fitting plugin is used to perform fit
58    """
59    def __init__(self, standalone=False):
60        PluginBase.__init__(self, name="Fitting", standalone=standalone)
61       
62        #Provide list of models existing in the application
63        self.menu_mng = models.ModelManager()
64       
65        #list of panel to send to guiframe
66        self.mypanels = []
67        # reference to the current running thread
68        self.calc_2D = None
69        self.calc_1D = None
70        self.fit_thread_list = {}
71       
72        # Start with a good default
73        self.elapsed = 0.022
74        # the type of optimizer selected, park or scipy
75        self.fitter  = None
76        #let fit ready
77        self.fitproblem_count = None
78        #Flag to let the plug-in know that it is running stand alone
79        self.standalone = True
80        ## dictionary of page closed and id
81        self.closed_page_dict = {}
82        ## Fit engine
83        self._fit_engine = 'scipy'
84        #List of selected data
85        self.selected_data_list = []
86        ## list of slicer panel created to display slicer parameters and results
87        self.slicer_panels = []
88        # model 2D view
89        self.model2D_id = None
90        #keep reference of the simultaneous fit page
91        self.sim_page = None
92        self.index_model = 0
93        #Create a reader for fit page's state
94        self.state_reader = None 
95        self._extensions = '.fitv'
96        self.temp_state = []
97        self.state_index = 0
98        self.sfile_ext = None
99        # take care of saving  data, model and page associated with each other
100        self.page_finder = {}
101        # Log startup
102        logging.info("Fitting plug-in started") 
103       
104    def populate_menu(self, owner):
105        """
106        Create a menu for the Fitting plug-in
107       
108        :param id: id to create a menu
109        :param owner: owner of menu
110       
111        :return: list of information to populate the main menu
112       
113        """
114        #Menu for fitting
115        self.menu1 = wx.Menu()
116       
117        #Set park engine
118        id3 = wx.NewId()
119        scipy_help= "Scipy Engine: Perform Simple fit. More in Help window...."
120        self.menu1.AppendCheckItem(id3, "Simple Fit  [Scipy]",scipy_help) 
121        wx.EVT_MENU(owner, id3,  self._onset_engine_scipy)
122       
123        id3 = wx.NewId()
124        park_help = "Park Engine: Perform Complex fit. More in Help window...."
125        self.menu1.AppendCheckItem(id3, "Complex Fit  [Park]",park_help) 
126        wx.EVT_MENU(owner, id3,  self._onset_engine_park)
127       
128        self.menu1.FindItemByPosition(0).Check(True)
129        self.menu1.FindItemByPosition(1).Check(False)
130           
131        self.menu1.AppendSeparator()
132        id1 = wx.NewId()
133        simul_help = "Simultaneous Fit"
134        self.menu1.Append(id1, '&Simultaneous Page',simul_help)
135        wx.EVT_MENU(owner, id1, self.on_add_sim_page)
136       
137        id1 = wx.NewId()
138        simul_help = "Add new fit page"
139        self.menu1.Append(id1, '&Create New Page',simul_help)
140        wx.EVT_MENU(owner, id1, self.on_add_new_page)
141       
142        #self.fit_panel.set_model_list(self.menu_mng.get_model_list())
143   
144        #create  menubar items
145        return [(self.menu1, "Fitting")]
146               
147    def on_add_sim_page(self, event):
148        """
149        Create a page to access simultaneous fit option
150        """
151        if self.sim_page != None:
152            msg= "Simultaneous Fit page already opened"
153            wx.PostEvent(self.parent, StatusEvent(status= msg))
154            return 
155       
156        self.sim_page= self.fit_panel.add_sim_page()
157       
158    def help(self, evt):
159        """
160        Show a general help dialog.
161        """
162        from help_panel import  HelpWindow
163        frame = HelpWindow(None, -1, 'HelpWindow')   
164        frame.Show(True)
165       
166    def get_context_menu(self, plotpanel=None):
167        """
168        Get the context menu items available for P(r).them allow fitting option
169        for Data2D and Data1D only.
170       
171        :param graph: the Graph object to which we attach the context menu
172       
173        :return: a list of menu items with call-back function
174       
175        :note: if Data1D was generated from Theory1D 
176                the fitting option is not allowed
177               
178        """
179        graph = plotpanel.graph
180        fit_option = "Select data for fitting"
181        fit_hint =  "Dialog with fitting parameters "
182       
183        if graph.selected_plottable not in plotpanel.plots:
184            return []
185        item = plotpanel.plots[graph.selected_plottable]
186        if item.__class__.__name__ is "Data2D": 
187            if hasattr(item,"is_data"):
188                if item.is_data:
189                    return [[fit_option, fit_hint, self._onSelect]]
190                else:
191                    return [] 
192            return [[fit_option, fit_hint, self._onSelect]]
193        else:
194           
195            # if is_data is true , this in an actual data loaded
196            #else it is a data created from a theory model
197            if hasattr(item,"is_data"):
198                if item.is_data:
199                    return [[fit_option, fit_hint,
200                              self._onSelect]]
201                else:
202                    return [] 
203        return []   
204
205
206    def get_panels(self, parent):
207        """
208        Create and return a list of panel objects
209        """
210        self.parent = parent
211        #self.parent.Bind(EVT_FITSTATE_UPDATE, self.on_set_state_helper)
212        # Creation of the fit panel
213        self.fit_panel = FitPanel(parent=self.parent, manager=self)
214        self.on_add_new_page(event=None)
215        #Set the manager for the main panel
216        self.fit_panel.set_manager(self)
217        # List of windows used for the perspective
218        self.perspective = []
219        self.perspective.append(self.fit_panel.window_name)
220       
221        #index number to create random model name
222        self.index_model = 0
223        self.index_theory= 0
224        self.parent.Bind(EVT_SLICER_PANEL, self._on_slicer_event)
225       
226        self.parent.Bind(EVT_REMOVE_DATA, self._closed_fitpage)
227        self.parent.Bind(EVT_SLICER_PARS_UPDATE, self._onEVT_SLICER_PANEL)
228        self.parent._mgr.Bind(wx.aui.EVT_AUI_PANE_CLOSE,self._onclearslicer)   
229        #Create reader when fitting panel are created
230        self.state_reader = Reader(self.set_state)   
231        #append that reader to list of available reader
232        loader = Loader()
233        loader.associate_file_reader(".fitv", self.state_reader)
234        loader.associate_file_reader(".svs", self.state_reader)
235        from sans.perspectives.calculator.sld_panel import SldPanel
236        #Send the fitting panel to guiframe
237        self.mypanels.append(self.fit_panel) 
238        self.mypanels.append(SldPanel(parent=self.parent, base=self.parent))
239        return self.mypanels
240   
241    def clear_panel(self):
242        """
243        """
244        self.fit_panel.clear_panel()
245       
246    def set_default_perspective(self):
247        """
248        Call back method that True to notify the parent that the current plug-in
249        can be set as default  perspective.
250        when returning False, the plug-in is not candidate for an automatic
251        default perspective setting
252        """
253        return True
254   
255    def delete_data(self, data):
256        """
257        delete  the given data from panel
258        """
259        self.fit_panel.delete_data(data)
260       
261    def set_data(self, data_list=None):
262        """
263        receive a list of data to fit
264        """
265        if data_list is None:
266            data_list = []
267        selected_data_list = []
268        if len(data_list) > MAX_NBR_DATA :
269            from fitting_widgets import DataDialog
270            dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
271            if dlg.ShowModal() == wx.ID_OK:
272                selected_data_list = dlg.get_data()
273        else:
274            selected_data_list = data_list
275        try:
276            for data in selected_data_list:
277                self.add_fit_page(data=data)
278                wx.PostEvent(self.parent, NewPlotEvent(plot=data, 
279                                                       title=str(data.title)))
280        except:
281            raise
282            #msg = "Fitting Set_data: " + str(sys.exc_value)
283            #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
284           
285    def set_theory(self,  theory_list=None):
286        """
287        """
288        #set the model state for a given theory_state:
289        for item in theory_list:
290            try:
291                _, theory_state = item
292                self.fit_panel.set_model_state(theory_state)
293            except:
294                msg = "Fitting: cannot deal with the theory received"
295                logging.error("set_theory " + msg + "\n" + str(sys.exc_value))
296                wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
297           
298    def set_state(self, state=None, datainfo=None, format=None):
299        """
300        Call-back method for the fit page state reader.
301        This method is called when a .fitv/.svs file is loaded.
302       
303        : param state: PageState object
304        : param datainfo: data
305        """
306        #state = self.state_reader.get_state()
307        if state != None:
308            # store fitting state in temp_state
309            self.temp_state.append(state) 
310        else:
311            self.temp_state = []
312        # index to start with for a new set_state
313        self.state_index = 0
314        # state file format
315        self.sfile_ext = format
316       
317        self.on_set_state_helper(event=None)
318
319    def  on_set_state_helper(self,event=None):
320        """
321        Set_state_helper. This actually sets state after plotting data from state file.
322       
323        : event: FitStateUpdateEvent called by dataloader.plot_data from guiframe
324        """
325        if len(self.temp_state) == 0:
326            if self.state_index==0 and len(self.mypanels) <= 0 and self.sfile_ext =='.svs':
327                self.fit_panel.add_default_pages()
328                self.temp_state = []
329                self.state_index = 0
330            return
331       
332        try:
333            # Load fitting state
334            state = self.temp_state[self.state_index]
335            #panel state should have model selection to set_state
336            if state.formfactorcombobox != None:
337                #set state
338                data = self.parent.create_gui_data(state.data)
339               
340                data.group_id = state.data.group_id
341                self.parent.add_data(data_list={data.id:data})
342                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
343                                        title=data.title))
344                #need to be fix later make sure we are sendind guiframe.data
345                #to panel
346                state.data = data
347                page = self.fit_panel.set_state(state)   
348            else:
349                #just set data because set_state won't work
350                data = self.parent.create_gui_data(state.data)
351                data.group_id = state.data.group_id
352                self.parent.add_data(data_list={data.id:data})
353                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
354                                        title=data.title))
355                self.add_fit_page(data)
356                caption = panel.window_name
357                self.store_data(page=panel.id, data=data, caption=caption)
358                self.mypanels.append(panel) 
359               
360            # get ready for the next set_state
361            self.state_index += 1
362
363            #reset state variables to default when all set_state is finished.
364            if len(self.temp_state) == self.state_index:
365               
366                self.temp_state = []
367                #self.state_index = 0
368                # Make sure the user sees the fitting panel after loading
369                #self.parent.set_perspective(self.perspective)
370                self.on_perspective(event=None)
371        except:
372            self.state_index==0
373            self.temp_state = []
374            raise
375                 
376    def save_fit_state(self, filepath, fitstate): 
377        """
378        save fit page state into file
379        """
380        self.state_reader.write(filename=filepath, fitstate=fitstate)
381       
382    def set_fit_range(self, uid, qmin, qmax):
383        """
384        Set the fitting range of a given page
385        """
386        self.page_finder[uid].set_range(qmin=qmin, qmax=qmax)
387                   
388    def schedule_for_fit(self,value=0, uid=None,fitproblem =None): 
389        """
390        Set the fit problem field to 0 or 1 to schedule that problem to fit.
391        Schedule the specified fitproblem or get the fit problem related to
392        the current page and set value.
393       
394        :param value: integer 0 or 1
395        :param fitproblem: fitproblem to schedule or not to fit
396       
397        """   
398        if fitproblem !=None:
399            fitproblem.schedule_tofit(value)
400        else:
401            self.page_finder[uid].schedule_tofit(value)
402         
403    def get_page_finder(self):
404        """
405        return self.page_finder used also by simfitpage.py
406        """ 
407        return self.page_finder
408   
409    def set_page_finder(self,modelname,names,values):
410        """
411        Used by simfitpage.py to reset a parameter given the string constrainst.
412         
413        :param modelname: the name ot the model for with the parameter has to reset
414        :param value: can be a string in this case.
415        :param names: the paramter name
416         
417        :note: expecting park used for fit.
418         
419        """ 
420        sim_page_id = self.sim_page.uid
421        for uid, value in self.page_finder.iteritems():
422            if uid != sim_page_id:
423                list = value.get_model()
424                model = list[0]
425                if model.name == modelname:
426                    value.set_model_param(names, values)
427                    break
428         
429    def split_string(self,item): 
430        """
431        receive a word containing dot and split it. used to split parameterset
432        name into model name and parameter name example: ::
433       
434            paramaterset (item) = M1.A
435            Will return model_name = M1 , parameter name = A
436           
437        """
438        if string.find(item,".")!=-1:
439            param_names= re.split("\.",item)
440            model_name=param_names[0]           
441            ##Assume max len is 3; eg., M0.radius.width
442            if len(param_names) == 3:
443                param_name=param_names[1]+"."+param_names[2]
444            else:
445                param_name=param_names[1]                   
446            return model_name,param_name
447       
448    def stop_fit(self, uid):
449        """
450        Stop the fit engine
451        """
452        if uid in self.fit_thread_list.keys():
453            calc_fit = self.fit_thread_list[uid]
454            if calc_fit is not  None and calc_fit.isrunning():
455                calc_fit.stop()
456                msg = "Fit stop!"
457                wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
458        #set the fit button label of page when fit stop is trigger from
459        #simultaneous fit pane
460        if  self.sim_page is not None and uid == self.sim_page.uid:
461            for uid, value in self.page_finder.iteritems():
462                if value.get_scheduled() == 1:
463                    if uid in self.fit_panel.opened_pages.keys():
464                        panel = self.fit_panel.opened_pages[uid]
465                        panel. _on_fit_complete()
466 
467    def set_smearer(self, uid, smearer, qmin=None, qmax=None, draw=True):
468        """
469        Get a smear object and store it to a fit problem
470       
471        :param smearer: smear object to allow smearing data
472       
473        """   
474        if uid not in self.page_finder.keys():
475            msg = "Cannot find ID: %s in page_finder" % str(uid)
476            raise ValueError, msg
477        self.page_finder[uid].set_smearer(smearer)
478        if draw:
479            ## draw model 1D with smeared data
480            data =  self.page_finder[uid].get_fit_data()
481            model = self.page_finder[uid].get_model()
482            if model is None:
483                return
484            ## if user has already selected a model to plot
485            ## redraw the model with data smeared
486            smear = self.page_finder[uid].get_smearer()
487            self.draw_model(model=model, data=data, page_id=uid, smearer=smear,
488                qmin=qmin, qmax=qmax)
489
490    def draw_model(self, model, page_id, data=None, smearer=None,
491                   enable1D=True, enable2D=False,
492                   state=None,
493                   toggle_mode_on=False,
494                   qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
495        """
496        Draw model.
497       
498        :param model: the model to draw
499        :param name: the name of the model to draw
500        :param data: the data on which the model is based to be drawn
501        :param description: model's description
502        :param enable1D: if true enable drawing model 1D
503        :param enable2D: if true enable drawing model 2D
504        :param qmin:  Range's minimum value to draw model
505        :param qmax:  Range's maximum value to draw model
506        :param qstep: number of step to divide the x and y-axis
507             
508        """
509        if data.__class__.__name__ == "Data1D" or not enable2D:   
510            ## draw model 1D with no loaded data
511           
512            self._draw_model1D(model=model, 
513                               data=data,
514                               page_id=page_id,
515                               enable1D=enable1D, 
516                               smearer=smearer,
517                               qmin=qmin,
518                               qmax=qmax, 
519                               toggle_mode_on=toggle_mode_on,
520                               state=state,
521                               qstep=qstep)
522        else:     
523            ## draw model 2D with no initial data
524             self._draw_model2D(model=model,
525                                page_id=page_id,
526                                data=data,
527                                enable2D=enable2D,
528                                smearer=smearer,
529                                qmin=qmin,
530                                qmax=qmax,
531                                state=state,
532                                toggle_mode_on=toggle_mode_on,
533                                qstep=qstep)
534           
535    def onFit(self):
536        """
537        perform fit
538        """
539        ##  count the number of fitproblem schedule to fit
540        fitproblem_count = 0
541        for value in self.page_finder.values():
542            if value.get_scheduled() == 1:
543                fitproblem_count += 1
544               
545        ## if simultaneous fit change automatically the engine to park
546        if fitproblem_count > 1:
547            self._on_change_engine(engine='park')
548           
549        self.fitproblem_count = fitproblem_count 
550         
551        from sans.fit.Fitting import Fit
552        fitter = Fit(self._fit_engine)
553       
554        if self._fit_engine == "park":
555            engineType = "Simultaneous Fit"
556        else:
557            engineType = "Single Fit"
558           
559        fproblemId = 0
560        self.current_pg = None
561        list_page_id = []
562        for page_id, value in self.page_finder.iteritems():
563            try:
564                if value.get_scheduled() == 1:
565                    #Get list of parameters name to fit
566                    pars = []
567                    templist = []
568                   
569                    page = self.fit_panel.get_page_by_id(page_id)
570                    templist = page.get_param_list()
571                    for element in templist:
572                        name = str(element[1])
573                        pars.append(name)
574                    #Set Engine  (model , data) related to the page on
575                    self._fit_helper(value=value, pars=pars,
576                                     fitter=fitter,
577                                      fitproblem_id=fproblemId,
578                                      title=engineType) 
579                    list_page_id.append(page_id)
580                    fproblemId += 1 
581                    current_page_id = page_id
582            except:
583                raise
584                #msg= "%s error: %s" % (engineType, sys.exc_value)
585                #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
586                #                                      type="stop"))
587                #return
588        ## If a thread is already started, stop it
589        #if self.calc_fit!= None and self.calc_fit.isrunning():
590        #    self.calc_fit.stop()
591         #Handler used for park engine displayed message
592        handler = ConsoleUpdate(parent=self.parent,
593                                manager=self,
594                                improvement_delta=0.1)
595       
596        ## perform single fit
597        if fitproblem_count == 1:
598            calc_fit = FitThread(handler = handler,
599                                    fn=fitter,
600                                   pars=pars,
601                                   page_id=list_page_id,
602                                   completefn=self._single_fit_completed)
603        else:
604            current_page_id = self.sim_page.uid
605            ## Perform more than 1 fit at the time
606            calc_fit = FitThread(handler=handler,
607                                    fn=fitter,
608                                    page_id=list_page_id,
609                                   completefn= self._simul_fit_completed)
610        self.fit_thread_list[current_page_id] = calc_fit
611        calc_fit.queue()
612        self.ready_fit(calc_fit=calc_fit)
613     
614           
615    def ready_fit(self, calc_fit):
616        """
617        Ready for another fit
618        """
619        if self.fitproblem_count != None and self.fitproblem_count > 1:
620            calc_fit.ready(2.5)
621           
622        else:
623            time.sleep(0.4)
624           
625    def remove_plot(self, uid, theory=False):
626        """
627        remove model plot when a fit page is closed
628        """
629        fitproblem = self.page_finder[uid]
630        data = fitproblem.get_fit_data()
631        model = fitproblem.get_model()
632        plot_id = None
633        if model is not None:
634            plot_id = data.id + name
635        if theory:
636            plot_id = data.id
637        group_id = data.group_id
638        wx.PostEvent(self.parent, NewPlotEvent(id=plot_id,
639                                                   group_id=group_id,
640                                                   action='remove'))
641           
642    def store_data(self, uid, data=None, caption=None):
643        """
644        Helper to save page reference into the plug-in
645       
646        :param page: page to store
647       
648        """
649        #create a fitproblem storing all link to data,model,page creation
650        if not uid in self.page_finder.keys():
651            self.page_finder[uid] = FitProblem()
652        self.page_finder[uid].set_fit_data(data)
653        self.page_finder[uid].set_fit_tab_caption(caption)
654       
655    def on_add_new_page(self, event=None):
656        """
657        ask fit panel to create a new empty page
658        """
659        try:
660            page = self.fit_panel.add_empty_page()
661            page_caption = page.window_name
662            # add data associated to the page created
663            if page != None: 
664                self.store_data(uid=page.uid, caption=page_caption,
665                                data=page.get_data())
666                wx.PostEvent(self.parent, StatusEvent(status="Page Created",
667                                               info="info"))
668            else:
669                msg = "Page was already Created"
670                wx.PostEvent(self.parent, StatusEvent(status=msg,
671                                                       info="warning"))
672        except:
673            raise
674            #msg = "Creating Fit page: %s"%sys.exc_value
675            #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
676       
677       
678    def add_fit_page(self, data):
679        """
680        given a data, ask to the fitting panel to create a new fitting page,
681        get this page and store it into the page_finder of this plug-in
682        """
683        page = self.fit_panel.set_data(data)
684        page_caption = page.window_name
685        #append Data1D to the panel containing its theory
686        #if theory already plotted
687        if page.uid in self.page_finder:
688            theory_data = self.page_finder[page.uid].get_theory_data()
689            if issubclass(data.__class__, Data2D):
690                data.group_id = wx.NewId()
691                if theory_data is not None:
692                    group_id = str(page.uid) + " Model1D"
693                    wx.PostEvent(self.parent, 
694                             NewPlotEvent(group_id=group_id,
695                                               action="delete"))
696                    self.parent.update_data(prev_data=theory_data, new_data=data)     
697            else:
698                if theory_data is not None:
699                    group_id = str(page.uid) + " Model2D"
700                    data.group_id = theory_data.group_id
701                    wx.PostEvent(self.parent, 
702                             NewPlotEvent(group_id=group_id,
703                                               action="delete"))
704                    self.parent.update_data(prev_data=theory_data, new_data=data)   
705             
706        self.store_data(uid=page.uid, data=data, caption=page.window_name)
707        if self.sim_page is not None:
708            self.sim_page.draw_page()
709           
710    def _onEVT_SLICER_PANEL(self, event):
711        """
712        receive and event telling to update a panel with a name starting with
713        event.panel_name. this method update slicer panel for a given interactor.
714       
715        :param event: contains type of slicer , paramaters for updating the panel
716            and panel_name to find the slicer 's panel concerned.
717        """
718        for item in self.parent.panels:
719            if self.parent.panels[item].window_caption.startswith(event.panel_name):
720                self.parent.panels[item].set_slicer(event.type, event.params)
721               
722        self.parent._mgr.Update()
723   
724    def _closed_fitpage(self, event):   
725        """
726        request fitpanel to close a given page when its unique data is removed
727        from the plot. close fitpage only when the a loaded data is removed
728        """   
729        if event is None or event.data is None:
730            return
731        if hasattr(event.data,"is_data"):
732            if not event.data.is_data or \
733                event.data.__class__.__name__ == "Data1D":
734                self.fit_panel.close_page_with_data(event.data) 
735       
736    def _add_page_onmenu(self, name, fitproblem=None):
737        """
738        Add name of a closed page of fitpanel in a menu
739        """
740        list = self.menu1.GetMenuItems()
741        for item in list:
742            if name == item.GetItemLabel():
743                self.closed_page_dict[name][1] = fitproblem
744               
745        if not name in self.closed_page_dict.keys():   
746            # Post paramters
747            event_id = wx.NewId()
748            self.menu1.Append(event_id, name, "Show %s fit panel" % name)
749            self.closed_page_dict[name]= [event_id, fitproblem]
750            wx.EVT_MENU(self.parent, event_id, self._open_closed_page)
751       
752    def _open_closed_page(self, event):   
753        """
754        reopen a closed page
755        """
756        for name, value in self.closed_page_dict.iteritems():
757            if event.GetId() in value:
758                uid,fitproblem = value
759                if name !="Model":
760                    data= fitproblem.get_fit_data()
761                    page = self.fit_panel.add_fit_page(data=data, reset=True)
762                    if fitproblem != None:
763                        self.page_finder[uid] = fitproblem
764                        if self.sim_page != None:
765                            self.sim_page.draw_page()
766                           
767                else:
768                    model = fitproblem
769                    self.fit_panel.add_model_page(model=model, topmenu=True,
770                                                  reset= True)
771                    break
772   
773    def _reset_schedule_problem(self, value=0):
774        """
775        unschedule or schedule all fitproblem to be fit
776        """
777        for page_id in self.page_finder.keys():
778            self.page_finder[page_id].schedule_tofit(value)
779           
780    def _fit_helper(self, pars, value, fitproblem_id,fitter, title="Single Fit " ):
781        """
782        helper for fitting
783        """
784        metadata = value.get_fit_data()
785        model = value.get_model()
786        smearer = value.get_smearer()
787        qmin, qmax = value.get_range()
788        self.fit_id = fitproblem_id
789        #Create list of parameters for fitting used
790        templist = []
791       
792        try:
793            #Extra list of parameters and their constraints
794            listOfConstraint = []
795           
796            param = value.get_model_param()
797            if len(param) > 0:
798                for item in param:
799                    ## check if constraint
800                    if item[0] != None and item[1] != None:
801                        listOfConstraint.append((item[0],item[1]))
802                   
803            #Do the single fit
804            fitter.set_model(model, self.fit_id,
805                                   pars, constraints=listOfConstraint)
806           
807            fitter.set_data(data=metadata, id=self.fit_id,
808                                 smearer=smearer, qmin=qmin, qmax=qmax)
809           
810            fitter.select_problem_for_fit(id=self.fit_id,
811                                               value=value.get_scheduled())
812            value.clear_model_param()
813        except:
814            raise
815            #msg = title + " error: %s" % sys.exc_value
816            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
817         
818    def _onSelect(self,event):
819        """
820        when Select data to fit a new page is created .Its reference is
821        added to self.page_finder
822        """
823        self.panel = event.GetEventObject()
824        Plugin.on_perspective(self, event=event)
825        for plottable in self.panel.graph.plottables:
826            if plottable.__class__.__name__ in ["Data1D", "Theory1D"]:
827                if plottable.name == self.panel.graph.selected_plottable:
828                    data = plottable
829                    self.add_fit_page(data=data)
830                    return
831            else:
832                data = plottable
833                self.add_fit_page(data=data)
834           
835    def update_fit(self, result=None, msg=""):
836        """
837        """
838        print "update_fit result", result
839       
840    def _single_fit_completed(self, result, pars, page_id, elapsed=None):
841        """
842        Display fit result on one page of the notebook.
843       
844        :param result: result of fit
845        :param pars: list of names of parameters fitted
846        :param current_pg: the page where information will be displayed
847        :param qmin: the minimum value of x to replot the model
848        :param qmax: the maximum value of x to replot model
849         
850        """     
851        try:
852            if result == None:
853                msg= "Simple Fitting Stop !!!"
854                wx.PostEvent(self.parent, StatusEvent(status=msg,info="warning",
855                                                      type="stop"))
856                return
857            if not numpy.isfinite(result.fitness) or \
858                    numpy.any(result.pvec == None) or \
859                    not numpy.all(numpy.isfinite(result.pvec)):
860                msg = "Single Fitting did not converge!!!"
861                wx.PostEvent(self.parent, 
862                             StatusEvent(status=msg, type="stop"))
863                return
864            for uid in page_id:
865                value = self.page_finder[uid]   
866                model = value.get_model()
867                page_id = uid
868                   
869                param_name = []
870                for name in pars:
871                    param_name.append(name)
872                   
873                cpage = self.fit_panel.get_page_by_id(uid)
874                cpage.onsetValues(result.fitness, 
875                                  param_name, result.pvec,result.stderr)
876                cpage._on_fit_complete()
877           
878        except:
879            raise
880            #msg = "Single Fit completed but Following"
881            #msg += " error occurred:%s" % sys.exc_value
882            #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
883            #                                      type="stop"))
884            return
885       
886    def _simul_fit_completed(self, result, page_id,pars=None, elapsed=None):
887        """
888        Parameter estimation completed,
889        display the results to the user
890       
891        :param alpha: estimated best alpha
892        :param elapsed: computation time
893       
894        """
895        if page_id is None:
896            page_id = []
897        ## fit more than 1 model at the same time
898        try:
899            msg = "" 
900            if result == None:
901                msg = "Complex Fitting Stop !!!"
902                wx.PostEvent(self.parent, StatusEvent(status=msg,
903                                                      type="stop"))
904                return
905            if not numpy.isfinite(result.fitness) or \
906                numpy.any(result.pvec == None) or not \
907                numpy.all(numpy.isfinite(result.pvec)):
908                msg= "Simultaneous Fitting did not converge!!!"
909                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
910                return
911             
912            for uid in page_id:   
913                value = self.page_finder[uid]
914                model = value.get_model()
915                data =  value.get_fit_data()
916                small_param_name = []
917                small_out = []
918                small_cov = []
919                #Separate result in to data corresponding to each page
920                for p in result.parameters:
921                    model_name, param_name = self.split_string(p.name) 
922                    if model.name == model_name:
923                        p_name= model.name+"."+param_name
924                        if p.name == p_name:     
925                            if p.value != None and numpy.isfinite(p.value):
926                                small_out.append(p.value)
927                                small_param_name.append(param_name)
928                                small_cov.append(p.stderr)
929                # Display result on each page
930                cpage = self.fit_panel.get_page_by_id(uid)
931                cpage.onsetValues(result.fitness,
932                                  small_param_name,
933                                  small_out,small_cov)
934                cpage._on_fit_complete()
935        except:
936            msg = "Simultaneous Fit completed"
937            msg += " but Following error occurred:%s" % sys.exc_value
938            wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
939   
940    def _on_show_panel(self, event):
941        """
942        """
943        pass
944       
945    def _onset_engine_park(self,event):
946        """
947        set engine to park
948        """
949        self._on_change_engine('park')
950       
951    def _onset_engine_scipy(self,event):
952        """
953        set engine to scipy
954        """
955        self._on_change_engine('scipy')
956       
957    def _on_slicer_event(self, event):
958        """
959        Receive a panel as event and send it to guiframe
960       
961        :param event: event containing a panel
962       
963        """
964        if event.panel is not None:
965            new_panel = event.panel
966            self.slicer_panels.append(event.panel)
967            # Set group ID if available
968            event_id = self.parent.popup_panel(new_panel)
969            #self.menu3.Append(event_id, new_panel.window_caption,
970            #                 "Show %s plot panel" % new_panel.window_caption)
971            # Set id to allow us to reference the panel later
972         
973            new_panel.uid = event_id
974            self.mypanels.append(new_panel) 
975       
976    def _onclearslicer(self, event):
977        """
978        Clear the boxslicer when close the panel associate with this slicer
979        """
980        name =event.GetPane().caption
981   
982        for panel in self.slicer_panels:
983            if panel.window_caption==name:
984               
985                for item in self.parent.panels:
986                    if hasattr(self.parent.panels[item],"uid"):
987                        if self.parent.panels[item].uid ==panel.base.uid:
988                            self.parent.panels[item].onClearSlicer(event)
989                            self.parent._mgr.Update()
990                            break 
991                break
992   
993    def _return_engine_type(self):
994        """
995        return the current type of engine
996        """
997        return self._fit_engine
998     
999     
1000    def _on_change_engine(self, engine='park'):
1001        """
1002        Allow to select the type of engine to perform fit
1003       
1004        :param engine: the key work of the engine
1005       
1006        """
1007        ## saving fit engine name
1008        self._fit_engine = engine
1009        ## change menu item state
1010        if engine=="park":
1011            self.menu1.FindItemByPosition(0).Check(False)
1012            self.menu1.FindItemByPosition(1).Check(True)
1013        else:
1014            self.menu1.FindItemByPosition(0).Check(True)
1015            self.menu1.FindItemByPosition(1).Check(False)
1016        ## post a message to status bar
1017        msg = "Engine set to: %s" % self._fit_engine
1018        wx.PostEvent(self.parent, 
1019                     StatusEvent(status=msg))
1020        ## send the current engine type to fitpanel
1021        self.fit_panel._on_engine_change(name=self._fit_engine)
1022       
1023    def _on_model_panel(self, evt):
1024        """
1025        react to model selection on any combo box or model menu.plot the model 
1026       
1027        :param evt: wx.combobox event
1028       
1029        """
1030        model = evt.model
1031        uid = evt.uid
1032        qmin = evt.qmin
1033        qmax = evt.qmax
1034        smearer = evt.smearer
1035       
1036        if model == None:
1037            return
1038       
1039        if self.page_finder[uid].get_model() is None:
1040            model.name = "M" + str(self.index_model)
1041            self.index_model += 1 
1042        else:
1043            model.name = self.page_finder[uid].get_model().name
1044        # save the name containing the data name with the appropriate model
1045        self.page_finder[uid].set_model(model)
1046        self.page_finder[uid].set_range(qmin=qmin, qmax=qmax)
1047        if self.sim_page is not None:
1048            self.sim_page.draw_page()
1049       
1050    def _update1D(self,x, output):
1051        """
1052        Update the output of plotting model 1D
1053        """
1054        msg = "Plot updating ... "
1055        wx.PostEvent(self.parent, StatusEvent(status=msg,type="update"))
1056        self.ready_fit()
1057       
1058   
1059    def _fill_default_model2D(self, theory, page_id, qmax,qstep, qmin=None):
1060        """
1061        fill Data2D with default value
1062       
1063        :param theory: Data2D to fill
1064       
1065        """
1066        from DataLoader.data_info import Detector, Source
1067       
1068        detector = Detector()
1069        theory.detector.append(detector)         
1070        theory.source= Source()
1071       
1072        ## Default values   
1073        theory.detector[0].distance= 8000   # mm       
1074        theory.source.wavelength= 6         # A     
1075        theory.detector[0].pixel_size.x= 5  # mm
1076        theory.detector[0].pixel_size.y= 5  # mm
1077       
1078        theory.detector[0].beam_center.x= qmax
1079        theory.detector[0].beam_center.y= qmax
1080   
1081        ## create x_bins and y_bins of the model 2D
1082        pixel_width_x = theory.detector[0].pixel_size.x
1083        pixel_width_y = theory.detector[0].pixel_size.y
1084        center_x      = theory.detector[0].beam_center.x/pixel_width_x
1085        center_y      = theory.detector[0].beam_center.y/pixel_width_y
1086
1087        # theory default: assume the beam
1088        #center is located at the center of sqr detector
1089        xmax = qmax
1090        xmin = -qmax
1091        ymax = qmax
1092        ymin = -qmax
1093       
1094        x=  numpy.linspace(start= -1*qmax,
1095                               stop=qmax,
1096                               num=qstep,
1097                               endpoint=True) 
1098        y = numpy.linspace(start=-1*qmax,
1099                               stop= qmax,
1100                               num= qstep,
1101                               endpoint=True)
1102         
1103        ## use data info instead
1104        new_x = numpy.tile(x, (len(y),1))
1105        new_y = numpy.tile(y, (len(x),1))
1106        new_y = new_y.swapaxes(0,1)
1107       
1108        # all data reuire now in 1d array
1109        qx_data = new_x.flatten()
1110        qy_data = new_y.flatten()
1111       
1112        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data)
1113        # set all True (standing for unmasked) as default
1114        mask    = numpy.ones(len(qx_data), dtype = bool)
1115       
1116        # calculate the range of qx and qy: this way,
1117        # it is a little more independent
1118        x_size = xmax- xmin
1119        y_size = ymax -ymin
1120       
1121        # store x and y bin centers in q space
1122        x_bins  = x
1123        y_bins  = y
1124        # bin size: x- & y-directions
1125        xstep = x_size/len(x_bins-1)
1126        ystep = y_size/len(y_bins-1)
1127       
1128        #theory.data = numpy.zeros(len(mask))
1129        theory.err_data = numpy.ones(len(mask))
1130        theory.qx_data = qx_data
1131        theory.qy_data = qy_data 
1132        theory.q_data = q_data
1133        theory.mask = mask           
1134        theory.x_bins = x_bins 
1135        theory.y_bins = y_bins   
1136       
1137        # max and min taking account of the bin sizes
1138        theory.xmin = xmin
1139        theory.xmax = xmax
1140        theory.ymin = ymin
1141        theory.ymax = ymax
1142        theory.group_id = str(page_id) + " Model2D"
1143        theory.id = str(page_id) + " Model2D"
1144 
1145    def _complete1D(self, x,y, page_id, elapsed,index,model,
1146                    toggle_mode_on=False,state=None, data=None):
1147        """
1148        Complete plotting 1D data
1149        """ 
1150        try:
1151            new_plot = Data1D(x=x, y=y)
1152            new_plot.is_data = False
1153            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
1154            if data != None:
1155                _xaxis, _xunit = data.get_xaxis() 
1156                _yaxis, _yunit = data.get_yaxis() 
1157                new_plot.title = data.name
1158                #if the theory is already plotted use the same group id
1159                #to replot
1160                if page_id in self.page_finder:
1161                    theory_data = self.page_finder[page_id].get_theory_data()
1162                    if theory_data is not None:
1163                       data.group_id = theory_data.group_id
1164                #data is plotted before the theory, then take its group_id
1165                #assign to the new theory
1166                new_plot.group_id = data.group_id
1167               
1168            else:
1169                _xaxis, _xunit = "\\rm{Q}", 'A^{-1}'
1170                _yaxis, _yunit = "\\rm{Intensity} ", "cm^{-1}"
1171                new_plot.title = "Analytical model 1D "
1172                #find a group id to plot theory without data
1173                new_plot.group_id =  str(page_id) + " Model1D" 
1174            new_plot.id =  str(page_id) + " Model1D" 
1175           
1176            #find if this theory was already plotted and replace that plot given
1177            #the same id
1178           
1179            theory_data = self.page_finder[page_id].get_theory_data()
1180            if theory_data is not None:
1181                new_plot.id = theory_data.id
1182             
1183            new_plot.name = model.name + " ["+ str(model.__class__.__name__)+ "]"
1184            new_plot.xaxis(_xaxis, _xunit)
1185            new_plot.yaxis(_yaxis, _yunit)
1186            if toggle_mode_on:
1187                new_plot.id =  str(page_id) + " Model" 
1188                wx.PostEvent(self.parent, 
1189                             NewPlotEvent(group_id=str(page_id) + " Model2D",
1190                                               action="Hide"))
1191           
1192            self.page_finder[page_id].set_theory_data(new_plot)
1193            if data is None:
1194                data_id = None
1195            else:
1196                data_id = data.id
1197            self.parent.update_theory(data_id=data_id, 
1198                                       theory=new_plot,
1199                                       state=state)     
1200            current_pg = self.fit_panel.get_page_by_id(page_id)
1201            title = new_plot.title
1202            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1203                                            title= str(title)))
1204           
1205            wx.PostEvent(current_pg,
1206                Chi2UpdateEvent(output=self._cal_chisqr(data=data,
1207                                                        page_id=page_id,
1208                                                        index=index)))
1209            msg = "Plot 1D  complete !"
1210            wx.PostEvent( self.parent, StatusEvent(status=msg, type="stop" ))
1211        except:
1212            raise
1213            #msg = " Error occurred when drawing %s Model 1D: " % new_plot.name
1214            #msg += " %s"  % sys.exc_value
1215            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1216   
1217    def _update2D(self, output,time=None):
1218        """
1219        Update the output of plotting model
1220        """
1221        wx.PostEvent(self.parent, StatusEvent(status="Plot \
1222        #updating ... ", type="update"))
1223        self.ready_fit()
1224 
1225    def _complete2D(self, image, data, model, page_id,  elapsed, index, qmin,
1226                     qmax, toggle_mode_on=False,state=None,qstep=DEFAULT_NPTS):
1227        """
1228        Complete get the result of modelthread and create model 2D
1229        that can be plot.
1230        """
1231        err_image = numpy.zeros(numpy.shape(image))
1232       
1233        new_plot= Data2D(image=image, err_image=err_image)
1234        new_plot.name = model.name
1235       
1236        if data is None:
1237            self._fill_default_model2D(theory=new_plot, 
1238                                       qmax=qmax, 
1239                                       page_id=page_id,
1240                                       qstep=qstep,
1241                                        qmin= qmin)
1242           
1243        else:
1244            new_plot.id = str(page_id) + " Model2D"
1245            new_plot.group_id = str(page_id) + " Model2D"
1246            new_plot.x_bins = data.x_bins
1247            new_plot.y_bins = data.y_bins
1248            new_plot.detector = data.detector
1249            new_plot.source = data.source
1250            new_plot.is_data = False 
1251            new_plot.qx_data = data.qx_data
1252            new_plot.qy_data = data.qy_data
1253            new_plot.q_data = data.q_data
1254            #numpy.zeros(len(data.err_data))#data.err_data
1255            new_plot.err_data = err_image
1256            new_plot.mask = data.mask
1257            ## plot boundaries
1258            new_plot.ymin = data.ymin
1259            new_plot.ymax = data.ymax
1260            new_plot.xmin = data.xmin
1261            new_plot.xmax = data.xmax
1262        new_plot.is_data = False
1263        new_plot.name = model.name + " ["+ str(model.__class__.__name__)+ "]"
1264        new_plot.title = "Analytical model 2D "
1265        theory_data = deepcopy(new_plot)
1266        theory_data.name = "Unknown"
1267        if toggle_mode_on:
1268            new_plot.id = str(page_id) + " Model"     
1269            wx.PostEvent(self.parent, 
1270                             NewPlotEvent(group_id=str(page_id) + " Model1D",
1271                                               action="Hide"))
1272       
1273        self.page_finder[page_id].set_theory_data(new_plot)
1274        if data is None:
1275            data_id = None
1276        else:
1277            data_id = data.id
1278        self.parent.update_theory(data_id=data_id, 
1279                                       theory=new_plot,
1280                                       state=state) 
1281        current_pg = self.fit_panel.get_page_by_id(page_id)
1282        title = new_plot.title
1283        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1284                                               title=title))
1285        # Chisqr in fitpage
1286        wx.PostEvent(current_pg,
1287            Chi2UpdateEvent(output=self._cal_chisqr(data=data,
1288                                                     page_id=page_id,
1289                                                     index=index)))
1290        msg = "Plot 2D complete !"
1291        wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1292   
1293    def _draw_model2D(self, model, page_id, data=None, smearer=None,
1294                      description=None, enable2D=False,
1295                      state=None,
1296                      toggle_mode_on=False,
1297                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX,
1298                       qstep=DEFAULT_NPTS):
1299        """
1300        draw model in 2D
1301       
1302        :param model: instance of the model to draw
1303        :param description: the description of the model
1304        :param enable2D: when True allows to draw model 2D
1305        :param qmin: the minimum value to  draw model 2D
1306        :param qmax: the maximum value to draw model 2D
1307        :param qstep: the number of division of Qx and Qy of the model to draw
1308           
1309        """
1310        x=  numpy.linspace(start=-1*qmax,
1311                               stop=qmax,
1312                               num=qstep,
1313                               endpoint=True) 
1314        y = numpy.linspace(start= -1*qmax,
1315                               stop=qmax,
1316                               num=qstep,
1317                               endpoint=True)
1318        if model is None:
1319            msg = "Panel with ID: %s does not contained model" % str(page_id)
1320            raise ValueError, msg
1321        ## use data info instead
1322        if data is not None:
1323            ## check if data2D to plot
1324            if hasattr(data, "x_bins"):
1325                enable2D = True
1326                x = data.x_bins
1327                y = data.y_bins
1328               
1329        if not enable2D:
1330            return None, None
1331        try:
1332            from model_thread import Calc2D
1333            ## If a thread is already started, stop it
1334            if (self.calc_2D is not None) and self.calc_2D.isrunning():
1335                self.calc_2D.stop()
1336
1337            self.calc_2D = Calc2D(x=x,
1338                                    y=y,
1339                                    model=model, 
1340                                    data=data,
1341                                    page_id=page_id,
1342                                    smearer=smearer,
1343                                    qmin=qmin,
1344                                    qmax=qmax,
1345                                    qstep=qstep,
1346                                    toggle_mode_on=toggle_mode_on,
1347                                    state=state,
1348                                    completefn=self._complete2D)#,
1349                                    #updatefn=self._update2D)
1350            self.calc_2D.queue()
1351
1352        except:
1353            raise
1354            #msg = " Error occurred when drawing %s Model 2D: " % model.name
1355            #msg += " %s" % sys.exc_value
1356            #wx.PostEvent(self.parent, StatusEvent(status=msg))
1357
1358    def _draw_model1D(self, model, page_id, data=None, smearer=None,
1359                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, 
1360                state=None,
1361                toggle_mode_on=False,
1362                qstep=DEFAULT_NPTS, enable1D=True):
1363        """
1364        Draw model 1D from loaded data1D
1365       
1366        :param data: loaded data
1367        :param model: the model to plot
1368       
1369        """
1370        x=  numpy.linspace(start=qmin,
1371                           stop=qmax,
1372                           num=qstep,
1373                           endpoint=True
1374                           )
1375        if data is not None:
1376            ## check for data2D
1377            if hasattr(data,"x_bins"):
1378                return
1379            x = data.x
1380            if qmin == DEFAULT_QMIN :
1381                qmin = min(data.x)
1382            if qmax == DEFAULT_QMAX:
1383                qmax = max(data.x) 
1384        if not enable1D:
1385            return 
1386        try:
1387            from model_thread import Calc1D
1388            ## If a thread is already started, stop it
1389            if (self.calc_1D is not None) and self.calc_1D.isrunning():
1390                self.calc_1D.stop()
1391            self.calc_1D = Calc1D(x=x,
1392                                  data=data,
1393                                  model=model,
1394                                  page_id=page_id, 
1395                                  qmin=qmin,
1396                                  qmax=qmax,
1397                                  smearer=smearer,
1398                                  state=state,
1399                                  toggle_mode_on=toggle_mode_on,
1400                                  completefn=self._complete1D)#,
1401                                  #updatefn=self._update1D)
1402            self.calc_1D.queue()
1403
1404        except:
1405            msg = " Error occurred when drawing %s Model 1D: " % model.name
1406            msg += " %s" % sys.exc_value
1407            wx.PostEvent(self.parent, StatusEvent(status=msg))
1408
1409    def _cal_chisqr(self, page_id, data=None, index=None): 
1410        """
1411        Get handy Chisqr using the output from draw1D and 2D,
1412        instead of calling expansive CalcChisqr in guithread
1413        """
1414        # default chisqr
1415        chisqr = None
1416       
1417        # return None if data == None
1418        if data == None: return chisqr
1419       
1420        # Get data: data I, theory I, and data dI in order
1421        if data.__class__.__name__ =="Data2D":
1422            if index == None: 
1423                index = numpy.ones(len(data.data),ntype=bool)
1424            # get rid of zero error points
1425            index = index & (data.err_data != 0) 
1426            fn = data.data[index] 
1427            theory_data = self.page_finder[page_id].get_theory_data()
1428            gn = theory_data.data[index]
1429            en = data.err_data[index]
1430        else:
1431            # 1 d theory from model_thread is only in the range of index
1432            if index == None:
1433                index = numpy.ones(len(data.y), ntype=bool)
1434            if data.dy == None or data.dy == []:
1435                dy = numpy.ones(len(data.y))
1436            else:
1437                ## Set consitently w/AbstractFitengine:
1438                # But this should be corrected later.
1439                dy = data.dy
1440                dy[dy==0] = 1 
1441            fn = data.y[index] 
1442            theory_data = self.page_finder[page_id].get_theory_data()
1443            gn = theory_data.y
1444            en = dy[index]
1445        # residual
1446        res = (fn - gn)/en
1447        # get chisqr only w/finite
1448        val = res[numpy.isfinite(res)]*res[numpy.isfinite(res)]
1449        chisqr = numpy.average(val)
1450        return chisqr
1451   
1452   
1453#def profile(fn, *args, **kw):
1454#    import cProfile, pstats, os
1455#    global call_result
1456#    def call():
1457#        global call_result
1458#        call_result = fn(*args, **kw)
1459#    cProfile.runctx('call()', dict(call=call), {}, 'profile.out')
1460#    stats = pstats.Stats('profile.out')
1461#    #stats.sort_stats('time')
1462#    stats.sort_stats('calls')
1463#    stats.print_stats()
1464#    os.unlink('profile.out')
1465#    return call_result
1466if __name__ == "__main__":
1467    i = Plugin()
1468   
1469   
1470   
1471   
Note: See TracBrowser for help on using the repository browser.