source: sasview/prview/perspectives/pr/inversion_panel.py @ a94c4e1

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 a94c4e1 was f5038c06, checked in by Gervaise Alina <gervyh@…>, 14 years ago

reverse code

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