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

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

bindind save button with guiframe toolbar

  • Property mode set to 100644
File size: 19.0 KB
Line 
1
2import numpy
3import string 
4import wx
5import wx.aui
6
7from sans.guiframe.panel_base import PanelBase
8from sans.guiframe.events import PanelOnFocusEvent
9import basepage
10
11_BOX_WIDTH = 80
12
13
14class StateIterator(object):
15    """
16    Contains all saved state of a given page.
17    Provide position of the current state of a page, the first save state
18    and the last state for a given page.
19    Allow easy undo or redo for a given page 
20    """
21    def __init__(self):
22        """
23        """
24        self._current=0
25       
26    def __iter__(self):
27        """
28        """
29        return self
30   
31    def first(self):
32        """
33        """
34        self._current =0
35        return self._current
36   
37    def next(self, max ):
38        """
39        """
40        if self._current < max:
41            self._current += 1
42        return self._current
43   
44    def previous(self):
45        """
46        """
47        if self._current > 0:
48            self._current = self._current -1
49        return self._current
50   
51    def currentPosition(self):
52        """
53        """
54        return self._current
55   
56    def setPosition(self, value):
57        """
58        """
59        if value >=0:
60            self._current = int(value)
61       
62   
63class ListOfState(list):   
64    """
65    """ 
66    def __init__(self, *args, **kw):
67        list.__init__(self, *args, **kw)
68        self.iterator = StateIterator()
69       
70    def appendItem(self, x):
71        """
72        """
73        self.append(x)
74        self.iterator.setPosition(value= len(self)-1)
75       
76    def removeItem(self, x):
77        """
78        """
79        self.iterator.previous()
80        self.remove(x)
81       
82    def getPreviousItem(self):
83        """
84        """
85        position = self.iterator.previous()
86       
87        if position < 0:
88            return None
89        else:
90            return self[position]
91       
92    def getNextItem(self):
93        """
94        """
95        position = self.iterator.next(max= len(self)-1)
96        if position >= len(self):
97            return None
98        else:
99            return self[position]
100       
101    def getCurrentItem(self):
102        """
103        """
104        postion = self.iterator.currentPosition()
105        if postion >= 0 and position < len(self):
106            return self[postion]
107        else:
108            return None
109       
110    def getCurrentPosition(self):
111        """
112        """
113        return self.iterator.currentPosition()
114         
115
116class PageInfo(object):
117    """
118    this class contains the minimum numbers of data members
119    a fitpage or model page need to be initialized.
120    """
121    data = None
122    model =  None
123    manager = None
124    event_owner= None
125    model_list_box = None
126    name = None
127    ## Internal name for the AUI manager
128    window_name = "Page"
129    ## Title to appear on top of the window
130    window_caption = "Page"
131    #type of page can be real data , theory 1D or therory2D
132    type = "Data"
133    def __init__(self, model=None, data=None, manager=None,
134                  event_owner=None, model_list_box=None, name=None):
135        """
136        Initialize data members
137        """
138        self.data = data
139        self.model= model
140        self._manager= manager
141        self.event_owner= event_owner
142        self.model_list_box = model_list_box
143        self.name=None
144        self.window_name = "Page"
145        self.window_caption = "Page"
146        self.type = "Data"
147       
148class FitPanel(wx.aui.AuiNotebook, PanelBase):   
149
150    """
151    FitPanel class contains fields allowing to fit  models and  data
152   
153    :note: For Fit to be performed the user should check at least one parameter
154        on fit Panel window.
155       
156    """
157    ## Internal name for the AUI manager
158    window_name = "Fit panel"
159    ## Title to appear on top of the window
160    window_caption = "Fit Panel "
161    CENTER_PANE = True
162   
163    def __init__(self, parent, *args, **kwargs):
164        """
165        """
166        wx.aui.AuiNotebook.__init__(self, parent, -1,
167                    style= wx.aui.AUI_NB_WINDOWLIST_BUTTON|
168                    wx.aui.AUI_NB_DEFAULT_STYLE|
169                    wx.CLIP_CHILDREN)
170        PanelBase.__init__(self, parent)
171   
172        self._manager = None
173        self.parent = parent
174        self.event_owner = None
175       
176        pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
177        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_close_page)
178       
179        #dictionary of miodel {model class name, model class}
180        self.model_list_box = {}
181        ## save the title of the last page tab added
182        self.fit_page_name = {}
183        ## list of existing fit page
184        self.opened_pages = {}
185        #page of simultaneous fit
186        self.sim_page = None
187        ## get the state of a page
188        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate)
189        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo)
190        self.Bind(basepage.EVT_NEXT_STATE, self._onRedo)
191       
192        #add default pages
193        self.add_default_pages()
194     
195        # increment number for model name
196        self.count = 0
197        #updating the panel
198        self.Update()
199        self.Center()
200       
201    def on_set_focus(self, event):
202        """
203        """
204        pos = self.GetSelection()
205        selected_page = self.GetPage(pos)
206        print "panel on fogus", selected_page.window_name
207        wx.PostEvent(self.parent, PanelOnFocusEvent(panel=selected_page))
208       
209    def get_data(self):
210        """
211        get the data in the current page
212        """
213        pos = self.GetSelection()
214        selected_page = self.GetPage(pos)
215        return selected_page.get_data()
216   
217    def get_state(self):
218        """
219         return the state of the current selected page
220        """
221        pos = self.GetSelection()
222        selected_page = self.GetPage(pos)
223        return selected_page.get_state()
224   
225    def add_default_pages(self):
226        """
227        Add default pages such as a hint page and an empty fit page
228        """
229        #add default page
230        from hint_fitpage import HintFitPage
231        self.hint_page = HintFitPage(self) 
232        self.AddPage(page=self.hint_page, caption="Hint")
233        self.hint_page.set_manager(self._manager)
234        #Add the first fit page
235        self.add_empty_page()
236
237   
238    def close_all(self):
239        """
240        remove all pages, used when a svs file is opened
241        """
242        #get number of pages
243        nop = self.GetPageCount()
244        #use while-loop, for-loop will not do the job well.
245        while (nop>0):
246            #delete the first page until no page exists
247            page = self.GetPage(0)
248            self._close_helper(selected_page=page)
249            self.DeletePage(0)
250            nop = nop - 1
251        ## save the title of the last page tab added
252        self.fit_page_name = {}
253        ## list of existing fit page
254        self.opened_pages = {} 
255         
256    def set_state(self, state):
257        """
258        Restore state of the panel
259        """
260        page_is_opened = False
261        if state is not None:
262            page_info = self.get_page_info(data=state.data)
263            for name, panel in self.opened_pages.values():
264                #Don't return any panel is the exact same page is created
265                if name == page_info.window_name:
266                    # the page is still opened
267                    panel.reset_page(state=state)
268                    panel.save_current_state() 
269                    page_is_opened = True
270            if not page_is_opened:
271                panel = self.add_fit_page(data=state.data)
272                # add data associated to the page created
273                if panel is not None: 
274                    self._manager.store_page(page=panel, data=state.data)
275                    panel.reset_page(state=state)
276                    panel.save_current_state()
277                   
278    def clear_panel(self, format='.svs'):
279        """
280        Clear and close all panels, used by guimanager
281        """
282        if format == '.svs':
283            #close all panels only when svs file opened
284            self.close_all()
285            self._manager.mypanels = []
286                       
287    def on_close_page(self, event=None):
288        """
289        close page and remove all references to the closed page
290        """
291        nbr_page = self.GetPageCount()
292        if nbr_page == 1:
293           
294            event.Veto()
295            return 
296        selected_page = self.GetPage(self.GetSelection())
297        self._close_helper(selected_page=selected_page)
298       
299    def close_page_with_data(self, deleted_data):
300        """
301        close a fit page when its data is completely remove from the graph
302        """
303        if deleted_data is None:
304            return
305        for index in range(self.GetPageCount()):
306            selected_page = self.GetPage(index) 
307            if hasattr(selected_page,"get_data"):
308                data = selected_page.get_data()
309               
310                if data is None:
311                    #the fitpanel exists and only the initial fit page is open
312                    #with no selected data
313                    return
314                if data.name == deleted_data.name:
315                    self._close_helper(selected_page)
316                    self.DeletePage(index)
317                    break
318       
319    def set_manager(self, manager):
320        """
321        set panel manager
322       
323        :param manager: instance of plugin fitting
324       
325        """
326        self._manager = manager
327        for pos in range(self.GetPageCount()):
328            page = self.GetPage(pos)
329            if page is not None:
330                page.set_manager(self._manager)
331
332       
333    def set_owner(self,owner):
334        """
335        set and owner for fitpanel
336       
337        :param owner: the class responsible of plotting
338       
339        """
340        self.event_owner = owner
341   
342    def set_model_list(self, dict):
343         """
344         copy a dictionary of model into its own dictionary
345         
346         :param dict: dictionnary made of model name as key and model class
347             as value
348         """
349         self.model_list_box = dict
350       
351    def get_current_page(self):
352        """
353        :return: the current page selected
354       
355        """
356        return self.GetPage(self.GetSelection() )
357   
358    def add_sim_page(self):
359        """
360        Add the simultaneous fit page
361        """
362        from simfitpage import SimultaneousFitPage
363        page_finder= self._manager.get_page_finder()
364        self.sim_page = SimultaneousFitPage(self,page_finder=page_finder, id=-1)
365       
366        self.AddPage(self.sim_page,caption="Simultaneous Fit",select=True)
367        self.sim_page.set_manager(self._manager)
368        return self.sim_page
369       
370    def get_page_info(self, data=None):
371        """
372        fill information required to add a page in the fit panel
373        """
374        name = "Fit Page"
375        type = 'empty'
376        if data is not None:
377            if data.is_data:
378                name = data.name
379                type = 'Data'
380            else:
381                if data.__class__.__name__ == "Data2D":
382                    name = 'Model 2D Fit'
383                    type = 'Theory2D'
384                else:
385                    name = 'Model 1D Fit'
386                    type = 'Theory1D'
387        page_info = PageInfo(data=data, name=name)
388        page_info.event_owner = self.event_owner
389        page_info.manager = self._manager
390        page_info.window_name = name
391        page_info.window_caption = name
392        page_info.type = type
393        return page_info
394   
395    def add_empty_page(self):
396        """
397        add an empty page
398        """
399        page_info = self.get_page_info()
400        from fitpage import FitPage
401        panel = FitPage(parent=self, page_info=page_info)
402        panel.set_manager(self._manager)
403        self.AddPage(page=panel, caption=page_info.window_name, select=True)
404        self.opened_pages[page_info.type] = [page_info.window_name, panel]
405        return panel
406   
407    def add_page(self, page_info):
408        """
409        add a new page
410        """
411        from fitpage import FitPage
412        panel = FitPage(parent=self, page_info=page_info)
413        panel.set_manager(self._manager)
414        self.AddPage(page=panel, caption=page_info.window_name, select=True)
415        index = self.GetPageIndex(panel)
416        self.change_page_content(data=page_info.data, index=index)
417        return panel
418   
419    def change_page_content(self, data, index):
420        """
421        replace the contains of an existing page
422        """
423        page_info = self.get_page_info(data=data)
424        self.SetPageText(index, page_info.window_name)
425        panel = self.GetPage(index)
426        panel.set_data(data)
427        if panel.model_list_box is None or len(panel.model_list_box) == 0: 
428            page_info.model_list_box = self.model_list_box.get_list()
429            panel.populate_box(dict=page_info.model_list_box)
430            panel.initialize_combox()
431        panel.set_page_info(page_info=page_info)
432        self.opened_pages[page_info.type] = [page_info.window_name, panel]
433        return panel
434   
435    def replace_page(self, index, page_info, type):
436        """
437        replace an existing page
438        """
439        self.DeletePage(index)
440        del self.opened_pages[type]
441        return self.add_page(page_info=page_info)
442       
443    def add_fit_page(self, data, reset=False):
444        """
445        Add a fitting page on the notebook contained by fitpanel
446       
447        :param data: data to fit
448       
449        :return panel : page just added for further used. is used by fitting module
450       
451        """
452        if data is None:
453            return None
454        page_info = self.get_page_info(data=data)
455        type = page_info.type
456        npages = len(self.opened_pages.keys())
457        #check if only and empty page is opened
458        if len(self.opened_pages.keys()) > 0:
459            first_page_type = self.opened_pages.keys()[0]
460            if npages == 1 and first_page_type in ['empty']:
461                #replace the first empty page
462                name, panel = self.opened_pages[first_page_type]
463                index = self.GetPageIndex(panel)
464                panel = self.change_page_content(data=data, index=index)
465                del self.opened_pages[first_page_type]
466                return panel
467        if type in self.opened_pages.keys():
468            #this type of page is already created but it is a theory
469            # meaning the same page is just to fit different data
470            if not type.lower() in ['data']:
471                #delete the previous theory page and add a new one
472                name, panel = self.opened_pages[type]
473                #self._manager.reset_plot_panel(panel.get_data())
474                #delete the existing page and replace it
475                index = self.GetPageIndex(panel)
476                panel = self.replace_page(index=index, page_info=page_info, type=type)
477                return panel
478            else:
479                for name, panel in self.opened_pages.values():
480                    #Don't return any panel is the exact same page is created
481                    if name == page_info.window_name:
482                        return None
483                    else:
484                        panel = self.add_page(page_info=page_info)
485                        return panel       
486        else:
487            #a new type of page is created
488            panel = self.add_page(page_info=page_info)
489            return panel
490       
491    def  _onGetstate(self, event):
492        """
493        copy the state of a page
494        """
495        page= event.page
496        if page.window_name in self.fit_page_name:
497            self.fit_page_name[page.window_name].appendItem(page.createMemento()) 
498           
499    def _onUndo(self, event ):
500        """
501        return the previous state of a given page is available
502        """
503        page = event.page
504        if page.window_name in self.fit_page_name:
505            if self.fit_page_name[page.window_name].getCurrentPosition()==0:
506                state = None
507            else:
508                state = self.fit_page_name[page.window_name].getPreviousItem()
509                page._redo.Enable(True)
510            page.reset_page(state)
511       
512    def _onRedo(self, event): 
513        """
514        return the next state available
515        """       
516        page = event.page
517        if page.window_name in self.fit_page_name:
518            length= len(self.fit_page_name[page.window_name])
519            if self.fit_page_name[page.window_name].getCurrentPosition()== length -1:
520                state = None
521                page._redo.Enable(False)
522                page._redo.Enable(True)
523            else:
524                state = self.fit_page_name[page.window_name].getNextItem()
525            page.reset_page(state) 
526                 
527    def _close_helper(self, selected_page):
528        """
529        Delete the given page from the notebook
530        """
531        #remove hint page
532        if selected_page == self.hint_page:
533            return
534        ## removing sim_page
535        if selected_page == self.sim_page :
536            self._manager.sim_page=None 
537            return
538       
539        ## closing other pages
540        state = selected_page.createMemento()
541        page_name = selected_page.window_name
542        page_finder = self._manager.get_page_finder() 
543        fitproblem = None
544        ## removing fit page
545        data = selected_page.get_data()
546        #Don' t remove plot for 2D
547        flag = True
548        if data.__class__.__name__ == 'Data2D':
549            flag = False
550        if selected_page in page_finder:
551            #Delete the name of the page into the list of open page
552            for type, list in self.opened_pages.iteritems():
553                #Don't return any panel is the exact same page is created
554                name = str(list[0])
555                if flag and selected_page.window_name == name:
556                    if type.lower() in ['theory1d', 'theory2d']:
557                        self._manager.remove_plot(selected_page, theory=True)
558                    else:
559                        self._manager.remove_plot(selected_page, theory=False)
560                    break 
561            del page_finder[selected_page]
562        ##remove the check box link to the model name of this page (selected_page)
563        try:
564            self.sim_page.draw_page()
565        except:
566            ## that page is already deleted no need to remove check box on
567            ##non existing page
568            pass
569               
570        #Delete the name of the page into the list of open page
571        for type, list in self.opened_pages.iteritems():
572            #Don't return any panel is the exact same page is created
573            name = str(list[0])
574            if selected_page.window_name == name:
575                del self.opened_pages[type]
576                break 
577     
578 
Note: See TracBrowser for help on using the repository browser.