source: sasview/sansview/perspectives/fitting/fitpanel.py @ 240b9966

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

working on undo and redo

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