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

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

resized some sizers

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