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

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

work on toggle 1D \2D

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