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

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

fixed a problem of not updating input_list properly when a new inv file is loaded

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