source: sasview/sansview/perspectives/fitting/fitpanel.py @ 97ec26b

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 97ec26b was 90a7bbd, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working save state

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