Exemple #1
0
class LineSearch(with_metaclass(ABCMeta, object)):

    """Abstract base class for line search step length methods."""

    @abstractmethod
    def __call__(self, x, direction, dir_derivative):
        """Calculate step length in direction.
Exemple #2
0
class StepLength(with_metaclass(ABCMeta, object)):

    """Abstract base class for step length methods."""

    # TODO: change signature so it reflects the requirements for e.g.
    # Barzilai-Borwein
    @abstractmethod
    def __call__(self, x, direction, dir_derivative):
        """Calculate the step length at a point.
Exemple #3
0
class Geometry(with_metaclass(ABCMeta, object)):

    """Abstract geometry class.

    A geometry is described by

    * a detector,
    * a set of detector motion parameters,
    * a function mapping motion parameters to the location of a
      reference point (e.g. the center of the detector surface),
    * a rotation applied to the detector surface, depending on the motion
      parameters,
    * a mapping from the motion and surface parameters to the detector pixel
      direction to the source,
    * optionally a mapping from the motion parameters to the source position
    """

    def __init__(self, ndim, motion_part, detector):
        """Initialize a new instance.

        Parameters
        ----------
        ndim : positive int
            Number of dimensions of this geometry, i.e. dimensionality
            of the physical space in which this geometry is embedded
        motion_part : `RectPartition`
           Partition for the set of "motion" parameters
        detector : `Detector`
           The detector of this geometry
        """
        if int(ndim) <= 0:
            raise ValueError('number of dimensions {} is not positive'
                             ''.format(ndim))
        if not isinstance(motion_part, RectPartition):
            raise TypeError('`motion_part` {!r} not a RectPartition instance'
                            ''.format(motion_part))

        if not isinstance(detector, Detector):
            raise TypeError('`detector` {!r} not a Detector instance'
                            ''.format(detector))

        self._ndim = int(ndim)
        self._motion_part = motion_part
        self._detector = detector
        self._implementation_cache = {}

    @property
    def ndim(self):
        """Number of dimensions of the geometry."""
        return self._ndim

    @property
    def motion_partition(self):
        """Partition of the motion parameter set into subsets."""
        return self._motion_part

    @property
    def motion_params(self):
        """Continuous motion parameter range, an `IntervalProd`."""
        return self.motion_partition.set

    @property
    def motion_grid(self):
        """Sampling grid of `motion_params`."""
        return self.motion_partition.grid

    @property
    def detector(self):
        """Detector representation of this geometry."""
        return self._detector

    @property
    def det_partition(self):
        """Partition of the detector parameter set into subsets."""
        return self.detector.partition

    @property
    def det_params(self):
        """Continuous detector parameter range, an `IntervalProd`."""
        return self.detector.params

    @property
    def det_grid(self):
        """Sampling grid of `det_params`."""
        return self.detector.grid

    @property
    def partition(self):
        """Joined parameter set partition for motion and detector.

        Returns a `RectPartition` with the detector partition inserted
        after the motion partition.
        """
        # TODO: change when RectPartition.append is implemented
        return self.det_partition.insert(0, self.motion_partition)

    @property
    def params(self):
        """Joined parameter set for motion and detector.

        By convention, the motion parameters come before the detector
        parameters.
        """
        return self.partition.set

    @property
    def grid(self):
        """Joined sampling grid for motion and detector.

        By convention, the motion grid comes before the detector grid.
        """
        return self.partition.grid

    @abstractmethod
    def det_refpoint(self, mpar):
        """Detector reference point function.

        Parameters
        ----------
        mpar : `motion_params` element
            Motion parameter for which to calculate the detector
            reference point

        Returns
        -------
        point : `numpy.ndarray`, shape (`ndim`,)
            The reference point, an `ndim`-dimensional vector
        """

    @abstractmethod
    def rotation_matrix(self, mpar):
        """Detector rotation function for calculating the detector
        reference position.

        Parameters
        ----------
        mpar : `motion_params` element
            Motion parameter for which to calculate the detector
            reference rotation

        Returns
        -------
        rot : `numpy.ndarray`, shape (`ndim`, `ndim`)
            The rotation matrix mapping the standard basis vectors in
            the fixed ("lab") coordinate system to the basis vectors of
            the local coordinate system of the detector reference point,
            expressed in the fixed system.
        """

    def det_to_src(self, mpar, dpar, normalized=True):
        """Vector pointing from a detector location to the source.

        A function of the motion and detector parameters.

        Parameters
        ----------
        mpar : `motion_params` element
            Motion parameter at which to evaluate
        dpar : `det_params` element
            Detector parameter at which to evaluate
        normalized : bool, optional
            If ``True``, return a normalized (unit) vector.

        Returns
        -------
        vec : `numpy.ndarray`, shape (`ndim`,)
            (Unit) vector pointing from the detector to the source
        """
        raise NotImplementedError('abstract method')

    def det_point_position(self, mpar, dpar):
        """Detector point position function.

        Parameters
        ----------
        mpar : `motion_params` element
            Motion parameter at which to evaluate
        dpar : `det_params` element
            Detector parameter at which to evaluate

        Returns
        -------
        pos : `numpy.ndarray` (shape (`ndim`,))
            Source position, an `ndim`-dimensional vector
        """
        # TODO: check and write test
        return np.asarray(
            (self.det_refpoint(mpar) +
             self.rotation_matrix(mpar).dot(self.detector.surface(dpar))))

    @property
    def implementation_cache(self):
        """Dictionary acting as a cache for this geometry.

        Intended for reuse of computations. Implementations that use this
        storage should take care of unique naming.

        Returns
        -------
        implementations : dict
        """
        return self._implementation_cache
Exemple #4
0
class Detector(with_metaclass(ABCMeta, object)):
    """Abstract detector class.

    A detector is described by

    * a set of parameters for surface parametrization (including sampling),
    * a function mapping a surface parameter to the location of a detector
      point relative to its reference point,
    * optionally a surface measure function.
    """
    def __init__(self, part):
        """Initialize a new instance.

        Parameters
        ----------
        part : `RectPartition`
           Partition of the detector parameter set (pixelization).
           It determines dimension, parameter range and discretization.
        """
        if not isinstance(part, RectPartition):
            raise TypeError('`part` {!r} is not a RectPartition instance'
                            ''.format(part))

        self._part = part

    @abstractmethod
    def surface(self, param):
        """Parametrization of the detector reference surface.

        Parameters
        ----------
        param : `params` element
            Parameter value where to evaluate the function

        Returns
        -------
        point :
            Spatial location of the detector point corresponding to
            ``param``
        """

    @property
    def partition(self):
        """Partition of the detector parameter set into subsets."""
        return self._part

    @property
    def ndim(self):
        """Number of dimensions of this detector (0, 1 or 2)."""
        return self.partition.ndim

    @property
    def params(self):
        """Surface parameter set of this detector."""
        return self.partition.set

    @property
    def grid(self):
        """Sampling grid of the parameters."""
        return self.partition.grid

    @property
    def shape(self):
        """Number of subsets (pixels) of the detector per axis."""
        return self.partition.shape

    @property
    def size(self):
        """Total number of pixels."""
        return self.partition.size

    def surface_deriv(self, param):
        """Partial derivative(s) of the surface parametrization.

        Parameters
        ----------
        param : `params` element
            The parameter value where to evaluate the function

        Returns
        -------
        deriv :
            Vector (``ndim=1``) or sequence of vectors corresponding
            to the partial derivatives at ``param``
        """
        raise NotImplementedError('abstract method')

    def surface_measure(self, param):
        """Density function of the surface measure.

        This is the default implementation relying on the `surface_deriv`
        method. For ``ndim == 1``, the density is given by the `Arc
        length`_, for ``ndim == 2``, it is the length of the cross product
        of the partial derivatives of the parametrization, see Wikipedia's
        `Surface area`_ article.

        Parameters
        ----------
        param : `params` element
            The parameter value where to evaluate the function

        Returns
        -------
        measure : float
            The density value at the given parameter

        .. _Arc length:
            https://en.wikipedia.org/wiki/Curve#Lengths_of_curves
        .. _Surface area:
            https://en.wikipedia.org/wiki/Surface_area
        """
        if param not in self.params:
            raise ValueError('`param` {} not in the valid range {}'
                             ''.format(param, self.params))
        if self.ndim == 1:
            return float(np.linalg.norm(self.surface_deriv(param)))
        elif self.ndim == 2:
            return float(np.linalg.norm(np.cross(*self.surface_deriv(param))))
        else:
            raise NotImplementedError('abstract method')
Exemple #5
0
class NtuplesBaseVector(with_metaclass(ABCMeta, object)):
    """Abstract class for representation of `NtuplesBase` elements.

    Defines abstract attributes and concrete ones which are
    independent of data representation.
    """
    def __init__(self, space, *args, **kwargs):
        """Initialize a new instance."""
        self._space = space

    @abstractmethod
    def copy(self):
        """Create an identical (deep) copy of this vector."""

    @abstractmethod
    def asarray(self, start=None, stop=None, step=None, out=None):
        """Extract the data of this array as a numpy array.

        Parameters
        ----------
        start : `int`, optional
            Start position. `None` means the first element.
        start : `int`, optional
            One element past the last element to be extracted.
            `None` means the last element.
        start : `int`, optional
            Step length. `None` means 1.
        out : `numpy.ndarray`
            Array to write result to.

        Returns
        -------
        asarray : `numpy.ndarray`
            Numpy array of the same type as the space.
        """

    @abstractmethod
    def __getitem__(self, indices):
        """Access values of this vector.

        Parameters
        ----------
        indices : `int` or `slice`
            The position(s) that should be accessed

        Returns
        -------
        values : `NtuplesBase.dtype` or `NtuplesBaseVector`
            The value(s) at the index (indices)
        """

    @abstractmethod
    def __setitem__(self, indices, values):
        """Set values of this vector.

        Parameters
        ----------
        indices : `int` or `slice`
            The position(s) that should be set
        values : scalar, `array-like` or `NtuplesBaseVector`
            The value(s) that are to be assigned.

            If ``index`` is an integer, ``value`` must be single value.

            If ``index`` is a slice, ``value`` must be broadcastable
            to the size of the slice (same size, shape (1,)
            or single value).
        """

    @abstractmethod
    def __eq__(self, other):
        """Return ``self == other``.

        Returns
        -------
        equals : `bool`
            `True` if all entries of ``other`` are equal to this
            vector's entries, `False` otherwise.
        """

    @property
    def space(self):
        """Space to which this vector."""
        return self._space

    @property
    def ndim(self):
        """Number of dimensions, always 1."""
        return 1

    @property
    def dtype(self):
        """Length of this vector, equal to space size."""
        return self.space.dtype

    @property
    def size(self):
        """Length of this vector, equal to space size."""
        return self.space.size

    def __len__(self):
        """Return ``len(self)``.

        Return the number of space dimensions.
        """
        return self.space.size

    @property
    def shape(self):
        """Number of entries per axis, equals (size,) for linear storage."""
        return self.space.shape

    @property
    def itemsize(self):
        """The size in bytes on one element of this type."""
        return self.dtype.itemsize

    @property
    def nbytes(self):
        """The number of bytes this vector uses in memory."""
        return self.size * self.itemsize

    def __array__(self, dtype=None):
        """Return a numpy array of this ntuple.

        Parameters
        ----------
        dtype : `object`
            Specifier for the data type of the output array

        Returns
        -------
        array : `numpy.ndarray`
        """
        if dtype is None:
            return self.asarray()
        else:
            return self.asarray().astype(dtype, copy=False)

    def __array_wrap__(self, obj):
        """Return a new vector from the data in obj.

        Parameters
        ----------
        obj : `numpy.ndarray`
            The array that should be wrapped

        Returns
        -------
            vector : `NtuplesBaseVector`
        """
        if obj.ndim == 0:
            return self.space.field.element(obj)
        else:
            return self.space.element(obj)

    def __ne__(self, other):
        """Return ``self != other``."""
        return not self.__eq__(other)

    def __str__(self):
        """Return ``str(self)``."""
        return array1d_str(self)

    def __repr__(self):
        """Return ``repr(self)``."""
        return '{!r}.element({})'.format(self.space, array1d_repr(self))

    @property
    def ufunc(self):
        """`NtuplesBaseUFuncs`, access to numpy style ufuncs.

        These are always available, but may or may not be optimized for
        the specific space in use.
        """
        return NtuplesBaseUFuncs(self)

    def show(self,
             title=None,
             method='scatter',
             show=False,
             fig=None,
             **kwargs):
        """Display the function graphically.

        Parameters
        ----------
        title : `str`, optional
            Set the title of the figure

        method : `str`, optional
            1d methods:

            'plot' : graph plot

            'scatter' : point plot

        show : `bool`, optional
            If the plot should be showed now or deferred until later.

        fig : `matplotlib.figure.Figure`
            The figure to show in. Expected to be of same "style", as
            the figure given by this function. The most common use case
            is that ``fig`` is the return value from an earlier call to
            this function.

        kwargs : {'figsize', 'saveto', ...}
            Extra keyword arguments passed on to display method
            See the Matplotlib functions for documentation of extra
            options.

        Returns
        -------
        fig : `matplotlib.figure.Figure`
            The resulting figure. It is also shown to the user.

        See Also
        --------
        odl.util.graphics.show_discrete_data : Underlying implementation
        """
        from odl.util.graphics import show_discrete_data
        from odl.discr import RegularGrid
        grid = RegularGrid(0, self.size - 1, self.size)
        return show_discrete_data(self.asarray(),
                                  grid,
                                  title=title,
                                  method=method,
                                  show=show,
                                  fig=fig,
                                  **kwargs)
Exemple #6
0
class Set(with_metaclass(ABCMeta, object)):
    """An abstract set.

    **Abstract Methods**

    Each subclass of `Set` must implement two methods: one to
    check if an object is contained in the set and one to test if two
    sets are equal.

    **Membership test:** ``__contains__(self, other)``

    Test if ``other`` is a member of this set. This function provides
    the operator overload for `in`.

    **Parameters:**
        other : `object`
            The object to be tested for membership

    **Returns:**
        contains : `bool`
            `True` if ``other`` is a member of this set, `False`
            otherwise.


    **Equality test:** ``__eq__(self, other)``

    Test if ``other`` is the same set as this set, i.e. both sets are
    of the same type and contain the same elements. This function
    provides the operator overload for ``==``.

    **Parameters:**
        other : `object`
            The object to be tested for equality.

    **Returns:**
        equals : `bool`
            `True` if both sets are of the same type and contain the
            same elements, `False` otherwise.

    A default implementation of the operator overload for ``!=`` via
    ``__ne__(self, other)`` is provided as ``not self.__eq__(other)``.

    **Element creation (optional)**: ``element(self, inp=None)``

    Create an element of this set, either from scratch or from an
    input parameter.

    **Parameters:**
        inp : `object`, optional
            The object from which to create the new element

    **Returns:**
        element : member of this set
            If ``inp`` is `None`, return an arbitrary element.
            Otherwise, return the element created from ``inp``.
    """
    @abstractmethod
    def __contains__(self, other):
        """Return ``other in self``."""

    def contains_set(self, other):
        """Test if ``other`` is a subset of this set.

        Implementing this method is optional. Default it tests for equality.
        """
        return self == other

    def contains_all(self, other):
        """Test if all points in ``other`` are contained in this set.

        This is a default implementation and should be overridden by
        subclasses.
        """
        return all(x in self for x in other)

    @abstractmethod
    def __eq__(self, other):
        """Return ``self == other``."""

    def __ne__(self, other):
        """Return ``self != other``."""
        return not self.__eq__(other)

    def element(self, inp=None):
        """Return an element from ``inp`` or from scratch.

        Implementing this method is optional.
        """
        raise NotImplementedError('`element` method not implemented')

    @property
    def examples(self):
        """Return a `generator` with elements in the set as name-value pairs.

        Can return a finite set of examples or an infinite set.

        Optional to implement, intended to be used for diagnostics.
        By default, the generator yields ``('element()', self.element())``.
        """
        yield ('element()', self.element())
Exemple #7
0
class Set(with_metaclass(ABCMeta, object)):
    """An abstract set.

    **Abstract Methods**

    Each subclass of `Set` must implement two methods: one to
    check if an object is contained in the set and one to test if two
    sets are equal.

    **Membership test:** ``__contains__(self, other)``

    Test if ``other`` is a member of this set. This function provides
    the operator overload for ``in``.

    **Parameters:**
        other :
            Object to be tested for membership

    **Returns:**
        contains : bool
            ``True`` if ``other`` is a member of this set, ``False``
            otherwise.


    **Equality test:** ``__eq__(self, other)``

    Test if ``other`` is the same set as this set, i.e. both sets are
    of the same type and contain the same elements. This function
    provides the operator overload for ``==``.

    **Parameters:**
        other :
            Object to be tested for equality.

    **Returns:**
        equals : bool
            ``True`` if both sets are of the same type and contain the
            same elements, ``False`` otherwise.

    A default implementation of the operator overload for ``!=`` via
    ``__ne__(self, other)`` is provided as ``not self.__eq__(other)``.

    **Element creation (optional)**: ``element(self, inp=None)``

    Create an element of this set, either from scratch or from an
    input parameter.

    **Parameters:**
        inp : optional
            Object from which to create the new element

    **Returns:**
        element : member of this set
            If ``inp`` is None, return an arbitrary element.
            Otherwise, return the element created from ``inp``.
    """
    @abstractmethod
    def __contains__(self, other):
        """Return ``other in self``."""

    def contains_set(self, other):
        """Test if ``other`` is a subset of this set.

        This is a default implementation that simply tests for equality.
        It should be overridden by subclasses.

        Returns
        -------
        set_contained : bool
            ``True`` if ``other`` is contained in this set, ``False``
            otherwise.
        """
        return self == other

    def contains_all(self, other):
        """Test if all elements in ``other`` are contained in this set.

        This is a default implementation that assumes ``other`` to be
        a sequence and tests each elment of ``other`` sequentially.
        This method should be overridden by subclasses.

        Returns
        -------
        all_contained : bool
            ``True`` if all elements of ``other`` are contained in this
            set, ``False`` otherwise
        """
        return all(x in self for x in other)

    @abstractmethod
    def __eq__(self, other):
        """Return ``self == other``."""

    def __ne__(self, other):
        """Return ``self != other``."""
        return not self.__eq__(other)

    def __cmp__(self, other):
        """Comparsion not implemented."""
        # Stops python 2 from allowing comparsion of arbitrary objects
        raise TypeError('unorderable types: {}, {}'
                        ''.format(self.__class__.__name__, type(other)))

    def element(self, inp=None):
        """Return an element from ``inp`` or from scratch.

        This method should be overridden by subclasses.
        """
        raise NotImplementedError('`element` method not implemented')

    @property
    def examples(self):
        """Generator creating name-value pairs of set elements.

        This method is mainly intended for diagnostics and yields elements,
        either a finite number of times or indefinitely.

        This default implementation returns
        ``('element()', self.element())`` and should be overridden by
        subclasses.
        """
        yield ('element()', self.element())

    def __repr__(self):
        """Return ``repr(self)``."""
        return '{}()'.format(self.__class__.__name__)

    def __str__(self):
        """Return ``str(self)``."""
        return '{}'.format(self.__class__.__name__)
Exemple #8
0
class NtuplesBaseVector(with_metaclass(ABCMeta, object)):

    """Abstract class for `NtuplesBase` elements.

    Do not use this class directly -- to create an element of a vector
    space, call the space's `LinearSpace.element` method instead.
    """

    def __init__(self, space, *args, **kwargs):
        """Initialize a new instance."""
        self.__space = space

    @abstractmethod
    def copy(self):
        """Return an identical (deep) copy of this vector."""

    @abstractmethod
    def asarray(self, start=None, stop=None, step=None, out=None):
        """Return the data of this vector as a numpy array.

        Parameters
        ----------
        start : int, optional
            Index of the first vector entry to be included in
            the extracted array. ``None`` is equivalent to 0.
        stop : int, optional
            Index of the first vector entry to be excluded from
            the extracted array. ``None`` is equivalent to `size`.
        step : int, optional
            Vector index step between consecutive array ellements.
            ``None`` is equivalent to 1.
        out : `numpy.ndarray`, optional
            Array to write the result to.

        Returns
        -------
        out : `numpy.ndarray`
            Numpy array of the same `dtype` as this vector. If ``out``
            was given, the returned object is a reference to it.
        """

    @abstractmethod
    def __getitem__(self, indices):
        """Return ``self[indices]``.

        Parameters
        ----------
        indices : int or `slice`
            The position(s) that should be accessed. An integer results
            in a single entry to be returned. For a slice, the output
            is a vector of the same type.

        Returns
        -------
        values : `NtuplesBase.dtype` or `NtuplesBaseVector`
            Extracted entries according to ``indices``.
        """

    @abstractmethod
    def __setitem__(self, indices, values):
        """Implement ``self[indices] = values``.

        Parameters
        ----------
        indices : int or `slice`
            The position(s) that should be assigned to.
        values : scalar, `array-like` or `NtuplesBaseVector`
            The value(s) that are to be assigned.

            If ``index`` is an integer, ``value`` must be a single
            value.

            If ``index`` is a slice, ``value`` must be broadcastable
            to the shape of the slice, i.e. same size, shape ``(1,)``
            or a single value.
        """

    @abstractmethod
    def __eq__(self, other):
        """Return ``self == other``.

        Returns
        -------
        equals : bool
            ``True`` if all entries of ``other`` are equal to this
            vector's entries, False otherwise.
        """

    def __ne__(self, other):
        """Return ``self != other``."""
        return not self.__eq__(other)

    @property
    def space(self):
        """Space to which this vector belongs."""
        return self.__space

    @property
    def ndim(self):
        """Number of dimensions of this vector's space, always 1."""
        return 1

    @property
    def dtype(self):
        """Data type of this vector's space."""
        return self.space.dtype

    @property
    def size(self):
        """Length of this vector, equal to space size."""
        return self.space.size

    def __len__(self):
        """Return ``len(self)``.

        Equal to the number of space dimensions.
        """
        return self.space.size

    @property
    def shape(self):
        """Number of entries per axis, equals ``(size,)``."""
        return self.space.shape

    @property
    def itemsize(self):
        """Size in bytes of one element of this vector."""
        return self.dtype.itemsize

    @property
    def nbytes(self):
        """Number of bytes this vector uses in memory."""
        return self.size * self.itemsize

    def __array__(self, dtype=None):
        """Return a Numpy array containing this vector's data.

        Parameters
        ----------
        dtype :
            Specifier for the data type of the output array.

        Returns
        -------
        array : `numpy.ndarray`
        """
        if dtype is None:
            return self.asarray()
        else:
            return self.asarray().astype(dtype, copy=False)

    def __array_wrap__(self, obj):
        """Return a new vector from the data in ``obj``.

        Parameters
        ----------
        obj : `numpy.ndarray`
            Array that should be wrapped.

        Returns
        -------
        vector : `NtuplesBaseVector`
            Numpy array wrapped back into this vector's element type.
        """
        if obj.ndim == 0:
            return self.space.field.element(obj)
        else:
            return self.space.element(obj)

    def __int__(self):
        """Return ``int(self)``.

        Returns
        -------
        int : int
            Integer representing this vector.

        Raises
        ------
        TypeError : If the vector is of `size` != 1.
        """
        if self.size != 1:
            raise TypeError('only size 1 vectors can be converted to int')
        return int(self[0])

    def __long__(self):
        """Return ``long(self)``.

        The `long` method is only available in Python 2.

        Returns
        -------
        long : `long`
            Integer representing this vector.

        Raises
        ------
        TypeError : If the vector is of `size` != 1.
        """
        if self.size != 1:
            raise TypeError('only size 1 vectors can be converted to long')
        return long(self[0])

    def __float__(self):
        """Return ``float(self)``.

        Returns
        -------
        float : float
            Floating point number representing this vector.

        Raises
        ------
        TypeError : If the vector is of `size` != 1.
        """
        if self.size != 1:
            raise TypeError('only size 1 vectors can be converted to float')
        return float(self[0])

    def __complex__(self):
        """Return ``complex(self)``.

        Returns
        -------
        complex : `complex`
            Complex floating point number representing this vector.

        Raises
        ------
        TypeError : If the vector is of `size` != 1.
        """
        if self.size != 1:
            raise TypeError('only size 1 vectors can be converted to complex')
        return complex(self[0])

    def __str__(self):
        """Return ``str(self)``."""
        return array1d_str(self)

    def __repr__(self):
        """Return ``repr(self)``."""
        return '{!r}.element({})'.format(self.space,
                                         array1d_repr(self))

    @property
    def ufuncs(self):
        """Internal class for access to Numpy style universal functions.

        These default ufuncs are always available, but may or may not be
        optimized for the specific space in use.
        """
        return NtuplesBaseUfuncs(self)

    def show(self, title=None, method='scatter', force_show=False, fig=None,
             **kwargs):
        """Display this vector graphically.

        Parameters
        ----------
        title : string, optional
            Set the title of the figure

        method : string, optional
            The following plotting methods are available:

            'scatter' : point plot

            'plot' : graph plot

        force_show : bool, optional
            Whether the plot should be forced to be shown now or deferred until
            later. Note that some backends always displays the plot, regardless
            of this value.
        fig : `matplotlib.figure.Figure`, optional
            Figure to draw into. Expected to be of same "style" as
            the figure given by this function. The most common use case
            is that ``fig`` is the return value of an earlier call to
            this function.
        kwargs : {'figsize', 'saveto', ...}, optional
            Extra keyword arguments passed on to the display method.
            See the Matplotlib functions for documentation of extra
            options.

        Returns
        -------
        fig : `matplotlib.figure.Figure`
            Resulting figure. If ``fig`` was given, the returned object
            is a reference to it.

        See Also
        --------
        odl.util.graphics.show_discrete_data : Underlying implementation
        """
        from odl.util.graphics import show_discrete_data
        from odl.discr import uniform_grid
        grid = uniform_grid(0, self.size - 1, self.size)
        return show_discrete_data(self.asarray(), grid, title=title,
                                  method=method, force_show=force_show,
                                  fig=fig, **kwargs)

    @property
    def impl(self):
        """Implementation of this vector's space."""
        return self.space.impl