def test_no_constraints(self): from scipy import optimize g1 = models.Gaussian1D(9.9, 14.5, stddev=.3) def func(p, x): return p[0] * np.exp(-0.5 / p[2]**2 * (x - p[1])**2) def errf(p, x, y): return func(p, x) - y p0 = [9.9, 14.5, 0.3] y = g1(self.x) n = np.random.randn(100) ny = y + n fitpar, s = optimize.leastsq(errf, p0, args=(self.x, ny)) fitter = fitting.LevMarLSQFitter() model = fitter(g1, self.x, ny) assert_allclose(model.parameters, fitpar, rtol=5 * 10**(-3))
def estimate_peak_width(data, min=2, max=8): """ Estimates the FWHM of the spectral features (arc lines) by fitting Gaussians to the brightest peaks. Parameters ---------- data: ndarray 1D data array (will be modified) min: int minimum plausible peak width max: int maximum plausible peak width (not inclusive) Returns ------- float: estimate of FWHM of features """ all_widths = [] for fwidth in range(min, max + 1): # plausible range of widths data_copy = data.copy() # We'll be editing the data widths = [] for i in range(15): # 15 brightest peaks, should ensure we get real ones index = 2 * fwidth + np.argmax(data_copy[2 * fwidth:-2 * fwidth - 1]) data_to_fit = data_copy[index - 2 * fwidth:index + 2 * fwidth + 1] m_init = models.Gaussian1D(stddev=0.42466 * fwidth) + models.Const1D(np.min(data_to_fit)) m_init.mean_0.bounds = [-1, 1] m_init.amplitude_1.fixed = True fit_it = fitting.FittingWithOutlierRemoval(fitting.LevMarLSQFitter(), sigma_clip, sigma=3) with warnings.catch_warnings(): # Ignore model linearity warning from the fitter warnings.simplefilter('ignore') m_final, _ = fit_it(m_init, np.arange(-2 * fwidth, 2 * fwidth + 1), data_to_fit) # Quick'n'dirty logic to remove "peaks" at edges of CCDs if m_final.amplitude_1 != 0 and m_final.stddev_0 < fwidth: widths.append(m_final.stddev_0 / 0.42466) # Set data to zero so no peak is found here data_copy[index - 2 * fwidth:index + 2 * fwidth + 1] = 0. all_widths.append(sigma_clip(widths).mean()) return sigma_clip(all_widths).mean()
def test__remove_axes_from_shape(): model = models.Gaussian1D() # len(shape) == 0 assert model._remove_axes_from_shape((), mk.MagicMock()) == () # axis < 0 assert model._remove_axes_from_shape((1, 2, 3), -1) == (1, 2) assert model._remove_axes_from_shape((1, 2, 3), -2) == (1, 3) assert model._remove_axes_from_shape((1, 2, 3), -3) == (2, 3) # axis >= len(shape) assert model._remove_axes_from_shape((1, 2, 3), 3) == () assert model._remove_axes_from_shape((1, 2, 3), 4) == () # 0 <= axis < len(shape) assert model._remove_axes_from_shape((1, 2, 3), 0) == (2, 3) assert model._remove_axes_from_shape((1, 2, 3), 1) == (3,) assert model._remove_axes_from_shape((1, 2, 3), 2) == ()
def test_fitting_missing_data_units(): """ Raise an error if the model has units but the data doesn't """ g_init = models.Gaussian1D(amplitude=1. * u.mJy, mean=3 * u.cm, stddev=2 * u.mm) fit_g = fitting.LevMarLSQFitter() with pytest.raises(UnitsError) as exc: fit_g(g_init, [1, 2, 3], [4, 5, 6]) assert exc.value.args[0] == ( "'cm' (length) and '' (dimensionless) are not " "convertible") with pytest.raises(UnitsError) as exc: fit_g(g_init, [1, 2, 3] * u.m, [4, 5, 6]) assert exc.value.args[0] == ("'mJy' (spectral flux density) and '' " "(dimensionless) are not convertible")
def test_fitters_interface(): """ Test that **kwargs work with all optimizers. This is a basic smoke test. """ levmar = LevMarLSQFitter() slsqp = SLSQPLSQFitter() simplex = SimplexLSQFitter() kwargs = {'maxiter': 77, 'verblevel': 1, 'epsilon': 1e-2, 'acc': 1e-6} simplex_kwargs = {'maxiter': 77, 'verblevel': 1, 'acc': 1e-6} model = models.Gaussian1D(10, 4, .3) x = np.arange(21) y = model(x) slsqp_model = slsqp(model, x, y, **kwargs) simplex_model = simplex(model, x, y, **simplex_kwargs) kwargs.pop('verblevel') lm_model = levmar(model, x, y, **kwargs)
def test_equivalent_width_regions(): np.random.seed(42) frequencies = np.linspace(100, 1, 10000) * u.GHz g = models.Gaussian1D(amplitude=1 * u.Jy, mean=10 * u.GHz, stddev=1 * u.GHz) noise = np.random.normal(0., 0.001, frequencies.shape) * u.Jy flux = g(frequencies) + noise + 1 * u.Jy spec = Spectrum1D(spectral_axis=frequencies, flux=flux) cont_norm_spec = spec / np.median(spec.flux) result = equivalent_width(cont_norm_spec, regions=SpectralRegion(97 * u.GHz, 3 * u.GHz)) expected = -(np.sqrt(2 * np.pi) * u.GHz) assert quantity_allclose(result, expected, atol=0.02 * u.GHz)
def fake_point_source_spatial_profile(height, width, model_parameters, fwhm=5): """ Generates a 2D array with a fake point source with constant intensity in the spectral dimension and a gaussian distribution in the spatial dimension. The center of the gaussian changes depends on the Chebyshev1D model defined by the input parameters. Parameters ---------- height : int Output 2D array's number of rows. width : int Output 2D array's number of columns. model_parameters : dict Model parameters with keys defined as 'c0', 'c1', ..., 'c{n-1}', where 'n' is the Chebyshev1D order. fwhm : float Full-width at half-maximum of the gaussian profile. Returns ------- np.ndarray 2D array with a fake point source """ order = len(model_parameters) + 1 trace_model = models.Chebyshev1D(order, domain=[0, width - 1], **model_parameters) x = np.arange(width) y = trace_model(x) n = y.size gaussian_model = models.Gaussian1D( mean=y, amplitude=[1] * n, stddev=[fwhm / (2. * np.sqrt(2 * np.log(2)))] * n, n_models=n) source = gaussian_model(np.arange(height), model_set_axis=False).T return source
def test_find_peaks_with_noise(noise): x = np.arange(0, 3200) y = np.zeros_like(x, dtype=float) n_peaks = 20 stddev = 4. peaks = np.linspace( x.min() + 0.05 * x.ptp(), x.max() - 0.05 * x.ptp(), n_peaks) for x0 in peaks: g = models.Gaussian1D(mean=x0, stddev=stddev) y += g(x) np.random.seed(0) y += (np.random.random(x.size) - 0.5) * noise peaks_detected, _ = tracing.find_peaks(y, np.ones_like(y) * stddev) np.testing.assert_allclose(peaks_detected, peaks, atol=1)
def gauss_fit_1p(velo, spec, toWrite=False, source='', size=0, paras=None): plt.gcf() if paras == None: plt.clf() paras = [0.1, 40., 10.] plt.plot(velo, spec) plt.xlim(-200, 200) plt.title(source + ' - Radius {:3.0f}"'.format(size), size='x-large') plt.xlabel('V$_{LSR}$ (km/s)', size='x-large') plt.ylabel('Jy/beam', size='x-large') else: plt.gcf() r_s2f = 2.355 # sigma to fwhm: FWHM = 2.355*sigma gauss = models.Gaussian1D(amplitude=paras[0], mean=paras[1], stddev=paras[2] / r_s2f) gauss.amplitude.min = 0. gauss.mean.bounds = [0., 150.] gauss.stddev.bounds = [5. / r_s2f, 40. / r_s2f] fit = LevMarLSQFitter() sp_fit = fit(gauss, velo, spec) fpeak = sp_fit.amplitude.value vlsr = sp_fit.mean.value fwhm = sp_fit.fwhm para_err = np.sqrt(np.diag(fit.fit_info['param_cov'])) print('Flux: {:6.4f}; Vlsr: {:5.1f}; FWHM: {:4.1f}'.format( fpeak, vlsr, fwhm)) for old_line in plt.gca().lines + plt.gca().collections: print('oldline') old_line.remove() plt.plot(velo, spec, color='C0') plt.plot(velo, sp_fit(velo), color='C3') if toWrite: plt.savefig(source + '.png', dpi=300, bbox_inches='tight') plt.show() return fpeak, vlsr, fwhm, para_err[0], para_err[1], para_err[2]
def test_equivalent_width_continuum(continuum): np.random.seed(42) frequencies = np.linspace(1, 100, 10000) * u.GHz g = models.Gaussian1D(amplitude=1*u.Jy, mean=10*u.GHz, stddev=1*u.GHz) noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise + continuum spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) result = equivalent_width(spectrum, continuum=continuum) assert result.unit.is_equivalent(spectrum.spectral_axis_unit) # Since this is an emission line, we expect the equivalent width value to # be negative expected = -(np.sqrt(2*np.pi) * u.GHz) / continuum.value assert quantity_allclose(result, expected, atol=0.01*u.GHz)
def fit_distribution(dist, start_mean=None, start_amp=None, start_std=None): x_vals = np.arange(len(dist)) start_mean = start_mean or dist.argmax() start_amp = start_amp or int(max(dist)) start_std = start_std or 1.05 g_init = models.Gaussian1D(amplitude=start_amp, mean=start_mean, stddev=start_std, bounds={'mean': [1, 30]}) g_init.stddev.fixed = True fit_g = fitting.LevMarLSQFitter() g = fit_g(g_init, x_vals, dist) success = fit_ok(g, fit_g, start_mean, start_amp, start_std) return g, fit_g, success
def test_double_peak_fit_with_exclusion(): """ Double Peak fit with a window. """ x_double, y_double = double_peak() s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) g1_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.9*u.um, stddev=0.2*u.um) g1_fit = fit_lines(s_double, g1_init, exclude_regions=[SpectralRegion(5.2*u.um, 5.8*u.um)]) y1_double_fit = g1_fit(x_double*u.um) # Comparing every 10th value. y1_double_fit_expected = np.array([4.64465938e-130, 3.11793334e-103, 1.60765691e-079, 6.36698036e-059, 1.93681098e-041, 4.52537486e-027, 8.12148549e-016, 1.11951515e-007, 1.18532671e-002, 9.63961653e-001, 6.02136613e-002, 2.88897581e-006, 1.06464879e-013, 3.01357787e-024, 6.55197242e-038, 1.09414605e-054, 1.40343441e-074, 1.38268273e-097, 1.04632487e-123, 6.08168818e-153]) assert np.allclose(y1_double_fit.value[::10], y1_double_fit_expected, atol=1e-5)
def test_fwzi_multi_spectrum(): np.random.seed(42) disp = np.linspace(0, 100, 1000) * u.AA amplitudes = [0.1, 1, 10] * u.Jy means = [25, 50, 75] * u.AA stddevs = [1, 5, 10] * u.AA params = list(zip(amplitudes, means, stddevs)) flux = np.zeros(shape=(3, len(disp))) for i in range(3): flux[i] = models.Gaussian1D(*params[i])(disp) spec = Spectrum1D(spectral_axis=disp, flux=flux * u.Jy) expected = [113.51706001 * u.AA, 567.21252727 * u.AA, 499.5024546 * u.AA] assert quantity_allclose(fwzi(spec), expected)
def fit_gaussian_peak(x, y, guess=None): # fit a Gaussian to a peak # # Return model fitted object # peak_model_fit.parameters = [offset, amplitude, mean, standard deviation] if guess is None: # help make some guesses offset = np.min(y) guess = [offset, np.max(y) - offset, x[np.argmax(y)], 1.0] g1 = models.Gaussian1D(guess[1], guess[2], guess[3]) amp = models.Const1D(guess[0]) peak_model = amp + g1 fitter = fitting.LevMarLSQFitter() peak_model_fit = fitter(peak_model, x, y) return peak_model_fit
def test_line_flux(): np.random.seed(42) frequencies = np.linspace(1, 100, 10000) * u.GHz g = models.Gaussian1D(amplitude=1*u.Jy, mean=10*u.GHz, stddev=1*u.GHz) noise = np.random.normal(0., 0.01, frequencies.shape) * u.Jy flux = g(frequencies) + noise spectrum = Spectrum1D(spectral_axis=frequencies, flux=flux) result = line_flux(spectrum) assert result.unit.is_equivalent(u.erg / u.cm**2 / u.s) # Account for the fact that Astropy uses a different normalization of the # Gaussian where the integral is not 1 expected = np.sqrt(2*np.pi) * u.GHz * u.Jy assert quantity_allclose(result, expected, atol=0.01*u.GHz*u.Jy)
def test_fitters_interface(fitter): """ Test that ``**kwargs`` work with all optimizers. This is a basic smoke test. """ fitter = fitter() model = models.Gaussian1D(10, 4, .3) x = np.arange(21) y = model(x) if isinstance(fitter, SimplexLSQFitter): kwargs = {'maxiter': 77, 'verblevel': 1, 'acc': 1e-6} else: kwargs = {'maxiter': 77, 'verblevel': 1, 'epsilon': 1e-2, 'acc': 1e-6} if isinstance(fitter, LevMarLSQFitter) or isinstance(fitter, _NLLSQFitter): kwargs.pop('verblevel') _ = fitter(model, x, y, **kwargs)
def test_double_peak_fit_with_exclusion(): """ Double Peak fit with a window. """ x_double, y_double = double_peak() s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) g1_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.9*u.um, stddev=0.2*u.um) g1_fit = fit_lines(s_double, g1_init, exclude_regions=[SpectralRegion(5.2*u.um, 5.8*u.um)]) y1_double_fit = g1_fit(x_double*u.um) # Comparing every 10th value. y1_double_fit_expected = np.array([1.22845792e-129, 6.72991033e-103, 2.89997996e-079, 9.82918347e-059, 2.62045444e-041, 5.49506092e-027, 9.06369193e-016, 1.17591109e-007, 1.19999812e-002, 9.63215290e-001, 6.08139060e-002, 3.02008492e-006, 1.17970152e-013, 3.62461471e-024, 8.75968088e-038, 1.66514266e-054, 2.48972475e-074, 2.92811381e-097, 2.70870241e-123, 1.97093074e-152]) assert np.allclose(y1_double_fit.value[::10], y1_double_fit_expected, atol=1e-5)
def fitline(wvl, flux, err, line): ''' Function to fit line ''' # Fit line with Gaussian + linear background gaussian_model = models.Gaussian1D(np.max(flux), line, 2) + models.Linear1D(0,0) fitter = fitting.LevMarLSQFitter() gaussian_fit = fitter(gaussian_model, wvl, flux, weights=1./err) # Get best-fit parameters params = gaussian_fit.parameters amp, mean, stddev = params[0:3] try: paramerrs = np.sqrt(np.diag(fitter.fit_info['param_cov'])) amp_err, mean_err, stddev_err = paramerrs[0:3] except: amp_err, mean_err, stddev_err = [np.nan, np.nan, np.nan] integral = np.sqrt(2.*np.pi)*amp*stddev if integral > 1e-3 and stddev < xlim/2. and np.abs(mean - line) < xlim/2.: # and amp_err < amp: #and gaussian_fit[0].stddev.value*2.355 > 2.4 # Compute SNR emidx = np.where((wvl > (mean-2.5*stddev)) & (wvl < (mean+2.5*stddev)))[0] emflux = flux[emidx] cont1idx = np.where((wvl < (mean-5*stddev)))[0] cont2idx = np.where((wvl > (mean+5*stddev)))[0] contflux1 = flux[cont1idx] contflux2 = flux[cont2idx] signal = np.sum(emflux - np.mean(np.hstack((contflux1,contflux2)))) / np.sqrt(len(emflux)) noisecont = (np.std(contflux1) + np.std(contflux2)) / 2. # Continuum noise pois = np.random.poisson(size=len(emflux)) noisepois = np.std(pois/np.sum(pois)*np.sqrt(emflux)) # Poisson noise noise = np.sqrt(noisecont**2. + noisepois**2.) else: signal, noise = [np.nan, np.nan] return amp, mean, stddev, amp_err, mean_err, stddev_err, integral, signal, noise
def fit_gaussian1d(x, y, init_amp=1.0, init_mean=0.0, init_std=0.45, xcrop=None): """Fit a Gaussian 1D kernel to the data. Parameters ---------- x: array-like x values. y: array-like y values. init_amp: float, optional Initial amplitude parameter for the fit. Default 1.0 init_mean: float, optional Initial mean parameter for the fit. Default 0.0 init_std: float, optional Initial standard deviation parameter for the fit. Default 0.45. xcrop: (min, max) or None, optional Crop input to min <= angle <= max. Returns ------- amp: float Amplitude of the fitted Gaussian. mean: float Mean of the fitted Gaussian. std: float Standard deviation of the fitted Gaussian. """ fitter = fitting.LevMarLSQFitter() g1_init = models.Gaussian1D(init_amp, init_mean, init_std) if xcrop is not None: mask = (x >= xcrop[0]) & (x <= xcrop[1]) else: mask = np.ones_like(x, dtype=bool) g1 = fitter(g1_init, x[mask], y[mask]) return g1.amplitude.value, g1.mean.value, g1.stddev.value
def fit_gaussians_to_spectrum_linebyline(obs_flx, obs_wvl, idx_peaks, d_wvl=2): print ' Fitting {:.0f} individual gaussinas to the extracted arc spectrum'.format(len(idx_peaks)) fitted_vals = [] # [mean, std] combinations for i_p, idx_p in enumerate(idx_peaks): # data subset idx_data_use = np.logical_and(obs_wvl > obs_wvl[idx_p]-d_wvl, obs_wvl < obs_wvl[idx_p]+d_wvl) use_flx = obs_flx[idx_data_use] use_wvl = obs_wvl[idx_data_use] # median_val = np.median(use_flx) fit_model = models.Const1D(amplitude=np.median(use_flx)) peak_val = obs_flx[idx_p] - median_val # dela boljs brez nastavljenih boundov fit_model += models.Gaussian1D(amplitude=peak_val, mean=obs_wvl[idx_p], stddev=0.1)#, # bounds={'mean': (obs_wvl[idx_p]-0.5, obs_wvl[idx_p]+0.5), # 'amplitude': (peak_val*0.8, peak_val*1.2)}) fit_t = fitting.LevMarLSQFitter() fitted_model = fit_t(fit_model, use_wvl, use_flx) # print fitted_model.param_names fitted_vals.append(fitted_model.parameters[2:]) return np.array(fitted_vals)
def _fit_ccf(rv, ccf): """Fit the CCF with a 1D gaussian :rv: The RV vector :ccf: The CCF values :returns: The RV, and best fit gaussian """ ampl = 1 mean = rv[ccf == ampl] I = np.where(ccf == ampl)[0] g_init = models.Gaussian1D(amplitude=ampl, mean=mean, stddev=5) fit_g = fitting.LevMarLSQFitter() try: g = fit_g(g_init, rv[I - 10:I + 10], ccf[I - 10:I + 10]) except TypeError: print('Warning: Not able to fit a gaussian to the CCF') return 0, g_init RV = g.mean.value return RV, g
def fit_gauss_1d(data): """Fit a 1D gaussian to the data and return the fit.""" # data is assumed to already be chunked to a reasonable size delta = int(len(data) / 2.) # guess the center ldata = len(data) x = np.arange(ldata) # Fit model to data fit = fitting.LevMarLSQFitter() # Gaussian1D + a constant model = (models.Gaussian1D( amplitude=data.max() - data.min(), mean=delta, stddev=1.) + models.Polynomial1D(c0=data.min(), degree=0)) with warnings.catch_warnings(): # Ignore model linearity warning from the fitter warnings.simplefilter('ignore') results = fit(model, x, data) # previous yield amp, ycenter, xcenter, sigma, offset return results
def test_custom_bounding_box_1d(): """ Tests that the bounding_box setter works. """ # 1D models g1 = models.Gaussian1D() bb = g1.bounding_box expected = g1.render() # assign the same bounding_box, now through the bounding_box setter g1.bounding_box = bb assert_allclose(g1.render(), expected) # 2D models g2 = models.Gaussian2D() bb = g2.bounding_box expected = g2.render() # assign the same bounding_box, now through the bounding_box setter g2.bounding_box = bb assert_allclose(g2.render(), expected)
def test_autocorrelation(): """ Test auto correlation """ size = 42 # Seed np.random so that results are consistent np.random.seed(41) # Create test spectra spec_axis = np.linspace(5000., 5040., num=size) * u.AA f1 = np.random.randn(size) * u.Jy g1 = models.Gaussian1D(amplitude=30 * u.Jy, mean=5020 * u.AA, stddev=2 * u.AA) flux1 = f1 + g1(spec_axis) # Observed spectrum must have a rest wavelength value set in. spec1 = Spectrum1D(spectral_axis=spec_axis, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy'), velocity_convention='optical', rest_value=5020.*u.AA) spec2 = Spectrum1D(spectral_axis=spec_axis, flux=flux1, uncertainty=StdDevUncertainty(np.random.sample(size), unit='Jy')) # Get result from correlation corr, lag = correlation.template_correlate(spec1, spec2) # Check units assert corr.unit == u.dimensionless_unscaled assert lag.unit == u.km / u.s # Check that lags are symmetrical midpoint = int(len(lag) / 2) np.testing.assert_almost_equal(lag[midpoint+1].value, (-(lag[midpoint-1])).value, 2) # Check position of correlation peak. maximum = np.argmax(corr) assert maximum == midpoint
def refine_velocity_guess(spectrum, axis, v_guess, detected_line, return_fit = False): """ Refines a velocity guess with better accuracy, avoiding to have discrete guess corresponding to pixel numbers. A gaussian function is fitted to estimate the line position. Parameters ---------- spectrum : 1D :class:`~numpy:numpy.ndarray` The spectrum containing emission lines axis : 1D :class:`~numpy:numpy.ndarray` The corresponding axis, in wavenumber v_guess : float A first guess on the velocity, typically obtained from :func:`guess_source_velocity` detected_line : str Names of the main line present in the spectrum (as defined `here <http://celeste.phy.ulaval.ca/orcs-doc/introduction.html#list-of-available-lines>`_) return_fit : bool, Default = False (Optional) If True, returns the fit parameters, for further investigation Returns ------- v : float The updated velocity guess """ from orb.utils.spectrum import line_shift, compute_radial_velocity from orb.core import Lines from astropy.modeling import models, fitting line_rest = Lines().get_line_cm1(detected_line) mu = line_rest + line_shift(v_guess, line_rest, wavenumber=True) G0 = models.Gaussian1D(amplitude=np.nanmax(spectrum), mean=mu, stddev=11) G0.mean.max = line_rest + line_shift(v_guess-25, line_rest, wavenumber=True) G0.mean.min = line_rest + line_shift(v_guess+25, line_rest, wavenumber=True) C = models.Const1D(amplitude = np.nanmedian(spectrum)) model = C+G0 fitter = fitting.LevMarLSQFitter() fit = fitter(model, axis, spectrum) if return_fit: return compute_radial_velocity(fit.mean_1,line_rest, wavenumber=True), fit else: return compute_radial_velocity(fit.mean_1,line_rest, wavenumber=True)
def test_spectrum_from_model(): """ This test fits the the first simulated spectrum from the fixture. The initial guesses are manually set here with bounds that essentially make sense as the functionality of the test is to make sure the fit works and we get a reasonable answer out **given** good initial guesses. """ np.random.seed(0) x = np.linspace(0., 10., 200) y = 3 * np.exp(-0.5 * (x - 6.3)**2 / 0.1**2) y += np.random.normal(0., 0.2, x.shape) y_continuum = 3.2 * np.exp(-0.5 * (x - 5.6)**2 / 4.8**2) y += y_continuum spectrum = Spectrum1D(flux=y*u.Jy, spectral_axis=x*u.um) # Unitless test chebyshev = models.Chebyshev1D(3, c0=0.1, c1=4, c2=5) spectrum_chebyshev = spectrum_from_model(chebyshev, spectrum) flux_expected = np.array([-4.90000000e+00, -3.64760991e-01, 9.22085553e+00, 2.38568496e+01, 4.35432211e+01, 6.82799702e+01, 9.80670968e+01, 1.32904601e+02, 1.72792483e+02, 2.17730742e+02, 2.67719378e+02, 3.22758392e+02, 3.82847784e+02, 4.47987553e+02, 5.18177700e+02, 5.93418224e+02, 6.73709126e+02, 7.59050405e+02, 8.49442062e+02, 9.44884096e+02]) assert np.allclose(spectrum_chebyshev.flux.value[::10], flux_expected, atol=1e-5) # Unitfull test gaussian = models.Gaussian1D(amplitude=5*u.Jy, mean=4*u.um, stddev=2.3*u.um) spectrum_gaussian = spectrum_from_model(gaussian, spectrum) flux_expected = np.array([1.1020263, 1.57342489, 2.14175093, 2.77946243, 3.4389158, 4.05649712, 4.56194132, 4.89121902, 4.99980906, 4.872576, 4.52723165, 4.01028933, 3.3867847, 2.72689468, 2.09323522, 1.5319218, 1.06886794, 0.71101768, 0.45092638, 0.27264641]) assert np.allclose(spectrum_gaussian.flux.value[::10], flux_expected, atol=1e-5)
def test_fwhm(): np.random.seed(42) # Create an (uncentered) spectrum for testing frequencies = np.linspace(0, 10, 1000) * u.GHz stddev = 0.8*u.GHz g1 = models.Gaussian1D(amplitude=5*u.Jy, mean=2*u.GHz, stddev=stddev) spectrum = Spectrum1D(spectral_axis=frequencies, flux=g1(frequencies)) result = fwhm(spectrum) expected = stddev * gaussian_sigma_to_fwhm assert quantity_allclose(result, expected, atol=0.01*u.GHz) # Highest point at the first point wavelengths = np.linspace(1, 10, 100) * u.um flux = (1.0 / wavelengths.value)*u.Jy # highest point first. spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 0.9090909090909092*u.um # Highest point at the last point wavelengths = np.linspace(1, 10, 100) * u.um flux = wavelengths.value*u.Jy # highest point last. spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 5*u.um # Flat spectrum wavelengths = np.linspace(1, 10, 100) * u.um flux = np.ones(wavelengths.shape)*u.Jy # highest point last. spectrum = Spectrum1D(spectral_axis=wavelengths, flux=flux) result = fwhm(spectrum) assert result == 9*u.um
def fake_emission_line_spectrum(size, n_lines, max_intensity=1, fwhm=2): """ Generates a 1D array with the a fake emission-line spectrum using lines at random positions and with random intensities. Parameters ---------- size : int Output array's size. n_lines : int Number of sky lines. max_intensity : float Maximum sky line intensity (default=1). fwhm : float Lines width in pixels (default=2). Returns ------- np.ndarray Modeled emission-line spectrum """ lines_positions = np.random.randint(low=0, high=size - 1, size=n_lines) lines_intensities = np.random.rand(n_lines) * max_intensity stddev = [fwhm / (2. * np.sqrt(2. * np.log(2.)))] * n_lines print(len(lines_positions), len(lines_intensities), len(stddev)) model = models.Gaussian1D( amplitude=lines_intensities, mean=lines_positions, stddev=stddev, n_models=n_lines ) source = model(np.arange(size), model_set_axis=False) source = source.sum(axis=0) return source
def test_fwzi_masked(): np.random.seed(42) disp = np.linspace(0, 100, 100) * u.AA g = models.Gaussian1D(mean=np.mean(disp), amplitude=1 * u.Jy, stddev=10 * u.AA) flux = g(disp) + ((np.random.sample(disp.size) - 0.5) * 0.1) * u.Jy # Add mask. It is built such that about 50% of the data points # on and around the Gaussian peak are masked out (this was checked # with the debugger to examine in-memory data). uncertainty = StdDevUncertainty(0.1 * np.random.random(len(disp)) * u.Jy) mask = (np.random.randn(disp.shape[0]) - 0.5) > 0 spec = Spectrum1D(spectral_axis=disp, flux=flux, uncertainty=uncertainty, mask=mask) assert quantity_allclose(fwzi(spec), 35.9996284 * u.AA)
def test_double_peak_fit_window(): """ Double Peak fit with a window. """ # Create the specturm to fit x_double, y_double = double_peak() s_double = Spectrum1D(flux=y_double*u.Jy, spectral_axis=x_double*u.um, rest_value=0*u.um) # Fit the spectrum g2_init = models.Gaussian1D(amplitude=1.*u.Jy, mean=4.7*u.um, stddev=0.2*u.um) g2_fit = fit_lines(s_double, g2_init, window=0.3*u.um) y2_double_fit = g2_fit(x_double*u.um) # Comparing every 10th value. y2_double_fit_expected = np.array([1.66363393e-128, 5.28910721e-102, 1.40949521e-078, 3.14848385e-058, 5.89516506e-041, 9.25224449e-027, 1.21718016e-015, 1.34220626e-007, 1.24062432e-002, 9.61209273e-001, 6.24240938e-002, 3.39815491e-006, 1.55056770e-013, 5.93054936e-024, 1.90132233e-037, 5.10943886e-054, 1.15092572e-073, 2.17309153e-096, 3.43926290e-122, 4.56256813e-151]) assert np.allclose(y2_double_fit.value[::10], y2_double_fit_expected, atol=1e-5)