def plot_model_full(self, model, data, labels=True, paramvalues=None, offset=0, **kw): if self.no_fits: return if paramvalues is None: paramvalues = prepare_params(model.params, data.meta)[3] nsamples = self._get_samples(model, data) imin, imax = data.x_plot.argmin(), data.x_plot.argmax() xx = multi_linspace(data.x[imin], data.x[imax], nsamples) xxp = linspace(data.x_plot[imin], data.x_plot[imax], nsamples) yy = model.fcn(paramvalues, xx) if 'label' not in kw: kw['label'] = labels and 'fit' or '' self.axes.plot(xxp, yy + offset, 'g', lw=kw.pop('kw', 2), **kw) for comp in model.get_components(): if comp is model: continue yy = comp.fcn(paramvalues, xx) kw['label'] = labels and comp.name or '' self.axes.plot(xxp, yy + offset, '-.', **kw)
def simulate(self, data): varying, varynames, dependent, _ = prepare_params( self.params, data.meta) pd = dict((p.name, p.value) for p in self.params) update_params(dependent, data.meta, pd) yy = self.fcn(pd, data.x) new = data.copy() new.y = yy new.dy = zeros(len(yy)) return new
def export_fits(self, filename): xx = linspace(self.data.x.min(), self.data.x.max(), 1000) paramvalues = prepare_params(self.model.params, self.data.meta)[3] yy = self.model.fcn(paramvalues, xx) yys = [] for comp in self.model.get_components(): if comp is self.model: continue yys.append(comp.fcn(paramvalues, xx)) savetxt(filename, array([xx, yy] + yys).T)
def do_fit(data, fcn, params, add_kw): x, y, dy = data.fit_columns meta = data.meta varying, varynames, dependent, _ = prepare_params(params, meta) def leastsqfcn(params, data): pd = dict(zip(varynames, params)) update_params(dependent, meta, pd) return (fcn(pd, x) - y) / dy initpars = [] warned = False for p in varying: initpars.append(p.value) if (p.pmin is not None or p.pmax is not None) and not warned: print('Sorry, scipy backend cannot handle parameter bounds.') warned = True try: res = leastsq(leastsqfcn, initpars, args=(data, ), full_output=1, **add_kw) except Exception as e: return False, str(e), 0 popt, pcov, infodict, errmsg, ier = res success = (ier in [1, 2, 3, 4]) nfree = len(y) - len(varying) if nfree > 0 and pcov is not None: s_sq = (leastsqfcn(popt, data)**2).sum() / nfree pcov = pcov * s_sq else: pcov = inf pd = {} for i, p in enumerate(varying): pd[p.name] = popt[i] if pcov is not inf: p.error = sqrt(pcov[i, i]) else: p.error = 0 p.correl = {} # XXX update_params(dependent, meta, pd) for p in params: p.value = pd[p.name] return success, errmsg, get_chisqr(fcn, x, y, dy, params)
def do_fit(data, fcn, params, add_kw): # lmfit can handle expression-based parameters itself, but that is # a) buggy (cannot pass custom items into namespace without subclass) # and b) it is better to use the same mechanism in all backends x, y, dy = data.fit_columns meta = data.meta varying, varynames, dependent, _ = prepare_params(params, meta) lmfparams = Parameters() for p in varying: lmfparams.add(p.name, p.value, min=p.pmin, max=p.pmax) def lmfitfcn(lmfparams, data): pd = dict((pn, lmfparams[pn].value) for pn in varynames) update_params(dependent, meta, pd) return (fcn(pd, x) - y) / dy printReport = add_kw.pop('printReport', False) try: out = minimize(lmfitfcn, lmfparams, args=(data,), **add_kw) except Exception as e: print(str(e)) return False, str(e), 0 if printReport: report_fit(out.params) pd = dict((pn, out.params[pn].value) for pn in varynames) update_params(dependent, meta, pd) for p in params: p.value = pd[p.name] if p.name in lmfparams: p.error = out.params[p.name].stderr p.correl = out.params[p.name].correl else: p.error = 0 p.correl = {} # sadly, out.message is a bit buggy message = '' if not out.success: message = out.lmdif_message if not out.errorbars: message += ' Could not estimate error bars.' return out.success, message, out.redchi
def do_fit(data, fcn, params, add_kw): x, y, dy = data.fit_columns meta = data.meta varying, varynames, dependent, _ = prepare_params(params, meta) def minuitfcn(*args): pd = dict(zip(varynames, args)) update_params(dependent, meta, pd) return ((fcn(pd, x) - y)**2 / dy**2).sum() printReport = add_kw.pop('printReport', False) marg = dict( print_level=int(printReport), forced_parameters=varynames, ) marg.update(add_kw) if 'errordef' not in marg: marg['errordef'] = 1 for p in varying: marg[p.name] = p.value marg['error_' + p.name] = 100*p.delta or p.value/100. or 0.01 if p.pmin is not None or p.pmax is not None: marg['limit_' + p.name] = (p.pmin is None and -1e8 or p.pmin, p.pmax is None and +1e8 or p.pmax) m = Minuit(minuitfcn, **marg) try: m.migrad() m.hesse() except Exception as e: return False, str(e), 0 # m.minos() -> would calculate more exact and asymmetric errors pd = dict((pn, m.values[pn]) for pn in varynames) update_params(dependent, meta, pd) for p in params: p.value = pd[p.name] if p.name in varynames: p.error = m.errors[p.name] p.correl = {} # XXX else: p.error = 0 p.correl = {} return True, '', get_chisqr(fcn, x, y, dy, params)
def plot_model_components(self, model, data, labels=True, paramvalues=None, offset=0, **kw): if self.no_fits: return if paramvalues is None: paramvalues = prepare_params(model.params, data.meta)[3] nsamples = self._get_samples(model, data) imin, imax = data.x_plot.argmin(), data.x_plot.argmax() xx = multi_linspace(data.x[imin], data.x[imax], nsamples) xxp = linspace(data.x_plot[imin], data.x_plot[imax], nsamples) for comp in model.get_components(): yy = comp.fcn(paramvalues, xx) kw['label'] = labels and comp.name or '' self.axes.plot(xxp, yy + offset, kw.pop('fmt', '-.'), **kw)
def do_fit(data, fcn, params, add_kw): x, y, dy = data.fit_columns meta = data.meta varying, varynames, dependent, _ = prepare_params(params, meta) def leastsqfcn(x, params): pd = dict(zip(varynames, params)) update_params(dependent, meta, pd) return fcn(pd, x) initpars = [] initdp = [] warned = False for p in varying: initpars.append(p.value) initdp.append(p.delta or p.value / 10. or 0.01) if (p.pmin is not None or p.pmax is not None) and not warned: print('Sorry, unifit backend cannot handle parameter bounds.') warned = True try: res = __leastsq((x, y, dy), leastsqfcn, initpars, initdp, **add_kw) except Exception as e: raise return False, str(e), 0 success = res['converged'] errmsg = res['errmsg'] pd = {} for i, p in enumerate(varying): pd[p.name] = res['values'][i] p.error = res['errors'][i] p.correl = {} # XXX update_params(dependent, meta, pd) for p in params: p.value = pd[p.name] return success, errmsg, get_chisqr(fcn, x, y, dy, params)
def plot_model(self, model, data, labels=True, paramvalues=None, offset=0, **kw): if self.no_fits: return if paramvalues is None: paramvalues = prepare_params(model.params, data.meta)[3] nsamples = self._get_samples(model, data) imin, imax = data.x_plot.argmin(), data.x_plot.argmax() xx = multi_linspace(data.x[imin], data.x[imax], nsamples) xxp = linspace(data.x_plot[imin], data.x_plot[imax], nsamples) yy = model.fcn(paramvalues, xx) if 'label' not in kw: kw['label'] = labels and 'fit' or '' self.axes.plot(xxp, yy + offset, kw.pop('fmt', 'g'), lw=kw.pop('lw', 2), **kw)