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

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

changed to setvalue from setlabel for qmin qmax tcls (MAC bug)

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