Ejemplo n.º 1
0
    def points(self, vertices):
        vertices = np.ascontiguousarray(vertices)
        # Store this to keep its data from being garbage collected.
        self._vertices = vertices

        if vertices is None:
            self.vtk_polydata.SetPoints(None)
        else:
            points = self.vtk_polydata.GetPoints() or vtk.vtkPoints()
            points.SetData(numpy_to_vtk(vertices))
            points._numpy_reference = vertices
            self.vtk_polydata.SetPoints(points)
Ejemplo n.º 2
0
    def setter(self, colors):

        if colors is not None:

            if colors.ndim == 1:
                colors = colors[:, np.newaxis]

            if colors.ndim != 2:
                raise ValueError("`colors` must be either 1-D or 2-D")
            colors = np.ascontiguousarray(colors)

            if colors.shape[1] == 1:
                # treat colors as scalars to be passed through a colormap
                self.color_mode = vtk.VTK_COLOR_MODE_DEFAULT

            elif colors.shape[1] == 2:
                # treat colors as texture coordinates to be passed through a texturemap
                # currently texture maps haven't been properly implemented. The
                # colors are evaluated immediately here.
                if self.texture_map is None:
                    raise ValueError(
                        "A texture map must be provided in polydata.texture_map to use uv scalars."
                    )
                colors = self.texture_map(colors)
                # self.color_mode = vtk.VTK_COLOR_MODE_MAP_SCALARS
                self.color_mode = vtk.VTK_COLOR_MODE_DIRECT_SCALARS

            elif colors.shape[1] == 3:
                # treat colors as raw RGB values
                self.color_mode = vtk.VTK_COLOR_MODE_DIRECT_SCALARS

            else:
                raise ValueError("{} is an invalid shape.".format(
                    colors.shape))

            self._colors = colors

            colors = numpy_to_vtk(colors)
            colors._numpy_ref = self._colors

        getter_getter(self)().SetScalars(colors)
        setattr(self, "color_source", vpl_name)
Ejemplo n.º 3
0
def vtkimagedata_from_array(arr, image_data=None):
    """Convert a numpy array to a vtkImageData.

    :param arr: Array of colors.
    :type arr: np.ndarray with dtype ``np.uint8``

    :param image_data: An image data to write into, a new one is created if not specified, defaults to ``None``.
    :type image_data: `vtkImageData`_, optional

    :return: A VTK image.
    :rtype: `vtkImageData`_

    Grayscale images are allowed. ``arr.shape`` can be any of ``(m, n)`` or
    ``(m, n, 1)`` for greyscale, ``(m, n, 3)`` for RGB, or ``(m, n, 4)`` for
    RGBA.

    .. seealso:: :meth:`vtkimagedata_to_array` for the reverse.

    .. seealso:: :meth:`as_vtkimagedata` for converting from other types.

    """
    assert arr.dtype == np.uint8

    if image_data is None:
        image_data = vtk.vtkImageData()

    if arr.ndim == 2:
        arr = arr[..., np.newaxis]

    image_data.SetDimensions(arr.shape[1], arr.shape[0], 1)
    image_data.SetNumberOfScalarComponents(arr.shape[2],
                                           image_data.GetInformation())

    pd = image_data.GetPointData()
    new_arr = arr[::-1].reshape((-1, arr.shape[2]))
    pd.SetScalars(numpy_to_vtk(new_arr))
    pd._numpy_reference = new_arr.data

    return image_data
Ejemplo n.º 4
0
def read(path, raw_bytes=None, format=None, convert_to_array=True):
    """Read an image from a file using one of VTK's ``vtkFormatReader`` classes
    where ``Format`` is replaced by JPEG, PNG, BMP or TIFF.

    :param path: Filename or file handle or ``None`` if using the **raw_bytes** argument.
    :type path: str, os.PathLike, io.BytesIO

    :param raw_bytes: Image compressed binary data, defaults to ``None``.
    :type raw_bytes: bytes, optional

    :param format: Image format extension (e.g. jpg), not needed if format can be determined from **path**, defaults to ``None``.
    :type format: str, optional

    :param convert_to_array: If true, convert to numpy, otherwise leave as vtkImageData, defaults to ``True``.
    :type convert_to_array: bool, optional

    :return: Read image.
    :rtype: np.ndarray or `vtkImageData`_

    The file format can be determined automatically from the **path** suffix or the beginning
    of **raw_bytes**. **format** can be any of JPEG, PNG, TIFF, BMP. It is case
    insensitive, tolerant to preceding '.'s e.g. ``format=".jpg"`` and
    understands the aliases JPG \u21d4 JPEG and TIF \u21d4 TIFF.

    The following demonstrates how to use pseudo file objects to avoid temporary
    files when reading an image from the web.

    .. code-block:: python

        import vtkplotlib as vpl

        # Link you're image url here
        url = "https://raw.githubusercontent.com/bwoodsend/vtkplotlib/master/vtkplotlib/data/icons/Right.jpg"

        # You can make the url request with either:
        from urllib import request
        raw_bytes = request.urlopen(url).read()

        # Or if you have the more modern requests library installed:
        # import requests
        # raw_bytes = requests.get(url).content

        # Pass the bytes to :meth:`read` using:
        image = vpl.image_io.read(path=None, raw_bytes=raw_bytes)

        # Visualize using matplotlib.
        from matplotlib import pyplot
        pyplot.imshow(image)
        pyplot.show()


    .. warning::

        Some formats only support reading from disk. See
        ``vtkplotlib.image_io.BUFFERABLE_FORMAT_MODES`` or for which these are.

    .. note::

        BytesIO and raw bytes functionality is new in vtkplotlib >= 1.3.0.
        Older versions are hardcoded to write to disk and therefore **path**
        must be a filename and not a BytesIO or similar pseudo file object.

    .. note::

        There is a bug in VTK==9.0.0


    """
    if isinstance(raw_bytes, bool):
        raise TypeError(
            "The arguments for this method have changed. If you meant to set the `convert_to_array` argument, please treat it as keyword only. i.e ``convert_to_array={}``"
            .format(raw_bytes))

    if (path is None) == (raw_bytes is None):
        raise TypeError(
            "Exactly one of `path` and `raw_bytes` should be specified.")

    if isinstance(path, io.IOBase):
        raw_bytes = path.read()

    format = _normalise_format(path, format, raw_bytes)
    try:
        Reader = getattr(vtk, "vtk{}Reader".format(format))
    except AttributeError:
        return NotImplemented

    reader = Reader()

    with VTKErrorRaiser(reader):

        if nuts_and_bolts.isinstance_PathLike(path):
            with PathHandler(path) as path_handler:
                reader.SetFileName(path_handler.access_path)
                reader.Update()
        else:
            if raw_bytes is not None:
                bytes_arr = np.frombuffer(raw_bytes, dtype=np.uint8)
                vtk_bytes = numpy_to_vtk(bytes_arr)
                vtk_bytes._numpy_ref = bytes_arr
                reader.SetMemoryBuffer(vtk_bytes)
                reader.SetMemoryBufferLength(len(bytes_arr))
                reader.Update()

        im_data = reader.GetOutput()

    if format == "TIFF" and VTK_VERSION_INFO >= (9, 0, 0):
        # There's a bug in VTK 9 that reads TIFFs upside-down.
        im_data = vtkimagedata_to_array(im_data)[::-1]
        return im_data if convert_to_array else vtkimagedata_from_array(im_data)

    if convert_to_array:
        return vtkimagedata_to_array(im_data)

    return im_data
Ejemplo n.º 5
0
def as_vtk_cmap(cmap, cache=True):
    """Colormaps are generally converted implicitly from any valid format to a
    ``vtk.vtkLookupTable`` using this method. `Any valid format` is defined as
    the following:

    #. A string matplotlib colormap name such as ``'RdYlGn'``.
    #. Anything out of the ``matplotlib.cm`` package.
    #. A list of named colors such as ``["red", "white", "blue"]``. See
       :meth:`cmap_from_list` for more details and flexibility.
    #. An ``(n, 3)`` or ``(n, 4)`` numpy array of RGB(A) int or float values.
    #. A callable that takes an array of scalars and returns an array of form **4**.

    Unless specified otherwise using ``cache=False``, named colormaps of form
    **1** are cached in ``vtkplotlib.colors.converted_cmaps``. If you intend to
    modify the vtkLookupTable then it's best not to allow caching.

    .. note::

        VTK doesn't interpolate between colors. i.e if you use form **4** and
        only provide a short list of colors then the resulting heatmap will be
        block colors rather than a smooth gradient.

    .. note::

        Whilst VTK appears to support opacity gradients in the colormaps, it
        doesn't actually use them. If your colormap says opacity should vary
        with scalars then the opacity is averaged for the plot.


    """

    if isinstance(cmap, _future_utils.string_types):
        if cache and cmap in converted_cmaps:
            return converted_cmaps[cmap]
        cmap = cm.get_cmap(cmap)

    if isinstance(cmap, vtk.vtkLookupTable):
        return cmap

    if cache and isinstance(
            cmap, (colors.ListedColormap, colors.LinearSegmentedColormap)):
        name = cmap.name
        if name in converted_cmaps:
            return converted_cmaps[name]
    else:
        name = None

    if isinstance(cmap, colors.ListedColormap):
        cmap = np.array(cmap.colors)

    if callable(cmap):
        cmap = cmap(np.arange(256, dtype=np.uint8))

    if isinstance(cmap, list):
        cmap = cmap_from_list(cmap)

    if not isinstance(cmap, np.ndarray):
        raise TypeError("cmap is of an invalid type {}.".format(type(cmap)))

    if cmap.ndim == 2 and 3 <= cmap.shape[1] <= 4:
        cmap = np.ascontiguousarray(
            (colors.to_rgba_array(cmap) * 255).astype(np.uint8))
        table = vtk.vtkLookupTable()
        table.SetTable(numpy_to_vtk(cmap))
        table._numpy_ref = cmap

        _temp.append(cmap)
        if name is not None:
            converted_cmaps[name] = table
        return table

    else:
        raise ValueError(
            "`cmap` should have shape (n, 3) or (n, 4). Received {}.".format(
                cmap.shape))