source: sasview/invariantview/src/sans/perspectives/invariant/invariant_panel.py @ a1fa589

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

removed a critical warning

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