source: sasview/prview/perspectives/pr/inversion_panel.py @ 3fd1ebc

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 3fd1ebc was 3fd1ebc, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Better behavior of "compute" context menu item

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