def test_fit_gaussians(): import numpy as np import matplotlib.pyplot as plt from myfitting import fit_gaussians def gauss(x, amp, x0, width): return amp * np.exp(-(x - x0)**2 / (2 * width**2)) x = np.linspace(-20, 15, 1000) y = np.exp(-(x-3)**2 / (2 * 1**2)) + \ 3 * np.exp(-(x-9)**2 / (2 * 0.5**2)) + \ 5 * np.exp(-(x+0.5)**2 / (2 * 5**2)) # amp, offset, width params = (1, 3, 1, 2, 9, 1, 0.5, -1, 1) fit = fit_gaussians(x, y, ncomps=3, guesses=params) assert len(fit) == 3 assert len(fit[1]) == 3
def calc_hi_vel_range( hi_spectrum, hi_vel_axis, gauss_fit_kwargs, width_scale=2, co_spectrum=None, co_vel_axis=None, ncomps=1, ): ''' Discussion of HI width error from Min: (3) For the uncertainty in the HI velocity range, you take the absolute difference between the Gaussian HI component center and the median CO peak velocity. In fact, this is sort of the minimum uncertainty we expect. The uncertainty mostly comes from our adoption of +/- 2 sigma(HI) to determine the HI velocity range. In this sense, the maximum uncertainty we expect would be (HI velocity range we determine by using +/- 2 sigma(HI) as thresholds) - (HI velocity range over which CO emission appears). Therefore, a more realistic estimate for the uncertainty in the HI velocity range would be, e.g., ("minimum" error + "maximum" error) / 2. This estimate would be a better measure in particular for Taurus, where CO emission appears over a relatively small velocity range. ''' from scipy.stats import nanmedian from myfitting import fit_gaussians co_width = np.copy(gauss_fit_kwargs['co_width']) del (gauss_fit_kwargs['co_width']) hi_fits = fit_gaussians(hi_vel_axis, hi_spectrum, **gauss_fit_kwargs) gauss_fit_kwargs['co_width'] = co_width # use either the gaussian closest to the CO peak, or the tallest gaussian if co_spectrum is not None: co_peak_vel = co_vel_axis[co_spectrum == np.nanmax(co_spectrum)][0] vel_diffs_center = [] vel_diffs_edge = [] for i, param in enumerate(hi_fits[2]): vel_center = param[1] width = param[2] vel_center_diff = np.abs(vel_center - co_peak_vel) vel_diffs_center.append(vel_center_diff) #vel_diffs_edge.append(vel_center_diff + 2.0 * width) vel_diffs_edge.append(4.0 * width) # get the velocity range vel_diffs_center = np.asarray(vel_diffs_center) vel_diffs_edge = np.asarray(vel_diffs_edge) sort_indices = np.argsort(vel_diffs_center) cloud_comp_num = np.asarray(sort_indices[:ncomps]) velocity_range = [np.inf, -np.inf] for i in cloud_comp_num: # get the component param = hi_fits[2][i] vel_center = param[1] width = param[2] # set absolute bounds if the component bounds extend beyond upper_vel = vel_center + width * width_scale lower_vel = vel_center - width * width_scale if upper_vel > velocity_range[1]: velocity_range[1] = upper_vel if lower_vel < velocity_range[0]: velocity_range[0] = lower_vel # the offset between the co and fitted gaussians will be the HI error hi_width_error_min = np.max(vel_diffs_center[cloud_comp_num]) # max error hi_width_error_max = np.max(vel_diffs_edge[cloud_comp_num]) - \ co_width #gauss_fit_kwargs['co_width'] hi_width_error_max = np.abs(velocity_range[1] - velocity_range[0]) - \ co_width hi_width_error = (hi_width_error_min + hi_width_error_max) / 2.0 #print 'min error', hi_width_error_min, 'km/s' #print 'max error', hi_width_error_max, 'km/s' #print 'avg error', hi_width_error, 'km/s' else: amp_max = -np.Inf for i, param in enumerate(hi_fits[2]): if param[0] > amp_max: amp_max = param[0] vel_center = param[1] width = param[2] * 4 cloud_comp_num = i velocity_range = [ vel_center - width * width_scale, vel_center + width * width_scale ] return velocity_range, hi_fits, cloud_comp_num, hi_width_error
def calc_hi_vel_range(hi_spectrum, hi_vel_axis, gauss_fit_kwargs, width_scale=2, co_spectrum=None, co_vel_axis=None, ncomps=1,): ''' Discussion of HI width error from Min: (3) For the uncertainty in the HI velocity range, you take the absolute difference between the Gaussian HI component center and the median CO peak velocity. In fact, this is sort of the minimum uncertainty we expect. The uncertainty mostly comes from our adoption of +/- 2 sigma(HI) to determine the HI velocity range. In this sense, the maximum uncertainty we expect would be (HI velocity range we determine by using +/- 2 sigma(HI) as thresholds) - (HI velocity range over which CO emission appears). Therefore, a more realistic estimate for the uncertainty in the HI velocity range would be, e.g., ("minimum" error + "maximum" error) / 2. This estimate would be a better measure in particular for Taurus, where CO emission appears over a relatively small velocity range. ''' from scipy.stats import nanmedian from myfitting import fit_gaussians co_width = np.copy(gauss_fit_kwargs['co_width']) del(gauss_fit_kwargs['co_width']) hi_fits = fit_gaussians(hi_vel_axis, hi_spectrum, **gauss_fit_kwargs) gauss_fit_kwargs['co_width'] = co_width # use either the gaussian closest to the CO peak, or the tallest gaussian if co_spectrum is not None: co_peak_vel = co_vel_axis[co_spectrum == np.nanmax(co_spectrum)][0] vel_diffs_center = [] vel_diffs_edge = [] for i, param in enumerate(hi_fits[2]): vel_center = param[1] width = param[2] vel_center_diff = np.abs(vel_center - co_peak_vel) vel_diffs_center.append(vel_center_diff) #vel_diffs_edge.append(vel_center_diff + 2.0 * width) vel_diffs_edge.append(4.0 * width) # get the velocity range vel_diffs_center = np.asarray(vel_diffs_center) vel_diffs_edge = np.asarray(vel_diffs_edge) sort_indices = np.argsort(vel_diffs_center) cloud_comp_num = np.asarray(sort_indices[:ncomps]) velocity_range = [np.inf, -np.inf] for i in cloud_comp_num: # get the component param = hi_fits[2][i] vel_center = param[1] width = param[2] # set absolute bounds if the component bounds extend beyond upper_vel = vel_center + width * width_scale lower_vel = vel_center - width * width_scale if upper_vel > velocity_range[1]: velocity_range[1] = upper_vel if lower_vel < velocity_range[0]: velocity_range[0] = lower_vel # the offset between the co and fitted gaussians will be the HI error hi_width_error_min = np.max(vel_diffs_center[cloud_comp_num]) # max error hi_width_error_max = np.max(vel_diffs_edge[cloud_comp_num]) - \ co_width #gauss_fit_kwargs['co_width'] hi_width_error_max = np.abs(velocity_range[1] - velocity_range[0]) - \ co_width hi_width_error = (hi_width_error_min + hi_width_error_max) / 2.0 #print 'min error', hi_width_error_min, 'km/s' #print 'max error', hi_width_error_max, 'km/s' #print 'avg error', hi_width_error, 'km/s' else: amp_max = -np.Inf for i, param in enumerate(hi_fits[2]): if param[0] > amp_max: amp_max = param[0] vel_center = param[1] width = param[2] * 4 cloud_comp_num = i velocity_range = [vel_center - width * width_scale, vel_center + width * width_scale] return velocity_range, hi_fits, cloud_comp_num, hi_width_error