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

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

working on 1D \2D toggle

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