source: sasview/src/sas/sasgui/plottools/fitDialog.py @ d7bb526

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 d7bb526 was d7bb526, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 8 years ago

Refactored plottools into sasgui

  • Property mode set to 100644
File size: 27.4 KB
RevLine 
[a9d5684]1import wx
2from plottables import Theory1D
3import math
4import numpy
5import fittings
6import transform
7import sys
8
[2df0b74]9# Linear fit panel size
[a9d5684]10if sys.platform.count("win32") > 0:
11    FONT_VARIANT = 0
12    PNL_WIDTH = 450
13    PNL_HEIGHT = 500
14else:
15    FONT_VARIANT = 1
16    PNL_WIDTH = 500
17    PNL_HEIGHT = 500
[2df0b74]18RG_ON = True
19
[a9d5684]20def format_number(value, high=False):
21    """
22    Return a float in a standardized, human-readable formatted string
23    """
24    try:
25        value = float(value)
26    except:
27        output = "NaN"
28        return output.lstrip().rstrip()
[2df0b74]29
[a9d5684]30    if high:
31        output = "%-6.4g" % value
[2df0b74]32
[a9d5684]33    else:
34        output = "%-5.3g" % value
35    return output.lstrip().rstrip()
36
37
38class LinearFit(wx.Dialog):
39    def __init__(self, parent, plottable, push_data, transform, title):
40        """
41        Dialog window pops- up when select Linear fit on Context menu
42        Displays fitting parameters
43        """
[2df0b74]44        wx.Dialog.__init__(self, parent, title=title,
[a9d5684]45                           size=(PNL_WIDTH, 350))
46        self.parent = parent
47        self.transform = transform
[2df0b74]48        # Font
[a9d5684]49        self.SetWindowVariant(variant=FONT_VARIANT)
50        # Registered owner for close event
51        self._registered_close = None
[2df0b74]52
53        # dialog panel self call function to plot the fitting function
[a9d5684]54        self.push_data = push_data
[2df0b74]55        # dialog self plottable
[a9d5684]56        self.plottable = plottable
57        self.rg_on = False
58        # Receive transformations of x and y
[2df0b74]59        self.xLabel, self.yLabel, self.Avalue, self.Bvalue, \
[a9d5684]60               self.ErrAvalue, self.ErrBvalue, self.Chivalue = self.transform()
[2df0b74]61
62        # Dialog interface
63        vbox = wx.BoxSizer(wx.VERTICAL)
[a9d5684]64        sizer = wx.GridBagSizer(5, 5)
65        _BOX_WIDTH = 100
[2df0b74]66
67        self.tcA = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]68        self.tcA.SetToolTipString("Fit value for the slope parameter.")
[2df0b74]69        self.tcErrA = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]70        self.tcErrA.SetToolTipString("Error on the slope parameter.")
[2df0b74]71        self.tcB = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]72        self.tcA.SetToolTipString("Fit value for the constant parameter.")
[2df0b74]73        self.tcErrB = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]74        self.tcErrB.SetToolTipString("Error on the constant parameter.")
[2df0b74]75        self.tcChi = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]76        self.tcChi.SetToolTipString("Chi^2 over degrees of freedom.")
[2df0b74]77        self.xminFit = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]78        msg = "Enter the minimum value on "
79        msg += "the x-axis to be included in the fit."
80        self.xminFit.SetToolTipString(msg)
[2df0b74]81        self.xmaxFit = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
[a9d5684]82        msg = "Enter the maximum value on "
83        msg += " the x-axis to be included in the fit."
84        self.xmaxFit.SetToolTipString(msg)
85        self.initXmin = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
86        msg = "Minimum value on the x-axis for the plotted data."
87        self.initXmin.SetToolTipString(msg)
88        self.initXmax = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20))
89        msg = "Maximum value on the x-axis for the plotted data."
90        self.initXmax.SetToolTipString(msg)
91
92        # Make the info box not editable
[2df0b74]93        # _BACKGROUND_COLOR = '#ffdf85'
[a9d5684]94        _BACKGROUND_COLOR = self.GetBackgroundColour()
95        self.initXmin.SetEditable(False)
96        self.initXmin.SetBackgroundColour(_BACKGROUND_COLOR)
97        self.initXmax.SetEditable(False)
98        self.initXmax.SetBackgroundColour(_BACKGROUND_COLOR)
[2df0b74]99
[a9d5684]100        # Buttons on the bottom
101        self.bg_on = False
102        self.static_line_1 = wx.StaticLine(self, -1)
103        self.btFit = wx.Button(self, -1, 'Fit')
104        self.btFit.Bind(wx.EVT_BUTTON, self._onFit)
105        self.btFit.SetToolTipString("Perform fit.")
[2df0b74]106        self.btClose = wx.Button(self, wx.ID_CANCEL, 'Close')
[a9d5684]107        self.btClose.Bind(wx.EVT_BUTTON, self._on_close)
108        if RG_ON:
109            if (self.yLabel == "ln(y)" or self.yLabel == "ln(y*x)") and \
110                    (self.xLabel == "x^(2)"):
111                self.rg_on = True
112            if (self.xLabel == "x^(4)") and (self.yLabel == "y*x^(4)"):
113                self.bg_on = True
114        # Intro
115        explanation = "Perform fit for y(x) = ax + b"
116        if self.bg_on:
117            param_a = 'Background (= Parameter a)'
118        else:
119            param_a = 'Parameter a'
120        vbox.Add(sizer)
121        ix = 0
122        iy = 1
123        sizer.Add(wx.StaticText(self, -1, explanation), (iy, ix),
[2df0b74]124                  (1, 1), wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]125        iy += 2
126        sizer.Add(wx.StaticText(self, -1, param_a), (iy, ix),
[2df0b74]127                  (1, 1), wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]128        ix += 1
[2df0b74]129        sizer.Add(self.tcA, (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]130        ix += 1
131        sizer.Add(wx.StaticText(self, -1, '+/-'),
[2df0b74]132                  (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]133        ix += 1
134        sizer.Add(self.tcErrA, (iy, ix), (1, 1),
[2df0b74]135                  wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]136        iy += 1
137        ix = 0
[2df0b74]138        sizer.Add(wx.StaticText(self, -1, 'Parameter b'), (iy, ix), (1, 1),
139                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]140        ix += 1
[2df0b74]141        sizer.Add(self.tcB, (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]142        ix += 1
143        sizer.Add(wx.StaticText(self, -1, '+/-'), (iy, ix),
[2df0b74]144                  (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]145        ix += 1
146        sizer.Add(self.tcErrB, (iy, ix), (1, 1),
[2df0b74]147                  wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]148        iy += 1
149        ix = 0
150        sizer.Add(wx.StaticText(self, -1, 'Chi2/dof'), (iy, ix), (1, 1),
[2df0b74]151                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]152        ix += 1
[2df0b74]153        sizer.Add(self.tcChi, (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]154        iy += 2
155        ix = 1
156        sizer.Add(wx.StaticText(self, -1, 'Min'), (iy, ix), (1, 1),
[2df0b74]157                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]158        ix += 2
159        sizer.Add(wx.StaticText(self, -1, 'Max'), (iy, ix),
[2df0b74]160                  (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]161
162        iy += 1
163        ix = 0
164        sizer.Add(wx.StaticText(self, -1, 'Maximum range (linear scale)'),
[2df0b74]165                  (iy, ix), (1, 1),
166                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]167        ix += 1
[2df0b74]168        sizer.Add(self.initXmin, (iy, ix), (1, 1),
169                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]170        ix += 2
[2df0b74]171        sizer.Add(self.initXmax, (iy, ix), (1, 1),
172                  wx.EXPAND | wx.ADJUST_MINSIZE, 0)
173
[a9d5684]174        iy += 1
175        ix = 0
176        sizer.Add(wx.StaticText(self, -1, 'Fit range of ' + self.xLabel),
177                  (iy, ix), (1, 1),
[2df0b74]178                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]179        ix += 1
180        sizer.Add(self.xminFit, (iy, ix), (1, 1),
[2df0b74]181                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]182        ix += 2
[2df0b74]183        sizer.Add(self.xmaxFit, (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]184        if self.rg_on:
185            self.SetSize((PNL_WIDTH, PNL_HEIGHT))
186            I0_stxt = wx.StaticText(self, -1, 'I(q=0)')
187            self.I0_tctr = wx.TextCtrl(self, -1, '')
188            self.I0_tctr.SetEditable(False)
189            self.I0_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
190            self.I0err_tctr = wx.TextCtrl(self, -1, '')
191            self.I0err_tctr.SetEditable(False)
192            self.I0err_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
193            Rg_stxt = wx.StaticText(self, -1, 'Rg [A]')
[2df0b74]194            Rg_stxt.Show(self.yLabel == "ln(y)")
[a9d5684]195            self.Rg_tctr = wx.TextCtrl(self, -1, '')
196            self.Rg_tctr.SetEditable(False)
197            self.Rg_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
[2df0b74]198            self.Rg_tctr.Show(self.yLabel == "ln(y)")
[a9d5684]199            self.Rgerr_tctr = wx.TextCtrl(self, -1, '')
200            self.Rgerr_tctr.SetEditable(False)
201            self.Rgerr_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
[2df0b74]202            self.Rgerr_tctr.Show(self.yLabel == "ln(y)")
[a9d5684]203            self.Rgerr_pm = wx.StaticText(self, -1, '+/-')
[2df0b74]204            self.Rgerr_pm.Show(self.yLabel == "ln(y)")
[a9d5684]205            Diameter_stxt = wx.StaticText(self, -1, 'Rod Diameter [A]')
206            Diameter_stxt.Show(self.yLabel == "ln(y*x)")
207            self.Diameter_tctr = wx.TextCtrl(self, -1, '')
208            self.Diameter_tctr.SetEditable(False)
209            self.Diameter_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
210            self.Diameter_tctr.Show(self.yLabel == "ln(y*x)")
211            self.Diameter_pm = wx.StaticText(self, -1, '+/-')
212            self.Diameter_pm.Show(self.yLabel == "ln(y*x)")
213            self.Diametererr_tctr = wx.TextCtrl(self, -1, '')
214            self.Diametererr_tctr.SetEditable(False)
215            self.Diametererr_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
216            self.Diametererr_tctr.Show(self.yLabel == "ln(y*x)")
217            RgQmin_stxt = wx.StaticText(self, -1, 'Rg*Qmin')
218            self.RgQmin_tctr = wx.TextCtrl(self, -1, '')
219            self.RgQmin_tctr.SetEditable(False)
220            self.RgQmin_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
221            RgQmax_stxt = wx.StaticText(self, -1, 'Rg*Qmax')
222            self.RgQmax_tctr = wx.TextCtrl(self, -1, '')
223            self.RgQmax_tctr.SetEditable(False)
224            self.RgQmax_tctr.SetBackgroundColour(_BACKGROUND_COLOR)
225
226            iy += 2
227            ix = 0
[2df0b74]228            sizer.Add(I0_stxt, (iy, ix), (1, 1),
229                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]230            ix += 1
[2df0b74]231            sizer.Add(self.I0_tctr, (iy, ix), (1, 1),
232                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]233            ix += 1
234            sizer.Add(wx.StaticText(self, -1, '+/-'), (iy, ix),
[2df0b74]235                      (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]236            ix += 1
[2df0b74]237            sizer.Add(self.I0err_tctr, (iy, ix), (1, 1),
238                      wx.EXPAND | wx.ADJUST_MINSIZE, 0)
239
[a9d5684]240            iy += 1
241            ix = 0
[2df0b74]242            sizer.Add(Rg_stxt, (iy, ix), (1, 1),
243                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]244            ix += 1
[2df0b74]245            sizer.Add(self.Rg_tctr, (iy, ix), (1, 1),
246                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
247
[a9d5684]248            ix += 1
249            sizer.Add(self.Rgerr_pm, (iy, ix),
[2df0b74]250                      (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]251            ix += 1
[2df0b74]252            sizer.Add(self.Rgerr_tctr, (iy, ix), (1, 1),
253                      wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]254            iy += 1
255            ix = 0
[2df0b74]256            sizer.Add(Diameter_stxt, (iy, ix), (1, 1),
257                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]258            ix += 1
[2df0b74]259            sizer.Add(self.Diameter_tctr, (iy, ix), (1, 1),
260                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
261
[a9d5684]262            ix += 1
263            sizer.Add(self.Diameter_pm, (iy, ix),
[2df0b74]264                      (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]265            ix += 1
[2df0b74]266            sizer.Add(self.Diametererr_tctr, (iy, ix), (1, 1),
267                      wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]268            iy += 1
269            ix = 0
[2df0b74]270            sizer.Add(RgQmin_stxt, (iy, ix), (1, 1),
271                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]272            ix += 1
[2df0b74]273            sizer.Add(self.RgQmin_tctr, (iy, ix), (1, 1),
274                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
[a9d5684]275            iy += 1
276            ix = 0
[2df0b74]277            sizer.Add(RgQmax_stxt, (iy, ix), (1, 1),
278                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
[a9d5684]279            ix += 1
[2df0b74]280            sizer.Add(self.RgQmax_tctr, (iy, ix), (1, 1),
281                      wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 0)
282
[a9d5684]283        iy += 1
284        ix = 1
[2df0b74]285
[a9d5684]286        vbox.Add(self.static_line_1, 0, wx.EXPAND, 0)
287        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
[2df0b74]288        sizer_button.Add((20, 20), 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0)
289        sizer_button.Add(self.btFit, 0, wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 10)
[a9d5684]290        sizer_button.Add(self.btClose, 0,
[2df0b74]291                         wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 10)
292        vbox.Add(sizer_button, 0, wx.EXPAND | wx.BOTTOM | wx.TOP, 10)
293
294        sizer.Add(self.btFit, (iy, ix), (1, 1), wx.LEFT | wx.ADJUST_MINSIZE, 0)
295        # panel.SetSizer(sizer)
[a9d5684]296        self.SetSizer(vbox)
297        self.Centre()
298        # Receives the type of model for the fitting
299        from LineModel import LineModel
300        self.model = LineModel()
[2df0b74]301        # Display the fittings values
[a9d5684]302        self.default_A = self.model.getParam('A')
303        self.default_B = self.model.getParam('B')
304        self.cstA = fittings.Parameter(self.model, 'A', self.default_A)
305        self.cstB = fittings.Parameter(self.model, 'B', self.default_B)
[2df0b74]306
[a9d5684]307        # Set default value of parameter in fit dialog
308        if self.Avalue == None:
309            self.tcA.SetValue(format_number(self.default_A))
310        else:
311            self.tcA.SetLabel(format_number(self.Avalue))
312        if self.Bvalue == None:
313            self.tcB.SetValue(format_number(self.default_B))
314        else:
315            self.tcB.SetLabel(format_number(self.Bvalue))
316        if self.ErrAvalue == None:
317            self.tcErrA.SetLabel(format_number(0.0))
318        else:
319            self.tcErrA.SetLabel(format_number(self.ErrAvalue))
320        if self.ErrBvalue == None:
321            self.tcErrB.SetLabel(format_number(0.0))
322        else:
323            self.tcErrB.SetLabel(format_number(self.ErrBvalue))
324        if self.Chivalue == None:
325            self.tcChi.SetLabel(format_number(0.0))
326        else:
327            self.tcChi.SetLabel(format_number(self.Chivalue))
328        if self.plottable.x != []:
[2df0b74]329            # store the values of View in self.x,self.y,self.dx,self.dy
[a9d5684]330            self.x, self.y, self.dx, \
331                     self.dy = self.plottable.returnValuesOfView()
332            try:
333                self.mini = self.floatForwardTransform(min(self.x))
334            except:
335                self.mini = "Invalid"
336            try:
337                self.maxi = self.floatForwardTransform(max(self.x))
338            except:
339                self.maxi = "Invalid"
340
341            self.initXmin.SetValue(format_number(min(self.plottable.x)))
342            self.initXmax.SetValue(format_number(max(self.plottable.x)))
343            self.mini = min(self.x)
344            self.maxi = max(self.x)
345            self.xminFit.SetValue(format_number(self.mini))
346            self.xmaxFit.SetValue(format_number(self.maxi))
[2df0b74]347
[a9d5684]348    def register_close(self, owner):
349        """
350        Method to register the close event to a parent
351        window that needs notification when the dialog
352        is closed
[2df0b74]353
[a9d5684]354        :param owner: parent window
[2df0b74]355
[a9d5684]356        """
357        self._registered_close = owner
[2df0b74]358
[a9d5684]359    def _on_close(self, event):
360        """
361        Close event.
362        Notify registered owner if available.
363        """
364        event.Skip()
365        if self._registered_close is not None:
366            self._registered_close()
[2df0b74]367
[a9d5684]368    def _onFit(self, event):
369        """
370        Performs the fit. Receive an event when clicking on
371        the button Fit.Computes chisqr ,
372        A and B parameters of the best linear fit y=Ax +B
373        Push a plottable to
374        """
375        tempx = []
376        tempy = []
377        tempdy = []
[2df0b74]378
[a9d5684]379        # Check if View contains a x array .we online fit when x exits
380        # makes transformation for y as a line to fit
381        if self.x != []:
[2df0b74]382            if self.checkFitValues(self.xminFit) == True:
383                # Check if the field of Fit Dialog contain values
[a9d5684]384                # and use the x max and min of the user
385                if not self._checkVal(self.xminFit, self.xmaxFit):
386                    return
387                xminView = float(self.xminFit.GetValue())
388                xmaxView = float(self.xmaxFit.GetValue())
389                xmin = xminView
390                xmax = xmaxView
391                # Store the transformed values of view x, y,dy
392                # in variables  before the fit
393                if self.yLabel.lower() == "log10(y)":
[2df0b74]394                    if self.xLabel.lower() == "log10(x)":
[a9d5684]395                        for i in range(len(self.x)):
396                            if self.x[i] >= math.log10(xmin):
397                                tempy.append(math.log10(self.y[i]))
[2df0b74]398                                tempdy.append(transform.errToLogX(self.y[i], 0, self.dy[i], 0))
[a9d5684]399                    else:
400                        for i in range(len(self.y)):
401                            tempy.append(math.log10(self.y[i]))
[2df0b74]402                            tempdy.append(transform.errToLogX(self.y[i], 0, self.dy[i], 0))
[a9d5684]403                else:
404                    tempy = self.y
405                    tempdy = self.dy
[2df0b74]406
407                if self.xLabel.lower() == "log10(x)":
[a9d5684]408                    for x_i in self.x:
409                        if x_i >= math.log10(xmin):
410                            tempx.append(math.log10(x_i))
411                else:
412                    tempx = self.x
[2df0b74]413
414                # Find the fitting parameters
[a9d5684]415                # Always use the same defaults, so that fit history
[2df0b74]416                # doesn't play a role!
[a9d5684]417                self.cstA = fittings.Parameter(self.model, 'A', self.default_A)
418                self.cstB = fittings.Parameter(self.model, 'B', self.default_B)
[2df0b74]419
420                if self.xLabel.lower() == "log10(x)":
[a9d5684]421                    tempdy = numpy.asarray(tempdy)
422                    tempdy[tempdy == 0] = 1
[b9a5f0e]423                    chisqr, out, cov = fittings.sasfit(self.model,
[2df0b74]424                                                       [self.cstA, self.cstB],
425                                                       tempx, tempy,
426                                                       tempdy,
427                                                       math.log10(xmin),
428                                                       math.log10(xmax))
[a9d5684]429                else:
430                    tempdy = numpy.asarray(tempdy)
431                    tempdy[tempdy == 0] = 1
[b9a5f0e]432                    chisqr, out, cov = fittings.sasfit(self.model,
[2df0b74]433                                                       [self.cstA, self.cstB],
434                                                       tempx, tempy, tempdy,
435                                                       xminView, xmaxView)
[a9d5684]436                # Use chi2/dof
437                if len(tempx) > 0:
[2df0b74]438                    chisqr = chisqr / len(tempx)
439
440                # Check that cov and out are iterable before displaying them
[a9d5684]441                if cov == None:
442                    errA = 0.0
443                    errB = 0.0
444                else:
445                    errA = math.sqrt(cov[0][0])
446                    errB = math.sqrt(cov[1][1])
447                if out == None:
448                    cstA = 0.0
449                    cstB = 0.0
450                else:
451                    cstA = out[0]
452                    cstB = out[1]
453                # Reset model with the right values of A and B
454                self.model.setParam('A', float(cstA))
455                self.model.setParam('B', float(cstB))
[2df0b74]456
[a9d5684]457                tempx = []
458                tempy = []
459                y_model = 0.0
460                # load tempy with the minimum transformation
[2df0b74]461
[a9d5684]462                if self.xLabel == "log10(x)":
463                    y_model = self.model.run(math.log10(xmin))
464                    tempx.append(xmin)
465                else:
466                    y_model = self.model.run(xminView)
467                    tempx.append(xminView)
[2df0b74]468
[a9d5684]469                if self.yLabel == "log10(y)":
470                    tempy.append(math.pow(10, y_model))
471                else:
472                    tempy.append(y_model)
[2df0b74]473
[a9d5684]474                # load tempy with the maximum transformation
475                if self.xLabel == "log10(x)":
476                    y_model = self.model.run(math.log10(xmax))
477                    tempx.append(xmax)
478                else:
479                    y_model = self.model.run(xmaxView)
480                    tempx.append(xmaxView)
[2df0b74]481
[a9d5684]482                if self.yLabel == "log10(y)":
483                    tempy.append(math.pow(10, y_model))
484                else:
485                    tempy.append(y_model)
[2df0b74]486                # Set the fit parameter display when  FitDialog is opened again
[a9d5684]487                self.Avalue = cstB
488                self.Bvalue = cstA
489                self.ErrAvalue = errA
490                self.ErrBvalue = errB
491                self.Chivalue = chisqr
492                self.push_data(tempx, tempy, xminView, xmaxView,
493                               xmin, xmax, self._ongetValues())
[2df0b74]494
[a9d5684]495                # Display the fitting value on the Fit Dialog
496                self._onsetValues(cstB, cstA, errA, errB, chisqr)
[2df0b74]497
[a9d5684]498    def _onsetValues(self, cstA, cstB, errA, errB, Chi):
499        """
500        Display  the value on fit Dialog
501        """
502        rg = None
503        self.tcA.SetValue(format_number(cstA))
504        self.tcB.SetValue(format_number(cstB))
505        self.tcErrA.SetValue(format_number(errA))
506        self.tcErrB.SetValue(format_number(errB))
507        self.tcChi.SetValue(format_number(Chi))
508        if self.rg_on:
509            if self.Rg_tctr.IsShown():
510                rg = numpy.sqrt(-3 * float(cstA))
511                value = format_number(rg)
512                self.Rg_tctr.SetValue(value)
513                if self.I0_tctr.IsShown():
514                    val = numpy.exp(cstB)
515                    self.I0_tctr.SetValue(format_number(val))
516            if self.Rgerr_tctr.IsShown():
517                if rg != None and rg != 0:
518                    value = format_number(3 * float(cstA) / (2 * rg))
519                else:
[2df0b74]520                    value = ''
[a9d5684]521                self.Rgerr_tctr.SetValue(value)
522                if self.I0err_tctr.IsShown():
523                    val = numpy.abs(numpy.exp(cstB) - numpy.exp(cstB + errB))
524                    self.I0err_tctr.SetValue(format_number(val))
525            if self.Diameter_tctr.IsShown():
526                rg = 4 * numpy.sqrt(-float(cstA))
527                value = format_number(rg)
528                self.Diameter_tctr.SetValue(value)
529            if self.Diametererr_tctr.IsShown():
530                if rg != None and rg != 0:
531                    value = format_number(8 * float(cstA) / rg)
532                else:
[2df0b74]533                    value = ''
[a9d5684]534                self.Diametererr_tctr.SetValue(value)
535            if self.RgQmin_tctr.IsShown():
536                value = format_number(rg * self.mini)
537                self.RgQmin_tctr.SetValue(value)
538            if self.RgQmax_tctr.IsShown():
539                value = format_number(rg * self.maxi)
540                self.RgQmax_tctr.SetValue(value)
[2df0b74]541
[a9d5684]542    def _ongetValues(self):
543        """
544        Display  the value on fit Dialog
545        """
546        return self.Avalue, self.Bvalue, self.ErrAvalue, \
547                            self.ErrBvalue, self.Chivalue
[2df0b74]548
[a9d5684]549    def _checkVal(self, usermin, usermax):
550        """
551        Ensure that fields parameter contains a min and a max value
552        within x min and x max range
553        """
554        self.mini = float(self.xminFit.GetValue())
555        self.maxi = float(self.xmaxFit.GetValue())
556        flag = True
557        try:
558            mini = float(usermin.GetValue())
559            maxi = float(usermax.GetValue())
560            if mini < maxi:
561                usermin.SetBackgroundColour(wx.WHITE)
562                usermin.Refresh()
563            else:
564                flag = False
565                usermin.SetBackgroundColour("pink")
566                usermin.Refresh()
567        except:
568            # Check for possible values entered
569            flag = False
570            usermin.SetBackgroundColour("pink")
571            usermin.Refresh()
[2df0b74]572
[a9d5684]573        return flag
[2df0b74]574
[a9d5684]575    def floatForwardTransform(self, x):
576        """
577        transform a float.
578        """
[2df0b74]579        # TODO: refactor this with proper object-oriented design
[a9d5684]580        # This code stinks.
[2df0b74]581        if self.xLabel == "x":
[a9d5684]582            return transform.toX(x)
[2df0b74]583        if self.xLabel == "x^(2)":
[a9d5684]584            return transform.toX2(x)
[2df0b74]585        if self.xLabel == "ln(x)":
[a9d5684]586            return transform.toLogX(x)
[2df0b74]587        if self.xLabel == "log10(x)":
[a9d5684]588            return math.log10(x)
[2df0b74]589
[a9d5684]590    def floatTransform(self, x):
591        """
592        transform a float.It is use to determine the x.
593        View min and x.View max for values
594        not in x
595        """
[2df0b74]596        # TODO: refactor this with proper object-oriented design
[a9d5684]597        # This code stinks.
[2df0b74]598        if self.xLabel == "x":
[a9d5684]599            return transform.toX(x)
[2df0b74]600        if self.xLabel == "x^(2)":
[a9d5684]601            return transform.toX2(x)
[2df0b74]602        if self.xLabel == "ln(x)":
[a9d5684]603            return transform.toLogX(x)
[2df0b74]604        if self.xLabel == "log10(x)":
[a9d5684]605            if x > 0:
606                return x
607            else:
608                raise ValueError, "cannot compute log of a negative number"
[2df0b74]609
[a9d5684]610    def floatInvTransform(self, x):
611        """
612        transform a float.It is use to determine the x.View min and x.View
613        max for values not in x
[2df0b74]614
[a9d5684]615        """
[2df0b74]616        # TODO: refactor this. This is just a hack to make the
[a9d5684]617        # functionality work without rewritting the whole code
618        # with good design (which really should be done...).
[2df0b74]619        if self.xLabel == "x^(2)":
[a9d5684]620            return math.sqrt(x)
[2df0b74]621        elif self.xLabel == "log10(x)":
[a9d5684]622            return math.pow(10, x)
[2df0b74]623        elif self.xLabel == "ln(x)":
[a9d5684]624            return math.exp(x)
625        return x
[2df0b74]626
[a9d5684]627    def checkFitValues(self, item):
628        """
629            Check the validity of input values
630        """
631        flag = True
632        value = item.GetValue()
633        # Check for possible values entered
[2df0b74]634        if self.xLabel == "log10(x)":
635            if float(value) > 0:
[a9d5684]636                item.SetBackgroundColour(wx.WHITE)
637                item.Refresh()
638            else:
639                flag = False
640                item.SetBackgroundColour("pink")
641                item.Refresh()
642        return flag
[2df0b74]643
[a9d5684]644    def setFitRange(self, xmin, xmax, xminTrans, xmaxTrans):
645        """
646        Set fit parameters
647        """
648        self.xminFit.SetValue(format_number(xmin))
649        self.xmaxFit.SetValue(format_number(xmax))
[2df0b74]650
[a9d5684]651    def set_fit_region(self, xmin, xmax):
652        """
653        Set the fit region
654        :param xmin: minimum x-value to be included in fit
655        :param xmax: maximum x-value to be included in fit
656        """
657        # Check values
658        try:
659            float(xmin)
660            float(xmax)
661        except:
662            msg = "LinearFit.set_fit_region: fit range must be floats"
663            raise ValueError, msg
664        self.xminFit.SetValue(format_number(xmin))
665        self.xmaxFit.SetValue(format_number(xmax))
[2df0b74]666
667
[a9d5684]668class MyApp(wx.App):
669    """
[2df0b74]670        Test application
[a9d5684]671    """
672    def OnInit(self):
673        """
[2df0b74]674            Test application initialization
[a9d5684]675        """
676        wx.InitAllImageHandlers()
677        plot = Theory1D([], [])
678        dialog = LinearFit(parent=None, plottable=plot,
679                           push_data=self.onFitDisplay,
680                           transform=self.returnTrans,
[2df0b74]681                           title='Linear Fit')
[a9d5684]682        if dialog.ShowModal() == wx.ID_OK:
683            pass
684        dialog.Destroy()
685        return 1
[2df0b74]686
[a9d5684]687    def onFitDisplay(self, tempx, tempy, xminView, xmaxView, xmin, xmax, func):
688        """
[2df0b74]689            Test application dummy method
[a9d5684]690        """
691        pass
[2df0b74]692
[a9d5684]693    def returnTrans(self):
694        """
[2df0b74]695            Test application dummy method
[a9d5684]696        """
697        return '', '', 0, 0, 0, 0, 0
Note: See TracBrowser for help on using the repository browser.