Beispiel #1
0
def fit_data_bg(x, y, peak_pos, peak_type='LO', width=None, bg_ord=0):
    """ 
    Builds a lmfit model of peaks in listed by index in `peak_pos`

    Parameters
    ----------
    peak_type : string (default='lorentizian')
        Peaks can be of the following types:

        - 'LO' : symmetric lorentzian
        - 'GA' : symmetric gaussain
        - 'VO' : symmetric pseudo voigt

    max_width : int (default = total points/10)
        max width (in data points) that peak fitted can be

    bg_ord: int
        order of the background polynomial
        0: constant, 1: linear, ...

    Returns
    -------
    out: 
        fitted model

    """
    # need to define peak width finding
    if width is None:
        width = guess_peak_width(x, y)
    
    # start with polynomial background
    model = PolynomialModel(bg_ord, prefix='bg_')
    pars = model.make_params()

    if peak_type == 'LO':
        peak_function = lorentzian
    elif peak_type == 'GA':
        peak_function = gaussian
    elif peak_type == 'VO':
        peak_function = voigt

    # add peak type for all peaks
    for i, peak in enumerate(peak_pos):
        temp_model = Model(peak_function, prefix='p%s_' % i)
        pars.update(temp_model.make_params())
        model += temp_model

    # set initial background as flat line at zeros
    for i in range(bg_ord + 1):
        pars['bg_c%i' % i].set(0)

    # give values for other peaks, keeping width and height positive
    for i, peak in enumerate(peak_pos):
        pars['p%s_x0' % i].set(x[peak])
        pars['p%s_fwhm' % i].set(width, min=0)
        pars['p%s_amp' % i].set(y[peak], min=0)

    out = model.fit(y, pars, x=x)
    return out
Beispiel #2
0
def fit_experimental_data_gauss(exp_x,
                                exp_y,
                                expected_peak_pos,
                                deg_of_bck_poly=5,
                                maxfev=25000):
    num_of_peaks = len(expected_peak_pos)
    mod = PolynomialModel(deg_of_bck_poly, prefix='poly_')
    for c in range(num_of_peaks):
        mod = mod + PseudoVoigtModel(prefix='p{}_'.format(c))

    params = mod.make_params()

    center = 0
    sigma = 0
    amplitude = 0
    fraction = 0
    for param in params:
        if 'center' in param:
            params[param].set(value=expected_peak_pos[center])
            params[param].set(min=expected_peak_pos[center] - 0.5)
            params[param].set(max=expected_peak_pos[center] + 0.5)
            center += 1
        if 'poly' in param:
            if param == 'poly_c0':
                params[param].set(value=50)
                params[param].set(min=-100)
                params[param].set(max=100)
                continue
            if param == 'poly_c1':
                params[param].set(value=-1)
                params[param].set(min=-100)
                params[param].set(max=100)
                continue
            params[param].set(value=0)


##            params[param].set(min = 3e-1)
##            params[param].set(max = 3e-1)
        if 'sigma' in param:
            params[param].set(value=0.5)
            params[param].set(min=0.0001)
            params[param].set(max=0.8)
            sigma += 1
        if 'amplitude' in param:
            params[param].set(value=5.5)
            params[param].set(min=0.0001)
            amplitude += 1
        if 'fraction' in param:
            params[param].set(value=0.0)
            params[param].set(min=0.000)
            params[param].set(max=0.000001)
            fraction += 1
    result = mod.fit(np.asarray(exp_y),
                     params,
                     x=np.asarray(exp_x),
                     fit_kws={'maxfev': maxfev})

    print(result.fit_report())
    return result
Beispiel #3
0
def fit_data_bg(x, y, peak_pos, peak_type="LO", width=None, bg_ord=0):
    """ 
    Builds a lmfit model of peaks in listed by index in `peak_pos`

    Parameters
    ----------
    peak_type : string (default='lorentizian')
        Peaks can be of the following types:

        - 'LO' : symmetric lorentzian
        - 'GA' : symmetric gaussain
        - 'VO' : symmetric pseudo voigt

    max_width : int (default = total points/10)
        max width (in data points) that peak fitted can be

    bg_ord: int
        order of the background polynomial
        0: constant, 1: linear, ...

    Returns
    -------
    out: 
        fitted model

    """
    # need to define peak width finding
    if width is None:
        width = guess_peak_width(x, y)

    # start with polynomial background
    model = PolynomialModel(bg_ord, prefix="bg_")
    pars = model.make_params()

    if peak_type == "LO":
        peak_function = lorentzian
    elif peak_type == "GA":
        peak_function = gaussian
    elif peak_type == "VO":
        peak_function = voigt

    # add peak type for all peaks
    for i, peak in enumerate(peak_pos):
        temp_model = Model(peak_function, prefix="p%s_" % i)
        pars.update(temp_model.make_params())
        model += temp_model

    # set initial background as flat line at zeros
    for i in range(bg_ord + 1):
        pars["bg_c%i" % i].set(0)

    # give values for other peaks, keeping width and height positive
    for i, peak in enumerate(peak_pos):
        pars["p%s_x0" % i].set(x[peak])
        pars["p%s_fwhm" % i].set(width, min=0)
        pars["p%s_amp" % i].set(y[peak], min=0)

    out = model.fit(y, pars, x=x)
    return out
def bg_sub(raman_spectra,
           plot_each=False,
           reduce_region=[3090, 4000],
           cut_region=[3150, 3722],
           order=2,
           to_run='all'):
    bg = PolynomialModel(order)

    flag = False
    if type(raman_spectra) == AHR.RamanSpectrum:
        raman_spectra = {'a': raman_spectra}
        flag = True

    BGsub = {}
    for key, spec in raman_spectra.items():
        if to_run != 'all':
            if key not in to_run:
                continue
        spec_red = spec.reduce_wn_region(reduce_region)
        spec_cut = spec_red.cut_wn_region(cut_region)
        spec_cut_x = spec_cut.wn
        spec_cut_y = np.squeeze(spec_cut.spec_data.T)

        bg_params = bg.make_params(c0=0,
                                   c1=0,
                                   c2=0,
                                   c3=0,
                                   c4=0,
                                   c5=5,
                                   c6=0,
                                   c7=0)
        bg_fit = bg.fit(spec_cut_y, x=spec_cut_x, params=bg_params)

        spec_red_bg_sub = AHR.RamanSpectrum(
            spec_red.wn,
            np.squeeze(spec_red.spec_data.T) - bg_fit.eval(x=spec_red.wn))

        BGsub[key] = spec_red_bg_sub

        if plot_each:

            fig, ax = plt.subplots()
            ax.plot(spec_red.wn, spec_red.spec_data.T)
            ax.scatter(spec_cut.wn, spec_cut.spec_data.T, s=3, color='orange')
            ax.plot(spec_red.wn, bg_fit.eval(x=spec_red.wn))
            ax.set_title(key)
    if flag:
        return BGsub['a']
    else:
        return BGsub
Beispiel #5
0
 def prepare_for_fitting(self, poly_order, maxwidth, centerrange):
     """
     :param x_center: numpy array of initial x values at picked centers
     :param y_center: numpy array of initial y values at picked centers
     :param fwhm: single float number for initial fwhm value
     """
     self.set_baseline(poly_order)
     baseline_mod = PolynomialModel(poly_order, prefix='b_')
     mod = baseline_mod
     pars = baseline_mod.make_params()
     peakinfo = {}
     for i in range(poly_order + 1):
         prefix = "b_c{0:d}".format(i)
         pars[prefix].set(value=self.baseline_in_queue[i]['value'],
                          vary=self.baseline_in_queue[i]['vary'])
     i = 0
     for peak in self.peaks_in_queue:
         prefix = "p{0:d}_".format(i)
         peak_mod = PseudoVoigtModel(prefix=prefix, )
         pars.update(peak_mod.make_params())
         pars[prefix + 'center'].set(value=peak['center'],
                                     min=peak['center'] - centerrange,
                                     max=peak['center'] + centerrange,
                                     vary=peak['center_vary'])
         pars[prefix + 'sigma'].set(value=peak['sigma'],
                                    min=0.0,
                                    vary=peak['sigma_vary'],
                                    max=maxwidth)
         pars[prefix + 'amplitude'].set(value=peak['amplitude'],
                                        min=0,
                                        vary=peak['amplitude_vary'])
         pars[prefix + 'fraction'].set(value=peak['fraction'],
                                       min=0.,
                                       max=1.,
                                       vary=peak['fraction_vary'])
         peakinfo[prefix + 'phasename'] = peak['phasename']
         peakinfo[prefix + 'h'] = peak['h']
         peakinfo[prefix + 'k'] = peak['k']
         peakinfo[prefix + 'l'] = peak['l']
         mod += peak_mod
         i += 1
     self.parameters = pars
     self.peakinfo = peakinfo
     self.fit_model = mod
def fitTwoGaussians(x,y):
	background  = PolynomialModel(2)
	pars = background.make_params()
	peak1 = GaussianModel(prefix='p1_')
	pars.update( peak1.make_params())
	peak2 = GaussianModel(prefix='p2_')
	pars.update( peak2.make_params())
	# Guess some parameters from data to help the fitting
	span = max(x)-min(x)
	c1Guess = (y[-1]-y[0])/(x[-1]-x[0])
	c0Guess = y[0]-c1Guess*x[0]
	bgGuess = background.func(x=x,c0=c0Guess,c1=c1Guess,c2=0.)
	signalGuess=min(y-bgGuess)
	sigmaGuess = span/30.
	amplitudeGuess = signalGuess*(sigmaGuess*np.sqrt(2.0*np.pi))
	# Fit variables initialization
	
	# pars.add('splitting',0.0001,max=span)
	
	pars['c2'].set(0.,min=-0.000001,max=0.001)
	pars['c1'].set(c1Guess)
	pars['c0'].set(c0Guess)
	pars['p1_center'].set(min(x)+span*0.35,min=min(x),max=max(x))
	pars['p2_center'].set(min(x)+span*0.55,min=min(x),max=max(x))
	# pars['p2_center'].set(min(x)+span*0.65,expr='p1_center+splitting')
	pars['p1_amplitude'].set(amplitudeGuess,max=amplitudeGuess/10000.)
	pars['p2_amplitude'].set(amplitudeGuess,max=amplitudeGuess/10000.)
	pars['p1_sigma'].set(sigmaGuess, min=sigmaGuess/100.,max=sigmaGuess*10000.)
	pars['p2_sigma'].set(sigmaGuess, min=sigmaGuess/100.,max=sigmaGuess*10000.)
	#Add some useful parameters to evaluate
	pars.add('p1_signal', expr='p1_amplitude/(p1_sigma*sqrt(2.0*pi))')
	pars.add('p2_signal', expr='p2_amplitude/(p2_sigma*sqrt(2.0*pi))')
	pars.add('p1_contrast', expr='-p1_amplitude/(p1_sigma*sqrt(2.0*pi)*(c0+c1*p1_center+c2*p1_center**2))')
	pars.add('p2_contrast', expr='-p2_amplitude/(p2_sigma*sqrt(2.0*pi)*(c0+c1*p2_center+c2*p2_center**2))')
	pars.add('splitting',pars['p2_center']-pars['p1_center'],expr='p2_center-p1_center',min=0.00001)
	model = peak1 + peak2 + background
	init = model.eval(pars, x=x)
	out = model.fit(y, pars, x=x)
	# print out.fit_report()
	return init,out
Beispiel #7
0
def build_model_dd(bg_ord=1, peak_num=1, peak_type="lorentzian"):
    model = PolynomialModel(bg_ord, prefix="bg_")

    peak_str = peak_type.lower()[:2]

    if peak_str == "lo":
        peak_function = lorentzian_dd
    elif peak_str == "ga":
        peak_function = gaussian_dd
    elif peak_str == "vo" or peak_type == "ps":
        peak_function = voigt
    else:
        print(
            "'peak_type' should be one of 'lorentzian', 'gaussian' or 'pseudo-voight'"
        )
        return

    for i in range(peak_num):
        model += Model(peak_function, prefix="p%s_" % i)

    params = model.make_params()
    return model, params
Beispiel #8
0
    def build_model(self, peak_type='LO', max_width=None, bg_ord=2):
        """ Builds a lmfit model of peaks in listed by index in `peak_pos`
        Uses some basic algorithms to determine initial parameters for
        amplitude and fwhm (limit on fwhm to avoid fitting background as peaks)

        Parameters
        ----------
        peak_type : string (default='lorentizian')
            Peaks can be of the following types:

            - 'LO' : symmetric lorentzian
            - 'GA' : symmetric gaussain

        max_width : int (default = total points/10)
            max width (in data points) that peak fitted can be

        bg_ord: int
            order of the background polynomial
            0: constant, 1: linear, ...

        Returns
        -------
        pars : model parameters
        model : model object


        """
        x = self.x
        y = self.y
        pw = self.test_peak_width
        peak_guess = self.x[self.peak_pos]
        print("Building model ... ")

        # start with polynomial background
        # second order
        model = PolynomialModel(bg_ord, prefix='bg_')
        pars = model.make_params()

        if peak_type == 'LO':
            peak_function = lorentzian
            self.afactor = pi
            self.wfactor = 2.0
        elif peak_type == 'GA':
            peak_function = gaussian
            self.afactor = sqrt(2 * pi)
            self.wfactor = 2.354820
        elif peak_type == 'VO':
            peak_function = voigt
            self.afactor = sqrt(2 * pi)
            self.wfactor = 3.60131

        # add lorentizian peak for all peaks
        for i, peak in enumerate(peak_guess):
            temp_model = Model(peak_function, prefix='p%s_' % i)
            pars.update(temp_model.make_params())
            model += temp_model

        # set inital background as flat line at zeros
        for i in range(bg_ord + 1):
            pars['bg_c%i' % i].set(0)

        # give values for other peaks
        for i, peak in enumerate(self.peak_pos):
            print('Peak %i: pos %s, height %s' % (i, x[peak], y[peak]))
            # could set bounds #, min=x[peak]-5, max=x[peak]+5)
            pars['p%s_center' % i].set(x[peak])
            pars['p%s_sigma' % i].set(pw / 2, min=pw * 0.25, max=pw * 2)
            # here as well #, min=0, max=2*max(y))
            pars['p%s_amplitude' % i].set(self.amplitude(y[peak], (pw / 2)))

        self.pars = pars
        self.model = model
        return self.pars, self.model
Beispiel #9
0
def fit_data(x, y, peak_pos, peak_type='LO', max_width=None, bg_ord=2):
    """ Builds a lmfit model of peaks in listed by index in `peak_pos`
    Uses some basic algorithms to determine initial parameters for
    amplitude and fwhm (limit on fwhm to avoid fitting background as peaks)

    Parameters
    ----------
    peak_type : string (default='lorentizian')
        Peaks can be of the following types:

        - 'LO' : symmetric lorentzian
        - 'GA' : symmetric gaussain
        - 'VO' : symmetric pseudo voigt

    max_width : int (default = total points/10)
        max width (in data points) that peak fitted can be

    bg_ord: int
        order of the background polynomial
        0: constant, 1: linear, ...

    Returns
    -------
    pars : model parameters
    model : model object


    """
    # need to define peak width finding
    pw = guess_peak_width(x, y)
    peak_guess = x[peak_pos]

    # start with polynomial background
    model = PolynomialModel(bg_ord, prefix='bg_')
    pars = model.make_params()

    if peak_type == 'LO':
        peak_function = lorentzian
    elif peak_type == 'GA':
        peak_function = gaussian
    elif peak_type == 'VO':
        peak_function = voigt

    # add lorentizian peak for all peaks
    for i, peak in enumerate(peak_guess):
        temp_model = Model(peak_function, prefix='p%s_' % i)
        pars.update(temp_model.make_params())
        model += temp_model

    # set inital background as flat line at zeros
    for i in range(bg_ord + 1):
        pars['bg_c%i' % i].set(0)

    # give values for other peaks
    for i, peak in enumerate(peak_pos):
        # could set bounds #, min=x[peak]-5, max=x[peak]+5)
        pars['p%s_x0' % i].set(x[peak])
        pars['p%s_fwhm' % i].set(pw / 2, min=pw * 0.25, max=pw * 2)
        # here as well #, min=0, max=2*max(y))
        pars['p%s_amp' % i].set(y[peak])

    out = model.fit(y, pars, x=x)
    return out
Beispiel #10
0
    def build_model(self, peak_type="LO", max_width=None, bg_ord=2):
        """ Builds a lmfit model of peaks in listed by index in `peak_pos`
        Uses some basic algorithms to determine initial parameters for
        amplitude and fwhm (limit on fwhm to avoid fitting background as peaks)

        Parameters
        ----------
        peak_type : string (default='lorentizian')
            Peaks can be of the following types:

            - 'LO' : symmetric lorentzian
            - 'GA' : symmetric gaussain

        max_width : int (default = total points/10)
            max width (in data points) that peak fitted can be

        bg_ord: int
            order of the background polynomial
            0: constant, 1: linear, ...

        Returns
        -------
        pars : model parameters
        model : model object


        """
        x = self.x
        y = self.y
        pw = self.test_peak_width
        peak_guess = self.x[self.peak_pos]
        print("Building model ... ")

        # start with polynomial background
        # second order
        model = PolynomialModel(bg_ord, prefix="bg_")
        pars = model.make_params()

        if peak_type == "LO":
            peak_function = lorentzian
            self.afactor = pi
            self.wfactor = 2.0
        elif peak_type == "GA":
            peak_function = gaussian
            self.afactor = sqrt(2 * pi)
            self.wfactor = 2.354820
        elif peak_type == "VO":
            peak_function = voigt
            self.afactor = sqrt(2 * pi)
            self.wfactor = 3.60131

        # add lorentizian peak for all peaks
        for i, peak in enumerate(peak_guess):
            temp_model = Model(peak_function, prefix="p%s_" % i)
            pars.update(temp_model.make_params())
            model += temp_model

        # set inital background as flat line at zeros
        for i in range(bg_ord + 1):
            pars["bg_c%i" % i].set(0)

        # give values for other peaks
        for i, peak in enumerate(self.peak_pos):
            print("Peak %i: pos %s, height %s" % (i, x[peak], y[peak]))
            # could set bounds #, min=x[peak]-5, max=x[peak]+5)
            pars["p%s_center" % i].set(x[peak])
            pars["p%s_sigma" % i].set(pw / 2, min=pw * 0.25, max=pw * 2)
            # here as well #, min=0, max=2*max(y))
            pars["p%s_amplitude" % i].set(self.amplitude(y[peak], (pw / 2)))

        self.pars = pars
        self.model = model
        return self.pars, self.model
Beispiel #11
0
def fit(spectra, obj, sigma=2.0, ord=4, iter=4):
    
    poly = PolynomialModel(3)
    pars = poly.make_params()
    for p in range(4):
        label = 'c'+str(p)
        pars[label].set(value=1., vary=True)
    wkcopy = np.copy(spectra[1])
    truesp = [i for i in wkcopy if i > 5]
    truex = [spectra[0][i] for i in range(len(spectra[1])) if spectra[1][i] > 5]
    outcont = poly.fit(truesp, pars, x=truex)
    firstcont = outcont.eval(x=spectra[0])
    
    xn = np.copy(spectra[0])
    yn = np.copy(spectra[1])/firstcont
    
    pl1=plt.subplot((iter+1)*100+11)
    pl1.plot(xn, spectra[1], 'k-', linewidth=0.3)
    pl1.plot(xn, firstcont, 'r-', linewidth=0.6)
    pl1.set_ylim([0, np.mean(firstcont)*1.5])
    
    for i in range(iter):
        i_=np.copy(i)
        niter=str(i_+1)
        sigma = sigma-i*0.21*sigma
        
        md = np.median(yn)
        n = len([i for i in yn if i > 0.1])
        offset = (len(xn)-n)/2
        absor = md - min(yn[offset:n-offset])
        freq, bin = np.histogram(yn, bins=50, range=(md-absor, md+absor))
        rebin = [(bin[b+1]+bin[b])/2 for b in range(len(bin)-1)]
        
        
        gauss = SkewedGaussianModel()
        pars = gauss.make_params()
        pars['center'].set(value=md, vary=True)
        pars['amplitude'].set(vary=True)
        pars['sigma'].set(vary=True)
        pars['gamma'].set(vary=True)
        out = gauss.fit(freq, pars, x=rebin)
        
        var = sigma*out.best_values['sigma']
        xrbn = np.linspace(rebin[0], rebin[-1], num=100)
        yrbn = list(out.eval(x=xrbn))
        mode = xrbn[yrbn.index(max(yrbn))]
        
        ync = np.copy(spectra[1])
        xnc = np.copy(spectra[0])
        
        mask = []
        for j in range(len(yn)):
            if (yn[j] > mode+var/2) or (yn[j] < mode-var/2):
                mask.append(False)
            else:
                mask.append(True)
        mask = np.array(mask)
        ync = ync[mask]
        xnc = xnc[mask]
        
        poly2 = PolynomialModel(ord)
        pars2 = poly2.make_params()
        for p in range(ord+1):
            label = 'c'+str(p)
            pars2[label].set(value=1., vary=True)
        outcont2 = poly2.fit(ync, pars2, x=xnc)
        
        contf = outcont2.eval(x=xn)
        yn = spectra[1]/contf
        err = spectra[2]/contf
        
        pln=plt.subplot(int((iter+1)*100+10+(i_+2)))
        pln.plot(xn, yn*(np.mean(contf)*0.8), 'k-', linewidth=0.3)
        pln.plot(xnc, ync, 'r-', linewidth=0.3)
        pln.plot(xn, contf, 'b-', linewidth=0.6)
        pln.set_ylim([0, np.mean(contf)*1.2])
        
    plt.savefig(obj[0]+'_fit.png', dpi=300)
    plt.clf()
        
    return np.array([xn, yn, err])
def fit(spectra, sigma=4.0, ptreg=8., ord=4, iter=2):
    rej = []
    for i, w in enumerate(spectra[1]):
        if w <= 0:
            rej.append(i)
    spectra[0] = np.delete(spectra[0], rej)
    spectra[1] = np.delete(spectra[1], rej)

    # prepare first kick
    poly = PolynomialModel(3)
    pars = poly.make_params()
    for p in range(4):
        label = 'c' + str(p)
        pars[label].set(value=1., vary=True)
    wkcopy = np.copy(spectra[1])
    truesp = [i for i in wkcopy if i >= 0]
    truex = [
        spectra[0][i] for i in range(len(spectra[1])) if spectra[1][i] >= 0
    ]
    outcont = poly.fit(truesp, pars, x=truex)
    firstcont = outcont.eval(x=spectra[0])

    xn = np.copy(spectra[0])
    yn = np.copy(spectra[1]) / firstcont

    # start cont. cleaning iterations
    for i in range(iter):
        i_ = np.copy(i)
        niter = str(i_ + 1)
        sigma = sigma - i * 0.21 * sigma

        md = np.median(yn)
        n = len([i for i in yn if i > 0.1])
        offset = (len(xn) - n) / 2
        absor = md - min(yn[offset:n - offset])
        freq, bin = np.histogram(yn, bins=50, range=(md - absor, md + absor))
        rebin = [(bin[b + 1] + bin[b]) / 2 for b in range(len(bin) - 1)]

        gauss = SkewedGaussianModel()
        pars = gauss.make_params()
        pars['center'].set(vary=True)
        pars['amplitude'].set(vary=True)
        pars['sigma'].set(vary=True)
        pars['gamma'].set(vary=True)
        out = gauss.fit(freq, pars, x=rebin)

        var = sigma * out.best_values['sigma']
        xrbn = np.linspace(rebin[0], rebin[-1], num=100)
        yrbn = list(out.eval(x=xrbn))
        mode = xrbn[yrbn.index(max(yrbn))]

        # clean cont.
        ync = np.copy(spectra[1])
        xnc = np.copy(spectra[0])

        mask = []
        for j in range(len(yn)):
            if (yn[j] > mode + var / 2) or (yn[j] < mode - var / 2):
                mask.append(False)
            else:
                mask.append(True)
        mask = np.array(mask)
        ync = ync[mask]
        xnc = xnc[mask]

        # re-fitting
        poly2 = PolynomialModel(ord)
        pars2 = poly2.make_params()
        for p in range(ord + 1):
            label = 'c' + str(p)
            pars2[label].set(value=1., vary=True)
        try:
            outcont2 = poly2.fit(ync, pars2, x=xnc)
        except:
            plt.plot(xn, yn, 'k-')
            plt.plot([xn[0], xn[-1]], [mode, mode], 'b-')
            plt.plot([xn[0], xn[-1]], [mode + var / 2, mode + var / 2], 'r-')
            plt.plot([xn[0], xn[-1]], [mode - var / 2, mode - var / 2], 'r-')
            plt.show()

        contf = outcont2.eval(x=xn)
        yn = spectra[1] / contf

    clspec = [xnc, ync]

    # start slicing
    firstv = clspec[0][0]
    wavrange = clspec[0][-1] - firstv
    sliceno = wavrange / ptreg
    slisize = wavrange / sliceno
    points = [[], []]

    # continuum point definition
    for s in range(int(sliceno)):
        i = bissec(clspec[0], firstv + s * slisize)
        f = bissec(clspec[0], firstv + (s + 1) * slisize)
        slc = [clspec[0][i:f], clspec[1][i:f]]
        if len(slc[1]) > 2.:
            md = np.median(slc[1])
            absor = min(slc[1])
            high = max(slc[1])
            freq, bin = np.histogram(slc[1], bins=20, range=(absor, high))
            rebin = [(bin[b + 1] + bin[b]) / 2 for b in range(len(bin) - 1)]

            fmode = rebin[list(freq).index(max(freq))]
            fsigma = rebin[-1] - rebin[0]

            gauss = GaussianModel()
            pars = gauss.make_params()
            pars['center'].set(value=fmode, vary=True)
            pars['amplitude'].set(value=max(freq), vary=True)
            pars['sigma'].set(value=fsigma, vary=True)
            out = gauss.fit(freq, pars, x=rebin)

            xrbn = np.linspace(rebin[0], rebin[-1], num=100)
            yrbn = list(out.eval(x=xrbn))
            mode = xrbn[yrbn.index(max(yrbn))]
            xp = slc[0][len(slc[0]) / 2]
            points[0].append(xp)
            points[1].append(mode)

    spline = splrep(points[0], points[1], k=3)
    contx = splev(clspec[0], spline)
    continuum = splev(spectra[0], spline)

    return [spectra[0], spectra[1] / continuum]