source: sasview/sansview/perspectives/fitting/fitpanel.py @ 13a63ab

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 13a63ab was f22e626, checked in by Gervaise Alina <gervyh@…>, 13 years ago

working on remove data

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