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

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

working on toogle 1D\2D

  • Property mode set to 100644
File size: 55.8 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   
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       
640        page = self.fit_panel.set_data(data)
641        page_caption = page.window_name
642        #append Data1D to the panel containing its theory
643        #if theory already plotted
644       
645        if page.id in self.page_finder:
646            theory_data = self.page_finder[page.id].get_theory_data()
647           
648            if issubclass(data.__class__, Data2D):
649                data.group_id.append(wx.NewId())
650                if theory_data is not None:
651                    group_id = str(page.id) + " Model1D"
652                    if group_id in theory_data.group_id:
653                        theory_data.group_id.remove(group_id)
654                    wx.PostEvent(self.parent, 
655                             NewPlotEvent(group_id=group_id,
656                                               action="delete"))
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           
669            self.parent.update_data(prev_data=theory_data, new_data=data)       
670        self.store_data(id=page.id, data=data, caption=page.window_name)
671        if self.sim_page is not None:
672            self.sim_page.draw_page()
673           
674    def _onEVT_SLICER_PANEL(self, event):
675        """
676        receive and event telling to update a panel with a name starting with
677        event.panel_name. this method update slicer panel for a given interactor.
678       
679        :param event: contains type of slicer , paramaters for updating the panel
680            and panel_name to find the slicer 's panel concerned.
681        """
682        for item in self.parent.panels:
683            if self.parent.panels[item].window_caption.startswith(event.panel_name):
684                self.parent.panels[item].set_slicer(event.type, event.params)
685               
686        self.parent._mgr.Update()
687   
688    def _closed_fitpage(self, event):   
689        """
690        request fitpanel to close a given page when its unique data is removed
691        from the plot. close fitpage only when the a loaded data is removed
692        """   
693        if event is None or event.data is None:
694            return
695       
696        if hasattr(event.data,"is_data"):
697            if not event.data.is_data or \
698                event.data.__class__.__name__=="Data1D":
699                self.fit_panel.close_page_with_data(event.data) 
700       
701    def _add_page_onmenu(self, name,fitproblem=None):
702        """
703        Add name of a closed page of fitpanel in a menu
704        """
705        list = self.menu1.GetMenuItems()
706        for item in list:
707            if name == item.GetItemLabel():
708                self.closed_page_dict[name][1] = fitproblem
709               
710        if not name in self.closed_page_dict.keys():   
711            # Post paramters
712            event_id = wx.NewId()
713            self.menu1.Append(event_id, name, "Show %s fit panel" % name)
714            self.closed_page_dict[name]= [event_id, fitproblem]
715            wx.EVT_MENU(self.parent,event_id,  self._open_closed_page)
716       
717    def _open_closed_page(self, event):   
718        """
719        reopen a closed page
720        """
721        for name, value in self.closed_page_dict.iteritems():
722            if event.GetId() in value:
723                id,fitproblem = value
724                if name !="Model":
725                    data= fitproblem.get_fit_data()
726                    page = self.fit_panel.add_fit_page(data= data,reset=True)
727                    if fitproblem != None:
728                        self.page_finder[id] = fitproblem
729                        if self.sim_page != None:
730                            self.sim_page.draw_page()
731                           
732                else:
733                    model = fitproblem
734                    self.fit_panel.add_model_page(model=model, topmenu=True,
735                                                  reset= True)
736                    break
737   
738    def _reset_schedule_problem(self, id, value=0):
739        """
740        unschedule or schedule all fitproblem to be fit
741        """
742        for page_id in self.page_finder.keys():
743            self.page_finder[id].schedule_tofit(value)
744           
745    def _fit_helper(self, pars, value, id, title="Single Fit " ):
746        """
747        helper for fitting
748        """
749        metadata = value.get_fit_data()
750        model = value.get_model()
751        smearer = value.get_smearer()
752        qmin, qmax = value.get_range()
753        self.fit_id = id
754        #Create list of parameters for fitting used
755        templist = []
756       
757        try:
758            #Extra list of parameters and their constraints
759            listOfConstraint = []
760           
761            param = value.get_model_param()
762            if len(param) > 0:
763                for item in param:
764                    ## check if constraint
765                    if item[0] != None and item[1] != None:
766                        listOfConstraint.append((item[0],item[1]))
767                   
768            #Do the single fit
769            self.fitter.set_model(model, self.fit_id,
770                                   pars, constraints=listOfConstraint)
771           
772            self.fitter.set_data(data=metadata, id=self.fit_id,
773                                 smearer=smearer, qmin=qmin, qmax=qmax)
774           
775            self.fitter.select_problem_for_fit(id=self.fit_id,
776                                               value=value.get_scheduled())
777            value.clear_model_param()
778        except:
779            raise
780            #msg = title + " error: %s" % sys.exc_value
781            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
782         
783    def _onSelect(self,event):
784        """
785        when Select data to fit a new page is created .Its reference is
786        added to self.page_finder
787        """
788        self.panel = event.GetEventObject()
789        Plugin.on_perspective(self, event=event)
790        for plottable in self.panel.graph.plottables:
791            if plottable.__class__.__name__ in ["Data1D", "Theory1D"]:
792                if plottable.name == self.panel.graph.selected_plottable:
793                    data = plottable
794                    self.add_fit_page(data=data)
795                    return
796            else:
797                data = plottable
798                self.add_fit_page(data=data)
799           
800    def _single_fit_completed(self,result, pars, elapsed=None):
801        """
802        Display fit result on one page of the notebook.
803       
804        :param result: result of fit
805        :param pars: list of names of parameters fitted
806        :param current_pg: the page where information will be displayed
807        :param qmin: the minimum value of x to replot the model
808        :param qmax: the maximum value of x to replot model
809         
810        """     
811        try:
812            if result ==None:
813                msg= "Simple Fitting Stop !!!"
814                wx.PostEvent(self.parent, StatusEvent(status=msg,info="warning",
815                                                      type="stop"))
816                return
817            if not numpy.isfinite(result.fitness) or \
818                    numpy.any(result.pvec == None) or \
819                    not numpy.all(numpy.isfinite(result.pvec)):
820                msg = "Single Fitting did not converge!!!"
821                wx.PostEvent(self.parent, 
822                             StatusEvent(status=msg, type="stop"))
823                return
824            page_id = None
825            for id, value in self.page_finder.iteritems():   
826                if value.get_scheduled()==1:
827                    model = value.get_model()
828                    page_id = id
829                    break
830            param_name = []
831            i = 0
832            for name in pars:
833                param_name.append(name)
834               
835            cpage = self.fit_panel.get_page_by_id(page_id)
836            cpage.onsetValues(result.fitness, 
837                              param_name, result.pvec,result.stderr)
838           
839        except:
840            msg = "Single Fit completed but Following"
841            msg += " error occurred:%s" % sys.exc_value
842            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
843                                                  type="stop"))
844            return
845       
846    def _simul_fit_completed(self, result, pars=None, elapsed=None):
847        """
848        Parameter estimation completed,
849        display the results to the user
850       
851        :param alpha: estimated best alpha
852        :param elapsed: computation time
853       
854        """
855        ## fit more than 1 model at the same time
856        try:
857            msg = "" 
858            if result ==None:
859                msg= "Complex Fitting Stop !!!"
860                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
861                return
862            if not numpy.isfinite(result.fitness) or numpy.any(result.pvec ==None )or not numpy.all(numpy.isfinite(result.pvec) ):
863                msg= "Simultaneous Fitting did not converge!!!"
864                wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
865                return
866             
867            for id, value in self.page_finder.iteritems():   
868                if value.get_scheduled() == 1:
869                    model = value.get_model()
870                    data =  value.get_fit_data()
871                    small_param_name = []
872                    small_out = []
873                    small_cov = []
874                    i = 0
875                    #Separate result in to data corresponding to each page
876                    for p in result.parameters:
877                        model_name,param_name = self.split_string(p.name) 
878                        if model.name == model_name:
879                            p_name= model.name+"."+param_name
880                            if p.name == p_name:     
881                                if p.value != None and numpy.isfinite(p.value):
882                                    small_out.append(p.value )
883                                    small_param_name.append(param_name)
884                                    small_cov.append(p.stderr)
885
886                    # Display result on each page
887                    cpage = self.fit_panel.get_page_by_id(id)
888                    cpage.onsetValues(result.fitness,
889                                      small_param_name,
890                                      small_out,small_cov)
891        except:
892            raise
893            #msg= "Simultaneous Fit completed"
894            #msg +=" but Following error occurred:%s"%sys.exc_value
895            #wx.PostEvent(self.parent, StatusEvent(status=msg,type="stop"))
896            #return
897             
898    def _on_show_panel(self, event):
899        """
900        """
901        pass
902       
903    def _onset_engine_park(self,event):
904        """
905        set engine to park
906        """
907        self._on_change_engine('park')
908       
909    def _onset_engine_scipy(self,event):
910        """
911        set engine to scipy
912        """
913        self._on_change_engine('scipy')
914       
915    def _on_slicer_event(self, event):
916        """
917        Receive a panel as event and send it to guiframe
918       
919        :param event: event containing a panel
920       
921        """
922        if event.panel is not None:
923            new_panel = event.panel
924            self.slicer_panels.append(event.panel)
925            # Set group ID if available
926            event_id = self.parent.popup_panel(new_panel)
927            #self.menu3.Append(event_id, new_panel.window_caption,
928            #                 "Show %s plot panel" % new_panel.window_caption)
929            # Set id to allow us to reference the panel later
930         
931            new_panel.uid = event_id
932            self.mypanels.append(new_panel) 
933       
934    def _onclearslicer(self, event):
935        """
936        Clear the boxslicer when close the panel associate with this slicer
937        """
938        name =event.GetPane().caption
939   
940        for panel in self.slicer_panels:
941            if panel.window_caption==name:
942               
943                for item in self.parent.panels:
944                    if hasattr(self.parent.panels[item],"uid"):
945                        if self.parent.panels[item].uid ==panel.base.uid:
946                            self.parent.panels[item].onClearSlicer(event)
947                            self.parent._mgr.Update()
948                            break 
949                break
950   
951    def _return_engine_type(self):
952        """
953        return the current type of engine
954        """
955        return self._fit_engine
956     
957     
958    def _on_change_engine(self, engine='park'):
959        """
960        Allow to select the type of engine to perform fit
961       
962        :param engine: the key work of the engine
963       
964        """
965        ## saving fit engine name
966        self._fit_engine = engine
967        ## change menu item state
968        if engine=="park":
969            self.menu1.FindItemByPosition(0).Check(False)
970            self.menu1.FindItemByPosition(1).Check(True)
971        else:
972            self.menu1.FindItemByPosition(0).Check(True)
973            self.menu1.FindItemByPosition(1).Check(False)
974        ## post a message to status bar
975        msg = "Engine set to: %s" % self._fit_engine
976        wx.PostEvent(self.parent, 
977                     StatusEvent(status=msg))
978        ## Bind every open fit page with a newevent to
979        #know the current fitting engine
980        #import fitpage
981        event = fitpage.FitterTypeEvent()
982        event.type = self._fit_engine
983        wx.PostEvent(self.fit_panel, event)
984       
985    def _on_model_panel(self, evt):
986        """
987        react to model selection on any combo box or model menu.plot the model 
988       
989        :param evt: wx.combobox event
990       
991        """
992        model = evt.model
993        id = evt.id
994        qmin = evt.qmin
995        qmax = evt.qmax
996        smearer = evt.smearer
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           
1173            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1174                                            title= str(new_plot.title)))
1175            current_pg = self.fit_panel.get_page_by_id(id)
1176            wx.PostEvent(current_pg,
1177                Chi2UpdateEvent(output=self._cal_chisqr(data=data,
1178                                                        id=id,
1179                                                        index=index)))
1180            msg = "Plot 1D  complete !"
1181            wx.PostEvent( self.parent, StatusEvent(status=msg, type="stop" ))
1182        except:
1183            raise
1184            #msg = " Error occurred when drawing %s Model 1D: " % new_plot.name
1185            #msg += " %s"  % sys.exc_value
1186            #wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1187   
1188    def _update2D(self, output,time=None):
1189        """
1190        Update the output of plotting model
1191        """
1192        wx.PostEvent(self.parent, StatusEvent(status="Plot \
1193        #updating ... ", type="update"))
1194        self.ready_fit()
1195        #self.calc_thread.ready(0.01)
1196   
1197    def _complete2D(self, image, data, model, id,  elapsed, index, qmin,
1198                     qmax, toggle_mode_on=False,state=None,qstep=DEFAULT_NPTS):
1199        """
1200        Complete get the result of modelthread and create model 2D
1201        that can be plot.
1202        """
1203        err_image = numpy.zeros(numpy.shape(image))
1204       
1205        new_plot= Data2D(image=image, err_image=err_image)
1206        new_plot.name = model.name
1207       
1208        if data is None:
1209            self._fill_default_model2D(theory=new_plot, 
1210                                       qmax=qmax, 
1211                                       id=id,
1212                                       qstep=qstep,
1213                                        qmin= qmin)
1214           
1215        else:
1216            new_plot.id = str(id) + " Model2D"
1217            group_id = str(id) + " Model2D"
1218            if group_id not in new_plot.group_id:
1219                new_plot.group_id.append(group_id)
1220         
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        self.page_finder[id].set_theory_data(theory_data)
1247       
1248        if data is None:
1249            theory_data = self.page_finder[id].get_theory_data()
1250            self.parent.add_data_helper(data_list=[theory_data])
1251            data_id = theory_data.id
1252        else:
1253            data_id = data.id
1254       
1255        self.parent.append_theory(data_id=data_id, 
1256                                          theory=new_plot, state=state)
1257        ## plot
1258        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
1259                                               title=new_plot.title))
1260        # Chisqr in fitpage
1261        current_pg = self.fit_panel.get_page_by_id(id)
1262        wx.PostEvent(current_pg,
1263            Chi2UpdateEvent(output=self._cal_chisqr(data=data, id=id, index=index)))
1264        msg = "Plot 2D complete !"
1265        wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop"))
1266   
1267    def _draw_model2D(self, model, id, data=None, smearer=None,
1268                      description=None, enable2D=False,
1269                      state=None,
1270                      toggle_mode_on=False,
1271                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX,
1272                       qstep=DEFAULT_NPTS):
1273        """
1274        draw model in 2D
1275       
1276        :param model: instance of the model to draw
1277        :param description: the description of the model
1278        :param enable2D: when True allows to draw model 2D
1279        :param qmin: the minimum value to  draw model 2D
1280        :param qmax: the maximum value to draw model 2D
1281        :param qstep: the number of division of Qx and Qy of the model to draw
1282           
1283        """
1284        x=  numpy.linspace(start=-1*qmax,
1285                               stop=qmax,
1286                               num=qstep,
1287                               endpoint=True) 
1288        y = numpy.linspace(start= -1*qmax,
1289                               stop=qmax,
1290                               num=qstep,
1291                               endpoint=True)
1292        if model is None:
1293            msg = "Panel with ID: %s does not contained model" % str(id)
1294            raise ValueError, msg
1295        ## use data info instead
1296        if data is not None:
1297            ## check if data2D to plot
1298            if hasattr(data, "x_bins"):
1299                enable2D = True
1300                x = data.x_bins
1301                y = data.y_bins
1302               
1303        if not enable2D:
1304            return None, None
1305        try:
1306            from model_thread import Calc2D
1307            ## If a thread is already started, stop it
1308            if (self.calc_2D is not None) and self.calc_2D.isrunning():
1309                self.calc_2D.stop()
1310
1311            self.calc_2D = Calc2D(x=x,
1312                                    y=y,
1313                                    model=model, 
1314                                    data=data,
1315                                    id=id,
1316                                    smearer=smearer,
1317                                    qmin=qmin,
1318                                    qmax=qmax,
1319                                    qstep=qstep,
1320                                    toggle_mode_on=toggle_mode_on,
1321                                    state=state,
1322                                    completefn=self._complete2D,
1323                                    updatefn=self._update2D)
1324            self.calc_2D.queue()
1325
1326        except:
1327            raise
1328            #msg = " Error occurred when drawing %s Model 2D: " % model.name
1329            #msg += " %s" % sys.exc_value
1330            #wx.PostEvent(self.parent, StatusEvent(status=msg))
1331
1332    def _draw_model1D(self, model, id, data=None, smearer=None,
1333                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, 
1334                state=None,
1335                toggle_mode_on=False,
1336                qstep=DEFAULT_NPTS, enable1D=True):
1337        """
1338        Draw model 1D from loaded data1D
1339       
1340        :param data: loaded data
1341        :param model: the model to plot
1342       
1343        """
1344        x=  numpy.linspace(start=qmin,
1345                           stop=qmax,
1346                           num=qstep,
1347                           endpoint=True
1348                           )
1349        if data is not None:
1350            ## check for data2D
1351            if hasattr(data,"x_bins"):
1352                return
1353            x = data.x
1354            if qmin == DEFAULT_QMIN :
1355                qmin = min(data.x)
1356            if qmax == DEFAULT_QMAX:
1357                qmax = max(data.x) 
1358        if not enable1D:
1359            return 
1360        try:
1361            from model_thread import Calc1D
1362            ## If a thread is already started, stop it
1363            if (self.calc_1D is not None) and self.calc_1D.isrunning():
1364                self.calc_1D.stop()
1365            self.calc_1D = Calc1D(x=x,
1366                                  data=data,
1367                                  model=model,
1368                                  id=id, 
1369                                  qmin=qmin,
1370                                  qmax=qmax,
1371                                  smearer=smearer,
1372                                  state=state,
1373                                  toggle_mode_on=toggle_mode_on,
1374                                  completefn=self._complete1D,
1375                                  updatefn=self._update1D)
1376            self.calc_1D.queue()
1377
1378        except:
1379            msg = " Error occurred when drawing %s Model 1D: " % model.name
1380            msg += " %s" % sys.exc_value
1381            wx.PostEvent(self.parent, StatusEvent(status=msg))
1382
1383    def _cal_chisqr(self, id, data=None, index=None): 
1384        """
1385        Get handy Chisqr using the output from draw1D and 2D,
1386        instead of calling expansive CalcChisqr in guithread
1387        """
1388        # default chisqr
1389        chisqr = None
1390       
1391        # return None if data == None
1392        if data == None: return chisqr
1393       
1394        # Get data: data I, theory I, and data dI in order
1395        if data.__class__.__name__ =="Data2D":
1396            if index == None: 
1397                index = numpy.ones(len(data.data),ntype=bool)
1398            # get rid of zero error points
1399            index = index & (data.err_data != 0) 
1400            fn = data.data[index] 
1401            theory_data = self.page_finder[id].get_theory_data()
1402            gn = theory_data.data[index]
1403            en = data.err_data[index]
1404        else:
1405            # 1 d theory from model_thread is only in the range of index
1406            if index == None:
1407                index = numpy.ones(len(data.y), ntype=bool)
1408            if data.dy == None or data.dy == []:
1409                dy = numpy.ones(len(data.y))
1410            else:
1411                ## Set consitently w/AbstractFitengine:
1412                # But this should be corrected later.
1413                dy = data.dy
1414                dy[dy==0] = 1 
1415            fn = data.y[index] 
1416            theory_data = self.page_finder[id].get_theory_data()
1417            gn = theory_data.y
1418            en = dy[index]
1419        # residual
1420        res = (fn - gn)/en
1421        # get chisqr only w/finite
1422        val = res[numpy.isfinite(res)]*res[numpy.isfinite(res)]
1423        chisqr = numpy.average(val)
1424        return chisqr
1425   
1426   
1427#def profile(fn, *args, **kw):
1428#    import cProfile, pstats, os
1429#    global call_result
1430#    def call():
1431#        global call_result
1432#        call_result = fn(*args, **kw)
1433#    cProfile.runctx('call()', dict(call=call), {}, 'profile.out')
1434#    stats = pstats.Stats('profile.out')
1435#    #stats.sort_stats('time')
1436#    stats.sort_stats('calls')
1437#    stats.print_stats()
1438#    os.unlink('profile.out')
1439#    return call_result
1440if __name__ == "__main__":
1441    i = Plugin()
1442   
1443   
1444   
1445   
Note: See TracBrowser for help on using the repository browser.