source: sasview/sansview/perspectives/fitting/fitting.py @ 14cd91b1

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

update plugin

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