From 89e5e417307d423221740a092155e3c39b47c8bf Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Thu, 21 Mar 2024 15:09:33 +0100 Subject: [PATCH 1/5] create an optional dependency group for wk-libs examples --- .github/workflows/ci.yml | 2 +- webknossos/README.md | 1 + webknossos/pyproject.toml | 10 +++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98d6e88d0..5cc3b74e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -163,7 +163,7 @@ jobs: - name: Install dependencies run: | pip install -r ../requirements.txt - poetry install --extras all + poetry install --extras all --with examples - name: Check formatting if: ${{ matrix.group == 1 && matrix.python-version == '3.11' }} diff --git a/webknossos/README.md b/webknossos/README.md index 09df0107b..c9efb1497 100644 --- a/webknossos/README.md +++ b/webknossos/README.md @@ -37,6 +37,7 @@ pip install webknossos ## Examples See the [examples folder](examples) or the [the documentation](https://docs.webknossos.org/webknossos-py). +The dependencies for the examples are not installed by default. Use `poetry install --with examples` to install them. ## Contributions & Development Please see the [respective documentation page](https://docs.webknossos.org/webknossos-py/development.html). diff --git a/webknossos/pyproject.toml b/webknossos/pyproject.toml index 6f44b8866..e5070d31c 100644 --- a/webknossos/pyproject.toml +++ b/webknossos/pyproject.toml @@ -46,8 +46,6 @@ psutil = "^5.6.7" python-dateutil = "^2.8.0" python-dotenv = "^0.19.0" rich = "^10.9.0" -scikit-image = "^0.21.0" -scikit-learn = "^1.0.1" scipy = "^1.9.0" typer = {extras = ["all"], version = "^0.9.0"} typing-extensions = "^4.0" @@ -73,7 +71,8 @@ bioformats = ["pims","JPype1"] czi = ["pims","pylibCZIrw"] all = ["pims","tifffile","imagecodecs","JPype1","pylibCZIrw"] -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +optional = true dask = { version = "^2023.9.1", python = ">=3.9", extras = ["distributed"] } hypothesis = "^6.35.0" icecream = "^2.1.1" @@ -90,12 +89,17 @@ pytest-timeout = "^2.1.0" pytest-timestamper = "^0.0.9" types-python-dateutil = "^0.1.6" ruff = "^0.3.2" + +[tool.poetry.group.examples.dependencies] # packages for examples: +optional = true fastremap = "^1.13.3" pandas = "^1.3.4" pooch = "^1.5.2" s3fs = "^2023.9.0" tabulate = "^0.8.9" +scikit-learn = "^1.0.1" +scikit-image = "^0.21.0" [[tool.poetry.source]] name = "PyPI" From 79bf710b8522de18a9f85dc1b2325f16218be1ea Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Thu, 21 Mar 2024 15:10:31 +0100 Subject: [PATCH 2/5] remove nifti script to avoid sklearn dependency --- docs/src/cli/index.md | 7 - webknossos/Changelog.md | 1 - webknossos/webknossos/cli/convert_nifti.py | 398 --------------------- webknossos/webknossos/cli/main.py | 2 - wkcuber/README.md | 1 - 5 files changed, 409 deletions(-) delete mode 100644 webknossos/webknossos/cli/convert_nifti.py diff --git a/docs/src/cli/index.md b/docs/src/cli/index.md index 74ed53544..5622e379b 100644 --- a/docs/src/cli/index.md +++ b/docs/src/cli/index.md @@ -9,7 +9,6 @@ The WEBKNOSSOS CLI offers many useful commands to work with WEBKNOSSOS datasets: - `webknossos compress`: Compress a WEBKNOSSOS dataset - `webknossos convert`: Convert an image stack (e.g., `tiff`, `jpg`, `png`, `bmp`, `dm3`, `dm4`) to a WEBKNOSSOS dataset - `webknossos convert-knossos`: Converts a KNOSSOS dataset to a WEBKNOSSOS dataset -- `webknossos convert-nifti`: Converts a NIFTI image or a directory with NIFTI files into a WEBKNOSSOS dataset - `webknossos convert-raw`: Converts a RAW image file to a WEBKNOSSOS dataset - `webknossos convert-zarr`: Converts a Zarr dataset to a WEBKNOSSOS dataset - `webknossos download`: Download a dataset from a WEBKNOSSOS server as WKW format @@ -57,12 +56,6 @@ webknossos compress data/target # Convert Knossos cubes to wkw cubes webknossos convert-knossos --layer-name color --voxel-size 11.24,11.24,25 data/source/mag1 data/target -# Convert NIFTI file to wkw file -webknossos convert-nifti --layer-name color --voxel-size 10,10,30 data/source/nifti_file data/target - -# Convert folder with NIFTI files to wkw files -webknossos convert-nifti --color-file one_nifti_file --segmentation-file another_nifti --voxel-size 10,10,30 data/source/ data/target - # Convert RAW file to wkw file webknossos convert-raw --layer-name color --voxel-size 10,10,30 --dtype uint8 --shape 2048,2048,1024 data/source/raw_file.raw data/target diff --git a/webknossos/Changelog.md b/webknossos/Changelog.md index bb493f1e9..224e2b825 100644 --- a/webknossos/Changelog.md +++ b/webknossos/Changelog.md @@ -226,7 +226,6 @@ For upgrade instructions, please check the respective _Breaking Changes_ section - `python -m wkcuber`, `python -m wkcuber.convert_image_stack_to_wkw` -> `webknossos convert` - `python -m wkcuber.export_wkw_as_tiff` -> `webknossos export-wkw-as-tiff` - `python -m wkcuber.convert_knossos` -> `webknossos convert-knossos` - - `python -m wkcuber.convert_nifti` -> `webknossos convert-nifti` - `python -m wkcuber.convert_raw` -> `webknossos convert-raw` - `python -m wkcuber.downsampling` -> `webknossos downsample` - `python -m wkcuber.compress` -> `webknossos compress` diff --git a/webknossos/webknossos/cli/convert_nifti.py b/webknossos/webknossos/cli/convert_nifti.py deleted file mode 100644 index 823537da2..000000000 --- a/webknossos/webknossos/cli/convert_nifti.py +++ /dev/null @@ -1,398 +0,0 @@ -"""This module converts a NIFTI image or a folder with NIFTI images to a WEBKNOSSOS dataset.""" - -import logging -from pathlib import Path -from typing import Any, Optional, Tuple, Union, cast - -import nibabel as nib -import numpy as np -import typer -from sklearn.preprocessing import LabelEncoder -from typing_extensions import Annotated - -from ..dataset import DataFormat, Dataset, LayerCategoryType -from ..dataset.defaults import DEFAULT_CHUNK_SHAPE, DEFAULT_CHUNKS_PER_SHARD -from ..geometry import BoundingBox, Vec3Int -from ..utils import time_start, time_stop -from ._utils import ( - Vec2Int, - VoxelSize, - pad_or_crop_to_size_and_topleft, - parse_bbox, - parse_path, - parse_vec3int, - parse_voxel_size, -) - - -def to_target_datatype( - data: np.ndarray, - target_dtype: Union[type, str, np.dtype], - is_segmentation_layer: bool, -) -> np.ndarray: - """Cast data into target datatype.""" - - if is_segmentation_layer: - original_shape = data.shape - label_encoder = LabelEncoder() - return ( - label_encoder.fit_transform(data.ravel()) - .reshape(original_shape) - .astype(np.dtype(target_dtype)) - ) - - factor: Any - if data.dtype == np.dtype("float32"): - factor = data.max() - elif data.dtype == np.dtype("float64"): - factor = data.max() / np.iinfo(target_dtype).max - else: - factor = np.iinfo(data.dtype).max / np.iinfo(target_dtype).max - - if data.max() == 0: - logging.warning("Not rescaling data since maximum is 0") - factor = 1 - - return (data / factor).astype(np.dtype(target_dtype)) - - -def convert_nifti( - source_nifti_path: Path, - target_path: Path, - layer_name: str, - dtype: str, - voxel_size: Optional[VoxelSize], - data_format: DataFormat, - chunk_shape: Vec3Int, - chunks_per_shard: Vec3Int, - is_segmentation_layer: bool = False, - bbox_to_enforce: Optional[BoundingBox] = None, - use_orientation_header: bool = False, - flip_axes: Optional[Union[int, Tuple[int, ...]]] = None, -) -> None: - """Converts a single NIFTI file into a WEBKNOSSOS dataset.""" - - shard_shape = chunk_shape * chunks_per_shard - time_start(f"Converting of {source_nifti_path}") - - source_nifti = nib.load(str(source_nifti_path.resolve())) - - if use_orientation_header: - # Get canonical representation of data to incorporate - # encoded transformations. Needs to be flipped later - # to match the coordinate system of WKW. - source_nifti = nib.funcs.as_closest_canonical(source_nifti, enforce_diag=False) - - cube_data = np.array(source_nifti.get_fdata()) # type:ignore - - category_type: LayerCategoryType = ( - "segmentation" if is_segmentation_layer else "color" - ) - logging.debug("Assuming %s as layer type for %s", category_type, layer_name) - - if len(source_nifti.shape) == 3: # type:ignore - cube_data = cube_data.reshape((1,) + source_nifti.shape) # type:ignore - - elif len(source_nifti.shape) == 4: # type:ignore - cube_data = np.transpose(cube_data, (3, 0, 1, 2)) - - else: - logging.warning( - "Converting of %s failed! Too many or too less dimensions", - source_nifti_path, - ) - - return - - if use_orientation_header: - # Flip y and z to transform data into wkw's coordinate system. - cube_data = np.flip(cube_data, (2, 3)) - - if flip_axes: - cube_data = np.flip(cube_data, flip_axes) - - if voxel_size is None: - voxel_size = tuple(map(float, source_nifti.header["pixdim"][:3])) # type:ignore - - logging.info("Using voxel_size: %s", voxel_size) - cube_data = to_target_datatype(cube_data, dtype, is_segmentation_layer) - - # everything needs to be padded to - if bbox_to_enforce is not None: - target_topleft = np.array((0,) + tuple(bbox_to_enforce.topleft)) - target_size = np.array((1,) + tuple(bbox_to_enforce.size)) - - cube_data = pad_or_crop_to_size_and_topleft( - cube_data, target_size, target_topleft - ) - - # Writing wkw compressed requires files of shape (shard_shape, shard_shape, shard_shape) - # Pad data accordingly - padding_offset = shard_shape - np.array(cube_data.shape[1:4]) % shard_shape - cube_data = np.pad( - cube_data, - ( - (0, 0), - (0, int(padding_offset[0])), - (0, int(padding_offset[1])), - (0, int(padding_offset[2])), - ), - ) - - wk_ds = Dataset( - target_path, - voxel_size=cast(Tuple[float, float, float], voxel_size or (1, 1, 1)), - exist_ok=True, - ) - wk_layer = ( - wk_ds.get_or_add_layer( - layer_name, - category_type, - dtype_per_layer=np.dtype(dtype), - data_format=data_format, - largest_segment_id=int(np.max(cube_data) + 1), - ) - if is_segmentation_layer - else wk_ds.get_or_add_layer( - layer_name, - category_type, - data_format=data_format, - dtype_per_layer=np.dtype(dtype), - ) - ) - wk_mag = wk_layer.get_or_add_mag( - "1", chunk_shape=chunk_shape, chunks_per_shard=chunks_per_shard - ) - wk_mag.write(cube_data) - - time_stop(f"Converting of {source_nifti_path}") - - -def convert_folder_nifti( - source_folder_path: Path, - target_path: Path, - color_subpath: Optional[str], - segmentation_subpath: Optional[str], - voxel_size: Optional[VoxelSize], - data_format: DataFormat, - chunk_shape: Vec3Int, - chunks_per_shard: Vec3Int, - use_orientation_header: bool = False, - bbox_to_enforce: Optional[BoundingBox] = None, - flip_axes: Optional[Union[int, Tuple[int, ...]]] = None, -) -> None: - """Converts a folder of NIFTI files into WEBKNOSSOS dataset.""" - paths = list(source_folder_path.rglob("**/*.nii")) - - color_path = None - segmentation_path = None - if color_subpath is not None: - color_path = target_path / color_subpath - if color_path not in paths: - logging.warning( - "Specified color file %s not in source path %s!", - color_path, - source_folder_path, - ) - - if segmentation_subpath is not None: - segmentation_path = target_path / segmentation_subpath - if segmentation_path not in paths: - logging.warning( - "Specified segmentation_file file %s not in source path %s!", - segmentation_path, - source_folder_path, - ) - - logging.info("Segmentation file will also use uint8 as a datatype.") - - for path in paths: - if path == color_path: - convert_nifti( - path, - target_path, - "color", - "uint8", - voxel_size, - data_format, - chunk_shape, - chunks_per_shard, - is_segmentation_layer=False, - bbox_to_enforce=bbox_to_enforce, - use_orientation_header=use_orientation_header, - flip_axes=flip_axes, - ) - elif path == segmentation_path: - convert_nifti( - path, - target_path, - "segmentation", - "uint8", - voxel_size, - data_format, - chunk_shape, - chunks_per_shard, - is_segmentation_layer=True, - bbox_to_enforce=bbox_to_enforce, - use_orientation_header=use_orientation_header, - flip_axes=flip_axes, - ) - else: - convert_nifti( - path, - target_path, - path.stem, - "uint8", - voxel_size, - data_format, - chunk_shape, - chunks_per_shard, - is_segmentation_layer=False, - bbox_to_enforce=bbox_to_enforce, - use_orientation_header=use_orientation_header, - flip_axes=flip_axes, - ) - - -def main( - *, - source: Annotated[ - Any, - typer.Argument( - help="Path to your image data.", - show_default=False, - parser=parse_path, - ), - ], - target: Annotated[ - Any, - typer.Argument( - help="Target path to save your WEBKNOSSOS dataset.", - show_default=False, - parser=parse_path, - ), - ], - layer_name: Annotated[ - str, - typer.Option(help="Name of the cubed layer (color or segmentation)"), - ] = "color", - voxel_size: Annotated[ - Optional[VoxelSize], - typer.Option( - help="The size of one voxel in source data in nanometers. \ -Should be a comma seperated string (e.g. 11.0,11.0,20.0).", - parser=parse_voxel_size, - metavar="VOXEL_SIZE", - ), - ] = None, - dtype: Annotated[ - str, typer.Option(help="Target datatype (e.g. uint8, uint16, uint32)") - ] = "uint8", - data_format: Annotated[ - DataFormat, - typer.Option( - help="Data format to store the target dataset in.", - ), - ] = "wkw", # type:ignore - chunk_shape: Annotated[ - Vec3Int, - typer.Option( - help="Number of voxels to be stored as a chunk in the output format " - "(e.g. `32` or `32,32,32`).", - parser=parse_vec3int, - metavar="Vec3Int", - ), - ] = DEFAULT_CHUNK_SHAPE, - chunks_per_shard: Annotated[ - Vec3Int, - typer.Option( - help="Number of chunks to be stored as a shard in the output format " - "(e.g. `32` or `32,32,32`).", - parser=parse_vec3int, - metavar="Vec3Int", - ), - ] = DEFAULT_CHUNKS_PER_SHARD, - enforce_bounding_box: Annotated[ - Optional[BoundingBox], - typer.Option( - help="The BoundingBox to which the input data should be written. " - "If the input data is too small, it will be padded. If it's too large, " - "it will be cropped. The input format is x,y,z,width,height,depth.", - parser=parse_bbox, - metavar="BBOX", - ), - ] = None, - color_file: Annotated[ - Optional[str], - typer.Option( - help="When converting folder, name of file to become color layer." - ), - ] = None, - segmentation_file: Annotated[ - Optional[str], - typer.Option( - help="When converting folder, name of file to become segmentation layer." - ), - ] = None, - use_orientation_header: Annotated[ - bool, - typer.Option( - help="Use orientation information from header to interpret the input data \ -(should be tried if output orientation seems to be wrong)." - ), - ] = False, - is_segmentation_layer: Annotated[ - bool, - typer.Option( - help="When converting one layer, signals whether layer is segmentation layer. \ -When converting a folder, this option is ignored." - ), - ] = False, - flip_axes: Annotated[ - Optional[Vec2Int], - typer.Option( - help="The axes at which should be flipped. \ -Input format is a comma separated list of axis indices. \ -For example, 1,2,3 will flip the x, y and z axes.", - parser=parse_vec3int, - metavar="Vec3Int", - ), - ] = None, -) -> None: - """Converts a NIFTI file or a folder of NIFTI files into a WEBKNOSSOS dataset.""" - - if flip_axes is not None: - for index in flip_axes: - assert ( - 0 <= index <= 3 - ), "flip_axes parameter must only contain indices between 0 and 3." - - if source.is_dir(): - convert_folder_nifti( - source, - target, - color_file, - segmentation_file, - voxel_size=voxel_size, - data_format=data_format, - chunk_shape=chunk_shape, - chunks_per_shard=chunks_per_shard, - bbox_to_enforce=enforce_bounding_box, - use_orientation_header=use_orientation_header, - flip_axes=flip_axes, - ) - else: - convert_nifti( - source, - target, - layer_name, - dtype, - voxel_size=voxel_size, - data_format=data_format, - chunk_shape=chunk_shape, - chunks_per_shard=chunks_per_shard, - is_segmentation_layer=is_segmentation_layer, - bbox_to_enforce=enforce_bounding_box, - use_orientation_header=use_orientation_header, - flip_axes=flip_axes, - ) diff --git a/webknossos/webknossos/cli/main.py b/webknossos/webknossos/cli/main.py index afd9ce118..3f56d05bf 100644 --- a/webknossos/webknossos/cli/main.py +++ b/webknossos/webknossos/cli/main.py @@ -7,7 +7,6 @@ compress, convert, convert_knossos, - convert_nifti, convert_raw, convert_zarr, download, @@ -24,7 +23,6 @@ app.command("compress")(compress.main) app.command("convert")(convert.main) app.command("convert-knossos")(convert_knossos.main) -app.command("convert-nifti")(convert_nifti.main) app.command("convert-raw")(convert_raw.main) app.command("convert-zarr")(convert_zarr.main) app.command("download")(download.main) diff --git a/wkcuber/README.md b/wkcuber/README.md index 16a58bf94..529e730ed 100644 --- a/wkcuber/README.md +++ b/wkcuber/README.md @@ -14,7 +14,6 @@ Run `webknossos --help` to get an overview of the currently available commands. - `python -m wkcuber`, `python -m wkcuber.convert_image_stack_to_wkw` → `webknossos convert` - `python -m wkcuber.export_wkw_as_tiff` → `webknossos export-wkw-as-tiff` - `python -m wkcuber.convert_knossos` → `webknossos convert-knossos` - - `python -m wkcuber.convert_nifti` → `webknossos convert-nifti` - `python -m wkcuber.convert_raw` → `webknossos convert-raw` - `python -m wkcuber.downsampling` → `webknossos downsample` - `python -m wkcuber.compress` → `webknossos compress` From 281c08bc32390c67abcae9ab581d8c9c4b9af1c0 Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Tue, 25 Jun 2024 14:52:13 +0200 Subject: [PATCH 3/5] fix optional marker --- webknossos/pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/webknossos/pyproject.toml b/webknossos/pyproject.toml index 14bed061c..7df11cd01 100644 --- a/webknossos/pyproject.toml +++ b/webknossos/pyproject.toml @@ -95,7 +95,6 @@ optional = true [tool.poetry.group.examples.dependencies] # packages for examples: -optional = true fastremap = "^1.13.3" pandas = "^1.3.4" pooch = "^1.5.2" From 1e65e7bed34faf379f56ce3f553d5596f1dd1031 Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Thu, 29 Aug 2024 14:44:30 +0200 Subject: [PATCH 4/5] added more submodules to api docs --- docs/generate_api_doc_pages.py | 79 ++++++++++++++++++++-------------- docs/mkdocs.yml | 14 +++--- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/docs/generate_api_doc_pages.py b/docs/generate_api_doc_pages.py index f6953363d..ca6446c89 100644 --- a/docs/generate_api_doc_pages.py +++ b/docs/generate_api_doc_pages.py @@ -6,45 +6,60 @@ import webknossos -''' +""" This script generates a mapping of all classes in webknossos to their corresponding MkDocs pages. It is used to generate the API reference. -''' +""" logger = getLogger(__name__) OUT_PATH = Path("src/api") -for key, value in webknossos.__dict__.items(): - if getattr(value, "__module__", "").startswith("webknossos"): - - logger.debug("Processing module", key) - - module = value.__module__ - - module_parts = module.split('.') - module_name = module_parts[-1] - module_path = "/".join(module_parts[:-1]) - file_name = f"{key.lower()}.md" - - # Extract all classes from the module - classes = inspect.getmembers(sys.modules[module], inspect.isclass) - - # Only include classes that are in implemented in that module - classes = [c for c in classes if c[1].__module__ == module] - classes = [c for c in classes if not c[0].startswith("_")] - - # The file content uses a special syntax for MkDocs to render the - # docstrings as Markdown. The syntax is: - # ::: module.submodule.class - # See https://mkdocstrings.github.io/python/ - classes_string = "\n".join([f" - {c[0]}" for c in classes]) - file_content = f"""::: {module} +# Initialize a dictionary to store submodules and their classes +submodules_classes = {} + +# Iterate through all the members of the module +for name, member in inspect.getmembers(webknossos): + # Check if the member is a module (submodule) + if inspect.ismodule(member) and member.__name__.startswith("webknossos"): + submodule_name = member.__name__ + + # List classes in the submodule + classes = inspect.getmembers(member, inspect.isclass) + + # Filter classes that are defined in this specific submodule + defined_classes = [ + cls for cls_name, cls in classes if cls.__module__ == submodule_name + ] + + # If there are classes defined in this submodule, add them to the dictionary + if defined_classes: + submodules_classes[submodule_name] = defined_classes + +# Print the submodules and their classes +for submodule, classes in submodules_classes.items(): + # The file content uses a special syntax for MkDocs to render the + # docstrings as Markdown. The syntax is: + # ::: module.submodule.class + # See https://mkdocstrings.github.io/python/ + classes_string = "\n".join( + [ + f" - {c.__name__}" + for c in classes + if not c.__name__.startswith("_") + ] + ) + file_content = f"""::: {submodule} options: members:\n{classes_string}\n""" - - out_path=OUT_PATH.joinpath(module_path) - out_path.mkdir(exist_ok=True, parents=True) - logger.debug(f"Writing API docs to {out_path.joinpath(file_name)}") - out_path.joinpath(file_name).write_text(file_content) + submodule_parts = submodule.split(".") + submodule_name = submodule_parts[-1] + file_name = Path(f"{submodule_name}.md") + file_path = "/".join(submodule_parts[:-1]) + + out_path = OUT_PATH.joinpath(file_path) + out_path.mkdir(exist_ok=True, parents=True) + + logger.debug(f"Writing API docs to {out_path.joinpath(file_name)}") + out_path.joinpath(file_name).write_text(file_content) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 813926323..1fe7233ac 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -115,15 +115,15 @@ nav: - API Reference: - Overview: api/webknossos.md - Geometry: - - BoundingBox: api/webknossos/geometry/boundingbox.md - - NDBoundingBox: api/webknossos/geometry/ndboundingbox.md + - BoundingBox: api/webknossos/geometry/bounding_box.md + - NDBoundingBox: api/webknossos/geometry/nd_bounding_box.md - Mag: api/webknossos/geometry/mag.md - - Vec3Int: api/webknossos/geometry/vec3int.md - - VecInt: api/webknossos/geometry/vecint.md + - Vec3Int: api/webknossos/geometry/vec3_int.md + - VecInt: api/webknossos/geometry/vec_int.md - Dataset: - Dataset: api/webknossos/dataset/dataset.md - Layer: api/webknossos/dataset/layer.md - - MagView: api/webknossos/dataset/magview.md + - MagView: api/webknossos/dataset/mag_view.md - View: api/webknossos/dataset/view.md - Annotation: api/webknossos/annotation/annotation.md - Skeleton: @@ -131,7 +131,7 @@ nav: - Group: api/webknossos/skeleton/group.md - Tree: api/webknossos/skeleton/tree.md - Node: api/webknossos/skeleton/node.md - - Authentication & Server Context: api/webknossos/client/webknossos_context.md + - Authentication & Server Context: api/webknossos/client/context.md - Administration: - User: api/webknossos/administration/user.md - Project: api/webknossos/administration/project.md @@ -174,7 +174,7 @@ plugins: show_source: false docstring_style: null docstring_section_style: list - heading_level: 2 + heading_level: 1 inherited_members: true merge_init_into_class: true parameter_headings: true From 4ea15fe55313dcd8775a66f0c466eb285060c22b Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Thu, 29 Aug 2024 16:07:10 +0200 Subject: [PATCH 5/5] remove unused imports --- docs/generate_api_doc_pages.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/generate_api_doc_pages.py b/docs/generate_api_doc_pages.py index ca6446c89..229f0c87f 100644 --- a/docs/generate_api_doc_pages.py +++ b/docs/generate_api_doc_pages.py @@ -1,6 +1,4 @@ -import shutil import inspect -import sys from logging import getLogger from pathlib import Path