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

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

add load many data fitting

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