source: sasview/sansview/perspectives/fitting/fitpanel.py @ afab469

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 afab469 was 3244cbe1, checked in by Gervaise Alina <gervyh@…>, 15 years ago

add media folder , reverse fit_panel for now

  • Property mode set to 100644
File size: 17.4 KB
RevLine 
[e2f1023]1
2import numpy
3import string 
[d89f09b]4import wx
[26bf293]5import wx.aui
[d89f09b]6import wx.lib
[3244cbe1]7from wx.aui import AuiNotebook
[330573d]8
9
[cfc0913]10import basepage
[00c3aac]11
[330573d]12_BOX_WIDTH = 80
13
14
15class StateIterator(object):
[1b69256]16    """
17        Contains all saved state of a given page.
18        Provide position of the current state of a page, the first save state
19        and the last state for a given page.
[330573d]20        Allow easy undo or redo for a given page 
[1b69256]21    """
[330573d]22    def __init__(self):
23        self._current=0
24       
25   
26    def __iter__(self):
27        return self
28   
29   
30    def first(self):
31        self._current =0
32        return self._current
33   
34    def next(self, max ):
35        if self._current < max:
36            self._current += 1
37        return self._current
38   
39    def previous(self):
40        if self._current > 0:
41            self._current = self._current -1
42        return self._current
43   
44    def currentPosition(self):
45        return self._current
46   
47    def setPosition(self, value):
48        if value >=0:
49            self._current = int(value)
50       
51       
52   
53 
54class ListOfState(list):     
55    def __init__(self, *args, **kw):
56        list.__init__(self, *args, **kw)
57        self.iterator = StateIterator()
58       
59    def appendItem(self, x):
60        self.append(x)
61        self.iterator.setPosition(value= len(self)-1)
62       
63    def removeItem(self, x):
64        self.iterator.previous()
65        self.remove(x)
66       
67    def getPreviousItem(self):
68        position = self.iterator.previous()
69       
70        if position < 0:
71            return None
72        else:
73            return self[position]
74       
75    def getNextItem(self):
[fe496eeb]76        position = self.iterator.next(max= len(self)-1)
[330573d]77        if position >= len(self):
78            return None
79        else:
80            return self[position]
81       
82    def getCurrentItem(self):
83        postion = self.iterator.currentPosition()
84        if postion >= 0 and position < len(self):
85            return self[postion]
86        else:
87            return None
88       
89    def getCurrentPosition(self):
90        return self.iterator.currentPosition()
91       
92
[1b69256]93       
94       
95       
[cfc0913]96class PageInfo(object):
97    """
98        this class contains the minimum numbers of data members
99        a fitpage or model page need to be initialized.
100    """
101    data = None
[ffa69b6]102    model =  None
103    manager = None
[cfc0913]104    event_owner= None
105    model_list_box = None
[ffa69b6]106    name = None
[330573d]107    ## Internal name for the AUI manager
[cfc0913]108    window_name = "Page"
109    ## Title to appear on top of the window
110    window_caption = "Page"
111   
112    def __init__(self, model=None,data=None, manager=None,
113                  event_owner=None,model_list_box=None , name=None):
114        """
115            Initialize data members
116        """
117        self.data = data
118        self.model= model
119        self.manager= manager
120        self.event_owner= event_owner
121        self.model_list_box = model_list_box
122        self.name=None
123        self.window_name = "Page"
124        self.window_caption = "Page"
125   
[3244cbe1]126class FitPanel(AuiNotebook):   
[925a30e]127
[d89f09b]128    """
129        FitPanel class contains fields allowing to fit  models and  data
130        @note: For Fit to be performed the user should check at least one parameter
131        on fit Panel window.
132       
133    """
134    ## Internal name for the AUI manager
135    window_name = "Fit panel"
136    ## Title to appear on top of the window
137    window_caption = "Fit Panel "
[2139c3f]138    CENTER_PANE = True
[7437880]139   
[d89f09b]140    def __init__(self, parent, *args, **kwargs):
[3244cbe1]141        AuiNotebook.__init__(self,parent,-1,
142                    style= wx.aui.AUI_NB_WINDOWLIST_BUTTON|
143                    wx.aui.AUI_NB_DEFAULT_STYLE|
144                    wx.CLIP_CHILDREN)
[848a2ef]145   
[d89f09b]146        self.manager=None
147        self.parent=parent
148        self.event_owner=None
[26bf293]149       
[3244cbe1]150        pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
151        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.onClosePage)
[51d47b5]152       
[d89f09b]153        #dictionary of miodel {model class name, model class}
154        self.model_list_box={}
[00c3aac]155        ##dictionary of page info
156        self.page_info_dict={}
[cfc0913]157        ## save the title of the last page tab added
158        self.fit_page_name={}
159        ## list of existing fit page
160        self.list_fitpage_name=[]
[6999659]161   
[f39511b]162        #model page info
[ffa69b6]163        self.model_page_number = None
[882a912]164        ## fit page number for model plot
[ffa69b6]165        self.fit_page1D_number = None
166        self.fit_page2D_number = None
167        self.model_page = None
168        self.sim_page = None
169        self.default_page = None
170        self.check_first_data = False
[cfc0913]171        ## get the state of a page
172        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate)
[330573d]173        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo)
[fe496eeb]174        self.Bind(basepage.EVT_NEXT_STATE, self._onRedo)
[9237df4]175       
176        #add default page
177        from hint_fitpage import HintFitPage
[2377cd4]178        self.hint_page = HintFitPage(self) 
179        self.AddPage(page=self.hint_page, caption="Hint")
[ffa69b6]180        #Add the first fit page
181        self.default_page = self.add_fit_page(data=None)
182       
[6bcdad1]183        # increment number for model name
184        self.count=0
[f39511b]185        #updating the panel
[26bf293]186        self.Update()
[d89f09b]187        self.Center()
[2a8fac1]188       
189       
[26bf293]190    def onClosePage(self, event):
[51d47b5]191        """
[925a30e]192             close page and remove all references to the closed page
[51d47b5]193        """
[d361b462]194        nbr_page = self.GetPageCount()
195        if nbr_page == 1:
196            event.Veto()
197            return 
[51d47b5]198        selected_page = self.GetPage(self.GetSelection())
[d361b462]199        #remove default page
200        if selected_page == self.default_page:
201            self.default_page = None
202            return 
[2377cd4]203        #remove hint page
204        if selected_page == self.hint_page:
205            return
[7c845cb]206        ## removing sim_page
[2377cd4]207        if selected_page == self.sim_page :
[7c845cb]208            self.manager.sim_page=None 
209            return
[9853ad0]210       
[7c845cb]211        ## closing other pages
212        state = selected_page.createMemento()
213        page_name = selected_page.window_name
214        page_finder = self.manager.get_page_finder() 
215        fitproblem = None
216        ## removing model page
217        if selected_page == self.model_page:
[09ef7d22]218            #fitproblem = selected_page.model.clone()
[7c845cb]219            self.model_page = None
[ff36f31]220            self.count =0
[7c845cb]221            ## page on menu
[09ef7d22]222            #self.manager._add_page_onmenu(page_name, fitproblem)
[7c845cb]223        else:
224            if selected_page in page_finder:
225       
[09ef7d22]226                #fitproblem= page_finder[selected_page].clone()
[882a912]227                if self.GetPageIndex(selected_page)==self.fit_page1D_number:
228                    self.fit_page1D_number=None
229                if self.GetPageIndex(selected_page)==self.fit_page2D_number:
230                    self.fit_page2D_number=None
[7c845cb]231                ## page on menu
[09ef7d22]232                #self.manager._add_page_onmenu(page_name, fitproblem)
[7c845cb]233                del page_finder[selected_page]
234            ##remove the check box link to the model name of this page (selected_page)
235            try:
[1d2782d]236                self.sim_page.draw_page()
[7c845cb]237            except:
238                ## that page is already deleted no need to remove check box on
239                ##non existing page
240                pass
[9853ad0]241               
[7c845cb]242        #Delete the name of the page into the list of open page
243        if selected_page.window_name in self.list_fitpage_name:
244            self.list_fitpage_name.remove(selected_page.window_name)
[a074145]245           
[d89f09b]246       
247    def set_manager(self, manager):
248        """
249             set panel manager
250             @param manager: instance of plugin fitting
251        """
252        self.manager = manager
[925a30e]253
[d89f09b]254       
255    def set_owner(self,owner):
256        """
257            set and owner for fitpanel
258            @param owner: the class responsible of plotting
259        """
[c77d859]260        self.event_owner = owner
261   
[ffa69b6]262    def set_model_list(self, dict):
[c77d859]263         """
264             copy a dictionary of model into its own dictionary
265             @param dict: dictionnary made of model name as key and model class
266             as value
267         """
268         self.model_list_box = dict
[51d47b5]269       
[c77d859]270 
271    def get_current_page(self):
272        """
273            @return the current page selected
274        """
275        return self.GetPage(self.GetSelection() )
276   
[51d47b5]277    def add_sim_page(self):
[925a30e]278        """
279            Add the simultaneous fit page
280        """
[51d47b5]281        from simfitpage import SimultaneousFitPage
[b28717b]282        page_finder= self.manager.get_page_finder()
283        self.sim_page = SimultaneousFitPage(self,page_finder=page_finder, id=-1)
284       
[51d47b5]285        self.AddPage(self.sim_page,caption="Simultaneous Fit",select=True)
286        self.sim_page.set_manager(self.manager)
287        return self.sim_page
[d89f09b]288       
[ffa69b6]289       
290    def add_fit_page( self,data=None, reset=False ):
[d89f09b]291        """
292            Add a fitting page on the notebook contained by fitpanel
[925a30e]293            @param data: data to fit
[b787e68c]294            @return panel : page just added for further used. is used by fitting module
[ffa69b6]295        """   
296        if data is not None:
297            if data.is_data:
298                name = data.name
[882a912]299            else:
[ffa69b6]300                if data.__class__.__name__=="Data2D":
301                    name = 'Model 2D Fit'
302                else:
303                    name = 'Model 1D Fit'
[cfc0913]304            myinfo = PageInfo( data=data, name=name )
[dcf29d7]305            myinfo.model_list_box = self.model_list_box.get_list()
306            myinfo.event_owner = self.event_owner
307            myinfo.manager = self.manager
[b787e68c]308            myinfo.window_name = name
309            myinfo.window_caption = name
[6e659ae8]310       
[ffa69b6]311        else :
312            name = "Fit Page" 
313            myinfo = PageInfo( data=data, name=name )
314       
315        if not name in self.list_fitpage_name:
316            # the first data loading
317            if not self.check_first_data and self.default_page is not None:
318                page_number = self.GetPageIndex(self.default_page)
319                self.SetPageText(page_number , name)
320                self.default_page.set_data(data)
321                self.default_page.set_page_info(page_info=myinfo)
322                self.default_page.initialize_combox()
323                if  data is not None:
324                    self.check_first_data = True
325                panel = self.default_page
[cfc0913]326            else:
[ffa69b6]327                #if not name in self.fit_page_name :
328                from fitpage import FitPage
329                panel = FitPage(parent=self, page_info=myinfo)
[240b9966]330               
[ffa69b6]331                self.AddPage(page=panel, caption=name, select=True)
332                if name == 'Model 1D Fit':
333                    self.fit_page1D_number= self.GetPageIndex(panel)
334                if name =='Model 2D Fit':
335                    self.fit_page2D_number= self.GetPageIndex(panel)
336                   
337                self.list_fitpage_name.append(name)
338                if data is not None:
339                    if reset:
340                        if name in self.fit_page_name.keys():
341                            memento= self.fit_page_name[name][0]
342                            panel.reset_page(memento)
343                        else:
344                            self.fit_page_name[name]=ListOfState()
345                   
346                    #self.fit_page_name[name].appendItem(panel.createMemento())
[882a912]347            #GetPage(self, page_idx)
[925a30e]348            return panel
[882a912]349        elif name =='Model 1D Fit':
350            if self.fit_page1D_number!=None:
351                panel =self.GetPage(self.fit_page1D_number) 
[330573d]352                #self.fit_page_name[name]=[]
353                self.fit_page_name[name]= ListOfState()
354                #self.fit_page_name[name].insert(0,panel.createMemento())
355                #self.fit_page_name[name].append(panel.createMemento())
[882a912]356                return panel
357            return None
358        elif name =='Model 2D Fit':
359            if self.fit_page2D_number!=None:
360                panel =self.GetPage(self.fit_page2D_number) 
[330573d]361                self.fit_page_name[name]=ListOfState()
362                #self.fit_page_name[name].append(panel.createMemento())
[882a912]363                return panel
364            return None
365        return None
[1c66bc5]366       
[9853ad0]367   
[cd793b9]368    def add_model_page(self,model,page_title="Model", qmin=0.0001, qmax=0.13,
[b787e68c]369                        npts=50, topmenu=False, reset=False):
[9853ad0]370        """
371            Add a model page only one  to display any model selected from the menu or the page combo box.
372            when this page is closed than the user will be able to open a new one
373           
374            @param model: the model for which paramters will be changed
375            @param page_title: the name of the page
[dcf29d7]376            @param page_info: contains info about the state of the page
[9853ad0]377            @param qmin: mimimum Q
378            @param qmax: maximum Q
379            @param npts: number of Q points
380        """
381        if topmenu==True:
[ff36f31]382            ##first time to open model page
383            if self.count==0 :
384                #if not page_title in self.list_fitpage_name :
[6999659]385                self._help_add_model_page(model=model, page_title=page_title,
[b787e68c]386                                qmin=qmin, qmax=qmax, npts=npts, reset=reset)
[ff36f31]387                self.count +=1
[9853ad0]388            else:
[fbf4bf8]389                self.model_page.select_model(model)
[3595309d]390                self.fit_page_name[page_title]=ListOfState()
[240b9966]391                #self.fit_page_name[page_title].insert(0,self.model_page.createMemento())
[b787e68c]392     
[848a2ef]393     
394     
395    def _close_fitpage(self,data):
396        """
397            close a fit page when its data is completely remove from the graph
398        """
399        name = data.name
400        for index in range(self.GetPageCount()):
401            if self.GetPageText(index)== name:
402                selected_page = self.GetPage(index) 
403   
404                if index ==self.fit_page1D_number:
405                    self.fit_page1D_number=None
406                if index ==self.fit_page2D_number:
407                    self.fit_page2D_number=None
408                if selected_page in self.manager.page_finder:
409                    del self.manager.page_finder[selected_page]
410                ##remove the check box link to the model name of this page (selected_page)
411                try:
412                    self.sim_page.draw_page()
413                except:
414                    ## that page is already deleted no need to remove check box on
415                    ##non existing page
416                    pass
417               
418                #Delete the name of the page into the list of open page
419                if selected_page.window_name in self.list_fitpage_name:
420                    self.list_fitpage_name.remove(selected_page.window_name)
421                self.DeletePage(index)
422                break
423       
424       
[cfc0913]425    def  _onGetstate(self, event):
426        """
427            copy the state of a page
428        """
429        page= event.page
[b787e68c]430        if page.window_name in self.fit_page_name:
[330573d]431            self.fit_page_name[page.window_name].appendItem(page.createMemento()) 
[cfc0913]432           
[330573d]433    def _onUndo(self, event ):
434        """
435            return the previous state of a given page is available
436        """
437        page = event.page
438        if page.window_name in self.fit_page_name:
439            if self.fit_page_name[page.window_name].getCurrentPosition()==0:
440                state = None
441            else:
442                state = self.fit_page_name[page.window_name].getPreviousItem()
[fe496eeb]443                page._redo.Enable(True)
[330573d]444            page.reset_page(state)
[fe496eeb]445       
446    def _onRedo(self, event ): 
447        """
448            return the next state available
449        """       
450        page = event.page
451        if page.window_name in self.fit_page_name:
452            length= len(self.fit_page_name[page.window_name])
453            if self.fit_page_name[page.window_name].getCurrentPosition()== length -1:
454                state = None
455                page._redo.Enable(False)
[3b9e023]456                page._redo.Enable(True)
[fe496eeb]457            else:
458                state = self.fit_page_name[page.window_name].getNextItem()
459            page.reset_page(state) 
[dcf29d7]460               
[cd793b9]461    def _help_add_model_page(self,model,page_title="Model", qmin=0.0001, 
462                             qmax=0.13, npts=50,reset= False):
[3f1af74]463        """
464            #TODO: fill in description
465           
466            @param qmin: mimimum Q
467            @param qmax: maximum Q
468            @param npts: number of Q points
469        """
[dcf29d7]470        ## creating object that contaning info about model
[b787e68c]471        myinfo = PageInfo(model= model ,name= page_title)
472        myinfo.model_list_box = self.model_list_box.get_list()
473        myinfo.event_owner = self.event_owner
474        myinfo.manager = self.manager
475        myinfo.window_name = page_title
476        myinfo.window_caption = page_title
477     
[c77d859]478        from modelpage import ModelPage
[cfc0913]479        panel = ModelPage(self,myinfo)
[b787e68c]480       
[848a2ef]481        self.AddPage(page=panel, caption=page_title, select=True)
[77e23a2]482
[bb18ef1]483        self.model_page_number=self.GetSelection()
484        self.model_page=self.GetPage(self.GetSelection())
[0aeabc6]485     
[3595309d]486        ##resetting page
[b787e68c]487        if reset:
488            if page_title in self.fit_page_name.keys():
[848a2ef]489
[b787e68c]490                memento= self.fit_page_name[page_title][0]
491                panel.reset_page(memento)
492        else:
[240b9966]493            self.fit_page_name[page_title]=ListOfState()
494            #self.fit_page_name[page_title]=[]
[3595309d]495            #self.fit_page_name[page_title].insert(0,panel.createMemento())
[0aeabc6]496       
[b787e68c]497 
Note: See TracBrowser for help on using the repository browser.