source: sasview/invariantview/perspectives/invariant/invariant_panel.py @ 8897d66

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

removed buggy line

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