source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ aebc4cc

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

added plot in html window

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