예제 #1
0
def test_resizing_op_call(odl_tspace_impl):

    impl = odl_tspace_impl
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_numeric_dtype(dt)
    ]

    for dtype in dtypes:
        # Minimal test since this operator only wraps resize_array
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=impl)
        res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2), impl=impl)
        res_op = odl.ResizingOperator(space, res_space)
        out = res_op(space.one())
        true_res = np.zeros((8, 2))
        true_res[:4, :] = 1
        assert np.array_equal(out, true_res)

        out = res_space.element()
        res_op(space.one(), out=out)
        assert np.array_equal(out, true_res)

        # Test also mapping to default impl for other 'impl'
        if impl != 'numpy':
            space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=impl)
            res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2))
            res_op = odl.ResizingOperator(space, res_space)
            out = res_op(space.one())
            true_res = np.zeros((8, 2))
            true_res[:4, :] = 1
            assert np.array_equal(out, true_res)

            out = res_space.element()
            res_op(space.one(), out=out)
            assert np.array_equal(out, true_res)
예제 #2
0
def test_resizing_op_adjoint(padding, odl_tspace_impl):

    impl = odl_tspace_impl
    pad_mode, pad_const = padding
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_real_floating_dtype(dt)
    ]

    for dtype in dtypes:
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5),
                                  dtype=dtype,
                                  impl=impl)
        res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7),
                                      dtype=dtype,
                                      impl=impl)
        res_op = odl.ResizingOperator(space,
                                      res_space,
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)

        if pad_const != 0.0:
            with pytest.raises(NotImplementedError):
                res_op.adjoint
            return

        elem = noise_element(space)
        res_elem = noise_element(res_space)
        inner1 = res_op(elem).inner(res_elem)
        inner2 = elem.inner(res_op.adjoint(res_elem))
        assert almost_equal(inner1, inner2, places=dtype_places(dtype))
def tensor_space(shape, dtype=None, impl='numpy', **kwargs):
    """Return a tensor space with arbitrary scalar data type.

    Parameters
    ----------
    shape : positive int or sequence of positive ints
        Number of entries per axis for elements in this space. A
        single integer results in a space with 1 axis.
    dtype : optional
        Data type of each element. Can be provided in any way the
        `numpy.dtype` function understands, e.g. as built-in type or
        as a string.
        For ``None``, the `TensorSpace.default_dtype` of the
        created space is used.
    impl : str, optional
        Impmlementation back-end for the space. See
        `odl.space.entry_points.tensor_space_impl_names` for available
        options.
    kwargs :
        Extra keyword arguments passed to the space constructor.

    Returns
    -------
    space : `TensorSpace`

    Examples
    --------
    Space of 3-tuples with ``uint64`` entries (although not strictly a
    vector space):

    >>> odl.tensor_space(3, dtype='uint64')
    tensor_space(3, dtype='uint64')

    2x3 tensors with same data type:

    >>> odl.tensor_space((2, 3), dtype='uint64')
    tensor_space((2, 3), dtype='uint64')

    The default data type depends on the implementation. For
    ``impl='numpy'``, it is ``'float64'``:

    >>> ts = odl.tensor_space((2, 3))
    >>> ts
    rn((2, 3))
    >>> ts.dtype
    dtype('float64')

    See Also
    --------
    rn, cn : Constructors for real and complex spaces
    """
    tspace_cls = tensor_space_impl(impl)

    if dtype is None:
        dtype = tspace_cls.default_dtype()

    # Use args by keyword since the constructor may take other arguments
    # by position
    return tspace_cls(shape=shape, dtype=dtype, **kwargs)
예제 #4
0
def space(request, ndim, dtype, odl_tspace_impl):
    """Provide a space for unit tests."""
    impl = odl_tspace_impl
    supported_dtypes = tensor_space_impl(impl).available_dtypes()
    if np.dtype(dtype) not in supported_dtypes:
        pytest.skip('dtype not available for this backend')

    return odl.uniform_discr([-1] * ndim, [1] * ndim, [20] * ndim,
                             impl=impl,
                             dtype=dtype)
예제 #5
0
def space(request, ndim, interp, dtype, odl_tspace_impl):
    """Example space.

    Generates example spaces with various implementations, dimensions, dtypes
    and interpolations.
    """
    impl = odl_tspace_impl
    supported_dtypes = tensor_space_impl(impl).available_dtypes()
    if np.dtype(dtype) not in supported_dtypes:
        pytest.skip('dtype not available for this backend')

    return odl.uniform_discr([-1] * ndim, [1] * ndim, [20] * ndim,
                             interp=interp, impl=impl, dtype=dtype)
예제 #6
0
def tspace_type(space, impl, dtype=None):
    """Select the correct corresponding tensor space.

    Parameters
    ----------
    space : `LinearSpace`
        Template space from which to infer an adequate tensor space. If
        it has a `LinearSpace.field` attribute, ``dtype`` must be
        consistent with it.
    impl : string
        Implementation backend for the tensor space.
    dtype : optional
        Data type which the space is supposed to use. If ``None`` is
        given, the space type is purely determined from ``space`` and
        ``impl``. Otherwise, it must be compatible with the
        field of ``space``.

    Returns
    -------
    stype : type
        Space type selected after the space's field, the backend and
        the data type.
    """
    field_type = type(getattr(space, 'field', None))

    if dtype is None:
        pass
    elif is_real_floating_dtype(dtype):
        if field_type is None or field_type == ComplexNumbers:
            raise TypeError('real floating data type {!r} requires space '
                            'field to be of type RealNumbers, got {}'
                            ''.format(dtype, field_type))
    elif is_complex_floating_dtype(dtype):
        if field_type is None or field_type == RealNumbers:
            raise TypeError('complex floating data type {!r} requires space '
                            'field to be of type ComplexNumbers, got {!r}'
                            ''.format(dtype, field_type))
    elif is_numeric_dtype(dtype):
        if field_type == ComplexNumbers:
            raise TypeError('non-floating data type {!r} requires space field '
                            'to be of type RealNumbers, got {!r}'.format(
                                dtype, field_type))

    try:
        return tensor_space_impl(impl)
    except ValueError:
        raise NotImplementedError('no corresponding tensor space available '
                                  'for space {!r} and implementation {!r}'
                                  ''.format(space, impl))
예제 #7
0
def test_resizing_op_properties(odl_tspace_impl, padding):

    impl = odl_tspace_impl
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_numeric_dtype(dt)
    ]

    pad_mode, pad_const = padding

    for dtype in dtypes:
        # Explicit range
        space = odl.uniform_discr([0, -1], [1, 1], (10, 5), dtype=dtype)
        res_space = odl.uniform_discr([0, -3], [2, 3], (20, 15), dtype=dtype)
        res_op = odl.ResizingOperator(space,
                                      res_space,
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)

        assert res_op.domain == space
        assert res_op.range == res_space
        assert res_op.offset == (0, 5)
        assert res_op.pad_mode == pad_mode
        assert res_op.pad_const == pad_const
        if pad_mode == 'constant' and pad_const != 0:
            assert not res_op.is_linear
        else:
            assert res_op.is_linear

        # Implicit range via ran_shp and offset
        res_op = odl.ResizingOperator(space,
                                      ran_shp=(20, 15),
                                      offset=[0, 5],
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)
        assert np.allclose(res_op.range.min_pt, res_space.min_pt)
        assert np.allclose(res_op.range.max_pt, res_space.max_pt)
        assert np.allclose(res_op.range.cell_sides, res_space.cell_sides)
        assert res_op.range.dtype == res_space.dtype
        assert res_op.offset == (0, 5)
        assert res_op.pad_mode == pad_mode
        assert res_op.pad_const == pad_const
        if pad_mode == 'constant' and pad_const != 0:
            assert not res_op.is_linear
        else:
            assert res_op.is_linear
예제 #8
0
def test_resizing_op_inverse(padding, odl_tspace_impl):

    impl = odl_tspace_impl
    pad_mode, pad_const = padding
    dtypes = [dt for dt in tensor_space_impl(impl).available_dtypes()
              if is_numeric_dtype(dt)]

    for dtype in dtypes:
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5), dtype=dtype,
                                  impl=impl)
        res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7),
                                      dtype=dtype, impl=impl)
        res_op = odl.ResizingOperator(space, res_space, pad_mode=pad_mode,
                                      pad_const=pad_const)

        # Only left inverse if the operator extends in all axes
        x = noise_element(space)
        assert res_op.inverse(res_op(x)) == x
def rn(shape, dtype=None, impl='numpy', **kwargs):
    """Return a space of real tensors.

    Parameters
    ----------
    shape : positive int or sequence of positive ints
        Number of entries per axis for elements in this space. A
        single integer results in a space with 1 axis.
    dtype : optional
        Data type of each element. Can be provided in any way the
        `numpy.dtype` function understands, e.g. as built-in type or
        as a string. Only real floating-point data types are allowed.
        For ``None``, the `TensorSpace.default_dtype` of the
        created space is used in the form
        ``default_dtype(RealNumbers())``.
    impl : str, optional
        Impmlementation back-end for the space. See
        `odl.space.entry_points.tensor_space_impl_names` for available
        options.
    kwargs :
        Extra keyword arguments passed to the space constructor.

    Returns
    -------
    real_space : `TensorSpace`

    Examples
    --------
    Space of real 3-tuples with ``float32`` entries:

    >>> odl.rn(3, dtype='float32')
    rn(3, dtype='float32')

    Real 2x3 tensors with ``float32`` entries:

    >>> odl.rn((2, 3), dtype='float32')
    rn((2, 3), dtype='float32')

    The default data type depends on the implementation. For
    ``impl='numpy'``, it is ``'float64'``:

    >>> ts = odl.rn((2, 3))
    >>> ts
    rn((2, 3))
    >>> ts.dtype
    dtype('float64')

    See Also
    --------
    tensor_space : Space of tensors with arbitrary scalar data type.
    cn : Complex tensor space.
    """
    rn_cls = tensor_space_impl(impl)

    if dtype is None:
        dtype = rn_cls.default_dtype(RealNumbers())

    # Use args by keyword since the constructor may take other arguments
    # by position
    rn = rn_cls(shape=shape, dtype=dtype, **kwargs)
    if not rn.is_real:
        raise ValueError('data type {!r} not a real floating-point type.'
                         ''.format(dtype))
    return rn