~ubuntu-branches/ubuntu/trusty/guiqwt/trusty

« back to all changes in this revision

Viewing changes to guiqwt/fit.py

  • Committer: Bazaar Package Importer
  • Author(s): Picca Frédéric-Emmanuel
  • Date: 2011-04-07 22:41:50 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110407224150-kkhppnq7rp2c8b3c
Tags: 2.1.0-1
* Imported Upstream version 2.1.0
* debian/patches/
  - 0001-features-01_bts614083.patch (delete)
  - 0001-feature-fix-the-documentation-build.patch (new)
* add and install the sift desktop file
* recommends python-dicom (Closes: #621421)
  thanks Junqian Gordon Xu for the report

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
   :inherited-members:
40
40
"""
41
41
 
42
 
from PyQt4.QtGui import (QGridLayout, QLabel, QSlider, QPushButton, QFrame,
43
 
                         QCheckBox)
44
 
from PyQt4.QtCore import Qt, SIGNAL, QObject
 
42
from __future__ import division
 
43
 
 
44
from PyQt4.QtGui import (QGridLayout, QLabel, QSlider, QPushButton, QLineEdit,
 
45
                         QDialog, QVBoxLayout, QHBoxLayout, QWidget,
 
46
                         QDialogButtonBox)
 
47
from PyQt4.QtCore import Qt, SIGNAL, QObject, SLOT
45
48
 
46
49
import numpy as np
47
50
from numpy import inf # Do not remove this import (used by optimization funcs)
48
51
 
49
52
import guidata
 
53
from guidata.qthelpers import create_groupbox
50
54
from guidata.configtools import get_icon
51
55
from guidata.dataset.datatypes import DataSet
52
56
from guidata.dataset.dataitems import (StringItem, FloatItem, IntItem,
55
59
# Local imports
56
60
from guiqwt.config import _
57
61
from guiqwt.builder import make
58
 
from guiqwt.plot import CurveDialog
 
62
from guiqwt.plot import CurveWidgetMixin
59
63
from guiqwt.signals import SIG_RANGE_CHANGED
60
64
 
61
65
class AutoFitParam(DataSet):
84
88
    value = FloatItem(_("Value"), default=0.0)
85
89
    min = FloatItem(_("Min"), default=-1.0)
86
90
    max = FloatItem(_("Max"), default=1.0).set_pos(col=1)
87
 
    steps = IntItem(_("Steps"), default=500)
 
91
    steps = IntItem(_("Steps"), default=5000)
88
92
    format = StringItem(_("Format"), default="%.3f").set_pos(col=1)
89
93
    logscale = BoolItem(_("Logarithmic"), _("Scale"))
90
94
 
91
95
    def __init__(self, name, value, min, max, logscale=False,
92
 
                 steps=500, format='%.3f'):
 
96
                 steps=5000, format='%.3f', size_offset=0):
93
97
        DataSet.__init__(self, title=_("Curve fitting parameter"))
94
98
        self.name = name
95
99
        self.value = value
99
103
        self.steps = steps
100
104
        self.format = format
101
105
        self.label = None
102
 
        
103
 
    def get_widgets(self, parent):
104
 
        button = QPushButton(get_icon('edit.png'), _('Edit'), parent)
105
 
        button.setToolTip(_("Edit fit parameter '%s' properties") % self.name)
106
 
        QObject.connect(button, SIGNAL('clicked()'), self.edit_param)
107
 
        self.checkbox = QCheckBox(_('Logarithmic scale'), parent)
108
 
        self.update_checkbox_state()
109
 
        QObject.connect(self.checkbox, SIGNAL('stateChanged(int)'), self.set_scale)
110
 
        self.label = QLabel(parent)
111
 
        self.slider = QSlider(parent)
 
106
        self.lineedit = None
 
107
        self.slider = None
 
108
        self.button = None
 
109
        self._size_offset = size_offset
 
110
        
 
111
    def copy(self):
 
112
        """Return a copy of this fitparam"""
 
113
        return FitParam(self.name, self.value, self.min, self.max,
 
114
                        self.logscale, self.steps, self.format,
 
115
                        self._size_offset)
 
116
        
 
117
    def create_widgets(self, parent):
 
118
        self.label = QLabel()
 
119
        font = self.label.font()
 
120
        font.setPointSize(font.pointSize()+self._size_offset)
 
121
        self.label.setFont(font)
 
122
        self.button = QPushButton()
 
123
        self.button.setIcon(get_icon('settings.png'))
 
124
        self.button.setToolTip(
 
125
                        _("Edit '%s' fit parameter properties") % self.name)
 
126
        QObject.connect(self.button, SIGNAL('clicked()'),
 
127
                        lambda: self.edit_param(parent))
 
128
        self.lineedit = QLineEdit()
 
129
        QObject.connect(self.lineedit, SIGNAL('editingFinished()'),
 
130
                        self.line_editing_finished)
 
131
        self.slider = QSlider()
112
132
        self.slider.setOrientation(Qt.Horizontal)
113
133
        self.slider.setRange(0, self.steps-1)
114
134
        QObject.connect(self.slider, SIGNAL("valueChanged(int)"),
115
135
                        self.slider_value_changed)
116
136
        self.set_text()
117
137
        self.update()
118
 
        return button, self.checkbox, self.slider, self.label
 
138
        return self.get_widgets()
 
139
        
 
140
    def get_widgets(self):
 
141
        return self.label, self.lineedit, self.slider, self.button
119
142
        
120
143
    def set_scale(self, state):
121
144
        self.logscale = state > 0
122
145
        self.update_slider_value()
123
146
        
124
147
    def set_text(self):
125
 
        text = ('<b>%s</b> : '+self.format) % (self.name, self.value)
126
 
        self.label.setText(text)
 
148
        style = "<span style=\'color: #444444\'><b>%s</b></span>"
 
149
        self.label.setText(style % self.name)
 
150
        if self.value is None:
 
151
            value_str = ''
 
152
        else:
 
153
            value_str = self.format % self.value
 
154
        self.lineedit.setText(value_str)
 
155
        
 
156
    def line_editing_finished(self):
 
157
        try:
 
158
            self.value = float(self.lineedit.text())
 
159
        except ValueError:
 
160
            self.set_text()
 
161
            self.update_slider_value()
127
162
        
128
163
    def slider_value_changed(self, int_value):
129
164
        if self.logscale:
130
 
            min, max = np.log10(self.min), np.log10(self.max)
131
 
            self.value = 10**(min+(max-min)*int_value/self.steps)
 
165
            total_delta = np.log10(1+self.max-self.min)
 
166
            self.value = self.min+10**(total_delta*int_value/(self.steps-1))-1
132
167
        else:
133
 
            self.value = self.min+(self.max-self.min)*int_value/self.steps
 
168
            total_delta = self.max-self.min
 
169
            self.value = self.min+total_delta*int_value/(self.steps-1)
134
170
        self.set_text()
135
171
    
136
 
    def _logscale_check(self):
137
 
        if self.min == 0:
138
 
            self.min = self.max/10
139
 
        if self.max == 0:
140
 
            self.max = self.mix*10
141
 
    
142
172
    def update_slider_value(self):
143
 
        if self.logscale:
144
 
            self._logscale_check()
145
 
            value, min, max = (np.log10(self.value), np.log10(self.min),
146
 
                               np.log10(self.max))
 
173
        if self.value is None or self.min is None or self.max is None:
 
174
            self.slider.setEnabled(False)
147
175
        else:
148
 
            value, min, max = self.value, self.min, self.max
149
 
        intval = int(self.steps*(value-min)/(max-min))
150
 
        self.slider.setValue(intval)
151
 
 
152
 
    def update_checkbox_state(self):
153
 
        state = Qt.Checked if self.logscale else Qt.Unchecked
154
 
        self.checkbox.setCheckState(state)
155
 
 
156
 
    def edit_param(self):
157
 
        res = self.edit()
158
 
        if res:
159
 
            self.update_checkbox_state()
 
176
            self.slider.setEnabled(True)
 
177
            if self.logscale:
 
178
                value_delta = max([np.log10(1+self.value-self.min), 0.])
 
179
                total_delta = np.log10(1+self.max-self.min)
 
180
            else:
 
181
                value_delta = self.value-self.min
 
182
                total_delta = self.max-self.min
 
183
            intval = int(self.steps*value_delta/total_delta)
 
184
            self.slider.blockSignals(True)
 
185
            self.slider.setValue(intval)
 
186
            self.slider.blockSignals(False)
 
187
 
 
188
    def edit_param(self, parent):
 
189
        if self.edit(parent=parent):
160
190
            self.update()
161
191
 
162
192
    def update(self):
163
193
        self.slider.setRange(0, self.steps-1)
164
194
        self.update_slider_value()
165
195
        self.set_text()
166
 
 
167
 
 
168
 
class FitDialog(CurveDialog):
169
 
    def __init__(self, x, y, fitfunc, fitparams, title=None):
170
 
        if title is None:
171
 
            title = _('Curve fitting')
 
196
        # Force the QLineEdit to emit the editingFinished() signal
 
197
        self.lineedit.emit(SIGNAL('editingFinished()'))
 
198
 
 
199
 
 
200
def add_fitparam_widgets_to(layout, fitparams, refresh_callback, param_cols=1):
 
201
    row_contents = []
 
202
    row_nb = 0
 
203
    col_nb = 0
 
204
    for i, param in enumerate(fitparams):
 
205
        widgets = param.create_widgets(layout.parent())
 
206
        w_colums = len(widgets)+1
 
207
        label, lineedit, slider, button = widgets
 
208
        QObject.connect(slider, SIGNAL("valueChanged(int)"), refresh_callback)
 
209
        QObject.connect(lineedit, SIGNAL("editingFinished()"), refresh_callback)
 
210
        row_contents += [(label,    row_nb, 0+col_nb*w_colums),
 
211
                         (slider,   row_nb, 1+col_nb*w_colums),
 
212
                         (lineedit, row_nb, 2+col_nb*w_colums),
 
213
                         (button,   row_nb, 3+col_nb*w_colums),]
 
214
        col_nb += 1
 
215
        if col_nb == param_cols:
 
216
            row_nb += 1
 
217
            col_nb = 0
 
218
            for widget, row, col in row_contents:
 
219
                layout.addWidget(widget, row, col)
 
220
    if fitparams:
 
221
        for col_nb in range(param_cols):
 
222
            layout.setColumnStretch(1+col_nb*w_colums, 5)
 
223
            if col_nb > 0:
 
224
                layout.setColumnStretch(col_nb*w_colums-1, 1)
 
225
 
 
226
class FitWidgetMixin(CurveWidgetMixin):
 
227
    def __init__(self, wintitle="guiqwt plot", icon="guiqwt.png",
 
228
                 toolbar=False, options=None, panels=None, param_cols=1,
 
229
                 legend_anchor='TR', auto_fit=True):
 
230
        if wintitle is None:
 
231
            wintitle = _('Curve fitting')
 
232
 
 
233
        self.x = None
 
234
        self.y = None
 
235
        self.fitfunc = None
 
236
        self.fitargs = None
 
237
        self.fitkwargs = None
 
238
        self.fitparams = None
 
239
        self.autofit_prm = None
 
240
        
 
241
        self.data_curve = None
 
242
        self.fit_curve = None
 
243
        self.legend = None
 
244
        self.legend_anchor = legend_anchor
 
245
        self.xrange = None
 
246
        self.show_xrange = False
 
247
        
 
248
        self.param_cols = param_cols
 
249
        self.auto_fit_enabled = auto_fit      
 
250
        self.button_list = [] # list of buttons to be disabled at startup
 
251
 
 
252
        self.fit_layout = None
 
253
        self.params_layout = None
 
254
        
 
255
        CurveWidgetMixin.__init__(self, wintitle=wintitle, icon=icon, 
 
256
                                  toolbar=toolbar, options=options,
 
257
                                  panels=panels)
 
258
        
 
259
        self.refresh()
 
260
        
 
261
    # CurveWidgetMixin API -----------------------------------------------------
 
262
    def setup_widget_layout(self):
 
263
        self.fit_layout = QHBoxLayout()
 
264
        self.params_layout = QGridLayout()
 
265
        params_group = create_groupbox(self, _("Fit parameters"),
 
266
                                       layout=self.params_layout)
 
267
        if self.auto_fit_enabled:
 
268
            auto_group = self.create_autofit_group()
 
269
            self.fit_layout.addWidget(auto_group)
 
270
        self.fit_layout.addWidget(params_group)
 
271
        self.plot_layout.addLayout(self.fit_layout, 1, 0)
 
272
        
 
273
        vlayout = QVBoxLayout(self)
 
274
        vlayout.addWidget(self.toolbar)
 
275
        vlayout.addLayout(self.plot_layout)
 
276
        self.setLayout(vlayout)
 
277
        
 
278
    def create_plot(self, options):
 
279
        super(FitWidgetMixin, self).create_plot(options)
 
280
        for plot in self.get_plots():
 
281
            self.connect(plot, SIG_RANGE_CHANGED, self.range_changed)
 
282
        
 
283
    # Public API ---------------------------------------------------------------  
 
284
    def set_data(self, x, y, fitfunc=None, fitparams=None,
 
285
                 fitargs=None, fitkwargs=None):
 
286
        if self.fitparams is not None and fitparams is not None:
 
287
            self.clear_params_layout()
172
288
        self.x = x
173
289
        self.y = y
174
 
        self.fitfunc = fitfunc
175
 
        self.fitparams = fitparams
176
 
        super(FitDialog, self).__init__(wintitle=title, icon="guiqwt.png",
177
 
                                        edit=True, toolbar=True, options=None)
178
 
                
 
290
        if fitfunc is not None:
 
291
            self.fitfunc = fitfunc
 
292
        if fitparams is not None:
 
293
            self.fitparams = fitparams
 
294
        if fitargs is not None:
 
295
            self.fitargs = fitargs
 
296
        if fitkwargs is not None:
 
297
            self.fitkwargs = fitkwargs
179
298
        self.autofit_prm = AutoFitParam(title=_("Automatic fitting options"))
180
299
        self.autofit_prm.xmin = x.min()
181
300
        self.autofit_prm.xmax = x.max()
182
301
        self.compute_imin_imax()
183
 
        
184
 
        self.xrange = None
185
 
        self.show_xrange = False
186
 
        self.refresh()
187
 
        
188
 
    # CurveDialog API ----------------------------------------------------------
189
 
    def install_button_layout(self):
190
 
        auto_button = QPushButton(get_icon('apply.png'), _("Auto"), self)
 
302
        if self.fitparams is not None and fitparams is not None:
 
303
            self.populate_params_layout()
 
304
        self.refresh()
 
305
        
 
306
    def set_fit_data(self, fitfunc, fitparams, fitargs=None, fitkwargs=None):
 
307
        if self.fitparams is not None:
 
308
            self.clear_params_layout()
 
309
        self.fitfunc = fitfunc
 
310
        self.fitparams = fitparams
 
311
        self.fitargs = fitargs
 
312
        self.fitkwargs = fitkwargs
 
313
        self.populate_params_layout()
 
314
        self.refresh()
 
315
        
 
316
    def clear_params_layout(self):
 
317
        for i, param in enumerate(self.fitparams):
 
318
            for widget in param.get_widgets():
 
319
                if widget is not None:
 
320
                    self.params_layout.removeWidget(widget)
 
321
                    widget.hide()
 
322
        
 
323
    def populate_params_layout(self):
 
324
        add_fitparam_widgets_to(self.params_layout, self.fitparams,
 
325
                                self.refresh, param_cols=self.param_cols)
 
326
    
 
327
    def create_autofit_group(self):        
 
328
        auto_button = QPushButton(get_icon('apply.png'), _("Run"), self)
191
329
        self.connect(auto_button, SIGNAL("clicked()"), self.autofit)
192
 
        autoprm_button = QPushButton(get_icon('settings.png'),
193
 
                                     _("Fit parameters..."), self)
 
330
        autoprm_button = QPushButton(get_icon('settings.png'), _("Settings"),
 
331
                                     self)
194
332
        self.connect(autoprm_button, SIGNAL("clicked()"), self.edit_parameters)
195
 
        xrange_button = QPushButton(get_icon('xrange.png'), _("Fit bounds"),
196
 
                                    self)
 
333
        xrange_button = QPushButton(get_icon('xrange.png'), _("Bounds"), self)
197
334
        xrange_button.setCheckable(True)
198
335
        self.connect(xrange_button, SIGNAL("toggled(bool)"), self.toggle_xrange)
199
 
        
200
 
        self.button_layout.addWidget(auto_button)
201
 
        self.button_layout.addWidget(autoprm_button)
202
 
        self.button_layout.addWidget(xrange_button)
203
 
        super(FitDialog, self).install_button_layout()
204
 
 
205
 
    def create_plot(self, options):
206
 
        super(FitDialog, self).create_plot(options)
207
 
        for plot in self.get_plots():
208
 
            self.connect(plot, SIG_RANGE_CHANGED, self.range_changed)
209
 
        
210
 
        params_frame = QFrame(self)
211
 
        params_frame.setFrameShape(QFrame.Box)
212
 
        params_frame.setFrameShadow(QFrame.Sunken)
213
 
        params_layout = QGridLayout()
214
 
        params_frame.setLayout(params_layout)
215
 
        for i, param in enumerate(self.fitparams):
216
 
            button, checkbox, slider, label = param.get_widgets(self)
217
 
            self.connect(slider, SIGNAL("valueChanged(int)"), self.refresh)
218
 
            self.connect(checkbox, SIGNAL("stateChanged(int)"), self.refresh)
219
 
            params_layout.addWidget(button, i, 0)
220
 
 
221
 
            params_layout.addWidget(checkbox, i, 1)
222
 
            params_layout.addWidget(slider, i, 2)
223
 
            params_layout.addWidget(label, i, 3)
224
 
        self.plot_layout.addWidget(params_frame, 1, 0)
225
 
        
226
 
    # Public API ---------------------------------------------------------------        
227
 
    def refresh(self):
 
336
        auto_layout = QVBoxLayout()
 
337
        auto_layout.addWidget(auto_button)
 
338
        auto_layout.addWidget(autoprm_button)
 
339
        auto_layout.addWidget(xrange_button)
 
340
        self.button_list += [auto_button, autoprm_button, xrange_button]
 
341
        return create_groupbox(self, _("Automatic fit"), layout=auto_layout)
 
342
        
 
343
    def get_fitfunc_arguments(self):
 
344
        """Return fitargs and fitkwargs"""
 
345
        fitargs = self.fitargs
 
346
        if self.fitargs is None:
 
347
            fitargs = []
 
348
        fitkwargs = self.fitkwargs
 
349
        if self.fitkwargs is None:
 
350
            fitkwargs = {}
 
351
        return fitargs, fitkwargs
 
352
        
 
353
    def refresh(self, slider_value=None):
228
354
        """Refresh Fit Tool dialog box"""
229
 
        yfit = self.fitfunc(self.x, [p.value for p in self.fitparams])
230
 
        self.xrange = make.range(self.autofit_prm.xmin, self.autofit_prm.xmax)
 
355
        # Update button states
 
356
        enable = self.x is not None and self.y is not None \
 
357
                 and self.x.size > 0 and self.y.size > 0 \
 
358
                 and self.fitfunc is not None and self.fitparams is not None \
 
359
                 and len(self.fitparams) > 0
 
360
        for btn in self.button_list:
 
361
            btn.setEnabled(enable)
 
362
            
 
363
        if not enable:
 
364
            # Fit widget is not yet configured
 
365
            return
 
366
 
 
367
        fitargs, fitkwargs = self.get_fitfunc_arguments()
 
368
        yfit = self.fitfunc(self.x, [p.value for p in self.fitparams],
 
369
                            *fitargs, **fitkwargs)
 
370
                            
 
371
        plot = self.get_plot()
 
372
        
 
373
        if self.legend is None:
 
374
            self.legend = make.legend(anchor=self.legend_anchor)
 
375
            plot.add_item(self.legend)
 
376
        
 
377
        if self.xrange is None:
 
378
            self.xrange = make.range(0., 1.)
 
379
            plot.add_item(self.xrange)
 
380
        self.xrange.set_range(self.autofit_prm.xmin, self.autofit_prm.xmax)
231
381
        self.xrange.setVisible(self.show_xrange)
232
 
        items = [make.curve(self.x, self.y, _("Data"), color="b", linewidth=2),
233
 
                 make.curve(self.x, yfit, _("Fit"), color="r", linewidth=2),
234
 
                 make.legend(), self.xrange]
235
 
        plot = self.get_plot()
236
 
        plot.del_all_items()
237
 
        for item in items:
238
 
            plot.add_item(item)
 
382
        
 
383
        if self.data_curve is None:
 
384
            self.data_curve = make.curve([], [],
 
385
                                         _("Data"), color="b", linewidth=2)
 
386
            plot.add_item(self.data_curve)
 
387
        self.data_curve.set_data(self.x, self.y)
 
388
        
 
389
        if self.fit_curve is None:
 
390
            self.fit_curve = make.curve([], [],
 
391
                                        _("Fit"), color="r", linewidth=2)
 
392
            plot.add_item(self.fit_curve)
 
393
        self.fit_curve.set_data(self.x, yfit)
 
394
        
239
395
        plot.replot()
240
396
        plot.disable_autoscale()
241
397
        
252
408
        self.show_xrange = state
253
409
        
254
410
    def edit_parameters(self):
255
 
        if self.autofit_prm.edit():
 
411
        if self.autofit_prm.edit(parent=self):
256
412
            self.xrange.set_range(self.autofit_prm.xmin, self.autofit_prm.xmax)
257
413
            plot = self.get_plot()
258
414
            plot.replot()
260
416
        
261
417
    def compute_imin_imax(self):
262
418
        self.i_min = self.x.searchsorted(self.autofit_prm.xmin)
263
 
        self.i_max = self.x.searchsorted(self.autofit_prm.xmax)
 
419
        self.i_max = self.x.searchsorted(self.autofit_prm.xmax, side='right')
264
420
        
265
421
    def errorfunc(self, params):
266
422
        x = self.x[self.i_min:self.i_max]
267
423
        y = self.y[self.i_min:self.i_max]
268
 
        return y - self.fitfunc(x, params)
 
424
        fitargs, fitkwargs = self.get_fitfunc_arguments()
 
425
        return y - self.fitfunc(x, params, *fitargs, **fitkwargs)
269
426
 
270
427
    def autofit(self):
271
428
        meth = self.autofit_prm.method
344
501
    def get_values(self):
345
502
        """Convenience method to get fit parameter values"""
346
503
        return [param.value for param in self.fitparams]
347
 
        
348
 
 
349
 
def guifit(x, y, fitfunc, fitparams, title=None):
 
504
 
 
505
 
 
506
class FitWidget(QWidget, FitWidgetMixin):
 
507
    def __init__(self, wintitle=None, icon="guiqwt.png", toolbar=False,
 
508
                 options=None, parent=None, panels=None,
 
509
                 param_cols=1, legend_anchor='TR', auto_fit=False):
 
510
        QWidget.__init__(self, parent)
 
511
        FitWidgetMixin.__init__(self, wintitle, icon, toolbar, options, panels,
 
512
                                param_cols, legend_anchor, auto_fit)
 
513
 
 
514
 
 
515
class FitDialog(QDialog, FitWidgetMixin):
 
516
    def __init__(self, wintitle=None, icon="guiqwt.png", edit=True,
 
517
                 toolbar=False, options=None, parent=None, panels=None,
 
518
                 param_cols=1, legend_anchor='TR', auto_fit=False):
 
519
        QDialog.__init__(self, parent)
 
520
        self.edit = edit
 
521
        self.button_layout = None
 
522
        FitWidgetMixin.__init__(self, wintitle, icon, toolbar, options, panels,
 
523
                                param_cols, legend_anchor, auto_fit)
 
524
        self.setWindowFlags(Qt.Window)
 
525
        
 
526
    def setup_widget_layout(self):
 
527
        FitWidgetMixin.setup_widget_layout(self)
 
528
        if self.edit:
 
529
            self.install_button_layout()
 
530
        
 
531
    def install_button_layout(self):        
 
532
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
 
533
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
 
534
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
 
535
        self.button_list += [bbox.button(QDialogButtonBox.Ok)]
 
536
 
 
537
        self.button_layout = QHBoxLayout()
 
538
        self.button_layout.addStretch()
 
539
        self.button_layout.addWidget(bbox)
 
540
        
 
541
        vlayout = self.layout()
 
542
        vlayout.addSpacing(10)
 
543
        vlayout.addLayout(self.button_layout)
 
544
        
 
545
 
 
546
def guifit(x, y, fitfunc, fitparams, fitargs=None, fitkwargs=None,
 
547
           wintitle=None, title=None, xlabel=None, ylabel=None,
 
548
           param_cols=1, auto_fit=True, winsize=None, winpos=None):
350
549
    """GUI-based curve fitting tool"""
351
550
    _app = guidata.qapplication()
352
 
    dlg = FitDialog(x, y, fitfunc, fitparams)
353
 
    if dlg.exec_():
354
 
        return dlg.get_values()
 
551
#    win = FitWidget(wintitle=wintitle, toolbar=True,
 
552
#                    param_cols=param_cols, auto_fit=auto_fit,
 
553
#                    options=dict(title=title, xlabel=xlabel, ylabel=ylabel))
 
554
    win = FitDialog(edit=True, wintitle=wintitle, toolbar=True,
 
555
                    param_cols=param_cols, auto_fit=auto_fit,
 
556
                    options=dict(title=title, xlabel=xlabel, ylabel=ylabel))
 
557
    win.set_data(x, y, fitfunc, fitparams, fitargs, fitkwargs)
 
558
    if winsize is not None:
 
559
        win.resize(*winsize)
 
560
    if winpos is not None:
 
561
        win.move(*winpos)
 
562
    if win.exec_():
 
563
        return win.get_values()
 
564
#    win.show()
 
565
#    _app.exec_()
 
566
#    return win.get_values()
355
567
 
356
568
 
357
569
if __name__ == "__main__":
361
573
        a, b = params
362
574
        return np.cos(b*x)+a
363
575
    a = FitParam("Offset", 1., 0., 2.)
364
 
    b = FitParam("Frequency", 2., 1., 10., logscale=True)
 
576
    b = FitParam("Frequency", 1.05, 0., 10., logscale=True)
365
577
    params = [a, b]
366
 
    values = guifit(x, y, fit, params)
 
578
    values = guifit(x, y, fit, params, auto_fit=True)
367
579
    print values
368
580
    print [param.value for param in params]