source: sasview/prview/perspectives/pr/inversion_panel.py @ 3658abed

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 3658abed was 3e41f43, checked in by Gervaise Alina <gervyh@…>, 14 years ago

make pr plugin inheriting from pluginbase in guiframe

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