source: sasview/sansview/perspectives/fitting/fitpanel.py @ 4faf4ba

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 4faf4ba was f20767b, checked in by Jae Cho <jhjcho@…>, 15 years ago

Working on 'Save(keep)' option. Still more to do on adding comments, on checkbox for array dispersion, and on bugs as being found.

  • Property mode set to 100644
File size: 15.8 KB
RevLine 
[d89f09b]1import wx
[26bf293]2import wx.aui
[d89f09b]3import wx.lib
4import numpy
[330573d]5import string 
6
7
[cfc0913]8import basepage
[00c3aac]9
[330573d]10_BOX_WIDTH = 80
11
12
13class StateIterator(object):
[1b69256]14    """
15        Contains all saved state of a given page.
16        Provide position of the current state of a page, the first save state
17        and the last state for a given page.
[330573d]18        Allow easy undo or redo for a given page 
[1b69256]19    """
[330573d]20    def __init__(self):
21        self._current=0
22       
23   
24    def __iter__(self):
25        return self
26   
27   
28    def first(self):
29        self._current =0
30        return self._current
31   
32    def next(self, max ):
33        if self._current < max:
34            self._current += 1
35        return self._current
36   
37    def previous(self):
38        if self._current > 0:
39            self._current = self._current -1
40        return self._current
41   
42    def currentPosition(self):
43        return self._current
44   
45    def setPosition(self, value):
46        if value >=0:
47            self._current = int(value)
48       
49       
50   
51 
52class ListOfState(list):     
53    def __init__(self, *args, **kw):
54        list.__init__(self, *args, **kw)
55        self.iterator = StateIterator()
56       
57    def appendItem(self, x):
58        self.append(x)
59        self.iterator.setPosition(value= len(self)-1)
60       
61    def removeItem(self, x):
62        self.iterator.previous()
63        self.remove(x)
64       
65    def getPreviousItem(self):
66        position = self.iterator.previous()
67       
68        if position < 0:
69            return None
70        else:
71            return self[position]
72       
73    def getNextItem(self):
[fe496eeb]74        position = self.iterator.next(max= len(self)-1)
[330573d]75        if position >= len(self):
76            return None
77        else:
78            return self[position]
79       
80    def getCurrentItem(self):
81        postion = self.iterator.currentPosition()
82        if postion >= 0 and position < len(self):
83            return self[postion]
84        else:
85            return None
86       
87    def getCurrentPosition(self):
88        return self.iterator.currentPosition()
89       
90
[1b69256]91       
92       
93       
[cfc0913]94class PageInfo(object):
95    """
96        this class contains the minimum numbers of data members
97        a fitpage or model page need to be initialized.
98    """
99    data = None
100    model= None
101    manager= None
102    event_owner= None
103    model_list_box = None
104    name=None
[330573d]105    ## Internal name for the AUI manager
[cfc0913]106    window_name = "Page"
107    ## Title to appear on top of the window
108    window_caption = "Page"
109   
110    def __init__(self, model=None,data=None, manager=None,
111                  event_owner=None,model_list_box=None , name=None):
112        """
113            Initialize data members
114        """
115        self.data = data
116        self.model= model
117        self.manager= manager
118        self.event_owner= event_owner
119        self.model_list_box = model_list_box
120        self.name=None
121        self.window_name = "Page"
122        self.window_caption = "Page"
123   
[26bf293]124class FitPanel(wx.aui.AuiNotebook):   
[925a30e]125
[d89f09b]126    """
127        FitPanel class contains fields allowing to fit  models and  data
128        @note: For Fit to be performed the user should check at least one parameter
129        on fit Panel window.
130       
131    """
132    ## Internal name for the AUI manager
133    window_name = "Fit panel"
134    ## Title to appear on top of the window
135    window_caption = "Fit Panel "
[2139c3f]136    CENTER_PANE = True
[7437880]137   
[d89f09b]138    def __init__(self, parent, *args, **kwargs):
[e814734]139        wx.aui.AuiNotebook.__init__(self,parent,-1,
[848a2ef]140                    style= wx.aui.AUI_NB_WINDOWLIST_BUTTON|wx.aui.AUI_NB_DEFAULT_STYLE|wx.CLIP_CHILDREN  )
141   
[d89f09b]142        self.manager=None
143        self.parent=parent
144        self.event_owner=None
[26bf293]145       
146        pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
[f20767b]147        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.onClosePage)
[51d47b5]148       
[d89f09b]149        #dictionary of miodel {model class name, model class}
150        self.model_list_box={}
[00c3aac]151        ##dictionary of page info
152        self.page_info_dict={}
[cfc0913]153        ## save the title of the last page tab added
154        self.fit_page_name={}
155        ## list of existing fit page
156        self.list_fitpage_name=[]
[6999659]157   
[f39511b]158        #model page info
159        self.model_page_number=None
[882a912]160        ## fit page number for model plot
161        self.fit_page1D_number=None
162        self.fit_page2D_number=None
[f39511b]163        self.model_page=None
[51d47b5]164        self.sim_page=None
[cfc0913]165        ## get the state of a page
166        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate)
[330573d]167        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo)
[fe496eeb]168        self.Bind(basepage.EVT_NEXT_STATE, self._onRedo)
169       
[6bcdad1]170        # increment number for model name
171        self.count=0
[f39511b]172        #updating the panel
[26bf293]173        self.Update()
[d89f09b]174        self.Center()
[2a8fac1]175       
176       
[26bf293]177    def onClosePage(self, event):
[51d47b5]178        """
[925a30e]179             close page and remove all references to the closed page
[51d47b5]180        """
181        selected_page = self.GetPage(self.GetSelection())
[7c845cb]182        ## removing sim_page
183        if selected_page == self.sim_page:
184            self.manager.sim_page=None 
185            return
[9853ad0]186       
[7c845cb]187        ## closing other pages
188        state = selected_page.createMemento()
189        page_name = selected_page.window_name
190        page_finder = self.manager.get_page_finder() 
191        fitproblem = None
192        ## removing model page
193        if selected_page == self.model_page:
194            fitproblem = selected_page.model.clone()
195            self.model_page = None
[ff36f31]196            self.count =0
[7c845cb]197            ## page on menu
[848a2ef]198            self.manager._add_page_onmenu(page_name, fitproblem)
[7c845cb]199        else:
200            if selected_page in page_finder:
201       
202                fitproblem= page_finder[selected_page].clone()
[882a912]203                if self.GetPageIndex(selected_page)==self.fit_page1D_number:
204                    self.fit_page1D_number=None
205                if self.GetPageIndex(selected_page)==self.fit_page2D_number:
206                    self.fit_page2D_number=None
[7c845cb]207                ## page on menu
[848a2ef]208                self.manager._add_page_onmenu(page_name, fitproblem)
[7c845cb]209                del page_finder[selected_page]
210            ##remove the check box link to the model name of this page (selected_page)
211            try:
[1d2782d]212                self.sim_page.draw_page()
[7c845cb]213            except:
214                ## that page is already deleted no need to remove check box on
215                ##non existing page
216                pass
[9853ad0]217               
[7c845cb]218        #Delete the name of the page into the list of open page
219        if selected_page.window_name in self.list_fitpage_name:
220            self.list_fitpage_name.remove(selected_page.window_name)
[a074145]221           
[d89f09b]222       
223    def set_manager(self, manager):
224        """
225             set panel manager
226             @param manager: instance of plugin fitting
227        """
228        self.manager = manager
[925a30e]229
[d89f09b]230       
231    def set_owner(self,owner):
232        """
233            set and owner for fitpanel
234            @param owner: the class responsible of plotting
235        """
[c77d859]236        self.event_owner = owner
237   
238    def set_model_list(self,dict):
239         """
240             copy a dictionary of model into its own dictionary
241             @param dict: dictionnary made of model name as key and model class
242             as value
243         """
244         self.model_list_box = dict
[51d47b5]245       
[c77d859]246 
247    def get_current_page(self):
248        """
249            @return the current page selected
250        """
251        return self.GetPage(self.GetSelection() )
252   
[51d47b5]253    def add_sim_page(self):
[925a30e]254        """
255            Add the simultaneous fit page
256        """
[51d47b5]257        from simfitpage import SimultaneousFitPage
[b28717b]258        page_finder= self.manager.get_page_finder()
259        self.sim_page = SimultaneousFitPage(self,page_finder=page_finder, id=-1)
260       
[51d47b5]261        self.AddPage(self.sim_page,caption="Simultaneous Fit",select=True)
262        self.sim_page.set_manager(self.manager)
263        return self.sim_page
[d89f09b]264       
[cfc0913]265    def add_fit_page( self,data, reset=False ):
[d89f09b]266        """
267            Add a fitting page on the notebook contained by fitpanel
[925a30e]268            @param data: data to fit
[b787e68c]269            @return panel : page just added for further used. is used by fitting module
[d89f09b]270        """     
[882a912]271        if data.is_data:
[925a30e]272            name = data.name
[882a912]273        else:
274            if data.__class__.__name__=="Data2D":
275                name = 'Model 2D Fit'
276            else:
277                name = 'Model 1D Fit'
[cfc0913]278        if not name in self.list_fitpage_name:
279            myinfo = PageInfo( data=data, name=name )
[dcf29d7]280            myinfo.model_list_box = self.model_list_box.get_list()
281            myinfo.event_owner = self.event_owner
282            myinfo.manager = self.manager
[b787e68c]283            myinfo.window_name = name
284            myinfo.window_caption = name
[6e659ae8]285       
[cfc0913]286            #if not name in self.fit_page_name :
[c77d859]287            from fitpage import FitPage
[cfc0913]288            panel = FitPage(parent= self, page_info=myinfo)
[b787e68c]289           
290            self.AddPage(page=panel, caption=name, select=True)
[882a912]291            if name == 'Model 1D Fit':
292                self.fit_page1D_number= self.GetPageIndex(panel)
293            if name =='Model 2D Fit':
294                self.fit_page2D_number= self.GetPageIndex(panel)
295               
[cfc0913]296            self.list_fitpage_name.append(name)
297            if reset:
298                if name in self.fit_page_name.keys():
299                    memento= self.fit_page_name[name][0]
300                    panel.reset_page(memento)
301            else:
[330573d]302                self.fit_page_name[name]=ListOfState()
[240b9966]303               
[330573d]304                #self.fit_page_name[name].appendItem(panel.createMemento())
[882a912]305            #GetPage(self, page_idx)
[925a30e]306            return panel
[882a912]307        elif name =='Model 1D Fit':
308            if self.fit_page1D_number!=None:
309                panel =self.GetPage(self.fit_page1D_number) 
[330573d]310                #self.fit_page_name[name]=[]
311                self.fit_page_name[name]= ListOfState()
312                #self.fit_page_name[name].insert(0,panel.createMemento())
313                #self.fit_page_name[name].append(panel.createMemento())
[882a912]314                return panel
315            return None
316        elif name =='Model 2D Fit':
317            if self.fit_page2D_number!=None:
318                panel =self.GetPage(self.fit_page2D_number) 
[330573d]319                self.fit_page_name[name]=ListOfState()
320                #self.fit_page_name[name].append(panel.createMemento())
[882a912]321                return panel
322            return None
323        return None
[1c66bc5]324       
[9853ad0]325   
[cd793b9]326    def add_model_page(self,model,page_title="Model", qmin=0.0001, qmax=0.13,
[b787e68c]327                        npts=50, topmenu=False, reset=False):
[9853ad0]328        """
329            Add a model page only one  to display any model selected from the menu or the page combo box.
330            when this page is closed than the user will be able to open a new one
331           
332            @param model: the model for which paramters will be changed
333            @param page_title: the name of the page
[dcf29d7]334            @param page_info: contains info about the state of the page
[9853ad0]335            @param qmin: mimimum Q
336            @param qmax: maximum Q
337            @param npts: number of Q points
338        """
339        if topmenu==True:
[ff36f31]340            ##first time to open model page
341            if self.count==0 :
342                #if not page_title in self.list_fitpage_name :
[6999659]343                self._help_add_model_page(model=model, page_title=page_title,
[b787e68c]344                                qmin=qmin, qmax=qmax, npts=npts, reset=reset)
[ff36f31]345                self.count +=1
[9853ad0]346            else:
[fbf4bf8]347                self.model_page.select_model(model)
[3595309d]348                self.fit_page_name[page_title]=ListOfState()
[240b9966]349                #self.fit_page_name[page_title].insert(0,self.model_page.createMemento())
[b787e68c]350     
[848a2ef]351     
352     
353    def _close_fitpage(self,data):
354        """
355            close a fit page when its data is completely remove from the graph
356        """
357        name = data.name
358        for index in range(self.GetPageCount()):
359            if self.GetPageText(index)== name:
360                selected_page = self.GetPage(index) 
361   
362                if index ==self.fit_page1D_number:
363                    self.fit_page1D_number=None
364                if index ==self.fit_page2D_number:
365                    self.fit_page2D_number=None
366                if selected_page in self.manager.page_finder:
367                    del self.manager.page_finder[selected_page]
368                ##remove the check box link to the model name of this page (selected_page)
369                try:
370                    self.sim_page.draw_page()
371                except:
372                    ## that page is already deleted no need to remove check box on
373                    ##non existing page
374                    pass
375               
376                #Delete the name of the page into the list of open page
377                if selected_page.window_name in self.list_fitpage_name:
378                    self.list_fitpage_name.remove(selected_page.window_name)
379                self.DeletePage(index)
380                break
381       
382       
[cfc0913]383    def  _onGetstate(self, event):
384        """
385            copy the state of a page
386        """
387        page= event.page
[b787e68c]388        if page.window_name in self.fit_page_name:
[330573d]389            self.fit_page_name[page.window_name].appendItem(page.createMemento()) 
[cfc0913]390           
[330573d]391    def _onUndo(self, event ):
392        """
393            return the previous state of a given page is available
394        """
395        page = event.page
396        if page.window_name in self.fit_page_name:
397            if self.fit_page_name[page.window_name].getCurrentPosition()==0:
398                state = None
399            else:
400                state = self.fit_page_name[page.window_name].getPreviousItem()
[fe496eeb]401                page._redo.Enable(True)
[330573d]402            page.reset_page(state)
[fe496eeb]403       
404    def _onRedo(self, event ): 
405        """
406            return the next state available
407        """       
408        page = event.page
409        if page.window_name in self.fit_page_name:
410            length= len(self.fit_page_name[page.window_name])
411            if self.fit_page_name[page.window_name].getCurrentPosition()== length -1:
412                state = None
413                page._redo.Enable(False)
[3b9e023]414                page._redo.Enable(True)
[fe496eeb]415            else:
416                state = self.fit_page_name[page.window_name].getNextItem()
417            page.reset_page(state) 
[dcf29d7]418               
[cd793b9]419    def _help_add_model_page(self,model,page_title="Model", qmin=0.0001, 
420                             qmax=0.13, npts=50,reset= False):
[3f1af74]421        """
422            #TODO: fill in description
423           
424            @param qmin: mimimum Q
425            @param qmax: maximum Q
426            @param npts: number of Q points
427        """
[dcf29d7]428        ## creating object that contaning info about model
[b787e68c]429        myinfo = PageInfo(model= model ,name= page_title)
430        myinfo.model_list_box = self.model_list_box.get_list()
431        myinfo.event_owner = self.event_owner
432        myinfo.manager = self.manager
433        myinfo.window_name = page_title
434        myinfo.window_caption = page_title
435     
[c77d859]436        from modelpage import ModelPage
[cfc0913]437        panel = ModelPage(self,myinfo)
[b787e68c]438       
[848a2ef]439        self.AddPage(page=panel, caption=page_title, select=True)
[77e23a2]440
[bb18ef1]441        self.model_page_number=self.GetSelection()
442        self.model_page=self.GetPage(self.GetSelection())
[0aeabc6]443     
[3595309d]444        ##resetting page
[b787e68c]445        if reset:
446            if page_title in self.fit_page_name.keys():
[848a2ef]447
[b787e68c]448                memento= self.fit_page_name[page_title][0]
449                panel.reset_page(memento)
450        else:
[240b9966]451            self.fit_page_name[page_title]=ListOfState()
452            #self.fit_page_name[page_title]=[]
[3595309d]453            #self.fit_page_name[page_title].insert(0,panel.createMemento())
[0aeabc6]454       
[b787e68c]455 
Note: See TracBrowser for help on using the repository browser.