コード例 #1
0
    def FitBaseline(self, x, y, xregion, show=False, degree=1):
        """
        Fit of the baseline by using the
        `PolynomalModel()
        <https://lmfit.github.io/lmfit-py/builtin_models.html#lmfit.models.PolynomialModel>`_
        from lmfit.

        Parameters
        ----------
        x : numpy.array
            x-values of spectrum which should be background-corrected.

        y : numpy.array
            y-values of spectrum which should be background-corrected.

        show : boolean, default: False
            Decides whether the a window with the fitted baseline is opened
            or not.

        degree : int, default: 1
            Degree of the polynomial that describes the background.

        Returns
        -------
        baseline : numpy.array
            Baseline of the input spectrum.
        """
        relevant = self.CreateMask(x, xregion)
        # polynomial to model the background
        background = PolynomialModel(degree=degree)
        pars = background.guess(y[relevant], x=x[relevant])
        fitresult = background.fit(y[relevant], pars, x=x[relevant])

        return fitresult
コード例 #2
0
def readFits(inFile):
    #import the relevant modules

    table = pyfits.open(name)
    data = table[1].data
    flux = data.field('flux')
    wavelength = 10**(data.field('loglam'))
    ivar = data.field('ivar')
    weights = ivar
    redshift_data = table[2].data.field('Z')
    #y_av = toolkit.movingaverage(flux, 50)
    #coefs = poly.polyfit(wavelength, flux, 8, w=ivar)
    #ffit = poly.polyval(wavelength, coefs)

    mod2 = PolynomialModel(6)
    pars = mod2.guess(flux, x=wavelength)
    out = mod2.fit(flux, pars, x=wavelength)
    #print(out.fit_report(min_correl=0.25))
    #plt.plot(wavelength, out.best_fit, 'r-', linewidth=2)

    #Choose to plot the results
    #plt.plot(wavelength, flux, label='flux')
    #plt.plot(wavelength, y_av, label='boxcar')
    #plt.plot(wavelength, ffit , label='fit')
    #legend()
    #plt.show()
    #plt.close('all')

    return {
        'flux': flux,
        'wavelength': wavelength,
        'z': redshift_data,
        'continuum': out.best_fit,
        'error': weights
    }
コード例 #3
0
    def fit_polynomial(self, max_degree: int = 7) -> List[float]:
        """
        Fit the highest degree polynomial possible with the available energy data. (0 degree is actually 1st degree with 0 shift)

        Parameters:
            max_degree (int): Max degree of polynomial to try and fit. (Max possible: 7)

        Returns:
            (List[Float]): The polynomial coefficients from highest degree to the constant term 
        """
        energies = self.refined_energies if self.refined_energies else self.energies
        if not energies:
            raise ValueError("No known energies found for strip {}".format(
                self.number))

        degree = min(
            len(energies) -
            1, max_degree) if max_degree is not None else len(energies) - 1

        model = PolynomialModel(max(degree, 1))
        x, y = [*zip(*energies)]
        pars = model.guess(y, x=x)
        if degree == 0:
            pars["c0"] = Parameter("c0", value=0, vary=False)

        out = model.fit(y, pars, x=x)
        self.polynomial_coefficients = list(
            reversed([p[1].value for p in out.params.items()]))
        return self.polynomial_coefficients
コード例 #4
0
def fitPolynomial(x,y,order):
	model = PolynomialModel(order)
	pars = model.guess(y, x=x)
	out = model.fit(y, pars, x=x)
	# out.params.update({'order':order})
	print out.fit_report()
	return out
コード例 #5
0
ファイル: fitting.py プロジェクト: rohanisaac/spectra
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
コード例 #6
0
ファイル: fitting.py プロジェクト: rohanisaac/spectra
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
コード例 #7
0
ファイル: XRDLib.py プロジェクト: caglayanoaras/XRD
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
コード例 #8
0
 def fitPoly(self, flux, wavelength):
     #Create the polynomial model from lmFit (from lmfit import PolynomialModel)
     mod = PolynomialModel(6)
     #Have an initial guess at the model parameters
     pars = mod.guess(flux, x=wavelength)
     #Use the parameters for the full model fit
     out = mod.fit(flux, pars, x=wavelength)
     #The output of the model is the fitted continuum
     continuum = out.best_fit
     #return this value
     return continuum
コード例 #9
0
	def fitPoly(self, flux, wavelength):
		#Create the polynomial model from lmFit (from lmfit import PolynomialModel)
		mod = PolynomialModel(6)
		#Have an initial guess at the model parameters 
		pars = mod.guess(flux, x=wavelength)
		#Use the parameters for the full model fit 
		out  = mod.fit(flux, pars, x=wavelength)
		#The output of the model is the fitted continuum
		continuum = out.best_fit
		#return this value
		return continuum
コード例 #10
0
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
コード例 #11
0
def readFits(inFile):

    table = pyfits.open(inFile)
    data = table[1].data
    flux = data.field('flux')
    wavelength = 10**(data.field('loglam'))
    ivar = data.field('ivar')
    weights = ivar
    redshift_data = table[2].data.field('Z')

    mod = PolynomialModel(6)
    pars = mod.guess(flux, x=wavelength)
    out = mod.fit(flux, pars, x=wavelength)
    continuum = out.best_fit

    #At the moment get a crude estimate of the observed normalised SED for redshift computation
    normalised_observed_flux = flux - continuum

    #Call the normaliseTemplate method to find the normalised SED of a given template
    normalised_template_flux = normaliseTemplate(
        'K20_late_composite_original.dat')
    plt.close('all')

    #Choose to plot the results
    #plt.plot(wavelength, flux, label='flux')
    #plt.plot(wavelength, y_av, label='boxcar')
    #plt.plot(wavelength, ffit , label='fit')
    #legend()
    #plt.show()
    #plt.close('all')

    return {
        'flux': flux,
        'wavelength': wavelength,
        'z': redshift_data,
        'weights': weights,
        'norm_flux': normalised_observed_flux
    }
コード例 #12
0
def readFits(inFile): 
	
		

	table = pyfits.open(inFile)
	data = table[1].data
	flux = data.field('flux')
	wavelength = 10**(data.field('loglam'))
	ivar = data.field('ivar')
	weights = ivar
	redshift_data = table[2].data.field('Z')

	mod = PolynomialModel(6)
	pars = mod.guess(flux, x=wavelength)
	out  = mod.fit(flux, pars, x=wavelength)
	continuum = out.best_fit

	#At the moment get a crude estimate of the observed normalised SED for redshift computation
	normalised_observed_flux = flux - continuum

	#Call the normaliseTemplate method to find the normalised SED of a given template
	normalised_template_flux = normaliseTemplate('K20_late_composite_original.dat')
	plt.close('all')




	#Choose to plot the results 
	#plt.plot(wavelength, flux, label='flux')
	#plt.plot(wavelength, y_av, label='boxcar')
	#plt.plot(wavelength, ffit , label='fit')
	#legend()
	#plt.show()
	#plt.close('all')

	
	return {'flux' : flux, 'wavelength' : wavelength,
	 'z' : redshift_data, 'weights': weights, 'norm_flux':normalised_observed_flux}
コード例 #13
0
def fitLines(flux, wavelength, z, weights): 	

	#Convert all into numpy arrays 
	flux = np.array(flux)
	wavelength = np.array(wavelength)
	z = np.array(z)
	weights = np.array(weights)
	error = np.sqrt(1 / weights)

	#Fit a polynomial to the continuum background emission of the galaxy
	#This is the crude way to do it 
	mod = PolynomialModel(6)
	pars = mod.guess(flux, x=wavelength)
	out  = mod.fit(flux, pars, x=wavelength)
	continuum_poly = out.best_fit

	#Can also compute the continuum in the more advanced way
	#masking the emission lines and using a moving average


	#Define the wavelength values of the relevant emission lines
	OII3727 = 3727.092
	OII3729 = 3729.875
	H_beta = 4862.721
	OIII4959 = 4960.295
	OIII5007 = 5008.239
	H_alpha = 6564.614
	NII6585 = 6585.27
	SII6718 = 6718.29
	SII6732 = 6732.68

	#Now apply the redshift formula to find where this will be observed
	#Note that for these SDSS spectra the OII doublet is not in range
	OII3727_shifted = OII3727 * (1 + z)
	OII3729_shifted = OII3729 * (1 + z)
	H_beta_shifted = H_beta * (1 + z)
	OIII4959_shifted = OIII4959 * (1 + z)
	OIII5007_shifted = OIII5007 * (1 + z)
	H_alpha_shifted = H_alpha * (1 + z)
	NII6585_shifted = NII6585 * (1 + z)
	SII6718_shifted = SII6718 * (1 + z)
	SII6732_shifted = SII6732 * (1 + z)

	#hellofriend
	#Will choose to mask pm 15 for each of the lines
	H_beta_index = np.where(np.logical_and(wavelength>=(H_beta_shifted - 15), wavelength<=(H_beta_shifted + 15)))
	OIII_one_index = np.where(np.logical_and(wavelength>=(OIII4959_shifted - 15), wavelength<=(OIII4959_shifted + 15)))
	OIII_two_index = np.where(np.logical_and(wavelength>=(OIII5007_shifted - 15), wavelength<=(OIII5007_shifted + 15)))
	NII_one_index = np.where(np.logical_and(wavelength>=(NII6585_shifted - 15), wavelength<=(NII6585_shifted + 15)))
	H_alpha_index = np.where(np.logical_and(wavelength>=(H_alpha_shifted - 15), wavelength<=(H_alpha_shifted + 15)))
	SII_one_index = np.where(np.logical_and(wavelength>=(SII6718_shifted - 15), wavelength<=(SII6718_shifted + 15)))
	SII_two_index = np.where(np.logical_and(wavelength>=(SII6732_shifted - 15), wavelength<=(SII6732_shifted + 15)))

	#define the mask 1 values from the index values
	mask = np.zeros(len(flux))
	mask[H_beta_index] = 1
	mask[OIII_one_index] = 1
	mask[OIII_two_index] = 1
	mask[NII_one_index] = 1
	mask[H_alpha_index] = 1
	mask[SII_one_index] = 1
	mask[SII_two_index] = 1

	#Now apply these to the flux to mask 
	masked_flux = ma.masked_array(flux, mask=mask)

	#Make my own with np.mean()
	continuum = np.empty(len(masked_flux))
	for i in range(len(masked_flux)):

		if (i + 5) < len(masked_flux):
			continuum[i] = ma.mean(masked_flux[i:i+5])
			if np.isnan(continuum[i]):
				continuum[i] = continuum[i - 1]
		else:
			continuum[i] = ma.mean(masked_flux[i-5:i])
			if np.isnan(continuum[i]):
				continuum[i] = continuum[i - 1]

	

	#Subtract the continuum from the flux, just use polynomial fit right now 
	counts = flux - continuum_poly

	#Construct a dictionary housing these shifted emission line values 
	#Note that values for the OII doublet are not present
	line_dict = {'H_beta' : H_beta_shifted, 'OIII4959' : OIII4959_shifted, 
	'OIII5007' : OIII5007_shifted, 'H_alpha' : H_alpha_shifted, 'NII6585' : NII6585_shifted, 
	'SII6718' : SII6718_shifted, 'SII6732' : SII6732_shifted}

	#Plot the initial continuum subtracted spectrum
	plt.plot(wavelength, counts)

	#Initialise a dictionary for the results in the for loop
	results_dict = {}

	#Begin for loop to fit an arbitrary number of emission lines
	for key in line_dict:
		
	
	########################################################################
	#FITTING EACH OF THE EMISSION LINES IN TURN
	########################################################################
	#We don't want to include all the data in the gaussian fit 
	#Look for the indices of the points closes to the wavelength value
	#The appropriate range is stored in fit_wavelength etc.

	#Use np.where to find the indices of data surrounding the gaussian
		new_index = np.where(np.logical_and(wavelength > (line_dict[key] - 10) ,
											wavelength < (line_dict[key] + 10)))  

	#Select only data for the fit with these indices
		fit_wavelength = wavelength[new_index]
		fit_counts = counts[new_index]
		fit_weights = weights[new_index]
		fit_continuum = continuum[new_index]
		fit_error = error[new_index]



	#Now use the lmfit package to perform gaussian fits to the data	
	#Construct the gaussian model
		mod = GaussianModel()

	#Take an initial guess at what the model parameters are 
	#In this case the gaussian model has three parameters, 
	#Which are amplitude, center and sigma
		pars = mod.guess(fit_counts, x=fit_wavelength)

	#We know from the redshift what the center of the gaussian is, set this
	#And choose the option not to vary this parameter 
	#Leave the guessed values of the other parameters
		pars['center'].set(value = line_dict[key])
		pars['center'].set(vary = 'False')

	#Now perform the fit to the data using the set and guessed parameters 
	#And the inverse variance weights form the fits file 
		out  = mod.fit(fit_counts, pars, weights = fit_weights, x=fit_wavelength)
		#print(out.fit_report(min_correl=0.25))

	#Plot the results and the spectrum to check the fit
		plt.plot(fit_wavelength, out.best_fit, 'r-')
	
	#Return the error on the flux 
		error_dict = fluxError(fit_counts, fit_wavelength, fit_error, continuum_poly)

	#Compute the equivalent width
		con_avg = np.mean(continuum_poly)
		E_w = out.best_values['amplitude'] / con_avg

	#The amplitude parameter is the area under the curve, equivalent to the flux
		results_dict[key] = [out.best_values['amplitude'], error_dict['flux_error'], out.best_values['sigma'], 
		2.3548200*out.best_values['sigma'], E_w, error_dict['E_W_error']]


	#The return dictionary for this method is a sequence of results vectors
	return results_dict
コード例 #14
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
コード例 #15
0
def _fit_polynomial(x, y, order, pars=None):
    """ Internal function to fit a polynomial using `lmfit`."""
    model = PolynomialModel(order)
    if not pars:
        pars = model.guess(y, x=x)
    return model.fit(y, pars, x=x)
コード例 #16
0
ファイル: tasks.py プロジェクト: elvis1020/astro_spec_scripts
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])
コード例 #17
0
        params2 = gmod.make_params()
        params2['A'].set(value=np.max(Voff_specm), min=0)
        params2['mu'].set(value=x_lambda[pts[n,0]-scan_l+int(*np.where(Voff_specm == Voff_specm.max()))], min=400, max=800)
        params2['sigma'].set(value=8, max=100)
        params1['slope'].set(value=slope2)
        params1['b'].set(value=np.min(Voff_specm))
        result1 = gmod.fit(Von_specm, x=x, **params1)
        result2 = gmod.fit(Voff_specm, x=x, **params2)
        fitpeak1 = result1.best_values['mu']
        fitpeak2 = result2.best_values['mu']
        deltaL = fitpeak1 -fitpeak2
    else:
        mod = PolynomialModel(7)
        pars1 = mod.guess(Von_specm, x=x)
        pars2 = mod.guess(Voff_specm, x=x)
        result1 = mod.fit(Von_specm, pars1, x=x)
        result2 = mod.fit(Voff_specm, pars2, x=x)
        fitpeak1 = x[np.where(result1.best_fit == np.max(result1.best_fit))]
        fitpeak2 = x[np.where(result2.best_fit == np.max(result2.best_fit))]
        deltaL = fitpeak1 -fitpeak2
    dL['NR#{}'.format(n)] = deltaL

    P = np.sum(spectra_bgcr[:,:,n]*x, axis=1)/np.sum(spectra_bgcr[:,:,n],axis=1)
    Pon = np.array([P[i] for i in range(frame_start, frame) if i%2==1 and tt[i,n] > threshold[n]])
    Poff = np.array([P[i] for i in range(frame_start, frame) if i%2==0 and tt[i,n] > threshold[n]])
    Ton = [T[i] for i in range(frame_start,frame) if tt[i,n] > threshold[n] and i%2 == 1]
    Toff = [T[i] for i in range(frame_start,frame) if tt[i,n] > threshold[n]and i%2 == 0]

    fig3, ax = plt.subplots(3,5, figsize=(18,5))
    ax[0,0] = plt.subplot2grid((3,5), (0,0), colspan=4, rowspan=1)
    ax[1,0] = plt.subplot2grid((3,5), (1,0), colspan=4, rowspan=1, sharex=ax[0,0])
コード例 #18
0
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]
コード例 #19
0
def fitLines(flux, wavelength, z, weights):

    #Convert all into numpy arrays
    flux = np.array(flux)
    wavelength = np.array(wavelength)
    z = np.array(z)
    weights = np.array(weights)
    error = np.sqrt(1 / weights)

    #Fit a polynomial to the continuum background emission of the galaxy
    #This is the crude way to do it
    mod = PolynomialModel(6)
    pars = mod.guess(flux, x=wavelength)
    out = mod.fit(flux, pars, x=wavelength)
    continuum_poly = out.best_fit

    #Can also compute the continuum in the more advanced way
    #masking the emission lines and using a moving average

    #Define the wavelength values of the relevant emission lines
    OII3727 = 3727.092
    OII3729 = 3729.875
    H_beta = 4862.721
    OIII4959 = 4960.295
    OIII5007 = 5008.239
    H_alpha = 6564.614
    NII6585 = 6585.27
    SII6718 = 6718.29
    SII6732 = 6732.68

    #Now apply the redshift formula to find where this will be observed
    #Note that for these SDSS spectra the OII doublet is not in range
    OII3727_shifted = OII3727 * (1 + z)
    OII3729_shifted = OII3729 * (1 + z)
    H_beta_shifted = H_beta * (1 + z)
    OIII4959_shifted = OIII4959 * (1 + z)
    OIII5007_shifted = OIII5007 * (1 + z)
    H_alpha_shifted = H_alpha * (1 + z)
    NII6585_shifted = NII6585 * (1 + z)
    SII6718_shifted = SII6718 * (1 + z)
    SII6732_shifted = SII6732 * (1 + z)

    #hellofriend
    #Will choose to mask pm 15 for each of the lines
    H_beta_index = np.where(
        np.logical_and(wavelength >= (H_beta_shifted - 15), wavelength <=
                       (H_beta_shifted + 15)))
    OIII_one_index = np.where(
        np.logical_and(wavelength >= (OIII4959_shifted - 15), wavelength <=
                       (OIII4959_shifted + 15)))
    OIII_two_index = np.where(
        np.logical_and(wavelength >= (OIII5007_shifted - 15), wavelength <=
                       (OIII5007_shifted + 15)))
    NII_one_index = np.where(
        np.logical_and(wavelength >= (NII6585_shifted - 15), wavelength <=
                       (NII6585_shifted + 15)))
    H_alpha_index = np.where(
        np.logical_and(wavelength >= (H_alpha_shifted - 15), wavelength <=
                       (H_alpha_shifted + 15)))
    SII_one_index = np.where(
        np.logical_and(wavelength >= (SII6718_shifted - 15), wavelength <=
                       (SII6718_shifted + 15)))
    SII_two_index = np.where(
        np.logical_and(wavelength >= (SII6732_shifted - 15), wavelength <=
                       (SII6732_shifted + 15)))

    #define the mask 1 values from the index values
    mask = np.zeros(len(flux))
    mask[H_beta_index] = 1
    mask[OIII_one_index] = 1
    mask[OIII_two_index] = 1
    mask[NII_one_index] = 1
    mask[H_alpha_index] = 1
    mask[SII_one_index] = 1
    mask[SII_two_index] = 1

    #Now apply these to the flux to mask
    masked_flux = ma.masked_array(flux, mask=mask)

    #Make my own with np.mean()
    continuum = np.empty(len(masked_flux))
    for i in range(len(masked_flux)):

        if (i + 5) < len(masked_flux):
            continuum[i] = ma.mean(masked_flux[i:i + 5])
            if np.isnan(continuum[i]):
                continuum[i] = continuum[i - 1]
        else:
            continuum[i] = ma.mean(masked_flux[i - 5:i])
            if np.isnan(continuum[i]):
                continuum[i] = continuum[i - 1]

    #Subtract the continuum from the flux, just use polynomial fit right now
    counts = flux - continuum_poly

    #Construct a dictionary housing these shifted emission line values
    #Note that values for the OII doublet are not present
    line_dict = {
        'H_beta': H_beta_shifted,
        'OIII4959': OIII4959_shifted,
        'OIII5007': OIII5007_shifted,
        'H_alpha': H_alpha_shifted,
        'NII6585': NII6585_shifted,
        'SII6718': SII6718_shifted,
        'SII6732': SII6732_shifted
    }

    #Plot the initial continuum subtracted spectrum
    plt.plot(wavelength, counts)

    #Initialise a dictionary for the results in the for loop
    results_dict = {}

    #Begin for loop to fit an arbitrary number of emission lines
    for key in line_dict:

        ########################################################################
        #FITTING EACH OF THE EMISSION LINES IN TURN
        ########################################################################
        #We don't want to include all the data in the gaussian fit
        #Look for the indices of the points closes to the wavelength value
        #The appropriate range is stored in fit_wavelength etc.

        #Use np.where to find the indices of data surrounding the gaussian
        new_index = np.where(
            np.logical_and(wavelength > (line_dict[key] - 10), wavelength <
                           (line_dict[key] + 10)))

        #Select only data for the fit with these indices
        fit_wavelength = wavelength[new_index]
        fit_counts = counts[new_index]
        fit_weights = weights[new_index]
        fit_continuum = continuum[new_index]
        fit_error = error[new_index]

        #Now use the lmfit package to perform gaussian fits to the data
        #Construct the gaussian model
        mod = GaussianModel()

        #Take an initial guess at what the model parameters are
        #In this case the gaussian model has three parameters,
        #Which are amplitude, center and sigma
        pars = mod.guess(fit_counts, x=fit_wavelength)

        #We know from the redshift what the center of the gaussian is, set this
        #And choose the option not to vary this parameter
        #Leave the guessed values of the other parameters
        pars['center'].set(value=line_dict[key])
        pars['center'].set(vary='False')

        #Now perform the fit to the data using the set and guessed parameters
        #And the inverse variance weights form the fits file
        out = mod.fit(fit_counts, pars, weights=fit_weights, x=fit_wavelength)
        #print(out.fit_report(min_correl=0.25))

        #Plot the results and the spectrum to check the fit
        plt.plot(fit_wavelength, out.best_fit, 'r-')

        #Return the error on the flux
        error_dict = fluxError(fit_counts, fit_wavelength, fit_error,
                               continuum_poly)

        #Compute the equivalent width
        con_avg = np.mean(continuum_poly)
        E_w = out.best_values['amplitude'] / con_avg

        #The amplitude parameter is the area under the curve, equivalent to the flux
        results_dict[key] = [
            out.best_values['amplitude'], error_dict['flux_error'],
            out.best_values['sigma'], 2.3548200 * out.best_values['sigma'],
            E_w, error_dict['E_W_error']
        ]

    #The return dictionary for this method is a sequence of results vectors
    return results_dict