コード例 #1
0
def test_spectrum_methods(spec_var, spec_novar):
    """Spectrum class: testing sum/mean/abs/sqrt methods"""
    wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm, shape=10)
    spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
                         wave=wave)
    sum1 = spectrum1.sum()
    assert_almost_equal(sum1[0], spectrum1.data.sum())
    spectrum2 = spectrum1[1:-2]
    sum1 = spectrum1.sum(lmin=spectrum1.wave.coord(1),
                         lmax=spectrum1.wave.coord(10 - 3),
                         unit=u.nm)
    sum2 = spectrum2.sum()
    assert_almost_equal(sum1, sum2)
    mean1 = spectrum1.mean(lmin=spectrum1.wave.coord(1),
                           lmax=spectrum1.wave.coord(10 - 3),
                           unit=u.nm)
    mean2 = spectrum2.mean()
    assert_almost_equal(mean1, mean2)

    spvar2 = spec_var.abs()
    assert spvar2[23] == np.abs(spec_var[23])
    spvar2 = spec_var.abs().sqrt()
    assert spvar2[8] == np.sqrt(np.abs(spec_var[8]))
    assert_almost_equal(spec_var.mean()[0], 11.526, 2)
    assert_almost_equal(spec_novar.mean()[0], 11.101, 2)
    spvarsum = spvar2 + 4 * spvar2 - 56 / spvar2

    assert_almost_equal(spvarsum[10],
                        spvar2[10] + 4 * spvar2[10] - 56 / spvar2[10], 2)
    assert_almost_equal(spec_var.get_step(), 0.630, 2)
    assert_almost_equal(spec_var.get_start(), 4602.604, 2)
    assert_almost_equal(spec_var.get_end(), 7184.289, 2)
    assert_almost_equal(spec_var.get_range()[0], 4602.604, 2)
    assert_almost_equal(spec_var.get_range()[1], 7184.289, 2)
コード例 #2
0
def test_resample2():
    """Spectrum class: testing resampling function
    with a spectrum of integers and resampling to a smaller pixel size"""
    wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm)
    spectrum1 = Spectrum(data=np.array([0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]),
                         wave=wave)
    flux1 = spectrum1.sum()[0] * spectrum1.wave.get_step()
    spectrum2 = spectrum1.resample(0.3)
    flux2 = spectrum2.sum()[0] * spectrum2.wave.get_step()
    assert_almost_equal(flux1, flux2, 2)
コード例 #3
0
def test_integrate():
    """Spectrum class: testing integration"""
    wave = WaveCoord(crpix=2.0, cdelt=3.0, crval=0.5, cunit=u.nm)
    spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
                         wave=wave,
                         unit=u.Unit('ct/Angstrom'))

    # Integrate the whole spectrum, by not specifying starting or ending
    # wavelengths. This should be the sum of the pixel values multiplied
    # by cdelt in angstroms (because the flux units are per angstrom).
    result, err = spectrum1.integrate()
    expected = spectrum1.get_step(unit=u.angstrom) * spectrum1.sum()[0]
    assert_almost_equal(result.value, expected)
    assert result.unit == u.ct
    assert np.isinf(err)

    # The result should not change if we change the wavelength units of
    # the wavelength limits to nanometers.
    result = spectrum1.integrate(unit=u.nm)[0]
    expected = spectrum1.get_step(unit=u.angstrom) * spectrum1.sum()[0]
    assert_almost_equal(result.value, expected)
    assert result.unit == u.ct

    # new spectrum with variance
    spectrum1 = Spectrum(data=np.array([0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
                         var=np.ones(10),
                         wave=wave,
                         unit=u.Unit('ct/Angstrom'))

    # Integrate over a wavelength range 3.5 to 6.5 nm. The WCS
    # conversion equation from wavelength to pixel index is,
    #
    #  index = crpix-1 + (lambda-crval)/cdelt
    #  index = 1 + (lambda - 0.5) / 3.0
    #
    # So wavelengths 3.5 and 6.5nm, correspond to pixel indexes
    # of 2.0 and 3.0. These are the centers of pixels 2 and 3.
    # Thus the integration should be the value of pixel 2 times
    # half of cdelt, plus the value of pixel 3 times half of cdelt.
    # This comes to 2*3.0/2 + 3*3.0/2 = 7.5 ct/Angstrom*nm, which
    # should be rescaled to 75 ct, since nm/Angstrom is 10.0.
    result, err = spectrum1.integrate(lmin=3.5, lmax=6.5, unit=u.nm)
    assert_almost_equal(result.value, 75)
    assert result.unit == u.ct

    datasum, var = spectrum1.sum(lmin=3.5, lmax=6.5, unit=u.nm)
    assert_almost_equal(result.value, datasum * 15)
    assert_almost_equal(err.value, var * 15)

    # Do the same test, but specify the wavelength limits in angstroms.
    # The result should be the same as before.
    result = spectrum1.integrate(lmin=35.0, lmax=65.0, unit=u.angstrom)[0]
    assert_almost_equal(result.value, 75)
    assert result.unit == u.ct

    assert_almost_equal(result.value, datasum * 15)
    assert_almost_equal(err.value, var * 15)

    # Do the same experiment yet again, but this time after changing
    # the flux units of the spectrum to simple counts, without any per
    # wavelength units. Since there are no wavelength units in the
    # flux units, the result should not be rescaled from the native
    # value of 7.5, and because we specified a wavelength range in
    # angstroms, the resulting units should be counts * nm.
    spectrum1.unit = u.ct
    result = spectrum1.integrate(lmin=3.5, lmax=6.5, unit=u.nm)[0]
    assert_almost_equal(result.value, 7.5)
    assert result.unit == u.ct * u.nm
コード例 #4
0
def test_resample():
    """Spectrum class: Test resampling"""

    # Choose the dimensions of the spectrum, choosing a large number that is
    # *not* a convenient power of 2.
    oldshape = 4000

    # Choose the wavelength pixel size and the default wavelength units.
    oldstep = 1.0
    oldunit = u.angstrom

    # Create the wavelength axis coordinates.
    wave = WaveCoord(crpix=2.0,
                     cdelt=oldstep,
                     crval=0.5,
                     cunit=oldunit,
                     shape=oldshape)

    # Specify the desired increase in pixel size, and the resulting pixel size.
    factor = 6.5
    newstep = ((factor * oldstep) * oldunit).to(u.nm).value

    # Specify the wavelength at which the peak of the resampled spectrum should
    # be expected.
    expected_peak_wave = 3000.0

    # Create the array in which the test spectrum will be composed.
    data = np.zeros(oldshape)

    # Get the wavelength coordinates of each pixel in the spectrum.
    w = wave.coord()

    # Add the following list gaussians to the spectrum, where each
    # gaussian is specified as: (amplitude, sigma_in_pixels,
    # center_wavelength). Given that narrow gaussians are reduced in
    # amplitude by resampling more than wide gaussians, we arrange
    # that the peak gaussian before and after correctly resampling are
    # different.
    gaussians = [
        (0.5, 12.0, 800.0),
        (0.7, 5.0, 1200.0),
        (0.4, 700.0, 1600.0),
        (1.5, 2.6, 1980.0),  # Peak before resampling
        (1.2, 2.6, 2000.0),
        (1.3, 15.0, expected_peak_wave),  # Peak if resampled correctly
        (1.0, 2.0, 3200.0)
    ]
    for amp, sigma, center in gaussians:
        sigma *= oldstep
        data += amp * np.exp(-0.5 * ((center - w) / sigma)**2)

    # Fill the variance array with a simple window function.
    var = np.hamming(oldshape)

    # Add gaussian random noise to the spectrum, but leave 3 output
    # pixel widths zero at each end of the spectrum so that the PSF of
    # the output grid doesn't spread flux from the edges off the edge
    # of the output grid. It takes about 3 pixel widths for the gaussian
    # PSF to drop to about 0.01 of its peak.
    margin = np.ceil(3 * factor).astype(int)
    data[margin:-margin] += np.random.normal(scale=0.1,
                                             size=data.shape - 2 * margin)

    # Install the spectral data in a Spectrum container.
    oldsp = Spectrum(data=data, var=var, wave=wave)

    # Mask a few pixels.
    masked_slice = slice(900, 910)
    oldsp.mask[masked_slice] = True

    # Create a down-sampled version of the input spectrum.
    newsp = oldsp.resample(newstep, unit=u.nm)

    # Check that the integral flux in the resampled spectrum matches that of
    # the original spectrum.
    expected_flux = oldsp.sum(weight=False)[0] * oldsp.wave.get_step(
        unit=oldunit)
    actual_flux = newsp.sum(weight=False)[0] * newsp.wave.get_step(
        unit=oldunit)
    assert_allclose(actual_flux, expected_flux, 1e-2)

    # Do the same test, but with fluxes weighted by the inverse of the variances.
    expected_flux = oldsp.sum(weight=True)[0] * oldsp.wave.get_step(
        unit=oldunit)
    actual_flux = newsp.sum(weight=True)[0] * newsp.wave.get_step(unit=oldunit)
    assert_allclose(actual_flux, expected_flux, 1e-2)

    # Check that the peak of the resampled spectrum is at the wavelength
    # where the strongest gaussian was centered in the input spectrum.
    assert_allclose(np.argmax(newsp.data),
                    newsp.wave.pixel(expected_peak_wave, nearest=True))

    # Now upsample the downsampled spectrum to the original pixel size.
    # This won't recover the same spectrum, since higher spatial frequencies
    # are lost when downsampling, but the total flux should be about the
    # same, and the peak should be at the same wavelength as the peak in
    # original spectrum within one pixel width of the downsampled spectrum.
    newsp2 = newsp.resample(oldstep, unit=oldunit)

    # Check that the doubly resampled spectrum has the same integrated flux
    # as the original.
    expected_flux = oldsp.sum(weight=False)[0] * oldsp.wave.get_step(
        unit=oldunit)
    actual_flux = newsp2.sum(weight=False)[0] * newsp2.wave.get_step(
        unit=oldunit)
    assert_allclose(actual_flux, expected_flux, 1e-2)

    # Check that the peak of the up-sampled spectrum is at the wavelength
    # of the peak of the down-sampled spectrum to within the pixel resolution
    # of the downsampled spectrum.
    assert_allclose(
        newsp.wave.pixel(newsp2.wave.coord(np.argmax(newsp2.data)),
                         nearest=True),
        newsp.wave.pixel(expected_peak_wave, nearest=True))

    # Check that pixels that were masked in the input spectrum are still
    # masked in the final spectrum.
    np.testing.assert_equal(newsp2.mask[masked_slice],
                            oldsp.mask[masked_slice])