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

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

working on guiframe

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