source: sasview/prview/perspectives/pr/inversion_panel.py @ 8994b6b

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 8994b6b was 75df58b, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on loading for prview

  • Property mode set to 100644
File size: 39.8 KB
RevLine 
[f3d51f6]1#!/usr/bin/env python
2
3# version
4__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
5__revision__ = "$Revision: 1193 $"
6
7import wx
[5d98370]8import os
[ceaf16e]9import sys
10import logging
[9ff861b]11from wx.lib.scrolledpanel import ScrolledPanel
[75df58b]12from sans.guiframe.events import StatusEvent   
13from sans.guiframe.panel_base import PanelBase
[5d98370]14from inversion_state import InversionState
[3e41f43]15from pr_widgets import PrTextCtrl
16from pr_widgets import DataFileTextCtrl
17from pr_widgets import OutputTextCtrl
[f3d51f6]18
19
20
[75df58b]21class InversionControl(ScrolledPanel, PanelBase):
[7116b6e0]22    """
23    """
[f3d51f6]24    window_name = 'pr_control'
25    window_caption = "P(r) control panel"
26    CENTER_PANE = True
27   
28    # Figure of merit parameters [default]
[dfb58f8]29   
30    ## Oscillation parameters (sin function = 1.1)
[f3d51f6]31    oscillation_max = 1.5
32   
[3e41f43]33    def __init__(self, parent, id=-1, plots=None, 
34                 standalone=False, **kwargs):
[7116b6e0]35        """
36        """
[3e41f43]37        ScrolledPanel.__init__(self, parent, id=id, **kwargs)
[75df58b]38        PanelBase.__init__(self)
[9ff861b]39        self.SetupScrolling()
[f3d51f6]40       
41        self.plots = plots
42        self.radio_buttons = {}
[c405c69]43        self.parent = parent
[f3d51f6]44       
45        ## Data file TextCtrl
[a4bd2ac]46        self.data_file  = None
47        self.plot_data  = None
48        self.nfunc_ctl  = None
49        self.alpha_ctl  = None
50        self.dmax_ctl   = None
51        self.time_ctl   = None
52        self.chi2_ctl   = None
53        self.osc_ctl    = None
[f3d51f6]54        self.file_radio = None
55        self.plot_radio = None
[634f1cf]56        self.label_sugg = None
[a4bd2ac]57        self.qmin_ctl   = None
58        self.qmax_ctl   = None
[5d98370]59        self.swidth_ctl = None
60        self.sheight_ctl = None
[a4bd2ac]61       
62        self.rg_ctl     = None
63        self.iq0_ctl    = None
64        self.bck_chk    = None
65        self.bck_ctl    = None
[f3d51f6]66       
[dfb58f8]67        # TextCtrl for fraction of positive P(r)
68        self.pos_ctl = None
69       
70        # TextCtrl for fraction of 1 sigma positive P(r)
71        self.pos_err_ctl = None 
72       
[f3d51f6]73        ## Estimates
74        self.alpha_estimate_ctl = None
[35adaf6]75        self.nterms_estimate_ctl = None
[a00ee4c]76        ## D_max distance explorator
77        self.distance_explorator_ctl = None
[f3d51f6]78        ## Data manager
79        self.manager   = None
[aa4b8379]80        ## Standalone flage
81        self.standalone = standalone
[5d98370]82        ## Default file location for save
83        self._default_save_location = os.getcwd()
[0ccd214]84        # Default width
85        self._default_width = 350
[f3d51f6]86        self._do_layout()
87       
88    def __setattr__(self, name, value):
89        """
[7116b6e0]90        Allow direct hooks to text boxes
[f3d51f6]91        """
[3e41f43]92        if name == 'nfunc':
[5d98370]93            self.nfunc_ctl.SetValue(str(int(value)))
[3e41f43]94        elif name == 'd_max':
[f3d51f6]95            self.dmax_ctl.SetValue(str(value))
[3e41f43]96        elif name == 'alpha':
[f3d51f6]97            self.alpha_ctl.SetValue(str(value))
[3e41f43]98        elif name == 'chi2':
[a4bd2ac]99            self.chi2_ctl.SetValue("%-5.2g" % value)
[3e41f43]100        elif name == 'bck':
[a4bd2ac]101            self.bck_ctl.SetValue("%-5.2g" % value)
[3e41f43]102        elif name == 'q_min':
[a4bd2ac]103            self.qmin_ctl.SetValue("%-5.2g" % value)
[3e41f43]104        elif name == 'q_max':
[a4bd2ac]105            self.qmax_ctl.SetValue("%-5.2g" % value)
[3e41f43]106        elif name == 'elapsed':
[f3d51f6]107            self.time_ctl.SetValue("%-5.2g" % value)
[3e41f43]108        elif name ==' rg':
[a4bd2ac]109            self.rg_ctl.SetValue("%-5.2g" % value)
[3e41f43]110        elif name == 'iq0':
[a4bd2ac]111            self.iq0_ctl.SetValue("%-5.2g" % value)
[3e41f43]112        elif name == 'oscillation':
[f3d51f6]113            self.osc_ctl.SetValue("%-5.2g" % value)
[3e41f43]114        elif name == 'slit_width':
[5d98370]115            self.swidth_ctl.SetValue("%-5.2g" % value)
[3e41f43]116        elif name == 'slit_height':
[5d98370]117            self.sheight_ctl.SetValue("%-5.2g" % value)
[3e41f43]118        elif name == 'positive':
[dfb58f8]119            self.pos_ctl.SetValue("%-5.2g" % value)
[3e41f43]120        elif name == 'pos_err':
[dfb58f8]121            self.pos_err_ctl.SetValue("%-5.2g" % value)
[3e41f43]122        elif name == 'alpha_estimate':
[634f1cf]123            self.alpha_estimate_ctl.SetToolTipString("Click to accept value.")
124            self.alpha_estimate_ctl.Enable(True)
125            self.alpha_estimate_ctl.SetLabel("%-3.1g" % value)
126            #self.alpha_estimate_ctl.Show()
127            #self.label_sugg.Show()
[3e41f43]128        elif name == 'nterms_estimate':
[35adaf6]129            self.nterms_estimate_ctl.SetToolTipString("Click to accept value.")
130            self.nterms_estimate_ctl.Enable(True)
131            self.nterms_estimate_ctl.SetLabel("%-g" % value)
[3e41f43]132        elif name == 'plotname':
[0d88a09]133            self.plot_data.SetValue(str(value))
134            self._on_pars_changed(None)
[3e41f43]135        elif name == 'datafile':
[0d88a09]136            self.plot_data.SetValue(str(value))
137            self._on_pars_changed(None)
[f3d51f6]138        else:
139            wx.Panel.__setattr__(self, name, value)
140       
141    def __getattr__(self, name):
142        """
[7116b6e0]143        Allow direct hooks to text boxes
[f3d51f6]144        """
[3e41f43]145        if name == 'nfunc':
[3fd1ebc]146            try:
147                return int(self.nfunc_ctl.GetValue())
148            except:
149                return -1
[3e41f43]150        elif name == 'd_max':
[3fd1ebc]151            try:
152                return self.dmax_ctl.GetValue()
153            except:
154                return -1.0
[3e41f43]155        elif name == 'alpha':
[3fd1ebc]156            try:
157                return self.alpha_ctl.GetValue()
158            except:
159                return -1.0
[3e41f43]160        elif name == 'chi2':
[3fd1ebc]161            try:
162                return float(self.chi2_ctl.GetValue())
163            except:
[5d98370]164                return None
[3e41f43]165        elif name == 'bck':
[a4bd2ac]166            try:
167                return float(self.bck_ctl.GetValue())
168            except:
[5d98370]169                return None
[3e41f43]170        elif name == 'q_min':
[3fd1ebc]171            try:
172                return float(self.qmin_ctl.GetValue())
173            except:
174                return 0.0
[634f1cf]175        elif name=='q_max':
[3fd1ebc]176            try:
177                return float(self.qmax_ctl.GetValue())
178            except:
179                return 0.0
[3e41f43]180        elif name == 'elapsed':
[3fd1ebc]181            try:
182                return float(self.time_ctl.GetValue())
183            except:
[5d98370]184                return None
[3e41f43]185        elif name == 'rg':
[a4bd2ac]186            try:
187                return float(self.rg_ctl.GetValue())
188            except:
[5d98370]189                return None
[a4bd2ac]190        elif name=='iq0':
191            try:
192                return float(self.iq0_ctl.GetValue())
193            except:
[5d98370]194                return None
[3e41f43]195        elif name == 'oscillation':
[3fd1ebc]196            try:
197                return float(self.osc_ctl.GetValue())
198            except:
[5d98370]199                return None
[3e41f43]200        elif name == 'slit_width':
[5d98370]201            try:
202                return float(self.swidth_ctl.GetValue())
203            except:
204                return None
205        elif name=='slit_height':
206            try:
207                return float(self.sheight_ctl.GetValue())
208            except:
209                return None
[3e41f43]210        elif name == 'pos':
[3fd1ebc]211            try:
212                return float(self.pos_ctl.GetValue())
213            except:
[5d98370]214                return None
[3e41f43]215        elif name == 'pos_err':
[5d98370]216            try:
217                return float(self.pos_err_ctl.GetValue())
218            except:
219                return None
[3e41f43]220        elif name == 'alpha_estimate':
[5d98370]221            try:
222                return float(self.alpha_estimate_ctl.GetLabel())
223            except:
224                return None
[3e41f43]225        elif name == 'nterms_estimate':
[5d98370]226            try:
227                return int(self.nterms_estimate_ctl.GetLabel())
228            except:
229                return None
[3e41f43]230        elif name == 'plotname':
[0d88a09]231            return self.plot_data.GetValue()
[3e41f43]232        elif name == 'datafile':
[0d88a09]233            return self.plot_data.GetValue()
[f3d51f6]234        else:
[a00ee4c]235            return wx.Panel.__getattribute__(self, name)
[f3d51f6]236       
[5d98370]237    def _save_state(self, evt=None):
238        """
[7116b6e0]239        Method used to create a memento of the current state
[5d98370]240           
[7116b6e0]241        :return: state object
[5d98370]242        """
243        # Ask the user the location of the file to write to.
244        path = None
[3e41f43]245        dlg = wx.FileDialog(self, "Choose a file",
246                            self._default_save_location, "", "*.prv", wx.SAVE)
[5d98370]247        if dlg.ShowModal() == wx.ID_OK:
248            path = dlg.GetPath()
249            self._default_save_location = os.path.dirname(path)
[0d88a09]250        else:
251            return None
252       
[5d98370]253        dlg.Destroy()
[b35d3d1]254       
255        state = self.get_state()
256           
257        self.manager.save_data(filepath=path, prstate=state)
258       
259        return state
260   
261    def get_state(self):
262        """
263        Get the current state
264       
265        : return: state object
266        """
[5d98370]267        # Construct the state object   
268        state = InversionState()
269       
270        # Read the panel's parameters
271        flag, alpha, dmax, nfunc, qmin, \
272        qmax, height, width = self._read_pars()
273       
274        state.nfunc = nfunc
275        state.d_max = dmax
276        state.alpha = alpha
277        state.qmin  = qmin
278        state.qmax  = qmax
279        state.width = width
280        state.height = height
281       
282        # Data file
[0d88a09]283        state.file = self.plot_data.GetValue()
[5d98370]284       
285        # Background evaluation checkbox
286        state.estimate_bck = self.bck_chk.IsChecked()
287       
288        # Estimates
289        state.nterms_estimate = self.nterms_estimate
290        state.alpha_estimate = self.alpha_estimate
291       
292        # Read the output values
293        state.chi2    = self.chi2
294        state.elapsed = self.elapsed
295        state.osc     = self.oscillation
296        state.pos     = self.pos
297        state.pos_err = self.pos_err
298        state.rg      = self.rg
299        state.iq0     = self.iq0
300        state.bck     = self.bck
[fde249c]301       
[5d98370]302        return state
303   
304    def set_state(self, state):
305        """
[7116b6e0]306        Set the state of the panel and inversion problem to
307        the state passed as a parameter.
308        Execute the inversion immediately after filling the
309        controls.
310       
311        :param state: InversionState object
[5d98370]312        """
[fde249c]313        if state.nfunc is not None:
314            self.nfunc = state.nfunc
315        if state.d_max is not None:
316            self.d_max = state.d_max
317        if state.alpha is not None:
318            self.alpha = state.alpha
319        if state.qmin is not None:
320            self.q_min  = state.qmin
321        if state.qmax is not None:
322            self.q_max  = state.qmax
323        if state.width is not None:
324            self.slit_width = state.width
325        if state.height is not None:
326            self.slit_height = state.height
[5d98370]327       
328        # Data file
[0d88a09]329        self.plot_data.SetValue(str(state.file))
[5d98370]330   
331        # Background evaluation checkbox
332        self.bck_chk.SetValue(state.estimate_bck)
333       
334        # Estimates
[fde249c]335        if state.nterms_estimate is not None:
336            self.nterms_estimate = state.nterms_estimate
337        if state.alpha_estimate is not None: 
338            self.alpha_estimate = state.alpha_estimate
[5d98370]339   
340       
341        # Read the output values
[fde249c]342        if state.chi2 is not None:
343            self.chi2    = state.chi2
344        if state.elapsed is not None:
345            self.elapsed = state.elapsed
346        if state.osc is not None:
347            self.oscillation = state.osc
348        if state.pos is not None:
349            self.positive = state.pos
350        if state.pos_err is not None:
351            self.pos_err = state.pos_err
352        if state.rg is not None:
353            self.rg      = state.rg
354        if state.iq0 is not None:
355            self.iq0     = state.iq0
356        if state.bck is not None:
357            self.bck     = state.bck
[5d98370]358
[0d88a09]359        # Perform inversion
360        if self.standalone == False:
[fde249c]361            self._on_invert(None)   
[5d98370]362       
[f3d51f6]363    def set_manager(self, manager):
364        self.manager = manager
365       
366    def _do_layout(self):
[4318af7f]367        vbox = wx.GridBagSizer(0,0)
368        iy_vb = 0
[f3d51f6]369
370        # ----- I(q) data -----
[aa4b8379]371        databox = wx.StaticBox(self, -1, "I(q) data source")
[f3d51f6]372       
373        boxsizer1 = wx.StaticBoxSizer(databox, wx.VERTICAL)
[3e41f43]374        boxsizer1.SetMinSize((self._default_width, 50))
375        pars_sizer = wx.GridBagSizer(5, 5)
[0d21ac1]376
[f3d51f6]377        iy = 0
[d2ee6f6]378        self.file_radio = wx.StaticText(self, -1, "Data:")
[3e41f43]379        pars_sizer.Add(self.file_radio, (iy, 0), (1, 1),
380                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[f3d51f6]381       
[9ff861b]382        self.plot_data = DataFileTextCtrl(self, -1, size=(260,20))
383       
[3e41f43]384        pars_sizer.Add(self.plot_data, (iy, 1), (1, 1),
385                       wx.EXPAND|wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 15)
[f3d51f6]386       
[a4bd2ac]387        self.bck_chk = wx.CheckBox(self, -1, "Estimate background level")
[3e41f43]388        hint_msg = "Check box to let the fit estimate "
389        hint_msg += "the constant background level."
390        self.bck_chk.SetToolTipString(hint_msg)
[a4bd2ac]391        self.bck_chk.Bind(wx.EVT_CHECKBOX, self._on_pars_changed)
392        iy += 1
[3e41f43]393        pars_sizer.Add(self.bck_chk, (iy, 0), (1, 2),
394                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[a4bd2ac]395        boxsizer1.Add(pars_sizer, 0, wx.EXPAND) 
[3e41f43]396        vbox.Add(boxsizer1, (iy_vb, 0), (1, 1),
397                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE|wx.TOP, 5)
[a4bd2ac]398       
399        # ----- Add slit parameters -----
[2a92852]400        if True:
[a4bd2ac]401            sbox = wx.StaticBox(self, -1, "Slit parameters")
402            sboxsizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)
[3e41f43]403            sboxsizer.SetMinSize((self._default_width, 20))
[a4bd2ac]404           
[3e41f43]405            sizer_slit = wx.GridBagSizer(5, 5)
[a4bd2ac]406   
[3e41f43]407            label_sheight = wx.StaticText(self, -1, "Height", size=(40, 20))
408            label_swidth = wx.StaticText(self, -1, "Width", size=(40, 20))
[a4bd2ac]409            #label_sunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[4318af7f]410            label_sunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55,20))
[3e41f43]411            self.sheight_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
412                                          size=(60,20))
413            self.swidth_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
414                                         size=(60,20))
415            hint_msg = "Enter slit height in units of Q or leave blank."
416            self.sheight_ctl.SetToolTipString(hint_msg)
417            hint_msg = "Enter slit width in units of Q or leave blank."
418            self.swidth_ctl.SetToolTipString(hint_msg)
[2a92852]419            #self.sheight_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
420            #self.swidth_ctl.Bind(wx.EVT_TEXT,  self._on_pars_changed)
[a4bd2ac]421           
422            iy = 0
[3e41f43]423            sizer_slit.Add(label_sheight,    (iy, 0), (1, 1),
424                           wx.LEFT|wx.EXPAND, 5)
425            sizer_slit.Add(self.sheight_ctl, (iy, 1), (1, 1),
426                           wx.LEFT|wx.EXPAND, 5)
427   
428            sizer_slit.Add(label_swidth,     (iy, 2), (1, 1),
429                           wx.LEFT|wx.EXPAND, 5)
430            sizer_slit.Add(self.swidth_ctl,  (iy, 3), (1, 1),
431                           wx.LEFT|wx.EXPAND, 5)
432            sizer_slit.Add(label_sunits2,    (iy, 4), (1, 1),
433                           wx.LEFT|wx.EXPAND, 5)
[a4bd2ac]434           
435            sboxsizer.Add(sizer_slit, wx.TOP, 15)
[4318af7f]436            iy_vb += 1
[3e41f43]437            vbox.Add(sboxsizer, (iy_vb, 0), (1, 1),
438                     wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[a4bd2ac]439       
[357b79b]440       
441        # ----- Q range -----
442        qbox = wx.StaticBox(self, -1, "Q range")
443        qboxsizer = wx.StaticBoxSizer(qbox, wx.VERTICAL)
[3e41f43]444        qboxsizer.SetMinSize((self._default_width, 20))
[357b79b]445       
[3e41f43]446        sizer_q = wx.GridBagSizer(5, 5)
[357b79b]447
[3e41f43]448        label_qmin = wx.StaticText(self, -1, "Q min", size=(40, 20))
449        label_qmax = wx.StaticText(self, -1, "Q max", size=(40, 20))
[357b79b]450        #label_qunits1 = wx.StaticText(self, -1, "[A^(-1)]")
[3e41f43]451        label_qunits2 = wx.StaticText(self, -1, "[A^(-1)]", size=(55, 20))
452        self.qmin_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
453                                   size=(60,20))
454        self.qmax_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
455                                   size=(60,20))
456        hint_msg = "Select a lower bound for Q or leave blank."
457        self.qmin_ctl.SetToolTipString(hint_msg)
458        hint_msg = "Select an upper bound for Q or leave blank."
459        self.qmax_ctl.SetToolTipString(hint_msg)
[357b79b]460        self.qmin_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
461        self.qmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
462       
463        iy = 0
[3e41f43]464        sizer_q.Add(label_qmin,    (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 5)
465        sizer_q.Add(self.qmin_ctl, (iy, 1), (1, 1), wx.LEFT|wx.EXPAND, 5)
[357b79b]466        #sizer_q.Add(label_qunits1, (iy,2), (1,1), wx.LEFT|wx.EXPAND, 15)
[3e41f43]467        sizer_q.Add(label_qmax,    (iy, 2), (1, 1), wx.LEFT|wx.EXPAND, 5)
468        sizer_q.Add(self.qmax_ctl, (iy, 3), (1, 1), wx.LEFT|wx.EXPAND, 5)
469        sizer_q.Add(label_qunits2, (iy, 4), (1, 1), wx.LEFT|wx.EXPAND, 5)
[357b79b]470        qboxsizer.Add(sizer_q, wx.TOP, 15)
[4318af7f]471
472        iy_vb += 1
[3e41f43]473        vbox.Add(qboxsizer, (iy_vb,0), (1,1),
474                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
475   
[f3d51f6]476        # ----- Parameters -----
477        parsbox = wx.StaticBox(self, -1, "Parameters")
478        boxsizer2 = wx.StaticBoxSizer(parsbox, wx.VERTICAL)
[0ccd214]479        boxsizer2.SetMinSize((self._default_width,50))
[f3d51f6]480       
[3e41f43]481        explanation  = "P(r) is found by fitting a set of base functions"
482        explanation += " to I(Q). The minimization involves"
483        explanation += " a regularization term to ensure a smooth P(r)."
484        explanation += " The regularization constant gives the size of that " 
485        explanation += "term. The suggested value is the value above which the"
486        explanation += " output P(r) will have only one peak."
[0ccd214]487        label_explain = wx.StaticText(self, -1, explanation, size=(280,120))
[32dffae4]488        boxsizer2.Add(label_explain,  wx.LEFT|wx.BOTTOM, 5)
489       
490       
491       
[f3d51f6]492        label_nfunc = wx.StaticText(self, -1, "Number of terms")
[3e41f43]493        label_nfunc.SetMinSize((120, 20))
[f3d51f6]494        label_alpha = wx.StaticText(self, -1, "Regularization constant")
495        label_dmax  = wx.StaticText(self, -1, "Max distance [A]")
[634f1cf]496        self.label_sugg  = wx.StaticText(self, -1, "Suggested value")
497        #self.label_sugg.Hide()
[f3d51f6]498       
[3e41f43]499        self.nfunc_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
500                                    size=(60,20))
[32dffae4]501        self.nfunc_ctl.SetToolTipString("Number of terms in the expansion.")
[3e41f43]502        self.alpha_ctl = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
503                                    size=(60,20))
504        hint_msg = "Control parameter for the size of the regularization term."
505        self.alpha_ctl.SetToolTipString(hint_msg)
506        self.dmax_ctl  = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER,
507                                    size=(60,20))
508        hint_msg = "Maximum distance between any two points in the system."
509        self.dmax_ctl.SetToolTipString(hint_msg)
[634f1cf]510        id = wx.NewId()
511        self.alpha_estimate_ctl  = wx.Button(self, id, "")
512        #self.alpha_estimate_ctl.Hide()
513        self.Bind(wx.EVT_BUTTON, self._on_accept_alpha, id = id)   
[f3d51f6]514        self.alpha_estimate_ctl.Enable(False)
[634f1cf]515        #self.alpha_estimate_ctl.SetBackgroundColour('#ffdf85')
516        #self.alpha_estimate_ctl.SetBackgroundColour(self.GetBackgroundColour())
517        self.alpha_estimate_ctl.SetToolTipString("Waiting for estimate...")
[f3d51f6]518       
[35adaf6]519        id = wx.NewId()
520        self.nterms_estimate_ctl  = wx.Button(self, id, "")
521        #self.nterms_estimate_ctl.Hide()
522        self.Bind(wx.EVT_BUTTON, self._on_accept_nterms, id = id)   
523        self.nterms_estimate_ctl.Enable(False)
[3e41f43]524     
[35adaf6]525        self.nterms_estimate_ctl.SetToolTipString("Waiting for estimate...")
526       
[d6113849]527        self.nfunc_ctl.Bind(wx.EVT_TEXT, self._read_pars)
[a4bd2ac]528        self.alpha_ctl.Bind(wx.EVT_TEXT, self._read_pars)
529        self.dmax_ctl.Bind(wx.EVT_TEXT, self._on_pars_changed)
530       
[a00ee4c]531        # Distance explorator
532        id = wx.NewId()
533        self.distance_explorator_ctl = wx.Button(self, id, "Explore")
534        self.Bind(wx.EVT_BUTTON, self._on_explore, id = id)           
[a4bd2ac]535       
536       
[f3d51f6]537        sizer_params = wx.GridBagSizer(5,5)
538
539        iy = 0
[3e41f43]540        sizer_params.Add(self.label_sugg, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]541        iy += 1
[3e41f43]542        sizer_params.Add(label_nfunc,      (iy, 0), (1, 1), wx.LEFT, 15)
543        sizer_params.Add(self.nfunc_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
544        sizer_params.Add(self.nterms_estimate_ctl, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]545        iy += 1
[3e41f43]546        sizer_params.Add(label_alpha,      (iy, 0), (1, 1), wx.LEFT, 15)
547        sizer_params.Add(self.alpha_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
548        sizer_params.Add(self.alpha_estimate_ctl, (iy, 2), (1, 1), wx.LEFT, 15)
[f3d51f6]549        iy += 1
[3e41f43]550        sizer_params.Add(label_dmax, (iy, 0), (1, 1), wx.LEFT, 15)
551        sizer_params.Add(self.dmax_ctl,   (iy, 1), (1, 1), wx.RIGHT, 0)
552        sizer_params.Add(self.distance_explorator_ctl, (iy, 2),
553                         (1, 1), wx.LEFT, 15)
[f3d51f6]554
555        boxsizer2.Add(sizer_params, 0)
[634f1cf]556       
[4318af7f]557        iy_vb += 1
[3e41f43]558        vbox.Add(boxsizer2, (iy_vb, 0), (1, 1),
559                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[f3d51f6]560
[634f1cf]561
[f3d51f6]562        # ----- Results -----
563        resbox = wx.StaticBox(self, -1, "Outputs")
564        ressizer = wx.StaticBoxSizer(resbox, wx.VERTICAL)
[3e41f43]565        ressizer.SetMinSize((self._default_width, 50))
[f3d51f6]566       
[a4bd2ac]567        label_rg       = wx.StaticText(self, -1, "Rg")
568        label_rg_unit  = wx.StaticText(self, -1, "[A]")
569        label_iq0      = wx.StaticText(self, -1, "I(Q=0)")
570        label_iq0_unit = wx.StaticText(self, -1, "[A^(-1)]")
571        label_bck      = wx.StaticText(self, -1, "Background")
572        label_bck_unit = wx.StaticText(self, -1, "[A^(-1)]")
[9ff861b]573        self.rg_ctl    = OutputTextCtrl(self, -1, size=(60,20))
[3e41f43]574        hint_msg = "Radius of gyration for the computed P(r)."
575        self.rg_ctl.SetToolTipString(hint_msg)
[75df58b]576        self.iq0_ctl   = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]577        hint_msg = "Scattering intensity at Q=0 for the computed P(r)."
578        self.iq0_ctl.SetToolTipString(hint_msg)
[75df58b]579        self.bck_ctl   = OutputTextCtrl(self, -1, size=(60, 20))
[a4bd2ac]580        self.bck_ctl.SetToolTipString("Value of estimated constant background.")
581       
[f3d51f6]582        label_time = wx.StaticText(self, -1, "Computation time")
583        label_time_unit = wx.StaticText(self, -1, "secs")
584        label_time.SetMinSize((120,20))
585        label_chi2 = wx.StaticText(self, -1, "Chi2/dof")
586        label_osc = wx.StaticText(self, -1, "Oscillations")
[dfb58f8]587        label_pos = wx.StaticText(self, -1, "Positive fraction")
588        label_pos_err = wx.StaticText(self, -1, "1-sigma positive fraction")
[f3d51f6]589       
[75df58b]590        self.time_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]591        hint_msg = "Computation time for the last inversion, in seconds."
592        self.time_ctl.SetToolTipString(hint_msg)
[32dffae4]593       
[75df58b]594        self.chi2_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[32dffae4]595        self.chi2_ctl.SetToolTipString("Chi^2 over degrees of freedom.")
596       
[dfb58f8]597        # Oscillation parameter
[75df58b]598        self.osc_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]599        hint_msg = "Oscillation parameter. P(r) for a sphere has an "
600        hint_msg += " oscillation parameter of 1.1."
601        self.osc_ctl.SetToolTipString(hint_msg)
[f3d51f6]602       
[dfb58f8]603        # Positive fraction figure of merit
[75df58b]604        self.pos_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]605        hint_msg = "Fraction of P(r) that is positive. "
606        hint_msg += "Theoretically, P(r) is defined positive."
607        self.pos_ctl.SetToolTipString(hint_msg)
[dfb58f8]608       
609        # 1-simga positive fraction figure of merit
[75df58b]610        self.pos_err_ctl = OutputTextCtrl(self, -1, size=(60, 20))
[3e41f43]611        message  = "Fraction of P(r) that is at least 1 standard deviation"
612        message += " greater than zero.\n"
613        message += "This figure of merit tells you about the size of the "
614        message += "P(r) errors.\n"
615        message += "If it is close to 1 and the other figures of merit are bad,"
616        message += " consider changing the maximum distance."
[dfb58f8]617        self.pos_err_ctl.SetToolTipString(message)
618       
[3e41f43]619        sizer_res = wx.GridBagSizer(5, 5)
[f3d51f6]620
621        iy = 0
[3e41f43]622        sizer_res.Add(label_rg, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
623        sizer_res.Add(self.rg_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
624        sizer_res.Add(label_rg_unit,   (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]625        iy += 1
[3e41f43]626        sizer_res.Add(label_iq0, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
627        sizer_res.Add(self.iq0_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
628        sizer_res.Add(label_iq0_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]629        iy += 1
[3e41f43]630        sizer_res.Add(label_bck, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
631        sizer_res.Add(self.bck_ctl, (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
632        sizer_res.Add(label_bck_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[a4bd2ac]633        iy += 1
[3e41f43]634        sizer_res.Add(label_time, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
635        sizer_res.Add(self.time_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
636        sizer_res.Add(label_time_unit, (iy, 2), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]637        iy += 1
[3e41f43]638        sizer_res.Add(label_chi2, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
639        sizer_res.Add(self.chi2_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]640        iy += 1
[3e41f43]641        sizer_res.Add(label_osc, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
642        sizer_res.Add(self.osc_ctl,   (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[f3d51f6]643
[dfb58f8]644        iy += 1
[3e41f43]645        sizer_res.Add(label_pos, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
646        sizer_res.Add(self.pos_ctl, (iy, 1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[dfb58f8]647
648        iy += 1
[3e41f43]649        sizer_res.Add(label_pos_err, (iy, 0), (1, 1), wx.LEFT|wx.EXPAND, 15)
650        sizer_res.Add(self.pos_err_ctl,  (iy,1), (1, 1), wx.RIGHT|wx.EXPAND, 15)
[dfb58f8]651
[f3d51f6]652        ressizer.Add(sizer_res, 0)
[4318af7f]653        iy_vb += 1
[3e41f43]654        vbox.Add(ressizer, (iy_vb, 0), (1, 1),
655                 wx.LEFT|wx.RIGHT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
[f3d51f6]656
657        # ----- Buttons -----
658        id = wx.NewId()
659        button_OK = wx.Button(self, id, "Compute")
[32dffae4]660        button_OK.SetToolTipString("Perform P(r) inversion.")
[f3d51f6]661        self.Bind(wx.EVT_BUTTON, self._on_invert, id = id)   
[b659551]662       
663        id = wx.NewId()
664        button_Reset = wx.Button(self, id, "Reset")
665        button_Reset.SetToolTipString("Reset inversion parameters to default.")
666        self.Bind(wx.EVT_BUTTON, self._on_reset, id = id)   
[f3d51f6]667        #button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
668       
[5d98370]669        id = wx.NewId()
670        button_Save = wx.Button(self, id, "Save")
671        button_Save.SetToolTipString("Save the current P(r) work to file.")
[3e41f43]672        self.Bind(wx.EVT_BUTTON, self._save_state, id=id)   
[5d98370]673       
[f3d51f6]674        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
675        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[5d98370]676        sizer_button.Add(button_Save, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[b659551]677        sizer_button.Add(button_Reset, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[f3d51f6]678        sizer_button.Add(button_OK, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
[3e41f43]679       
[4318af7f]680        iy_vb += 1
[3e41f43]681        vbox.Add(sizer_button, (iy_vb, 0), (1, 1),
682                 wx.EXPAND|wx.BOTTOM|wx.TOP|wx.RIGHT, 10)
[f3d51f6]683
[a00ee4c]684        self.Bind(wx.EVT_TEXT_ENTER, self._on_invert)
[f3d51f6]685
686        self.SetSizer(vbox)
687       
[634f1cf]688    def _on_accept_alpha(self, evt):
689        """
[7116b6e0]690        User has accepted the estimated alpha,
691        set it as part of the input parameters
[634f1cf]692        """
693        try:
694            alpha = self.alpha_estimate_ctl.GetLabel()
695            tmp = float(alpha)
696            self.alpha_ctl.SetValue(alpha)
697        except:
698            # No estimate or bad estimate, either do nothing
[3e41f43]699            #import sys
[634f1cf]700            print "InversionControl._on_accept_alpha: %s" % sys.exc_value
701            pass
[35adaf6]702   
703    def _on_accept_nterms(self, evt):
704        """
[7116b6e0]705        User has accepted the estimated number of terms,
706        set it as part of the input parameters
[35adaf6]707        """
708        try:
709            nterms = self.nterms_estimate_ctl.GetLabel()
710            tmp = float(nterms)
711            self.nfunc_ctl.SetValue(nterms)
712        except:
713            # No estimate or bad estimate, either do nothing
714            import sys
715            print "InversionControl._on_accept_nterms: %s" % sys.exc_value
716            pass
[634f1cf]717       
[b659551]718    def _on_reset(self, evt):
719        """
[7116b6e0]720        Resets inversion parameters
[b659551]721        """
722        self.nfunc = self.manager.DEFAULT_NFUNC
723        self.d_max = self.manager.DEFAULT_DMAX
724        self.alpha = self.manager.DEFAULT_ALPHA
725        self.qmin_ctl.SetValue("")
726        self.qmax_ctl.SetValue("")
727        self.time_ctl.SetValue("")
[a4bd2ac]728        self.rg_ctl.SetValue("")
729        self.iq0_ctl.SetValue("")
730        self.bck_ctl.SetValue("")
[b659551]731        self.chi2_ctl.SetValue("")
732        self.osc_ctl.SetValue("")
733        self.pos_ctl.SetValue("")
734        self.pos_err_ctl.SetValue("")
735        self.alpha_estimate_ctl.Enable(False)
736        self.alpha_estimate_ctl.SetLabel("")
[35adaf6]737        self.nterms_estimate_ctl.Enable(False)
738        self.nterms_estimate_ctl.SetLabel("")
[b659551]739        self._on_pars_changed()
[634f1cf]740       
[b659551]741    def _on_pars_changed(self, evt=None):
[f3d51f6]742        """
[7116b6e0]743        Called when an input parameter has changed
744        We will estimate the alpha parameter behind the
745        scenes.
[f3d51f6]746        """
[2a92852]747        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]748        has_bck = self.bck_chk.IsChecked()
[f3d51f6]749       
750        # If the pars are valid, estimate alpha
751        if flag:
[2a92852]752            self.nterms_estimate_ctl.Enable(False)
753            self.alpha_estimate_ctl.Enable(False)
754           
[0d88a09]755            dataset = self.plot_data.GetValue()
756            self.manager.estimate_plot_inversion(alpha=alpha, nfunc=nfunc, 
757                                                 d_max=dmax,
758                                                 q_min=qmin, q_max=qmax,
759                                                 bck=has_bck, 
760                                                 height=height,
761                                                 width=width)
[f3d51f6]762       
[7116b6e0]763    def _read_pars(self, evt=None):
764        """
765        """   
[f3d51f6]766        alpha = 0
767        nfunc = 5
768        dmax  = 120
[3fd1ebc]769        qmin  = 0
770        qmax  = 0
[2a92852]771        height = 0
772        width  = 0
[f3d51f6]773        flag = True
[2a92852]774        # Read slit height
775        try:
776            height_str = self.sheight_ctl.GetValue()
[3e41f43]777            if len(height_str.lstrip().rstrip()) == 0:
[2a92852]778                height = 0
779            else:
780                height = float(height_str)
781                self.sheight_ctl.SetBackgroundColour(wx.WHITE)
782                self.sheight_ctl.Refresh()
783        except:
784            flag = False
785            self.sheight_ctl.SetBackgroundColour("pink")
786            self.sheight_ctl.Refresh()
787           
788        # Read slit width
789        try:
790            width_str = self.swidth_ctl.GetValue()
791            if len(width_str.lstrip().rstrip())==0:
792                width = 0
793            else:
794                width = float(width_str)
795                self.swidth_ctl.SetBackgroundColour(wx.WHITE)
796                self.swidth_ctl.Refresh()
797        except:
798            flag = False
799            self.swidth_ctl.SetBackgroundColour("pink")
800            self.swidth_ctl.Refresh()
801       
[f3d51f6]802        # Read alpha
803        try:
804            alpha = float(self.alpha_ctl.GetValue())
805            self.alpha_ctl.SetBackgroundColour(wx.WHITE)
806            self.alpha_ctl.Refresh()
807        except:
808            flag = False
809            self.alpha_ctl.SetBackgroundColour("pink")
810            self.alpha_ctl.Refresh()
811       
812        # Read d_max   
813        try:
814            dmax = float(self.dmax_ctl.GetValue())
815            self.dmax_ctl.SetBackgroundColour(wx.WHITE)
816            self.dmax_ctl.Refresh()
817        except:
818            flag = False
819            self.dmax_ctl.SetBackgroundColour("pink")
820            self.dmax_ctl.Refresh()
821           
822        # Read nfunc
823        try:
824            nfunc = int(self.nfunc_ctl.GetValue())
[b659551]825            npts = self.manager.get_npts()
[3e41f43]826            if npts > 0 and nfunc > npts:
827                message = "Number of function terms should be smaller "
828                message += "than the number of points"
[0d21ac1]829                wx.PostEvent(self.manager.parent, StatusEvent(status=message))
[b659551]830                raise ValueError, message
[f3d51f6]831            self.nfunc_ctl.SetBackgroundColour(wx.WHITE)
832            self.nfunc_ctl.Refresh()
833        except:
834            flag = False
835            self.nfunc_ctl.SetBackgroundColour("pink")
836            self.nfunc_ctl.Refresh()
837       
[634f1cf]838        # Read qmin
839        try:
840            qmin_str = self.qmin_ctl.GetValue()
[3e41f43]841            if len(qmin_str.lstrip().rstrip()) == 0:
[634f1cf]842                qmin = None
843            else:
844                qmin = float(qmin_str)
845                self.qmin_ctl.SetBackgroundColour(wx.WHITE)
846                self.qmin_ctl.Refresh()
847        except:
848            flag = False
849            self.qmin_ctl.SetBackgroundColour("pink")
850            self.qmin_ctl.Refresh()
851       
852        # Read qmax
853        try:
854            qmax_str = self.qmax_ctl.GetValue()
[3e41f43]855            if len(qmax_str.lstrip().rstrip()) == 0:
[634f1cf]856                qmax = None
857            else:
858                qmax = float(qmax_str)
859                self.qmax_ctl.SetBackgroundColour(wx.WHITE)
860                self.qmax_ctl.Refresh()
861        except:
862            flag = False
863            self.qmax_ctl.SetBackgroundColour("pink")
864            self.qmax_ctl.Refresh()
865       
[2a92852]866        return flag, alpha, dmax, nfunc, qmin, qmax, height, width
[f3d51f6]867   
[a00ee4c]868    def _on_explore(self, evt):
869        """
[7116b6e0]870        Invoke the d_max exploration dialog
[a00ee4c]871        """
872        from explore_dialog import ExploreDialog
873        if self.manager._last_pr is not None:
874            pr = self.manager._create_plot_pr()
875            dialog = ExploreDialog(pr, 10, None, -1, "")
876            dialog.ShowModal()
877        else:
878            message = "No data to analyze. Please load a data set to proceed."
879            wx.PostEvent(self.manager.parent, StatusEvent(status=message))
880           
[f3d51f6]881    def _on_invert(self, evt):
882        """
[7116b6e0]883        Perform inversion
884       
885        :param silent: when True, there will be no output for the user
886       
[f3d51f6]887        """
888        # Get the data from the form
889        # Push it to the manager
890       
[2a92852]891        flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars()
[a4bd2ac]892        has_bck = self.bck_chk.IsChecked()
[f3d51f6]893       
894        if flag:
[0d88a09]895            dataset = self.plot_data.GetValue()
[9bc4ed23]896            if dataset==None or len(dataset.strip())==0:
[3e41f43]897                message = "No data to invert. Select a data set before"
898                message += " proceeding with P(r) inversion."
[0d88a09]899                wx.PostEvent(self.manager.parent, StatusEvent(status=message))
[f3d51f6]900            else:
[0d88a09]901                self.manager.setup_plot_inversion(alpha=alpha, nfunc=nfunc, 
902                                                  d_max=dmax,
903                                                  q_min=qmin, q_max=qmax,
904                                                  bck=has_bck,
905                                                  height=height,
906                                                  width=width)
[f3d51f6]907        else:
[3e41f43]908            message = "The P(r) form contains invalid values: "
909            message += "please submit it again."
[f3d51f6]910            wx.PostEvent(self.parent, StatusEvent(status=message))
911       
[75df58b]912    def _change_file(self, evt=None, filepath=None, data=None):
[f3d51f6]913        """
[7116b6e0]914        Choose a new input file for I(q)
[f3d51f6]915        """
[75df58b]916        if not self.manager is None:
917            self.plot_data.SetValue(str(data.name))
918            try:
919                self.manager.show_data(data=data, reset=True)
920                self._on_pars_changed(None)
921                self._on_invert(None)
922            except:
923                msg = "InversionControl._change_file: %s" % sys.exc_value
924                logging.error(msg)                   
[119a11d]925
926class HelpDialog(wx.Dialog):
[7116b6e0]927    """
928    """
[119a11d]929    def __init__(self, parent, id):
[7116b6e0]930        """
931        """
[119a11d]932        from sans.pr.invertor import help
[fc4ab6e]933        wx.Dialog.__init__(self, parent, id, size=(400, 420))
[119a11d]934        self.SetTitle("P(r) help") 
935       
936
937        vbox = wx.BoxSizer(wx.VERTICAL)
938
939        explanation = help()
940           
[75df58b]941        label_explain = wx.StaticText(self, -1, explanation, size=(350, 320))
[119a11d]942           
943        vbox.Add(label_explain, 0, wx.ALL|wx.EXPAND, 15)
944
945
946        static_line = wx.StaticLine(self, -1)
947        vbox.Add(static_line, 0, wx.EXPAND, 0)
948       
949        button_OK = wx.Button(self, wx.ID_OK, "OK")
950        #button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
951       
952        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
953        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
954        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[3e41f43]955       
[119a11d]956        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
957
958        self.SetSizer(vbox)
959        self.SetAutoLayout(True)
960       
961        self.Layout()
962        self.Centre()
963
[b659551]964class PrDistDialog(wx.Dialog):
965    """
[7116b6e0]966    Property dialog to let the user change the number
967    of points on the P(r) plot.
[b659551]968    """
969    def __init__(self, parent, id):
970        from sans.pr.invertor import help
971        wx.Dialog.__init__(self, parent, id, size=(250, 120))
972        self.SetTitle("P(r) distribution") 
973       
974
975        vbox = wx.BoxSizer(wx.VERTICAL)
976       
977        label_npts = wx.StaticText(self, -1, "Number of points")
[75df58b]978        self.npts_ctl = PrTextCtrl(self, -1, size=(100, 20))
[b659551]979                 
[75df58b]980        pars_sizer = wx.GridBagSizer(5, 5)
[b659551]981        iy = 0
[75df58b]982        pars_sizer.Add(label_npts, (iy, 0), (1, 1), wx.LEFT, 15)
983        pars_sizer.Add(self.npts_ctl, (iy, 1), (1, 1), wx.RIGHT, 0)
[b659551]984       
985        vbox.Add(pars_sizer, 0, wx.ALL|wx.EXPAND, 15)
986
987        static_line = wx.StaticLine(self, -1)
988        vbox.Add(static_line, 0, wx.EXPAND, 0)
989       
990        button_OK = wx.Button(self, wx.ID_OK, "OK")
991        self.Bind(wx.EVT_BUTTON, self._checkValues, button_OK)
992        button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
993       
994        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
995        sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
996        sizer_button.Add(button_OK, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[3e41f43]997        sizer_button.Add(button_Cancel, 0,
998                         wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)       
[b659551]999        vbox.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1000
1001        self.SetSizer(vbox)
1002        self.SetAutoLayout(True)
1003       
1004        self.Layout()
1005        self.Centre()
1006
1007    def _checkValues(self, event):
1008        """
[7116b6e0]1009        Check the dialog content.
[b659551]1010        """
1011        flag = True
1012        try:
1013            int(self.npts_ctl.GetValue())
1014            self.npts_ctl.SetBackgroundColour(wx.WHITE)
1015            self.npts_ctl.Refresh()
1016        except:
1017            flag = False
1018            self.npts_ctl.SetBackgroundColour("pink")
1019            self.npts_ctl.Refresh()
1020        if flag:
1021            event.Skip(True)
1022
1023    def get_content(self):
1024        """
[7116b6e0]1025        Return the content of the dialog.
1026        At this point the values have already been
1027        checked.
[b659551]1028        """
1029        value = int(self.npts_ctl.GetValue())
1030        return value
1031   
1032    def set_content(self, npts):
1033        """
[7116b6e0]1034        Initialize the content of the dialog.
[b659551]1035        """
1036        self.npts_ctl.SetValue("%i" % npts)
1037
[f3d51f6]1038##### testing code ############################################################
[7116b6e0]1039"""
1040Example: ::
1041
[f3d51f6]1042class TestPlot:
1043    def __init__(self, text):
1044        self.name = text
1045   
1046class MyApp(wx.App):
1047    def OnInit(self):
1048        wx.InitAllImageHandlers()
[b659551]1049        dialog = PrDistDialog(None, -1)
[f3d51f6]1050        if dialog.ShowModal() == wx.ID_OK:
[119a11d]1051            pass
[f3d51f6]1052        dialog.Destroy()
1053       
1054        return 1
1055
1056# end of class MyApp
1057
1058if __name__ == "__main__":
1059    app = MyApp(0)
1060    app.MainLoop()
1061   
[7116b6e0]1062"""
[f3d51f6]1063##### end of testing code #####################################################   
Note: See TracBrowser for help on using the repository browser.