source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 178bfea

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

cleaned up report codes

  • Property mode set to 100644
File size: 77.5 KB
Line 
1"""
2This module provide GUI for the neutron scattering length density calculator
3
4"""
5
6import wx
7
8import sys,os
9
10from wx.lib.scrolledpanel import ScrolledPanel
11from sans.invariant import invariant
12from sans.guiframe.utils import format_number, check_float
13from sans.guicomm.events import NewPlotEvent, StatusEvent
14from invariant_details import InvariantDetailsPanel, InvariantContainer
15from invariant_widgets import OutputTextCtrl, InvTextCtrl
16from invariant_state import InvariantState as IState
17import copy,time
18# The minimum q-value to be used when extrapolating
19Q_MINIMUM  = 1e-5
20# The maximum q-value to be used when extrapolating
21Q_MAXIMUM  = 10
22# the ratio of maximum q value/(qmax of data) to plot the theory data
23Q_MAXIMUM_PLOT = 3
24# the number of points to consider during fit
25NPTS = 10
26#Default value for background
27BACKGROUND = 0.0
28#default value for the scale
29SCALE = 1.0
30#default value of the contrast
31CONTRAST = 1.0
32#default value of the power used for power law
33POWER = 4.0
34#Invariant panel size
35_BOX_WIDTH = 76
36
37
38if sys.platform.count("win32")>0:
39    _STATICBOX_WIDTH = 450
40    PANEL_WIDTH = 500 
41    PANEL_HEIGHT = 700
42    FONT_VARIANT = 0
43else:
44    _STATICBOX_WIDTH = 480
45    PANEL_WIDTH = 530
46    PANEL_HEIGHT = 700
47    FONT_VARIANT = 1
48
49
50class InvariantPanel(ScrolledPanel):
51    """
52    Provides the Invariant GUI.
53    """
54    ## Internal nickname for the window, used by the AUI manager
55    window_name = "Invariant"
56    ## Name to appear on the window title bar
57    window_caption = "Invariant"
58    ## Flag to tell the AUI manager to put this panel in the center pane
59    CENTER_PANE = True
60    def __init__(self, parent, data=None, manager=None,*args, **kwds):
61        kwds["size"]= (PANEL_WIDTH, PANEL_HEIGHT)
62        kwds["style"]= wx.FULL_REPAINT_ON_RESIZE
63        ScrolledPanel.__init__(self, parent=parent, *args, **kwds)
64        self.SetupScrolling()
65        #Font size
66        self.SetWindowVariant(variant=FONT_VARIANT)
67        #Object that receive status event
68        self.parent = parent
69        #plug-in using this panel
70        self._manager = manager
71        #Data uses for computation
72        self._data = data
73        self._scale = SCALE
74        self._background = BACKGROUND
75        self._bmark = None
76        self.bookmark_num = 0
77       
78        self._set_bookmark_menu()
79        #Init state
80        self.set_state()
81        # default flags for state
82        self.new_state = False
83        self.is_power_out = False
84        self.is_state_data = False
85
86        #container of invariant value
87        self.inv_container = None
88        #Draw the panel
89        self._do_layout()
90        self.reset_panel()
91        self._reset_state_list()
92       
93        if self.parent is not None:
94            msg = ""
95            wx.PostEvent(self.parent,StatusEvent(status=msg, info="info"))
96           
97        ## Default file location for save
98        self._default_save_location = os.getcwd()
99       
100    def err_check_on_data(self):
101        """
102        Check if data is valid for further computation
103        """
104        flag = False
105        self.hint_msg_txt.SetLabel('')
106        #edit the panel
107        if self._data is not None:
108            if len(self._data.x[self._data.x==0]) > 0:
109                flag = True
110                msg = "Invariant: one of your q-values is zero. Delete that entry before proceeding"
111                self.hint_msg_txt.SetLabel(msg)
112                wx.PostEvent(self.parent, StatusEvent(status=msg,
113                                                      info="warning",
114                                                      type="stop")) 
115        return flag
116   
117    def on_select_data(self, event=None):
118        """
119        """
120       
121        n = self.data_cbbox.GetCurrentSelection()
122        try:
123            data, path = self.data_cbbox.GetClientData(n)
124       
125            if not self._data == data:
126                self._manager.compute_helper(data=data)
127            else:
128                msg = "The data named %s is already loaded..."% data.name
129                wx.PostEvent(self.parent, StatusEvent(status=msg))
130        except:
131           self.data_cbbox.SetSelection(0)
132   
133    def set_data(self, list=[], state=None):
134        """
135        Receive  a list of data from gui_manager to compute invariant
136        """
137        if not list:
138            return 
139        count_bf = self.data_cbbox.GetCount()
140        for data, path in list:
141            if data.__class__.__name__ != "Data2D" and \
142                data.name not in self.data_cbbox.GetItems():
143                position = self.data_cbbox.GetCount()
144                self.data_cbbox.Insert(item=data.name, pos=position,
145                                    clientData=(data, path))
146        count = self.data_cbbox.GetCount()
147        if count >0:
148            # set data only on the first or state data
149            if count ==1 or self.is_state_data:
150                # when count increased especially if self.is_state_data.
151                if count > count_bf:
152                    self.data_cbbox.SetSelection(count-1)
153
154                self.data_cbbox.Enable()
155                self.on_select_data(event=None)
156                self.is_state_data = False
157           
158            title = "Untitled"
159            if hasattr(data,"title"):
160                title = str(data.title.lstrip().rstrip())
161                if title == "":
162                    title = str(data.name)
163            else:
164                title = str(data.name)
165   
166            wx.PostEvent(self.parent, NewPlotEvent(plot=data, title=title))
167           
168    def set_current_data(self, data, path=None):
169        """
170        Set the data
171       
172        : return: True/False; if False, it will not set_current_data
173        """
174        # warn the users
175        if self._data != None and data != None:
176            if not self._show_message():
177                return False
178           
179        self._data = data
180        # reset popUpMenu
181        self._set_bookmark_menu()
182        #edit the panel
183        if self._data is not None:
184           
185            self.err_check_on_data()
186            self.get_state_by_num(0)
187            data_name = self._data.name
188            data_qmin = min (self._data.x)
189            data_qmax = max (self._data.x)
190
191            if data.name not in self.data_cbbox.GetItems():
192                self.data_cbbox.Insert(pos=0, clientData=(data, None), 
193                                       item=data.name)
194            else:
195                pos = self.data_cbbox.FindString(data.name)
196                self.data_cbbox.SetSelection(pos)
197            self.data_min_tcl.SetLabel(str(data_qmin))
198            self.data_max_tcl.SetLabel(str(data_qmax))
199            self.button_save.Enable(True) 
200            self.reset_panel()
201            self.compute_invariant(event=None)
202            #Reset the list of states
203            self.state.data = copy.deepcopy(data)
204            self._reset_state_list()
205           
206        return True     
207
208    def set_message(self):
209        """
210        Display warning message if available
211        """
212        if self.inv_container is not None:
213            if self.inv_container.existing_warning:
214                msg = "Warning! Computations on invariant require your "
215                msg += "attention.\n Please click on Details button."
216                self.hint_msg_txt.SetForegroundColour("red")
217   
218                wx.PostEvent(self.parent,StatusEvent(status=msg,info="warning"))
219            else:
220                msg = "For more information, click on Details button."
221                self.hint_msg_txt.SetForegroundColour("black")
222                wx.PostEvent(self.parent,StatusEvent(status=msg,info="info"))
223            self.hint_msg_txt.SetLabel(msg)
224           
225       
226    def set_manager(self, manager):
227        """
228        set value for the manager
229        """
230        self._manager = manager
231       
232    def set_state(self,state=None,data=None):
233        """
234        set state when loading it from a .inv file
235        """
236        if state == None or data == None:
237            self.state = IState()
238        else:
239            if not self.set_current_data(data, path=None):
240                return
241            self.new_state = True
242            self.state = state   
243           
244            num = self.state.saved_state['state_num']
245           
246            if num > 0 :
247                self._undo_enable()
248            if num < len(state.state_list)-1:
249                self._redo_enable()
250               
251            # get bookmarks
252            self.bookmark_num = len(self.state.bookmark_list)
253
254            total_bookmark_num = self.bookmark_num+1
255            for ind in range(1,total_bookmark_num):
256                #bookmark_num = ind
257                value = self.state.bookmark_list[ind]
258                name = "%d] bookmarked at %s on %s"% (ind,value[0], value[1])
259                # append it to menu
260                id = wx.NewId()
261                self.popUpMenu.Append(id,name,str(''))
262                wx.EVT_MENU(self, id, self._back_to_bookmark) 
263
264            self.get_state_by_num(state_num=str(num))
265           
266            self._get_input_list() 
267            #make sure that the data is reset (especially when loaded from a inv file)
268            self.state.data = self._data
269            self.new_state = False 
270           
271
272    def get_background(self):
273        """
274        return the background textcrtl value as a float
275        """
276        background = self.background_tcl.GetValue().lstrip().rstrip()
277        if background == "":
278            raise ValueError, "Need a background"
279        if check_float(self.background_tcl):
280            return float(background)
281        else:
282            raise ValueError, "Receive invalid value for background : %s"%(background)
283   
284    def get_scale(self):
285        """
286        return the scale textcrtl value as a float
287        """
288        scale = self.scale_tcl.GetValue().lstrip().rstrip()
289        if scale == "":
290            raise ValueError, "Need a background"
291        if check_float(self.scale_tcl):
292            if float(scale)<= 0.0:
293                self.scale_tcl.SetBackgroundColour("pink")
294                self.scale_tcl.Refresh()
295                raise ValueError, "Receive invalid value for scale: %s"%(scale)
296            return float(scale)
297        else:
298            raise ValueError, "Receive invalid value for scale : %s"%(scale)
299       
300    def get_contrast(self):
301        """
302        return the contrast textcrtl value as a float
303        """
304        par_str = self.contrast_tcl.GetValue().strip()
305        contrast = None
306        if par_str !="" and check_float(self.contrast_tcl):
307            contrast = float(par_str)
308        return contrast
309   
310    def get_extrapolation_type(self, low_q, high_q):
311        """
312        """
313        extrapolation = None
314        if low_q  and not high_q:
315            extrapolation = "low"
316        elif not low_q  and high_q:
317            extrapolation = "high"
318        elif low_q and high_q:
319            extrapolation = "both"
320        return extrapolation
321           
322    def get_porod_const(self):
323        """
324        return the porod constant textcrtl value as a float
325        """
326        par_str = self.porod_constant_tcl.GetValue().strip()
327        porod_const = None
328        if par_str !="" and check_float(self.porod_constant_tcl):
329            porod_const = float(par_str)
330        return porod_const
331   
332    def get_volume(self, inv, contrast, extrapolation):
333        """
334        """
335        if contrast is not None:
336            try:
337                v, dv = inv.get_volume_fraction_with_error(contrast=contrast, 
338                                                           extrapolation=extrapolation)
339                self.volume_tcl.SetValue(format_number(v))
340                self.volume_err_tcl.SetValue(format_number(dv))
341            except:
342                self.volume_tcl.SetValue(format_number(None))
343                self.volume_err_tcl.SetValue(format_number(None))
344                msg= "Error occurred computing volume fraction: %s"%sys.exc_value
345                wx.PostEvent(self.parent, StatusEvent(status=msg,
346                                                      info="error",
347                                                      type="stop"))
348               
349    def get_surface(self, inv, contrast, porod_const, extrapolation):
350        """
351        """
352        if contrast is not None and porod_const is not None:
353            try:
354                s, ds = inv.get_surface_with_error(contrast=contrast,
355                                        porod_const=porod_const,
356                                        extrapolation=extrapolation)
357                self.surface_tcl.SetValue(format_number(s))
358                self.surface_err_tcl.SetValue(format_number(ds))
359            except:
360                self.surface_tcl.SetValue(format_number(None))
361                self.surface_err_tcl.SetValue(format_number(None))
362                msg = "Error occurred computing specific surface: %s"%sys.exc_value
363                wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
364                                                       type="stop"))
365               
366    def get_total_qstar(self, inv, extrapolation):
367        """
368        """
369        try:
370            qstar_total, qstar_total_err = inv.get_qstar_with_error(extrapolation)
371           
372            self.invariant_total_tcl.SetValue(format_number(qstar_total))
373            self.invariant_total_err_tcl.SetValue(format_number(qstar_total_err))
374            self.inv_container.qstar_total = qstar_total
375            self.inv_container.qstar_total_err = qstar_total_err
376         
377        except:
378            self.inv_container.qstar_total = "Error"
379            self.inv_container.qstar_total_err = "Error"
380            self.invariant_total_tcl.SetValue(format_number(None))
381            self.invariant_total_err_tcl.SetValue(format_number(None))
382            msg= "Error occurred computing invariant using extrapolation: %s"%sys.exc_value
383            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
384           
385    def get_low_qstar(self, inv, npts_low, low_q=False):
386        """
387        """
388        if low_q:
389            try: 
390                qstar_low, qstar_low_err = inv.get_qstar_low()
391                self.inv_container.qstar_low = qstar_low
392                self.inv_container.qstar_low_err = qstar_low_err
393                extrapolated_data = inv.get_extra_data_low(npts_in=npts_low) 
394                power_low = inv.get_extrapolation_power(range='low') 
395                if self.power_law_low.GetValue():
396                    self.power_low_tcl.SetValue(format_number(power_low))
397                self._manager.plot_theory(data=extrapolated_data,
398                                           name="Low-Q extrapolation")
399            except:
400                self.inv_container.qstar_low = "ERROR"
401                self.inv_container.qstar_low_err = "ERROR"
402                self._manager.plot_theory(name="Low-Q extrapolation")
403                msg= "Error occurred computing low-Q invariant: %s"%sys.exc_value
404                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
405        else:
406            try:
407                self._manager.plot_theory(name="Low-Q extrapolation")
408            except: pass
409           
410    def get_high_qstar(self, inv, high_q=False):
411        """
412        """
413        if high_q:
414            try: 
415                qmax_plot = Q_MAXIMUM_PLOT * max(self._data.x)
416                if qmax_plot > Q_MAXIMUM: qmax_plot = Q_MAXIMUM
417                qstar_high, qstar_high_err = inv.get_qstar_high()
418                self.inv_container.qstar_high = qstar_high
419                self.inv_container.qstar_high_err = qstar_high_err
420                power_high = inv.get_extrapolation_power(range='high') 
421                self.power_high_tcl.SetValue(format_number(power_high))
422                high_out_data = inv.get_extra_data_high(q_end=qmax_plot,npts=500)
423                self._manager.plot_theory(data=high_out_data,
424                                           name="High-Q extrapolation")
425            except:
426                self.inv_container.qstar_high = "ERROR"
427                self.inv_container.qstar_high_err = "ERROR"
428                self._manager.plot_theory(name="High-Q extrapolation")
429                msg= "Error occurred computing high-Q invariant: %s"%sys.exc_value
430                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
431        else:
432            try:
433                self._manager.plot_theory(name="High-Q extrapolation")
434            except: pass
435
436    def get_qstar(self, inv):
437        """
438        """
439        qstar, qstar_err = inv.get_qstar_with_error()
440        self.inv_container.qstar = qstar
441        self.inv_container.qstar_err = qstar_err
442             
443    def set_extrapolation_low(self, inv, low_q=False):
444        """
445        return float value necessary to compute invariant a low q
446        """
447        #get funtion
448        if self.guinier.GetValue():
449            function_low = "guinier"
450        # get the function
451        power_low = None #2.0/3.0
452        if self.power_law_low.GetValue():
453            function_low = "power_law"
454            if self.fit_enable_low.GetValue():
455                #set value of power_low to none to allow fitting
456                power_low = None
457            else:
458                power_low = self.power_low_tcl.GetValue().lstrip().rstrip()
459                if check_float(self.power_low_tcl):
460                    power_low = float(power_low)
461                else:
462                    if low_q :
463                        #Raise error only when qstar at low q is requested
464                        msg = "Expect float for power at low q , got %s"%(power_low)
465                        raise ValueError, msg
466       
467        #Get the number of points to extrapolated
468        npts_low = self.npts_low_tcl.GetValue().lstrip().rstrip()   
469        if check_float(self.npts_low_tcl):
470            npts_low = float(npts_low)
471        else:
472            if low_q:
473                msg = "Expect float for number of points at low q , got %s"%(npts_low)
474                raise ValueError, msg
475        #Set the invariant calculator
476        inv.set_extrapolation(range="low", npts=npts_low,
477                                   function=function_low, power=power_low)   
478        return inv, npts_low 
479   
480
481    def set_extrapolation_high(self, inv, high_q=False):
482        """
483        return float value necessary to compute invariant a high q
484        """
485        power_high = None
486        #if self.power_law_high.GetValue():
487        function_high = "power_law"
488        if self.fit_enable_high.GetValue():
489            #set value of power_high to none to allow fitting
490            power_high = None
491        else:
492            power_high = self.power_high_tcl.GetValue().lstrip().rstrip()
493            if check_float(self.power_high_tcl):
494                power_high = float(power_high)
495            else:
496                if high_q :
497                    #Raise error only when qstar at high q is requested
498                    msg = "Expect float for power at high q , got %s"%(power_high)
499                    raise ValueError, msg
500                         
501        npts_high = self.npts_high_tcl.GetValue().lstrip().rstrip()   
502        if check_float(self.npts_high_tcl):
503            npts_high = float(npts_high)
504        else:
505            if high_q:
506                msg = "Expect float for number of points at high q , got %s"%(npts_high)
507                raise ValueError, msg
508        inv.set_extrapolation(range="high", npts=npts_high,
509                                   function=function_high, power=power_high)
510        return inv, npts_high
511   
512    def display_details(self, event):
513        """
514        open another panel for more details on invariant calculation
515        """
516        panel = InvariantDetailsPanel(parent=self, 
517                                           qstar_container=self.inv_container)
518        panel.ShowModal()
519        panel.Destroy()
520        self.button_calculate.SetFocus()
521       
522    def compute_invariant(self, event=None):
523        """
524        compute invariant
525        """
526        if self._data == None:
527            msg = "\n\nData must be loaded first in order to perform a compution..."
528            wx.PostEvent(self.parent, StatusEvent(status=msg))
529        # set a state for this computation for saving
530        elif event != None: 
531            self._set_compute_state(state='compute')
532            self.button_bookmark.Enable(True)
533            msg= "\n\nStarting a new invariant computation..."           
534            wx.PostEvent(self.parent, StatusEvent(status=msg))
535           
536
537        if self._data is None or self.err_check_on_data():
538            return
539       
540        #clear outputs textctrl
541        self._reset_output()
542        try:
543            background = self.get_background()
544            scale = self.get_scale()
545        except:
546            msg= "Invariant Error: %s"%(sys.exc_value)
547            wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop"))
548            return
549       
550        low_q = self.enable_low_cbox.GetValue()
551        high_q = self.enable_high_cbox.GetValue() 
552        #set invariant calculator
553        inv = invariant.InvariantCalculator(data=self._data,
554                                            background=background,
555                                            scale=scale)
556        try:
557            inv, npts_low = self.set_extrapolation_low(inv=inv, low_q=low_q)
558            inv, npts_high = self.set_extrapolation_high(inv=inv, high_q=high_q)
559        except:
560            msg = "Error occurred computing invariant: %s"%sys.exc_value
561            wx.PostEvent(self.parent, StatusEvent(status=msg,
562                                                 info="warning",type="stop"))
563            return
564        #check the type of extrapolation
565        extrapolation = self.get_extrapolation_type(low_q=low_q, high_q=high_q)
566       
567        #Compute invariant
568        bkg_changed = False
569        scale_changed = False
570        try:
571            self.get_qstar(inv=inv)
572            #if scale_changed or bkg_changed:
573            #self._manager.plot_data(data=inv.get_data())
574           
575        except:
576            msg= "Error occurred computing invariant: %s"%sys.exc_value
577            wx.PostEvent(self.parent, StatusEvent(status=msg, 
578                                                  info="warning",type="stop"))
579            return
580       
581        #Compute qstar extrapolated to low q range
582        self.get_low_qstar(inv=inv, npts_low=npts_low, low_q=low_q)
583        #Compute qstar extrapolated to high q range
584        self.get_high_qstar(inv=inv, high_q=high_q)
585        #Compute qstar extrapolated to total q range and set value to txtcrtl
586        self.get_total_qstar(inv=inv, extrapolation=extrapolation)
587        # Parse additional parameters
588        porod_const = self.get_porod_const()       
589        contrast = self.get_contrast()
590       
591        try:
592            #Compute volume and set value to txtcrtl
593            self.get_volume(inv=inv, contrast=contrast, extrapolation=extrapolation)
594            #compute surface and set value to txtcrtl
595        except:
596            msg = "Error occurred computing invariant: %s"%sys.exc_value
597            wx.PostEvent(self.parent, StatusEvent(status=msg,
598                                                  info="warning",type="stop"))
599        try:
600            self.get_surface(inv=inv, contrast=contrast, porod_const=porod_const, 
601                                    extrapolation=extrapolation)
602           
603        except:
604            msg = "Error occurred computing invariant: %s"%sys.exc_value
605            wx.PostEvent(self.parent, StatusEvent(status=msg,
606                                                  info="warning",type="stop"))
607           
608        #compute percentage of each invariant
609        self.inv_container.compute_percentage()
610       
611        #display a message
612        self.set_message()
613       
614        # reset power_out to default to get ready for another '_on_text'
615        if self.is_power_out == True:
616            self.state.container = copy.deepcopy(self.inv_container)
617            self.state.timestamp= self._get_time_stamp()
618            msg = self.state.__str__()
619            self.state.set_report_string()
620            self.is_power_out = False
621            wx.PostEvent(self.parent, StatusEvent(status = msg ))
622
623        #enable the button_ok for more details
624        self.button_details.Enable()
625
626        if event != None: 
627            self.button_report.Enable(True)
628            wx.PostEvent(self.parent, StatusEvent(status = '\nFinished invariant computation...'))
629       
630    def undo(self,event=None):
631        """
632        Go back to the previous state
633       
634        : param event: undo button event
635        """
636        if event != None: event.Skip()
637        if self.state.state_num <0: return
638        self.is_power_out = True
639        # get the previous state_num
640        pre_state_num = int(self.state.saved_state['state_num']) - 1
641        self.get_state_by_num(state_num=str(pre_state_num))
642       
643        if float(pre_state_num) <=0:
644            self._undo_disable()
645        else:
646            self._undo_enable()
647
648        self._redo_enable()
649        self.is_power_out = False 
650        self._info_state_num()
651       
652       
653    def redo(self,event=None):
654        """
655        Go forward to the previous state
656       
657        : param event: redo button event
658        """
659        if event != None: event.Skip()
660        self.is_power_out = True
661        # get the next state_num
662        next_state_num = int(self.state.saved_state['state_num']) + 1
663
664        self.get_state_by_num(state_num=str(next_state_num))
665       
666        if float(next_state_num)+2 > len(self.state.state_list):
667            self._redo_disable()
668        else:
669            self._redo_enable()
670       
671        self._undo_enable()
672        self.is_power_out = False
673        self._info_state_num()
674       
675    def report(self, event=None):
676        """
677        Invoke report dialog panel
678       
679        : param event: report button event
680        """
681        from report_dialog import ReportDialog
682
683        self.state.set_report_string()
684        report_html_str = self.state.report_str
685        report_text_str = self.state.__str__()
686        report_img = self.state.image
687        report_list = [report_html_str,report_text_str,report_img]
688        dialog = ReportDialog(report_list, None, -1, "")
689        dialog.ShowModal()
690       
691    def get_state_by_num(self,state_num=None):
692        """
693        Get the state given by number
694       
695        : param state_num: the given state number
696        """     
697        if state_num == None:
698            return
699
700        backup_state_list = copy.deepcopy(self.state.state_list)
701       
702        # get the previous state
703        try:
704            current_state = copy.deepcopy(self.state.state_list[str(state_num)])
705            # get the previously computed state number (computation before the state changes happened)
706            current_compute_num = str(current_state['compute_num'])
707        except :
708            raise
709            #raise ValueError,  "No such state exists in history"
710       
711        # get the state at pre_compute_num
712        comp_state = copy.deepcopy(self.state.state_list[current_compute_num])
713
714        # set the parameters
715        for key in comp_state:
716            value = comp_state[key]
717            try:
718                exec "self.%s.SetValue(str(%s))" % (key, value)
719            except TypeError:
720                exec "self.%s.SetValue(%s)" % (key, value)
721            except:
722                pass
723         
724        self.compute_invariant(event=None)
725        # set the input params at the state at pre_state_num
726        for key in current_state:
727            # set the inputs and boxes
728            value = current_state[key]
729            try:
730                exec 'self.%s.SetValue(str(%s))' % (key, value)
731            except TypeError:
732                exec 'self.%s.SetValue(%s)' % (key, value)
733            except:
734                pass
735
736        self._enable_high_q_section(event=None)
737        self._enable_low_q_section(event=None)
738        self.state.state_list = backup_state_list
739        self.state.saved_state = current_state
740        self.state.state_num = state_num
741           
742       
743    def get_bookmark_by_num(self, num=None):
744        """
745        Get the bookmark state given by number
746       
747        : param num: the given bookmark number
748       
749        """
750        current_state = {}
751        comp_state = {}
752        backup_state_list = copy.deepcopy(self.state.state_list)
753
754        # get the previous state
755        try:
756            time,date,current_state,comp_state = self.state.bookmark_list[int(num)] 
757        except :
758            raise ValueError,  "No such bookmark exists"
759
760        # set the parameters
761        for key in comp_state:
762            value = comp_state[key]
763            try:
764                exec "self.%s.SetValue(str(%s))" % (key, value)
765            except TypeError:
766                exec "self.%s.SetValue(%s)" % (key, value)
767            except:
768                pass
769
770        self.compute_invariant(event=None)
771        # set the input params at the state of pre_state_num
772        for key in current_state:
773            value = current_state[key]
774            try:
775                exec 'self.%s.SetValue(str(%s))' % (key, value)
776            except TypeError:
777                exec 'self.%s.SetValue(%s)' % (key, value)
778            except:
779                pass
780        self.state.saved_state = copy.deepcopy(current_state)
781       
782        self._enable_high_q_section(event=None)
783        self._enable_low_q_section(event=None)
784        self.state.state_list = backup_state_list
785        #self.state.saved_state = current_state
786        #self.state.state_num = state_num
787
788    def reset_panel(self):
789        """
790        set the panel at its initial state.
791        """
792        self.background_tcl.SetValue(str(BACKGROUND))
793        self.scale_tcl.SetValue(str(SCALE)) 
794        self.contrast_tcl.SetValue(str(CONTRAST))
795        self.porod_constant_tcl.SetValue('') 
796        self.npts_low_tcl.SetValue(str(NPTS))
797        self.enable_low_cbox.SetValue(False)
798        self.fix_enable_low.SetValue(True)
799        self.power_low_tcl.SetValue(str(POWER))
800        self.guinier.SetValue(True)
801        self.power_low_tcl.Disable()
802        self.enable_high_cbox.SetValue(False)
803        self.fix_enable_high.SetValue(True)
804        self.power_high_tcl.SetValue(str(POWER))
805        self.npts_high_tcl.SetValue(str(NPTS))
806        self.button_details.Disable()
807        #Change the state of txtcrtl to enable/disable
808        self._enable_low_q_section()
809        #Change the state of txtcrtl to enable/disable
810        self._enable_high_q_section()
811        self._reset_output()
812        self.button_undo.Disable()
813        self.button_redo.Disable()
814        self.button_bookmark.Disable()
815        self.button_report.Disable()
816        self.button_calculate.SetFocus()
817        #self.SetupScrolling()
818       
819    def _set_state(self, event):
820        """
821        Set the state list
822       
823        :param event: rb/cb event
824        """
825        if event == None:
826            return
827        obj = event.GetEventObject()
828        name = str(obj.GetName())
829        value = str(obj.GetValue())
830        rb_list = [['power_law_low','guinier'],['fit_enable_low','fix_enable_low'],['fit_enable_high','fix_enable_high']]
831
832        try:
833            if value == None or value.lstrip().rstrip() =='':
834                value = 'None'
835            exec 'self.state.%s = %s' % (name, value)
836            exec "self.state.saved_state['%s'] = %s" %  (name, value)
837           
838            # set the count part of radio button clicked False for the saved_state
839            for title,content in rb_list:
840                if name ==  title:
841                    name = content
842                    value = False     
843                elif name == content:
844                    name = title
845                    value = False 
846            exec "self.state.saved_state['%s'] = %s" %  (name, value)     
847           
848            # Instead of changing the future, create a new future.
849            max_state_num = len(self.state.state_list)-1   
850            self.state.saved_state['state_num'] = max_state_num   
851           
852            self.state.saved_state['state_num'] +=1
853            self.state.state_num = self.state.saved_state['state_num']
854            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
855        except:           
856            pass
857
858        event.Skip()
859        self._undo_enable()
860        self._redo_disable()
861           
862    def _set_compute_state(self,state=None):
863        """
864        Notify the compute_invariant state to self.state
865       
866        : param state: set 'compute' when the computation is activated by the 'compute' button, else None
867       
868        """
869        # reset the default
870        if state != 'compute':
871            self.new_state = False
872            self.is_power_out = False
873        else:
874            self.is_power_out = True
875        # Instead of changing the future, create a new future.
876        max_state_num = len(self.state.state_list)-1   
877        self.state.saved_state['state_num'] = max_state_num       
878        # A new computation is also A state
879        temp_saved_states = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
880        temp_saved_states['state_num'] +=1
881        self.state.state_num = temp_saved_states['state_num']
882
883               
884        # set the state number of the computation
885        if state == 'compute':
886            temp_saved_states['compute_num'] = self.state.state_num
887        self.state.saved_state= copy.deepcopy(temp_saved_states)
888        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
889       
890        # A computation is a new state, so delete the states with any higher state numbers
891        for i in range(self.state.state_num+1,len(self.state.state_list)):
892            try:
893                del (self.state.state_list[str(i)])
894            except: 
895                pass
896        # Enable the undo button if it was not
897        self._undo_enable()
898        self._redo_disable()
899       
900       
901    def _reset_state_list(self,data=None):
902        """
903        Reset the state_list just before data was loading: Used in 'set_current_data()'
904        """
905        #if data == None: return
906        #temp_state = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
907        # Clear the list
908        self.state.state_list.clear()
909        self.state.bookmark_list.clear()
910        # Set defaults
911        self.state.saved_state['state_num'] = 0
912        self.state.saved_state['compute_num'] = 0
913        if self._data != None:
914            self.state.saved_state['file'] = str(self._data.name)
915        else:
916            self.state.saved_state['file'] = 'None'
917        self.state.file = self.state.saved_state['file']
918
919        self.state.state_num = self.state.saved_state['state_num']
920        self.state.timestamp = "('00:00:00', '00/00/0000')"
921
922        # Put only the current state in the list
923        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
924        self._undo_disable()
925       
926    def _on_text(self, event):
927        """
928        Catch text change event to add the state to the state_list
929       
930        :param event: txtctr event ; assumes not None
931       
932        """
933        if self._data == None: 
934            return
935        # check if this event is from do/undo button
936        if self.state.saved_state['is_time_machine'] or self.new_state:
937            event.Skip()
938            return
939       
940        # get the object
941        obj = event.GetEventObject()
942        name = str(obj.GetName())
943        value = str(obj.GetValue())
944        state_num = self.state.saved_state['state_num']
945
946        # text event is a new state, so delete the states with higher state_num
947        # i.e., change the future
948        for i in range(int(state_num)+1,len(self.state.state_list)):
949            try:
950                del (self.state.state_list[str(i)])
951            except: 
952                pass
953       
954        # Instead of changing the future, create a new future.
955        #max_state_num = len(self.state.state_list)-1   
956        #self.state.saved_state['state_num'] = max_state_num
957
958        # try to add new state of the text changes in the state_list
959        try:
960            if value.strip() == None: value = ''
961            exec "self.state.%s = '%s'" % (name, value)
962            exec "self.state.saved_state['%s'] = '%s'" %  (name, value)
963            exec "self.state.input_list['%s'] = '%s'" % (name, value)
964            if not self.is_power_out:
965                if name != 'power_low_tcl' and name !='power_high_tcl':
966                    self.state.saved_state['state_num'] += 1
967            self.state.state_num = self.state.saved_state['state_num']
968            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
969        except:
970            pass
971
972        event.Skip()
973        self._undo_enable()
974        self._redo_disable()
975        self.button_bookmark.Enable(True)
976        self.button_report.Disable()
977       
978       
979    def _on_out_text(self, event):     
980        """
981        Catch ouput text change to add the state
982       
983        :param event: txtctr event ; assumes not None
984       
985        """   
986        # get the object
987        obj = event.GetEventObject()
988        name = str(obj.GetName())
989        value = str(obj.GetValue())
990        try:
991            exec "self.state.saved_state['%s'] = '%s'" %  (name, value)
992            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()
993        except:
994            pass
995        if event != None: event.Skip()\
996
997    def _get_input_list(self):     
998        """
999        get input_list; called by set_state
1000        """   
1001        # get state num of the last compute state
1002        compute_num = self.state.saved_state['compute_num']
1003        # find values and put into the input list
1004        for key1,value1 in self.state.state_list[str(compute_num)].iteritems(): 
1005            for key,value in self.state.input_list.iteritems(): 
1006                if key == key1:
1007                    self.state.input_list[key]=value1
1008                    break
1009       
1010    def _set_bookmark_menu(self):
1011        """
1012        Setup 'bookmark' context menu
1013        """
1014        ## Create context menu for page
1015        self.popUpMenu = wx.Menu()
1016        id = wx.NewId()
1017        self._bmark = wx.MenuItem(self.popUpMenu,id,"BookMark"," Bookmark the panel to recall it later")
1018        self.popUpMenu.AppendItem(self._bmark)
1019        self._bmark.Enable(True)
1020        wx.EVT_MENU(self, id, self._on_bookmark)
1021        self.popUpMenu.AppendSeparator()
1022        self.Bind(wx.EVT_CONTEXT_MENU, self._on_context_menu)
1023       
1024    def _on_bookmark(self,event):
1025        """
1026        Save the panel state in memory and add the list on the popup menu on bookmark context menu event
1027        """ 
1028        if self._data == None: return
1029        if event == None: return
1030        self.bookmark_num += 1
1031        # date and time of the event
1032        #year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
1033        #my_time= str(hour)+" : "+str(minute)+" : "+str(second)+" "
1034        #date= str( month)+"/"+str(day)+"/"+str(year)
1035        my_time, date = self._get_time_stamp()
1036        state_num = self.state.state_num
1037        compute_num = self.state.saved_state['compute_num']
1038        # name and message of the bookmark list
1039        msg=  "State saved at %s on %s"%(my_time, date)
1040         ## post help message for the selected model
1041        msg +=" Right click on the panel to retrieve this state"
1042        #wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1043        name = "%d] bookmarked at %s on %s"%(self.bookmark_num,my_time, date)
1044       
1045        # append it to menu
1046        id = wx.NewId()
1047        self.popUpMenu.Append(id,name,str(msg))
1048        wx.EVT_MENU(self, id, self._back_to_bookmark )
1049        state = self.state.clone_state()
1050        comp_state = copy.deepcopy(self.state.state_list[str(compute_num)])
1051        self.state.bookmark_list[self.bookmark_num] = [my_time,date,state,comp_state]
1052        self.state.toXML(self, doc=None, entry_node=None)
1053       
1054        wx.PostEvent(self.parent,StatusEvent(status=msg,info="info"))
1055
1056    def _back_to_bookmark(self,event):
1057        """
1058        Bring the panel back to the state of bookmarked requested by context menu event
1059        and set it as a new state
1060        """
1061        ## post help message for the selected model
1062        msg = self.popUpMenu.GetHelpString(event.GetId())
1063        msg +=" reloaded"
1064        wx.PostEvent(self.parent, StatusEvent(status = msg ))
1065       
1066        name= self.popUpMenu.GetLabel(event.GetId())
1067        num,time = name.split(']')
1068        current_state_num = self.state.state_num 
1069        self.get_bookmark_by_num(num)
1070        state_num = int(current_state_num)+1
1071       
1072        self.state.saved_state['state_num'] = state_num
1073        self.state.state_list[str(state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state)
1074        self.state.state_num = state_num
1075        self._undo_enable()
1076        self._info_bookmark_num(event)
1077       
1078    def _info_bookmark_num(self,event=None):
1079        """
1080        print the bookmark number in info
1081       
1082        : event: popUpMenu event
1083        """
1084        if event == None: return
1085        # get the object
1086        item = self.popUpMenu.FindItemById(event.GetId())
1087        text = item.GetText()
1088        num = text.split(']')[0]
1089        msg = "bookmark num = %s "% num
1090       
1091        wx.PostEvent(self.parent, StatusEvent(status = msg ))
1092       
1093    def _info_state_num(self):
1094        """
1095        print the current state number in info
1096        """
1097        msg = "state num = "
1098        msg += self.state.state_num
1099       
1100        wx.PostEvent(self.parent, StatusEvent(status = msg))
1101                         
1102    def _get_time_stamp(self):
1103        """
1104        return time and date stings
1105        """
1106        # date and time
1107        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
1108        my_time= str(hour)+":"+str(minute)+":"+str(second)
1109        date= str( month)+"/"+str(day)+"/"+str(year)
1110        return my_time, date
1111   
1112    def _undo_enable(self):
1113        """
1114        Enable undo button
1115        """
1116        if not self.button_undo.IsEnabled():
1117            self.button_undo.Enable(True)
1118
1119    def _undo_disable(self):
1120        """
1121        Disable undo button
1122        """
1123        if self.button_undo.IsEnabled():
1124            self.button_undo.Disable()
1125
1126    def _redo_enable(self):
1127        """
1128        Enable redo button
1129        """
1130        if not self.button_redo.IsEnabled():
1131            self.button_redo.Enable(True)
1132
1133    def _redo_disable(self):
1134        """
1135        Disable redo button
1136        """
1137        if self.button_redo.IsEnabled():
1138            self.button_redo.Disable()
1139           
1140    def _on_save_button(self, evt=None): 
1141        """
1142        Save invariant state into a file
1143        """
1144        # Ask the user the location of the file to write to.
1145        path = None
1146        dlg = wx.FileDialog(self, "Choose a file", self._default_save_location, "", "*.inv", wx.SAVE)
1147        if dlg.ShowModal() == wx.ID_OK:
1148            path = dlg.GetPath()
1149            self._default_save_location = os.path.dirname(path)
1150        else:
1151            return None
1152       
1153        dlg.Destroy()
1154       
1155        self._manager.save_file(filepath=path, state=self.state)
1156       
1157    def _show_message(self, mssg='',msg='Warning'):
1158        """
1159        Show warning message when resetting data
1160        """
1161       
1162        mssg += 'Loading a new data set will reset all the work done in this panel. \n\r'
1163        mssg += 'Please make sure to save it first... \n\r'
1164        answer = wx.MessageBox(mssg, msg, wx.CANCEL|wx.OK|wx.ICON_EXCLAMATION)
1165
1166        if answer == wx.OK:
1167            return True
1168        else:
1169            return False
1170
1171       
1172    def _reset_output(self):
1173        """
1174        clear outputs textcrtl
1175        """
1176        self.invariant_total_tcl.Clear()
1177        self.invariant_total_err_tcl.Clear()
1178        self.volume_tcl.Clear()
1179        self.volume_err_tcl.Clear()
1180        self.surface_tcl.Clear()
1181        self.surface_err_tcl.Clear()
1182        #prepare a new container to put result of invariant
1183        self.inv_container = InvariantContainer()
1184
1185   
1186    def _on_context_menu(self,event):
1187       
1188        pos = event.GetPosition()
1189        pos = self.ScreenToClient(pos)
1190       
1191        self.PopupMenu(self.popUpMenu, pos) 
1192     
1193    def _define_structure(self):
1194        """
1195        Define main sizers needed for this panel
1196        """
1197        ## Box sizers must be defined first before defining buttons/textctrls (MAC).
1198        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
1199        #Sizer related to outputs
1200        outputs_box = wx.StaticBox(self, -1, "Outputs")
1201        self.outputs_sizer = wx.StaticBoxSizer(outputs_box, wx.VERTICAL)
1202        self.outputs_sizer.SetMinSize((PANEL_WIDTH,-1))
1203        #Sizer related to data
1204        data_name_box = wx.StaticBox(self, -1, "I(q) Data Source")
1205        self.data_name_boxsizer = wx.StaticBoxSizer(data_name_box, wx.VERTICAL)
1206        self.data_name_boxsizer.SetMinSize((PANEL_WIDTH,-1))
1207        self.hint_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
1208        self.loaded_data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
1209       
1210        self.data_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
1211        #Sizer related to background and scale
1212        self.bkg_scale_sizer = wx.BoxSizer(wx.HORIZONTAL) 
1213        #Sizer related to contrast and porod constant
1214        self.contrast_porod_sizer = wx.BoxSizer(wx.HORIZONTAL) 
1215        #Sizer related to inputs
1216        inputs_box = wx.StaticBox(self, -1, "Customized Inputs")
1217        self.inputs_sizer = wx.StaticBoxSizer(inputs_box, wx.VERTICAL)
1218        #Sizer related to extrapolation
1219        extrapolation_box = wx.StaticBox(self, -1, "Extrapolation")
1220        self.extrapolation_sizer = wx.StaticBoxSizer(extrapolation_box,
1221                                                        wx.VERTICAL)
1222        self.extrapolation_sizer.SetMinSize((PANEL_WIDTH,-1))
1223        self.extrapolation_range_sizer = wx.BoxSizer(wx.HORIZONTAL)
1224        self.extrapolation_low_high_sizer = wx.BoxSizer(wx.HORIZONTAL)
1225        #Sizer related to extrapolation at low q range
1226        low_q_box = wx.StaticBox(self, -1, "Low Q")
1227        self.low_extrapolation_sizer = wx.StaticBoxSizer(low_q_box, wx.VERTICAL)
1228        self.low_q_sizer = wx.GridBagSizer(5,5)
1229        #Sizer related to extrapolation at low q range
1230        high_q_box = wx.StaticBox(self, -1, "High Q")
1231        self.high_extrapolation_sizer = wx.StaticBoxSizer(high_q_box, wx.VERTICAL)
1232        self.high_q_sizer = wx.GridBagSizer(5,5)
1233        #sizer to define outputs
1234        self.volume_surface_sizer = wx.GridBagSizer(5,5)
1235        #Sizer related to invariant output
1236        self.invariant_sizer = wx.GridBagSizer(5, 5)
1237        #Sizer related to button
1238        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1239        #Sizer related to save button
1240        self.save_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1241       
1242    def _layout_data_name(self):
1243        """
1244        Draw widgets related to data's name
1245        """
1246        #Sizer hint
1247        hint_msg = "First open data file from 'File' menu.  Then Highlight and right click on the data plot. \n"
1248        hint_msg += "Finally, select 'Compute Invariant'."
1249        self.hint_msg_txt = wx.StaticText(self, -1, hint_msg) 
1250        self.hint_msg_txt.SetForegroundColour("red")
1251        msg = "Highlight = mouse the mouse's cursor on the data until the plot's color changes to yellow"
1252        self.hint_msg_txt.SetToolTipString(msg)
1253        self.hint_msg_sizer.Add(self.hint_msg_txt)
1254       
1255        self.data_txt = wx.StaticText(self, -1,"Data: ")
1256        self.data_cbbox = wx.ComboBox(self, -1, size=(260,20),
1257                                      style=wx.CB_READONLY)
1258        self.data_cbbox.Disable()
1259        wx.EVT_COMBOBOX(self.data_cbbox ,-1, self.on_select_data) 
1260   
1261        self.loaded_data_name_sizer.AddMany([(self.data_txt, 0,
1262                                               wx.LEFT|wx.RIGHT, 10),
1263                                      (self.data_cbbox, 0, wx.EXPAND)])
1264        #Data range [string]
1265        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ') 
1266        data_min_txt = wx.StaticText(self, -1, 'Min : ') 
1267        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='data_min_tcl')
1268        self.data_min_tcl.SetToolTipString("The minimum value of q range.")
1269        data_max_txt = wx.StaticText(self, -1, 'Max : ') 
1270        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='data_max_tcl') 
1271        self.data_max_tcl.SetToolTipString("The maximum value of q range.")
1272        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10),
1273                                       (data_min_txt, 0, wx.RIGHT, 10),
1274                                       (self.data_min_tcl, 0, wx.RIGHT, 10),
1275                                       (data_max_txt, 0, wx.RIGHT, 10),
1276                                       (self.data_max_tcl, 0, wx.RIGHT, 10)])
1277        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 5),
1278                            (self.loaded_data_name_sizer, 0 , wx.ALL, 10),
1279                                     (self.data_range_sizer, 0 , wx.ALL, 10)])
1280   
1281    def _layout_bkg_scale(self):
1282        """
1283        Draw widgets related to background and scale
1284        """
1285        background_txt = wx.StaticText(self, -1, 'Background : ') 
1286        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='background_tcl') 
1287        wx.EVT_TEXT(self, self.background_tcl.GetId(), self._on_text)
1288        background_hint_txt = "Background"
1289        self.background_tcl.SetToolTipString(background_hint_txt)
1290        background_unit_txt = wx.StaticText(self, -1, '[1/cm]') 
1291        scale_txt = wx.StaticText(self, -1, 'Scale : ') 
1292        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='scale_tcl')
1293        wx.EVT_TEXT(self, self.scale_tcl.GetId(), self._on_text)
1294        scale_hint_txt = "Scale"
1295        self.scale_tcl.SetToolTipString(scale_hint_txt)
1296        self.bkg_scale_sizer.AddMany([(background_txt, 0, wx.LEFT, 10),
1297                                       (self.background_tcl, 0, wx.LEFT, 5),
1298                                       (background_unit_txt, 0, wx.LEFT, 10),
1299                                       (scale_txt, 0, wx.LEFT, 70),
1300                                       (self.scale_tcl, 0, wx.LEFT, 40)])
1301 
1302    def _layout_contrast_porod(self):
1303        """
1304        Draw widgets related to porod constant and contrast
1305        """
1306        contrast_txt = wx.StaticText(self, -1, 'Contrast : ') 
1307        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0,name='contrast_tcl')
1308        wx.EVT_TEXT(self, self.contrast_tcl.GetId(), self._on_text)
1309        contrast_hint_txt = "Contrast"
1310        self.contrast_tcl.SetToolTipString(contrast_hint_txt)
1311        contrast_unit_txt = wx.StaticText(self, -1, '[1/A^(2)]') 
1312        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:') 
1313        self.porod_constant_tcl = InvTextCtrl(self, -1, 
1314                                              size=(_BOX_WIDTH, 20), style=0,name='porod_constant_tcl') 
1315        wx.EVT_TEXT(self, self.porod_constant_tcl.GetId(), self._on_text)
1316        porod_const_hint_txt = "Porod Constant"
1317        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt)
1318        optional_txt = wx.StaticText(self, -1, '(Optional)') 
1319        self.contrast_porod_sizer.AddMany([(contrast_txt, 0, wx.LEFT, 10),
1320                                           (self.contrast_tcl, 0, wx.LEFT, 20),
1321                                           (contrast_unit_txt, 0, wx.LEFT, 10),
1322                                           (porod_const_txt, 0, wx.LEFT, 50),
1323                                       (self.porod_constant_tcl, 0, wx.LEFT, 0),
1324                                       (optional_txt, 0, wx.LEFT, 10)])
1325       
1326    def _enable_fit_power_law_low(self, event=None):
1327        """
1328        Enable and disable the power value editing
1329        """
1330        if event != None: 
1331            self.button_bookmark.Enable(True)
1332            self.button_report.Disable()
1333            print "enable fit==>event!=None"
1334
1335        if self.fix_enable_low.IsEnabled():
1336           
1337            if self.fix_enable_low.GetValue():
1338                self.fit_enable_low.SetValue(False)
1339                self.power_low_tcl.Enable()
1340            else:
1341                self.fit_enable_low.SetValue(True)
1342                self.power_low_tcl.Disable()
1343        self._set_state(event=event)
1344           
1345    def _enable_low_q_section(self, event=None):
1346        """
1347        Disable or enable some button if the user enable low q extrapolation
1348        """
1349        if event != None: 
1350            self.button_bookmark.Enable(True)
1351            self.button_report.Disable()
1352           
1353        if self.enable_low_cbox.GetValue():
1354            self.npts_low_tcl.Enable()
1355            self.fix_enable_low.Enable()
1356            self.fit_enable_low.Enable()
1357            self.guinier.Enable()
1358            self.power_law_low.Enable()
1359
1360        else:
1361            self.npts_low_tcl.Disable()
1362            self.fix_enable_low.Disable()
1363            self.fit_enable_low.Disable()
1364            self.guinier.Disable()
1365            self.power_law_low.Disable()
1366       
1367        self._enable_power_law_low()
1368        self._enable_fit_power_law_low()
1369        self._set_state(event=event)
1370        self.button_calculate.SetFocus()
1371       
1372    def _enable_power_law_low(self, event=None):
1373        """
1374        Enable editing power law section at low q range
1375        """
1376        if event != None: 
1377            self.button_bookmark.Enable(True)
1378            self.button_report.Disable()
1379        if self.guinier.GetValue():
1380            self.power_law_low.SetValue(False)
1381            self.fix_enable_low.Disable()
1382            self.fit_enable_low.Disable()
1383            self.power_low_tcl.Disable()
1384        else:
1385            self.power_law_low.SetValue(True)
1386            self.fix_enable_low.Enable()
1387            self.fit_enable_low.Enable()
1388            self.power_low_tcl.Enable()
1389        self._enable_fit_power_law_low()
1390        self._set_state(event=event)
1391           
1392    def _layout_extrapolation_low(self):
1393        """
1394        Draw widgets related to extrapolation at low q range
1395        """
1396        self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q",name='enable_low_cbox')
1397        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(),
1398                                         self._enable_low_q_section)
1399        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix',
1400                                         (10, 10),style=wx.RB_GROUP,name='fix_enable_low')
1401        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,
1402                                     id=self.fix_enable_low.GetId())
1403        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10),name='fit_enable_low')
1404        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
1405                                        id=self.fit_enable_low.GetId())
1406        self.guinier = wx.RadioButton(self, -1, 'Guinier',
1407                                         (10, 10),style=wx.RB_GROUP, name='guinier')
1408        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,
1409                                     id=self.guinier.GetId())       
1410        self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10),name='power_law_low')
1411        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
1412                                        id=self.power_law_low.GetId())
1413       
1414        npts_low_txt = wx.StaticText(self, -1, 'Npts')
1415        self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='npts_low_tcl')
1416        wx.EVT_TEXT(self, self.npts_low_tcl.GetId(), self._on_text)
1417        msg_hint = "Number of Q points to consider"
1418        msg_hint +="while extrapolating the low-Q region"
1419        self.npts_low_tcl.SetToolTipString(msg_hint)
1420        power_txt = wx.StaticText(self, -1, 'Power')
1421        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='power_low_tcl')
1422        wx.EVT_TEXT(self, self.power_low_tcl.GetId(), self._on_text)
1423       
1424        power_hint_txt = "Exponent to apply to the Power_law function."
1425        self.power_low_tcl.SetToolTipString(power_hint_txt)
1426        iy = 0
1427        ix = 0
1428        self.low_q_sizer.Add(self.enable_low_cbox,(iy, ix),(1,5),
1429                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1430        iy += 1
1431        ix = 0
1432        self.low_q_sizer.Add(npts_low_txt,(iy, ix),(1,1),
1433                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1434        ix += 1
1435        self.low_q_sizer.Add(self.npts_low_tcl, (iy, ix), (1,1),
1436                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1437        iy += 1
1438        ix = 0
1439        self.low_q_sizer.Add(self.guinier,(iy, ix),(1,2),
1440                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1441        iy += 1
1442        ix = 0
1443        self.low_q_sizer.Add(self.power_law_low,(iy, ix),(1,2),
1444                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1445       
1446        # Parameter controls for power law
1447        ix = 1
1448        iy += 1
1449        self.low_q_sizer.Add(self.fix_enable_low,(iy, ix),(1,1),
1450                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1451        ix += 1
1452        self.low_q_sizer.Add(self.fit_enable_low,(iy, ix),(1,1),
1453                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1454        ix = 1
1455        iy += 1
1456        self.low_q_sizer.Add(power_txt,(iy, ix),(1,1),
1457                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1458        ix += 1
1459        self.low_q_sizer.Add(self.power_low_tcl, (iy, ix), (1,1),
1460                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1461        self.low_extrapolation_sizer.AddMany([(self.low_q_sizer, 0,
1462                                                wx.BOTTOM|wx.RIGHT, 15)])
1463       
1464    def _enable_fit_power_law_high(self, event=None):
1465        """
1466        Enable and disable the power value editing
1467        """
1468        if event != None: 
1469            self.button_bookmark.Enable(True)
1470            self.button_report.Disable()
1471        if self.fix_enable_high.IsEnabled():
1472            if self.fix_enable_high.GetValue():
1473                self.fit_enable_high.SetValue(False)
1474                self.power_high_tcl.Enable()
1475            else:
1476                self.fit_enable_high.SetValue(True)
1477                self.power_high_tcl.Disable()
1478        self._set_state(event=event)
1479       
1480    def _enable_high_q_section(self, event=None):
1481        """
1482        Disable or enable some button if the user enable high q extrapolation
1483        """
1484        if event != None: 
1485            self.button_bookmark.Enable(True)
1486            self.button_report.Disable()
1487        if self.enable_high_cbox.GetValue():
1488            self.npts_high_tcl.Enable()
1489            self.power_law_high.Enable()
1490            self.power_high_tcl.Enable()
1491            self.fix_enable_high.Enable()
1492            self.fit_enable_high.Enable()
1493        else:
1494            self.npts_high_tcl.Disable()
1495            self.power_law_high.Disable()
1496            self.power_high_tcl.Disable()
1497            self.fix_enable_high.Disable()
1498            self.fit_enable_high.Disable()
1499        self._enable_fit_power_law_high()
1500        self._set_state(event=event)
1501        self.button_calculate.SetFocus()
1502 
1503    def _layout_extrapolation_high(self):
1504        """
1505        Draw widgets related to extrapolation at high q range
1506        """
1507        self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q", name='enable_high_cbox')
1508        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(),
1509                                         self._enable_high_q_section)
1510        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix',
1511                                         (10, 10),style=wx.RB_GROUP,name='fix_enable_high')
1512        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,
1513                                     id=self.fix_enable_high.GetId())
1514        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10),name='fit_enable_high')     
1515        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
1516                                        id=self.fit_enable_high.GetId())
1517       
1518        self.power_law_high = wx.StaticText(self, -1, 'Power Law')
1519        msg_hint ="Check to extrapolate data at high-Q"
1520        self.power_law_high.SetToolTipString(msg_hint)
1521        npts_high_txt = wx.StaticText(self, -1, 'Npts')
1522        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='npts_high_tcl')
1523        wx.EVT_TEXT(self, self.npts_high_tcl.GetId(), self._on_text)
1524        msg_hint = "Number of Q points to consider"
1525        msg_hint += "while extrapolating the high-Q region"
1526        self.npts_high_tcl.SetToolTipString(msg_hint)
1527        power_txt = wx.StaticText(self, -1, 'Power')
1528        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='power_high_tcl')
1529        wx.EVT_TEXT(self, self.power_high_tcl.GetId(), self._on_text)
1530        power_hint_txt = "Exponent to apply to the Power_law function."
1531        self.power_high_tcl.SetToolTipString(power_hint_txt)
1532        iy = 0
1533        ix = 0
1534        self.high_q_sizer.Add(self.enable_high_cbox,(iy, ix),(1,5),
1535                            wx.TOP|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1536        iy += 1
1537        ix = 0
1538        self.high_q_sizer.Add(npts_high_txt,(iy, ix),(1,1),
1539                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1540        ix += 1
1541        self.high_q_sizer.Add(self.npts_high_tcl, (iy, ix), (1,1),
1542                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1543        iy += 2
1544        ix = 0
1545        self.high_q_sizer.Add(self.power_law_high,(iy, ix),(1,2),
1546                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1547       
1548        # Parameter controls for power law
1549        ix = 1
1550        iy += 1
1551        self.high_q_sizer.Add(self.fix_enable_high,(iy, ix),(1,1),
1552                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1553        ix += 1
1554        self.high_q_sizer.Add(self.fit_enable_high,(iy, ix),(1,1),
1555                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1556        ix = 1
1557        iy += 1
1558        self.high_q_sizer.Add(power_txt,(iy, ix),(1,1),
1559                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1560        ix += 1
1561        self.high_q_sizer.Add(self.power_high_tcl, (iy, ix), (1,1),
1562                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1563        self.high_extrapolation_sizer.AddMany([(self.high_q_sizer, 0, 
1564                                                wx.BOTTOM|wx.RIGHT, 10)])
1565       
1566    def _layout_extrapolation(self):
1567        """
1568        Draw widgets related to extrapolation
1569        """
1570        extra_hint = "Extrapolation Maximum Q Range [1/A]: "
1571        extra_hint_txt = wx.StaticText(self, -1, extra_hint)
1572        #Extrapolation range [string]
1573        extrapolation_min_txt = wx.StaticText(self, -1, 'Min :') 
1574        self.extrapolation_min_tcl = OutputTextCtrl(self, -1, 
1575                                                size=(_BOX_WIDTH, 20), style=0,name='extrapolation_min_tcl')
1576        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM))
1577        self.extrapolation_min_tcl.SetToolTipString("The minimum extrapolated q value.")
1578        extrapolation_max_txt = wx.StaticText(self, -1, 'Max :') 
1579        self.extrapolation_max_tcl = OutputTextCtrl(self, -1,
1580                                                  size=(_BOX_WIDTH, 20), style=0,name='extrapolation_max_tcl') 
1581        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM))
1582        self.extrapolation_max_tcl.SetToolTipString("The maximum extrapolated q value.")
1583        self.extrapolation_range_sizer.AddMany([(extra_hint_txt, 0, wx.LEFT, 10),
1584                                                (extrapolation_min_txt, 0, wx.LEFT, 10),
1585                                                (self.extrapolation_min_tcl,
1586                                                            0, wx.LEFT, 10),
1587                                                (extrapolation_max_txt, 0, wx.LEFT, 10),
1588                                                (self.extrapolation_max_tcl,
1589                                                            0, wx.LEFT, 10),
1590                                                ])
1591        self._layout_extrapolation_low()
1592        self._layout_extrapolation_high()
1593        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer,
1594                                                     0, wx.ALL, 5),
1595                                                   (self.high_extrapolation_sizer,
1596                                                    0, wx.ALL, 5)])
1597        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0,
1598                                            wx.RIGHT, 5),
1599                                        (self.extrapolation_low_high_sizer, 0,
1600                                           wx.ALL, 5)])
1601       
1602    def _layout_volume_surface_sizer(self):
1603        """
1604        Draw widgets related to volume and surface
1605        """
1606        unit_volume = ''
1607        unit_surface = ''
1608        uncertainty = "+/-" 
1609        volume_txt = wx.StaticText(self, -1, 'Volume Fraction      ')
1610        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='volume_tcl')
1611        wx.EVT_TEXT(self, self.volume_tcl.GetId(), self._on_out_text)
1612        self.volume_tcl.SetToolTipString("Volume fraction.")
1613        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='volume_err_tcl')
1614        wx.EVT_TEXT(self, self.volume_err_tcl.GetId(), self._on_out_text)
1615        self.volume_err_tcl.SetToolTipString("Uncertainty on the volume fraction.")
1616        volume_units_txt = wx.StaticText(self, -1, unit_volume)
1617       
1618        surface_txt = wx.StaticText(self, -1, 'Specific Surface')
1619        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='surface_tcl')
1620        wx.EVT_TEXT(self, self.surface_tcl.GetId(), self._on_out_text)
1621        self.surface_tcl.SetToolTipString("Specific surface value.")
1622        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='surface_err_tcl')
1623        wx.EVT_TEXT(self, self.surface_err_tcl.GetId(), self._on_out_text)
1624        self.surface_err_tcl.SetToolTipString("Uncertainty on the specific surface.")
1625        surface_units_txt = wx.StaticText(self, -1, unit_surface)
1626        iy = 0
1627        ix = 0
1628        self.volume_surface_sizer.Add(volume_txt, (iy, ix), (1,1),
1629                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1630        ix += 1
1631        self.volume_surface_sizer.Add(self.volume_tcl, (iy, ix), (1,1),
1632                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1633        ix += 1
1634        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
1635                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
1636        ix += 1
1637        self.volume_surface_sizer.Add(self.volume_err_tcl, (iy, ix), (1,1),
1638                            wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
1639        ix += 1
1640        self.volume_surface_sizer.Add(volume_units_txt, (iy, ix), (1,1),
1641                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1642        iy += 1
1643        ix = 0
1644        self.volume_surface_sizer.Add(surface_txt, (iy, ix), (1,1),
1645                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1646        ix += 1
1647        self.volume_surface_sizer.Add(self.surface_tcl, (iy, ix), (1,1),
1648                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1649        ix += 1
1650        self.volume_surface_sizer.Add(wx.StaticText(self, -1, uncertainty),
1651                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1652        ix += 1
1653        self.volume_surface_sizer.Add(self.surface_err_tcl, (iy, ix), (1,1),
1654                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1655        ix += 1
1656        self.volume_surface_sizer.Add(surface_units_txt, (iy, ix), (1,1),
1657                            wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1658       
1659    def _layout_invariant_sizer(self):
1660        """
1661        Draw widgets related to invariant
1662        """
1663        uncertainty = "+/-" 
1664        unit_invariant = '[1/(cm * A)]'
1665        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total [Q*]')
1666        self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='invariant_total_tcl')
1667        msg_hint = "Total invariant [Q*], including extrapolated regions."
1668        self.invariant_total_tcl.SetToolTipString(msg_hint)
1669        self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='invariant_total_err_tcl')
1670        self.invariant_total_err_tcl.SetToolTipString("Uncertainty on invariant.")
1671        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant)
1672   
1673        #Invariant total
1674        iy = 0
1675        ix = 0
1676        self.invariant_sizer.Add(invariant_total_txt, (iy, ix), (1,1),
1677                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1678        ix += 1
1679        self.invariant_sizer.Add(self.invariant_total_tcl, (iy, ix), (1,1),
1680                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1681        ix += 1
1682        self.invariant_sizer.Add( wx.StaticText(self, -1, uncertainty),
1683                         (iy, ix),(1,1),wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
1684        ix += 1
1685        self.invariant_sizer.Add(self.invariant_total_err_tcl, (iy, ix), (1,1),
1686                             wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1687        ix += 1
1688        self.invariant_sizer.Add(invariant_total_units_txt,(iy, ix), (1,1),
1689                          wx.EXPAND|wx.ADJUST_MINSIZE, 10)
1690 
1691    def _layout_inputs_sizer(self):
1692        """
1693        Draw widgets related to inputs
1694        """
1695        self._layout_bkg_scale()
1696        self._layout_contrast_porod()
1697        self.inputs_sizer.AddMany([(self.bkg_scale_sizer, 0, wx.ALL, 5),
1698                                    (self.contrast_porod_sizer, 0, wx.ALL, 5)])
1699       
1700    def _layout_outputs_sizer(self):
1701        """
1702        Draw widgets related to outputs
1703        """
1704        self._layout_volume_surface_sizer()
1705        self._layout_invariant_sizer()
1706        static_line = wx.StaticLine(self, -1)
1707        self.outputs_sizer.AddMany([(self.volume_surface_sizer, 0, wx.ALL, 10),
1708                                    (static_line, 0, wx.EXPAND, 0),
1709                                    (self.invariant_sizer, 0, wx.ALL, 10)])
1710    def _layout_button(self): 
1711        """
1712        Do the layout for the button widgets
1713        """ 
1714        #compute button
1715        id = wx.NewId()
1716        self.button_calculate = wx.Button(self, id, "Compute", name ='compute_invariant' )
1717        self.button_calculate.SetToolTipString("Compute invariant")
1718        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)   
1719        #detail button
1720        id = wx.NewId()
1721        self.button_details = wx.Button(self, id, "Details?")
1722        self.button_details.SetToolTipString("Details about the results of the computation")
1723        self.Bind(wx.EVT_BUTTON, self.display_details, id=id)
1724        details = "Details on Invariant Total Calculations"
1725        details_txt = wx.StaticText(self, -1, details)
1726        self.button_sizer.AddMany([((50,10), 0 , wx.LEFT,0),
1727                                   (details_txt, 0 , 
1728                                    wx.RIGHT|wx.BOTTOM|wx.TOP, 10),
1729                                   (self.button_details, 0 , wx.ALL, 10),
1730                        (self.button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])#,
1731                                   #(self.button_undo, 0 , wx.ALL, 10),
1732                                   #(self.button_redo, 0 , wx.ALL, 10)])
1733    def _layout_save_button(self): 
1734        """
1735        Do the layout for the save button widgets
1736        """ 
1737        import sans.perspectives.invariant as inv
1738
1739        path = inv.get_data_path(media='media')
1740        self.undo_png = os.path.join(path,"undo.png")
1741        self.redo_png = os.path.join(path,"redo.png")
1742        self.bookmark_png = os.path.join(path,"bookmark.png")
1743        self.report_png = os.path.join(path,"report.png")
1744        self.save_png = os.path.join(path,"save.png")
1745        #undo button
1746        id = wx.NewId()
1747        self.button_undo = wx.BitmapButton(self, id,wx.Bitmap(self.undo_png))#wx.Button(self, id, "Undo",size=(50,20))
1748        self.button_undo.SetToolTipString("Undo")
1749        #self.button_undo.SetBackgroundColour('#c2e6f8')
1750        self.Bind(wx.EVT_BUTTON, self.undo, id=id)
1751        self._undo_disable()
1752        #redo button
1753        id = wx.NewId()
1754        self.button_redo = wx.BitmapButton(self, id,wx.Bitmap(self.redo_png))#wx.Button(self, id, "Redo",size=(50,20))
1755        self.button_redo.SetToolTipString("Redo")
1756        self.Bind(wx.EVT_BUTTON, self.redo, id=id)
1757        self._redo_disable()   
1758        #bookmark button
1759        id = wx.NewId()
1760        self.button_bookmark = wx.BitmapButton(self, id,wx.Bitmap(self.bookmark_png))#wx.Button(self, id, "Undo",size=(50,20))
1761        self.button_bookmark.SetToolTipString("Bookmark: right-click on the panel to retrieve it")
1762        self.Bind(wx.EVT_BUTTON, self._on_bookmark, id=id)
1763        #report button
1764        id = wx.NewId()
1765        self.button_report = wx.BitmapButton(self, id,wx.Bitmap(self.report_png))#wx.Button(self, id, "Redo",size=(50,20))
1766        self.button_report.SetToolTipString("Report the result of the computation")
1767        self.Bind(wx.EVT_BUTTON, self.report, id=id)
1768        #self.button_report.Disable()   
1769        #save button
1770        id = wx.NewId()
1771        self.button_save = wx.BitmapButton(self, id,wx.Bitmap(self.save_png), name ='Save_invariant')#wx.Button(self, id, "Save", name ='Save_invariant' )
1772        self.button_save.SetToolTipString("Save as a file")
1773        self.Bind(wx.EVT_BUTTON, self._on_save_button, id=id)   
1774        self.button_save.Disable() 
1775        self.save_button_sizer.AddMany([((PANEL_WIDTH/2,20), 1 , wx.EXPAND|wx.ADJUST_MINSIZE,0),
1776                                   (self.button_undo, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10),
1777                                   (self.button_redo, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10),
1778                                   (self.button_bookmark, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10),
1779                                   (self.button_report, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10),
1780                                   (self.button_save, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10)])       
1781    def _do_layout(self):
1782        """
1783        Draw window content
1784        """
1785        self._define_structure()
1786        self._layout_data_name()
1787        self._layout_extrapolation()
1788        self._layout_inputs_sizer()
1789        self._layout_outputs_sizer()
1790        self._layout_button()
1791        self._layout_save_button()
1792        self.main_sizer.AddMany([(self.data_name_boxsizer,0, wx.ALL, 10),
1793                                  (self.outputs_sizer, 0,
1794                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
1795                                  (self.button_sizer,0,
1796                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
1797                                 (self.inputs_sizer, 0,
1798                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),
1799                                  (self.extrapolation_sizer, 0,
1800                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),\
1801                                  (self.save_button_sizer,0,
1802                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)])
1803        self.SetSizer(self.main_sizer)
1804        self.SetAutoLayout(True)
1805   
1806class InvariantDialog(wx.Dialog):
1807    """
1808    """
1809    def __init__(self, parent=None, id=1,graph=None,
1810                 data=None, title="Invariant",base=None):
1811        wx.Dialog.__init__(self, parent, id, title, size=(PANEL_WIDTH,
1812                                                             PANEL_HEIGHT))
1813        self.panel = InvariantPanel(self)
1814        self.Centre()
1815        self.Show(True)
1816       
1817class InvariantWindow(wx.Frame):
1818    """
1819    """
1820    def __init__(self, parent=None, id=1,graph=None, 
1821                 data=None, title="Invariant",base=None):
1822       
1823        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100,
1824                                                             PANEL_HEIGHT+100))
1825        from DataLoader.loader import  Loader
1826        self.loader = Loader()
1827        import invariant
1828
1829        data= self.loader.load("C:/ECLPS/workspace/trunk/DataLoader/test/ascii_test_3.txt")
1830        self.panel = InvariantPanel(self)
1831
1832        data.name = data.filename
1833        self.panel.set_current_data(data)
1834        self.Centre()
1835        self.Show(True)
1836       
1837class MyApp(wx.App):
1838    def OnInit(self):
1839        wx.InitAllImageHandlers()
1840        frame = InvariantWindow()
1841        frame.Show(True)
1842        self.SetTopWindow(frame)
1843       
1844        return True
1845     
1846# end of class MyApp
1847
1848if __name__ == "__main__":
1849    app = MyApp(0)
1850    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.