source: sasview/sansview/perspectives/fitting/fitpanel.py @ 29ef718

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 29ef718 was 9466f2d6, checked in by Gervaise Alina <gervyh@…>, 14 years ago

make sure plugin model are recompile online when the plugin dir has changed

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