source: sasview/sansview/perspectives/fitting/fitting.py @ 8ee56a9

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

work on delete data

  • Property mode set to 100644
File size: 56.2 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(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])
340                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
341                                        title=data.title))
342                page = self.fit_panel.set_state(state)   
343            else:
344                self.parent.add_data(data_list=[data])
345                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
346                                        title=data.title))
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.add_fit_page(data)
351                caption = panel.window_name
352                self.store_data(page=panel.id, data=data, caption=caption)
353                self.mypanels.append(panel) 
354               
355            # get ready for the next set_state
356            self.state_index += 1
357
358            #reset state variables to default when all set_state is finished.
359            if len(self.temp_state) == self.state_index:
360               
361                self.temp_state = []
362                #self.state_index = 0
363                # Make sure the user sees the fitting panel after loading
364                #self.parent.set_perspective(self.perspective)
365                self.on_perspective(event=None)
366        except:
367            self.state_index==0
368            self.temp_state = []
369            raise
370                 
371    def save_fit_state(self, filepath, fitstate): 
372        """
373        save fit page state into file
374        """
375        self.state_reader.write(filename=filepath, fitstate=fitstate)
376       
377    def set_fit_range(self, id, qmin, qmax):
378        """
379        Set the fitting range of a given page
380        """
381        self.page_finder[id].set_range(qmin=qmin, qmax=qmax)
382                   
383    def schedule_for_fit(self,value=0, id=None,fitproblem =None): 
384        """
385        Set the fit problem field to 0 or 1 to schedule that problem to fit.
386        Schedule the specified fitproblem or get the fit problem related to
387        the current page and set value.
388       
389        :param value: integer 0 or 1
390        :param fitproblem: fitproblem to schedule or not to fit
391       
392        """   
393        if fitproblem !=None:
394            fitproblem.schedule_tofit(value)
395        else:
396            self.page_finder[id].schedule_tofit(value)
397         
398    def get_page_finder(self):
399        """
400        return self.page_finder used also by simfitpage.py
401        """ 
402        return self.page_finder
403   
404    def set_page_finder(self,modelname,names,values):
405        """
406        Used by simfitpage.py to reset a parameter given the string constrainst.
407         
408        :param modelname: the name ot the model for with the parameter has to reset
409        :param value: can be a string in this case.
410        :param names: the paramter name
411         
412        :note: expecting park used for fit.
413         
414        """ 
415        sim_page_id = self.sim_page.id
416        for id, value in self.page_finder.iteritems():
417            if id != sim_page_id:
418                list = value.get_model()
419                model = list[0]
420                if model.name == modelname:
421                    value.set_model_param(names, values)
422                    break
423         
424    def split_string(self,item): 
425        """
426        receive a word containing dot and split it. used to split parameterset
427        name into model name and parameter name example: ::
428       
429            paramaterset (item) = M1.A
430            Will return model_name = M1 , parameter name = A
431           
432        """
433        if string.find(item,".")!=-1:
434            param_names= re.split("\.",item)
435            model_name=param_names[0]           
436            ##Assume max len is 3; eg., M0.radius.width
437            if len(param_names) == 3:
438                param_name=param_names[1]+"."+param_names[2]
439            else:
440                param_name=param_names[1]                   
441            return model_name,param_name
442       
443    def stop_fit(self):
444        """
445        Stop the fit engine
446        """
447        if self.calc_fit!= None and self.calc_fit.isrunning():
448            self.calc_fit.stop()
449            wx.PostEvent(self.parent, StatusEvent(status="Fitting  \
450                is cancelled" , type="stop"))
451 
452    def set_smearer(self, id, smearer, qmin=None, qmax=None, draw=True):
453        """
454        Get a smear object and store it to a fit problem
455       
456        :param smearer: smear object to allow smearing data
457       
458        """   
459        if id not in self.page_finder.keys():
460            msg = "Cannot find ID: %s in page_finder" % str(id)
461            raise ValueError, msg
462        self.page_finder[id].set_smearer(smearer)
463        if draw:
464            ## draw model 1D with smeared data
465            data =  self.page_finder[id].get_fit_data()
466            model = self.page_finder[id].get_model()
467            if model is None:
468                return
469            ## if user has already selected a model to plot
470            ## redraw the model with data smeared
471            smear = self.page_finder[id].get_smearer()
472            self.draw_model(model=model, data=data, id=id, smearer=smear,
473                qmin=qmin, qmax=qmax)
474
475    def draw_model(self, model, id, data=None, smearer=None,
476                   enable1D=True, enable2D=False,
477                   state=None,
478                   toggle_mode_on=False,
479                   qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
480        """
481        Draw model.
482       
483        :param model: the model to draw
484        :param name: the name of the model to draw
485        :param data: the data on which the model is based to be drawn
486        :param description: model's description
487        :param enable1D: if true enable drawing model 1D
488        :param enable2D: if true enable drawing model 2D
489        :param qmin:  Range's minimum value to draw model
490        :param qmax:  Range's maximum value to draw model
491        :param qstep: number of step to divide the x and y-axis
492             
493        """
494        if data.__class__.__name__ == "Data1D" or not enable2D:   
495            ## draw model 1D with no loaded data
496           
497            self._draw_model1D(model=model, 
498                               data=data,
499                               id=id,
500                               enable1D=enable1D, 
501                               smearer=smearer,
502                               qmin=qmin,
503                               qmax=qmax, 
504                               toggle_mode_on=toggle_mode_on,
505                               state=state,
506                               qstep=qstep)
507        else:     
508            ## draw model 2D with no initial data
509             self._draw_model2D(model=model,
510                                id=id,
511                                data=data,
512                                enable2D=enable2D,
513                                smearer=smearer,
514                                qmin=qmin,
515                                qmax=qmax,
516                                state=state,
517                                toggle_mode_on=toggle_mode_on,
518                                qstep=qstep)
519           
520    def onFit(self):
521        """
522        perform fit
523        """
524        ##  count the number of fitproblem schedule to fit
525        fitproblem_count = 0
526        for value in self.page_finder.itervalues():
527            if value.get_scheduled() == 1:
528                fitproblem_count += 1
529               
530        ## if simultaneous fit change automatically the engine to park
531        if fitproblem_count > 1:
532            self._on_change_engine(engine='park')
533           
534        self.fitproblem_count = fitproblem_count 
535         
536        from sans.fit.Fitting import Fit
537        self.fitter = Fit(self._fit_engine)
538       
539        if self._fit_engine == "park":
540            engineType = "Simultaneous Fit"
541        else:
542            engineType = "Single Fit"
543           
544        fproblemId = 0
545        self.current_pg = None
546        for id, value in self.page_finder.iteritems():
547            try:
548                if value.get_scheduled() == 1:
549                    #Get list of parameters name to fit
550                    pars = []
551                    templist = []
552                    page = self.fit_panel.get_page_by_id(id)
553                    templist = page.get_param_list()
554                    for element in templist:
555                        name = str(element[1])
556                        pars.append(name)
557                    #Set Engine  (model , data) related to the page on
558                    self._fit_helper(value=value, pars=pars,
559                                      id=fproblemId, title=engineType) 
560                    fproblemId += 1 
561                    self.current_page_id = page
562            except:
563                raise
564                #msg= "%s error: %s" % (engineType, sys.exc_value)
565                #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
566                #                                      type="stop"))
567                #return
568        ## If a thread is already started, stop it
569        #if self.calc_fit!= None and self.calc_fit.isrunning():
570        #    self.calc_fit.stop()
571         #Handler used for park engine displayed message
572        handler = ConsoleUpdate(parent=self.parent,improvement_delta=0.1)
573        ## perform single fit
574        if fitproblem_count == 1:
575            calc_fit = FitThread(parent=self.parent,
576                                    handler = handler,
577                                    fn=self.fitter,
578                                   pars=pars,
579                                   updatefn=handler.update_fit,
580                                   completefn=self._single_fit_completed)
581        else:
582            ## Perform more than 1 fit at the time
583            calc_fit = FitThread(parent=self.parent,
584                                handler=handler,
585                                    fn= self.fitter,
586                                   completefn= self._simul_fit_completed,
587                                  updatefn=handler.update_fit)
588       
589        calc_fit.queue()
590        self.ready_fit(calc_fit=calc_fit)
591     
592    def ready_fit(self, calc_fit):
593        """
594        Ready for another fit
595        """
596        if self.fitproblem_count != None and self.fitproblem_count > 1:
597            calc_fit.ready(2.5)
598           
599        else:
600            time.sleep(0.4)
601           
602    def remove_plot(self, id, theory=False):
603        """
604        remove model plot when a fit page is closed
605        """
606        fitproblem = self.page_finder[id]
607        data = fitproblem.get_fit_data()
608        model = fitproblem.get_model()
609        id = None
610        if model is not None:
611            id = data.id + name
612        if theory:
613            id = data.id
614        group_id = data.group_id
615        wx.PostEvent(self.parent, NewPlotEvent(id=id,
616                                                   group_id=group_id,
617                                                   action='remove'))
618           
619    def store_data(self, id, data=None, caption=None):
620        """
621        Helper to save page reference into the plug-in
622       
623        :param page: page to store
624       
625        """
626        #create a fitproblem storing all link to data,model,page creation
627        if not id in self.page_finder.keys():
628            self.page_finder[id] = FitProblem()
629        self.page_finder[id].set_fit_data(data)
630        self.page_finder[id].set_fit_tab_caption(caption)
631       
632    def on_add_new_page(self, event=None):
633        """
634        ask fit panel to create a new empty page
635        """
636        try:
637            page = self.fit_panel.add_empty_page()
638            page_caption = page.window_name
639            # add data associated to the page created
640            if page != None: 
641                self.store_data(id=page.id, caption=page_caption,
642                                data=page.get_data())
643                wx.PostEvent(self.parent, StatusEvent(status="Page Created",
644                                               info="info"))
645            else:
646                msg = "Page was already Created"
647                wx.PostEvent(self.parent, StatusEvent(status=msg,
648                                                       info="warning"))
649        except:
650            raise
651            #msg = "Creating Fit page: %s"%sys.exc_value
652            #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
653       
654       
655    def add_fit_page(self, data):
656        """
657        given a data, ask to the fitting panel to create a new fitting page,
658        get this page and store it into the page_finder of this plug-in
659        """
660        page = self.fit_panel.set_data(data)
661        page_caption = page.window_name
662        #append Data1D to the panel containing its theory
663        #if theory already plotted
664        if page.id in self.page_finder:
665            theory_data = self.page_finder[page.id].get_theory_data()
666            if issubclass(data.__class__, Data2D):
667                data.group_id = wx.NewId()
668                if theory_data is not None:
669                    group_id = str(page.id) + " Model1D"
670                    wx.PostEvent(self.parent, 
671                             NewPlotEvent(group_id=group_id,
672                                               action="delete"))
673                    self.parent.update_data(prev_data=theory_data, new_data=data)     
674            else:
675                if theory_data is not None:
676                    group_id = str(page.id) + " Model2D"
677                    data.group_id = theory_data.group_id
678                    wx.PostEvent(self.parent, 
679                             NewPlotEvent(group_id=group_id,
680                                               action="delete"))
681                    self.parent.update_data(prev_data=theory_data, new_data=data)   
682             
683        self.store_data(id=page.id, data=data, caption=page.window_name)
684        if self.sim_page is not None:
685            self.sim_page.draw_page()
686           
687    def _onEVT_SLICER_PANEL(self, event):
688        """
689        receive and event telling to update a panel with a name starting with
690        event.panel_name. this method update slicer panel for a given interactor.
691       
692        :param event: contains type of slicer , paramaters for updating the panel
693            and panel_name to find the slicer 's panel concerned.
694        """
695        for item in self.parent.panels:
696            if self.parent.panels[item].window_caption.startswith(event.panel_name):
697                self.parent.panels[item].set_slicer(event.type, event.params)
698               
699        self.parent._mgr.Update()
700   
701    def _closed_fitpage(self, event):   
702        """
703        request fitpanel to close a given page when its unique data is removed
704        from the plot. close fitpage only when the a loaded data is removed
705        """   
706        if event is None or event.data is None:
707            return
708       
709        if hasattr(event.data,"is_data"):
710            if not event.data.is_data or \
711                event.data.__class__.__name__=="Data1D":
712                self.fit_panel.close_page_with_data(event.data) 
713       
714    def _add_page_onmenu(self, name,fitproblem=None):
715        """
716        Add name of a closed page of fitpanel in a menu
717        """
718        list = self.menu1.GetMenuItems()
719        for item in list:
720            if name == item.GetItemLabel():
721                self.closed_page_dict[name][1] = fitproblem
722               
723        if not name in self.closed_page_dict.keys():   
724            # Post paramters
725            event_id = wx.NewId()
726            self.menu1.Append(event_id, name, "Show %s fit panel" % name)
727            self.closed_page_dict[name]= [event_id, fitproblem]
728            wx.EVT_MENU(self.parent,event_id,  self._open_closed_page)
729       
730    def _open_closed_page(self, event):   
731        """
732        reopen a closed page
733        """
734        for name, value in self.closed_page_dict.iteritems():
735            if event.GetId() in value:
736                id,fitproblem = value
737                if name !="Model":
738                    data= fitproblem.get_fit_data()
739                    page = self.fit_panel.add_fit_page(data=data, reset=True)
740                    if fitproblem != None:
741                        self.page_finder[id] = fitproblem
742                        if self.sim_page != None:
743                            self.sim_page.draw_page()
744                           
745                else:
746                    model = fitproblem
747                    self.fit_panel.add_model_page(model=model, topmenu=True,
748                                                  reset= True)
749                    break
750   
751    def _reset_schedule_problem(self, id, value=0):
752        """
753        unschedule or schedule all fitproblem to be fit
754        """
755        for page_id in self.page_finder.keys():
756            self.page_finder[id].schedule_tofit(value)
757           
758    def _fit_helper(self, pars, value, id, title="Single Fit " ):
759        """
760        helper for fitting
761        """
762        metadata = value.get_fit_data()
763        model = value.get_model()
764        smearer = value.get_smearer()
765        qmin, qmax = value.get_range()
766        self.fit_id = id
767        #Create list of parameters for fitting used
768        templist = []
769       
770        try:
771            #Extra list of parameters and their constraints
772            listOfConstraint = []
773           
774            param = value.get_model_param()
775            if len(param) > 0:
776                for item in param:
777                    ## check if constraint
778                    if item[0] != None and item[1] != None:
779                        listOfConstraint.append((item[0],item[1]))
780                   
781            #Do the single fit
782            self.fitter.set_model(model, self.fit_id,
783                                   pars, constraints=listOfConstraint)
784           
785            self.fitter.set_data(data=metadata, id=self.fit_id,
786                                 smearer=smearer, qmin=qmin, qmax=qmax)
787           
788            self.fitter.select_problem_for_fit(id=self.fit_id,
789                                               value=value.get_scheduled())
790            value.clear_model_param()
791        except:
792            raise
793            #msg = title + " error: %s" % sys.exc_value
794            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
795         
796    def _onSelect(self,event):
797        """
798        when Select data to fit a new page is created .Its reference is
799        added to self.page_finder
800        """
801        self.panel = event.GetEventObject()
802        Plugin.on_perspective(self, event=event)
803        for plottable in self.panel.graph.plottables:
804            if plottable.__class__.__name__ in ["Data1D", "Theory1D"]:
805                if plottable.name == self.panel.graph.selected_plottable:
806                    data = plottable
807                    self.add_fit_page(data=data)
808                    return
809            else:
810                data = plottable
811                self.add_fit_page(data=data)
812           
813    def _single_fit_completed(self,result, pars, elapsed=None):
814        """
815        Display fit result on one page of the notebook.
816       
817        :param result: result of fit
818        :param pars: list of names of parameters fitted
819        :param current_pg: the page where information will be displayed
820        :param qmin: the minimum value of x to replot the model
821        :param qmax: the maximum value of x to replot model
822         
823        """     
824        try:
825            if result ==None:
826                msg= "Simple Fitting Stop !!!"
827                wx.PostEvent(self.parent, StatusEvent(status=msg,info="warning",
828                                                      type="stop"))
829                return
830            if not numpy.isfinite(result.fitness) or \
831                    numpy.any(result.pvec == None) or \
832                    not numpy.all(numpy.isfinite(result.pvec)):
833                msg = "Single Fitting did not converge!!!"
834                wx.PostEvent(self.parent, 
835                             StatusEvent(status=msg, type="stop"))
836                return
837            page_id = None
838            for id, value in self.page_finder.iteritems():   
839                if value.get_scheduled()==1:
840                    model = value.get_model()
841                    page_id = id
842                    break
843            param_name = []
844            i = 0
845            for name in pars:
846                param_name.append(name)
847               
848            cpage = self.fit_panel.get_page_by_id(page_id)
849            cpage.onsetValues(result.fitness, 
850                              param_name, result.pvec,result.stderr)
851           
852        except:
853            msg = "Single Fit completed but Following"
854            msg += " error occurred:%s" % sys.exc_value
855            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
856                                                  type="stop"))
857            return
858       
859    def _simul_fit_completed(self, result, pars=None, elapsed=None):
860        """
861        Parameter estimation completed,
862        display the results to the user
863       
864        :param alpha: estimated best alpha
865        :param elapsed: computation time
866       
867        """
868        ## fit more than 1 model at the same time
869        try:
870            msg = "" 
871            if result ==None:
872                msg= "Complex Fitting Stop !!!"
873                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
874                return
875            if not numpy.isfinite(result.fitness) or numpy.any(result.pvec ==None )or not numpy.all(numpy.isfinite(result.pvec) ):
876                msg= "Simultaneous Fitting did not converge!!!"
877                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
878                return
879             
880            for id, value in self.page_finder.iteritems():   
881                if value.get_scheduled() == 1:
882                    model = value.get_model()
883                    data =  value.get_fit_data()
884                    small_param_name = []
885                    small_out = []
886                    small_cov = []
887                    i = 0
888                    #Separate result in to data corresponding to each page
889                    for p in result.parameters:
890                        model_name,param_name = self.split_string(p.name) 
891                        if model.name == model_name:
892                            p_name= model.name+"."+param_name
893                            if p.name == p_name:     
894                                if p.value != None and numpy.isfinite(p.value):
895                                    small_out.append(p.value )
896                                    small_param_name.append(param_name)
897                                    small_cov.append(p.stderr)
898
899                    # Display result on each page
900                    cpage = self.fit_panel.get_page_by_id(id)
901                    cpage.onsetValues(result.fitness,
902                                      small_param_name,
903                                      small_out,small_cov)
904        except:
905            raise
906            #msg= "Simultaneous Fit completed"
907            #msg +=" but Following error occurred:%s"%sys.exc_value
908            #wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
909            #return
910             
911    def _on_show_panel(self, event):
912        """
913        """
914        pass
915       
916    def _onset_engine_park(self,event):
917        """
918        set engine to park
919        """
920        self._on_change_engine('park')
921       
922    def _onset_engine_scipy(self,event):
923        """
924        set engine to scipy
925        """
926        self._on_change_engine('scipy')
927       
928    def _on_slicer_event(self, event):
929        """
930        Receive a panel as event and send it to guiframe
931       
932        :param event: event containing a panel
933       
934        """
935        if event.panel is not None:
936            new_panel = event.panel
937            self.slicer_panels.append(event.panel)
938            # Set group ID if available
939            event_id = self.parent.popup_panel(new_panel)
940            #self.menu3.Append(event_id, new_panel.window_caption,
941            #                 "Show %s plot panel" % new_panel.window_caption)
942            # Set id to allow us to reference the panel later
943         
944            new_panel.uid = event_id
945            self.mypanels.append(new_panel) 
946       
947    def _onclearslicer(self, event):
948        """
949        Clear the boxslicer when close the panel associate with this slicer
950        """
951        name =event.GetPane().caption
952   
953        for panel in self.slicer_panels:
954            if panel.window_caption==name:
955               
956                for item in self.parent.panels:
957                    if hasattr(self.parent.panels[item],"uid"):
958                        if self.parent.panels[item].uid ==panel.base.uid:
959                            self.parent.panels[item].onClearSlicer(event)
960                            self.parent._mgr.Update()
961                            break 
962                break
963   
964    def _return_engine_type(self):
965        """
966        return the current type of engine
967        """
968        return self._fit_engine
969     
970     
971    def _on_change_engine(self, engine='park'):
972        """
973        Allow to select the type of engine to perform fit
974       
975        :param engine: the key work of the engine
976       
977        """
978        ## saving fit engine name
979        self._fit_engine = engine
980        ## change menu item state
981        if engine=="park":
982            self.menu1.FindItemByPosition(0).Check(False)
983            self.menu1.FindItemByPosition(1).Check(True)
984        else:
985            self.menu1.FindItemByPosition(0).Check(True)
986            self.menu1.FindItemByPosition(1).Check(False)
987        ## post a message to status bar
988        msg = "Engine set to: %s" % self._fit_engine
989        wx.PostEvent(self.parent, 
990                     StatusEvent(status=msg))
991        ## Bind every open fit page with a newevent to
992        #know the current fitting engine
993        #import fitpage
994        event = fitpage.FitterTypeEvent()
995        event.type = self._fit_engine
996        wx.PostEvent(self.fit_panel, event)
997       
998    def _on_model_panel(self, evt):
999        """
1000        react to model selection on any combo box or model menu.plot the model 
1001       
1002        :param evt: wx.combobox event
1003       
1004        """
1005        model = evt.model
1006        id = evt.id
1007        qmin = evt.qmin
1008        qmax = evt.qmax
1009        smearer = evt.smearer
1010       
1011        if model == None:
1012            return
1013       
1014        if self.page_finder[id].get_model() is None:
1015            model.name = "M" + str(self.index_model)
1016            self.index_model += 1 
1017        else:
1018            model.name = self.page_finder[id].get_model().name
1019        # save the name containing the data name with the appropriate model
1020        self.page_finder[id].set_model(model)
1021        self.page_finder[id].set_range(qmin=qmin, qmax=qmax)
1022        if self.sim_page is not None:
1023            self.sim_page.draw_page()
1024       
1025    def _update1D(self,x, output):
1026        """
1027        Update the output of plotting model 1D
1028        """
1029        msg = "Plot updating ... "
1030        wx.PostEvent(self.parent, StatusEvent(status=msg,type="update"))
1031        self.ready_fit()
1032        #self.calc_thread.ready(0.01)
1033   
1034    def _fill_default_model2D(self, theory,id, qmax,qstep, qmin=None):
1035        """
1036        fill Data2D with default value
1037       
1038        :param theory: Data2D to fill
1039       
1040        """
1041        from DataLoader.data_info import Detector, Source
1042       
1043        detector = Detector()
1044        theory.detector.append(detector)         
1045        theory.source= Source()
1046       
1047        ## Default values   
1048        theory.detector[0].distance= 8000   # mm       
1049        theory.source.wavelength= 6         # A     
1050        theory.detector[0].pixel_size.x= 5  # mm
1051        theory.detector[0].pixel_size.y= 5  # mm
1052       
1053        theory.detector[0].beam_center.x= qmax
1054        theory.detector[0].beam_center.y= qmax
1055   
1056        ## create x_bins and y_bins of the model 2D
1057        pixel_width_x = theory.detector[0].pixel_size.x
1058        pixel_width_y = theory.detector[0].pixel_size.y
1059        center_x      = theory.detector[0].beam_center.x/pixel_width_x
1060        center_y      = theory.detector[0].beam_center.y/pixel_width_y
1061
1062        # theory default: assume the beam
1063        #center is located at the center of sqr detector
1064        xmax = qmax
1065        xmin = -qmax
1066        ymax = qmax
1067        ymin = -qmax
1068       
1069        x=  numpy.linspace(start= -1*qmax,
1070                               stop=qmax,
1071                               num=qstep,
1072                               endpoint=True) 
1073        y = numpy.linspace(start=-1*qmax,
1074                               stop= qmax,
1075                               num= qstep,
1076                               endpoint=True)
1077         
1078        ## use data info instead
1079        new_x = numpy.tile(x, (len(y),1))
1080        new_y = numpy.tile(y, (len(x),1))
1081        new_y = new_y.swapaxes(0,1)
1082       
1083        # all data reuire now in 1d array
1084        qx_data = new_x.flatten()
1085        qy_data = new_y.flatten()
1086       
1087        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data)
1088        # set all True (standing for unmasked) as default
1089        mask    = numpy.ones(len(qx_data), dtype = bool)
1090       
1091        # calculate the range of qx and qy: this way,
1092        # it is a little more independent
1093        x_size = xmax- xmin
1094        y_size = ymax -ymin
1095       
1096        # store x and y bin centers in q space
1097        x_bins  = x
1098        y_bins  = y
1099        # bin size: x- & y-directions
1100        xstep = x_size/len(x_bins-1)
1101        ystep = y_size/len(y_bins-1)
1102       
1103        #theory.data = numpy.zeros(len(mask))
1104        theory.err_data = numpy.ones(len(mask))
1105        theory.qx_data = qx_data
1106        theory.qy_data = qy_data 
1107        theory.q_data = q_data
1108        theory.mask = mask           
1109        theory.x_bins = x_bins 
1110        theory.y_bins = y_bins   
1111       
1112        # max and min taking account of the bin sizes
1113        theory.xmin = xmin
1114        theory.xmax = xmax
1115        theory.ymin = ymin
1116        theory.ymax = ymax
1117        theory.group_id = str(id) + " Model2D"
1118        theory.id = str(id) + " Model2D"
1119 
1120    def _complete1D(self, x,y, id, elapsed,index,model,
1121                    toggle_mode_on=False,state=None, data=None):
1122        """
1123        Complete plotting 1D data
1124        """ 
1125        try:
1126            new_plot = Data1D(x=x, y=y)
1127            new_plot.is_data = False
1128            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
1129            if data != None:
1130                _xaxis, _xunit = data.get_xaxis() 
1131                _yaxis, _yunit = data.get_yaxis() 
1132                new_plot.title = data.name
1133                #if the theory is already plotted use the same group id
1134                #to replot
1135                if id in self.page_finder:
1136                    theory_data = self.page_finder[id].get_theory_data()
1137                    if theory_data is not None:
1138                       data.group_id = theory_data.group_id
1139                #data is plotted before the theory, then take its group_id
1140                #assign to the new theory
1141                new_plot.group_id = data.group_id
1142               
1143            else:
1144                _xaxis, _xunit = "\\rm{Q}", 'A^{-1}'
1145                _yaxis, _yunit = "\\rm{Intensity} ", "cm^{-1}"
1146                new_plot.title = "Analytical model 1D "
1147                #find a group id to plot theory without data
1148                new_plot.group_id =  str(id) + " Model1D" 
1149            new_plot.id =  str(id) + " Model1D" 
1150           
1151            #find if this theory was already plotted and replace that plot given
1152            #the same id
1153            if id in self.page_finder:
1154                theory_data = self.page_finder[id].get_theory_data()
1155                if theory_data is not None:
1156                    new_plot.id = theory_data.id
1157             
1158            new_plot.name = model.name + " ["+ str(model.__class__.__name__)+ "]"
1159            new_plot.xaxis(_xaxis, _xunit)
1160            new_plot.yaxis(_yaxis, _yunit)
1161            if toggle_mode_on:
1162                new_plot.id =  str(id) + " Model" 
1163                wx.PostEvent(self.parent, 
1164                             NewPlotEvent(group_id=str(id) + " Model2D",
1165                                               action="Hide"))
1166           
1167            self.page_finder[id].set_theory_data(new_plot)
1168            theory_data = self.page_finder[id].get_theory_data()
1169            if data is None:
1170                name = "Data generates by Fitting "
1171                theory_data.name = name
1172                self.parent.add_data_helper({theory_data.id:theory_data})
1173                data_id = theory_data.id
1174            else:
1175                data_id = data.id
1176           
1177            self.parent.update_theory(data_id=data_id, 
1178                                       theory=theory_data,
1179                                       state=state)     
1180            current_pg = self.fit_panel.get_page_by_id(id)
1181            title = new_plot.title
1182            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1183                                            title= str(title)))
1184           
1185            wx.PostEvent(current_pg,
1186                Chi2UpdateEvent(output=self._cal_chisqr(data=data,
1187                                                        id=id,
1188                                                        index=index)))
1189            msg = "Plot 1D  complete !"
1190            wx.PostEvent( self.parent, StatusEvent(status=msg, type="stop" ))
1191        except:
1192            raise
1193            #msg = " Error occurred when drawing %s Model 1D: " % new_plot.name
1194            #msg += " %s"  % sys.exc_value
1195            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1196   
1197    def _update2D(self, output,time=None):
1198        """
1199        Update the output of plotting model
1200        """
1201        wx.PostEvent(self.parent, StatusEvent(status="Plot \
1202        #updating ... ", type="update"))
1203        self.ready_fit()
1204        #self.calc_thread.ready(0.01)
1205   
1206    def _complete2D(self, image, data, model, id,  elapsed, index, qmin,
1207                     qmax, toggle_mode_on=False,state=None,qstep=DEFAULT_NPTS):
1208        """
1209        Complete get the result of modelthread and create model 2D
1210        that can be plot.
1211        """
1212        err_image = numpy.zeros(numpy.shape(image))
1213       
1214        new_plot= Data2D(image=image, err_image=err_image)
1215        new_plot.name = model.name
1216       
1217        if data is None:
1218            self._fill_default_model2D(theory=new_plot, 
1219                                       qmax=qmax, 
1220                                       id=id,
1221                                       qstep=qstep,
1222                                        qmin= qmin)
1223           
1224        else:
1225            new_plot.id = str(id) + " Model2D"
1226            new_plot.group_id = str(id) + " Model2D"
1227            new_plot.x_bins = data.x_bins
1228            new_plot.y_bins = data.y_bins
1229            new_plot.detector = data.detector
1230            new_plot.source = data.source
1231            new_plot.is_data = False 
1232            new_plot.qx_data = data.qx_data
1233            new_plot.qy_data = data.qy_data
1234            new_plot.q_data = data.q_data
1235            #numpy.zeros(len(data.err_data))#data.err_data
1236            new_plot.err_data = err_image
1237            new_plot.mask = data.mask
1238            ## plot boundaries
1239            new_plot.ymin = data.ymin
1240            new_plot.ymax = data.ymax
1241            new_plot.xmin = data.xmin
1242            new_plot.xmax = data.xmax
1243        new_plot.is_data = False
1244        new_plot.name = model.name + " ["+ str(model.__class__.__name__)+ "]"
1245        new_plot.title = "Analytical model 2D "
1246        theory_data = deepcopy(new_plot)
1247        theory_data.name = "Unknown"
1248        if toggle_mode_on:
1249            new_plot.id = str(id) + " Model"     
1250            wx.PostEvent(self.parent, 
1251                             NewPlotEvent(group_id=str(id) + " Model1D",
1252                                               action="Hide"))
1253       
1254        self.page_finder[id].set_theory_data(new_plot)
1255        theory_data = self.page_finder[id].get_theory_data()
1256        if data is None:
1257            name = "Data generates by Fitting "
1258            theory_data.name = name
1259            self.parent.add_data_helper({theory_data.id:theory_data})
1260            data_id = theory_data.id
1261        else:
1262            data_id = data.id
1263        self.parent.update_theory(data_id=data_id, 
1264                                       theory=theory_data,
1265                                       state=state) 
1266        current_pg = self.fit_panel.get_page_by_id(id)
1267        title = new_plot.title
1268        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1269                                               title=title))
1270        # Chisqr in fitpage
1271        wx.PostEvent(current_pg,
1272            Chi2UpdateEvent(output=self._cal_chisqr(data=data, id=id, index=index)))
1273        msg = "Plot 2D complete !"
1274        wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1275   
1276    def _draw_model2D(self, model, id, data=None, smearer=None,
1277                      description=None, enable2D=False,
1278                      state=None,
1279                      toggle_mode_on=False,
1280                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX,
1281                       qstep=DEFAULT_NPTS):
1282        """
1283        draw model in 2D
1284       
1285        :param model: instance of the model to draw
1286        :param description: the description of the model
1287        :param enable2D: when True allows to draw model 2D
1288        :param qmin: the minimum value to  draw model 2D
1289        :param qmax: the maximum value to draw model 2D
1290        :param qstep: the number of division of Qx and Qy of the model to draw
1291           
1292        """
1293        x=  numpy.linspace(start=-1*qmax,
1294                               stop=qmax,
1295                               num=qstep,
1296                               endpoint=True) 
1297        y = numpy.linspace(start= -1*qmax,
1298                               stop=qmax,
1299                               num=qstep,
1300                               endpoint=True)
1301        if model is None:
1302            msg = "Panel with ID: %s does not contained model" % str(id)
1303            raise ValueError, msg
1304        ## use data info instead
1305        if data is not None:
1306            ## check if data2D to plot
1307            if hasattr(data, "x_bins"):
1308                enable2D = True
1309                x = data.x_bins
1310                y = data.y_bins
1311               
1312        if not enable2D:
1313            return None, None
1314        try:
1315            from model_thread import Calc2D
1316            ## If a thread is already started, stop it
1317            if (self.calc_2D is not None) and self.calc_2D.isrunning():
1318                self.calc_2D.stop()
1319
1320            self.calc_2D = Calc2D(x=x,
1321                                    y=y,
1322                                    model=model, 
1323                                    data=data,
1324                                    id=id,
1325                                    smearer=smearer,
1326                                    qmin=qmin,
1327                                    qmax=qmax,
1328                                    qstep=qstep,
1329                                    toggle_mode_on=toggle_mode_on,
1330                                    state=state,
1331                                    completefn=self._complete2D,
1332                                    updatefn=self._update2D)
1333            self.calc_2D.queue()
1334
1335        except:
1336            raise
1337            #msg = " Error occurred when drawing %s Model 2D: " % model.name
1338            #msg += " %s" % sys.exc_value
1339            #wx.PostEvent(self.parent, StatusEvent(status=msg))
1340
1341    def _draw_model1D(self, model, id, data=None, smearer=None,
1342                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, 
1343                state=None,
1344                toggle_mode_on=False,
1345                qstep=DEFAULT_NPTS, enable1D=True):
1346        """
1347        Draw model 1D from loaded data1D
1348       
1349        :param data: loaded data
1350        :param model: the model to plot
1351       
1352        """
1353        x=  numpy.linspace(start=qmin,
1354                           stop=qmax,
1355                           num=qstep,
1356                           endpoint=True
1357                           )
1358        if data is not None:
1359            ## check for data2D
1360            if hasattr(data,"x_bins"):
1361                return
1362            x = data.x
1363            if qmin == DEFAULT_QMIN :
1364                qmin = min(data.x)
1365            if qmax == DEFAULT_QMAX:
1366                qmax = max(data.x) 
1367        if not enable1D:
1368            return 
1369        try:
1370            from model_thread import Calc1D
1371            ## If a thread is already started, stop it
1372            if (self.calc_1D is not None) and self.calc_1D.isrunning():
1373                self.calc_1D.stop()
1374            self.calc_1D = Calc1D(x=x,
1375                                  data=data,
1376                                  model=model,
1377                                  id=id, 
1378                                  qmin=qmin,
1379                                  qmax=qmax,
1380                                  smearer=smearer,
1381                                  state=state,
1382                                  toggle_mode_on=toggle_mode_on,
1383                                  completefn=self._complete1D,
1384                                  updatefn=self._update1D)
1385            self.calc_1D.queue()
1386
1387        except:
1388            msg = " Error occurred when drawing %s Model 1D: " % model.name
1389            msg += " %s" % sys.exc_value
1390            wx.PostEvent(self.parent, StatusEvent(status=msg))
1391
1392    def _cal_chisqr(self, id, data=None, index=None): 
1393        """
1394        Get handy Chisqr using the output from draw1D and 2D,
1395        instead of calling expansive CalcChisqr in guithread
1396        """
1397        # default chisqr
1398        chisqr = None
1399       
1400        # return None if data == None
1401        if data == None: return chisqr
1402       
1403        # Get data: data I, theory I, and data dI in order
1404        if data.__class__.__name__ =="Data2D":
1405            if index == None: 
1406                index = numpy.ones(len(data.data),ntype=bool)
1407            # get rid of zero error points
1408            index = index & (data.err_data != 0) 
1409            fn = data.data[index] 
1410            theory_data = self.page_finder[id].get_theory_data()
1411            gn = theory_data.data[index]
1412            en = data.err_data[index]
1413        else:
1414            # 1 d theory from model_thread is only in the range of index
1415            if index == None:
1416                index = numpy.ones(len(data.y), ntype=bool)
1417            if data.dy == None or data.dy == []:
1418                dy = numpy.ones(len(data.y))
1419            else:
1420                ## Set consitently w/AbstractFitengine:
1421                # But this should be corrected later.
1422                dy = data.dy
1423                dy[dy==0] = 1 
1424            fn = data.y[index] 
1425            theory_data = self.page_finder[id].get_theory_data()
1426            gn = theory_data.y
1427            en = dy[index]
1428        # residual
1429        res = (fn - gn)/en
1430        # get chisqr only w/finite
1431        val = res[numpy.isfinite(res)]*res[numpy.isfinite(res)]
1432        chisqr = numpy.average(val)
1433        return chisqr
1434   
1435   
1436#def profile(fn, *args, **kw):
1437#    import cProfile, pstats, os
1438#    global call_result
1439#    def call():
1440#        global call_result
1441#        call_result = fn(*args, **kw)
1442#    cProfile.runctx('call()', dict(call=call), {}, 'profile.out')
1443#    stats = pstats.Stats('profile.out')
1444#    #stats.sort_stats('time')
1445#    stats.sort_stats('calls')
1446#    stats.print_stats()
1447#    os.unlink('profile.out')
1448#    return call_result
1449if __name__ == "__main__":
1450    i = Plugin()
1451   
1452   
1453   
1454   
Note: See TracBrowser for help on using the repository browser.