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

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

Added reset button, added option to change number of points on the P(r) plot, fixed minor problems with displaying error bars.

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