Example #1
0
    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))
Example #2
0
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()
Example #3
0
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) == ()
Example #4
0
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")
Example #5
0
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)
Example #6
0
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)
Example #7
0
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
Example #8
0
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]
Example #10
0
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)
Example #11
0
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
Example #12
0
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)
Example #13
0
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)
Example #14
0
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
Example #15
0
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)
Example #16
0
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)
Example #17
0
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)
Example #18
0
		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
Example #19
0
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)
Example #21
0
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
Example #22
0
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
Example #23
0
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)
Example #24
0
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
Example #25
0
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)
Example #26
0
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)
Example #27
0
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
Example #28
0
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
Example #29
0
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)
Example #30
0
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)