source: sasview/sansview/perspectives/fitting/fitpanel.py @ 9cd6872

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 9cd6872 was 2296316, checked in by Jae Cho <jhjcho@…>, 14 years ago

moving features from the branch

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