Beispiel #1
0
def write_layers(
    path: str,
    layers: List[Layer],
    plugin_name: Optional[str] = None,
    writer: Optional[WriterContribution] = None,
) -> List[str]:
    """
    Write layers to a file using an NPE2 plugin.

    Parameters
    ----------
    path : str
        The path (file, directory, url) to write.
    layer_type : str
        All lower-class name of the layer class to be written.
    plugin_name : str, optional
        Name of the plugin to write data with. If None then all plugins
        corresponding to appropriate hook specification will be looped
        through to find the first one that can write the data.
    command_id : str, optional
        npe2 command identifier that uniquely identifies the command to ivoke
        to save layers. If specified, overrides, the plugin_name.

    Returns
    -------
    list of str
        Empty list when no plugin was found, otherwise a list of file paths,
        if any, that were written.
    """
    layer_data = [layer.as_layer_data_tuple() for layer in layers]

    if writer is None:
        try:
            return npe2.write(
                path=path, layer_data=layer_data, plugin_name=plugin_name
            )
        except ValueError:
            return []

    n = sum(ltc.max() for ltc in writer.layer_type_constraints())
    args = (path, *layer_data[0][:2]) if n <= 1 else (path, layer_data)
    res = writer.exec(args=args)
    if isinstance(
        res, str
    ):  # pragma: no cover # it shouldn't be... bad plugin.
        return [res]
    return res or []
Beispiel #2
0
def write_layer_data_with_plugins(
    path: str,
    layer_data: List[FullLayerData],
    *,
    plugin_name: Optional[str] = 'napari',
) -> List[str]:
    """Write layer data out into a folder one layer at a time.

    Call ``napari_write_<layer>`` for each layer using the ``layer.name``
    variable to modify the path such that the layers are written to unique
    files in the folder.

    If ``plugin_name`` is ``None`` then we just directly call
    ``plugin_manager.hook.napari_write_<layer>()`` which will loop through
    implementations and stop when the first one returns a non-None result. The
    order in which implementations are called can be changed with the
    implementation sorter/disabler.

    If ``plugin_name`` is provided, then we call the
    ``napari_write_<layer_type>`` for that plugin, and if it fails we error.
    By default, we restrict this function to using only napari ``builtins``
    plugins.

    Parameters
    ----------
    path : str
        path to file/directory
    layer_data : list of napari.types.LayerData
        List of layer_data, where layer_data is ``(data, meta, layer_type)``.
    plugin_name : str, optional
        Name of the plugin to use for saving. If None then all plugins
        corresponding to appropriate hook specification will be looped
        through to find the first one that can save the data. By default,
        only builtin napari implementations are used.

    Returns
    -------
    list of str
        A list of any filepaths that were written.
    """
    from tempfile import TemporaryDirectory

    import npe2

    if plugin_name == 'builtins':
        plugin_name = 'napari'

    # remember whether it was there to begin with
    already_existed = os.path.exists(path)
    # Try and make directory based on current path if it doesn't exist
    if not already_existed:
        os.makedirs(path)

    written: List[str] = []  # the files that were actually written
    try:
        # build in a temporary directory and then move afterwards,
        # it makes cleanup easier if an exception is raised inside.
        with TemporaryDirectory(dir=path) as tmp:
            # Loop through data for each layer
            for layer_data_tuple in layer_data:
                _, meta, type_ = layer_data_tuple

                # Create full path using name of layer
                full_path = abspath_or_url(os.path.join(tmp, meta['name']))
                if type_ == 'image':
                    # workaround for https://github.com/napari/npe2/issues/129
                    full_path += '.tif'

                # Write out data using first plugin found for this hook spec
                # or named plugin if provided
                out = npe2.write(
                    path=full_path,
                    layer_data=[layer_data_tuple],  # type: ignore
                    plugin_name=plugin_name,
                )

                written.extend(out)
            for fname in os.listdir(tmp):
                shutil.move(os.path.join(tmp, fname), path)
    except Exception as exc:
        if not already_existed:
            shutil.rmtree(path, ignore_errors=True)
        raise exc
    return written