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

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 b90decd was 0ccd214, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

prview: changed default sizes of panel objects

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