예제 #1
0
 def fit_single_line_BS(self, x, y, zero_lev, err_continuum, fitting_parameters, bootstrap_iterations = 1000):
     
     #Declare parameters and containers for the fit
     params_dict     = fitting_parameters.valuesdict()
     initial_values  = [params_dict['A0'], params_dict['mu0'], params_dict['sigma0']]
     area_array      = empty(bootstrap_iterations)
     params_array    = empty([3, bootstrap_iterations])
     n_points        = len(x)
                         
     #Perform the fit
     for i in range(bootstrap_iterations):
         y_new               = y + np_normal_dist(0, err_continuum, n_points)
         area_array[i]       = simps(y_new, x) - simps(zero_lev, x)
         best_vals, covar    = curve_fit(gaussian_curveBS, (x, zero_lev), y_new, p0=initial_values, maxfev = 1600)
         params_array[:,i]   = best_vals
                 
     #Compute Bootstrap output
     mean_area, std_area = mean(area_array), std(area_array)
     mean_params_array, stdev_params_array = params_array.mean(1), params_array.std(1)
     
     #Store the data
     self.fit_dict['area_intg'],     self.fit_dict['area_intg_er']   = mean_area, std_area
     self.fit_dict['A0_norm'],       self.fit_dict['A0_norm_er']     = mean_params_array[0], stdev_params_array[0]
     self.fit_dict['mu0_norm'],      self.fit_dict['mu0_norm_er']    = mean_params_array[1], stdev_params_array[1]  
     self.fit_dict['sigma0_norm'],   self.fit_dict['sigma0_norm_er'] = mean_params_array[2], stdev_params_array[2]  
             
     A = ufloat(mean_params_array[0], stdev_params_array[0]) 
     sigma = ufloat(mean_params_array[2], stdev_params_array[2])         
     fwhm0_norm = 2.354820045 * sigma
     areaG0_norm = A * sigma * self.sqrt2pi
   
     self.fit_dict['fwhm0_norm'], self.fit_dict['fwhm0_norm_er'] = fwhm0_norm.nominal_value, fwhm0_norm.std_dev
     self.fit_dict['area_G0_norm'], self.fit_dict['area_G0_norm_er'] = areaG0_norm.nominal_value, areaG0_norm.std_dev
                        
     return
예제 #2
0
    def fit_single_line(self, x, y, zero_lev, err_continuum, fitting_parameters, bootstrap_iterations = 1000):

        #Simple fit
        if self.fit_dict['MC_iterations'] == 1:
            fit_output = lmfit_minimize(residual_gauss, fitting_parameters, args=(x, y, zero_lev, err_continuum))
            self.fit_dict['area_intg'] = simps(y, x) - simps(zero_lev, x)
            self.fit_dict['area_intg_err'] = 0.0
             
        #Bootstrap
        else:
            mini_posterior  = Minimizer(lnprob_gaussCurve, fitting_parameters, fcn_args = ([x, y, zero_lev, err_continuum]))
            fit_output      = mini_posterior.emcee(steps=200, params = fitting_parameters)
            
            #Bootstrap for the area of the lines
            area_array = empty(bootstrap_iterations) 
            len_x_array = len(x)
            for i in range(bootstrap_iterations):
                y_new =  y + np_normal_dist(0.0, err_continuum, len_x_array)
                area_array[i] = simps(y_new, x) - simps(zero_lev, x)
            self.fit_dict['area_intg'] = mean(area_array)
            self.fit_dict['area_intg_err'] = std(area_array)           
        
        #Store the fitting parameters
        output_params = fit_output.params
        for key in self.fit_dict['parameters_list']:
            self.fit_dict[key + '_norm'] = output_params[key].value
            self.fit_dict[key + '_norm_er'] = output_params[key].stderr
            
        return
예제 #3
0
    def fit_blended_line_BS_lmfit(self, x, y, zero_lev, err_continuum, Ncomps, fitting_parameters, add_wide_component, fitting_parameters_wide, bootstrap_iterations = 500, MC_iterations = 200):
                        
        #Prepare some data in advance
        n_points        = len(x)
        n_parameters    = len(self.fit_dict['parameters_list'])
        params_list     = self.fit_dict['parameters_list']
        range_param     = range(n_parameters)
        range_boots     = range(bootstrap_iterations)
        area_array      = empty(bootstrap_iterations)
        idcs_components = map(str, range(Ncomps))
        params_matrix   = empty((n_parameters, bootstrap_iterations))
        errors_matrix   = empty((n_parameters, bootstrap_iterations))
        Ncomps_wide     = ['3']
        
        #Loop through the iterations:
        for i in range_boots:
            
            y_new           = y + np_normal_dist(0.0, err_continuum, n_points)
            area_array[i]   = simps(y_new, x) - simps(zero_lev, x)
            fit_Output      = lmfit_minimize(residual_gaussMix, fitting_parameters, args=(x, y_new, zero_lev, err_continuum, idcs_components))
            output_params   = fit_Output.params
            
            #Case with a wide component
            if add_wide_component:
                
                #Only works for Halpha
                sigma_limit = output_params['sigma1'].value
                limit_0, limit_1 = 6548.05 - self.fit_dict['x_scaler'] - sigma_limit * 1.5, 6548.05 - self.fit_dict['x_scaler'] + sigma_limit * 1.5
                limit_2, limit_3 = 0 - sigma_limit * 4,                                     0 + sigma_limit * 4 
                limit_4, limit_5 = 6583.46 - self.fit_dict['x_scaler'] - sigma_limit * 3,   6583.46 - self.fit_dict['x_scaler'] + sigma_limit * 3
                
                indeces = ((x >= limit_0) & (x <= limit_1)) + ((x >= limit_2) & (x <= limit_3)) + ((x >= limit_4) & (x <= limit_5))
                mask = invert(indeces) 
                x_wide, y_wide, zero_wide = x[mask], y[mask], zero_lev[mask]

                #Fit the wide component without narrow component
                fit_output_wide     = lmfit_minimize(residual_gaussMix, fitting_parameters_wide, args=(x_wide, y_wide, zero_wide, err_continuum, Ncomps_wide))
                output_params_wide  = fit_output_wide.params
                
                #Get wide curve
                y_wide = gaussian_mixture(output_params_wide.valuesdict(), x, zero_lev, Ncomps_wide)

                #Calculate emission line region again
                y_pure_narrow       = y - y_wide + zero_lev 
                
                #Fit narrow components again
                fit_Output          = lmfit_minimize(residual_gaussMix, fitting_parameters, args=(x, y_pure_narrow, zero_lev, err_continuum, idcs_components))
                out_params_narrow   = fit_Output.params           

                #Combine the results from both fits
                output_params       = out_params_narrow + output_params_wide
                
            #save parameters to array
            for j in range_param:
                params_matrix[j,i] = output_params[params_list[j]].value
                errors_matrix[j,i] = output_params[params_list[j]].stderr

        #Calculate mean and std deviation values
        mean_area, std_area = mean(area_array), std(area_array)
        mean_params_array, stdev_params_array = params_matrix.mean(1), params_matrix.std(1)
        errorsmean_array = errors_matrix.mean(1)
                
        #Return the data to a dictionary format
        self.fit_dict['area_intg'], self.fit_dict['area_intg_er'] = mean_area, std_area
        
        for j in range(len(self.fit_dict['parameters_list'])):
            param = self.fit_dict['parameters_list'][j]
            self.fit_dict[param+'_norm'] = mean_params_array[j]
            self.fit_dict[param+'_norm_er'] = errorsmean_array[j]

        #Increase the number of components if wide observed
        self.fit_dict.line_number = self.fit_dict.line_number + 1 if add_wide_component else self.fit_dict.line_number

        return
예제 #4
0
    def fit_blended_line_BS(self, x, y, zero_lev, err_continuum, Ncomps, fitting_parameters, add_wide_component, fitting_parameters_wide, bootstrap_iterations = 1000, MC_iterations = 200):

        #Declare parameters and containers for the fit
        params_dict     = fitting_parameters.valuesdict()
        n_points        = len(x)
        list_parameters = []
        initial_val     = empty(3 * Ncomps)
        area_array      = empty(bootstrap_iterations)
        params_array    = empty([3 * Ncomps, bootstrap_iterations])
        
#         if add_wide_component:
#             x_scaler        = self.fit_dict['x_scaler']
#             need_to_extract = coso
            
        #Reshape parameters from dict to array (A0, mu0, sigma0, A1, mu1, sigma1...)
        for i in range(Ncomps):
            comp = str(i)
            line_param                  = [param.format(str(comp)) for param in ['A{}', 'mu{}', 'sigma{}']] 
            initial_val[i*3:(i+1)*3]    = params_dict[line_param[0]], params_dict[line_param[1]], params_dict[line_param[2]]
            list_parameters             += line_param
        
        #Perform the fit
        for j in range(bootstrap_iterations):
            y_new               = y + np_normal_dist(0, err_continuum, n_points)
            area_array[j]       = simps(y_new, x) - simps(zero_lev, x)
            best_vals, covar    = curve_fit(gaussian_MixBS, (x, zero_lev, Ncomps), y_new, p0=initial_val) # Need to poot here the new function
            params_array[:,j]   = best_vals
            
#             if add_wide_component:
#                 sigma_limit = best_vals[5]
#                 limit_0, limit_1 = 6548.05 - x_scaler - sigma_limit * 1.5,     6548.05 - x_scaler + sigma_limit * 1.5
#                 limit_2, limit_3 = 0 - sigma_limit * 4,                                         0 + sigma_limit * 4 
#                 limit_4, limit_5 = 6583.46 - x_scaler - sigma_limit * 3,       6583.46 - x_scaler + sigma_limit * 3            
#       
#                 indeces = ((x >= limit_0) & (x <= limit_1)) + ((x >= limit_2) & (x <= limit_3)) + ((x >= limit_4) & (x <= limit_5))
#                 mask = invert(indeces) 
#                 x_wide, y_wide, zero_wide = x[mask], y_new[mask], zero_lev[mask]
#                 
#                 best_vals_wide, covar = curve_fit(gaussian_curveBS, (x_wide, zero_wide), y_wide, p0=initial_wide_values)
#                 
#                 #Calculate wide component curve            
#                 y_wide_fit = gaussian_curveBS((x, zero_lev), *best_vals_wide) 
#                 
#                 #Calculate emission line region again
#                 y_pure_narrow = y_new - y_wide_fit + zero_lev 
#                 
#                 #Recalculate the narrow components
#                 best_vals = curve_fit(gaussian_MixBS, (x, zero_lev, Ncomps), y_pure_narrow, p0=initial_val)        
# 
#         if add_wide_component:
#             self.fit_dict.line_number = self.fit_dict.line_number + 1
#             concantenate Matrix
            
        #Compute Bootstrap output
        mean_area, std_area = mean(area_array), std(area_array)
        mean_params_array, stdev_params_array = params_array.mean(1), params_array.std(1)

        #Store the data
        self.fit_dict[['area_intg', 'area_intg_er']] = mean_area, std_area
        
        #Return to a dictionary format
        for m in range(Ncomps):
            comp            = str(m)
            line_param      = [param.format(str(comp)) for param in ['A{}_norm', 'mu{}_norm', 'sigma{}_norm']]
            line_param_er   = [param.format(str(comp)) for param in ['A{}_norm_er', 'mu{}_norm_er', 'sigma{}_norm_er']]
            for n in range(len(line_param)):
                self.fit_dict[line_param[n]] = mean_params_array[m*3:(m+1)*3][n]
                self.fit_dict[line_param_er[n]] = stdev_params_array[m*3:(m+1)*3][n]
                
        #Calculate the gaussian area
        A_keys, Aerr_keys = ['A{}_norm'.format(str(i)) for i in range(Ncomps)], ['A{}_norm_er'.format(str(i)) for i in range(Ncomps)]
        sigma_keys, sigmaerr_keys = ['sigma{}_norm'.format(str(i)) for i in range(Ncomps)], ['sigma{}_norm_er'.format(str(i)) for i in range(Ncomps)]   
        A_vector = unumpy.uarray(self.fit_dict[A_keys].values, self.fit_dict[Aerr_keys].values) 
        sigma_vector = unumpy.uarray(self.fit_dict[sigma_keys].values, self.fit_dict[sigmaerr_keys].values) 

        fwhm_vector = 2.354820045 * sigma_vector
        areaG_vector = A_vector * sigma_vector * self.sqrt2pi 
    
        #Add areas to dict
        fwhm_keys, fwhmerr_keys = ['fwhm{}'.format(str(i)) for i in range(Ncomps)], ['fwhm{}_er'.format(str(i)) for i in range(Ncomps)]           
        AreaG_keys, AreaGerr_keys = ['area_G{}_norm'.format(str(i)) for i in range(Ncomps)], ['area_G{}_norm_er'.format(str(i)) for i in range(Ncomps)]
        fwhm_nominal, fwhm_std_dev = unumpy.nominal_values(fwhm_vector), unumpy.std_devs(fwhm_vector)
        AreaG_nominal, AreaG_std_dev = unumpy.nominal_values(areaG_vector), unumpy.std_devs(areaG_vector)
        
        for m in range(len(AreaG_keys)):
            self.fit_dict[fwhm_keys[m]]     = fwhm_nominal[m]
            self.fit_dict[fwhmerr_keys[m]]  = fwhm_std_dev[m]
            self.fit_dict[AreaG_keys[m]]    = AreaG_nominal[m]
            self.fit_dict[AreaGerr_keys[m]] = AreaG_std_dev[m]      
                            
        return
예제 #5
0
    def fit_blended_line_emcee(self, x, y, zero_lev, err_continuum, Ncomps, fitting_parameters, add_wide_component, fitting_parameters_wide, bootstrap_iterations = 1000, MC_iterations = 200):

        #---First we integrate the brute area with all the components
        if self.fit_dict['MC_iterations'] == 1:
            self.fit_dict['area_intg'] = simps(y, x) - simps(zero_lev, x)
            self.fit_dict['area_intg_err'] = 0.0
        
        else:
            area_array  = empty(bootstrap_iterations) 
            len_x_array = len(x)
            for i in range(bootstrap_iterations):
                y_new           = y + np_normal_dist(0.0, err_continuum, len_x_array)
                area_array[i]   = simps(y_new, x) - simps(zero_lev, x)
            self.fit_dict['area_intg'] = mean(area_array)
            self.fit_dict['area_intg_err'] = std(area_array)                   
        
        #---Second we proceed to analyze as gaussian components
        idcs_components = map(str, range(Ncomps))        
        
        mini_posterior  = Minimizer(lnprob_gaussMix, fitting_parameters, fcn_args = ([x, y, zero_lev, err_continuum, idcs_components]), method='powell')
        fit_output      = mini_posterior.emcee(steps=MC_iterations, params = fitting_parameters)
        output_params   = fit_output.params
        
        if add_wide_component: #This currently only valid for Halpha

            sigma_limit = output_params['sigma1'].value
            limit_0, limit_1 = 6548.05 - self.fit_dict['x_scaler'] - sigma_limit * 1.5,     6548.05 - self.fit_dict['x_scaler'] + sigma_limit * 1.5
            limit_2, limit_3 = 0 - sigma_limit * 4,                                         0 + sigma_limit * 4 
            limit_4, limit_5 = 6583.46 - self.fit_dict['x_scaler'] - sigma_limit * 3,       6583.46 - self.fit_dict['x_scaler'] + sigma_limit * 3

            #Get the wide component area
            indeces = ((x >= limit_0) & (x <= limit_1)) + ((x >= limit_2) & (x <= limit_3)) + ((x >= limit_4) & (x <= limit_5))
            mask = invert(indeces) 
            x_wide, y_wide, zero_wide = x[mask], y[mask], zero_lev[mask]
            Ncomps_wide = ['3']
            
            #Fit the wide component without narrow component
            mini_posterior_wide = Minimizer(lnprob_gaussMix, fitting_parameters_wide, fcn_args = ([x_wide, y_wide, zero_wide, err_continuum, Ncomps_wide]), method='powell')
            fit_output_wide     = mini_posterior_wide.emcee(steps=MC_iterations, params = fitting_parameters_wide)
            output_params_wide  = fit_output_wide.params

            #Calculate wide component curve            
            y_wide_fit          = gaussian_mixture(output_params_wide.valuesdict(), x, zero_lev, Ncomps_wide)
            
            #Calculate emission line region again
            y_pure_narrow       = y - y_wide_fit + zero_lev 
            
            #Fit narrow components again
            mini_posterior          = Minimizer(lnprob_gaussMix, fitting_parameters, fcn_args = ([x, y_pure_narrow, zero_lev, err_continuum, idcs_components]), method='powell')
            fit_output_narrow       = mini_posterior.emcee(steps=MC_iterations, params=fitting_parameters)
            output_params_narrow    = fit_output_narrow.params
            
            #Combine the results from both fits
            output_params = output_params_narrow + output_params_wide

            #Add the wide component to the fit we are performing
            self.fit_dict.line_number = self.fit_dict.line_number + 1
        
        for key in self.fit_dict['parameters_list']:
            
            self.fit_dict[key + '_norm'] = output_params[key].value if output_params[key].value is not None else np_nan
            self.fit_dict[key + '_norm_er'] = output_params[key].stderr if output_params[key].stderr is not None else np_nan       
             
        return