예제 #1
0
def test_crop():
    """Image class: testing crop method"""
    # Create an image whose pixels are all masked.

    image1 = generate_image(shape=(9, 7), data=2.0, var=0.5, mask=True)

    # Create a masked array of unmasked values to be assigned to the
    # part of the image, with just a diamond shaped area of pixels
    # unmasked.

    diamond = np.ma.array(data=[[6.0, 2.0, 9.0],
                                [1.0, 4.0, 8.0],
                                [0.0, 5.0, 3.0]],
                          mask=[[True, False, True],
                                [False, False, False],
                                [True, False, True]])

    # Assign the above array to part of the image to clear the mask of
    # an irregular rectangular area of pixels there.

    image1.data[2:5, 1:4] = diamond

    # The following should crop all but the rectangular area that was
    # assigned above.

    image1.crop()

    # Check that the masked data array is as expected.

    assert_masked_allclose(image1.data, diamond)

    # The cropped variance array should look like the following array.

    expected_var = np.ma.array(data=[[0.5, 0.5, 0.5],
                                     [0.5, 0.5, 0.5],
                                     [0.5, 0.5, 0.5]], mask=diamond.mask)

    # Check that the masked variance array is as expected.

    assert_masked_allclose(image1.var, expected_var)

    # Check the WCS characteristics of the cropped image.

    assert_image_equal(image1, shape=(3, 3), start=(2, 1), end=(4, 3))
    assert image1.get_rot() == 0
예제 #2
0
def test_convolve():
    """Image class: testing discrete convolution method."""

    shape = (12, 25)
    wcs = WCS(cdelt=(1.0, 1.0), crval=(0.0, 0.0), shape=shape)
    data = np.zeros(shape)
    data[7, 5] = 1.0
    mask = np.zeros(shape, dtype=bool)
    mask[5, 3] = True
    ima = Image(wcs=wcs, data=data, mask=mask, copy=False)

    # Create a symmetric convolution kernel with an even number of elements
    # along one dimension and and odd number along the other dimension.
    # Make the kernel symmetric around (shape-1)//2. This requires that
    # the final column be all zeros.
    kern = np.array([[0.1, 0.25, 0.1, 0.0],
                     [0.25, 0.50, 0.25, 0.0],
                     [0.1, 0.25, 0.1, 0.0]])

    # The image should consist of a copy of the convolution kernel, centered
    # such that pixels (kern.shape-1)//2 is at pixel 7,5 of data.
    expected_data = np.ma.array(data=np.zeros(shape), mask=mask)
    expected_data.data[6:9, 4:8] = kern

    res = ima.convolve(kern)
    assert_masked_allclose(res.data, expected_data)

    res = ima.convolve(Image(data=kern))
    assert_masked_allclose(res.data, expected_data)

    res = ima.fftconvolve(kern)
    assert_masked_allclose(res.data, expected_data, atol=1e-15)
예제 #3
0
파일: test_cube.py 프로젝트: musevlt/mpdaf
def test_convolve():

    shape = (3, 12, 25)
    data = np.zeros(shape)
    data[:, 7, 5] = 1.0
    mask = np.zeros(shape, dtype=bool)
    mask[:, 5, 3] = True
    c = generate_cube(data=data, mask=mask, shape=shape,
                      wave=WaveCoord(crval=1, cunit=u.angstrom))

    # Create a symmetric convolution kernel with an even number of elements
    # along one dimension and and odd number along the other dimension.
    # Make the kernel symmetric around (shape-1)//2. This requires that
    # the final column be all zeros.
    kern = np.array([[[0.1, 0.25, 0.1, 0.0],
                      [0.25, 0.50, 0.25, 0.0],
                      [0.1, 0.25, 0.1, 0.0]]])

    # The image should consist of a copy of the convolution kernel, centered
    # such that pixels (kern.shape-1)//2 is at pixel 7,5 of data.
    expected_data = ma.array(data=np.zeros(shape), mask=mask)
    expected_data.data[:, 6:9, 4:8] = kern

    res = c.convolve(kern)
    assert_masked_allclose(res.data, expected_data, atol=1e-15)

    res = c.convolve(Image(data=kern))
    assert_masked_allclose(res.data, expected_data, atol=1e-15)

    res = c.fftconvolve(kern)
    assert_masked_allclose(res.data, expected_data, atol=1e-15)
예제 #4
0
def test_rebin():
    """Image class: testing rebin methods."""
    wcs = WCS(crval=(0, 0))
    data = np.arange(30).reshape(6, 5)
    image1 = Image(data=data, wcs=wcs, var=np.ones(data.shape) * 0.5)
    image1.mask_region((2, 2), (1.5, 1.5),
                       inside=False,
                       unit_center=None,
                       unit_radius=None)

    # The test data array looks as follows:
    #
    # ---- ---- ---- ---- ----
    # ----  6.0  7.0  8.0 ----
    # ---- 11.0 12.0 13.0 ----
    # ---- 16.0 17.0 18.0 ----
    # ---- ---- ---- ---- ----
    # ---- ---- ---- ---- ----
    #
    # Where ---- signifies a masked value.
    #
    # After reducing both dimensions by a factor of 2, we should
    # get a data array of the following 6 means of 4 pixels each:
    #
    #  ---- ---- => 6/1         ---- ---- => (7+8)/2
    #  ----  6.0                 7.0  8.0
    #
    #  ---- 11.0 => (11+16)/2   12.0 13.0 => (12+13+17+18)/4
    #  ---- 16.0                17.0 18.0
    #
    #  ---- ---- => ----        ---- ---- => ----
    #  ---- ----                ---- ----

    expected = np.ma.array(data=[[6.0, 7.5], [13.5, 15], [0.0, 0.0]],
                           mask=[[False, False], [False, False], [True, True]])
    image2 = image1.rebin(2)
    assert_masked_allclose(image2.data, expected)

    image2 = image1.rebin(factor=(2, 2))
    assert_masked_allclose(image2.data, expected)

    # The variances of the original pixels were all 0.5, so taking the
    # mean of N of these should give the mean a variance of 0.5/N.
    # Given the number of pixels averaged in each of the above means,
    # we thus expect the variance array to look as follows.

    expected = np.ma.array(data=[[0.5, 0.25], [0.25, 0.125], [0.0, 0.0]],
                           mask=[[False, False], [False, False], [True, True]])
    assert_masked_allclose(image2.var, expected)

    # Check the WCS information.

    start = image2.get_start()
    assert start[0] == 0.5
    assert start[1] == 0.5
예제 #5
0
def test_add_image(tmpdir, source2, a478hst, a370II):
    """Source class: testing add_image method"""
    minicube = Cube(get_data_file('sdetect', 'minicube.fits'), dtype=float)
    source2.add_white_image(minicube)
    ima = minicube.mean(axis=0)

    # The position source2.dec, source2.ra corresponds
    # to pixel index 18.817,32.432 in the cube. The default 5
    # arcsecond requested size of the white-light image corresponds
    # to 25 pixels. There will thus be 12 pixels on either side of
    # a central pixel. The nearest pixel to the center is 19,32, so
    # we expect add_white_image() to have selected the following
    # range of pixels cube[19-12:19+12+1, 32-12:32+12+1], which
    # is cube[7:32, 20:45]. However the cube only has 40 pixels
    # along the X-axis, so the white-light image should correspond
    # to:
    #
    #  white[:,:] = cube[7:32, 20:40]
    #  white.shape=(25,20)
    #
    # So: cube[15,25] = white[15-7, 25-20] = white[8, 5]
    assert ima[15, 25] == source2.images['MUSE_WHITE'][8, 5]

    # Add a square patch of an HST image equal in width and height
    # to the height of the white-light image, which has a height
    # of 25 white-light pixels.
    source2.add_image(a478hst, 'HST1')

    # Add the same HST image, but this time set the width and height
    # equal to the height of the above HST patch (ie. 50 pixels). This
    # should have the same result as giving it the same size as the
    # white-light image.
    size = source2.images['HST1'].shape[0]
    source2.add_image(a478hst, 'HST2', size=size, minsize=size, unit_size=None)
    assert source2.images['HST1'][10, 10] == source2.images['HST2'][10, 10]

    # Add the HST image again, but this time rotate it to the same
    # orientation as the white-light image, then check that they end
    # up with the same rotation angles.
    source2.add_image(a478hst, 'HST3', rotate=True)
    assert_almost_equal(source2.images['HST3'].get_rot(),
                        source2.images['MUSE_WHITE'].get_rot(), 3)

    # Trying to add image not overlapping with Source
    assert source2.add_image(a370II, 'ERROR') is None

    white = source2.images['MUSE_WHITE']
    mean, std = white.background()
    mask = white.data > (mean + 2 * std)
    mask = Image.new_from_obj(white, data=mask.astype(int))
    mask.data = mask.data.astype(int)
    source2.add_image(mask, 'MYMASK')

    filename = str(tmpdir.join('source.fits'))
    source2.write(filename)
    src = Source.from_file(filename)
    assert src.images['MYMASK'].data.dtype == '>i8'
    assert_masked_allclose(mask.data, src.images['MYMASK'].data)

    with fits.open(filename) as hdul:
        'IMA_MYMASK_DQ' in hdul
        assert (np.count_nonzero(hdul['IMA_MYMASK_DQ'].data) ==
                np.count_nonzero(white.mask))
예제 #6
0
파일: test_cube.py 프로젝트: musevlt/mpdaf
def test_bandpass_image():
    """Cube class: testing bandpass_image"""

    shape = (7, 2, 2)

    # Create a rectangular shaped bandpass response whose ends are half
    # way into pixels.

    wavelengths = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
    sensitivities = np.array([1.0, 1.0, 1.0, 1.0, 1.0])

    # Specify a ramp for the values of the pixels in the cube versus
    # wavelength.

    spectral_values = np.arange(shape[0], dtype=float)

    # Specify a ramp for the variances of the pixels in the cube
    # versus wavelength.

    spectral_vars = np.arange(shape[0], dtype=float) * 0.5

    # Calculate the expected weights versus wavelength for each
    # spectral pixels. The weight of each pixel is supposed to be
    # integral of the sensitivity function over the width of the pixel.
    #
    # | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  Pixel indexes
    #          _______________________
    #  _______|                       |_________  Sensitivities
    #
    #   0.0  0.5   1.0   1.0   1.0   0.5   0.0    Weights
    #   0.0  1.0   2.0   3.0   4.0   5.0   6.0    Pixel values vs wavelength
    #   0.0  0.5   2.0   3.0   4.0   2.5   0.0    Pixel values * weights

    weights = np.array([0.0, 0.5, 1.0, 1.0, 1.0, 0.5, 0.0])

    # Compute the expected weighted mean of the spectral pixel values,
    # assuming that no pixels are unmasked.

    unmasked_mean = (weights * spectral_values).sum() / weights.sum()

    # Compute the expected weighted mean if pixel 1 is masked.

    masked_pixel = 1
    masked_mean = (((weights * spectral_values).sum() -
                    weights[masked_pixel] * spectral_values[masked_pixel]) /
                   (weights.sum() - weights[masked_pixel]))

    # Compute the expected variances of the unmasked and masked means.

    unmasked_var = (weights**2 * spectral_vars).sum() / weights.sum()**2
    masked_var = (((weights**2 * spectral_vars).sum() -
                   weights[masked_pixel]**2 * spectral_vars[masked_pixel]) /
                  (weights.sum() - weights[masked_pixel])**2)

    # Create the data array of the cube, giving all map pixels the
    # same data and variance spectrums.

    data = spectral_values[:, np.newaxis, np.newaxis] * np.ones(shape)
    var = spectral_vars[:, np.newaxis, np.newaxis] * np.ones(shape)

    # Create a mask with all pixels unmasked.

    mask = np.zeros(shape)

    # Mask spectral pixel 'masked_pixel' of map index 1,1.

    mask[masked_pixel, 1, 1] = True

    # Also mask all pixels of map pixel 0,0.

    mask[:, 0, 0] = True

    # Create a test cube with the above data and mask arrays.

    c = generate_cube(shape=shape, data=data, mask=mask, var=var,
                      wave=WaveCoord(crval=0.0, cdelt=1.0, crpix=1.0,
                                     cunit=u.angstrom))

    # Extract an image that has the above bandpass response.

    im = c.bandpass_image(wavelengths, sensitivities)

    # Only the map pixel in which all spectral pixels are masked should
    # be masked in the output, so just map pixel [0,0] should be masked.

    expected_mask = np.array([[True, False],
                              [False, False]], dtype=bool)

    # What do we expect?

    expected_data = ma.array(
        data=[[unmasked_mean, unmasked_mean], [unmasked_mean, masked_mean]],
        mask=expected_mask)

    expected_var = ma.array(
        data=[[unmasked_var, unmasked_var], [unmasked_var, masked_var]],
        mask=expected_mask)

    # Are the results consistent with the predicted values?

    assert_masked_allclose(im.data, expected_data)
    assert_masked_allclose(im.var, expected_var)
예제 #7
0
파일: test_cube.py 프로젝트: musevlt/mpdaf
def test_rebin():
    """Cube class: testing rebin methods"""

    # Create spectral and spatial world coordinates that make each
    # pixel equal its index.

    wcs = WCS(crval=(0, 0), crpix=(1, 1), cdelt=(1.0, 1.0))
    wave = WaveCoord(crval=0.0, crpix=1.0, cdelt=1.0)

    # Create a cube with even valued dimensions, filled with ones.
    data = ma.ones((4, 6, 8))       # Start with all pixels 1.0
    data.reshape(4 * 6 * 8)[::2] = 0.0   # Set every second pixel to 0.0
    data.mask = data < -1            # Unmask all pixels.
    cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave)

    # Rebin each of the axes such as to leave only 2 pixels along each
    # dimension.
    factor = (2, 3, 4)
    cube2 = cube1.rebin(factor=factor)

    # Compute the expected output cube, given that the input cube is a
    # repeating pattern of 1,0, and we divided the x-axis by a
    # multiple of 2, the output pixels should all be 0.5.
    expected = ma.ones((2, 2, 2)) * 0.5
    expected.mask = expected < 0  # All pixels unmasked.
    assert_masked_allclose(cube2.data, expected)

    # Do the same experiment but with the zero valued pixels all masked.
    data = ma.ones((4, 6, 8))       # Start with all pixels 1.0
    data.reshape(4 * 6 * 8)[::2] = 0.0   # Set every second pixel to 0.0
    data.mask = data < 0.1           # Mask the pixels that are 0.0
    cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave)

    # Rebin each of the axes such as to leave only 2 pixels along each
    # dimension.
    factor = np.array([2, 3, 4])
    cube2 = cube1.rebin(factor=factor)

    # Compute the expected output cube. The zero valued pixels are all
    # masked, leaving just pixels with values of 1, so the mean that is
    # recorded in each output pixel should be 1.0.
    expected = ma.ones((2, 2, 2)) * 1.0
    expected.mask = expected < 0  # All output pixels should be unmasked.
    assert_masked_allclose(cube2.data, expected)

    # Check that the world coordinates are correct.  We averaged
    # factor[] pixels whose coordinates were equal to their pixel
    # indexes, so the coordinates of the first pixel of the rebinned
    # cube should be the mean of the first factor indexes along each
    # dimension. The sum from k=0 to factor-1 is
    # ((factor-1)*factor)/2, and dividing this by the number of pixels
    # gives (factor-1)/2.
    assert_allclose(np.asarray(cube2.get_start()), (factor - 1) / 2.0)

    # Create a cube that has a larger number of pixels along the
    # y and x axes of the images, so that we can divide those axes
    # by a number whose remainder is large enough to test selection
    # of the truncated part of the cube.
    shape = np.array([4, 17, 15])
    data = ma.ones(shape)                # Start with all pixels 1.0
    data.reshape(shape.prod())[::2] = 0.0   # Set every second pixel to 0.0
    data.mask = data < -1                   # Unmask all pixels.
    cube1 = generate_cube(data=data.data, mask=data.mask, wcs=wcs, wave=wave)

    # Choose the rebinning factors such that there is a significant
    # remainder after dividing the final two dimensions of the cube by
    # the specified factor. We don't do this for the first axis because
    # we want the interleaved pattern of 0s and 1s to remain.
    factor = np.array([2, 7, 9])
    cube2 = cube1.rebin(factor=factor, margin='origin')

    # Compute the expected output cube. Given that the input cube is a
    # repeating pattern of 1,0, and we divided the x-axis by a
    # multiple of 2, the output pixels should all be 0.5.
    expected_shape = cube1.shape // factor
    expected = ma.ones(expected_shape) * 0.5
    expected.mask = expected < 0  # All pixels unmasked.
    assert_masked_allclose(cube2.data, expected)

    # We chose a margin value of 'origin', so that the outer corner of
    # pixel 0,0,0 of the input cube would also be the outer corner of
    # pixel 0,0,0 of the rebinned cube. The output world coordinates
    # can be calculated as described for the previous test.
    assert_allclose(np.asarray(cube2.get_start()), (factor - 1) / 2.0)

    # Do the same test, but with margin='center'.
    cube2 = cube1.rebin(factor=factor, margin='center')

    # Compute the expected output cube. The values should be the
    # same as the previous test.
    expected_shape = cube1.shape // factor
    expected = ma.ones(expected_shape) * 0.5
    expected.mask = expected < 0  # All pixels unmasked.
    assert_masked_allclose(cube2.data, expected)

    # We chose a margin value of 'center'. We need to know which
    # pixels should have contributed to pixel 0,0,0. First calculate
    # how many pixels remain after dividing the shape by the reduction
    # factors. This is the number of extra pixels that should have been
    # discarded. Divide this by 2 to determine the number of pixels that
    # are removed from the start of each axis.
    cut = np.mod(shape, factor).astype(int) // 2

    # The world coordinates of the input cube were equal to its pixel
    # indexes, and the world coordinates of a pixel of the output cube
    # is thus the mean of the indexes of the pixels that were combined
    # to make that pixel. In this case, we combine pixels
    # data[cut:cut+factor] along each axis. This can be calculated as
    # the sum of pixel indexes from 0 to cut+factor, minus the sum of
    # pixel indexes from 0 to cut, with the result divided by the number
    # of pixels that were averaged. Again we make use of the series sum,
    # sum[n=0..N] = (n*(n-1))/2.
    tmp = cut + factor
    assert_allclose(np.asarray(cube2.get_start()),
                    ((tmp * (tmp - 1)) / 2.0 -
                     (cut * (cut - 1)) / 2.0) / factor)