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
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
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
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
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