source: sasview/sansview/perspectives/fitting/fitting.py @ 3eb2811

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 3eb2811 was 3eb2811, checked in by Jae Cho <jhjcho@…>, 14 years ago

fixed minor bug when a file is saved without model selection: fit_panel

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