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

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

all scrollwindows: unfocus child when scrolling: wx2.9 bug fix

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