def fit_gaussian_peak_step_background_2(x, y): # create data from broadened step npts = 201 x = np.linspace(0, 10, npts) y = step(x, amplitude=12.5, center=4.5, sigma=0.88, form='erf') y = y + np.random.normal(size=npts, scale=0.35) # create Composite Model using the custom convolution operator mod = CompositeModel(Model(jump), Model(gaussian), convolve) pars = mod.make_params(amplitude=1, center=3.5, sigma=1.5, mid=5.0) # 'mid' and 'center' should be completely correlated, and 'mid' is # used as an integer index, so a very poor fit variable: pars['mid'].vary = False # fit this model to data array y result = mod.fit(y, params=pars, x=x) print(result.fit_report()) plot_components = True # plot results plt.plot(x, y, 'bo') if plot_components: # generate components comps = result.eval_components(x=x) plt.plot(x, 10 * comps['jump'], 'k--') plt.plot(x, 10 * comps['gaussian'], 'r-') else: plt.plot(x, result.init_fit, 'k--') plt.plot(x, result.best_fit, 'r-') plt.show() # #<end examples/model_doc3.py> return fit_fwhm, fit_center, fwhm_err
def fit_composit(seq, *params, report=False): x = np.arange(len(seq)) y = seq amp, cen, wid = params cmodel = CompositeModel(Model(gaussian), Model(LognormalModel), ExponentialGaussianModel) pars = cmodel.make_params(amplitude=amp, center=cen, sigma=wid, mid=cen) # 'mid' and 'center' should be completely correlated, and 'mid' is # used as an integer index, so a very poor fit variable: pars['mid'].vary = False # fit this model to data array y result = cmodel.fit(y, params=pars, x=x) # limit the amplitude to be in 0-256 cmodel.set_param_hint('amp', min=0) cmodel.set_param_hint('amp', max=256) result = gmodel.fit(y, x=x, amp=amp, cen=cen, wid=wid) if result.redchi >= 1e3: # if report: plt.figure() plt.plot(x, y, 'bo') # plt.plot(x, result.init_fit, 'k--') plt.plot(x, np.ceil(result.best_fit), 'r-') plt.title('chi2: {0:.2e} - red_chi2: {0:.2e}'.format( result.chisqr, result.redchi)) plt.show() return result
def get_equivalent_circuit_model(modelname, logscale=False, diel=False): """Get LMFIT CompositeModel. Parameters ---------- modelname: str String representation of the equivalent circuit. logscale: bool Convert to logscale. diel: bool Convert to complex permittivity and fit this instead of impedance. Returns ------- :py:class:`lmfit.model.CompositeModel` or :class:`lmfit.model.Model` the final model of the entire circuit Notes ----- The parser is based on Pyparsing. It is sensitive towards extra `(` or `)` or `+`. Thus, keep the circuit simple. """ circuit = [] assert isinstance(modelname, str), "Pass the model as a string" str2parse = modelname.replace("parallel", "") circuit_elements = pp.Word(pp.srange("[a-zA-Z_0-9]")) plusop = pp.Literal('+') commaop = pp.Literal(',') expr = pp.infixNotation(circuit_elements, [(plusop, 2, pp.opAssoc.LEFT), (commaop, 2, pp.opAssoc.LEFT)]) try: circuitstr = expr.parseString(str2parse) except pp.ParseException: raise ("You must provide a correct string!") _check_circuit(circuitstr.asList()[0], startpar=modelname.startswith("parallel")) circuit = _process_circuit(circuitstr.asList()[0]) if logscale: circuit = CompositeModel(circuit, Model(dummy), log) elif diel: circuit = CompositeModel(circuit, Model(make_eps), eps) if logscale and diel: raise RuntimeError( "You must chose the representation of the impedance value") _check_models_suffix(circuit) logger.debug("Created composite model {}".format(circuit)) return circuit
def __init__(self, q, nLor=2, **kwargs): prefix = "" if "prefix" in kwargs.keys(): prefix = kwargs.pop("prefix") left = delta(q, prefix="%sdelta_" % prefix, **kwargs) right = lorentzian(q, prefix="%sl0_" % prefix, **kwargs) for i in range(1, nLor): right = CompositeModel( right, lorentzian(q, prefix="%sl%i_" % (prefix, i), **kwargs), operator.add, ) super().__init__(left, right, operator.add)
def _process_parallel(model): """Process parallel circuit. Parameters ---------- model: list Contains the parallel circuit as a nested list. Returns ------- :py:class:`lmfit.model.CompositeModel` The CompositeModel of the parallel circuit. """ assert len(model) == 3, "The model must be [model1, ',' , model2]" first_model = model[0] second_model = model[2] first = _process_element(first_model) second = _process_element(second_model) return CompositeModel(first, second, parallel)
# code from https://lmfit.github.io/lmfit-py/model.html def convolve(arr, kernel): # simple convolution of two arrays npts = min(len(arr), len(kernel)) pad = np.ones(npts) tmp = np.concatenate((pad * arr[0], arr, pad * arr[-1])) out = np.convolve(tmp, kernel, mode='valid') noff = int((len(out) - npts) / 2) return out[noff:noff + npts] # Create model for the fit gmodel = CompositeModel(Model(irf_gate), Model(model_2lorentzians), convolve) print('Names of parameters:', gmodel.param_names) print('Independent variable(s):', gmodel.independent_vars) # Load reference data - extract x and y values two_lorentzians_iris = np.loadtxt(path_to_data + 'data_2lorentzians.dat') xx = two_lorentzians_iris[:, 0] yy = two_lorentzians_iris[:, 1] # Fit result = gmodel.fit(yy, x=xx, scale1=1., center1=0., hwhm1=0.25,
o = np.zeros(len(x)) imid = max(np.where(x<=mid)[0]) o[imid:] = 1.0 return o def convolve(arr, kernel): # simple convolution of two arrays npts = min(len(arr), len(kernel)) pad = np.ones(npts) tmp = np.concatenate((pad*arr[0], arr, pad*arr[-1])) out = np.convolve(tmp, kernel, mode='valid') noff = int((len(out) - npts)/2) return out[noff:noff+npts] # # create Composite Model using the custom convolution operator mod = CompositeModel(Model(jump), Model(gaussian), convolve) pars = mod.make_params(amplitude=1, center=3.5, sigma=1.5, mid=5.0) # 'mid' and 'center' should be completely correlated, and 'mid' is # used as an integer index, so a very poor fit variable: pars['mid'].vary = False # fit this model to data array y result = mod.fit(y, params=pars, x=x) print(result.fit_report()) plot_components = False # plot results
# Create convolution function # code from https://lmfit.github.io/lmfit-py/model.html def convolve(arr, kernel): # simple convolution of two arrays npts = min(len(arr), len(kernel)) pad = np.ones(npts) tmp = np.concatenate((pad * arr[0], arr, pad * arr[-1])) out = np.convolve(tmp, kernel, mode='valid') noff = int((len(out) - npts) / 2) return out[noff:noff + npts] model = CompositeModel(Model(irf_gate), Model(QENSmodels.sqwWaterTeixeira), convolve) print('Names of parameters:', model.param_names) print('Independent variable(s):', model.independent_vars) # Define boundaries for parameters to be refined model.set_param_hint('scale', min=0, max=100) model.set_param_hint('center', min=-0.1, max=0.1) model.set_param_hint('D', min=0.05, max=0.25) model.set_param_hint('resTime', min=0, max=1) model.set_param_hint('radius', min=0.9, max=1.1) model.set_param_hint('DR', min=0, max=1) # Fix some of the parameters model.set_param_hint('q', vary=False) model.set_param_hint('spectrum_nb', vary=False)
def _convolve( self, left, right, params=None, returnComponents=None, **kwargs ): r"""Perform a convolution between `left` and `right`. If the convolutions between function in `left` and the function in `right` is defined in `convolutions` attribute, then use this corresponding function for analytical convolution. Else, the behavior is determined by the `on_undefined_conv` parameter. Parameters ---------- left : :class:`Model` or :class:`CompositeModel` Model or CompositeModel to be used for convolution. right : :class:`Model` or :class:`CompositeModel` Model or CompositeModel to be used for convolution. params : Parameters, optional Parameters to be given to the model functions. kwargs : dict Additional keyword arguments to pass to the model functions. Returns ------- An array containing the result of the convolution. Notes ----- This composition of models works differently than for other operators, as the operators is applied between each pair of components in left and right components. That is, for ``left = a1 + a2 - a3`` and ``right = b1 * b2``, where a's and b's are instances of :class:`Model` class: .. math:: left \otimes right = (a_1 \otimes b_1 * a_1 \otimes b_2) + (a_2 \otimes b_1 * a_2 \otimes b_2) - (a_3 \otimes b_1 * a_3 \otimes b_2) """ if returnComponents == "right": tmp = left left = right right = tmp lcomponents = left.components rcomponents = right.components lops, rops = self._operators() models = [] compPrefix = [] for lcomp in lcomponents: tmpRes = [] for rcomp in rcomponents: if lcomp.func.__name__ in self.convMap.keys(): funcName = rcomp.func.__name__ leftConvMap = self.convMap[lcomp.func.__name__] if funcName in leftConvMap.keys(): if params is None: params = self.make_params() convFunc = leftConvMap[funcName] tmpRes.append(convFunc(lcomp, rcomp, params, **kwargs)) else: if self._on_undefined_conv == "numeric": convFunc = lambda l, r: fftconvolve( l, r, mode="same", axes=-1 ) tmpRes.append( CompositeModel(lcomp, rcomp, convFunc).eval( params, **kwargs ) ) elif self._on_undefined_conv == "raise": raise KeyError( "Convolution function between %s and %s is " "not defined." % (lcomp.func.__name__, funcName) ) else: if self._on_undefined_conv == "numeric": convFunc = lambda l, r: fftconvolve( l, r, mode="same", axes=-1 ) tmpRes.append( CompositeModel(lcomp, rcomp, convFunc).eval( params, **kwargs ) ) # apply operators from the right if len(tmpRes) > 1: for idx, rop in enumerate(rops): tmpRes[0] = rop(tmpRes[idx], tmpRes[idx + 1]) models.append(tmpRes[0]) compPrefix.append(lcomp.prefix) if returnComponents is None: # finally apply operators from the left if len(models) > 1: for idx, lop in enumerate(lops): models[0] = lop(models[idx], models[idx + 1]) return models[0] else: out = OrderedDict() for val in zip(compPrefix, models): out[val[0]] = val[1] return out
return o def convolve(arr, kernel): # simple convolution of two arrays npts = min(len(arr), len(kernel)) pad = np.ones(npts) tmp = np.concatenate((pad * arr[0], arr, pad * arr[-1])) out = np.convolve(tmp, kernel, mode='valid') noff = int((len(out) - npts) / 2) return out[noff:noff + npts] # # create Composite Model using the custom convolution operator mod = CompositeModel(Model(jump), Model(gaussian), convolve) pars = mod.make_params(amplitude=1, center=3.5, sigma=1.5, mid=5.0) # 'mid' and 'center' should be completely correlated, and 'mid' is # used as an integer index, so a very poor fit variable: pars['mid'].vary = False # fit this model to data array y result = mod.fit(y, params=pars, x=x) print(result.fit_report()) plot_components = False # plot results