source: sasview/sansview/perspectives/fitting/fitting.py @ 511c6810

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 511c6810 was f95301b, checked in by Gervaise Alina <gervyh@…>, 14 years ago

work on saving state

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