# WEBKNOSSOS Documentation # API Reference # webknossos.utils ## LazyPath ``` LazyPath(*paths: UPath) ``` ### paths ``` paths: tuple[UPath, ...] = tuple(paths) ``` ### resolution ``` resolution: int | None = None ``` ### resolve ``` resolve() -> UPath ``` ### resolved ``` resolved(path: UPath) -> LazyPath ``` ## LazyReadOnlyDict ``` LazyReadOnlyDict( entries: dict[K, C], func: Callable[[C], V] ) ``` Bases: `Mapping[K, V]` ### entries ``` entries = entries ``` ### func ``` func = func ``` ## NDArrayLike Bases: `Protocol` ### dtype ``` dtype: dtype ``` ### ndim ``` ndim: int ``` ### shape ``` shape: tuple[int, ...] ``` ## WkImportError ``` WkImportError( missing_package: str, extras: str = "all", custom_message: str | None = None, ) ``` Bases: `ImportError` Exception raised when a dependency is missing. # webknossos.\_nml ## Branchpoint Bases: `NamedTuple` ### id ``` id: int ``` ### time ``` time: int | None ``` # webknossos.\_nml ## Comment Bases: `NamedTuple` ### content ``` content: str ``` ### node ``` node: int ``` # webknossos.\_nml ## Edge Bases: `NamedTuple` ### source ``` source: int ``` ### target ``` target: int ``` # webknossos.\_nml ## Group Bases: `NamedTuple` ### children ``` children: list[Group] ``` ### id ``` id: int ``` ### name ``` name: str ``` # webknossos.\_nml ## Meta Bases: `NamedTuple` ### content ``` content: str ``` ### name ``` name: str ``` # webknossos.\_nml ## MetadataEntry Bases: `NamedTuple` ### key ``` key: str ``` ### type ``` type: Literal['str', 'number', 'list'] ``` ### value ``` value: str | int | float | Sequence[str] ``` # webknossos.\_nml ## Nml Bases: `NamedTuple` ### branchpoints ``` branchpoints: list[Branchpoint] ``` ### comments ``` comments: list[Comment] ``` ### groups ``` groups: list[Group] ``` ### meta ``` meta: list[Meta] ``` ### parameters ``` parameters: Parameters ``` ### trees ``` trees: list[Tree] ``` ### volumes ``` volumes: list[Volume] = [] ``` ### get_meta ``` get_meta(key: str) -> str | None ``` ### parse ``` parse(file: IO[bytes]) -> Nml ``` Reads a WEBKNOSSOS NML skeleton file from disk, \_parses it and returns an NML Python object Parameters: - **`file`** (`BinaryIO`) – A Python file handle Return NML: A WEBKNOSSOS skeleton annotation as Python NML object Examples: ``` with open("input.nml", "rb") as f: nml = Nml.parse(f) ``` ### write ``` write(file: BinaryIO) -> None ``` Writes the NML object to a file on disk. Parameters: - **`file`** (`BinaryIO`) – A Python file handle Examples: ``` with open("out.nml", "wb") as f: nml.write(f, nml) ``` # webknossos.\_nml ## Node Bases: `NamedTuple` ### bitDepth ``` bitDepth: int | None = None ``` ### id ``` id: int ``` ### inMag ``` inMag: int | None = None ``` ### inVp ``` inVp: int | None = None ``` ### interpolation ``` interpolation: bool | None = None ``` ### position ``` position: Vector3 ``` ### radius ``` radius: float | None = None ``` ### rotation ``` rotation: Vector3 | None = None ``` ### time ``` time: int | None = None ``` # webknossos.\_nml ## Parameters Bases: `NamedTuple` ### dataset_id ``` dataset_id: str | None = None ``` ### description ``` description: str | None = None ``` ### editPosition ``` editPosition: Vector3 | None = None ``` ### editRotation ``` editRotation: Vector3 | None = None ``` ### name ``` name: str ``` ### offset ``` offset: Vector3 | None = None ``` ### organization ``` organization: str | None = None ``` ### scale ``` scale: VoxelSize ``` ### taskBoundingBox ``` taskBoundingBox: NDBoundingBox | None = None ``` ### time ``` time: int | None = None ``` ### userBoundingBoxes ``` userBoundingBoxes: list[NDBoundingBox] | None = None ``` ### zoomLevel ``` zoomLevel: float | None = None ``` # webknossos.\_nml ## Segment Bases: `NamedTuple` ### anchor_position ``` anchor_position: Vec3Int | None ``` ### color ``` color: Vector4 | None ``` ### id ``` id: int ``` ### metadata ``` metadata: list[MetadataEntry] ``` ### name ``` name: str | None ``` # webknossos.\_nml ## Tree Bases: `NamedTuple` ### color ``` color: Vector4 | None ``` ### edges ``` edges: list[Edge] ``` ### groupId ``` groupId: int | None = None ``` ### id ``` id: int ``` ### is_visible ``` is_visible: bool = True ``` ### metadata ``` metadata: list[MetadataEntry] ``` ### name ``` name: str ``` ### nodes ``` nodes: list[Node] ``` # webknossos.\_nml ## Volume Bases: `NamedTuple` ### fallback_layer ``` fallback_layer: str | None ``` ### format ``` format: str | None = None ``` ### id ``` id: int ``` ### largest_segment_id ``` largest_segment_id: int | None = None ``` ### location ``` location: str | None ``` ### name ``` name: str | None ``` ### segments ``` segments: list[Segment] ``` # webknossos.administration ## Project Data class containing information about a WEBKNOSSOS project ### expected_time ``` expected_time: int | None ``` ### is_blacklisted_from_report ``` is_blacklisted_from_report: bool ``` ### name ``` name: str ``` ### owner_id ``` owner_id: str | None ``` ### paused ``` paused: bool ``` ### priority ``` priority: int ``` ### project_id ``` project_id: str ``` ### team_id ``` team_id: str ``` ### team_name ``` team_name: str ``` ### create ``` create( name: str, team: str | Team, expected_time: int | None, priority: int = 100, paused: bool = False, is_blacklisted_from_report: bool = False, owner: str | User | None = None, ) -> Project ``` Creates a new project and returns it. Note: The project will be created with the current user as owner. Parameters: - **`name`** (`str`) – The name of the project. - **`priority`** (`int`, default: `100` ) – The priority of the project. - **`paused`** (`bool`, default: `False` ) – Whether the project is paused or not. - **`expected_time`** (`int | None`) – The expected time for the project in minutes. - **`team_id`** (`str`) – The ID of the team to which the project belongs. - **`owner_id`** – (str | None): The ID of the owner user of the project. If None, the current user will be used. Returns: - **`Project`** ( `Project` ) – The created project. ### delete ``` delete() -> None ``` Deletes this project from server. WARNING: This is irreversible! ### get_by_id ``` get_by_id(project_id: str) -> Project ``` Retrieve a project by its unique identifier. Fetches the project with the specified `project_id` from the backend, provided the current user can access the project. This method requires valid authentication. Parameters: - **`project_id`** (`str`) – The unique identifier of the project to retrieve. Returns: - **`Project`** ( `Project` ) – An instance of the Project class corresponding to the specified ID. Raises: - `UnexpectedStatusError` – If the project does not exist or the user is not authorized to access it. Examples: Retrieve a project by ID: ``` project = Project.get_by_id("project_12345") print(project.name) ``` ### get_by_name ``` get_by_name(name: str) -> Project ``` Retrieve a project by its unique name. Fetches the project with the specified `name` from the backend, provided the current user can access the project. This method requires valid authentication. Parameters: - **`name`** (`str`) – The unique name of the project to retrieve. Returns: - **`Project`** ( `Project` ) – An instance of the Project class corresponding to the specified name. Raises: - `UnexpectedStatusError` – If the project does not exist or the user is not authorized to access it. Examples: Retrieve a project by name: ``` project = Project.get_by_name("my_project") print(project.project_id) ``` ### get_owner ``` get_owner() -> User ``` Returns the user that is the owner of this task ### get_tasks ``` get_tasks(fetch_all: bool = False) -> list[Task] ``` Retrieve the list of tasks associated with this project. By default, this method fetches up to the first 1000 tasks for the project. If the project contains more than 1000 tasks, a warning is issued unless `fetch_all=True` is passed, in which case all tasks are fetched using pagination. Parameters: - **`fetch_all`** (`bool`, default: `False` ) – If True, fetches all tasks for the project using pagination. If False (default), only the first 1000 tasks are returned and a warning is issued if more tasks exist. Returns: - `list[Task]` – list\[Task\]: A list of Task objects associated with this project. Examples: Fetch up to 1000 tasks: ``` tasks = project.get_tasks() print(f"Fetched {len(tasks)} tasks") ``` Fetch all tasks, regardless of count: ``` all_tasks = project.get_tasks(fetch_all=True) print(f"Total tasks: {len(all_tasks)}") ``` ### update ``` update( priority: int | None = None, expected_time: int | None = None, is_blacklisted_from_report: bool | None = None, ) -> Project ``` Update the project's properties and return the updated Project instance. This method updates the project's priority, expected time, and blacklist status for reporting. Only the parameters provided (not None) will be updated; others remain unchanged. Parameters: - **`priority`** (`int | None`, default: `None` ) – Optional new priority for the project. If not provided, the current priority is kept. - **`expected_time`** (`int | None`, default: `None` ) – Optional new expected time (in minutes or relevant unit) for the project. If not provided, the current expected time is kept. - **`is_blacklisted_from_report`** (`bool | None`, default: `None` ) – Optional flag to set whether the project should be excluded from reports. If not provided, the current blacklist status is kept. Returns: - **`Project`** ( `Project` ) – The updated Project instance reflecting the new properties. Examples: Update only the priority: ``` project = project.update(priority=5) ``` Update expected time and blacklist status: ``` project = project.update(expected_time=120, is_blacklisted_from_report=True) ``` # webknossos.administration ## Task Data class containing information about a WEBKNOSSOS task ### bounding_box ``` bounding_box: BoundingBox | None = None ``` ### dataset_id ``` dataset_id: str ``` ### edit_position ``` edit_position: Vec3Int ``` ### edit_rotation ``` edit_rotation: tuple[float, float, float] ``` ### experience ``` experience: TaskExperience ``` ### project_id ``` project_id: str ``` ### script_id ``` script_id: str | None = None ``` ### status ``` status: TaskStatus ``` ### task_id ``` task_id: str ``` ### task_type ``` task_type: TaskType ``` ### create ``` create( task_type_id: str | TaskType, project_name: str | Project, needed_experience_domain: str, needed_experience_value: int, starting_position: Vec3IntLike, dataset_id: str | RemoteDataset, dataset_name: str | RemoteDataset | None = None, starting_rotation: Vec3IntLike = Vec3Int(0, 0, 0), instances: int = 1, script_id: str | None = None, bounding_box: BoundingBox | None = None, ) -> list[Task] ``` Submits one or more tasks to WEBKNOSSOS based on the specified dataset, starting position, and rotation, and returns the created Task objects. This method allows you to create annotation or analysis tasks for a given dataset, specifying the required experience, starting position, and other parameters. The dataset can be referenced either by its ID or by passing a RemoteDataset instance. Optionally, a bounding box can be provided to restrict the task area. Parameters: - **`task_type_id`** (`str | TaskType`) – The ID of the task type to create, or a TaskType instance. - **`project_name`** (`str | Project`) – The name of the project to associate the task with, or a Project instance. - **`needed_experience_domain`** (`str`) – The experience domain required for the task (e.g., "segmentation"). - **`needed_experience_value`** (`int`) – The minimum experience value required for the task. - **`starting_position`** (`Vec3IntLike`) – The starting position for the task as a Vec3IntLike (x, y, z). - **`dataset_id`** (`str | RemoteDataset`) – The dataset ID as a string or a RemoteDataset instance. - **`dataset_name`** (`str | RemoteDataset | None`, default: `None` ) – (Deprecated) The dataset name as a string or RemoteDataset instance. Prefer using dataset_id. - **`starting_rotation`** (`Vec3IntLike`, default: `Vec3Int(0, 0, 0)` ) – The starting rotation for the task as a Vec3IntLike (default: Vec3Int(0, 0, 0)). - **`instances`** (`int`, default: `1` ) – The number of task instances to create (default: 1). - **`script_id`** (`str | None`, default: `None` ) – Optional script ID to associate with the task. - **`bounding_box`** (`BoundingBox | None`, default: `None` ) – Optional BoundingBox to restrict the task area. Returns: - `list[Task]` – list\[Task\]: A list of created Task objects. Raises: - `AssertionError` – If neither dataset_id nor dataset_name is provided. - `DeprecationWarning` – If dataset_name is used instead of dataset_id. Examples: Create a new segmentation task for a dataset: ``` tasks = Task.create( task_type_id="segmentation", project_name="MyProject", needed_experience_domain="segmentation", needed_experience_value=10, starting_position=(100, 200, 300), dataset_id="abc123", instances=5 for task in tasks: print(task.id) ``` Create a task with a bounding box and a RemoteDataset: ``` bbox = BoundingBox((0, 0, 0), (100, 100, 100)) tasks = Task.create( task_type_id=task_type, project_name=project, needed_experience_domain="proofreading", needed_experience_value=5, starting_position=(0, 0, 0), dataset_id=remote_ds, bounding_box=bbox ``` ### create_from_annotations ``` create_from_annotations( task_type_id: str | TaskType, project_name: str | Project, base_annotations: list[Annotation], needed_experience_domain: str, needed_experience_value: int, instances: int = 1, script_id: str | None = None, bounding_box: BoundingBox | None = None, ) -> list[Task] ``` Create new tasks in WEBKNOSSOS from existing annotations. This class method submits one or more tasks to WEBKNOSSOS, using a list of base annotations as input. It returns the created Task objects. The method allows specifying the task type, project, required experience, number of task instances, and optionally a script and bounding box. Parameters: - **`task_type_id`** (`str | TaskType`) – The ID or TaskType object specifying the type of task to create. - **`project_name`** (`str | Project`) – The name or Project object specifying the project to which the tasks belong. - **`base_annotations`** (`list[Annotation]`) – List of Annotation objects to use as the basis for the new tasks. Must not be empty. - **`needed_experience_domain`** (`str`) – The experience domain required for the task (e.g., "proofreading"). - **`needed_experience_value`** (`int`) – The minimum experience value required for the task. - **`instances`** (`int`, default: `1` ) – Number of task instances to create (default: 1). - **`script_id`** (`str | None`, default: `None` ) – Optional script ID to associate with the task. - **`bounding_box`** (`BoundingBox | None`, default: `None` ) – Optional BoundingBox object specifying the spatial extent of the task. Returns: - `list[Task]` – list\[Task\]: List of created Task objects. Raises: - `AssertionError` – If no base annotations are provided. Examples: ``` tasks = Task.create_from_annotations( task_type_id="proofreading", project_name="MyProject", base_annotations=[annotation1, annotation2], needed_experience_domain="proofreading", needed_experience_value=3, instances=2, script_id="script_123", bounding_box=BoundingBox((0, 0, 0), (100, 100, 100)) for task in tasks: print(task.task_id) ``` Note Each annotation in `base_annotations` will be uploaded as a zipped file and associated with the created tasks. The method requires authentication and will raise an error if the user is not authenticated. ### delete ``` delete() -> None ``` Deletes this task. WARNING: This is irreversible! ### get_annotation_infos ``` get_annotation_infos() -> list[AnnotationInfo] ``` Returns AnnotationInfo objects describing all task instances that have been started by annotators for this task ### get_by_id ``` get_by_id(task_id: str) -> Task ``` Retrieve a Task by its unique identifier. Fetches the task with the specified ID from the backend, provided the current user is authorized to access it. This method requires authentication. Parameters: - **`task_id`** (`str`) – The unique identifier of the task to retrieve. Returns: - **`Task`** ( `Task` ) – The Task instance corresponding to the given ID. Raises: - `UnexpectedStatusError` – If the task does not exist or the user is not authorized. Examples: Get a task by ID: ``` task = Task.get_by_id("task_12345") print(task.name) ``` ### get_list ``` get_list() -> list[Task] ``` Retrieve all tasks visible to the current user. Returns a list of all tasks that the authenticated user is authorized to see. This method queries the backend for all available tasks and returns them as a list of Task objects. Returns: - `list[Task]` – list\[Task\]: List of Task objects the user is authorized to access. Examples: Get all tasks for the current user: ``` tasks = Task.get_list() for task in tasks: print(task.name) ``` ### get_project ``` get_project() -> Project ``` Returns the project this task belongs to ### update ``` update(remaining_instances: int) -> Task ``` Update the task with new parameters. Updates the current task instance on the server with the specified number of remaining instances and other task parameters. Parameters: - **`remaining_instances`** (`int`) – The number of remaining instances for this task. Returns: - **`Task`** ( `Task` ) – The updated Task object as returned by the server. Examples: ``` task = Task.get_by_id("task_id") updated_task = task.update(remaining_instances=5) print(updated_task.remaining_instances) ``` ## TaskType ### description ``` description: str ``` ### name ``` name: str ``` ### settings ``` settings: dict[str, Any] | None = None ``` ### task_type_id ``` task_type_id: str ``` ### team_id ``` team_id: str ``` ### team_name ``` team_name: str ``` ### tracingType ``` tracingType: str | None = None ``` ### create ``` create( name: str, description: str, team: str | Team, tracing_type: Literal[ "skeleton", "volume", "hybrid" ] = "skeleton", settings: dict[str, Any] = { "mergerMode": False, "magRestrictions": {"min": 1, "max": 1}, "somaClickingAllowed": True, "volumeInterpolationAllowed": False, "allowedModes": [], "preferredMode": None, "branchPointsAllowed": True, "clippingDistance": 80, "moveValue": 500, "displayScalebars": False, "newNodeNewTree": False, "centerNewNode": True, "tdViewDisplayPlanes": "WIREFRAME", "tdViewDisplayDatasetBorders": True, "tdViewDisplayLayerBorders": False, "dynamicSpaceDirection": True, "highlightCommentedNodes": False, "overrideNodeRadius": True, "particleSize": 5, "keyboardDelay": 0, "displayCrosshair": True, "useLegacyBindings": False, "fourBit": False, "interpolation": True, "segmentationOpacity": 0, "segmentationPatternOpacity": 40, "zoom": 0.8, "renderMissingDataBlack": False, "loadingStrategy": "BEST_QUALITY_FIRST", "clippingDistanceArbitrary": 60, "moveValue3d": 600, "mouseRotateValue": 0.001, "rotateValue": 0.01, "sphericalCapRadius": 500, "brushSize": 50, }, ) -> TaskType ``` Creates a new task type and returns it. This class method allows you to create a new task type in the system, specifying its name, description, associated team, and tracing type. The created task type is returned as an instance of `TaskType`. Parameters: - **`name`** (`str`) – The name of the new task type. This will be used as the summary for the task type. - **`description`** (`str`) – A detailed description of the task type. - **`team`** (`str | Team`) – The team to which this task type will belong. Can be either a team name (str) or a Team object. - **`tracing_type`** (`Literal['skeleton', 'volume', 'hybrid']`, default: `'skeleton'` ) – The tracing type for the task. Must be one of "skeleton", "volume", or "hybrid". - **`settings`** (`dict[str, Any]`, default: `{'mergerMode': False, 'magRestrictions': {'min': 1, 'max': 1}, 'somaClickingAllowed': True, 'volumeInterpolationAllowed': False, 'allowedModes': [], 'preferredMode': None, 'branchPointsAllowed': True, 'clippingDistance': 80, 'moveValue': 500, 'displayScalebars': False, 'newNodeNewTree': False, 'centerNewNode': True, 'tdViewDisplayPlanes': 'WIREFRAME', 'tdViewDisplayDatasetBorders': True, 'tdViewDisplayLayerBorders': False, 'dynamicSpaceDirection': True, 'highlightCommentedNodes': False, 'overrideNodeRadius': True, 'particleSize': 5, 'keyboardDelay': 0, 'displayCrosshair': True, 'useLegacyBindings': False, 'fourBit': False, 'interpolation': True, 'segmentationOpacity': 0, 'segmentationPatternOpacity': 40, 'zoom': 0.8, 'renderMissingDataBlack': False, 'loadingStrategy': 'BEST_QUALITY_FIRST', 'clippingDistanceArbitrary': 60, 'moveValue3d': 600, 'mouseRotateValue': 0.001, 'rotateValue': 0.01, 'sphericalCapRadius': 500, 'brushSize': 50}` ) – Additional settings for the task type. Information about the task type's configuration options can be found here: https://docs.webknossos.org/webknossos/tasks_projects/tasks.html Returns: - **`TaskType`** ( `TaskType` ) – The newly created task type object. Raises: - `ValueError` – If the provided team does not exist or cannot be resolved. - `ApiException` – If the API call to create the task type fails. Examples: Create a new skeleton tracing task type for a team: ``` task_type = TaskType.create( name="Neuron Skeleton Tracing", description="Trace neuron skeletons for connectomics project.", team="NeuroLab", tracing_type="skeleton" print(task_type.id) ``` ### delete ``` delete() -> None ``` Deletes the task type. ### get_by_id ``` get_by_id(task_type_id: str) -> TaskType ``` Retrieve a TaskType instance by its unique ID. This class method fetches the task type corresponding to the given `task_type_id` from the backend, provided the current user has permission to view it. Parameters: - **`task_type_id`** (`str`) – The unique identifier of the task type to retrieve. Returns: - **`TaskType`** ( `TaskType` ) – The TaskType instance corresponding to the specified ID. Raises: - `UnexpectedStatusError` – If the task type cannot be found or the user does not have access. Examples: Retrieve a task type by ID: ``` task_type = TaskType.get_by_id("1234567890abcdef") print(task_type.name) ``` ### get_by_name ``` get_by_name(name: str) -> TaskType ``` Get a TaskType by its name. Searches for a task type with the specified name among all available task types visible to the current user. If found, returns the corresponding TaskType object. Parameters: - **`name`** (`str`) – The name of the task type to retrieve. Returns: - **`TaskType`** ( `TaskType` ) – The task type object with the specified name. Raises: - `ValueError` – If no task type with the given name is found. Examples: ``` task_type = TaskType.get_by_name("Segmentation") print(task_type.id) ``` ### get_list ``` get_list() -> list[TaskType] ``` Retrieve all accessible task types for the current user. This class method queries the backend for all task types that the authenticated user is authorized to access. It returns a list of `TaskType` instances corresponding to the available tasks. Returns: - `list[TaskType]` – list\[TaskType\]: List of all task types accessible to the current user. Examples: Get all available task types: ``` task_types = TaskType.get_list() for task_type in task_types: print(task_type.name) ``` # webknossos.administration ## Team ### id ``` id: str ``` ### name ``` name: str ``` ### organization_id ``` organization_id: str ``` ### add ``` add(team_name: str) -> Team ``` Adds a new team with the specified name. ### add_user ``` add_user( user: User, *, is_team_manager: bool = False ) -> None ``` Adds a user to the team. ### delete ``` delete() -> None ``` Deletes the team. ### get_by_id ``` get_by_id(team_id: str) -> Team ``` Returns the Team specified by the passed ID. ### get_by_name ``` get_by_name(name: str) -> Team ``` Returns the Team specified by the passed name if your token authorizes you to see it. ### get_list ``` get_list() -> list[Team] ``` Returns all teams of the current user. # webknossos.administration ## User Represents a user of a webknossos instance. You can get users via `get_current_user` and `get_all_managed_users`. ### created ``` created: int ``` ### email ``` email: str ``` ### experiences ``` experiences: dict[str, int] ``` ### first_name ``` first_name: str ``` ### is_active ``` is_active: bool ``` ### is_admin ``` is_admin: bool ``` ### is_dataset_manager ``` is_dataset_manager: bool ``` ### last_activity ``` last_activity: int ``` ### last_name ``` last_name: str ``` ### organization_id ``` organization_id: str ``` ### teams ``` teams: tuple[Team, ...] ``` ### user_id ``` user_id: str ``` ### assign_team_roles ``` assign_team_roles( team: str | Team, is_team_manager: bool ) -> None ``` Assigns the specified roles to the user for the specified team. ### get_all_managed_users ``` get_all_managed_users() -> list[User] ``` Returns all users of whom the current user is admin or team-manager. ### get_by_id ``` get_by_id(id: str) -> User ``` Returns the user specified by the passed id if your token authorizes you to see them. ### get_current_user ``` get_current_user() -> User ``` Returns the current user from the authentication context. ### get_logged_times ``` get_logged_times() -> list[LoggedTime] ``` Get the logged times of this user. Returns a list of `LoggedTime` objects where one represents one month. # webknossos.ai_model ## AiModelCategory Bases: `Enum` ### em_cell_organelles ``` em_cell_organelles = 'em_cell_organelles' ``` ### em_neuron_types ``` em_neuron_types = 'em_neuron_types' ``` ### em_neurons ``` em_neurons = 'em_neurons' ``` ### em_nuclei ``` em_nuclei = 'em_nuclei' ``` ### em_synapses ``` em_synapses = 'em_synapses' ``` # webknossos.ai_model ## RemoteAiModel ``` RemoteAiModel( ai_model_id: str, name: str, path: str, is_usable: bool ) ``` A remote AiModel instance. Note: Please not initialize this class directly, use RemoteAiModel.open_remote() instead. ### ai_model_id ``` ai_model_id = ai_model_id ``` ### is_usable ``` is_usable = is_usable ``` ### name ``` name = name ``` ### path ``` path = path ``` ### open_remote ``` open_remote(ai_model_id: str) -> RemoteAiModel ``` ### upload_from_path ``` upload_from_path( src_path: UPath, *, existing_id: str | None, data_store_name: str, name: str, comment: str | None, category: AiModelCategory | None, path_prefix: str | None, transfer_mode: TransferMode = COPY ) -> RemoteAiModel ``` # webknossos.annotation ## Annotation Represents an annotation from WEBKNOSSOS containing skeleton and/or volume data. The Annotation class provides functionality to: 1. Load/save annotations from/to .nml or .zip files 1. Download/upload annotations from/to WEBKNOSSOS 1. Work with skeleton data and volume layers 1. Export volume layers to datasets Attributes: - **`name`** (`str`) – Name of the annotation. - **`skeleton`** (`Skeleton`) – Skeleton object containing tree/node data. - **`owner_name`** (`str | None`) – Name of annotation owner. - **`annotation_id`** (`str | None`) – Unique identifier for the annotation. - **`time`** (`int | None`) – Creation timestamp in ms since epoch. - **`edit_position`** (`Vector3 | None`) – 3D position coordinates. - **`edit_rotation`** (`Vector3 | None`) – 3D rotation angles. - **`zoom_level`** (`float | None`) – Current zoom level. - **`metadata`** (`dict[str, str]`) – Dictionary of custom metadata. - **`task_bounding_box`** (`NDBoundingBox | None`) – Optional bounding box for task annotations. - **`user_bounding_boxes`** (`list[NDBoundingBox]`) – List of user-defined bounding boxes. Examples: Create a new annotation: ``` ann = Annotation( name="my_annotation", dataset_name="sample_dataset", voxel_size=(11.2, 11.2, 25.0) ) ``` Load annotation from file: ``` ann = Annotation.load("annotation.nml") ``` Download from WEBKNOSSOS: ``` ann = Annotation.download("annotation_id") ``` Save annotation: ``` ann.save("annotation.zip") ``` Add volume layer: ``` ann.add_volume_layer( name="segmentation", fallback_layer="segmentation_layer" ) ``` ### annotation_id ``` annotation_id: str | None = None ``` ### dataset_id ``` dataset_id: str | None ``` ID of the dataset this annotation belongs to. Proxies to skeleton.dataset_id. ### dataset_name ``` dataset_name: str ``` Name of the dataset this annotation belongs to. Proxies to skeleton.dataset_name. ### description ``` description: str | None ``` Optional description of the annotation. Proxies to skeleton.description. ### edit_position ``` edit_position: Vector3 | None = None ``` ### edit_rotation ``` edit_rotation: Vector3 | None = None ``` ### metadata ``` metadata: dict[str, str] = Factory(dict) ``` ### name ``` name: str ``` ### organization_id ``` organization_id: str | None ``` ID of the organization owning this annotation. Proxies to skeleton.organization_id. ### owner_name ``` owner_name: str | None = None ``` ### skeleton ``` skeleton: Skeleton = None ``` ### task_bounding_box ``` task_bounding_box: NDBoundingBox | None = None ``` ### time ``` time: int | None = ib(factory=time_since_epoch_in_ms) ``` ### user_bounding_boxes ``` user_bounding_boxes: list[NDBoundingBox] = Factory(list) ``` ### voxel_size ``` voxel_size: tuple[float, float, float] ``` Voxel dimensions in nanometers (x, y, z). Proxies to skeleton.voxel_size. ### voxel_size_with_unit ``` voxel_size_with_unit: VoxelSize ``` ### zoom_level ``` zoom_level: float | None = None ``` ### add_volume_layer ``` add_volume_layer( name: str, dtype: DTypeLike, fallback_layer: Layer | str | None = None, volume_layer_id: int | None = None, ) -> VolumeLayer ``` Adds a new volume layer to the annotation. Volume layers can be used to store segmentation data. Using fallback layers is recommended for better performance in WEBKNOSSOS. Parameters: - **`name`** (`str`) – Name of the volume layer. - **`dtype`** (`DTypeLike`) – Datatype of the volume layer. - **`fallback_layer`** (`Layer | str | None`, default: `None` ) – Optional reference to existing segmentation layer in WEBKNOSSOS. Can be Layer instance or layer name. - **`volume_layer_id`** (`int | None`, default: `None` ) – Optional explicit ID for the layer. Auto-generated if not provided. Raises: - `AssertionError` – If volume_layer_id already exists. - `AssertionError` – If fallback_layer is provided but not a segmentation layer. Examples: ``` # Add basic layer annotation.add_volume_layer("segmentation", dtype=np.uint32) # Add with fallback annotation.add_volume_layer("segmentation", fallback_layer="base_segmentation", dtype=np.uint32) ``` ### delete_volume_layer ``` delete_volume_layer( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> None ``` Removes a volume layer from the annotation. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of the layer to delete if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of the layer to delete if multiple exist. Raises: - `ValueError` – If neither name nor ID is provided when multiple layers exist. - `AssertionError` – If specified layer doesn't exist. Examples: ``` # Delete by name annotation.delete_volume_layer("unused_layer") # Delete by ID annotation.delete_volume_layer(volume_layer_id=2) ``` ### download ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False ) -> Annotation ``` ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False, _return_context: bool ) -> tuple[Annotation, AbstractContextManager[None]] ``` ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False, retry_count: int = 5, _return_context: bool = False ) -> Union[ Annotation, tuple[Annotation, AbstractContextManager[None]], ] ``` Downloads an annotation from WEBKNOSSOS. Parameters: - **`annotation_id_or_url`** (`str`) – Either an annotation ID or complete WEBKNOSSOS URL. Example URL: https://webknossos.org/annotations/[id] - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. - **`skip_volume_data`** (`bool`, default: `False` ) – If True, omits downloading volume layer data. - **`_return_context`** (`bool`, default: `False` ) – Internal use only. Returns: - **`Annotation`** ( `Union[Annotation, tuple[Annotation, AbstractContextManager[None]]]` ) – The downloaded annotation instance. Examples: ``` # Download by ID ann = Annotation.download("5f7d3a...") # Download by URL ann = Annotation.download("https://webknossos.org/annotations/5f7d3a...") # Skip volume data ann = Annotation.download("5f7d3a...", skip_volume_data=True) ``` ### export_volume_layer_to_dataset ``` export_volume_layer_to_dataset( dataset: Dataset, layer_name: str = "volume_layer", volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> SegmentationLayer ``` Exports a volume layer to a dataset. Creates a new layer in the target dataset containing the volume annotation data. Parameters: - **`dataset`** (`Dataset`) – Target Dataset instance. - **`layer_name`** (`str`, default: `'volume_layer'` ) – Name for the new layer (default: "volume_layer"). - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of source volume layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of source volume layer if multiple exist. Returns: - **`SegmentationLayer`** ( `SegmentationLayer` ) – The created layer in the target dataset. Raises: - `AssertionError` – If specified volume layer doesn't exist. - `AssertionError` – If volume layer data is not available. Examples: ``` # Export to dataset layer = annotation.export_volume_layer_to_dataset( dataset, layer_name="exported_segmentation" ) ``` ### get_remote_annotation_dataset ``` get_remote_annotation_dataset() -> RemoteDataset ``` Returns a streamed dataset of the annotation from WEBKNOSSOS. Creates a remote dataset that includes fallback layers and potentially any active agglomerate mappings. Requires the annotation to be already stored in WEBKNOSSOS. Returns: - **`Dataset`** ( `RemoteDataset` ) – Remote dataset instance representing the annotation. Raises: - `ValueError` – If annotation_id is not set (annotation not in WEBKNOSSOS). Examples: ``` # Stream annotation as dataset dataset = annotation.get_remote_annotation_dataset() # Access layers layer = dataset.get_layer("segmentation") ``` Notes: After an agglomerate mapping was activated in WEBKNOSSOS, it is applied to this method as soon as the first volume editing action is done. Note that this behavior might change in the future. ### get_remote_base_dataset ``` get_remote_base_dataset( sharing_token: str | None = None, webknossos_url: str | None = None, ) -> RemoteDataset ``` Returns a remote dataset connection to the base dataset. Creates a connection to the dataset referenced by this annotation. Parameters: - **`sharing_token`** (`str | None`, default: `None` ) – Optional token for accessing private datasets. - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. Returns: - **`RemoteDataset`** ( `RemoteDataset` ) – Connection to the base dataset. Examples: ``` # Connect to base dataset dataset = annotation.get_remote_base_dataset() # With sharing token dataset = annotation.get_remote_base_dataset( sharing_token="abc123" ) ``` ### get_volume_layer ``` get_volume_layer( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> VolumeLayer ``` ### get_volume_layer_names ``` get_volume_layer_names() -> Iterable[str] ``` Returns names of all volume layers in the annotation. Returns: - `Iterable[str]` – Iterable\[str\]: Iterator of volume layer names. Examples: ``` # Print all layer names for name in annotation.get_volume_layer_names(): print(f"Found layer: {name}") ``` ### get_volume_layer_segments ``` get_volume_layer_segments( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> dict[int, SegmentInformation] ``` Returns segment information for a volume layer. Returns a mutable dictionary mapping segment IDs to their metadata. Changes to the returned dictionary are reflected in the annotation locally. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of the target volume layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of the target volume layer if multiple exist. Returns: - `dict[int, SegmentInformation]` – dict\[int, SegmentInformation\]: Dictionary mapping segment IDs to their information. Raises: - `ValueError` – If neither name nor ID is provided when multiple layers exist. - `AssertionError` – If specified layer doesn't exist. Examples: ``` # Get segments for a layer segments = annotation.get_volume_layer_segments("segmentation_layer") # Update segment name segments[1].name = "Cell A" ``` Notes: Any changes performed on the online version of the annotaiton in webknossos are not synced automatically. The annotation needs to be re-downloaded to update segment information. ### load ``` load(annotation_path: str | PathLike | UPath) -> Annotation ``` Loads an annotation from a file. Supports loading from: - .nml files (skeleton-only annotations) - .zip files (containing .nml and optional volume layers) Parameters: - **`annotation_path`** (`str | PathLike | UPath`) – Path to the .nml or .zip file. Returns: - **`Annotation`** ( `Annotation` ) – The loaded annotation instance. Raises: - `AssertionError` – If the file doesn't exist or has invalid extension. - `RuntimeError` – If the file format is invalid. Examples: ``` # Load from NML ann = Annotation.load("annotation.nml") # Load from ZIP ann = Annotation.load("annotation.zip") ``` ### merge_fallback_layer ``` merge_fallback_layer( target: str | PathLike | UPath, dataset_directory: str | PathLike | UPath, volume_layer_name: str | None = None, executor: Executor | None = None, ) -> None ``` Merges volume annotations with their fallback layer. Creates a new dataset containing the merged result of volume annotations and fallback layer data. Parameters: - **`target`** (`str | PathLike | UPath`) – Output path for merged dataset. - **`dataset_directory`** (`str | PathLike | UPath`) – Directory containing the fallback dataset. - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of volume layer to merge if multiple exist. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel processing. Raises: - `AssertionError` – If no volume layers exist. - `AssertionError` – If specified volume layer doesn't exist. Examples: ``` # Merge annotations with fallback annotation.merge_fallback_layer( Path("merged_dataset"), Path("original_dataset") ) ``` ### open_as_remote_dataset ``` open_as_remote_dataset( annotation_id_or_url: str, webknossos_url: str | None = None, ) -> RemoteDataset ``` Opens an annotation directly as a remote dataset from WEBKNOSSOS. This is a convenience method that combines downloading an annotation and converting it to a remote dataset in one step. It's useful when you want to work with the annotation data as a dataset without storing it locally. Parameters: - **`annotation_id_or_url`** (`str`) – Either an annotation ID or complete WEBKNOSSOS URL. Example URL: https://webknossos.org/annotations/[id] - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. Returns: - **`Dataset`** ( `RemoteDataset` ) – A remote dataset instance representing the annotation. Examples: ``` # Open by ID dataset = Annotation.open_as_remote_dataset("5f7d3a...") # Open by URL dataset = Annotation.open_as_remote_dataset( "https://webknossos.org/annotations/5f7d3a..." ) # Access layers layer = dataset.get_layer("segmentation") ``` Notes This method automatically skips downloading volume data locally for efficiency, as the data will be streamed from the remote source. ### open_remote ``` open_remote( annotation_id_or_url: str, webknossos_url: str | None = None, ) -> RemoteAnnotation ``` ### save ``` save(path: str | PathLike | UPath) -> None ``` Saves the annotation to a file. For skeleton-only annotations, saves as .nml file. For annotations with volume layers, saves as .zip file containing .nml and layers. Parameters: - **`path`** (`str | PathLike | UPath`) – Target path ending in .nml or .zip (.zip required if annotation contains volume layers) Raises: - `AssertionError` – If path has invalid extension or trying to save volume layers to .nml file. Examples: ``` # Save skeleton-only annotation annotation.save("skeleton.nml") # Save with volume layers annotation.save("full_annotation.zip") ``` ### temporary_volume_layer_copy ``` temporary_volume_layer_copy( volume_layer_name: str | None = None, volume_layer_id: int | None = None, read_only: bool = True, ) -> Iterator[SegmentationLayer] ``` Creates a temporary copy of a volume layer as a dataset. Context manager that provides temporary access to volume layer data as a SegmentationLayer. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of target layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of target layer if multiple exist. - **`read_only`** (`bool`, default: `True` ) – If True, prevents modifications to the layer. Yields: - **`SegmentationLayer`** ( `SegmentationLayer` ) – Temporary layer containing volume data. Examples: ``` # Temporarily access volume data with annotation.temporary_volume_layer_copy("segmentation") as layer: data = layer.get_mag(1).read() ``` ### upload ``` upload() -> str ``` Uploads the annotation to WEBKNOSSOS. Uses the current webknossos_context for authentication and target instance. See webknossos.webknossos_context() for configuration. Returns: - **`str`** ( `str` ) – URL of the uploaded annotation in WEBKNOSSOS. Raises: - `RuntimeError` – If no valid authentication is configured. Examples: ``` with webknossos.webknossos_context(token="my_token"): url = annotation.upload() print(f"Uploaded to: {url}") ``` ## AnnotationState Bases: `Enum` This Enum contains the state of annotations belonging to tasks. Can be retrieved via `Task` instances, getting `AnnotationInfo` from `task.get_annotation_infos()`. ### ACTIVE ``` ACTIVE = 'Active' ``` ### CANCELLED ``` CANCELLED = 'Cancelled' ``` ### FINISHED ``` FINISHED = 'Finished' ``` ### INITIALIZING ``` INITIALIZING = 'Initializing' ``` ## AnnotationType Bases: `Enum` Annotations can be of different types which has to be specified when using `Annotation.download()` with an annotation id. ### EXPLORATIONAL ``` EXPLORATIONAL = 'Explorational' ``` **Explorational** annotations are all annotations created without the task system, e.g. by uploading an annotation or using the "Create Annotation" Button in the dataset view in webknossos. ### TASK ``` TASK = 'Task' ``` The **Task** type is automatically assigned to all annotations that are instances of a task. See also `Task`. ## RemoteAnnotation ``` RemoteAnnotation( annotation_id: str, organization_id: str, dataset_id: str | None = None, *, name: str, skeleton: Skeleton, owner_name: str, time: int | None = None, edit_position: Vector3 | None = None, edit_rotation: Vector3 | None = None, zoom_level: float | None = None, task_bounding_box: NDBoundingBox | None = None, user_bounding_boxes: list[NDBoundingBox] | None = None, metadata: dict[str, str] = {} ) ``` Bases: `Annotation` A remote Annotation instance. Note: Please not initialize this class directly, use Annotation.open_remote() instead. ### annotation_id ``` annotation_id = annotation_id ``` ### dataset_id ``` dataset_id = dataset_id ``` ### dataset_name ``` dataset_name: str ``` Name of the dataset this annotation belongs to. Proxies to skeleton.dataset_name. ### description ``` description: str | None ``` ### edit_position ``` edit_position = edit_position ``` ### edit_rotation ``` edit_rotation = edit_rotation ``` ### metadata ``` metadata = metadata ``` ### name ``` name: str ``` ### organization_id ``` organization_id = organization_id ``` ### owner_name ``` owner_name = owner_name ``` ### skeleton ``` skeleton = skeleton ``` ### task_bounding_box ``` task_bounding_box = task_bounding_box ``` ### time ``` time = time ``` ### url ``` url: str ``` ### user_bounding_boxes ``` user_bounding_boxes = user_bounding_boxes or [] ``` ### voxel_size ``` voxel_size: tuple[float, float, float] ``` Voxel dimensions in nanometers (x, y, z). Proxies to skeleton.voxel_size. ### voxel_size_with_unit ``` voxel_size_with_unit: VoxelSize ``` ### zoom_level ``` zoom_level = zoom_level ``` ### add_volume_layer ``` add_volume_layer( name: str, dtype: DTypeLike, fallback_layer: Layer | str | None = None, volume_layer_id: int | None = None, ) -> VolumeLayer ``` Adds a new volume layer to the annotation. Volume layers can be used to store segmentation data. Using fallback layers is recommended for better performance in WEBKNOSSOS. Parameters: - **`name`** (`str`) – Name of the volume layer. - **`dtype`** (`DTypeLike`) – Datatype of the volume layer. - **`fallback_layer`** (`Layer | str | None`, default: `None` ) – Optional reference to existing segmentation layer in WEBKNOSSOS. Can be Layer instance or layer name. - **`volume_layer_id`** (`int | None`, default: `None` ) – Optional explicit ID for the layer. Auto-generated if not provided. Raises: - `AssertionError` – If volume_layer_id already exists. - `AssertionError` – If fallback_layer is provided but not a segmentation layer. Examples: ``` # Add basic layer annotation.add_volume_layer("segmentation", dtype=np.uint32) # Add with fallback annotation.add_volume_layer("segmentation", fallback_layer="base_segmentation", dtype=np.uint32) ``` ### delete_volume_layer ``` delete_volume_layer( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> None ``` Removes a volume layer from the annotation. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of the layer to delete if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of the layer to delete if multiple exist. Raises: - `ValueError` – If neither name nor ID is provided when multiple layers exist. - `AssertionError` – If specified layer doesn't exist. Examples: ``` # Delete by name annotation.delete_volume_layer("unused_layer") # Delete by ID annotation.delete_volume_layer(volume_layer_id=2) ``` ### download ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False ) -> Annotation ``` ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False, _return_context: bool ) -> tuple[Annotation, AbstractContextManager[None]] ``` ``` download( annotation_id_or_url: str, webknossos_url: str | None = None, *, skip_volume_data: bool = False, retry_count: int = 5, _return_context: bool = False ) -> Union[ Annotation, tuple[Annotation, AbstractContextManager[None]], ] ``` Downloads an annotation from WEBKNOSSOS. Parameters: - **`annotation_id_or_url`** (`str`) – Either an annotation ID or complete WEBKNOSSOS URL. Example URL: https://webknossos.org/annotations/[id] - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. - **`skip_volume_data`** (`bool`, default: `False` ) – If True, omits downloading volume layer data. - **`_return_context`** (`bool`, default: `False` ) – Internal use only. Returns: - **`Annotation`** ( `Union[Annotation, tuple[Annotation, AbstractContextManager[None]]]` ) – The downloaded annotation instance. Examples: ``` # Download by ID ann = Annotation.download("5f7d3a...") # Download by URL ann = Annotation.download("https://webknossos.org/annotations/5f7d3a...") # Skip volume data ann = Annotation.download("5f7d3a...", skip_volume_data=True) ``` ### download_mesh ``` download_mesh( segment_id: int, output_dir: PathLike | UPath | str, tracing_id: str, mesh_file_name: str | None = None, lod: int = 0, mapping_name: str | None = None, mapping_type: ( Literal["agglomerate", "json"] | None ) = None, mag: MagLike | None = None, seed_position: Vec3IntLike | None = None, token: str | None = None, ) -> UPath ``` ### export_volume_layer_to_dataset ``` export_volume_layer_to_dataset( dataset: Dataset, layer_name: str = "volume_layer", volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> SegmentationLayer ``` Exports a volume layer to a dataset. Creates a new layer in the target dataset containing the volume annotation data. Parameters: - **`dataset`** (`Dataset`) – Target Dataset instance. - **`layer_name`** (`str`, default: `'volume_layer'` ) – Name for the new layer (default: "volume_layer"). - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of source volume layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of source volume layer if multiple exist. Returns: - **`SegmentationLayer`** ( `SegmentationLayer` ) – The created layer in the target dataset. Raises: - `AssertionError` – If specified volume layer doesn't exist. - `AssertionError` – If volume layer data is not available. Examples: ``` # Export to dataset layer = annotation.export_volume_layer_to_dataset( dataset, layer_name="exported_segmentation" ) ``` ### get_agglomerate_graph ``` get_agglomerate_graph( agglomerate_id: int, ) -> AgglomerateGraphData ``` ### get_agglomerate_graph_data ``` get_agglomerate_graph_data( agglomerate_id: int, ) -> AgglomerateGraphData ``` Get the agglomerate graph data for the specified agglomerate id. This works only for proofreading annotations that have only a single volume layer. Parameters: - **`agglomerate_id`** (`int`) – The id of the agglomerate to get the graph for. Returns: - **`AgglomerateGraphData`** ( `AgglomerateGraphData` ) – The agglomerate graph for the specified agglomerate id. - `AgglomerateGraphData` – The agglomerate graph has a vertex for all segments that belong to the agglomerate. - `AgglomerateGraphData` – Adjacent segments are connected by an edge. Raises: - `ValueError` – If the agglomerate id is not valid - `UnexpectedStatusError` – If the annotation does not have an editable mapping (is not a proofreading annotation) - `AssertionError` – If the annotation does not have exactly one volume layer ### get_remote_annotation_dataset ``` get_remote_annotation_dataset() -> RemoteDataset ``` Returns a streamed dataset of the annotation from WEBKNOSSOS. Creates a remote dataset that includes fallback layers and potentially any active agglomerate mappings. Requires the annotation to be already stored in WEBKNOSSOS. Returns: - **`Dataset`** ( `RemoteDataset` ) – Remote dataset instance representing the annotation. Raises: - `ValueError` – If annotation_id is not set (annotation not in WEBKNOSSOS). Examples: ``` # Stream annotation as dataset dataset = annotation.get_remote_annotation_dataset() # Access layers layer = dataset.get_layer("segmentation") ``` Notes: After an agglomerate mapping was activated in WEBKNOSSOS, it is applied to this method as soon as the first volume editing action is done. Note that this behavior might change in the future. ### get_remote_base_dataset ``` get_remote_base_dataset( sharing_token: str | None = None, webknossos_url: str | None = None, ) -> RemoteDataset ``` Returns a remote dataset connection to the base dataset. Creates a connection to the dataset referenced by this annotation. Parameters: - **`sharing_token`** (`str | None`, default: `None` ) – Optional token for accessing private datasets. - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. Returns: - **`RemoteDataset`** ( `RemoteDataset` ) – Connection to the base dataset. Examples: ``` # Connect to base dataset dataset = annotation.get_remote_base_dataset() # With sharing token dataset = annotation.get_remote_base_dataset( sharing_token="abc123" ) ``` ### get_volume_layer ``` get_volume_layer( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> VolumeLayer ``` ### get_volume_layer_names ``` get_volume_layer_names() -> Iterable[str] ``` Returns names of all volume layers in the annotation. Returns: - `Iterable[str]` – Iterable\[str\]: Iterator of volume layer names. Examples: ``` # Print all layer names for name in annotation.get_volume_layer_names(): print(f"Found layer: {name}") ``` ### get_volume_layer_segments ``` get_volume_layer_segments( volume_layer_name: str | None = None, volume_layer_id: int | None = None, ) -> dict[int, SegmentInformation] ``` Returns segment information for a volume layer. Returns a mutable dictionary mapping segment IDs to their metadata. Changes to the returned dictionary are reflected in the annotation locally. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of the target volume layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of the target volume layer if multiple exist. Returns: - `dict[int, SegmentInformation]` – dict\[int, SegmentInformation\]: Dictionary mapping segment IDs to their information. Raises: - `ValueError` – If neither name nor ID is provided when multiple layers exist. - `AssertionError` – If specified layer doesn't exist. Examples: ``` # Get segments for a layer segments = annotation.get_volume_layer_segments("segmentation_layer") # Update segment name segments[1].name = "Cell A" ``` Notes: Any changes performed on the online version of the annotaiton in webknossos are not synced automatically. The annotation needs to be re-downloaded to update segment information. ### load ``` load(annotation_path: str | PathLike | UPath) -> Annotation ``` Loads an annotation from a file. Supports loading from: - .nml files (skeleton-only annotations) - .zip files (containing .nml and optional volume layers) Parameters: - **`annotation_path`** (`str | PathLike | UPath`) – Path to the .nml or .zip file. Returns: - **`Annotation`** ( `Annotation` ) – The loaded annotation instance. Raises: - `AssertionError` – If the file doesn't exist or has invalid extension. - `RuntimeError` – If the file format is invalid. Examples: ``` # Load from NML ann = Annotation.load("annotation.nml") # Load from ZIP ann = Annotation.load("annotation.zip") ``` ### merge_fallback_layer ``` merge_fallback_layer( target: str | PathLike | UPath, dataset_directory: str | PathLike | UPath, volume_layer_name: str | None = None, executor: Executor | None = None, ) -> None ``` Merges volume annotations with their fallback layer. Creates a new dataset containing the merged result of volume annotations and fallback layer data. Parameters: - **`target`** (`str | PathLike | UPath`) – Output path for merged dataset. - **`dataset_directory`** (`str | PathLike | UPath`) – Directory containing the fallback dataset. - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of volume layer to merge if multiple exist. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel processing. Raises: - `AssertionError` – If no volume layers exist. - `AssertionError` – If specified volume layer doesn't exist. Examples: ``` # Merge annotations with fallback annotation.merge_fallback_layer( Path("merged_dataset"), Path("original_dataset") ) ``` ### open_as_remote_dataset ``` open_as_remote_dataset( annotation_id_or_url: str, webknossos_url: str | None = None, ) -> RemoteDataset ``` Opens an annotation directly as a remote dataset from WEBKNOSSOS. This is a convenience method that combines downloading an annotation and converting it to a remote dataset in one step. It's useful when you want to work with the annotation data as a dataset without storing it locally. Parameters: - **`annotation_id_or_url`** (`str`) – Either an annotation ID or complete WEBKNOSSOS URL. Example URL: https://webknossos.org/annotations/[id] - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom WEBKNOSSOS instance URL. Returns: - **`Dataset`** ( `RemoteDataset` ) – A remote dataset instance representing the annotation. Examples: ``` # Open by ID dataset = Annotation.open_as_remote_dataset("5f7d3a...") # Open by URL dataset = Annotation.open_as_remote_dataset( "https://webknossos.org/annotations/5f7d3a..." ) # Access layers layer = dataset.get_layer("segmentation") ``` Notes This method automatically skips downloading volume data locally for efficiency, as the data will be streamed from the remote source. ### open_remote ``` open_remote( annotation_id_or_url: str, webknossos_url: str | None = None, ) -> RemoteAnnotation ``` ### save ``` save(path: str | PathLike | UPath) -> None ``` ### temporary_volume_layer_copy ``` temporary_volume_layer_copy( volume_layer_name: str | None = None, volume_layer_id: int | None = None, read_only: bool = True, ) -> Iterator[SegmentationLayer] ``` Creates a temporary copy of a volume layer as a dataset. Context manager that provides temporary access to volume layer data as a SegmentationLayer. Parameters: - **`volume_layer_name`** (`str | None`, default: `None` ) – Name of target layer if multiple exist. - **`volume_layer_id`** (`int | None`, default: `None` ) – ID of target layer if multiple exist. - **`read_only`** (`bool`, default: `True` ) – If True, prevents modifications to the layer. Yields: - **`SegmentationLayer`** ( `SegmentationLayer` ) – Temporary layer containing volume data. Examples: ``` # Temporarily access volume data with annotation.temporary_volume_layer_copy("segmentation") as layer: data = layer.get_mag(1).read() ``` ### upload ``` upload() -> str ``` Uploads the annotation to WEBKNOSSOS. Uses the current webknossos_context for authentication and target instance. See webknossos.webknossos_context() for configuration. Returns: - **`str`** ( `str` ) – URL of the uploaded annotation in WEBKNOSSOS. Raises: - `RuntimeError` – If no valid authentication is configured. Examples: ``` with webknossos.webknossos_context(token="my_token"): url = annotation.upload() print(f"Uploaded to: {url}") ``` # webknossos.annotation ## AnnotationInfo Data class containing information about a WEBKNOSSOS annotation ### description ``` description: str ``` ### duration_in_seconds ``` duration_in_seconds: float | None ``` ### id ``` id: str ``` ### modified ``` modified: int | None ``` ### name ``` name: str ``` ### owner_id ``` owner_id: str | None ``` ### state ``` state: AnnotationState ``` ### type ``` type: AnnotationType ``` ### download_annotation ``` download_annotation() -> Annotation ``` Downloads and returns the annotation that is described by this AnnotationInfo object ### get_remote_annotations ``` get_remote_annotations( is_finished: bool | None = False, owner: str | None = None, ) -> list[AnnotationInfo] ``` Returns a list of AnnotationInfo objects for all annotations that belong to the current user (if owner is None). If owner is not None, only annotations of the specified owner are returned. # webknossos.annotation ## SegmentInformation ### anchor_position ``` anchor_position: Vec3Int | None ``` ### color ``` color: Vector4 | None ``` ### metadata ``` metadata: dict[str, str | int | float | Sequence[str]] ``` ### name ``` name: str | None ``` # webknossos.client ## webknossos_context ``` webknossos_context( url: str | None = None, token: str | None = None, timeout: int | None = None, api_version: int | None = None, ) ``` Bases: `ContextDecorator` Creates a new WEBKNOSSOS server context manager. Can be used as a context manager with 'with' or as a decorator. Parameters: - **`url`** (`str | None`, default: `None` ) – Base URL for WEBKNOSSOS server, defaults to https://webknossos.org. Taken from previous context if not specified. - **`token`** (`str | None`, default: `None` ) – Authentication token from https://webknossos.org/account/token. Must be specified explicitly. - **`timeout`** (`int | None`, default: `None` ) – Network request timeout in seconds, defaults to 1800 (30 min). Taken from previous context if not specified. - **`api_version`** (`int | None`, default: `None` ) – WEBKNOSSOS API version to use. Defaults to the previous context version. Examples: Using as context manager: ``` with webknossos_context(token="my_webknossos_token"): # code that interacts with webknossos ds.download(...) ``` Using as decorator: ``` @webknossos_context(token="my_webknossos_token") def my_func(): # code that interacts with webknossos ... ``` Note The url and timeout parameters will use values from the previous context (e.g. environment variables) if not specified explicitly. The token parameter must always be set explicitly. # webknossos.client # webknossos.client # webknossos.client # webknossos.client # webknossos.client # webknossos.client ## WkApiClient ``` WkApiClient( *, base_wk_url: str, timeout_seconds: float, headers: dict[str, str] | None = None ) ``` Bases: `AbstractApiClient` ### base_wk_url ``` base_wk_url = rstrip('/') ``` ### headers ``` headers = headers ``` ### timeout_seconds ``` timeout_seconds = timeout_seconds ``` ### url_prefix ``` url_prefix: str ``` ### webknossos_api_version ``` webknossos_api_version = webknossos_api_version ``` ### annotation_download ``` annotation_download( *, annotation_id: str, skip_volume_data: bool, retry_count: int = 0 ) -> tuple[bytes, str] ``` ### annotation_edit ``` annotation_edit( *, annotation_typ: str, annotation_id: str, annotation: ApiAnnotation ) -> None ``` ### annotation_info ``` annotation_info(*, annotation_id: str) -> ApiAnnotation ``` ### annotation_infos_by_task ``` annotation_infos_by_task( *, task_id: str ) -> list[ApiAnnotation] ``` ### annotation_list ``` annotation_list( *, is_finished: bool | None ) -> list[ApiAnnotation] ``` ### annotation_upload ``` annotation_upload( *, file_body: bytes, filename: str, createGroupForEachFile: bool ) -> ApiAnnotationUploadResult ``` ### build_info ``` build_info() -> ApiWkBuildInfo ``` ### dataset_add_attachment_as_ref ``` dataset_add_attachment_as_ref( *, dataset_id: str, compose_attachment: ApiDatasetComposeAttachment ) -> None ``` ### dataset_add_layer_as_ref ``` dataset_add_layer_as_ref( *, dataset_id: str, compose_layer: ApiDatasetComposeLayer ) -> None ``` ### dataset_add_mag_as_ref ``` dataset_add_mag_as_ref( *, dataset_id: str, compose_mag: ApiDatasetComposeMag ) -> None ``` ### dataset_configuration ``` dataset_configuration( *, dataset_id: str, volume_tracing_ids: list[str] ) -> DatasetViewConfiguration ``` ### dataset_explore_and_add_remote ``` dataset_explore_and_add_remote( *, dataset: ApiDatasetExploreAndAddRemote ) -> str ``` ### dataset_id_from_name ``` dataset_id_from_name( *, directory_name: str, organization_id: str ) -> str ``` ### dataset_info ``` dataset_info( *, dataset_id: str, sharing_token: str | None = None ) -> ApiDataset ``` ### dataset_is_valid_new_name ``` dataset_is_valid_new_name( *, dataset_name: str ) -> ApiDatasetIsValidNewNameResponse ``` ### dataset_list ``` dataset_list( *, is_active: bool | None, organization_id: str | None, name: str | None, folder_id: str | None ) -> list[ApiDataset] ``` ### dataset_sharing_token ``` dataset_sharing_token( *, dataset_id: str ) -> ApiSharingToken ``` ### dataset_update ``` dataset_update( *, dataset_id: str, dataset_updates: dict[str, Any] ) -> None ``` ### dataset_update_teams ``` dataset_update_teams( *, dataset_id: str, team_ids: list[str] ) -> None ``` ### datastore_list ``` datastore_list() -> list[ApiDataStore] ``` ### finish_ai_model_upload_to_path ``` finish_ai_model_upload_to_path(ai_model_id: str) -> None ``` ### finish_attachment_upload_to_path ``` finish_attachment_upload_to_path( dataset_id: str, layer_name: str, attachment_name: str, attachment_type: str, attachment_dataformat: str, common_storage_prefix: str | None = None, ) -> None ``` ### finish_dataset_upload_to_paths ``` finish_dataset_upload_to_paths(dataset_id: str) -> None ``` ### finish_mag_upload_to_paths ``` finish_mag_upload_to_paths( dataset_id: str, reserve_mag_upload_to_path_parameters: ApiReserveMagUploadToPathParameters, ) -> None ``` ### folder_add ``` folder_add( *, folder_name: str, parent_id: str ) -> ApiFolderWithParent ``` ### folder_delete ``` folder_delete(*, folder_id: str) -> None ``` ### folder_get ``` folder_get(*, folder_id: str) -> ApiFolder ``` ### folder_move ``` folder_move( *, folder_id: str, new_parent_id: str ) -> ApiFolderWithParent ``` ### folder_root ``` folder_root() -> ApiFolderWithParent ``` ### folder_tree ``` folder_tree() -> list[ApiFolderWithParent] ``` ### folder_update ``` folder_update( *, folder_id: str, folder: ApiFolderUpdate ) -> None ``` ### get_ai_model_info ``` get_ai_model_info(ai_model_id: str) -> ApiAiModel ``` ### get_task_type ``` get_task_type(*, task_type_id: str) -> ApiTaskType ``` ### health ``` health() -> None ``` ### post_multipart_with_json_response ``` post_multipart_with_json_response( route: str, response_type: type[T], multipart_data: RequestData | None = None, files: RequestFiles | None = None, ) -> T ``` ### project_create ``` project_create(*, project: ApiProjectCreate) -> ApiProject ``` ### project_delete ``` project_delete(*, project_id: str) -> None ``` ### project_info_by_id ``` project_info_by_id(*, project_id: str) -> ApiProject ``` ### project_info_by_name ``` project_info_by_name(*, project_name: str) -> ApiProject ``` ### project_update ``` project_update( *, project_id: str, project: ApiProjectCreate ) -> ApiProject ``` ### reserve_ai_model_upload_to_path ``` reserve_ai_model_upload_to_path( params: ApiReserveAiModelUploadToPathParameters, ) -> ApiAiModel ``` ### reserve_attachment_upload_to_path ``` reserve_attachment_upload_to_path( dataset_id: str, layer_name: str, attachment_name: str, attachment_type: str, attachment_dataformat: str, common_storage_prefix: str | None = None, overwrite_pending: bool = True, ) -> str ``` ### reserve_dataset_upload_to_paths ``` reserve_dataset_upload_to_paths( reserve_dataset_upload_to_path_parameters: ApiReserveDatasetUploadToPathsParameters, ) -> ApiReserveDatasetUploadToPathsResponse ``` ### reserve_dataset_upload_to_paths_for_preliminary ``` reserve_dataset_upload_to_paths_for_preliminary( dataset_id: str, reserve_dataset_upload_to_path_for_preliminary_parameters: ApiReserveDatasetUploadToPathsForPreliminaryParameters, ) -> ApiReserveDatasetUploadToPathsForPreliminaryResponse ``` ### reserve_mag_upload_to_paths ``` reserve_mag_upload_to_paths( dataset_id: str, reserve_mag_upload_to_path_parameters: ApiReserveMagUploadToPathParameters, ) -> str ``` ### short_link_by_key ``` short_link_by_key(*, key: str) -> ApiShortLink ``` ### task_delete ``` task_delete(*, task_id: str) -> None ``` ### task_info ``` task_info(*, task_id: str) -> ApiTask ``` ### task_infos_by_project_id_paginated ``` task_infos_by_project_id_paginated( *, project_id: str, limit: int | None, page_number: int | None ) -> tuple[list[ApiTask], int] ``` ### task_list ``` task_list() -> list[ApiTask] ``` ### task_type_create ``` task_type_create( *, task_type: ApiTaskTypeCreate ) -> ApiTaskType ``` ### task_type_delete ``` task_type_delete(*, task_type_id: str) -> None ``` ### task_type_list ``` task_type_list() -> list[ApiTaskType] ``` ### task_update ``` task_update( *, task_id: str, task_parameters: ApiTaskParameters ) -> ApiTask ``` ### tasks_create ``` tasks_create( *, task_parameters: list[ApiTaskParameters] ) -> ApiTaskCreationResult ``` ### tasks_create_from_files ``` tasks_create_from_files( *, nml_task_parameters: ApiNmlTaskParameters, annotation_files: list[tuple[str, bytes]] ) -> ApiTaskCreationResult ``` ### team_add ``` team_add(*, team: ApiTeamAdd) -> None ``` ### team_delete ``` team_delete(*, team_id: str) -> None ``` ### team_list ``` team_list() -> list[ApiTeam] ``` ### tracing_store ``` tracing_store() -> ApiTracingStore ``` ### url_from_route ``` url_from_route(route: str) -> str ``` ### user_by_id ``` user_by_id(*, user_id: str) -> ApiUser ``` ### user_current ``` user_current() -> ApiUser ``` ### user_list ``` user_list() -> list[ApiUser] ``` ### user_logged_time ``` user_logged_time( *, user_id: str ) -> ApiLoggedTimeGroupedByMonth ``` ### user_update ``` user_update(*, user: ApiUser) -> None ``` # webknossos.dataset # webknossos.dataset ## Dataset ``` Dataset( dataset_path: str | PathLike | UPath, voxel_size: tuple[float, float, float] | None = None, name: str | None = None, exist_ok: bool = False, *, voxel_size_with_unit: VoxelSize | None = None, read_only: bool = False ) ``` Bases: `AbstractDataset[Layer, SegmentationLayer]` A dataset is the entry point of the Dataset API. An existing dataset on disk can be opened or new datasets can be created. A dataset stores the data in `.wkw` files on disk with metadata in `datasource-properties.json`. The information in those files are kept in sync with the object. Each dataset consists of one or more layers (webknossos.dataset.layer.Layer), which themselves can comprise multiple magnifications (webknossos.dataset.mag_view.MagView). Examples: Create a new dataset: ``` ds = Dataset("path/to/dataset", voxel_size=(11.2, 11.2, 25)) ``` Open an existing dataset: ``` ds = Dataset.open("path/to/dataset") ``` Open a remote dataset: ``` ds = RemoteDataset.open("my_dataset", "organization_id") ``` Create a new dataset or open an existing one. Creates a new dataset and the associated `datasource-properties.json` if one does not exist. If the dataset already exists and exist_ok is True, it is opened (the provided voxel_size and name are asserted to match the existing dataset). Please use `Dataset.open` if you intend to open an existing dataset and don't want/need the creation behavior. Parameters: - **`dataset_path`** (`str | PathLike | UPath`) – Path where the dataset should be created/opened - **`voxel_size`** (`tuple[float, float, float] | None`, default: `None` ) – Optional tuple of floats (x, y, z) specifying voxel size in nanometers - **`name`** (`str | None`, default: `None` ) – Optional name for the dataset, defaults to last part of dataset_path if not provided - **`exist_ok`** (`bool`, default: `False` ) – Whether to open an existing dataset at the path rather than failing - **`voxel_size_with_unit`** (`VoxelSize | None`, default: `None` ) – Optional voxel size with unit specification - **`read_only`** (`bool`, default: `False` ) – Whether to open dataset in read-only mode Raises: - `RuntimeError` – If dataset exists and exist_ok=False - `AssertionError` – If opening existing dataset with mismatched voxel size or name ### default_view_configuration ``` default_view_configuration: DatasetViewConfiguration | None ``` Default view configuration for this dataset in webknossos. Controls how the dataset is displayed in webknossos when first opened by a user, including position, zoom level, rotation etc. Returns: - `DatasetViewConfiguration | None` – DatasetViewConfiguration | None: Current view configuration if set Examples: ``` ds.default_view_configuration = DatasetViewConfiguration( zoom=1.5, position=(100, 100, 100) ) ``` ### layers ``` layers: Mapping[str, LayerType] ``` Dictionary containing all layers of this dataset. Returns: - `Mapping[str, LayerType]` – dict\[str, Layer\]: Dictionary mapping layer names to Layer objects Examples: ``` for layer_name, layer in ds.layers.items(): print(layer_name) ``` ### name ``` name: str ``` Name of this dataset as specified in datasource-properties.json. Can be modified to rename the dataset. Changes are persisted to the properties file. Returns: - **`str`** ( `str` ) – Current dataset name Examples: ``` ds.name = "my_renamed_dataset" # Updates the name in properties file ``` ### path ``` path: UPath = path ``` ### read_only ``` read_only: bool ``` Whether this dataset is opened in read-only mode. When True, operations that would modify the dataset (adding layers, changing properties, etc.) are not allowed and will raise RuntimeError. Returns: - **`bool`** ( `bool` ) – True if dataset is read-only, False otherwise ### resolved_path ``` resolved_path: UPath ``` ### voxel_size ``` voxel_size: tuple[float, float, float] ``` Size of each voxel in nanometers along each dimension (x, y, z). Returns: - `tuple[float, float, float]` – tuple\[float, float, float\]: Size of each voxel in nanometers for x,y,z dimensions Examples: ``` vx, vy, vz = ds.voxel_size print(f"X resolution is {vx}nm") ``` ### voxel_size_with_unit ``` voxel_size_with_unit: VoxelSize ``` Size of voxels including unit information. Size of each voxel along each dimension (x, y, z), including unit specification. The default unit is nanometers. Returns: - **`VoxelSize`** ( `VoxelSize` ) – Object containing voxel sizes and their units ### ConversionLayerMapping Bases: `Enum` Strategies for mapping file paths to layers when importing images. These strategies determine how input image files are grouped into layers during dataset creation using `Dataset.from_images()`. If no strategy is provided, `INSPECT_SINGLE_FILE` is used as the default. If none of the pre-defined strategies fit your needs, you can provide a custom callable that takes a Path and returns a layer name string. Examples: Using default strategy: ``` ds = Dataset.from_images("images/", "dataset/") ``` Explicit strategy: ``` ds = Dataset.from_images( "images/", "dataset/", map_filepath_to_layer_name=ConversionLayerMapping.ENFORCE_SINGLE_LAYER ) ``` Custom mapping function: ``` ds = Dataset.from_images( "images/", "dataset/", map_filepath_to_layer_name=lambda p: p.stem ) ``` #### ENFORCE_LAYER_PER_FILE ``` ENFORCE_LAYER_PER_FILE = 'enforce_layer_per_file' ``` Creates a new layer for each input file. Useful for converting multiple 3D images or when each 2D image should become its own layer. #### ENFORCE_LAYER_PER_FOLDER ``` ENFORCE_LAYER_PER_FOLDER = 'enforce_layer_per_folder' ``` Groups files by their containing folder. Each folder becomes one layer. Useful for organized 2D image stacks. #### ENFORCE_LAYER_PER_TOPLEVEL_FOLDER ``` ENFORCE_LAYER_PER_TOPLEVEL_FOLDER = ( "enforce_layer_per_toplevel_folder" ) ``` Groups files by their top-level folder. Useful when multiple layers each have their stacks split across subfolders. #### ENFORCE_SINGLE_LAYER ``` ENFORCE_SINGLE_LAYER = 'enforce_single_layer' ``` Combines all input files into a single layer. Only useful when all images are 2D slices that should be combined. #### INSPECT_EVERY_FILE ``` INSPECT_EVERY_FILE = 'inspect_every_file' ``` Like INSPECT_SINGLE_FILE but determines strategy separately for each file. More flexible but slower for many files. #### INSPECT_SINGLE_FILE ``` INSPECT_SINGLE_FILE = 'inspect_single_file' ``` Default strategy. Inspects first image file to determine if data is 2D or 3D. For 2D data uses ENFORCE_LAYER_PER_FOLDER, for 3D uses ENFORCE_LAYER_PER_FILE. ### add_copy_layer ``` add_copy_layer( foreign_layer: ( str | PathLike | UPath | Layer | RemoteLayer ), new_layer_name: str | None = None, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, data_format: str | DataFormat | None = None, compress: bool | None = None, exists_ok: bool = False, executor: Executor | None = None, with_attachments: bool = True ) -> Layer ``` Deprecated. Use `Dataset.add_layer_as_copy` instead. ### add_fs_copy_layer ``` add_fs_copy_layer( foreign_layer: str | PathLike | UPath | Layer, new_layer_name: str | None = None, ) -> Layer ``` Deprecated. File-based copy is automatically used in `Dataset.add_layer_as_copy`. Copies the files at `foreign_layer` which belongs to another dataset to the current dataset via the filesystem. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied too. If new_layer_name is None, the name of the foreign layer is used. ### add_layer ``` add_layer( layer_name: str, category: LayerCategoryType, *, dtype: DTypeLike | None = None, dtype_per_channel: DTypeLike | None = None, num_channels: int | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, bounding_box: NDBoundingBox | None = None, **kwargs: Any ) -> Layer ``` Create a new layer in the dataset. Creates a new layer with the given name, category, and data type. Parameters: - **`layer_name`** (`str`) – Name for the new layer - **`category`** (`LayerCategoryType`) – Either 'color' or 'segmentation' - **`dtype`** (`DTypeLike | None`, default: `None` ) – Optional data type per channel, e.g. np.uint8 - **`dtype_per_channel`** (`DTypeLike | None`, default: `None` ) – Deprecated, use dtype. - **`num_channels`** (`int | None`, default: `None` ) – Number of channels (default 1) - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store data ('wkw', 'zarr', 'zarr3') - **`bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Optional initial bounding box of layer - **`**kwargs`** (`Any`, default: `{}` ) – Additional arguments: - largest_segment_id: For segmentation layers, initial largest ID - mappings: For segmentation layers, optional ID mappings Returns: - **`Layer`** ( `Layer` ) – The newly created layer Raises: - `IndexError` – If layer with given name already exists - `RuntimeError` – If invalid category specified - `AttributeError` – If both dtype and dtype_per_channel specified - `AssertionError` – If invalid layer name or WKW format used with remote dataset Examples: Create color layer: ``` layer = ds.add_layer( "my_raw_microscopy_layer", LayerCategoryType.COLOR_CATEGORY, dtype=np.uint8, ) ``` Create segmentation layer: ``` layer = ds.add_layer( "my_segmentation_labels", LayerCategoryType.SEGMENTATION_CATEGORY, dtype=np.uint64 ) ``` Note The dtype can be specified either per layer or per channel, but not both. If neither is specified, uint8 per channel is used by default. WKW format can only be used with local datasets. ### add_layer_as_copy ``` add_layer_as_copy( foreign_layer: ( str | PathLike | UPath | Layer | RemoteLayer ), new_layer_name: str | None = None, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, data_format: str | DataFormat | None = None, compress: bool | Zarr3Config | None = None, exists_ok: bool = False, executor: Executor | None = None, with_attachments: bool = True ) -> Layer ``` Copy layer from another dataset to this one. Creates a new layer in this dataset by copying data and metadata from a layer in another dataset. Parameters: - **`foreign_layer`** (`str | PathLike | UPath | Layer | RemoteLayer`) – Layer to copy (path or Layer object) - **`new_layer_name`** (`str | None`, default: `None` ) – Optional name for the new layer, uses original name if None - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of chunks for storage - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of shards for storage - **`chunks_per_shard`** (`Vec3IntLike | int | None`, default: `None` ) – Deprecated, use shard_shape. Optional number of chunks per shard - **`data_format`** (`str | DataFormat | None`, default: `None` ) – Optional format to store copied data ('wkw', 'zarr', etc.) - **`compress`** (`bool | Zarr3Config | None`, default: `None` ) – Optional whether to compress copied data - **`exists_ok`** (`bool`, default: `False` ) – Whether to overwrite existing layers - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel copying Returns: - **`Layer`** ( `Layer` ) – The newly created copy of the layer Raises: - `IndexError` – If target layer name already exists - `RuntimeError` – If dataset is read-only Examples: Copy layer keeping same name: ``` other_ds = Dataset.open("other/dataset") copied = ds.add_layer_as_copy(other_ds.get_layer("color")) ``` Copy with new name: ``` copied = ds.add_layer_as_copy( other_ds.get_layer("color"), new_layer_name="color_copy", compress=True ) ``` ### add_layer_as_ref ``` add_layer_as_ref( foreign_layer: ( str | PathLike | UPath | Layer | RemoteLayer ), new_layer_name: str | None = None, ) -> Layer ``` Add a layer from another dataset by reference. Creates a layer that references data from another dataset. The image data will be streamed on-demand when accessed. Parameters: - **`foreign_layer`** (`str | PathLike | UPath | Layer | RemoteLayer`) – Foreign layer to add (path or Layer object) - **`new_layer_name`** (`str | None`, default: `None` ) – Optional name for the new layer, uses original name if None Returns: - **`Layer`** ( `Layer` ) – The newly created layer referencing the foreign data Raises: - `IndexError` – If target layer name already exists - `AssertionError` – If trying to add non-remote layer or same origin dataset - `RuntimeError` – If dataset is read-only Examples: ``` ds = Dataset.open("other/dataset") foreign_ds = Dataset.open("my_dataset") new_layer = ds.add_layer_as_ref( foreign_ds.get_layer("color") ) ``` Note Changes to the original layer's properties afterwards won't affect this dataset. Data is only referenced, not copied. ### add_layer_for_existing_files ``` add_layer_for_existing_files( layer_name: str, category: LayerCategoryType, **kwargs: Any ) -> Layer ``` Create a new layer from existing data files. Adds a layer by discovering and incorporating existing data files that were created externally, rather than creating new ones. The layer properties are inferred from the existing files unless overridden. Parameters: - **`layer_name`** (`str`) – Name for the new layer - **`category`** (`LayerCategoryType`) – Layer category ('color' or 'segmentation') - **`**kwargs`** (`Any`, default: `{}` ) – Additional arguments: - num_channels: Override detected number of channels - dtype: Override detected data type - dtype_per_channel: Deprecated, use dtype instead - data_format: Override detected data format - bounding_box: Override detected bounding box Returns: - **`Layer`** ( `Layer` ) – The newly created layer referencing the existing files Raises: - `AssertionError` – If layer already exists or no valid files found - `RuntimeError` – If dataset is read-only Examples: Basic usage: ``` layer = ds.add_layer_for_existing_files( "external_data", "color" ) ``` Override properties: ``` layer = ds.add_layer_for_existing_files( "segmentation_data", "segmentation", dtype=np.uint64 ) ``` Note The data files must already exist in the dataset directory under the layer name. Files are analyzed to determine properties like data type and number of channels. Magnifications are discovered automatically. ### add_layer_from_images ``` add_layer_from_images( images: Union[ str, FramesSequence, list[str | PathLike | UPath] ], layer_name: str, category: LayerCategoryType | None = "color", *, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, mag: MagLike = Mag(1), chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: int | Vec3IntLike | None = None, compress: bool = True, topleft: VecIntLike = zeros(), swap_xy: bool = False, flip_x: bool = False, flip_y: bool = False, flip_z: bool = False, dtype: DTypeLike | None = None, use_bioformats: bool = False, channel: int | None = None, timepoint: int | None = None, czi_channel: int | None = None, batch_size: int | None = None, allow_multiple_layers: bool = False, max_layers: int = 20, truncate_rgba_to_rgb: bool = True, executor: Executor | None = None ) -> Layer ``` Creates a new layer called `layer_name` with mag `mag` from `images`. `images` can be one of the following: - glob-string - list of paths - `pims.FramesSequence` instance Please see the [pims docs](http://soft-matter.github.io/pims/v0.6.1/opening_files.html) for more information. This method needs extra packages like tifffile or pylibczirw. Please install the respective extras, e.g. using `pip install "webknossos[all]"`. Further Arguments: - `category`: `color` by default, may be set to "segmentation" - `data_format`: by default zarr3 files are written, may be set to "wkw" or "zarr" to write in these formats. - `mag`: magnification to use for the written data - `chunk_shape`, `chunks_per_shard`, `shard_shape`, `compress`: adjust how the data is stored on disk - `topleft`: set an offset in Mag(1) to start writing the data, only affecting the output - `swap_xy`: set to `True` to interchange x and y axis before writing to disk - `flip_x`, `flip_y`, `flip_z`: set to `True` to reverse the respective axis before writing to disk - `dtype`: the read image data will be convertoed to this dtype using `numpy.ndarray.astype` - `use_bioformats`: set to `True` to only use the [pims bioformats adapter](https://soft-matter.github.io/pims/v0.6.1/bioformats.html) directly, needs a JVM, set to `False` to forbid using the bioformats adapter. Defaults to `False`. - `channel`: may be used to select a single channel, if multiple are available - `timepoint`: for timeseries, select a timepoint to use by specifying it as an int, starting from 0 - `czi_channel`: may be used to select a channel for .czi images, which differs from normal color-channels - `batch_size`: size to process the images (influences RAM consumption), must be a multiple of the chunk-size z-axis for uncompressed and the shard-size z-axis for compressed layers, default is the chunk-size or shard-size respectively - `allow_multiple_layers`: set to `True` if timepoints or channels may result in multiple layers being added (only the first is returned) - `max_layers`: only applies if `allow_multiple_layers=True`, limits the number of layers added via different channels or timepoints - `truncate_rgba_to_rgb`: only applies if `allow_multiple_layers=True`, set to `False` to write four channels into layers instead of an RGB channel - `executor`: pass a `ClusterExecutor` instance to parallelize the conversion jobs across the batches ### add_layer_like ``` add_layer_like( other_layer: Layer | RemoteLayer, layer_name: str ) -> Layer ``` ### add_remote_layer ``` add_remote_layer( foreign_layer: ( str | PathLike | UPath | Layer | RemoteLayer ), new_layer_name: str | None = None, ) -> Layer ``` Deprecated. Use `Dataset.add_layer_as_ref` instead. ### add_symlink_layer ``` add_symlink_layer( foreign_layer: str | PathLike | UPath | Layer, new_layer_name: str | None = None, *, make_relative: bool = False ) -> Layer ``` Deprecated. Use `Dataset.add_layer_as_ref` instead. Create symbolic link to layer from another dataset. Instead of copying data, creates a symbolic link to the original layer's data and copies only the layer metadata. Changes to the original layer's properties, e.g. bounding box, afterwards won't affect this dataset and vice-versa. Parameters: - **`foreign_layer`** (`str | PathLike | UPath | Layer`) – Layer to link to (path or Layer object) - **`make_relative`** (`bool`, default: `False` ) – Whether to create relative symlinks - **`new_layer_name`** (`str | None`, default: `None` ) – Optional name for the linked layer, uses original name if None Returns: - **`Layer`** ( `Layer` ) – The newly created symbolic link layer Raises: - `IndexError` – If target layer name already exists - `AssertionError` – If trying to create symlinks in/to remote datasets - `RuntimeError` – If dataset is read-only Examples: ``` other_ds = Dataset.open("other/dataset") linked = ds.add_symlink_layer( other_ds.get_layer("color"), make_relative=True ) ``` Note Only works with local file systems, cannot link remote datasets or create symlinks in remote datasets. ### calculate_bounding_box ``` calculate_bounding_box() -> NDBoundingBox ``` Calculate the enclosing bounding box of all layers. Finds the smallest box that contains all data from all layers in the dataset. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box containing all layer data Examples: ``` bbox = ds.calculate_bounding_box() print(f"Dataset spans {bbox.size} voxels") print(f"Dataset starts at {bbox.topleft}") ``` ### compress ``` compress(*, executor: Executor | None = None) -> None ``` Compress all uncompressed magnifications in-place. Compresses the data of all magnification levels that aren't already compressed, for all layers in the dataset. Parameters: - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel compression Raises: - `RuntimeError` – If dataset is read-only Examples: ``` ds.compress() ``` Note If data is already compressed, this will have no effect. ### copy_dataset ``` copy_dataset( new_dataset_path: str | PathLike | UPath, *, voxel_size: tuple[float, float, float] | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, data_format: str | DataFormat | None = None, compress: bool | None = None, exists_ok: bool = False, executor: Executor | None = None, voxel_size_with_unit: VoxelSize | None = None, layers_to_ignore: Iterable[str] | None = None ) -> Dataset ``` Creates an independent copy of the dataset with all layers at a new location. Data storage parameters can be customized for the copied dataset. Parameters: - **`new_dataset_path`** (`str | PathLike | UPath`) – Path where new dataset should be created - **`voxel_size`** (`tuple[float, float, float] | None`, default: `None` ) – Optional tuple of floats (x,y,z) specifying voxel size in nanometers - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of chunks for data storage - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of shards for data storage - **`chunks_per_shard`** (`Vec3IntLike | int | None`, default: `None` ) – Deprecated, use shard_shape. Optional number of chunks per shard - **`data_format`** (`str | DataFormat | None`, default: `None` ) – Optional format to store data ('wkw', 'zarr', 'zarr3') - **`compress`** (`bool | None`, default: `None` ) – Optional whether to compress data - **`exists_ok`** (`bool`, default: `False` ) – Whether to overwrite existing datasets and layers - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel copying - **`voxel_size_with_unit`** (`VoxelSize | None`, default: `None` ) – Optional voxel size specification with units - **`layers_to_ignore`** (`Iterable[str] | None`, default: `None` ) – List of layer names to exclude from the copy Returns: - **`Dataset`** ( `Dataset` ) – The newly created copy Raises: - `AssertionError` – If trying to copy WKW layers to remote dataset Examples: Basic copy: ``` copied = ds.copy_dataset("path/to/copy") ``` Copy with different storage: ``` copied = ds.copy_dataset( "path/to/copy", data_format="zarr", compress=True ) ``` Note WKW layers can only be copied to datasets on local file systems. For remote datasets, use data_format='zarr3'. ### delete_layer ``` delete_layer(layer_name: str) -> None ``` Delete a layer from the dataset. Removes the layer's data and metadata from disk completely. This deletes both the datasource-properties.json entry and all data files for the layer. Parameters: - **`layer_name`** (`str`) – Name of layer to delete Raises: - `IndexError` – If no layer with the given name exists - `RuntimeError` – If dataset is read-only Examples: ``` ds.delete_layer("old_layer") print("Remaining layers:", list(ds.layers)) ``` ### download ``` download( dataset_name_or_url: str, *, organization_id: str | None = None, sharing_token: str | None = None, webknossos_url: str | None = None, bbox: BoundingBox | None = None, layers: list[str] | str | None = None, mags: list[Mag] | None = None, path: PathLike | UPath | str | None = None, exist_ok: bool = False ) -> Dataset ``` Downloads a dataset and returns the Dataset instance. - `dataset_name_or_url` may be a dataset name or a full URL to a dataset view, e.g. `https://webknossos.org/datasets/scalable_minds/l4_sample_dev/view` If a URL is used, `organization_id`, `webknossos_url` and `sharing_token` must not be set. - `organization_id` may be supplied if a dataset name was used in the previous argument, it defaults to your current organization from the `webknossos_context`. You can find your `organization_id` [here](https://webknossos.org/account/token). - `sharing_token` may be supplied if a dataset name was used and can specify a sharing token. - `webknossos_url` may be supplied if a dataset name was used, and allows to specify in which webknossos instance to search for the dataset. It defaults to the url from your current `webknossos_context`, using https://webknossos.org as a fallback. - `bbox`, `layers`, and `mags` specify which parts of the dataset to download. If nothing is specified the whole image, all layers, and all mags are downloaded respectively. - `path` and `exist_ok` specify where to save the downloaded dataset and whether to overwrite if the `path` exists. ### downsample ``` downsample( *, sampling_mode: SamplingModes = ANISOTROPIC, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, executor: Executor | None = None ) -> None ``` Generate downsampled magnifications for all layers. Creates lower resolution versions (coarser magnifications) of all layers that are not yet downsampled, up to the specified coarsest magnification. Parameters: - **`sampling_mode`** (`SamplingModes`, default: `ANISOTROPIC` ) – Strategy for downsampling (e.g. ANISOTROPIC, MAX) - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Optional maximum/coarsest magnification to generate - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default" (= "mode" for segmentation, "median" for color). - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel processing Raises: - `RuntimeError` – If dataset is read-only Examples: Basic downsampling: ``` ds.downsample() ``` With custom parameters: ``` ds.downsample( sampling_mode=SamplingModes.ANISOTROPIC, coarsest_mag=Mag(8), ) ``` Note - ANISOTROPIC sampling creates anisotropic downsampling until dataset is isotropic - Other modes like MAX, CONSTANT etc create regular downsampling patterns - If magnifications already exist they will not be regenerated ### from_images ``` from_images( input_path: str | PathLike | UPath, output_path: str | PathLike | UPath, voxel_size: tuple[float, float, float] | None = None, name: str | None = None, *, map_filepath_to_layer_name: ( ConversionLayerMapping | Callable[[UPath], str] ) = INSPECT_SINGLE_FILE, z_slices_sort_key: Callable[[UPath], Any] | None = None, voxel_size_with_unit: VoxelSize | None = None, layer_name: str | None = None, layer_category: LayerCategoryType | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: int | Vec3IntLike | None = None, compress: bool = True, swap_xy: bool = False, flip_x: bool = False, flip_y: bool = False, flip_z: bool = False, use_bioformats: bool = False, max_layers: int = 20, batch_size: int | None = None, executor: Executor | None = None ) -> Dataset ``` This method imports image data in a folder or from a file as a webknossos dataset. The image data can be 3D images (such as multipage tiffs) or stacks of 2D images. Multiple 3D images or image stacks are mapped to different layers based on the mapping strategy. The exact mapping is handled by the argument `map_filepath_to_layer_name`, which can be a pre-defined strategy from the enum `ConversionLayerMapping`, or a custom callable, taking a path of an image file and returning the corresponding layer name. All files belonging to the same layer name are then grouped. In case of multiple files per layer, those are usually mapped to the z-dimension. The order of the z-slices can be customized by setting `z_slices_sort_key`. For more fine-grained control, please create an empty dataset and use `add_layer_from_images`. Parameters: - **`input_path`** (`str | PathLike | UPath`) – Path to input image files - **`output_path`** (`str | PathLike | UPath`) – Output path for created dataset - **`voxel_size`** (`tuple[float, float, float] | None`, default: `None` ) – Optional tuple of floats (x,y,z) for voxel size in nm - **`name`** (`str | None`, default: `None` ) – Optional name for dataset - **`map_filepath_to_layer_name`** (`ConversionLayerMapping | Callable[[UPath], str]`, default: `INSPECT_SINGLE_FILE` ) – Strategy for mapping files to layers, either a ConversionLayerMapping enum value or callable taking Path and returning str - **`z_slices_sort_key`** (`Callable[[UPath], Any] | None`, default: `None` ) – Optional key function for sorting z-slices - **`voxel_size_with_unit`** (`VoxelSize | None`, default: `None` ) – Optional voxel size with unit specification - **`layer_name`** (`str | None`, default: `None` ) – Optional name for layer(s) - **`layer_category`** (`LayerCategoryType | None`, default: `None` ) – Optional category override (LayerCategoryType.color / LayerCategoryType.segmentation) - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store data in ('wkw'/'zarr'/'zarr3) - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional. Shape of chunks to store data in - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional. Shape of shards to store data in - **`chunks_per_shard`** (`int | Vec3IntLike | None`, default: `None` ) – Deprecated, use shard_shape. Optional. number of chunks per shard - **`compress`** (`bool`, default: `True` ) – Whether to compress the data - **`swap_xy`** (`bool`, default: `False` ) – Whether to swap x and y axes - **`flip_x`** (`bool`, default: `False` ) – Whether to flip the x axis - **`flip_y`** (`bool`, default: `False` ) – Whether to flip the y axis - **`flip_z`** (`bool`, default: `False` ) – Whether to flip the z axis - **`use_bioformats`** (`bool`, default: `False` ) – Whether to use bioformats for reading, defaults to False - **`max_layers`** (`int`, default: `20` ) – Maximum number of layers to create - **`batch_size`** (`int | None`, default: `None` ) – Size of batches for processing - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallelization Returns: - **`Dataset`** ( `Dataset` ) – The created dataset instance Examples: ``` ds = Dataset.from_images("path/to/images/", "path/to/dataset/", voxel_size=(1, 1, 1)) ``` Note This method needs extra packages like tifffile or pylibczirw. Install with `pip install "webknossos[all]"`. ### fs_copy_dataset ``` fs_copy_dataset( new_dataset_path: str | PathLike | UPath, *, exists_ok: bool = False, layers_to_ignore: Iterable[str] | None = None ) -> Dataset ``` Deprecated. File-based copy is automatically used by `Dataset.copy_dataset`. Creates an independent copy of the dataset with all layers at a new location. This method copies the files of the dataset as is and, therefore, might be faster than Dataset.copy_dataset, which decodes and encodes all the data. If you wish to change the data storage parameters, use Dataset.copy_dataset. Parameters: - **`new_dataset_path`** (`str | PathLike | UPath`) – Path where new dataset should be created - **`exists_ok`** (`bool`, default: `False` ) – Whether to overwrite existing datasets and layers - **`layers_to_ignore`** (`Iterable[str] | None`, default: `None` ) – List of layer names to exclude from the copy Returns: - **`Dataset`** ( `Dataset` ) – The newly created copy Raises: - `AssertionError` – If trying to copy WKW layers to remote dataset Examples: Basic copy: ``` copied = ds.fs_copy_dataset("path/to/copy") ``` Note WKW layers can only be copied to datasets on local file systems. ### get_color_layers ``` get_color_layers() -> list[LayerType] ``` Get all color layers in the dataset. Provides access to all layers with category 'color'. Useful when a dataset contains multiple color layers. Returns: - `list[LayerType]` – list\[Layer\]: List of all color layers in order Examples: Print all color layer names: ``` for layer in ds.get_color_layers(): print(layer.name) ``` Note If you need only a single color layer, consider using `get_layer()` with the specific layer name instead. ### get_layer ``` get_layer(layer_name: str) -> LayerType ``` Get a specific layer from this dataset. Parameters: - **`layer_name`** (`str`) – Name of the layer to retrieve Returns: - **`Layer`** ( `LayerType` ) – The requested layer object Raises: - `IndexError` – If no layer with the given name exists Examples: ``` color_layer = ds.get_layer("color") seg_layer = ds.get_layer("segmentation") ``` Note Use `layers` property to access all layers at once. ### get_or_add_layer ``` get_or_add_layer( layer_name: str, category: LayerCategoryType, *, dtype: DTypeLike | None = None, dtype_per_channel: DTypeLike | None = None, num_channels: int | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, **kwargs: Any ) -> LayerType ``` Get an existing layer or create a new one. Gets a layer with the given name if it exists, otherwise creates a new layer with the specified parameters. Parameters: - **`layer_name`** (`str`) – Name of the layer to get or create - **`category`** (`LayerCategoryType`) – Layer category ('color' or 'segmentation') - **`dtype`** (`DTypeLike | None`, default: `None` ) – Optional data type per channel - **`dtype_per_channel`** (`DTypeLike | None`, default: `None` ) – Deprecated, use dtype. - **`num_channels`** (`int | None`, default: `None` ) – Optional number of channels - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store data ('wkw', 'zarr', etc.) - **`**kwargs`** (`Any`, default: `{}` ) – Additional arguments passed to add_layer() Returns: - **`Layer`** ( `LayerType` ) – The existing or newly created layer Raises: - `AssertionError` – If existing layer's properties don't match specified parameters - `ValueError` – If both dtype and dtype_per_channel specified - `RuntimeError` – If invalid category specified Examples: ``` layer = ds.get_or_add_layer( "segmentation", LayerCategoryType.SEGMENTATION_CATEGORY, dtype=np.uint64, ) ``` Note The dtype can be specified either per layer or per channel, but not both. For existing layers, the parameters are validated against the layer properties. ### get_remote_datasets ``` get_remote_datasets( *, organization_id: str | None = None, tags: str | Sequence[str] | None = None, name: str | None = None, folder_id: RemoteFolder | str | None = None ) -> Mapping[str, RemoteDataset] ``` ### get_segmentation_layer ``` get_segmentation_layer( layer_name: str, ) -> SegmentationLayerType ``` Get a segmentation layer by name. Parameters: - **`layer_name`** (`str`) – Name of the layer to get Returns: - **`SegmentationLayer`** ( `SegmentationLayerType` ) – The segmentation layer ### get_segmentation_layers ``` get_segmentation_layers() -> list[SegmentationLayerType] ``` Get all segmentation layers in the dataset. Provides access to all layers with category 'segmentation'. Useful when a dataset contains multiple segmentation layers. Returns: - `list[SegmentationLayerType]` – list\[SegmentationLayer\]: List of all segmentation layers in order Examples: Print all segmentation layer names: ``` for layer in ds.get_segmentation_layers(): print(layer.name) ``` Note If you need only a single segmentation layer, consider using `get_layer()` with the specific layer name instead. ### open ``` open( dataset_path: str | PathLike | UPath, read_only: bool = False, ) -> Dataset ``` To open an existing dataset on disk, simply call `Dataset.open("your_path")`. This requires `datasource-properties.json` to exist in this folder. Based on the `datasource-properties.json`, a dataset object is constructed. Only layers and magnifications that are listed in the properties are loaded (even though there might exist more layers or magnifications on disk). The `dataset_path` refers to the top level directory of the dataset (excluding layer or magnification names). ### open_remote ``` open_remote( dataset_name_or_url: str | None = None, *, organization_id: str | None = None, sharing_token: str | None = None, webknossos_url: str | None = None, dataset_id: str | None = None, annotation_id: str | None = None, access_mode: RemoteAccessMode | None = None, read_only: bool = False, use_zarr_streaming: bool | None = None ) -> RemoteDataset ``` ### publish_to_preliminary_dataset ``` publish_to_preliminary_dataset( dataset_id: str, *, path_prefix: str | None = None, transfer_mode: TransferMode = COPY ) -> None ``` Copies or moves+symlinks the data to paths returned by WEBKNOSSOS The dataset needs to be in status "uploading". The dataset already exists in WEBKNOSSOS but has no dataset_properties. With the dataset_properties WEBKNOSSOS can reserve the paths. Args: dataset_id: The dataset_id of the already existing dataset path_prefix: The prefix of the storage path, can be used to select one of the storage path options. symlink_data_instead_of_copy: Set to true if the client has access to the same file system as the WEBKNOSSOS datastore. ### shallow_copy_dataset ``` shallow_copy_dataset( new_dataset_path: str | PathLike | UPath, *, name: str | None = None, layers_to_ignore: Iterable[str] | None = None, make_relative: bool | None = None ) -> Dataset ``` Create a new dataset that contains references to the layers, mags and attachments of another dataset. Useful for creating alternative views or exposing datasets to WEBKNOSOSS. Parameters: - **`new_dataset_path`** (`str | PathLike | UPath`) – Path where new dataset should be created - **`name`** (`str | None`, default: `None` ) – Optional name for the new dataset, uses original name if None - **`layers_to_ignore`** (`Iterable[str] | None`, default: `None` ) – Optional iterable of layer names to exclude - **`executor`** – Optional executor for copy operations Returns: - **`Dataset`** ( `Dataset` ) – The newly created dataset with linked layers Raises: - `RuntimeError` – If dataset is read-only Examples: Basic shallow copy: ``` linked = ds.shallow_copy_dataset("path/to/link") ``` With relative links excluding layers: ``` linked = ds.shallow_copy_dataset( "path/to/link", make_relative=True, layers_to_ignore=["temp_layer"] ) ``` ### trigger_dataset_import ``` trigger_dataset_import( directory_name: str, organization: str, token: str ) -> None ``` Deprecated. Use `Dataset.trigger_reload_in_datastore` instead. ### trigger_reload_in_datastore ``` trigger_reload_in_datastore( *, dataset_name_or_url: str | None = None, organization_id: str | None = None, webknossos_url: str | None = None, dataset_id: str | None = None, organization: str | None = None, datastore_url: str | None = None, token: str | None = None ) -> None ``` ### upload ``` upload( *, new_dataset_name: str | None = None, initial_team_ids: list[str] | None = None, folder: str | RemoteFolder | None = None, require_unique_name: bool = False, layers_to_link: ( Sequence[LayerToLink | RemoteLayer] | None ) = None, transfer_mode: TransferMode = HTTP, jobs: int | None = None, common_storage_path_prefix: str | None = None, folder_id: str | RemoteFolder | None = None ) -> RemoteDataset ``` Upload this dataset to webknossos. Creates database entries and sets access rights on the webknossos instance before the actual data upload. The client then copies the data directly to the returned paths. Parameters: - **`new_dataset_name`** (`str | None`, default: `None` ) – Name for the new dataset defaults to the current name. - **`initial_team_ids`** (`list[str] | None`, default: `None` ) – Optional list of team IDs to grant initial access - **`folder`** (`str | RemoteFolder | None`, default: `None` ) – Optional ID of folder where dataset should be placed - **`require_unique_name`** (`bool`, default: `False` ) – Whether to make request fail in case a dataset with the name already exists - **`layers_to_link`** (`Sequence[LayerToLink | RemoteLayer] | None`, default: `None` ) – Optional list of LayerToLink to link already published layers to the dataset. - **`jobs`** (`int | None`, default: `None` ) – Optional number of jobs to use for uploading the data. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is either COPY or MOVE_AND_SYMLINK to select one of the available WEBKNOSSOS storages. - **`folder_id`** (`str | RemoteFolder | None`, default: `None` ) – Deprecated, use folder instead. Returns: RemoteDataset: Reference to the newly created remote dataset Note: upload_directly_to_common_storage is typically only used by administrators with direct file system or S3 access to the WEBKNOSSOS datastore. Most users should let upload_directly_to_common_storage to default to False Examples: ``` remote_ds = ds.upload( "my_dataset", ["team_a", "team_b"], "folder_123" ) print(remote_ds.url) ``` Link existing layers: ``` link = LayerToLink.from_remote_layer(existing_layer) remote_ds = ds.upload(layers_to_link=[link]) ``` ### write_layer ``` write_layer( layer_name: str, category: LayerCategoryType, data: ndarray, *, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, downsample: bool = True, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, axes: Iterable[str] | None = None, absolute_offset: Vec3IntLike | VecIntLike | None = None, mag: MagLike = Mag(1) ) -> Layer ``` Write a numpy array to a new layer and downsample. Parameters: - **`layer_name`** (`str`) – Name of the new layer. - **`category`** (`LayerCategoryType`) – Category of the new layer. - **`data`** (`ndarray`) – The data to write. - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store the data. Defaults to zarr3. - **`downsample`** (`bool`, default: `True` ) – Whether to downsample the data. Defaults to True. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. If specified, chunks_per_shard must not be specified. Defaults to (1024, 1024, 1024). - **`chunks_per_shard`** (`Vec3IntLike | int | None`, default: `None` ) – Deprecated, use shard_shape. Number of chunks per shards. If specified, shard_shape must not be specified. - **`axes`** (`Iterable[str] | None`, default: `None` ) – The axes of the data for non-3D data. - **`absolute_offset`** (`Vec3IntLike | VecIntLike | None`, default: `None` ) – The offset of the data. Specified in Mag 1. - **`mag`** (`MagLike`, default: `Mag(1)` ) – Magnification to write the data at. # webknossos.dataset ## RemoteAccessMode Bases: `Enum` Determines how data of a remote dataset is accessed. Note that DIRECT_PATH can only be used if the client has access to the underlying storage. ### DIRECT_PATH ``` DIRECT_PATH = 'direct_path' ``` ### PROXY_PATH ``` PROXY_PATH = 'proxy_path' ``` ### ZARR_STREAMING ``` ZARR_STREAMING = 'zarr_streaming' ``` ## RemoteDataset ``` RemoteDataset( *, zarr_streaming_path: UPath | None, dataset_properties: DatasetProperties | None, dataset_id: str, annotation_id: str | None, context: webknossos_context, read_only: bool ) ``` Bases: `AbstractDataset[RemoteLayer, RemoteSegmentationLayer]` A representation of a dataset managed by a WEBKNOSSOS server. This class is returned from `RemoteDataset.open()` and provides read-only access to image data streamed from the webknossos server. It uses the same interface as `Dataset` but additionally allows metadata manipulation through properties. In case of zarr streaming, an even smaller subset of metadata manipulation is possible. Properties metadata: Dataset metadata as key-value pairs name: Human readable name description: Dataset description tags: Dataset tags is_public: Whether dataset is public sharing_token: Dataset sharing token allowed_teams: Teams with dataset access folder: Dataset folder location Examples: Opening a remote dataset with organization ID: ``` ds = RemoteDataset.open("my_dataset", "org_id") ``` Opening with dataset URL: ``` ds = RemoteDataset.open("https://webknossos.org/datasets/org/dataset/view") ``` Setting metadata: ``` ds.metadata = {"key": "value", "tags": ["tag1", "tag2"]} ds.name = "My_Dataset" ds.allowed_teams = [Team.get_by_name("Lab_A")] ``` Note Do not instantiate directly, use `RemoteDataset.open()` or `RemoteDataset.open_remote` instead. Initialize a remote dataset instance. Parameters: - **`zarr_streaming_path`** (`UPath | None`) – Path to the zarr streaming directory - **`dataset_properties`** (`DatasetProperties | None`) – Properties of the remote dataset - **`dataset_id`** (`str`) – dataset id of the remote dataset - **`context`** (`webknossos_context`) – Context manager for WEBKNOSSOS connection Raises: - `FileNotFoundError` – If dataset cannot be opened as zarr format and no metadata exists Note Do not call this constructor directly, use RemoteDataset.open() instead. This class provides access to remote WEBKNOSSOS datasets with additional metadata manipulation. ### allowed_teams ``` allowed_teams: tuple[Team, ...] ``` Teams that are allowed to access this dataset. Controls which teams have read access to view and use this dataset. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `tuple[Team, ...]` – tuple\[Team, ...\]: Teams currently having access Examples: ``` from webknossos import Team team = Team.get_by_name("Lab_A") ds.allowed_teams = [team] print([t.name for t in ds.allowed_teams]) # Give access to multiple teams: ds.allowed_teams = [ Team.get_by_name("Lab_A"), Team.get_by_name("Lab_B") ] ``` Note - Teams must be from the same organization as the dataset - Can be set using Team objects or team ID strings - An empty list makes the dataset private ### annotation_id ``` annotation_id: str | None ``` ### created ``` created: str ``` Creation date of the dataset. Returns: - **`str`** ( `str` ) – Date and time when dataset was created ### dataset_id ``` dataset_id: str ``` ### default_view_configuration ``` default_view_configuration: DatasetViewConfiguration | None ``` Default view configuration for this dataset in webknossos. Controls how the dataset is displayed in webknossos when first opened by a user, including position, zoom level, rotation etc. Returns: - `DatasetViewConfiguration | None` – DatasetViewConfiguration | None: Current view configuration if set Examples: ``` ds.default_view_configuration = DatasetViewConfiguration( zoom=1.5, position=(100, 100, 100) ) ``` ### description ``` description: str | None ``` Free-text description of the dataset. Can be edited with markdown formatting. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `str | None` – str | None: Current description if set, None otherwise Examples: ``` ds.description = "Dataset acquired on *June 1st*" ds.description = None # Remove description ``` ### display_name ``` display_name: str ``` Deprecated, please use `name`. The human-readable name for the dataset in the webknossos interface. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `str` – str | None: Current display name if set, None otherwise Examples: ``` remote_ds.name = "Mouse Brain Sample A" ``` ### folder ``` folder: RemoteFolder ``` The (virtual) folder containing this dataset in WEBKNOSSOS. Represents the folder location in the WEBKNOSSOS UI folder structure. Can be changed to move the dataset to a different folder. Changes are immediately synchronized with WEBKNOSSOS. Returns: - **`RemoteFolder`** ( `RemoteFolder` ) – Current folder containing the dataset Examples: ``` folder = RemoteFolder.get_by_path("Datasets/Published") ds.folder = folder print(ds.folder.path) # 'Datasets/Published' ``` ### is_public ``` is_public: bool ``` Control whether the dataset is publicly accessible. When True, anyone can view the dataset without logging in to WEBKNOSSOS. Changes are immediately synchronized with WEBKNOSSOS. Returns: - **`bool`** ( `bool` ) – True if dataset is public, False if private Examples: ``` ds.is_public = True ds.is_public = False print("Public" if ds.is_public else "Private") # Private ``` ### layers ``` layers: Mapping[str, LayerType] ``` Dictionary containing all layers of this dataset. Returns: - `Mapping[str, LayerType]` – dict\[str, Layer\]: Dictionary mapping layer names to Layer objects Examples: ``` for layer_name, layer in ds.layers.items(): print(layer_name) ``` ### metadata ``` metadata: DatasetMetadata ``` Get or set metadata key-value pairs for the dataset. The metadata can contain strings, numbers, and lists of strings as values. Changes are immediately synchronized with WEBKNOSSOS. Returns: - **`DatasetMetadata`** ( `DatasetMetadata` ) – Current metadata key-value pairs Examples: ``` ds.metadata = { "species": "mouse", "age_days": 42, "tags": ["verified", "published"] } print(ds.metadata["species"]) ``` ### name ``` name: str ``` The human-readable name for the dataset in the webknossos interface. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `str` – str | None: Current display name if set, None otherwise Examples: ``` remote_ds.name = "Mouse Brain Sample A" ``` ### read_only ``` read_only: bool ``` Whether this dataset is opened in read-only mode. When True, operations that would modify the dataset (adding layers, changing properties, etc.) are not allowed and will raise RuntimeError. Returns: - **`bool`** ( `bool` ) – True if dataset is read-only, False otherwise ### sharing_token ``` sharing_token: str ``` Get a new token for sharing access to this dataset. Each call generates a fresh token that allows viewing the dataset without logging in. The token can be appended to dataset URLs as a query parameter. Returns: - **`str`** ( `str` ) – Fresh sharing token for dataset access Examples: ``` token = ds.sharing_token url = f"{ds.url}?token={token}" print("Share this link:", url) ``` Note - A new token is generated on each access - The token provides read-only access - Anyone with the token can view the dataset ### tags ``` tags: tuple[str, ...] ``` User-assigned tags for organizing and filtering datasets. Tags allow categorizing and filtering datasets in the webknossos dashboard interface. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `tuple[str, ...]` – tuple\[str, ...\]: Currently assigned tags, in string tuple form Examples: ``` ds.tags = ["verified", "published"] print(ds.tags) # ('verified', 'published') ds.tags = [] # Remove all tags ``` ### url ``` url: str ``` URL to access this dataset in webknossos. Constructs the full URL to the dataset in the webknossos web interface. Returns: - **`str`** ( `str` ) – Full dataset URL including organization and dataset name Examples: ``` print(ds.url) # 'https://webknossos.org/datasets/my_org/my_dataset' ``` ### used_storage_bytes ``` used_storage_bytes: int ``` The amount of storage used by the dataset on the WEBKNOSSOS server. Note that 0 may indicate that the data is either not stored on the WEBKNOSSOS server directly, or that the storage usage was not yet scanned. Returns: - **`int`** ( `int` ) – The amount of storage used by the dataset in bytes. ### voxel_size ``` voxel_size: tuple[float, float, float] ``` Size of each voxel in nanometers along each dimension (x, y, z). Returns: - `tuple[float, float, float]` – tuple\[float, float, float\]: Size of each voxel in nanometers for x,y,z dimensions Examples: ``` vx, vy, vz = ds.voxel_size print(f"X resolution is {vx}nm") ``` ### voxel_size_with_unit ``` voxel_size_with_unit: VoxelSize ``` Size of voxels including unit information. Size of each voxel along each dimension (x, y, z), including unit specification. The default unit is nanometers. Returns: - **`VoxelSize`** ( `VoxelSize` ) – Object containing voxel sizes and their units ### zarr_streaming_path ``` zarr_streaming_path = zarr_streaming_path ``` ### add_layer ``` add_layer( layer_name: str, category: LayerCategoryType, *, dtype: DTypeLike | None = None, dtype_per_channel: DTypeLike | None = None, num_channels: int | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, bounding_box: NDBoundingBox | None = None, **kwargs: Any ) -> RemoteLayer ``` ### add_layer_as_copy ``` add_layer_as_copy( foreign_layer: Union[ str, PathLike, UPath, Layer, RemoteLayer ], new_layer_name: str | None = None, *, data_format: str | DataFormat | None = None, exists_ok: bool = False, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, with_attachments: bool = True ) -> RemoteLayer ``` Copy a layer from another dataset to this remote dataset. Creates a new layer in this dataset by copying data and metadata from a layer in another dataset. Parameters: - **`foreign_layer`** (`Union[str, PathLike, UPath, Layer, RemoteLayer]`) – Layer to copy (path or Layer/RemoteLayer object) - **`new_layer_name`** (`str | None`, default: `None` ) – Optional name for the new layer, uses original name if None - **`data_format`** (`str | DataFormat | None`, default: `None` ) – Optional format to store copied data ('zarr', 'zarr3', etc.) - **`exists_ok`** (`bool`, default: `False` ) – Whether to overwrite existing layers - **`transfer_mode`** (`TransferMode`, default: `COPY` ) – How data is transferred to remote storage. Defaults to COPY. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix to select one of the available WEBKNOSSOS storages. - **`overwrite_pending`** (`bool`, default: `True` ) – If there are already pending/unfinished committed mags on the server, overwrite them. Defaults to True. - **`with_attachments`** (`bool`, default: `True` ) – Whether to copy attachments from segmentation layers. Defaults to True. Returns: - **`RemoteLayer`** ( `RemoteLayer` ) – The newly created copy of the layer Raises: - `IndexError` – If target layer name already exists and exists_ok is False - `RuntimeError` – If dataset is read-only Examples: Copy layer keeping same name: ``` other_ds = Dataset.open("other/dataset") copied = remote_ds.add_layer_as_copy(other_ds.get_layer("color")) ``` Copy with new name: ``` copied = remote_ds.add_layer_as_copy( other_ds.get_layer("color"), new_layer_name="color_copy", ) ``` ### add_layer_as_ref ``` add_layer_as_ref( foreign_layer: Union[ str, PathLike, UPath, Layer, RemoteLayer ], *, new_layer_name: str | None = None ) -> RemoteLayer ``` Add a layer from another dataset by reference. Creates a layer that references data from a remote dataset. Parameters: - **`foreign_layer`** (`Union[str, PathLike, UPath, Layer, RemoteLayer]`) – Foreign layer to add (path or Layer object) - **`new_layer_name`** (`str | None`, default: `None` ) – Optional name for the new layer, uses original name if None Returns: - **`Layer`** ( `RemoteLayer` ) – The newly created remote layer referencing the foreign data Raises: - `IndexError` – If target layer name already exists - `AssertionError` – If trying to add non-remote layer or same origin dataset - `RuntimeError` – If dataset is read-only Examples: ``` remote_ds = RemoteDataset.open("https://webknossos.org/datasets/...") other_ds = RemoteDataset.open("https://webknossos.org/datasets/...") new_layer = remote_ds.add_layer_as_ref(other_ds.get_layer("color")) ``` Note Changes to the original layer's properties afterwards won't affect this dataset. Data is only referenced, not copied. ### calculate_bounding_box ``` calculate_bounding_box() -> NDBoundingBox ``` Calculate the enclosing bounding box of all layers. Finds the smallest box that contains all data from all layers in the dataset. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box containing all layer data Examples: ``` bbox = ds.calculate_bounding_box() print(f"Dataset spans {bbox.size} voxels") print(f"Dataset starts at {bbox.topleft}") ``` ### delete_layer ``` delete_layer(layer_name: str) -> None ``` ### download ``` download( *, sharing_token: str | None = None, bounding_box: BoundingBox | None = None, bbox: BoundingBox | None = None, layers: list[str] | str | None = None, mags: list[Mag] | None = None, data_format: DataFormat | None = None, path: PathLike | UPath | str | None = None, exist_ok: bool = False ) -> Dataset ``` Downloads a dataset and returns the Dataset instance. * `sharing_token` may be supplied if a dataset name was used and can specify a sharing token. * `bounding_box`, `layers`, and `mags` specify which parts of the dataset to download. If nothing is specified the whole image, all layers, and all mags are downloaded respectively. * `path` and `exist_ok` specify where to save the downloaded dataset and whether to overwrite if the `path` exists. * `data_format` specifies the data format of the downloaded dataset. ### download_mesh ``` download_mesh( segment_id: int, output_dir: PathLike | UPath | str, *, layer_name: str | None = None, mesh_file_name: str | None = None, datastore_url: str | None = None, lod: int = 0, mapping_name: str | None = None, mapping_type: ( Literal["agglomerate", "json"] | None ) = None, mag: MagLike | None = None, seed_position: Vec3Int | None = None, token: str | None = None, sharing_token: str | None = None ) -> UPath ``` ### downsample ``` downsample( *, sampling_mode: SamplingModes = ANISOTROPIC, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, executor: Executor | None = None ) -> None ``` Generate downsampled magnifications for all layers. Creates lower resolution versions (coarser magnifications) of all layers that are not yet downsampled, up to the specified coarsest magnification. Parameters: - **`sampling_mode`** (`SamplingModes`, default: `ANISOTROPIC` ) – Strategy for downsampling (e.g. ANISOTROPIC, MAX) - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Optional maximum/coarsest magnification to generate - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default" (= "mode" for segmentation, "median" for color). - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is either COPY or MOVE_AND_SYMLINK to select one of the available WEBKNOSSOS storages. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel processing Raises: - `RuntimeError` – If dataset is read-only Examples: Basic downsampling: ``` ds.downsample() ``` With custom parameters: ``` ds.downsample( sampling_mode=SamplingModes.ANISOTROPIC, coarsest_mag=Mag(8), ) ``` Note - ANISOTROPIC sampling creates anisotropic downsampling until dataset is isotropic - Other modes like MAX, CONSTANT etc create regular downsampling patterns - If magnifications already exist they will not be regenerated ### explore_and_add_remote ``` explore_and_add_remote( dataset_uri: str | PathLike | UPath, dataset_name: str, *, folder: str | RemoteFolder | None = None, folder_path: str | None = None ) -> RemoteDataset ``` Explore and add an external dataset as a remote dataset. Adds a dataset from an external location (e.g. S3, Google Cloud Storage, or HTTPs) to WEBKNOSSOS by inspecting its layout and metadata without copying the data. Parameters: - **`dataset_uri`** (`str | PathLike | UPath`) – URI pointing to the remote dataset location - **`dataset_name`** (`str`) – Name to register dataset under in WEBKNOSSOS - **`folder`** (`str | RemoteFolder | None`, default: `None` ) – Path in WEBKNOSSOS folder structure where dataset should appear - **`folder_path`** (`str | None`, default: `None` ) – Deprecated, use folder instead. Returns: - **`RemoteDataset`** ( `RemoteDataset` ) – The newly added dataset accessible via WEBKNOSSOS Examples: ``` remote = Dataset.explore_and_add_remote( "s3://bucket/dataset", "my_dataset", folder=RemoteFolder.get_by_path("Datasets/Research") ) ``` Note The dataset files must be accessible from the WEBKNOSSOS server for this to work. The data will be streamed through webknossos from the source. ### from_images ``` from_images( input_path: str | PathLike | UPath, voxel_size: tuple[float, float, float] | None = None, name: str | None = None, *, map_filepath_to_layer_name: Any = None, z_slices_sort_key: Callable[[UPath], Any] | None = None, voxel_size_with_unit: VoxelSize | None = None, layer_name: str | None = None, layer_category: LayerCategoryType | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: int | Vec3IntLike | None = None, compress: bool = True, swap_xy: bool = False, flip_x: bool = False, flip_y: bool = False, flip_z: bool = False, use_bioformats: bool = False, max_layers: int = 20, batch_size: int | None = None, executor: Executor | None = None, url: str | None = None, token: str | None = None, folder: str | RemoteFolder | None = None ) -> RemoteDataset ``` Convert images to a WEBKNOSSOS dataset, upload it, and return the RemoteDataset. This combines `Dataset.from_images` and `Dataset.upload` into a single step. Images are converted to a temporary local dataset which is then uploaded to the WEBKNOSSOS server. The temporary files are cleaned up automatically. Parameters: - **`input_path`** (`str | PathLike | UPath`) – Path to input image files - **`voxel_size`** (`tuple[float, float, float] | None`, default: `None` ) – Optional tuple of floats (x,y,z) for voxel size in nm - **`name`** (`str | None`, default: `None` ) – Optional name for the uploaded dataset - **`map_filepath_to_layer_name`** (`Any`, default: `None` ) – Strategy for mapping files to layers - **`z_slices_sort_key`** (`Callable[[UPath], Any] | None`, default: `None` ) – Optional key function for sorting z-slices - **`voxel_size_with_unit`** (`VoxelSize | None`, default: `None` ) – Optional voxel size with unit specification - **`layer_name`** (`str | None`, default: `None` ) – Optional name for layer(s) - **`layer_category`** (`LayerCategoryType | None`, default: `None` ) – Optional category override - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store data in - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of chunks - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Optional shape of shards - **`chunks_per_shard`** (`int | Vec3IntLike | None`, default: `None` ) – Deprecated, use shard_shape - **`compress`** (`bool`, default: `True` ) – Whether to compress the data - **`swap_xy`** (`bool`, default: `False` ) – Whether to swap x and y axes - **`flip_x`** (`bool`, default: `False` ) – Whether to flip the x axis - **`flip_y`** (`bool`, default: `False` ) – Whether to flip the y axis - **`flip_z`** (`bool`, default: `False` ) – Whether to flip the z axis - **`use_bioformats`** (`bool`, default: `False` ) – Whether to use bioformats for reading, defaults to False - **`max_layers`** (`int`, default: `20` ) – Maximum number of layers to create - **`batch_size`** (`int | None`, default: `None` ) – Size of batches for processing - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallelization - **`url`** (`str | None`, default: `None` ) – Optional WEBKNOSSOS server URL - **`token`** (`str | None`, default: `None` ) – Optional authentication token - **`folder`** (`str | RemoteFolder | None`, default: `None` ) – Optional WEBKNOSSOS folder path or RemoteFolder object Returns: - **`RemoteDataset`** ( `RemoteDataset` ) – The uploaded remote dataset Examples: ``` remote_ds = RemoteDataset.from_images( "path/to/images/", voxel_size=(11.0, 11.0, 20.0), name="my_dataset", url="https://webknossos.org", token="my_token", ) ``` ### get_color_layers ``` get_color_layers() -> list[LayerType] ``` Get all color layers in the dataset. Provides access to all layers with category 'color'. Useful when a dataset contains multiple color layers. Returns: - `list[LayerType]` – list\[Layer\]: List of all color layers in order Examples: Print all color layer names: ``` for layer in ds.get_color_layers(): print(layer.name) ``` Note If you need only a single color layer, consider using `get_layer()` with the specific layer name instead. ### get_layer ``` get_layer(layer_name: str) -> LayerType ``` Get a specific layer from this dataset. Parameters: - **`layer_name`** (`str`) – Name of the layer to retrieve Returns: - **`Layer`** ( `LayerType` ) – The requested layer object Raises: - `IndexError` – If no layer with the given name exists Examples: ``` color_layer = ds.get_layer("color") seg_layer = ds.get_layer("segmentation") ``` Note Use `layers` property to access all layers at once. ### get_or_add_layer ``` get_or_add_layer( layer_name: str, category: LayerCategoryType, *, dtype: DTypeLike | None = None, dtype_per_channel: DTypeLike | None = None, num_channels: int | None = None, data_format: str | DataFormat = DEFAULT_DATA_FORMAT, **kwargs: Any ) -> LayerType ``` Get an existing layer or create a new one. Gets a layer with the given name if it exists, otherwise creates a new layer with the specified parameters. Parameters: - **`layer_name`** (`str`) – Name of the layer to get or create - **`category`** (`LayerCategoryType`) – Layer category ('color' or 'segmentation') - **`dtype`** (`DTypeLike | None`, default: `None` ) – Optional data type per channel - **`dtype_per_channel`** (`DTypeLike | None`, default: `None` ) – Deprecated, use dtype. - **`num_channels`** (`int | None`, default: `None` ) – Optional number of channels - **`data_format`** (`str | DataFormat`, default: `DEFAULT_DATA_FORMAT` ) – Format to store data ('wkw', 'zarr', etc.) - **`**kwargs`** (`Any`, default: `{}` ) – Additional arguments passed to add_layer() Returns: - **`Layer`** ( `LayerType` ) – The existing or newly created layer Raises: - `AssertionError` – If existing layer's properties don't match specified parameters - `ValueError` – If both dtype and dtype_per_channel specified - `RuntimeError` – If invalid category specified Examples: ``` layer = ds.get_or_add_layer( "segmentation", LayerCategoryType.SEGMENTATION_CATEGORY, dtype=np.uint64, ) ``` Note The dtype can be specified either per layer or per channel, but not both. For existing layers, the parameters are validated against the layer properties. ### get_segmentation_layer ``` get_segmentation_layer( layer_name: str, ) -> SegmentationLayerType ``` Get a segmentation layer by name. Parameters: - **`layer_name`** (`str`) – Name of the layer to get Returns: - **`SegmentationLayer`** ( `SegmentationLayerType` ) – The segmentation layer ### get_segmentation_layers ``` get_segmentation_layers() -> list[SegmentationLayerType] ``` Get all segmentation layers in the dataset. Provides access to all layers with category 'segmentation'. Useful when a dataset contains multiple segmentation layers. Returns: - `list[SegmentationLayerType]` – list\[SegmentationLayer\]: List of all segmentation layers in order Examples: Print all segmentation layer names: ``` for layer in ds.get_segmentation_layers(): print(layer.name) ``` Note If you need only a single segmentation layer, consider using `get_layer()` with the specific layer name instead. ### list ``` list( organization_id: str | None = None, tags: str | Sequence[str] | None = None, name: str | None = None, folder: RemoteFolder | str | None = None, folder_id: RemoteFolder | str | None = None, ) -> Mapping[str, RemoteDataset] ``` Get all available datasets from the WEBKNOSSOS server. Returns a mapping of dataset ids to lazy-initialized RemoteDataset objects for all datasets visible to the specified organization or current user. Datasets can be further filtered by tags, name or folder. Parameters: - **`organization_id`** (`str | None`, default: `None` ) – Optional organization to get datasets from. Defaults to organization of logged in user. - **`tags`** (`str | Sequence[str] | None`, default: `None` ) – Optional tag(s) to filter datasets by. Can be a single tag string or sequence of tags. Only returns datasets with all specified tags. - **`name`** (`str | None`, default: `None` ) – Optional name to filter datasets by. Only returns datasets with matching name. - **`folder`** (`RemoteFolder | str | None`, default: `None` ) – Optional folder to filter datasets by. Only returns datasets in the specified folder. - **`folder_id`** (`RemoteFolder | str | None`, default: `None` ) – Deprecated, use folder instead. Returns: - `Mapping[str, RemoteDataset]` – Mapping\[str, RemoteDataset\]: Dict mapping dataset ids to RemoteDataset objects Examples: List all available datasets: ``` datasets = RemoteDataset.list() print(sorted(datasets.keys())) ``` Get datasets for specific organization: ``` org_datasets = RemoteDataset.list()("my_organization") ds = org_datasets["dataset_name"] ``` Filter datasets by tag: ``` published = RemoteDataset.list(tags="published") tagged = RemoteDataset.list(tags=["tag1", "tag2"]) ``` Filter datasets by name: ``` fun_datasets = RemoteDataset.list(name="MyFunDataset") ``` Note RemoteDataset objects are initialized lazily when accessed for the first time. The mapping object provides a fast way to list and look up available datasets. ### open ``` open( dataset_name_or_url: str | None = None, *, organization_id: str | None = None, sharing_token: str | None = None, webknossos_url: str | None = None, dataset_id: str | None = None, annotation_id_or_url: str | None = None, access_mode: RemoteAccessMode | None = None, read_only: bool = False, use_zarr_streaming: bool | None = None ) -> RemoteDataset ``` Opens a remote webknossos dataset. Image data is accessed via network requests. Dataset metadata such as allowed teams or the sharing token can be read and set via the respective `RemoteDataset` properties. Parameters: - **`dataset_name_or_url`** (`str | None`, default: `None` ) – Either dataset name or full URL to dataset view, e.g. https://webknossos.org/datasets/scalable_minds/l4_sample_dev/view - **`organization_id`** (`str | None`, default: `None` ) – Optional organization ID if using dataset name. Can be found here - **`sharing_token`** (`str | None`, default: `None` ) – Optional sharing token for dataset access - **`webknossos_url`** (`str | None`, default: `None` ) – Optional custom webknossos URL, defaults to context URL, usually https://webknossos.org - **`dataset_id`** (`str | None`, default: `None` ) – Optional unique ID of the dataset - **`annotation_id_or_url`** (`str | None`, default: `None` ) – Optional unique ID or URL of the annotation to stream the data from the annotation. - **`access_mode`** (`RemoteAccessMode | None`, default: `None` ) – Access mode for the dataset. Defaults to RemoteAccessMode.ZARR_STREAMING. - **`use_zarr_streaming`** (`bool | None`, default: `None` ) – Whether to use zarr streaming. Deprecated, use access_mode instead. Returns: - **`RemoteDataset`** ( `RemoteDataset` ) – Dataset instance for remote access Examples: ``` ds = RemoteDataset.open("`https://webknossos.org/datasets/scalable_minds/l4_sample_dev/view`") ``` Note If supplying an URL, organization_id, webknossos_url and sharing_token must not be set. ### reopen ``` reopen(*, access_mode: RemoteAccessMode) -> RemoteDataset ``` Reopens the dataset in the specified access mode. Parameters: - **`access_mode`** (`RemoteAccessMode`) – The access mode to reopen the dataset in. Returns: - `RemoteDataset` – The reopened dataset. ### trigger_reload_in_datastore ``` trigger_reload_in_datastore( *, dataset_name_or_url: str | None = None, organization_id: str | None = None, webknossos_url: str | None = None, dataset_id: str | None = None, organization: str | None = None, datastore_url: str | None = None, token: str | None = None ) -> None ``` Trigger a manual reload of the dataset's properties. For manually uploaded datasets, properties are normally updated automatically after a few minutes. This method forces an immediate reload. This is typically only needed after manual changes to the dataset's files. Cannot be used for local datasets. Parameters: - **`dataset_name_or_url`** (`str | None`, default: `None` ) – Name or URL of dataset to reload - **`dataset_id`** (`str | None`, default: `None` ) – ID of dataset to reload - **`organization_id`** (`str | None`, default: `None` ) – Organization ID where dataset is located - **`datastore_url`** (`str | None`, default: `None` ) – Optional URL to the datastore - **`webknossos_url`** (`str | None`, default: `None` ) – Optional URL to the webknossos server Examples: ``` # Force reload after manual file changes Dataset.trigger_reload_in_datastore( "my_dataset", "organization_id" ) ``` # webknossos.dataset # webknossos.dataset ## RemoteFolder This class is used to access and edit metadata of a folder on the webknossos server. ### allowed_teams ``` allowed_teams: tuple[Team, ...] ``` Teams that are allowed to access this folder. Controls which teams have read access to view and use this folder, as well as its datasets. Changes are immediately synchronized with WEBKNOSSOS. Returns: - `tuple[Team, ...]` – tuple\[Team, ...\]: Teams currently having access ### id ``` id: str ``` ### metadata ``` metadata: FolderMetadata ``` ### name ``` name: str ``` The name for the folder in the WEBKNOSSOS interface. Changes are immediately synchronized with WEBKNOSSOS. ### parent ``` parent: RemoteFolder | None ``` The parent folder of the folder in the WEBKNOSSOS interface. ### add_subfolder ``` add_subfolder(name: str) -> RemoteFolder ``` Adds a new folder with the specified name. ### delete ``` delete() -> None ``` Deletes the folder. ### get_by_id ``` get_by_id(folder_id: str) -> RemoteFolder ``` Returns the folder specified by the passed id. ### get_by_path ``` get_by_path(path: str) -> RemoteFolder ``` Returns the folder specified by the passed path. Separate multiple folder names with a slash. ### get_datasets ``` get_datasets() -> Mapping[str, RemoteDataset] ``` Returns all datasets in this folder. ### get_root ``` get_root() -> RemoteFolder ``` Returns the root folder of the current organization. ### get_subfolders ``` get_subfolders() -> tuple[RemoteFolder, ...] ``` Returns all subfolders in this folder. ### move_to ``` move_to(new_parent: RemoteFolder) -> RemoteFolder ``` Deprecated. Use `RemoteFolder.parent` instead. Move the folder to a new parent folder. This method returns a new `RemoteFolder` instance representing the moved folder. The original `RemoteFolder` object is not modified, so you should use the returned value. Parameters: - **`new_parent`** (`RemoteFolder`) – The new parent folder. Returns: - `RemoteFolder` – A new RemoteFolder instance in the new location. # webknossos.dataset ## SamplingModes Bases: `Enum` ### ANISOTROPIC ``` ANISOTROPIC = 'anisotropic' ``` ### CONSTANT_Z ``` CONSTANT_Z = 'constant_z' ``` ### ISOTROPIC ``` ISOTROPIC = 'isotropic' ``` ### parse ``` parse(mode: Union[str, SamplingModes]) -> SamplingModes ``` # webknossos.dataset ## TransferMode Bases: `str`, `Enum` The transfer mode determines how mags or attachments are transferred to the remote or local storage. ### COPY ``` COPY = 'copy' ``` ### HTTP ``` HTTP = 'http' ``` ### MOVE_AND_SYMLINK ``` MOVE_AND_SYMLINK = 'move+symlink' ``` ### SYMLINK ``` SYMLINK = 'symlink' ``` ### copy ``` copy( src_path: UPath, dst_path: UPath, progress_desc_label: str | None = None, ) -> None ``` ### move_and_symlink ``` move_and_symlink(src_path: UPath, dst_path: UPath) -> None ``` ### symlink ``` symlink(src_path: UPath, dst_path: UPath) -> None ``` ### transfer ``` transfer( src_path: UPath, dst_path: UPath, progress_desc_label: str | None = None, ) -> None ``` # webknossos.dataset # webknossos.dataset # webknossos.dataset # webknossos.dataset ## Layer ``` Layer( dataset: Dataset, properties: LayerProperties, read_only: bool, ) ``` Bases: `AbstractLayer` A Layer represents a portion of hierarchical data at multiple magnifications. A Layer consists of multiple MagViews, which store the same data in different magnifications. Layers are components of a Dataset and provide access to the underlying data arrays. Attributes: - **`name`** (`str`) – Name identifier for this layer - **`dataset`** (`Dataset`) – Parent dataset containing this layer - **`path`** (`Path`) – Filesystem path to this layer's data - **`category`** (`LayerCategoryType`) – Category of data (e.g. color, segmentation) - **`dtype`** (`dtype`) – Data type used per channel - **`num_channels`** (`int`) – Number of channels in the layer - **`data_format`** (`DataFormat`) – Format used to store the data - **`default_view_configuration`** (`LayerViewConfiguration | None`) – View configuration - **`read_only`** (`bool`) – Whether layer is read-only - **`mags`** (`dict[Mag, MagView]`) – Dictionary of magnification levels Parameters: - **`dataset`** (`Dataset`) – The parent dataset that contains this layer - **`properties`** (`LayerProperties`) – Properties defining this layer's attributes. Must contain num_channels. - **`read_only`** (`bool`) – Whether layer is read-only Raises: - `AssertionError` – If properties.num_channels is None Note Do not use this constructor manually. Instead use Dataset.add_layer() to create a Layer. ### bounding_box ``` bounding_box: NDBoundingBox ``` Gets the bounding box encompassing this layer's data. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box with layer dimensions ### category ``` category: LayerCategoryType ``` Gets the category type of this layer. Returns: - **`LayerCategoryType`** ( `LayerCategoryType` ) – Layer category (e.g. COLOR_CATEGORY) ### data_format ``` data_format: DataFormat ``` Gets the data storage format used by this layer. Returns: - **`DataFormat`** ( `DataFormat` ) – Format used to store data Raises: - `AssertionError` – If data_format is not set in properties ### dataset ``` dataset: Dataset ``` ### default_view_configuration ``` default_view_configuration: LayerViewConfiguration | None ``` Gets the default view configuration for this layer. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: View configuration if set, otherwise None ### dtype ``` dtype: dtype ``` Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### dtype_per_channel ``` dtype_per_channel: dtype ``` Deprecated. Use `dtype` instead. Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### is_foreign ``` is_foreign: bool ``` Whether this layer's data is stored remotely relative to its dataset. Returns: bool: True if layer path parent differs from dataset path ### is_remote_to_dataset ``` is_remote_to_dataset: bool ``` ### mags ``` mags: Mapping[Mag, MagView] ``` Getter for dictionary containing all mags. ### name ``` name: str ``` Returns the name of the layer. ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this layer. Returns: - **`int`** ( `int` ) – Number of channels Raises: - `AssertionError` – If num_channels is not set in properties ### path ``` path: UPath ``` Gets the filesystem path to this layer's data. This is defined as a subdirectory of the dataset directory named like the layer. Therefore, this directory does not contain the actual data of any linked or remote layers or mags. Returns: - **`UPath`** ( `UPath` ) – Filesystem path to this layer's data directory Raises: - `AssertionError` – If mags in layer point to different layers ### read_only ``` read_only: bool ``` Whether this layer is read-only. Returns: - **`bool`** ( `bool` ) – True if layer is read-only, False if writable ### resolved_path ``` resolved_path: UPath ``` ### add_copy_mag ``` add_copy_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | None = None, exists_ok: bool = False, executor: Executor | None = None, progress_desc: str | None = None ) -> MagView ``` Deprecated. Use `Layer.add_mag_as_copy` instead. ### add_fs_copy_mag ``` add_fs_copy_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, exists_ok: bool = False ) -> MagView[Layer] ``` Deprecated. File-copy is automatically selected when using `Layer.add_mag_as_copy`. Copies the data at `foreign_mag_view_or_path` which belongs to another dataset to the current dataset via the filesystem. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag ``` add_mag( mag: MagLike, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: int | Vec3IntLike | None = None, compress: bool | Zarr3Config = True ) -> MagView[Layer] ``` Creates and adds a new magnification level to the layer. The new magnification can be configured with various storage parameters to optimize performance, notably `chunk_shape`, `shard_shape` and `compress`. Note that writing data which is not aligned with the blocks on disk may result in diminished performance, as full blocks will automatically be read to pad the write actions. Parameters: - **`mag`** (`MagLike`) – Identifier for new magnification level - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. If specified, chunks_per_shard must not be specified. Defaults to (1024, 1024, 1024). - **`chunks_per_shard`** (`int | Vec3IntLike | None`, default: `None` ) – Deprecated, use shard_shape. Number of chunks per shards. If specified, shard_shape must not be specified. - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to enable compression. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. Returns: - **`MagView`** ( `MagView[Layer]` ) – View of newly created magnification level Raises: - `IndexError` – If magnification already exists - `Warning` – If chunk_shape is not optimal for WEBKNOSSOS performance ### add_mag_as_copy ``` add_mag_as_copy( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | Zarr3Config | None = None, exists_ok: bool = False, executor: Executor | None = None, progress_desc: str | None = None ) -> MagView[Layer] ``` Copies the data at `foreign_mag_view_or_path` which can belong to another dataset to the current dataset. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag_as_ref ``` add_mag_as_ref( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, mag: MagLike | None = None, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Adds the mag at `foreign_mag_view_or_path` which belongs to foreign dataset. The relevant information from the `datasource-properties.json` of the other dataset is copied to this dataset. Note: If the other dataset modifies its bounding box afterwards, the change does not affect this properties (or vice versa). ### add_mag_from_zarrarray ``` add_mag_from_zarrarray( mag: MagLike, path: PathLike | UPath, *, move: bool = False, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Copies the data at `path` to the current layer of the dataset via the filesystem and adds it as `mag`. When `move` flag is set the array is moved, otherwise a copy of the zarrarray is created. ### add_remote_mag ``` add_remote_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Deprecated. Use `Layer.add_mag_as_ref` instead. ### add_symlink_mag ``` add_symlink_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, make_relative: bool = False, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Deprecated. Use `Layer.add_mag_as_ref` instead. Creates a symlink to the data at `foreign_mag_view_or_path` which belongs to another dataset. The relevant information from the `datasource-properties.json` of the other dataset is copied to this dataset. Note: If the other dataset modifies its bounding box afterwards, the change does not affect this properties (or vice versa). If make_relative is True, the symlink is made relative to the current dataset path. Symlinked mags can only be added to layers on local file systems. ### as_segmentation_layer ``` as_segmentation_layer() -> SegmentationLayer ``` Casts into SegmentationLayer. ### delete_mag ``` delete_mag(mag: MagLike) -> None ``` Deletes the MagView from the `datasource-properties.json` and the data from disk. This function raises an `IndexError` if the specified `mag` does not exist. ### downsample ``` downsample( *, from_mag: Mag | None = None, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: Union[ bool, Dataset, RemoteDataset ] = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, force_sampling_scheme: bool = False, allow_overwrite: bool = False, only_setup_mags: bool = False, from_mag_view: MagView | None = None, executor: Executor | None = None ) -> None ``` Downsample data from a source magnification to coarser magnifications. Downsamples the data starting from from_mag until a magnification is >= max(coarsest_mag). Different sampling modes control how dimensions are downsampled. Parameters: - **`from_mag`** (`Mag | None`, default: `None` ) – Source magnification to downsample from. Defaults to highest existing mag. - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Target magnification to stop at. Defaults to calculated value. - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". Supported modes: "median", "mode", "nearest", "bilinear", "bicubic" - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress the generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be downsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool | Dataset | RemoteDataset`, default: `True` ) – Whether to align with other layers. True by default. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. Defaults to (1024, 1024, 1024). - **`force_sampling_scheme`** (`bool`, default: `False` ) – Force invalid sampling schemes. Defaults to False. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether existing mags can be overwritten. False by default. - **`only_setup_mags`** (`bool`, default: `False` ) – Only create mags without data. False by default. - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source magnification view, pass only if the source data should be from another layer or dataset. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. None by default. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `RuntimeError` – If sampling scheme produces invalid magnifications - `AttributeError` – If sampling_mode is invalid Examples: ``` from webknossos import SamplingModes # let 'layer' be a `Layer` with only `Mag(1)` assert "1" in self.mags.keys() layer.downsample( coarsest_mag=Mag(4), sampling_mode=SamplingModes.ISOTROPIC ) assert "2" in self.mags.keys() assert "4" in self.mags.keys() ``` ### downsample_mag ``` downsample_mag( from_mag: Mag, target_mag: Mag, *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, allow_overwrite: bool = False, only_setup_mag: bool = False, from_mag_view: MagView | None = None, executor: Executor | None = None ) -> None ``` Performs a single downsampling step between magnification levels. Parameters: - **`from_mag`** (`Mag`) – Source magnification level - **`target_mag`** (`Mag`) – Target magnification level - **`interpolation_mode`** (`str`, default: `'default'` ) – Method for interpolation ("median", "mode", "nearest", "bilinear", "bicubic") - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress target data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether to allow overwriting existing mag - **`only_setup_mag`** (`bool`, default: `False` ) – Only create mag without data. This parameter can be used to prepare for parallel downsampling of multiple layers while avoiding parallel writes with outdated updates to the datasource-properties.json file. - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source magnification view, pass only if the source data should be from another layer or dataset. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If target exists without overwrite - `ValueError` – If from_mag is greater than target_mag ### downsample_mag_list ``` downsample_mag_list( from_mag: Mag, target_mags: list[Mag], *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, allow_overwrite: bool = False, only_setup_mags: bool = False, executor: Executor | None = None ) -> None ``` Downsample data iteratively through multiple magnification levels. Performs sequential downsampling from from_mag through each magnification in target_mags in order. Parameters: - **`from_mag`** (`Mag`) – Source magnification to start from - **`target_mags`** (`List[Mag]`) – Ordered list of target magnifications - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress outputs. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether to allow overwriting mags. Defaults to False. - **`only_setup_mags`** (`bool`, default: `False` ) – Only create mag structures without data. Defaults to False. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If target mags not in ascending order See downsample_mag() for more details on parameters. ### get_finest_mag ``` get_finest_mag() -> MagView[Layer] ``` ### get_mag ``` get_mag(mag: MagLike) -> MagView[Layer] ``` ### get_or_add_mag ``` get_or_add_mag( mag: MagLike, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | Zarr3Config | None = None ) -> MagView[Layer] ``` Creates a new mag and adds it to the dataset, in case it did not exist before. Then, returns the mag. See `add_mag` for more information. ### is_mag_view_foreign ``` is_mag_view_foreign(mag: MagView) -> bool ``` Check if this magnification's data is stored not as part of to the dataset. Returns: bool: True if data is stored in a different location than the parent dataset. ### redownsample ``` redownsample( *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, executor: Executor | None = None ) -> None ``` Recompute all downsampled magnifications from base mag. Used after modifying data in the base magnification to update all derived magnifications. Parameters: - **`interpolation_mode`** (`str`, default: `'default'` ) – Method for interpolation - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress recomputed data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing ### upsample ``` upsample( from_mag: Mag, *, from_mag_view: MagView | None = None, finest_mag: Mag = Mag(1), compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: Union[bool, Dataset] = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, executor: Executor | None = None ) -> None ``` Upsample data to finer magnifications. Upsamples from a coarser magnification to a sequence of finer magnifications, stopping at finest_mag. The sampling mode controls how dimensions are handled. Parameters: - **`from_mag`** (`Mag`) – Source coarse magnification - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source coarse magnification view, pass only if the source data should be from another layer or dataset. - **`finest_mag`** (`Mag`, default: `Mag(1)` ) – Target finest magnification (default Mag(1)) - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress upsampled data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be upsampled: - 'anisotropic': Equalizes voxel dimensions based on voxel_size - 'isotropic': Equal upsampling in all dimensions - 'constant_z': Only upsamples x/y dimensions. z remains unchanged. - **`align_with_other_layers`** (`Union[bool, Dataset]`, default: `True` ) – Whether to align mags with others. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If finest_mag is invalid. - `AttributeError` – If sampling_mode is invalid # webknossos.dataset ## LayerToLink Bases: `NamedTuple` ### dataset_id ``` dataset_id: str ``` ### layer_name ``` layer_name: str ``` ### new_layer_name ``` new_layer_name: str | None = None ``` ### organization_id ``` organization_id: str | None = None ``` ### from_remote_layer ``` from_remote_layer( remote_layer: RemoteLayer, new_layer_name: str | None = None, ) -> LayerToLink ``` # webknossos.dataset ## RemoteLayer ``` RemoteLayer( dataset: RemoteDataset, properties: LayerProperties, read_only: bool, ) ``` Bases: `AbstractLayer` ### bounding_box ``` bounding_box: NDBoundingBox ``` Gets the bounding box encompassing this layer's data. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box with layer dimensions ### category ``` category: LayerCategoryType ``` Gets the category type of this layer. Returns: - **`LayerCategoryType`** ( `LayerCategoryType` ) – Layer category (e.g. COLOR_CATEGORY) ### data_format ``` data_format: DataFormat ``` Gets the data storage format used by this layer. Returns: - **`DataFormat`** ( `DataFormat` ) – Format used to store data Raises: - `AssertionError` – If data_format is not set in properties ### dataset ``` dataset: RemoteDataset ``` ### default_view_configuration ``` default_view_configuration: LayerViewConfiguration | None ``` Gets the default view configuration for this layer. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: View configuration if set, otherwise None ### dtype ``` dtype: dtype ``` Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### dtype_per_channel ``` dtype_per_channel: dtype ``` Deprecated. Use `dtype` instead. Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### mags ``` mags: Mapping[Mag, MagView] ``` Getter for dictionary containing all mags. ### name ``` name: str ``` Returns the name of the layer. ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this layer. Returns: - **`int`** ( `int` ) – Number of channels Raises: - `AssertionError` – If num_channels is not set in properties ### read_only ``` read_only: bool ``` Whether this layer is read-only. Returns: - **`bool`** ( `bool` ) – True if layer is read-only, False if writable ### view_configuration ``` view_configuration: LayerViewConfiguration | None ``` The current view configuration for this layer as stored on the WEBKNOSSOS server. This reflects the user-saved view settings (color, opacity, intensity range, etc.) and is distinct from `default_view_configuration`, which is default for all users accessing the dataset properties. The value is fetched from the server on every access. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: The saved view configuration, or None if none is set. Examples: ``` cfg = layer.view_configuration if cfg is not None: print(cfg.color, cfg.alpha) ``` ### add_mag_as_copy ``` add_mag_as_copy( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True ) -> MagView[RemoteLayer] ``` Copies the data at `foreign_mag_view_or_path` which can belong to another dataset to the current remote dataset. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag_as_ref ``` add_mag_as_ref( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, mag: MagLike | None = None, extend_layer_bounding_box: bool = True ) -> MagView[RemoteLayer] ``` Add a mag from another remote dataset by reference. Creates a mag that references data from a foreign remote layer without copying it. Parameters: - **`foreign_mag_view_or_path`** (`PathLike | UPath | str | MagView`) – Foreign mag to add (path or MagView object) - **`mag`** (`MagLike | None`, default: `None` ) – Target mag level; uses the foreign mag level if None - **`extend_layer_bounding_box`** (`bool`, default: `True` ) – If True, extends this layer's bounding box to include the foreign layer's bounding box Returns: - **`MagView`** ( `MagView[RemoteLayer]` ) – The newly created mag view referencing the foreign data Raises: - `ValueError` – If the foreign mag belongs to a local layer or a different WEBKNOSSOS instance ### as_segmentation_layer ``` as_segmentation_layer() -> RemoteSegmentationLayer ``` Casts into SegmentationLayer. ### delete_mag ``` delete_mag(mag: MagLike) -> None ``` ### downsample ``` downsample( *, from_mag: Mag | None = None, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: bool = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, force_sampling_scheme: bool = False, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, executor: Executor | None = None ) -> None ``` Downsample data from a source magnification to coarser magnifications. Downsamples the data starting from from_mag until a magnification is >= max(coarsest_mag). Different sampling modes control how dimensions are downsampled. Note that the data is written temporarily on the local disk and uploaded afterwards so some local disk space is required. Parameters: - **`from_mag`** (`Mag | None`, default: `None` ) – Source magnification to downsample from. Defaults to highest existing mag. - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Target magnification to stop at. Defaults to calculated value. - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". Supported modes: "median", "mode", "nearest", "bilinear", "bicubic" - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress the generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be downsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool`, default: `True` ) – Whether to align the mag selection with the dataset’s other layers. True by default. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`force_sampling_scheme`** (`bool`, default: `False` ) – Force invalid sampling schemes. Defaults to False. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is either COPY or MOVE_AND_SYMLINK to select one of the available WEBKNOSSOS storages. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. None by default. Raises: - `AssertionError` – If from_mag does not exist - `RuntimeError` – If sampling scheme produces invalid magnifications - `AttributeError` – If sampling_mode is invalid ### get_finest_mag ``` get_finest_mag() -> MagView[RemoteLayer] ``` ### get_mag ``` get_mag(mag: MagLike) -> MagView[RemoteLayer] ``` ### upsample ``` upsample( from_mag: Mag, *, finest_mag: Mag = Mag(1), compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: bool = True, buffer_shape: Vec3IntLike | None = None, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, executor: Executor | None = None ) -> None ``` Upsample data to finer magnifications. Upsamples from a coarser magnification to a sequence of finer magnifications, stopping at finest_mag. The data is written temporarily on the local disk and uploaded afterwards, so some local disk space is required. Parameters: - **`from_mag`** (`Mag`) – Source coarse magnification. - **`finest_mag`** (`Mag`, default: `Mag(1)` ) – Target finest magnification. Defaults to Mag(1). - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress upsampled data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be upsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool`, default: `True` ) – Whether to align mags with the dataset's other layers. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`transfer_mode`** (`TransferMode`, default: `COPY` ) – How new mags are transferred to the remote storage. Defaults to COPY. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is COPY or MOVE_AND_SYMLINK. - **`overwrite_pending`** (`bool`, default: `True` ) – If there are already pending/unfinished committed mags on the server, overwrite them. Defaults to True. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Defaults to None. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If finest_mag is invalid. - `AttributeError` – If sampling_mode is invalid. # webknossos.dataset # webknossos.dataset ## RemoteSegmentationLayer ``` RemoteSegmentationLayer( dataset: RemoteDataset, properties: SegmentationLayerProperties, read_only: bool, ) ``` Bases: `AbstractSegmentationLayer[RemoteAttachments]`, `RemoteLayer` ### attachments ``` attachments: AttachmentsTypeT ``` Access, add and remove the attachments of this layer. Attachments are additional files that can be attached to a segmentation layer. They can be used to store additional information, such as meshes, agglomerations, segment indices, cumsums and connectomes. Examples: ``` # Add a mesh attachment to the segmentation layer layer.attachments.add_attachment_as_ref( MeshAttachment.from_path_and_name( mesh_path, "meshfile", data_format=AttachmentDataFormat.Zarr3 ) ) # Access the mesh attachment path layer.attachments.meshes[0].path # Remove the mesh attachment layer.attachments.delete_attachment(layer.attachments.meshes[0]) ``` ### bounding_box ``` bounding_box: NDBoundingBox ``` Gets the bounding box encompassing this layer's data. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box with layer dimensions ### category ``` category: LayerCategoryType ``` ### data_format ``` data_format: DataFormat ``` Gets the data storage format used by this layer. Returns: - **`DataFormat`** ( `DataFormat` ) – Format used to store data Raises: - `AssertionError` – If data_format is not set in properties ### dataset ``` dataset: RemoteDataset ``` ### default_view_configuration ``` default_view_configuration: LayerViewConfiguration | None ``` Gets the default view configuration for this layer. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: View configuration if set, otherwise None ### dtype ``` dtype: dtype ``` Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### dtype_per_channel ``` dtype_per_channel: dtype ``` Deprecated. Use `dtype` instead. Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### largest_segment_id ``` largest_segment_id: int | None ``` Gets the largest segment ID present in the data. The largest segment ID is the highest numerical identifier assigned to any segment in this layer. This is useful for: - Allocating new segment IDs - Validating segment ID ranges - Optimizing data structures Returns: - `int | None` – int | None: The highest segment ID present, or None if no segments exist ### mags ``` mags: Mapping[Mag, MagView] ``` Getter for dictionary containing all mags. ### name ``` name: str ``` Returns the name of the layer. ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this layer. Returns: - **`int`** ( `int` ) – Number of channels Raises: - `AssertionError` – If num_channels is not set in properties ### read_only ``` read_only: bool ``` Whether this layer is read-only. Returns: - **`bool`** ( `bool` ) – True if layer is read-only, False if writable ### view_configuration ``` view_configuration: LayerViewConfiguration | None ``` The current view configuration for this layer as stored on the WEBKNOSSOS server. This reflects the user-saved view settings (color, opacity, intensity range, etc.) and is distinct from `default_view_configuration`, which is default for all users accessing the dataset properties. The value is fetched from the server on every access. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: The saved view configuration, or None if none is set. Examples: ``` cfg = layer.view_configuration if cfg is not None: print(cfg.color, cfg.alpha) ``` ### add_mag_as_copy ``` add_mag_as_copy( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True ) -> MagView[RemoteLayer] ``` Copies the data at `foreign_mag_view_or_path` which can belong to another dataset to the current remote dataset. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag_as_ref ``` add_mag_as_ref( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, mag: MagLike | None = None, extend_layer_bounding_box: bool = True ) -> MagView[RemoteLayer] ``` Add a mag from another remote dataset by reference. Creates a mag that references data from a foreign remote layer without copying it. Parameters: - **`foreign_mag_view_or_path`** (`PathLike | UPath | str | MagView`) – Foreign mag to add (path or MagView object) - **`mag`** (`MagLike | None`, default: `None` ) – Target mag level; uses the foreign mag level if None - **`extend_layer_bounding_box`** (`bool`, default: `True` ) – If True, extends this layer's bounding box to include the foreign layer's bounding box Returns: - **`MagView`** ( `MagView[RemoteLayer]` ) – The newly created mag view referencing the foreign data Raises: - `ValueError` – If the foreign mag belongs to a local layer or a different WEBKNOSSOS instance ### as_segmentation_layer ``` as_segmentation_layer() -> RemoteSegmentationLayer ``` Casts into SegmentationLayer. ### delete_mag ``` delete_mag(mag: MagLike) -> None ``` ### download_mesh ``` download_mesh( segment_id: int, output_dir: PathLike | UPath | str, mesh_file_name: str | None = None, datastore_url: str | None = None, lod: int = 0, mapping_name: str | None = None, mapping_type: ( Literal["agglomerate", "json"] | None ) = None, mag: MagLike | None = None, seed_position: Vec3IntLike | None = None, token: str | None = None, sharing_token: str | None = None, ) -> UPath ``` ### downsample ``` downsample( *, from_mag: Mag | None = None, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: bool = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, force_sampling_scheme: bool = False, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, executor: Executor | None = None ) -> None ``` Downsample data from a source magnification to coarser magnifications. Downsamples the data starting from from_mag until a magnification is >= max(coarsest_mag). Different sampling modes control how dimensions are downsampled. Note that the data is written temporarily on the local disk and uploaded afterwards so some local disk space is required. Parameters: - **`from_mag`** (`Mag | None`, default: `None` ) – Source magnification to downsample from. Defaults to highest existing mag. - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Target magnification to stop at. Defaults to calculated value. - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". Supported modes: "median", "mode", "nearest", "bilinear", "bicubic" - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress the generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be downsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool`, default: `True` ) – Whether to align the mag selection with the dataset’s other layers. True by default. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`force_sampling_scheme`** (`bool`, default: `False` ) – Force invalid sampling schemes. Defaults to False. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is either COPY or MOVE_AND_SYMLINK to select one of the available WEBKNOSSOS storages. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. None by default. Raises: - `AssertionError` – If from_mag does not exist - `RuntimeError` – If sampling scheme produces invalid magnifications - `AttributeError` – If sampling_mode is invalid ### get_finest_mag ``` get_finest_mag() -> MagView[RemoteLayer] ``` ### get_mag ``` get_mag(mag: MagLike) -> MagView[RemoteLayer] ``` ### refresh_largest_segment_id ``` refresh_largest_segment_id( *, chunk_shape: Vec3Int | None = None, executor: Executor | None = None ) -> None ``` Updates largest_segment_id based on actual data content. Scans through the data to find the highest segment ID value. Sets to None if data is empty. Parameters: - **`chunk_shape`** (`Vec3Int | None`, default: `None` ) – Shape of chunks for processing - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing ### upsample ``` upsample( from_mag: Mag, *, finest_mag: Mag = Mag(1), compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: bool = True, buffer_shape: Vec3IntLike | None = None, transfer_mode: TransferMode = COPY, common_storage_path_prefix: str | None = None, overwrite_pending: bool = True, executor: Executor | None = None ) -> None ``` Upsample data to finer magnifications. Upsamples from a coarser magnification to a sequence of finer magnifications, stopping at finest_mag. The data is written temporarily on the local disk and uploaded afterwards, so some local disk space is required. Parameters: - **`from_mag`** (`Mag`) – Source coarse magnification. - **`finest_mag`** (`Mag`, default: `Mag(1)` ) – Target finest magnification. Defaults to Mag(1). - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress upsampled data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be upsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool`, default: `True` ) – Whether to align mags with the dataset's other layers. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`transfer_mode`** (`TransferMode`, default: `COPY` ) – How new mags are transferred to the remote storage. Defaults to COPY. - **`common_storage_path_prefix`** (`str | None`, default: `None` ) – Optional path prefix used when transfer_mode is COPY or MOVE_AND_SYMLINK. - **`overwrite_pending`** (`bool`, default: `True` ) – If there are already pending/unfinished committed mags on the server, overwrite them. Defaults to True. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Defaults to None. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If finest_mag is invalid. - `AttributeError` – If sampling_mode is invalid. # webknossos.dataset ## SegmentationLayer ``` SegmentationLayer( dataset: Dataset, properties: SegmentationLayerProperties, read_only: bool, ) ``` Bases: `AbstractSegmentationLayer[Attachments]`, `Layer` ### attachments ``` attachments: AttachmentsTypeT ``` Access, add and remove the attachments of this layer. Attachments are additional files that can be attached to a segmentation layer. They can be used to store additional information, such as meshes, agglomerations, segment indices, cumsums and connectomes. Examples: ``` # Add a mesh attachment to the segmentation layer layer.attachments.add_attachment_as_ref( MeshAttachment.from_path_and_name( mesh_path, "meshfile", data_format=AttachmentDataFormat.Zarr3 ) ) # Access the mesh attachment path layer.attachments.meshes[0].path # Remove the mesh attachment layer.attachments.delete_attachment(layer.attachments.meshes[0]) ``` ### bounding_box ``` bounding_box: NDBoundingBox ``` Gets the bounding box encompassing this layer's data. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – Bounding box with layer dimensions ### category ``` category: LayerCategoryType ``` ### data_format ``` data_format: DataFormat ``` Gets the data storage format used by this layer. Returns: - **`DataFormat`** ( `DataFormat` ) – Format used to store data Raises: - `AssertionError` – If data_format is not set in properties ### dataset ``` dataset: Dataset ``` ### default_view_configuration ``` default_view_configuration: LayerViewConfiguration | None ``` Gets the default view configuration for this layer. Returns: - `LayerViewConfiguration | None` – LayerViewConfiguration | None: View configuration if set, otherwise None ### dtype ``` dtype: dtype ``` Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### dtype_per_channel ``` dtype_per_channel: dtype ``` Deprecated. Use `dtype` instead. Gets the data type used per channel. Returns: - `dtype` – np.dtype: NumPy data type for individual channels ### is_foreign ``` is_foreign: bool ``` Whether this layer's data is stored remotely relative to its dataset. Returns: bool: True if layer path parent differs from dataset path ### is_remote_to_dataset ``` is_remote_to_dataset: bool ``` ### largest_segment_id ``` largest_segment_id: int | None ``` Gets the largest segment ID present in the data. The largest segment ID is the highest numerical identifier assigned to any segment in this layer. This is useful for: - Allocating new segment IDs - Validating segment ID ranges - Optimizing data structures Returns: - `int | None` – int | None: The highest segment ID present, or None if no segments exist ### mags ``` mags: Mapping[Mag, MagView] ``` Getter for dictionary containing all mags. ### name ``` name: str ``` Returns the name of the layer. ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this layer. Returns: - **`int`** ( `int` ) – Number of channels Raises: - `AssertionError` – If num_channels is not set in properties ### path ``` path: UPath ``` Gets the filesystem path to this layer's data. This is defined as a subdirectory of the dataset directory named like the layer. Therefore, this directory does not contain the actual data of any linked or remote layers or mags. Returns: - **`UPath`** ( `UPath` ) – Filesystem path to this layer's data directory Raises: - `AssertionError` – If mags in layer point to different layers ### read_only ``` read_only: bool ``` Whether this layer is read-only. Returns: - **`bool`** ( `bool` ) – True if layer is read-only, False if writable ### resolved_path ``` resolved_path: UPath ``` ### add_copy_mag ``` add_copy_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | None = None, exists_ok: bool = False, executor: Executor | None = None, progress_desc: str | None = None ) -> MagView ``` Deprecated. Use `Layer.add_mag_as_copy` instead. ### add_fs_copy_mag ``` add_fs_copy_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, exists_ok: bool = False ) -> MagView[Layer] ``` Deprecated. File-copy is automatically selected when using `Layer.add_mag_as_copy`. Copies the data at `foreign_mag_view_or_path` which belongs to another dataset to the current dataset via the filesystem. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag ``` add_mag( mag: MagLike, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: int | Vec3IntLike | None = None, compress: bool | Zarr3Config = True ) -> MagView[Layer] ``` Creates and adds a new magnification level to the layer. The new magnification can be configured with various storage parameters to optimize performance, notably `chunk_shape`, `shard_shape` and `compress`. Note that writing data which is not aligned with the blocks on disk may result in diminished performance, as full blocks will automatically be read to pad the write actions. Parameters: - **`mag`** (`MagLike`) – Identifier for new magnification level - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. If specified, chunks_per_shard must not be specified. Defaults to (1024, 1024, 1024). - **`chunks_per_shard`** (`int | Vec3IntLike | None`, default: `None` ) – Deprecated, use shard_shape. Number of chunks per shards. If specified, shard_shape must not be specified. - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to enable compression. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. Returns: - **`MagView`** ( `MagView[Layer]` ) – View of newly created magnification level Raises: - `IndexError` – If magnification already exists - `Warning` – If chunk_shape is not optimal for WEBKNOSSOS performance ### add_mag_as_copy ``` add_mag_as_copy( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | Zarr3Config | None = None, exists_ok: bool = False, executor: Executor | None = None, progress_desc: str | None = None ) -> MagView[Layer] ``` Copies the data at `foreign_mag_view_or_path` which can belong to another dataset to the current dataset. Additionally, the relevant information from the `datasource-properties.json` of the other dataset are copied, too. ### add_mag_as_ref ``` add_mag_as_ref( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, mag: MagLike | None = None, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Adds the mag at `foreign_mag_view_or_path` which belongs to foreign dataset. The relevant information from the `datasource-properties.json` of the other dataset is copied to this dataset. Note: If the other dataset modifies its bounding box afterwards, the change does not affect this properties (or vice versa). ### add_mag_from_zarrarray ``` add_mag_from_zarrarray( mag: MagLike, path: PathLike | UPath, *, move: bool = False, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Copies the data at `path` to the current layer of the dataset via the filesystem and adds it as `mag`. When `move` flag is set the array is moved, otherwise a copy of the zarrarray is created. ### add_remote_mag ``` add_remote_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Deprecated. Use `Layer.add_mag_as_ref` instead. ### add_symlink_mag ``` add_symlink_mag( foreign_mag_view_or_path: ( PathLike | UPath | str | MagView ), *, make_relative: bool = False, extend_layer_bounding_box: bool = True ) -> MagView[Layer] ``` Deprecated. Use `Layer.add_mag_as_ref` instead. Creates a symlink to the data at `foreign_mag_view_or_path` which belongs to another dataset. The relevant information from the `datasource-properties.json` of the other dataset is copied to this dataset. Note: If the other dataset modifies its bounding box afterwards, the change does not affect this properties (or vice versa). If make_relative is True, the symlink is made relative to the current dataset path. Symlinked mags can only be added to layers on local file systems. ### as_segmentation_layer ``` as_segmentation_layer() -> SegmentationLayer ``` Casts into SegmentationLayer. ### delete_mag ``` delete_mag(mag: MagLike) -> None ``` Deletes the MagView from the `datasource-properties.json` and the data from disk. This function raises an `IndexError` if the specified `mag` does not exist. ### downsample ``` downsample( *, from_mag: Mag | None = None, coarsest_mag: Mag | None = None, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: Union[ bool, Dataset, RemoteDataset ] = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, force_sampling_scheme: bool = False, allow_overwrite: bool = False, only_setup_mags: bool = False, from_mag_view: MagView | None = None, executor: Executor | None = None ) -> None ``` Downsample data from a source magnification to coarser magnifications. Downsamples the data starting from from_mag until a magnification is >= max(coarsest_mag). Different sampling modes control how dimensions are downsampled. Parameters: - **`from_mag`** (`Mag | None`, default: `None` ) – Source magnification to downsample from. Defaults to highest existing mag. - **`coarsest_mag`** (`Mag | None`, default: `None` ) – Target magnification to stop at. Defaults to calculated value. - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". Supported modes: "median", "mode", "nearest", "bilinear", "bicubic" - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress the generated magnifications. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be downsampled. Defaults to ANISOTROPIC. - **`align_with_other_layers`** (`bool | Dataset | RemoteDataset`, default: `True` ) – Whether to align with other layers. True by default. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. Defaults to None. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. Defaults to (1024, 1024, 1024). - **`force_sampling_scheme`** (`bool`, default: `False` ) – Force invalid sampling schemes. Defaults to False. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether existing mags can be overwritten. False by default. - **`only_setup_mags`** (`bool`, default: `False` ) – Only create mags without data. False by default. - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source magnification view, pass only if the source data should be from another layer or dataset. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. None by default. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `RuntimeError` – If sampling scheme produces invalid magnifications - `AttributeError` – If sampling_mode is invalid Examples: ``` from webknossos import SamplingModes # let 'layer' be a `Layer` with only `Mag(1)` assert "1" in self.mags.keys() layer.downsample( coarsest_mag=Mag(4), sampling_mode=SamplingModes.ISOTROPIC ) assert "2" in self.mags.keys() assert "4" in self.mags.keys() ``` ### downsample_mag ``` downsample_mag( from_mag: Mag, target_mag: Mag, *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, allow_overwrite: bool = False, only_setup_mag: bool = False, from_mag_view: MagView | None = None, executor: Executor | None = None ) -> None ``` Performs a single downsampling step between magnification levels. Parameters: - **`from_mag`** (`Mag`) – Source magnification level - **`target_mag`** (`Mag`) – Target magnification level - **`interpolation_mode`** (`str`, default: `'default'` ) – Method for interpolation ("median", "mode", "nearest", "bilinear", "bicubic") - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress target data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether to allow overwriting existing mag - **`only_setup_mag`** (`bool`, default: `False` ) – Only create mag without data. This parameter can be used to prepare for parallel downsampling of multiple layers while avoiding parallel writes with outdated updates to the datasource-properties.json file. - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source magnification view, pass only if the source data should be from another layer or dataset. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If target exists without overwrite - `ValueError` – If from_mag is greater than target_mag ### downsample_mag_list ``` downsample_mag_list( from_mag: Mag, target_mags: list[Mag], *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, allow_overwrite: bool = False, only_setup_mags: bool = False, executor: Executor | None = None ) -> None ``` Downsample data iteratively through multiple magnification levels. Performs sequential downsampling from from_mag through each magnification in target_mags in order. Parameters: - **`from_mag`** (`Mag`) – Source magnification to start from - **`target_mags`** (`List[Mag]`) – Ordered list of target magnifications - **`interpolation_mode`** (`str`, default: `'default'` ) – Interpolation method to use. Defaults to "default". - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress outputs. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`allow_overwrite`** (`bool`, default: `False` ) – Whether to allow overwriting mags. Defaults to False. - **`only_setup_mags`** (`bool`, default: `False` ) – Only create mag structures without data. Defaults to False. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If target mags not in ascending order See downsample_mag() for more details on parameters. ### get_finest_mag ``` get_finest_mag() -> MagView[Layer] ``` ### get_mag ``` get_mag(mag: MagLike) -> MagView[Layer] ``` ### get_or_add_mag ``` get_or_add_mag( mag: MagLike, *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, chunks_per_shard: Vec3IntLike | int | None = None, compress: bool | Zarr3Config | None = None ) -> MagView[Layer] ``` Creates a new mag and adds it to the dataset, in case it did not exist before. Then, returns the mag. See `add_mag` for more information. ### is_mag_view_foreign ``` is_mag_view_foreign(mag: MagView) -> bool ``` Check if this magnification's data is stored not as part of to the dataset. Returns: bool: True if data is stored in a different location than the parent dataset. ### redownsample ``` redownsample( *, interpolation_mode: str = "default", compress: bool | Zarr3Config = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, executor: Executor | None = None ) -> None ``` Recompute all downsampled magnifications from base mag. Used after modifying data in the base magnification to update all derived magnifications. Parameters: - **`interpolation_mode`** (`str`, default: `'default'` ) – Method for interpolation - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress recomputed data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing ### refresh_largest_segment_id ``` refresh_largest_segment_id( *, chunk_shape: Vec3Int | None = None, executor: Executor | None = None ) -> None ``` Updates largest_segment_id based on actual data content. Scans through the data to find the highest segment ID value. Sets to None if data is empty. Parameters: - **`chunk_shape`** (`Vec3Int | None`, default: `None` ) – Shape of chunks for processing - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing ### upsample ``` upsample( from_mag: Mag, *, from_mag_view: MagView | None = None, finest_mag: Mag = Mag(1), compress: bool | Zarr3Config = True, sampling_mode: str | SamplingModes = ANISOTROPIC, align_with_other_layers: Union[bool, Dataset] = True, buffer_shape: Vec3IntLike | int | None = None, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, executor: Executor | None = None ) -> None ``` Upsample data to finer magnifications. Upsamples from a coarser magnification to a sequence of finer magnifications, stopping at finest_mag. The sampling mode controls how dimensions are handled. Parameters: - **`from_mag`** (`Mag`) – Source coarse magnification - **`from_mag_view`** (`MagView | None`, default: `None` ) – Source coarse magnification view, pass only if the source data should be from another layer or dataset. - **`finest_mag`** (`Mag`, default: `Mag(1)` ) – Target finest magnification (default Mag(1)) - **`compress`** (`bool | Zarr3Config`, default: `True` ) – Whether to compress upsampled data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. Defaults to True. - **`sampling_mode`** (`str | SamplingModes`, default: `ANISOTROPIC` ) – How dimensions should be upsampled: - 'anisotropic': Equalizes voxel dimensions based on voxel_size - 'isotropic': Equal upsampling in all dimensions - 'constant_z': Only upsamples x/y dimensions. z remains unchanged. - **`align_with_other_layers`** (`Union[bool, Dataset]`, default: `True` ) – Whether to align mags with others. Defaults to True. - **`buffer_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of processing buffer. - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. Raises: - `KeyError` – If from_mag doesn't exist is invalid. - `AssertionError` – If finest_mag is invalid. - `AttributeError` – If sampling_mode is invalid # webknossos.dataset ## AgglomerateAttachment ``` AgglomerateAttachment( properties: AttachmentProperties, path: UPath ) ``` Bases: `Attachment` ### container_name ``` container_name = 'agglomerates' ``` ### data_format ``` data_format: Literal[Zarr3, HDF5] ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name = 'agglomerate' ``` ### create ``` create( path: str | PathLike | UPath, graph: AgglomerateGraph, *, segmentation_dtype: DTypeLike = "uint32" ) -> AgglomerateAttachment ``` Create and write a Zarr v3 agglomerate attachment from a networkx graph. The graph must have: - Integer node labels (segment IDs, 1-based) - 'position' node attribute: Vec3Int (x, y, z) - 'affinity' edge attribute: float Connected components become agglomerates. The AgglomerateAttachment will be created at `path`. `segmentation_dtype` must match the dtype of the corresponding segmentation layer. Returns an AgglomerateAttachment usable directly with `seg_layer.attachments.add_attachment_as_copy(attachment)`. ### create_and_add_to ``` create_and_add_to( layer: SegmentationLayer, name: str, graph: AgglomerateGraph, ) -> AgglomerateAttachment ``` Create a Zarr v3 agglomerate attachment from a networkx graph and add it to a segmentation layer. `name` is the attachment name. The `graph` must have: - Integer node labels (segment IDs, 1-based) - 'position' node attribute: Vec3Int (x, y, z) - 'affinity' edge attribute: float Connected components become agglomerates. Returns the added AgglomerateAttachment. ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` ### to_graph ``` to_graph() -> AgglomerateGraph ``` Read the agglomerate attachment from disk and reconstruct an AgglomerateGraph. Returns an AgglomerateGraph with: - Integer node labels (segment IDs, 1-based) - 'position' node attribute: Vec3Int (x, y, z) - 'affinity' edge attribute: float ## AgglomerateGraph Bases: `Graph` Typed networkx Graph for agglomerate data. Node labels are segment IDs (integers, 1-based). ### add_affinity_edge ``` add_affinity_edge( u: int, v: int, *, affinity: float ) -> None ``` Add an undirected edge between two segment IDs with an affinity score. ### add_segment ``` add_segment(segment_id: int, *, position: Vec3Int) -> None ``` Add a segment node with a (x, y, z) position. ### to_agglomerate_graph_data ``` to_agglomerate_graph_data( segmentation_dtype: DTypeLike = dtype("uint32"), ) -> AgglomerateGraphData ``` Convert to an AgglomerateGraphData (flat numpy-array representation). Returns an AgglomerateGraphData with: - segments: segment IDs, segmentation_dtype (uint32 or uint64) - positions: [x, y, z] per segment, dtype int64 - edges: [source, target] segment ID pairs, segmentation_dtype (uint32 or uint64) - affinities: affinity per edge, dtype float32 # webknossos.dataset ## Attachment ``` Attachment(properties: AttachmentProperties, path: UPath) ``` ### container_name ``` container_name: Literal[ "agglomerates", "meshes", "segment_index", "cumsum", "connectomes", ] ``` The container names are also used to derive the folder names to put the attachments. The container names are converted to camelCase to get the folder names. ### data_format ``` data_format: AttachmentDataFormat = data_format ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name: Literal[ "mesh", "agglomerate", "segmentIndex", "connectome", "cumsum", ] ``` The type names are used to communicate to WEBKNOSSOS which attachment type we want to e.g. upload. ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` ## ConnectomeAttachment ``` ConnectomeAttachment( properties: AttachmentProperties, path: UPath ) ``` Bases: `Attachment` ### container_name ``` container_name = 'connectomes' ``` ### data_format ``` data_format: Literal[Zarr3, HDF5] ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name = 'connectome' ``` ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` ## CumsumAttachment ``` CumsumAttachment( properties: AttachmentProperties, path: UPath ) ``` Bases: `Attachment` ### container_name ``` container_name = 'cumsum' ``` ### data_format ``` data_format: Literal[Zarr3, JSON] ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name = 'cumsum' ``` ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` ## MeshAttachment ``` MeshAttachment( properties: AttachmentProperties, path: UPath ) ``` Bases: `Attachment` ### container_name ``` container_name = 'meshes' ``` ### data_format ``` data_format: Literal[Zarr3, HDF5] ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name = 'mesh' ``` ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` ## SegmentIndexAttachment ``` SegmentIndexAttachment( properties: AttachmentProperties, path: UPath ) ``` Bases: `Attachment` ### container_name ``` container_name = 'segment_index' ``` ### data_format ``` data_format: Literal[Zarr3, HDF5] ``` ### name ``` name: str = name ``` ### path ``` path: UPath = path ``` ### type_name ``` type_name = 'segmentIndex' ``` ### from_path_and_name ``` from_path_and_name( path: str | PathLike | UPath, name: str, *, data_format: AttachmentDataFormat, dataset_path: str | PathLike | UPath | None = None ) -> Self ``` # webknossos.dataset ## Attachments ``` Attachments(layer: SegmentationLayer) ``` Bases: `AbstractAttachments` ### agglomerates ``` agglomerates: tuple[AgglomerateAttachment, ...] ``` ### connectomes ``` connectomes: tuple[ConnectomeAttachment, ...] ``` ### cumsum ``` cumsum: CumsumAttachment | None ``` ### is_empty ``` is_empty: bool ``` ### meshes ``` meshes: tuple[MeshAttachment, ...] ``` ### segment_index ``` segment_index: SegmentIndexAttachment | None ``` ### add_agglomerate ``` add_agglomerate( path: str | PathLike | UPath, *, name: str, data_format: AttachmentDataFormat ) -> AgglomerateAttachment ``` ### add_attachment_as_copy ``` add_attachment_as_copy( attachment: Attachment, ) -> Attachment ``` ### add_attachment_as_ref ``` add_attachment_as_ref( attachment: Attachment, *, new_name: str | None = None ) -> Attachment ``` ### add_attachments ``` add_attachments(*other: Attachment) -> list[Attachment] ``` ### add_connectome ``` add_connectome( path: str | PathLike | UPath, *, name: str, data_format: AttachmentDataFormat ) -> ConnectomeAttachment ``` ### add_copy_attachments ``` add_copy_attachments( *other: Attachment, ) -> list[Attachment] ``` ### add_mesh ``` add_mesh( path: str | PathLike | UPath, *, name: str, data_format: AttachmentDataFormat ) -> MeshAttachment ``` ### add_symlink_attachments ``` add_symlink_attachments( *other: Attachment, make_relative: bool = False ) -> list[Attachment] ``` ### delete_attachment ``` delete_attachment(attachment: Attachment) -> None ``` ### detect_legacy_attachments ``` detect_legacy_attachments() -> None ``` Detects and adds legacy attachments. Legacy attachments are attachments that were stored in the folder hierarchy of the layer without explicit metadata. ### rename_attachment ``` rename_attachment( attachment: Attachment, *, new_name: str ) -> Attachment ``` ### set_cumsum ``` set_cumsum( path: str | PathLike | UPath, *, name: str, data_format: AttachmentDataFormat ) -> CumsumAttachment ``` ### set_segment_index ``` set_segment_index( path: str | PathLike | UPath, *, name: str, data_format: AttachmentDataFormat ) -> SegmentIndexAttachment ``` ## RemoteAttachments ``` RemoteAttachments(layer: RemoteSegmentationLayer) ``` Bases: `AbstractAttachments` ### agglomerates ``` agglomerates: tuple[AgglomerateAttachment, ...] ``` ### connectomes ``` connectomes: tuple[ConnectomeAttachment, ...] ``` ### cumsum ``` cumsum: CumsumAttachment | None ``` ### is_empty ``` is_empty: bool ``` ### meshes ``` meshes: tuple[MeshAttachment, ...] ``` ### segment_index ``` segment_index: SegmentIndexAttachment | None ``` ### add_attachment_as_copy ``` add_attachment_as_copy( attachment: Attachment, *, transfer_mode: TransferMode = COPY, common_storage_prefix: str | None = None, overwrite_pending: bool = True ) -> Attachment ``` ### add_attachment_as_ref ``` add_attachment_as_ref( attachment: Attachment, *, foreign_layer: RemoteSegmentationLayer, new_name: str | None ) -> Attachment ``` ### add_copy_attachments ``` add_copy_attachments( *other: Attachment, ) -> list[Attachment] ``` ### delete_attachment ``` delete_attachment(attachment: Attachment) -> None ``` ### rename_attachment ``` rename_attachment( attachment: Attachment, *, new_name: str ) -> Attachment ``` ### upload_attachment ``` upload_attachment( attachment: Attachment, *, transfer_mode: TransferMode = COPY, common_storage_prefix: str | None = None ) -> Attachment ``` # webknossos.dataset # webknossos.dataset ## MagView ``` MagView( layer: LayerTypeT, mag: Mag, path: UPath, read_only: bool = False, ) ``` Bases: `View`, `Generic[LayerTypeT]` A view of a specific magnification level within a WEBKNOSSOS layer. MagView provides access to volumetric data at a specific resolution/magnification level. It supports reading, writing, and processing operations on the underlying data, with coordinates automatically handled in the correct magnification space. Key Features - Read/write volumetric data at specific magnification levels - Automatic coordinate transformation between Mag(1) and current magnification - Support for compressed and uncompressed data formats - Chunked processing for efficient memory usage - Downsampling and upsampling capabilities Attributes: - **`layer`** (`LayerTypeT`) – The parent Layer object this magnification belongs to. - **`mag`** (`Mag`) – The magnification level (e.g., Mag(1), Mag(2), Mag(4), etc.). - **`info`** (`ArrayInfo`) – Information about array storage (chunk shape, compression, etc.). - **`path`** (`UPath`) – Path to the data on disk. - **`bounding_box`** (`NDBoundingBox`) – The spatial extent of this magnification in Mag(1) coordinates. - **`read_only`** (`bool`) – Whether this magnification is read-only. Examples: ``` # Create a dataset with a segmentation layer ds = Dataset("path/to/dataset", voxel_size=(1, 1, 1)) layer = ds.add_layer( "segmentation", SEGMENTATION_CATEGORY, bounding_box=BoundingBox((100, 200, 300), (512, 512, 512)), ) # Add and work with magnification levels mag1 = layer.add_mag(Mag(1)) mag2 = layer.add_mag(Mag(2)) # Write data at Mag(1) mag1.write(data, absolute_offset=(100, 200, 300)) # Read data at Mag(2) - coordinates are in Mag(1) space data = mag2.read(absolute_offset=(100, 200, 300), size=(512, 512, 512)) # Process data in chunks def process_chunk(view: View) -> None: data = view.read() # Process data... view.write(processed_data) mag1.for_each_chunk(process_chunk) ``` Notes - All offset/size parameters in read/write methods expect Mag(1) coordinates - Use get_view() to obtain restricted views of the data - Compressed data operations may have performance implications - When writing to segmentation layers, update largest_segment_id as needed See Also - Layer: Parent container for magnification levels - View: Base class providing data access methods - Dataset: Root container for all layers Do not use this constructor manually. Instead use `webknossos.dataset.layer.Layer.get_mag()`. ### bounding_box ``` bounding_box: NDBoundingBox ``` Get the spatial extent of this magnification level in Mag(1) coordinates. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – The bounding box of this magnification level in Mag(1) coordinates. Notes - The bounding box is automatically aligned with the magnification level - It represents the overall extent of the data, potentially including empty regions ### info ``` info: ArrayInfo ``` Get information about the array structure and properties. Returns: - **`ArrayInfo`** ( `ArrayInfo` ) – Object containing array metadata such as data type, bounding box, and other array-specific information. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) array_info = view.info print(f"Data type: {array_info.data_type}") print(f"Shape: {array_info.bounding_box.size}") ``` ### is_foreign ``` is_foreign: bool ``` Check if this magnification's data is stored not as part of to the dataset. ### layer ``` layer: LayerTypeT ``` Get the parent Layer object. Returns: - **`Layer`** ( `LayerTypeT` ) – The Layer object that contains this magnification level. Notes - The Layer provides context about data type, category, and overall properties - Used internally for coordinate transformations and data validation ### mag ``` mag: Mag ``` Gets the magnification level of this view. The magnification level determines the resolution at which the data is accessed. A higher magnification number means lower resolution (e.g., mag 2 means every second voxel, mag 4 means every fourth voxel, etc.). Returns: - **`Mag`** ( `Mag` ) – The magnification level of this view. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) print(f"Current magnification: {view.mag}") ``` ### name ``` name: str ``` Get the name of this magnification level. Returns: - **`str`** ( `str` ) – String representation of the magnification level (e.g., "1-1-1" for Mag(1)). ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this view. Returns: - **`int`** ( `int` ) – Number of channels ### path ``` path: UPath ``` Get the path to this magnification level's data. Returns: - **`UPath`** ( `UPath` ) – Path to the data files on disk. Notes - Path may be local or remote depending on dataset configuration ### read_only ``` read_only: bool ``` Indicates whether this view is read-only. When a view is read-only, write operations are not permitted. This property helps prevent accidental modifications to the dataset. Returns: - **`bool`** ( `bool` ) – True if the view is read-only, False if write operations are allowed. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) if not view.read_only: view.write(data) else: print("Cannot modify read-only view") ``` ### chunk ``` chunk( chunk_shape: VecIntLike, *, chunk_border_alignments: VecIntLike | None = None, read_only: bool | None = None ) -> Generator[View, None, None] ``` Generate a sequence of sub-views by chunking the current view. Divides the view into smaller, regularly-sized chunks that can be processed independently. This is useful for parallel processing or when working with large datasets that don't fit in memory. Parameters: - **`chunk_shape`** (`VecIntLike`) – Size of each chunk in Mag(1) coordinates. - **`chunk_border_alignments`** (`VecIntLike | None`, default: `None` ) – Alignment of chunk borders in Mag(1) coordinates. If None, aligns to (0, 0, 0). Defaults to None. - **`read_only`** (`bool`, default: `None` ) – Whether the generated chunks should be read-only. Defaults to self.read_only. Yields: - **`View`** ( `View` ) – Sub-views representing each chunk of the original view. Examples: ``` # let 'mag1' be a `MagView` chunks = mag1.chunk(chunk_shape=(100, 100, 100), chunk_border_alignments=(50, 50, 50)) ``` ### compress ``` compress( *, target_path: str | PathLike | UPath | None = None, executor: Executor | None = None ) -> None ``` Compresses the files on disk. Compresses the magnification level's data, either in-place or to a new location. Compression can reduce storage space but may impact read/write performance. Parameters: - **`target_path`** (`str | PathLike | UPath | None`, default: `None` ) – Optional path to write compressed data. If None, compresses in-place. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel compression. Examples: ``` # Compress in-place mag1.compress() ``` Notes - In-place compression requires local filesystem - Remote compression requires target_path - Compression is parallelized when executor is provided - Progress is displayed during compression - Compressed data may have slower read/write speeds ### content_is_equal ``` content_is_equal( other: View, *, executor: Executor | None = None, progress_desc: str | None = None, chunk_shape: Vec3IntLike | None = None ) -> bool ``` Compare the content of this view with another view. Performs a chunk-by-chunk comparison of the data in both views. This is more memory efficient than reading entire views at once for large datasets. Parameters: - **`other`** (`View`) – The view to compare against. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel comparison. If None, compares sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Returns: - **`bool`** ( `bool` ) – True if the content of both views is identical, False otherwise. Examples: ``` # Compare views sequentially if view1.content_is_equal(view2): print("Views are identical") ``` Note - Comparison is done chunk by chunk to manage memory usage - Views must have the same shape and data type - Returns False immediately if shapes or types don't match - Progress tracks total volume compared - Parallel execution can speed up comparison of large views ### create ``` create( layer: LayerTypeT, mag: Mag, *, path: UPath, chunk_shape: Vec3Int, shard_shape: Vec3Int | None = None, chunks_per_shard: Vec3Int | None = None, compression_mode: bool | Zarr3Config, read_only: bool = False ) -> MagView ``` Do not use this constructor manually. Instead use `webknossos.dataset.layer.Layer.add_mag()`. ### for_each_chunk ``` for_each_chunk( func_per_chunk: Callable[[tuple[View, int]], None], *, chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> None ``` Process each chunk of the view with a given function. Divides the view into chunks and applies a function to each chunk, optionally in parallel. This is useful for processing large datasets in manageable pieces, with optional progress tracking and parallel execution. Parameters: - **`func_per_chunk`** (`Callable[[tuple[View, int]], None]`) – Function to apply to each chunk. Takes a tuple of (chunk_view, chunk_index) as argument. The chunk_index can be used for progress tracking or logging. - **`chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of each chunk in Mag(1) coordinates. If None, uses one chunk per file based on the dataset's file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Examples: ``` from webknossos.utils import named_partial # Define processing function def process_chunk(args: tuple[View, int], threshold: float) -> None: chunk_view, chunk_idx = args data = chunk_view.read() # Process data... chunk_view.write(processed_data) print(f"Processed chunk {chunk_idx}") # Sequential processing with progress bar view.for_each_chunk( named_partial(process_chunk, threshold=0.5), chunk_shape=(64, 64, 64), progress_desc="Processing chunks" ) ``` Note - Each chunk is processed independently, making this suitable for parallel execution - For non-read-only views, chunks must align with file boundaries - Progress tracking shows total volume processed - Memory usage depends on chunk_shape and parallel execution settings - When using an executor, ensure thread/process safety in func_per_chunk - The view's magnification affects the actual data resolution ### for_zipped_chunks ``` for_zipped_chunks( func_per_chunk: Callable[ [tuple[View, View, int]], None ], target_view: View, *, source_chunk_shape: Vec3IntLike | None = None, target_chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> None ``` Process paired chunks from source and target views simultaneously. Chunks both the source (self) and target views, then applies a function to each corresponding pair of chunks. This is particularly useful for operations that transform data between views of different magnifications, like downsampling. Parameters: - **`func_per_chunk`** (`Callable[[tuple[View, View, int]], None]`) – Function to apply to each chunk pair. Takes (source_chunk, target_chunk, index) as arguments. - **`target_view`** (`View`) – The target view to write transformed data to. - **`source_chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of source chunks in Mag(1). If None, uses maximum of source and target file dimensions. Defaults to None. - **`target_chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of target chunks in Mag(1). If None, uses maximum of source and target file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Examples: ``` # Downsample data from Mag(1) to Mag(2) def downsample_chunk(args: tuple[View, View, int]) -> None: source_chunk, target_chunk, idx = args data = source_chunk.read() downsampled = downsample_data(data) # Your downsampling function target_chunk.write(downsampled) print(f"Processed chunk pair {idx}") # Process with default chunk sizes mag1_view.for_zipped_chunks( downsample_chunk, mag2_view, progress_desc="Downsampling data" ) ``` Note - Source/target view size ratios must match chunk size ratios - Target chunks must align with file boundaries to avoid concurrent writes - Both views are chunked with matching strides - Progress tracks total volume processed - Memory usage depends on chunk sizes and parallel execution ### get_bounding_boxes_on_disk ``` get_bounding_boxes_on_disk() -> Iterator[NDBoundingBox] ``` Returns a Mag(1) bounding box for each file on disk. This method iterates through the actual files stored on disk and returns their bounding boxes. This is different from the layer's bounding box property, which represents the overall extent of the data, potentially including regions without actual data files. Returns: - `Iterator[NDBoundingBox]` – Iterator\[NDBoundingBox\]: Iterator yielding bounding boxes in Mag(1) coordinates. Examples: ``` # Print all data file bounding boxes for bbox in mag1.get_bounding_boxes_on_disk(): print(f"Found data file at {bbox}") # Calculate total data volume total_volume = sum(bbox.volume() for bbox in mag1.get_bounding_boxes_on_disk()) ``` Notes - Bounding boxes are in Mag(1) coordinates - Some storage formats may not support efficient listing - For unsupported formats, falls back to chunk-based iteration - Useful for understanding actual data distribution on disk ### get_buffered_slice_reader ``` get_buffered_slice_reader( buffer_size: int | None = None, dimension: str | int = "z", *, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, use_logging: bool = False ) -> BufferedSliceReader ``` Get a buffered reader for efficiently reading data slices. Creates a BufferedSliceReader that allows efficient reading of data slices by buffering multiple slices in memory. This is particularly useful when reading large datasets slice by slice. Parameters: - **`buffer_size`** (`int`, default: `None` ) – Number of slices to buffer in memory at once. Defaults to the size of the shard in the dimension. - **`dimension`** (`str | int`, default: `'z'` ) – Axis along which to read slices (0=x, 1=y, 2=z). Defaults to "z". - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates, relative to the current view's offset. Mutually exclusive with absolute_bounding_box. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_bounding_box. Defaults to None. - **`use_logging`** (`bool`, default: `False` ) – Whether to enable logging of read operations. Returns: - **`BufferedSliceReader`** ( `BufferedSliceReader` ) – A reader object that yields data slices. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) # Create a reader with default settings (z-slices) with view.get_buffered_slice_reader() as reader: for slice_data in reader: process_slice(slice_data) # Read y-slices with custom buffer size with view.get_buffered_slice_reader( buffer_size=10, dimension="y", relative_offset=(10, 0, 0) ) as reader: ``` Note - Larger buffer sizes improve performance but use more memory - Choose dimension based on your data access pattern - Only one positioning parameter should be specified - The reader can be used as an iterator ### get_buffered_slice_writer ``` get_buffered_slice_writer( buffer_size: int | None = None, dimension: str | int = "z", *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, use_logging: bool = False, allow_unaligned: bool = False ) -> BufferedSliceWriter ``` Get a buffered writer for efficiently writing data slices. Creates a BufferedSliceWriter that allows efficient writing of data slices by buffering multiple slices before performing the actual write operation. Parameters: - **`buffer_size`** (`int`, default: `None` ) – Number of slices to buffer before performing a write. Defaults to the size of the shard in the dimension. - **`dimension`** (`str | int`, default: `'z'` ) – Axis along which to write slices (0=x, 1=y, 2=z). Defaults to "z". - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset in mag1 coordinates, relative to the current view's position. Mutually exclusive with absolute_offset. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_offset. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates, relative to the current view's offset. Mutually exclusive with absolute_bounding_box. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_bounding_box. Defaults to None. - **`use_logging`** (`bool`, default: `False` ) – Whether to enable logging of write operations. Defaults to False. - **`allow_unaligned`** (`bool`, default: `False` ) – Whether to allow unaligned writes. Defaults to False. Returns: - **`BufferedSliceWriter`** ( `BufferedSliceWriter` ) – A writer object for buffered slice writing. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) # Create a buffered writer with default settings with view.get_buffered_slice_writer() as writer: # Write slices efficiently for z in range(10): slice_data = np.zeros((100, 100)) # Your slice data writer.send(slice_data) # Create a writer with custom buffer size and offset with view.get_buffered_slice_writer( buffer_size=5, relative_offset=(10, 10, 0) ) ``` Note - Larger buffer sizes can improve performance but use more memory - Remember to use the writer in a context manager - Only one positioning parameter should be specified ### get_dtype ``` get_dtype() -> dtype ``` Returns the dtype per channel of the data. For example `uint8`. ### get_view ``` get_view( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, read_only: bool | None = None ) -> View ``` Create a new view restricted to a specified region. This method returns a new View instance that represents a subset of the current view's data. The new view can be specified using various coordinate systems and can optionally be made read-only. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of the new view. Must be specified when using any offset parameter. Defaults to None. ``` relative_offset (Vec3IntLike | None, optional): Offset relative to current view's position in Mag(1) coordinates. Must be used with size. Defaults to None. absolute_offset (Vec3IntLike | None, optional): Absolute offset in Mag(1) coordinates. Must be used with size. Defaults to None. relative_bounding_box (NDBoundingBox | None, optional): Bounding box relative to current view's position in Mag(1) coordinates. Defaults to None. absolute_bounding_box (NDBoundingBox | None, optional): Absolute bounding box in Mag(1) coordinates. Defaults to None. read_only (bool | None, optional): Whether the new view should be read-only. If None, inherits from parent view. Defaults to None. ``` Returns: - **`View`** ( `View` ) – A new View instance representing the specified region. Raises: - `AssertionError` – If: - Multiple positioning parameters are provided - Size is missing when using offset parameters - Non-read-only subview requested from read-only parent - Non-read-only subview extends beyond parent's bounds Examples: ``` # Create view from MagView mag1 = layer.get_mag("1") view = mag1.get_view(absolute_offset=(10, 20, 30), size=(100, 200, 300)) # Create subview within bounds sub_view = view.get_view( relative_offset=(50, 60, 70), size=(10, 120, 230) ) # Create read-only subview (can extend beyond bounds) large_view = view.get_view( relative_offset=(50, 60, 70), size=(999, 120, 230), read_only=True ) # Use bounding box instead of offset+size bbox = BoundingBox((10, 10, 0), (50, 50, 10)) bbox_view = view.get_view(relative_bounding_box=bbox) ``` Note - Use only one method to specify the region (offset+size or bounding_box) - All coordinates are in Mag(1) - Non-read-only views must stay within parent view's bounds - Read-only views can extend beyond parent view's bounds - The view's magnification affects the actual data resolution ### get_views_on_disk ``` get_views_on_disk( read_only: bool | None = None, ) -> Iterator[View] ``` Yields a view for each file on disk for efficient parallelization. Creates View objects that correspond to actual data files on disk. This is particularly useful for parallel processing as each view represents a natural unit of data storage. Parameters: - **`read_only`** (`bool | None`, default: `None` ) – If True, returned views will be read-only. If None, determined by context. Returns: - `Iterator[View]` – Iterator\[View\]: Iterator yielding View objects for each data file. Examples: ``` # Process each data file in parallel def process_chunk(view: View) -> None: data = view.read() # Process data... if not view.read_only: view.write(processed_data) with get_executor("multiprocessing", max_workers=3) as executor: executor.map(process_chunk, mag1.get_views_on_disk()) ``` Notes - Views correspond to actual files/chunks on disk - Ideal for parallel processing of large datasets - Each view's bounding box aligns with storage boundaries - Memory efficient as only one chunk is loaded at a time ### get_zarr_array ``` get_zarr_array() -> TensorStore ``` Get direct access to the underlying Zarr array. Provides direct access to the underlying Zarr array for advanced operations. Only available for Zarr-based datasets. Returns: - **`NDArrayLike`** ( `TensorStore` ) – The underlying Zarr array object. Raises: - `ValueError` – If called on a non-Zarr dataset. Notes - Only works with Zarr-based datasets - Provides low-level access to data storage - Use with caution as it bypasses normal access patterns ### map_chunk ``` map_chunk( func_per_chunk: Callable[[View], Any], *, chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> list[Any] ``` Process each chunk of the view and collect results. Similar to for_each_chunk(), but collects and returns the results from each chunk. Useful for parallel data analysis or feature extraction where results need to be aggregated. Parameters: - **`func_per_chunk`** (`Callable[[View], Any]`) – Function to apply to each chunk. Takes a chunk view as argument and returns a result of any type. - **`chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of each chunk in Mag(1) coordinates. If None, uses one chunk per file based on the dataset's file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Returns: - `list[Any]` – list\[Any\]: List of results from processing each chunk, in chunk order. Examples: ``` from webknossos.utils import named_partial # Calculate statistics per chunk def chunk_statistics(view: View, min_value: float) -> dict[str, float]: data = view.read() return { "mean": data[data > min_value].mean(), "std": data[data > min_value].std(), "volume": view.bounding_box.volume() } # Sequential processing stats = view.map_chunk( named_partial(chunk_statistics, min_value=0.1), chunk_shape=(128, 128, 128) ) # Aggregate results total_volume = sum(s["volume"] for s in stats) mean_values = [s["mean"] for s in stats] ``` Note - Results are collected in memory, consider memory usage for large datasets - Each chunk is processed independently, suitable for parallel execution - For non-read-only views, chunks must align with file boundaries - When using an executor, ensure thread/process safety in func_per_chunk - Results maintain chunk order regardless of execution order ### merge_chunk ``` merge_chunk( args: tuple[ MagView, NDBoundingBox, list[NDBoundingBox] ], ) -> None ``` Merge a single chunk during parallel merge operations. Internal method used by merge_with_view() for parallel processing. Merges data from another view into this one for a specific chunk region. Parameters: - **`args`** (`tuple[MagView, NDBoundingBox, list[NDBoundingBox]]`) – Tuple containing: - other (MagView): Source view to merge from - shard (NDBoundingBox): Target shard region - bboxes (list[NDBoundingBox]): List of source bounding boxes ### merge_with_view ``` merge_with_view(other: MagView, executor: Executor) -> None ``` Merges data from another view into this one. Combines data from another MagView into this one, using this view's data as the base and overlaying the other view's data where present. This is particularly useful for merging annotations or overlays. Parameters: - **`other`** (`MagView`) – The MagView to merge into this one. - **`executor`** (`Executor`) – Executor for parallel merging operations. Notes - Both views must have same magnification - Other view must have file_len = 1 - Both views must have same voxel type - Merging is parallelized using the provided executor - Updates layer bounding box if necessary ### read ``` read( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read data from the view at a specified location. This method provides flexible ways to read data from the view's region. If no parameters are provided, it reads the entire view's bounding box. The region to read can be specified using either offset+size combinations or bounding boxes. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of region to read. Specified in Mag(1) coordinates. Defaults to None. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to the view's position in Mag(1) coordinates. Must be used with size. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Must be used with size. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: The requested data as a numpy array. The shape will be (channels, x, y, z). Areas outside the dataset are zero-padded. Raises: - `AssertionError` – If incompatible parameters are provided (e.g., both offset+size and bounding_box) or if the requested region is empty. Examples: ``` # Read entire view's data view = layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read() # Returns (1, x, y, z) array for single-channel data # Read with relative offset and size data = view.read( relative_offset=(10, 10, 0), # Offset from view's position size=(50, 50, 10) # Size in Mag(1) coordinates ) # Read with absolute bounding box bbox = BoundingBox((0, 0, 0), (100, 100, 10)) data = view.read(absolute_bounding_box=bbox) # Read from multi-channel data view = color_layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read() # Returns (channels, x, y, z) array ``` Note - Use only one method to specify the region (offset+size or bounding_box) - All coordinates are in Mag(1) - The returned array always has the shape (C, X, Y, Z), even for single channel data - Regions outside the dataset are automatically zero-padded - The view's magnification affects the actual data resolution - Data shape must match the target region size ### read_cxyz ``` read_cxyz( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read data from the view and return it in `(c, x, y, z)` axis order. Equivalent to :meth:`read` but always returns a 4-D array ordered as `(channels, x, y, z)` regardless of the underlying storage axis ordering. If the array does not have a channel axis, one of size 1 is added. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of region to read in Mag(1) coordinates. Defaults to None. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: Data as a 4-D numpy array with shape (c, x, y, z). Areas outside the dataset are zero-padded. Examples: ``` # Read entire view's data in cxyz order view = layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read_cxyz() # Always returns (c, x, y, z) array # Read with relative offset and size data = view.read_cxyz(relative_offset=(10, 10, 0), size=(50, 50, 10)) ``` ### read_xyz ``` read_xyz( *, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read n-dimensional data and convert it to 3D XYZ format. This method is designed for handling n-dimensional data (n > 3) and converting it to strictly 3D data ordered as (X, Y, Z). It is primarily used internally by operations that require 3D data like downsampling, upsampling, and compression. When provided with a BoundingBox where additional dimensions (beyond X, Y, Z) have a shape of 1, it returns an array containing only the 3D spatial data. This ensures compatibility with operations that expect purely 3-dimensional input. Parameters: - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: The requested data as a numpy array with dimensions ordered as (channels, X, Y, Z) data. Areas outside the dataset are zero-padded. Examples: ``` # Read entire view's data in XYZ order view = layer.get_mag("1").get_view(size=(100, 100, 10)) xyz_data = view.read_xyz() # Returns (X, Y, Z) array # Read with relative bounding box bbox = NDBoundingBox((10, 10, 0), (50, 50, 10), axis=("x", "y", "z"), index=(1, 2, 3)) xyz_data = view.read_xyz(relative_bounding_box=bbox) ``` Note - If no bounding box is provided, reads the entire view's region - Only one bounding box parameter should be specified - The returned array's axes are ordered differently from read() - All coordinates are in Mag(1) ### rechunk ``` rechunk( *, chunk_shape: Vec3IntLike | int | None = None, shard_shape: Vec3IntLike | int | None = None, compress: bool | Zarr3Config | None = None, target_path: str | PathLike | UPath | None = None, executor: Executor | None = None, _progress_desc: str | None = None ) -> None ``` Rechunks the files on disk. Rechunks the magnification level's data, either in-place or to a new location. Parameters: - **`chunk_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of chunks for storage. Recommended (32,32,32) or (64,64,64). Defaults to (32,32,32). - **`shard_shape`** (`Vec3IntLike | int | None`, default: `None` ) – Shape of shards for storage. Must be a multiple of chunk_shape. If specified, chunks_per_shard must not be specified. Defaults to (1024, 1024, 1024). - **`compress`** (`bool | Zarr3Config | None`, default: `None` ) – Whether to compress the data. For Zarr3 datasets, codec configuration and chunk key encoding may also be supplied. - **`target_path`** (`str | PathLike | UPath | None`, default: `None` ) – Optional path to write compressed data. If None, compresses in-place. - **`executor`** (`Executor | None`, default: `None` ) – Optional executor for parallel rechunking. Examples: ``` # Rechunk in-place mag1.rechunk(chunk_shape=(32,32,32)) # Rechunk with custom parameters mag1.rechunk( chunk_shape=(32, 32, 32), shard_shape=(64, 64, 64), compress=True, target_path="path/to/new/dataset" ) ``` Notes - In-place rechunking requires local filesystem - Remote rechunking requires target_path - Rechunking is parallelized when executor is provided - Progress is displayed during rechunking - Compressed data may have slower read/write speeds ### write ``` write( data: ndarray, *, allow_resize: bool = False, allow_unaligned: bool = False, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> None ``` Write volumetric data to the magnification level. This method writes numpy array data to the dataset at the specified location. All offset and bounding box coordinates are expected to be in Mag(1) space, regardless of the current magnification level. Parameters: - **`data`** (`ndarray`) – The data to write. For 3D data, shape should be (x, y, z). For multi-channel 3D data, shape should be (channels, x, y, z). For n-dimensional data, the axes must match the bounding box axes of the layer. Shape must match the target region size. - **`allow_resize`** (`bool`, default: `False` ) – If True, allows updating the layer's bounding box if the write extends beyond it. Must not be set to True, when writing to the same magnification level in parallel. For one-off writes, consider using Dataset.write_layer. Defaults to False. - **`allow_unaligned`** (`bool`, default: `False` ) – If True, allows writing data to without being aligned to the shard shape. Defaults to False. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Examples: ``` # Write data at absolute position mag1.write(data, absolute_offset=(100, 200, 300)) # Write using bounding box bbox = BoundingBox((0, 0, 0), (100, 100, 100)) mag2.write(data, absolute_bounding_box=bbox) ``` Notes - At least one of offset/bounding_box parameters must be provided - Data shape must match the target region size - Coordinates are automatically scaled based on magnification - For compressed data, writing may be slower due to compression - Large writes may temporarily increase memory usage ### write_cxyz ``` write_cxyz( data: ndarray, *, allow_resize: bool = False, allow_unaligned: bool = False, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> None ``` Write data from a (c, x, y, z) ordered array to the magnification level. Equivalent to :meth:`write` but always accepts data in `(c, x, y, z)` axis order regardless of the underlying storage axis ordering. Parameters: - **`data`** (`ndarray`) – 4D array in (c, x, y, z) order. - **`allow_resize`** (`bool`, default: `False` ) – If True, allows updating the layer's bounding box if the write extends beyond it. Defaults to False. - **`allow_unaligned`** (`bool`, default: `False` ) – If True, allows writing data without being aligned to the shard shape. Defaults to False. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. # webknossos.dataset ## View ``` View( path_to_mag_view: UPath, bounding_box: NormalizedBoundingBox | None, mag: Mag, data_format: DataFormat, read_only: bool = False, cached_array: BaseArray | None = None, ) ``` A View represents a bounding box to a region of a specific StorageBackend with additional functionality. The View class provides a way to access and manipulate a specific region of data within a dataset. Write operations are restricted to the defined bounding box. Views are designed to be easily passed around as parameters and can be used to efficiently work with subsets of larger datasets. Examples: ``` from webknossos.dataset import Dataset, View dataset = Dataset.open("path/to/dataset") # Get a view for a specific layer at mag 1 layer = dataset.get_layer("color") view = layer.get_mag("1").get_view(size=(100, 100, 10)) # Read data from the view data = view.read() # Write data to the view (if not read_only) import numpy as np view.write(np.zeros(view.bounding_box.in_mag(view.mag).size)) ``` Initialize a View instance for accessing and manipulating dataset regions. Note: Do not use this constructor manually. Instead use `View.get_view()` (also available on a `MagView`) to get a `View`. Parameters: - **`path_to_mag_view`** (`Path`) – Path to the magnification view directory. - **`array_info`** (`ArrayInfo`) – Information about the array structure and properties. - **`bounding_box`** (`NDBoundingBox | None`) – The bounding box in mag 1 absolute coordinates. Optional only for mag_view since it overwrites the bounding_box property. - **`mag`** (`Mag`) – Magnification level of the view. - **`read_only`** (`bool`, default: `False` ) – Whether the view is read-only. Defaults to False. Examples: ``` # The recommended way to create a View is through get_view(): layer = dataset.get_layer("color") mag_view = layer.get_mag("1") view = mag_view.get_view(size=(100, 100, 10)) ``` ### bounding_box ``` bounding_box: NDBoundingBox ``` Gets the bounding box of this view. The bounding box defines the region of interest within the dataset in absolute coordinates at magnification level 1. It specifies both the position and size of the view's data. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – A bounding box object representing the view's boundaries in absolute coordinates at magnification level 1. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) bbox = view.bounding_box print(f"Top-left corner: {bbox.topleft}") print(f"Size: {bbox.size}") ``` ### info ``` info: ArrayInfo ``` Get information about the array structure and properties. Returns: - **`ArrayInfo`** ( `ArrayInfo` ) – Object containing array metadata such as data type, bounding box, and other array-specific information. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) array_info = view.info print(f"Data type: {array_info.data_type}") print(f"Shape: {array_info.bounding_box.size}") ``` ### mag ``` mag: Mag ``` Gets the magnification level of this view. The magnification level determines the resolution at which the data is accessed. A higher magnification number means lower resolution (e.g., mag 2 means every second voxel, mag 4 means every fourth voxel, etc.). Returns: - **`Mag`** ( `Mag` ) – The magnification level of this view. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) print(f"Current magnification: {view.mag}") ``` ### normalized_bounding_box ``` normalized_bounding_box: NormalizedBoundingBox ``` Gets the bounding box with axes normalized to include the channel dimension. Returns: - **`NormalizedBoundingBox`** ( `NormalizedBoundingBox` ) – Bounding box with channel axis included ### num_channels ``` num_channels: int ``` Gets the number of channels in this view. Returns: - **`int`** ( `int` ) – Number of channels ### read_only ``` read_only: bool ``` Indicates whether this view is read-only. When a view is read-only, write operations are not permitted. This property helps prevent accidental modifications to the dataset. Returns: - **`bool`** ( `bool` ) – True if the view is read-only, False if write operations are allowed. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) if not view.read_only: view.write(data) else: print("Cannot modify read-only view") ``` ### chunk ``` chunk( chunk_shape: VecIntLike, *, chunk_border_alignments: VecIntLike | None = None, read_only: bool | None = None ) -> Generator[View, None, None] ``` Generate a sequence of sub-views by chunking the current view. Divides the view into smaller, regularly-sized chunks that can be processed independently. This is useful for parallel processing or when working with large datasets that don't fit in memory. Parameters: - **`chunk_shape`** (`VecIntLike`) – Size of each chunk in Mag(1) coordinates. - **`chunk_border_alignments`** (`VecIntLike | None`, default: `None` ) – Alignment of chunk borders in Mag(1) coordinates. If None, aligns to (0, 0, 0). Defaults to None. - **`read_only`** (`bool`, default: `None` ) – Whether the generated chunks should be read-only. Defaults to self.read_only. Yields: - **`View`** ( `View` ) – Sub-views representing each chunk of the original view. Examples: ``` # let 'mag1' be a `MagView` chunks = mag1.chunk(chunk_shape=(100, 100, 100), chunk_border_alignments=(50, 50, 50)) ``` ### content_is_equal ``` content_is_equal( other: View, *, executor: Executor | None = None, progress_desc: str | None = None, chunk_shape: Vec3IntLike | None = None ) -> bool ``` Compare the content of this view with another view. Performs a chunk-by-chunk comparison of the data in both views. This is more memory efficient than reading entire views at once for large datasets. Parameters: - **`other`** (`View`) – The view to compare against. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel comparison. If None, compares sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Returns: - **`bool`** ( `bool` ) – True if the content of both views is identical, False otherwise. Examples: ``` # Compare views sequentially if view1.content_is_equal(view2): print("Views are identical") ``` Note - Comparison is done chunk by chunk to manage memory usage - Views must have the same shape and data type - Returns False immediately if shapes or types don't match - Progress tracks total volume compared - Parallel execution can speed up comparison of large views ### for_each_chunk ``` for_each_chunk( func_per_chunk: Callable[[tuple[View, int]], None], *, chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> None ``` Process each chunk of the view with a given function. Divides the view into chunks and applies a function to each chunk, optionally in parallel. This is useful for processing large datasets in manageable pieces, with optional progress tracking and parallel execution. Parameters: - **`func_per_chunk`** (`Callable[[tuple[View, int]], None]`) – Function to apply to each chunk. Takes a tuple of (chunk_view, chunk_index) as argument. The chunk_index can be used for progress tracking or logging. - **`chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of each chunk in Mag(1) coordinates. If None, uses one chunk per file based on the dataset's file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Examples: ``` from webknossos.utils import named_partial # Define processing function def process_chunk(args: tuple[View, int], threshold: float) -> None: chunk_view, chunk_idx = args data = chunk_view.read() # Process data... chunk_view.write(processed_data) print(f"Processed chunk {chunk_idx}") # Sequential processing with progress bar view.for_each_chunk( named_partial(process_chunk, threshold=0.5), chunk_shape=(64, 64, 64), progress_desc="Processing chunks" ) ``` Note - Each chunk is processed independently, making this suitable for parallel execution - For non-read-only views, chunks must align with file boundaries - Progress tracking shows total volume processed - Memory usage depends on chunk_shape and parallel execution settings - When using an executor, ensure thread/process safety in func_per_chunk - The view's magnification affects the actual data resolution ### for_zipped_chunks ``` for_zipped_chunks( func_per_chunk: Callable[ [tuple[View, View, int]], None ], target_view: View, *, source_chunk_shape: Vec3IntLike | None = None, target_chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> None ``` Process paired chunks from source and target views simultaneously. Chunks both the source (self) and target views, then applies a function to each corresponding pair of chunks. This is particularly useful for operations that transform data between views of different magnifications, like downsampling. Parameters: - **`func_per_chunk`** (`Callable[[tuple[View, View, int]], None]`) – Function to apply to each chunk pair. Takes (source_chunk, target_chunk, index) as arguments. - **`target_view`** (`View`) – The target view to write transformed data to. - **`source_chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of source chunks in Mag(1). If None, uses maximum of source and target file dimensions. Defaults to None. - **`target_chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of target chunks in Mag(1). If None, uses maximum of source and target file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Examples: ``` # Downsample data from Mag(1) to Mag(2) def downsample_chunk(args: tuple[View, View, int]) -> None: source_chunk, target_chunk, idx = args data = source_chunk.read() downsampled = downsample_data(data) # Your downsampling function target_chunk.write(downsampled) print(f"Processed chunk pair {idx}") # Process with default chunk sizes mag1_view.for_zipped_chunks( downsample_chunk, mag2_view, progress_desc="Downsampling data" ) ``` Note - Source/target view size ratios must match chunk size ratios - Target chunks must align with file boundaries to avoid concurrent writes - Both views are chunked with matching strides - Progress tracks total volume processed - Memory usage depends on chunk sizes and parallel execution ### get_buffered_slice_reader ``` get_buffered_slice_reader( buffer_size: int | None = None, dimension: str | int = "z", *, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, use_logging: bool = False ) -> BufferedSliceReader ``` Get a buffered reader for efficiently reading data slices. Creates a BufferedSliceReader that allows efficient reading of data slices by buffering multiple slices in memory. This is particularly useful when reading large datasets slice by slice. Parameters: - **`buffer_size`** (`int`, default: `None` ) – Number of slices to buffer in memory at once. Defaults to the size of the shard in the dimension. - **`dimension`** (`str | int`, default: `'z'` ) – Axis along which to read slices (0=x, 1=y, 2=z). Defaults to "z". - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates, relative to the current view's offset. Mutually exclusive with absolute_bounding_box. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_bounding_box. Defaults to None. - **`use_logging`** (`bool`, default: `False` ) – Whether to enable logging of read operations. Returns: - **`BufferedSliceReader`** ( `BufferedSliceReader` ) – A reader object that yields data slices. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) # Create a reader with default settings (z-slices) with view.get_buffered_slice_reader() as reader: for slice_data in reader: process_slice(slice_data) # Read y-slices with custom buffer size with view.get_buffered_slice_reader( buffer_size=10, dimension="y", relative_offset=(10, 0, 0) ) as reader: ``` Note - Larger buffer sizes improve performance but use more memory - Choose dimension based on your data access pattern - Only one positioning parameter should be specified - The reader can be used as an iterator ### get_buffered_slice_writer ``` get_buffered_slice_writer( buffer_size: int | None = None, dimension: str | int = "z", *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, use_logging: bool = False, allow_unaligned: bool = False ) -> BufferedSliceWriter ``` Get a buffered writer for efficiently writing data slices. Creates a BufferedSliceWriter that allows efficient writing of data slices by buffering multiple slices before performing the actual write operation. Parameters: - **`buffer_size`** (`int`, default: `None` ) – Number of slices to buffer before performing a write. Defaults to the size of the shard in the dimension. - **`dimension`** (`str | int`, default: `'z'` ) – Axis along which to write slices (0=x, 1=y, 2=z). Defaults to "z". - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset in mag1 coordinates, relative to the current view's position. Mutually exclusive with absolute_offset. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_offset. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates, relative to the current view's offset. Mutually exclusive with absolute_bounding_box. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box in mag1 coordinates in absolute dataset coordinates. Mutually exclusive with relative_bounding_box. Defaults to None. - **`use_logging`** (`bool`, default: `False` ) – Whether to enable logging of write operations. Defaults to False. - **`allow_unaligned`** (`bool`, default: `False` ) – Whether to allow unaligned writes. Defaults to False. Returns: - **`BufferedSliceWriter`** ( `BufferedSliceWriter` ) – A writer object for buffered slice writing. Examples: ``` view = layer.get_mag("1").get_view(size=(100, 100, 10)) # Create a buffered writer with default settings with view.get_buffered_slice_writer() as writer: # Write slices efficiently for z in range(10): slice_data = np.zeros((100, 100)) # Your slice data writer.send(slice_data) # Create a writer with custom buffer size and offset with view.get_buffered_slice_writer( buffer_size=5, relative_offset=(10, 10, 0) ) ``` Note - Larger buffer sizes can improve performance but use more memory - Remember to use the writer in a context manager - Only one positioning parameter should be specified ### get_dtype ``` get_dtype() -> dtype ``` Returns the dtype per channel of the data. For example `uint8`. ### get_view ``` get_view( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None, read_only: bool | None = None ) -> View ``` Create a new view restricted to a specified region. This method returns a new View instance that represents a subset of the current view's data. The new view can be specified using various coordinate systems and can optionally be made read-only. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of the new view. Must be specified when using any offset parameter. Defaults to None. ``` relative_offset (Vec3IntLike | None, optional): Offset relative to current view's position in Mag(1) coordinates. Must be used with size. Defaults to None. absolute_offset (Vec3IntLike | None, optional): Absolute offset in Mag(1) coordinates. Must be used with size. Defaults to None. relative_bounding_box (NDBoundingBox | None, optional): Bounding box relative to current view's position in Mag(1) coordinates. Defaults to None. absolute_bounding_box (NDBoundingBox | None, optional): Absolute bounding box in Mag(1) coordinates. Defaults to None. read_only (bool | None, optional): Whether the new view should be read-only. If None, inherits from parent view. Defaults to None. ``` Returns: - **`View`** ( `View` ) – A new View instance representing the specified region. Raises: - `AssertionError` – If: - Multiple positioning parameters are provided - Size is missing when using offset parameters - Non-read-only subview requested from read-only parent - Non-read-only subview extends beyond parent's bounds Examples: ``` # Create view from MagView mag1 = layer.get_mag("1") view = mag1.get_view(absolute_offset=(10, 20, 30), size=(100, 200, 300)) # Create subview within bounds sub_view = view.get_view( relative_offset=(50, 60, 70), size=(10, 120, 230) ) # Create read-only subview (can extend beyond bounds) large_view = view.get_view( relative_offset=(50, 60, 70), size=(999, 120, 230), read_only=True ) # Use bounding box instead of offset+size bbox = BoundingBox((10, 10, 0), (50, 50, 10)) bbox_view = view.get_view(relative_bounding_box=bbox) ``` Note - Use only one method to specify the region (offset+size or bounding_box) - All coordinates are in Mag(1) - Non-read-only views must stay within parent view's bounds - Read-only views can extend beyond parent view's bounds - The view's magnification affects the actual data resolution ### map_chunk ``` map_chunk( func_per_chunk: Callable[[View], Any], *, chunk_shape: Vec3IntLike | None = None, executor: Executor | None = None, progress_desc: str | None = None ) -> list[Any] ``` Process each chunk of the view and collect results. Similar to for_each_chunk(), but collects and returns the results from each chunk. Useful for parallel data analysis or feature extraction where results need to be aggregated. Parameters: - **`func_per_chunk`** (`Callable[[View], Any]`) – Function to apply to each chunk. Takes a chunk view as argument and returns a result of any type. - **`chunk_shape`** (`Vec3IntLike | None`, default: `None` ) – Size of each chunk in Mag(1) coordinates. If None, uses one chunk per file based on the dataset's file dimensions. Defaults to None. - **`executor`** (`Executor | None`, default: `None` ) – Executor for parallel processing. If None, processes chunks sequentially. Defaults to None. - **`progress_desc`** (`str | None`, default: `None` ) – Description for progress bar. If None, no progress bar is shown. Defaults to None. Returns: - `list[Any]` – list\[Any\]: List of results from processing each chunk, in chunk order. Examples: ``` from webknossos.utils import named_partial # Calculate statistics per chunk def chunk_statistics(view: View, min_value: float) -> dict[str, float]: data = view.read() return { "mean": data[data > min_value].mean(), "std": data[data > min_value].std(), "volume": view.bounding_box.volume() } # Sequential processing stats = view.map_chunk( named_partial(chunk_statistics, min_value=0.1), chunk_shape=(128, 128, 128) ) # Aggregate results total_volume = sum(s["volume"] for s in stats) mean_values = [s["mean"] for s in stats] ``` Note - Results are collected in memory, consider memory usage for large datasets - Each chunk is processed independently, suitable for parallel execution - For non-read-only views, chunks must align with file boundaries - When using an executor, ensure thread/process safety in func_per_chunk - Results maintain chunk order regardless of execution order ### read ``` read( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read data from the view at a specified location. This method provides flexible ways to read data from the view's region. If no parameters are provided, it reads the entire view's bounding box. The region to read can be specified using either offset+size combinations or bounding boxes. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of region to read. Specified in Mag(1) coordinates. Defaults to None. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to the view's position in Mag(1) coordinates. Must be used with size. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Must be used with size. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: The requested data as a numpy array. The shape will be (channels, x, y, z). Areas outside the dataset are zero-padded. Raises: - `AssertionError` – If incompatible parameters are provided (e.g., both offset+size and bounding_box) or if the requested region is empty. Examples: ``` # Read entire view's data view = layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read() # Returns (1, x, y, z) array for single-channel data # Read with relative offset and size data = view.read( relative_offset=(10, 10, 0), # Offset from view's position size=(50, 50, 10) # Size in Mag(1) coordinates ) # Read with absolute bounding box bbox = BoundingBox((0, 0, 0), (100, 100, 10)) data = view.read(absolute_bounding_box=bbox) # Read from multi-channel data view = color_layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read() # Returns (channels, x, y, z) array ``` Note - Use only one method to specify the region (offset+size or bounding_box) - All coordinates are in Mag(1) - The returned array always has the shape (C, X, Y, Z), even for single channel data - Regions outside the dataset are automatically zero-padded - The view's magnification affects the actual data resolution - Data shape must match the target region size ### read_cxyz ``` read_cxyz( size: Vec3IntLike | None = None, *, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read data from the view and return it in `(c, x, y, z)` axis order. Equivalent to :meth:`read` but always returns a 4-D array ordered as `(channels, x, y, z)` regardless of the underlying storage axis ordering. If the array does not have a channel axis, one of size 1 is added. Parameters: - **`size`** (`Vec3IntLike | None`, default: `None` ) – Size of region to read in Mag(1) coordinates. Defaults to None. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to the view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: Data as a 4-D numpy array with shape (c, x, y, z). Areas outside the dataset are zero-padded. Examples: ``` # Read entire view's data in cxyz order view = layer.get_mag("1").get_view(size=(100, 100, 10)) data = view.read_cxyz() # Always returns (c, x, y, z) array # Read with relative offset and size data = view.read_cxyz(relative_offset=(10, 10, 0), size=(50, 50, 10)) ``` ### read_xyz ``` read_xyz( *, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> ndarray ``` Read n-dimensional data and convert it to 3D XYZ format. This method is designed for handling n-dimensional data (n > 3) and converting it to strictly 3D data ordered as (X, Y, Z). It is primarily used internally by operations that require 3D data like downsampling, upsampling, and compression. When provided with a BoundingBox where additional dimensions (beyond X, Y, Z) have a shape of 1, it returns an array containing only the 3D spatial data. This ensures compatibility with operations that expect purely 3-dimensional input. Parameters: - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Returns: - `ndarray` – np.ndarray: The requested data as a numpy array with dimensions ordered as (channels, X, Y, Z) data. Areas outside the dataset are zero-padded. Examples: ``` # Read entire view's data in XYZ order view = layer.get_mag("1").get_view(size=(100, 100, 10)) xyz_data = view.read_xyz() # Returns (X, Y, Z) array # Read with relative bounding box bbox = NDBoundingBox((10, 10, 0), (50, 50, 10), axis=("x", "y", "z"), index=(1, 2, 3)) xyz_data = view.read_xyz(relative_bounding_box=bbox) ``` Note - If no bounding box is provided, reads the entire view's region - Only one bounding box parameter should be specified - The returned array's axes are ordered differently from read() - All coordinates are in Mag(1) ### write ``` write( data: ndarray, *, allow_unaligned: bool = False, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> None ``` Write data to the view at a specified location. This method writes array data to the view's region. If no position parameters are provided, data is written to the view's bounding box. The write location can be specified using either offset parameters or bounding boxes. Parameters: - **`data`** (`ndarray`) – The data to write. For 3D data, shape should be (x, y, z). For multi-channel 3D data, shape should be (channels, x, y, z). For n-dimensional data, the axes must match the bounding box axes of the layer. Shape must match the target region size. - **`allow_unaligned`** (`bool`, default: `False` ) – If True, allows writing data to without being aligned to the shard shape. Defaults to False. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. Raises: - `AssertionError` – If: - View is read-only - Data dimensions don't match the target region - Number of channels doesn't match the dataset - Write region is outside the view's bounding box - Multiple positioning parameters are provided Examples: ``` import numpy as np from webknossos.dataset import Dataset, View # Write to entire view's region view = layer.get_mag("1").get_view(size=(100, 100, 10)) data = np.zeros(view.bounding_box.in_mag(view.mag).size) view.write(data) # Write with relative offset data = np.ones((50, 50, 5)) # Smaller region view.write(data, relative_offset=(10, 10, 0)) # Write multi-channel data rgb_data = np.zeros((3, 100, 100, 10)) # 3 channels rgb_view = color_layer.get_mag("1").get_view(size=(100, 100, 10)) rgb_view.write(rgb_data) # Write with absolute bounding box bbox = BoundingBox((0, 0, 0), (100, 100, 10)) view.write(data, absolute_bounding_box=bbox) ``` Note - Only one positioning parameter (offset or bounding_box) should be used - For compressed data, writes should align with shards - For segmentation layers, call refresh_largest_segment_id() after writing - The view's magnification affects the actual data resolution - Data shape must match the target region size ### write_cxyz ``` write_cxyz( data: ndarray, *, allow_unaligned: bool = False, relative_offset: Vec3IntLike | None = None, absolute_offset: Vec3IntLike | None = None, relative_bounding_box: NDBoundingBox | None = None, absolute_bounding_box: NDBoundingBox | None = None ) -> None ``` Write data from a (c, x, y, z) ordered array to the view. Accepts data always in `(c, x, y, z)` axis order regardless of the underlying storage axis ordering, reordering axes internally as needed. Parameters: - **`data`** (`ndarray`) – 4D array in (c, x, y, z) order. - **`allow_unaligned`** (`bool`, default: `False` ) – If True, allows writing data without being aligned to the shard shape. Defaults to False. - **`relative_offset`** (`Vec3IntLike | None`, default: `None` ) – Offset relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_offset`** (`Vec3IntLike | None`, default: `None` ) – Absolute offset in Mag(1) coordinates. Defaults to None. - **`relative_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Bounding box relative to view's position in Mag(1) coordinates. Defaults to None. - **`absolute_bounding_box`** (`NDBoundingBox | None`, default: `None` ) – Absolute bounding box in Mag(1) coordinates. Defaults to None. # webknossos.dataset_properties ## AttachmentDataFormat Bases: `Enum` ### HDF5 ``` HDF5 = 'hdf5' ``` ### JSON ``` JSON = 'json' ``` ### Zarr3 ``` Zarr3 = 'zarr3' ``` ## DataFormat Bases: `Enum` ### N5 ``` N5 = 'n5' ``` ### NeuroglancerPrecomputed ``` NeuroglancerPrecomputed = 'neuroglancerPrecomputed' ``` ### WKW ``` WKW = 'wkw' ``` ### Zarr ``` Zarr = 'zarr' ``` ### Zarr3 ``` Zarr3 = 'zarr3' ``` # webknossos.dataset_properties ## AttachmentProperties ### data_format ``` data_format: AttachmentDataFormat ``` ### name ``` name: str ``` ### path ``` path: str ``` ## AttachmentsProperties ### agglomerates ``` agglomerates: list[AttachmentProperties] | None = None ``` ### connectomes ``` connectomes: list[AttachmentProperties] | None = None ``` ### cumsum ``` cumsum: AttachmentProperties | None = None ``` ### meshes ``` meshes: list[AttachmentProperties] | None = None ``` ### segment_index ``` segment_index: AttachmentProperties | None = None ``` ## DatasetProperties ### data_layers ``` data_layers: list[ SegmentationLayerProperties | LayerProperties ] ``` ### default_view_configuration ``` default_view_configuration: ( DatasetViewConfiguration | None ) = None ``` ### id ``` id: dict[str, str] ``` id is a legacy field that is not used anymore. Its keys are name (dataset directory name) and team (organization id) However, WEBKNOSSOS will take both from the dataset path and not from what is here in the datasource-properties.json. ### scale ``` scale: VoxelSize ``` ### version ``` version: int ``` A default version is set during structuring ### update_for_layer ``` update_for_layer( layer_name: str, layer_properties: LayerProperties ) -> None ``` ## DatasetViewConfiguration Stores information on how the dataset is shown in WEBKNOSSOS by default. ### blend_mode ``` blend_mode: str | None = None ``` ### color_layer_order ``` color_layer_order: list[str] | None = None ``` ### four_bit ``` four_bit: bool | None = None ``` ### interpolation ``` interpolation: bool | None = None ``` ### layers ``` layers: dict[str, LayerViewConfiguration] | None = None ``` ### loading_strategy ``` loading_strategy: str | None = None ``` ### natively_rendered_layer_name ``` natively_rendered_layer_name: str | None = None ``` ### position ``` position: tuple[int, int, int] | None = None ``` ### render_missing_data_black ``` render_missing_data_black: bool | None = None ``` ### rotation ``` rotation: tuple[int, int, int] | None = None ``` ### segmentation_pattern_opacity ``` segmentation_pattern_opacity: int | None = None ``` ### zoom ``` zoom: float | None = None ``` ## LayerProperties ### bounding_box ``` bounding_box: NormalizedBoundingBox ``` ### category ``` category: LayerCategoryType ``` ### data_format ``` data_format: DataFormat ``` ### default_view_configuration ``` default_view_configuration: ( LayerViewConfiguration | None ) = None ``` ### dtype ``` dtype: str ``` ### dtype_np ``` dtype_np: dtype ``` ### mags ``` mags: list[MagViewProperties] ``` ### name ``` name: str ``` ## LayerViewConfiguration Stores information on how the dataset is shown in webknossos by default. ### alpha ``` alpha: float | None = None ``` Alpha value from 0 to 100. The WEBKNOSSOS default is 100 except for segmentation layers where it is 20. ### color ``` color: tuple[int, int, int] | None = None ``` Color in RGB from 0 to 255. The WEBKNOSSOS default is [255, 255, 255]. ### intensity_range ``` intensity_range: tuple[float, float] | None = None ``` Min and max data value range (dependent on the layer's data type). Can be used to threshold the value range. The WEBKNOSSOS default is the full value range. ### is_disabled ``` is_disabled: bool | None = None ``` Disable a layer. The WEBKNOSSOS default is False. ### is_in_edit_mode ``` is_in_edit_mode: bool | None = None ``` Enable the histogram edit mode. The WEBKNOSSOS default is False. ### is_inverted ``` is_inverted: bool | None = None ``` Invert a layer. The WEBKNOSSOS default is False. ### mapping ``` mapping: dict[str, str] | None = None ``` Enables ID mapping for a segmentation layer and applies the selected mapping by default. The default WK behavior is to disable ID mapping. Expected values is a Dict with {"name": my_mapping_name, "type": "HDF5"}. ### max ``` max: float | None = None ``` Maximum data value that might be encountered. This will restrict the histogram in WEBKNOSSOS and possibly overwrite the max value of the `intensityRange` (if that is higher). ### min ``` min: float | None = None ``` Minimum data value that might be encountered. This will restrict the histogram in WEBKNOSSOS and possibly overwrite the min value of the `intensityRange` (if that is lower). ## MagViewProperties ### cube_length ``` cube_length: int | None = None ``` ### mag ``` mag: Mag ``` ### path ``` path: str | None = None ``` Could be None for older datasource-proterties.json files. ## SegmentationLayerProperties Bases: `LayerProperties` ### attachments ``` attachments: AttachmentsProperties = field( factory=AttachmentsProperties ) ``` ### bounding_box ``` bounding_box: NormalizedBoundingBox ``` ### category ``` category: LayerCategoryType ``` ### data_format ``` data_format: DataFormat ``` ### default_view_configuration ``` default_view_configuration: ( LayerViewConfiguration | None ) = None ``` ### dtype ``` dtype: str ``` ### dtype_np ``` dtype_np: dtype ``` ### largest_segment_id ``` largest_segment_id: int | None = None ``` ### mags ``` mags: list[MagViewProperties] ``` ### mappings ``` mappings: list[str] = [] ``` ### name ``` name: str ``` ## VoxelSize ### factor ``` factor: tuple[float, float, float] = field( converter=float_tpl ) ``` ### unit ``` unit: LengthUnit = DEFAULT_LENGTH_UNIT ``` ### to_nanometer ``` to_nanometer() -> tuple[float, float, float] ``` # webknossos.dataset_properties ## LengthUnit Bases: `Enum` ### ANGSTROM ``` ANGSTROM = 'angstrom' ``` ### ATTOMETER ``` ATTOMETER = 'attometer' ``` ### CENTIMETER ``` CENTIMETER = 'centimeter' ``` ### DECIMETER ``` DECIMETER = 'decimeter' ``` ### EXAMETER ``` EXAMETER = 'exameter' ``` ### FEMTOMETER ``` FEMTOMETER = 'femtometer' ``` ### FOOT ``` FOOT = 'foot' ``` ### GIGAMETER ``` GIGAMETER = 'gigameter' ``` ### HECTOMETER ``` HECTOMETER = 'hectometer' ``` ### INCH ``` INCH = 'inch' ``` ### KILOMETER ``` KILOMETER = 'kilometer' ``` ### MEGAMETER ``` MEGAMETER = 'megameter' ``` ### METER ``` METER = 'meter' ``` ### MICROMETER ``` MICROMETER = 'micrometer' ``` ### MILE ``` MILE = 'mile' ``` ### MILLIMETER ``` MILLIMETER = 'millimeter' ``` ### NANOMETER ``` NANOMETER = 'nanometer' ``` ### PARSEC ``` PARSEC = 'parsec' ``` ### PETAMETER ``` PETAMETER = 'petameter' ``` ### PICOMETER ``` PICOMETER = 'picometer' ``` ### TERAMETER ``` TERAMETER = 'terameter' ``` ### YARD ``` YARD = 'yard' ``` ### YOCTOMETER ``` YOCTOMETER = 'yoctometer' ``` ### YOTTAMETER ``` YOTTAMETER = 'yottameter' ``` ### ZEPTOMETER ``` ZEPTOMETER = 'zeptometer' ``` ### ZETTAMETER ``` ZETTAMETER = 'zettameter' ``` # webknossos.datastore ## Datastore Datastore class for managing datastores. ### allows_upload ``` allows_upload: bool ``` ### name ``` name: str ``` ### url ``` url: str ``` ### get_datastores ``` get_datastores( allows_upload: bool | None = None, ) -> list[Datastore] ``` Get a list of all datastore URLs. Parameters: - **`allows_upload`** (`bool | None`, default: `None` ) – Optional filter for datastores that allow or deny dataset uploads (None for all) Returns: - `list[Datastore]` – List of datastore URLs Examples: ``` # Get a list of all datastores that allow dataset uploads datastores = Dataset.get_upload_datastores() ``` ### get_upload_url ``` get_upload_url() -> str ``` Get URL for uploading a dataset. Returns: - `str` – Upload URL Examples: ``` # Get the upload URL for the first datastore that allows dataset uploads upload_url = Datastore.get_upload_url() ``` # webknossos.geometry ## BoundingBox Bases: `NDBoundingBox` An axis-aligned 3D bounding box with integer coordinates. This class represents a axis-aligned cuboid in 3D space. The top-left coordinate is inclusive and the bottom-right coordinate is exclusive, defining a volume in space. A small usage example: ``` from webknossos import BoundingBox bbox_1 = BoundingBox((0, 0, 0), (100, 100, 100)) bbox_2 = BoundingBox((75, 75, 75), (100, 100, 100)) assert bbox_1.intersected_with(bbox_2).size == (25, 25, 25) ``` Attributes: - **`topleft`** (`Vec3Int`) – Top-left corner coordinates (inclusive) - **`size`** (`Vec3Int`) – Size of the bounding box in units of voxels for each dimension (width, height, depth) - **`axes`** (`tuple[str, str, str]`) – Names of the coordinate axes, defaults to ("x", "y", "z") - **`index`** (`Vec3Int`) – Index values for each dimension, defaults to (1, 2, 3) - **`bottomright`** (`Vec3Int`) – Bottom-right corner coordinates (exclusive), computed from topleft + size - **`name`** (`str | None`) – Optional name for the bounding box, defaults to "Unnamed Bounding Box" - **`is_visible`** (`bool`) – Whether the bounding box should be visible, defaults to True - **`color`** (`tuple[float, float, float, float] | None`) – Optional RGBA color values ### axes ``` axes: tuple[str, str, str] = field(default=('x', 'y', 'z')) ``` ### bottomright ``` bottomright: Vec3Int = field(init=False) ``` ### bottomright_xyz ``` bottomright_xyz: Vec3Int ``` The bottomright corner of the bounding box regarding only x, y and z axis. ### color ``` color: tuple[float, float, float, float] | None = None ``` ### index ``` index: Vec3Int = field(default=Vec3Int(1, 2, 3)) ``` ### index_xyz ``` index_xyz: Vec3Int ``` The index of x, y and z axis within the bounding box. ### is_visible ``` is_visible: bool = True ``` ### name ``` name: str | None = _DEFAULT_BBOX_NAME ``` ### ndim ``` ndim: int ``` The number of dimensions of the bounding box. ### size ``` size: Vec3Int = field(converter=Vec3Int) ``` ### size_xyz ``` size_xyz: Vec3Int ``` The size of the bounding box regarding only x, y and z axis. ### topleft ``` topleft: Vec3Int = field(converter=Vec3Int) ``` ### topleft_xyz ``` topleft_xyz: Vec3Int ``` The topleft corner of the bounding box regarding only x, y and z axis. ### align_with_mag ``` align_with_mag( mag: Mag | Vec3Int, ceil: bool = False ) -> BoundingBox ``` Rounds the bounding box, so that both topleft and bottomright are divisible by mag. Parameters: - **`mag`** (`Mag`) – The mag to align with. - **`ceil`** (`bool`, default: `False` ) – If true, the bounding box is enlarged when necessary. If false, it's shrunk when necessary. Returns: - **`BoundingBox`** ( `BoundingBox` ) – The aligned bounding box. ### chunk ``` chunk( chunk_shape: Vec3IntLike, chunk_border_alignments: Vec3IntLike | None = None, ) -> Generator[BoundingBox, None, None] ``` Decompose the bounding box into smaller chunks of size `chunk_shape`. Parameters: - **`chunk_shape`** (`Vec3IntLike`) – Size of chunks to decompose into. Each chunk will be at most this size. - **`chunk_border_alignments`** (`Vec3IntLike | None`, default: `None` ) – If provided, all border coordinates between chunks will be divisible by these values. Yields: - **`BoundingBox`** ( `BoundingBox` ) – Smaller chunks of the original bounding box. Border chunks may be smaller than chunk_shape. Raises: - `AssertionError` – If chunk_border_alignments is provided and chunk_shape is not divisible by it. Note - Border chunks may be smaller than chunk_shape - If chunk_border_alignments is provided, all border coordinates between chunks will be aligned to those values ### contains ``` contains(coord: Vec3IntLike | ndarray) -> bool ``` Check whether a point is inside of the bounding box. Note that the point may have float coordinates in the ndarray case ### contains_bbox ``` contains_bbox( inner_bbox: BoundingBox | NormalizedBoundingBox, ) -> bool ``` Check whether a bounding box is completely inside this bounding box. When checking containment of a NormalizedBoundingBox, only the spatial (x, y, z) dimensions are considered, ignoring the channel axis. ### denormalize ``` denormalize() -> NDBoundingBox ``` ### empty ``` empty() -> BoundingBox ``` ### extended_by ``` extended_by( other: NormalizedBoundingBox, ) -> NormalizedBoundingBox ``` ``` extended_by(other: BoundingBox) -> BoundingBox ``` ``` extended_by( other: BoundingBox | NormalizedBoundingBox, ) -> BoundingBox | NormalizedBoundingBox ``` Returns the smallest bounding box that contains both bounding boxes. When extending with a NormalizedBoundingBox, the operation is performed on the spatial (x, y, z) dimensions only, ignoring the channel axis. The result is a NormalizedBoundingBox with the channel count preserved from the NormalizedBoundingBox operand. ### from_auto ``` from_auto( obj: Union[BoundingBox, str, dict, list, tuple], ) -> BoundingBox ``` ### from_checkpoint_name ``` from_checkpoint_name(checkpoint_name: str) -> BoundingBox ``` This function extracts a bounding box in the format `x_y_z_sx_sy_xz` which is contained in a string. ### from_config_dict ``` from_config_dict(bbox: dict) -> BoundingBox ``` Creates a BoundingBox from a config-format dictionary. Parameters: - **`bbox`** (`Dict`) – Dictionary containing config-format bounding box data with keys 'topleft' and 'size' Returns: - **`BoundingBox`** ( `BoundingBox` ) – A new bounding box with the specified dimensions ### from_csv ``` from_csv(csv_bbox: str) -> BoundingBox ``` ### from_mag_to_mag1 ``` from_mag_to_mag1(from_mag: Mag) -> _T ``` Returns the bounging box in the finest magnification (Mag(1)). Parameters: - **`from_mag`** (`Mag`) – The current magnification of the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – The bounding box in the given magnification. ### from_ndbbox ``` from_ndbbox(bbox: NDBoundingBox) -> BoundingBox ``` ### from_points ``` from_points(points: Iterable[Vec3IntLike]) -> BoundingBox ``` Returns a bounding box which is guaranteed to completely enclose all points in the input. Parameters: - **`points`** (`Iterable[Vec3IntLike]`) – Set of points to be bounded. Each point must be convertible to Vec3Int. Returns: - **`BoundingBox`** ( `BoundingBox` ) – A bounding box that is the minimum size needed to contain all input points.exactly containing all points. ### from_tuple2 ``` from_tuple2( tuple2: tuple[Vec3IntLike, Vec3IntLike], ) -> BoundingBox ``` Creates a BoundingBox from a 2-tuple of coordinates. Parameters: - **`tuple2`** (`tuple[Vec3IntLike, Vec3IntLike]`) – A tuple containing the topleft coordinates and size dimensions Returns: - **`BoundingBox`** ( `BoundingBox` ) – A new bounding box with the specified dimensions ### from_tuple6 ``` from_tuple6( tuple6: tuple[int, int, int, int, int, int], ) -> BoundingBox ``` Creates a BoundingBox from a 6-tuple of coordinates. Parameters: - **`tuple6`** (`tuple[int, int, int, int, int, int]`) – A tuple containing (x, y, z) coordinates followed by (width, height, depth) dimensions Returns: - **`BoundingBox`** ( `BoundingBox` ) – A new bounding box with the specified dimensions ### get_bounds ``` get_bounds(axis: str) -> tuple[int, int] ``` Returns the bounds of the given axis. Parameters: - **`axis`** (`str`) – The name of the axis to get the bounds for. Returns: - `tuple[int, int]` – tuple\[int, int\]: A tuple containing the top-left and bottom-right coordinates along the specified axis. ### get_shape ``` get_shape(axis_name: str) -> int ``` Returns the size of the bounding box along the specified axis. Parameters: - **`axis_name`** (`str`) – The name of the axis to get the size for. Returns: - **`int`** ( `int` ) – The size of the bounding box along the specified axis. ### group_boxes_with_aligned_mag ``` group_boxes_with_aligned_mag( bounding_boxes: Iterable[NDBoundingBox], aligning_mag: Mag, ) -> dict[NDBoundingBox, list[NDBoundingBox]] ``` Groups the given BoundingBox instances by aligning each bbox to the given mag and using that as the key. For example, bounding boxes of size 256**3 could be grouped into the corresponding 1024**3 chunks to which they belong by using aligning_mag = Mag(1024). ### in_mag ``` in_mag(mag: Mag) -> BoundingBox ``` Returns a new bounding box with coordinates scaled by the given magnification factor. The method asserts that both topleft and bottomright coordinates are already properly aligned with the magnification factor. Use align_with_mag() first if needed. Parameters: - **`mag`** (`Mag`) – The magnification factor to scale coordinates by Returns: - **`BoundingBox`** ( `BoundingBox` ) – A new bounding box with coordinates divided by the magnification factor Raises: - `AssertionError` – If topleft or bottomright coordinates are not aligned with mag ### intersected_with ``` intersected_with( other: NormalizedBoundingBox, dont_assert: bool = False ) -> NormalizedBoundingBox ``` ``` intersected_with( other: BoundingBox, dont_assert: bool = False ) -> BoundingBox ``` ``` intersected_with( other: BoundingBox | NormalizedBoundingBox, dont_assert: bool = False, ) -> BoundingBox | NormalizedBoundingBox ``` Returns the intersection of two bounding boxes. When intersecting with a NormalizedBoundingBox, the operation is performed on the spatial (x, y, z) dimensions only, ignoring the channel axis. The result is a NormalizedBoundingBox with the channel count preserved from the NormalizedBoundingBox operand. ### is_empty ``` is_empty() -> bool ``` Checks if the bounding box has zero or negative size. Tests if any dimension of the bounding box has zero or negative size. Returns: - **`bool`** ( `bool` ) – True if any dimension has zero or negative size, False otherwise. ### normalize_axes ``` normalize_axes(num_channels: int) -> NormalizedBoundingBox ``` ### offset ``` offset(vector: Vec3IntLike) -> BoundingBox ``` Creates an offset copy of this bounding box by adding a vector to the topleft coordinate. Generates a new bounding box with identical dimensions but translated by the given vector. Parameters: - **`vector`** (`Vec3IntLike`) – The vector to offset the bounding box by Returns: - **`BoundingBox`** ( `BoundingBox` ) – A new bounding box offset by the given vector ### padded_with_margins ``` padded_with_margins( margins_left: Vec3IntLike, margins_right: Vec3IntLike | None = None, ) -> _T ``` ### slice_array ``` slice_array(array: ndarray) -> ndarray ``` Returns a slice of the given array that corresponds to the bounding box. ### to_checkpoint_name ``` to_checkpoint_name() -> str ``` Converts the bounding box dimensions to a checkpoint name string. Creates a string formatted as "x_y_z_width_height_depth" containing the bounding box coordinates and dimensions. Returns: - **`str`** ( `str` ) – A string in checkpoint name format containing the bounding box dimensions ### to_config_dict ``` to_config_dict() -> dict ``` Converts the bounding box to a config-format dictionary. Creates a dictionary with config-format fields containing the bounding box dimensions. Returns: - **`dict`** ( `dict` ) – A dictionary with keys: - topleft: list[int] of (x,y,z) coordinates - size: list[int] of (width,height,depth) dimensions ### to_csv ``` to_csv() -> str ``` Converts the bounding box coordinates to a comma-separated string. Creates a string containing the bounding box coordinates and dimensions in comma-separated format. Returns: - **`str`** ( `str` ) – A comma-separated string containing: - First three values: (x,y,z) coordinates of topleft - Last three values: (width,height,depth) dimensions ### to_slices ``` to_slices() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box. ### to_slices_xyz ``` to_slices_xyz() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box in x, y, z and leaves all other axes one dimensional without offset. ### to_tuple6 ``` to_tuple6() -> tuple[int, int, int, int, int, int] ``` Converts the bounding box coordinates to a 6-tuple. Creates a tuple containing the bounding box coordinates and dimensions. Returns: - `tuple[int, int, int, int, int, int]` – tuple\[int, int, int, int, int, int\]: A tuple containing: - First three values: (x,y,z) coordinates of topleft - Last three values: (width,height,depth) dimensions ### volume ``` volume() -> int ``` Returns the volume of the bounding box. ### with_bottomright ``` with_bottomright(new_bottomright: VecIntLike) -> _T ``` Returns a new NDBoundingBox with an updated bottomright value. Parameters: - **`new_bottomright`** (`VecIntLike`) – The new bottom right corner coordinates. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated bottom right corner. ### with_bottomright_xyz ``` with_bottomright_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the bottomright corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. ### with_bounds ``` with_bounds( axis: str, new_topleft: int | None = None, new_size: int | None = None, ) -> _T ``` Returns a new NDBoundingBox object with updated bounds along the specified axis. Parameters: - **`axis`** (`str`) – The name of the axis to update. - **`new_topleft`** (`int | None`, default: `None` ) – The new value for the top-left coordinate along the specified axis. - **`new_size`** (`int | None`, default: `None` ) – The new size along the specified axis. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with updated bounds. Raises: - `KeyError` – If the given axis name does not exist. ### with_bounds_x ``` with_bounds_x( new_topleft_x: int | None = None, new_size_x: int | None = None, ) -> BoundingBox ``` Returns a copy of the bounding box with topleft.x optionally replaced and size.x optionally replaced. ### with_bounds_y ``` with_bounds_y( new_topleft_y: int | None = None, new_size_y: int | None = None, ) -> BoundingBox ``` Returns a copy of the bounding box with topleft.y optionally replaced and size.y optionally replaced. ### with_bounds_z ``` with_bounds_z( new_topleft_z: int | None = None, new_size_z: int | None = None, ) -> BoundingBox ``` Returns a copy of the bounding box with topleft.z optionally replaced and size.z optionally replaced. ### with_color ``` with_color(color: tuple[float, float, float, float]) -> _T ``` Returns a new instance of NDBoundingBox with the specified color. Parameters: - **`color`** (`tuple[float, float, float, float] | None`) – The color to set for the bounding box. The color should be specified as a tuple of four floats representing RGBA values. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified color. ### with_index ``` with_index(new_index: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified index. Parameters: - **`new_index`** (`VecIntLike`) – The new axis order for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated index. ### with_index_xyz ``` with_index_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z index. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z index for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z index. ### with_is_visible ``` with_is_visible(is_visible: bool) -> _T ``` Returns a new NDBoundingBox object with the specified visibility. Parameters: - **`is_visible`** (`bool`) – The visibility value to set. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated visibility value. ### with_name ``` with_name(name: str | None) -> _T ``` Returns a new instance of `NDBoundingBox` with the specified name. Parameters: - **`name`** (`str | None`) – The name to assign to the new NDBoundingBox instance. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified name. ### with_size ``` with_size(new_size: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified size. Parameters: - **`new_size`** (`VecIntLike`) – The new size of the bounding box. Can be a VecInt or any object that can be converted to a VecInt. Returns: - `_T` – A new NDBoundingBox object with the specified size. ### with_size_xyz ``` with_size_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z size. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z size for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z size. ### with_topleft ``` with_topleft(new_topleft: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified top left coordinates. Parameters: - **`new_topleft`** (`VecIntLike`) – The new top left coordinates for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated top left coordinates. ### with_topleft_xyz ``` with_topleft_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the topleft corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. ### xyz_array_to_bbox_shape ``` xyz_array_to_bbox_shape(data: ndarray) -> ndarray ``` Transforms data array with xyz axes to the shape of the bounding box. This is only possible for bboxes that are flat in all dimensions except xyz. # webknossos.geometry ## Mag Represents the magnification level of a data layer. The magnification level indicates the downsampling factor from the original data. Examples: Non-downsampled finest quality: ``` mag = Mag(1) ``` 4x downsampling in all dimensions: `` ` mag = Mag(4) `` Anisotropic downsampling: ``` mag = Mag(2, 2, 1) # 2x in x,y dimensions, no downsampling in z ``` ### max_dim ``` max_dim: int ``` ### max_dim_log2 ``` max_dim_log2: int ``` ### x ``` x: int ``` ### y ``` y: int ``` ### z ``` z: int ``` ### to_layer_name ``` to_layer_name() -> str ``` ### to_list ``` to_list() -> list[int] ``` ### to_long_layer_name ``` to_long_layer_name() -> str ``` ### to_np ``` to_np() -> ndarray ``` ### to_tuple ``` to_tuple() -> tuple[int, int, int] ``` ### to_vec3_int ``` to_vec3_int() -> Vec3Int ``` # webknossos.geometry ## NDBoundingBox A generalized N-dimensional bounding box that can handle arbitrary dimensions. The NDBoundingBox represents an N-dimensional rectangular region defined by its top-left corner coordinates and size. Each dimension has an associated axis name and index for ordering. Parameters: - **`topleft`** – The coordinates of the upper-left corner (inclusive) - **`size`** – The size/extent in each dimension - **`axes`** – The names of the axes/dimensions (e.g. "x", "y", "z", "t") - **`index`** – The order/position of each axis, starting from 0. Deprecated, index is inferred from axes. - **`name`** – Optional name for this bounding box - **`is_visible`** – Whether this bounding box should be visible - **`color`** – Optional RGBA color tuple (4 floats) for display Examples: Create a 2D bounding box: ``` bbox_1 = NDBoundingBox( topleft=(0, 0), size=(100, 100), axes=("x", "y"), ) ``` Create a 4D bounding box: ``` bbox_2 = NDBoundingBox( topleft=(75, 75, 75, 0), size=(100, 100, 100, 20), axes=("x", "y", "z", "t"), ) ``` Note - The top-left coordinate is inclusive while bottom-right is exclusive - Each axis must have a unique dense index starting from 0 ### axes ``` axes: tuple[str, ...] = field( converter=str_iterable_to_tuple ) ``` ### bottomright ``` bottomright: VecInt = field(init=False) ``` ### bottomright_xyz ``` bottomright_xyz: Vec3Int ``` The bottomright corner of the bounding box regarding only x, y and z axis. ### color ``` color: tuple[float, float, float, float] | None = None ``` ### index ``` index: VecInt = field( converter=parse_vec_int_or_none, default=None ) ``` ### index_xyz ``` index_xyz: Vec3Int ``` The index of x, y and z axis within the bounding box. ### is_visible ``` is_visible: bool = True ``` ### name ``` name: str | None = _DEFAULT_BBOX_NAME ``` ### ndim ``` ndim: int ``` The number of dimensions of the bounding box. ### size ``` size: VecInt = field(converter=parse_vec_int) ``` ### size_xyz ``` size_xyz: Vec3Int ``` The size of the bounding box regarding only x, y and z axis. ### topleft ``` topleft: VecInt = field(converter=parse_vec_int) ``` ### topleft_xyz ``` topleft_xyz: Vec3Int ``` The topleft corner of the bounding box regarding only x, y and z axis. ### align_with_mag ``` align_with_mag( mag: Mag | Vec3Int, ceil: bool = False ) -> _T ``` Rounds the bounding box, so that both topleft and bottomright are divisible by mag. Parameters: - **`mag`** (`Mag | Vec3Int`) – The magnification to align the bounding box to. - **`ceil`** (`bool`, default: `False` ) – If True, the bounding box is enlarged when necessary. If False, it's shrunk when necessary. Returns: - **`NDBoundingBox`** ( `_T` ) – The aligned bounding box. ### chunk ``` chunk( chunk_shape: VecIntLike, chunk_border_alignments: VecIntLike | None = None, ) -> Generator[_T, None, None] ``` Decompose the bounding box into smaller chunks of size `chunk_shape`. Chunks at the border of the bounding box might be smaller than chunk_shape. If `chunk_border_alignment` is set, all border coordinates *between two chunks* will be divisible by that value. Parameters: - **`chunk_shape`** (`VecIntLike`) – The size of the chunks to generate. - **`chunk_border_alignments`** (`VecIntLike | None`, default: `None` ) – The alignment of the chunk borders. Yields: - `_T` – Generator\[NDBoundingBox\]: A generator of the chunks. ### contains ``` contains(coord: VecIntLike) -> bool ``` Check whether a point is inside of the bounding box. Note that the point may have float coordinates in the ndarray case Parameters: - **`coord`** (`VecIntLike`) – The coordinates to check. Returns: - **`bool`** ( `bool` ) – True if the point is inside of the bounding box, False otherwise. ### contains_bbox ``` contains_bbox(inner_bbox: _T) -> bool ``` Check whether a bounding box is completely inside of the bounding box. Parameters: - **`inner_bbox`** (`NDBoundingBox`) – The bounding box to check. Returns: - **`bool`** ( `bool` ) – True if the bounding box is completely inside of the bounding box, False otherwise. ### denormalize ``` denormalize() -> NDBoundingBox ``` ### extended_by ``` extended_by(other: _T) -> _T ``` Returns the smallest bounding box that contains both bounding boxes. Parameters: - **`other`** (`NDBoundingBox`) – The other bounding box to extend with. Returns: - **`NDBoundingBox`** ( `_T` ) – The smallest bounding box that contains both bounding boxes. ### from_mag_to_mag1 ``` from_mag_to_mag1(from_mag: Mag) -> _T ``` Returns the bounging box in the finest magnification (Mag(1)). Parameters: - **`from_mag`** (`Mag`) – The current magnification of the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – The bounding box in the given magnification. ### get_bounds ``` get_bounds(axis: str) -> tuple[int, int] ``` Returns the bounds of the given axis. Parameters: - **`axis`** (`str`) – The name of the axis to get the bounds for. Returns: - `tuple[int, int]` – tuple\[int, int\]: A tuple containing the top-left and bottom-right coordinates along the specified axis. ### get_shape ``` get_shape(axis_name: str) -> int ``` Returns the size of the bounding box along the specified axis. Parameters: - **`axis_name`** (`str`) – The name of the axis to get the size for. Returns: - **`int`** ( `int` ) – The size of the bounding box along the specified axis. ### group_boxes_with_aligned_mag ``` group_boxes_with_aligned_mag( bounding_boxes: Iterable[NDBoundingBox], aligning_mag: Mag, ) -> dict[NDBoundingBox, list[NDBoundingBox]] ``` Groups the given BoundingBox instances by aligning each bbox to the given mag and using that as the key. For example, bounding boxes of size 256**3 could be grouped into the corresponding 1024**3 chunks to which they belong by using aligning_mag = Mag(1024). ### in_mag ``` in_mag(mag: Mag) -> _T ``` Returns the bounding box in the given mag. Parameters: - **`mag`** (`Mag`) – The magnification to convert the bounding box to. Returns: - **`NDBoundingBox`** ( `_T` ) – The bounding box in the given magnification. ### intersected_with ``` intersected_with( other: _T, dont_assert: bool = False ) -> _T ``` Returns the intersection of two bounding boxes. If there is no intersection (resulting bounding box is empty) and dont_assert is False (default) the function raises an assertion error. If dont_assert is set to True this method returns an empty bounding box if there is no intersection. Parameters: - **`other`** (`NDBoundingBox`) – The other bounding box to intersect with. - **`dont_assert`** (`bool`, default: `False` ) – If True, the method may return an empty bounding box. Default is False. Returns: - **`NDBoundingBox`** ( `_T` ) – The intersection of the two bounding boxes. ### is_empty ``` is_empty() -> bool ``` Boolean check whether the boundung box is empty. Returns: - **`bool`** ( `bool` ) – True if the bounding box is empty, False otherwise. ### normalize_axes ``` normalize_axes(num_channels: int) -> NormalizedBoundingBox ``` ### offset ``` offset(vector: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified offset. Parameters: - **`vector`** (`VecIntLike`) – The offset to apply to the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the specified offset. ### padded_with_margins ``` padded_with_margins( margins_left: Vec3IntLike, margins_right: Vec3IntLike | None = None, ) -> _T ``` ### slice_array ``` slice_array(array: ndarray) -> ndarray ``` Returns a slice of the given array that corresponds to the bounding box. ### to_checkpoint_name ``` to_checkpoint_name() -> str ``` Returns a string representation of the bounding box that can be used as a checkpoint name. Returns: - **`str`** ( `str` ) – A string representation of the bounding box. ### to_config_dict ``` to_config_dict() -> dict ``` Returns a dictionary representation of the bounding box. Returns: - **`dict`** ( `dict` ) – A dictionary representation of the bounding box. ### to_slices ``` to_slices() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box. ### to_slices_xyz ``` to_slices_xyz() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box in x, y, z and leaves all other axes one dimensional without offset. ### volume ``` volume() -> int ``` Returns the volume of the bounding box. ### with_bottomright ``` with_bottomright(new_bottomright: VecIntLike) -> _T ``` Returns a new NDBoundingBox with an updated bottomright value. Parameters: - **`new_bottomright`** (`VecIntLike`) – The new bottom right corner coordinates. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated bottom right corner. ### with_bottomright_xyz ``` with_bottomright_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the bottomright corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. ### with_bounds ``` with_bounds( axis: str, new_topleft: int | None = None, new_size: int | None = None, ) -> _T ``` Returns a new NDBoundingBox object with updated bounds along the specified axis. Parameters: - **`axis`** (`str`) – The name of the axis to update. - **`new_topleft`** (`int | None`, default: `None` ) – The new value for the top-left coordinate along the specified axis. - **`new_size`** (`int | None`, default: `None` ) – The new size along the specified axis. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with updated bounds. Raises: - `KeyError` – If the given axis name does not exist. ### with_color ``` with_color(color: tuple[float, float, float, float]) -> _T ``` Returns a new instance of NDBoundingBox with the specified color. Parameters: - **`color`** (`tuple[float, float, float, float] | None`) – The color to set for the bounding box. The color should be specified as a tuple of four floats representing RGBA values. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified color. ### with_index ``` with_index(new_index: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified index. Parameters: - **`new_index`** (`VecIntLike`) – The new axis order for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated index. ### with_index_xyz ``` with_index_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z index. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z index for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z index. ### with_is_visible ``` with_is_visible(is_visible: bool) -> _T ``` Returns a new NDBoundingBox object with the specified visibility. Parameters: - **`is_visible`** (`bool`) – The visibility value to set. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated visibility value. ### with_name ``` with_name(name: str | None) -> _T ``` Returns a new instance of `NDBoundingBox` with the specified name. Parameters: - **`name`** (`str | None`) – The name to assign to the new NDBoundingBox instance. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified name. ### with_size ``` with_size(new_size: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified size. Parameters: - **`new_size`** (`VecIntLike`) – The new size of the bounding box. Can be a VecInt or any object that can be converted to a VecInt. Returns: - `_T` – A new NDBoundingBox object with the specified size. ### with_size_xyz ``` with_size_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z size. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z size for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z size. ### with_topleft ``` with_topleft(new_topleft: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified top left coordinates. Parameters: - **`new_topleft`** (`VecIntLike`) – The new top left coordinates for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated top left coordinates. ### with_topleft_xyz ``` with_topleft_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the topleft corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. ### xyz_array_to_bbox_shape ``` xyz_array_to_bbox_shape(data: ndarray) -> ndarray ``` Transforms data array with xyz axes to the shape of the bounding box. This is only possible for bboxes that are flat in all dimensions except xyz. # webknossos.geometry ## NormalizedBoundingBox Bases: `NDBoundingBox` ### axes ``` axes: tuple[str, ...] = field( converter=str_iterable_to_tuple ) ``` ### bottomright ``` bottomright: VecInt = field(init=False) ``` ### bottomright_xyz ``` bottomright_xyz: Vec3Int ``` The bottomright corner of the bounding box regarding only x, y and z axis. ### color ``` color: tuple[float, float, float, float] | None = None ``` ### index ``` index: VecInt = field( converter=parse_vec_int_or_none, default=None ) ``` ### index_xyz ``` index_xyz: Vec3Int ``` The index of x, y and z axis within the bounding box. ### is_visible ``` is_visible: bool = True ``` ### name ``` name: str | None = _DEFAULT_BBOX_NAME ``` ### ndim ``` ndim: int ``` The number of dimensions of the bounding box. ### size ``` size: VecInt = field(converter=parse_vec_int) ``` ### size_xyz ``` size_xyz: Vec3Int ``` The size of the bounding box regarding only x, y and z axis. ### topleft ``` topleft: VecInt = field(converter=parse_vec_int) ``` ### topleft_xyz ``` topleft_xyz: Vec3Int ``` The topleft corner of the bounding box regarding only x, y and z axis. ### align_with_mag ``` align_with_mag( mag: Mag | Vec3Int, ceil: bool = False ) -> _T ``` Rounds the bounding box, so that both topleft and bottomright are divisible by mag. Parameters: - **`mag`** (`Mag | Vec3Int`) – The magnification to align the bounding box to. - **`ceil`** (`bool`, default: `False` ) – If True, the bounding box is enlarged when necessary. If False, it's shrunk when necessary. Returns: - **`NDBoundingBox`** ( `_T` ) – The aligned bounding box. ### chunk ``` chunk( chunk_shape: VecIntLike, chunk_border_alignments: VecIntLike | None = None, ) -> Generator[_T, None, None] ``` Decompose the bounding box into smaller chunks of size `chunk_shape`. Chunks at the border of the bounding box might be smaller than chunk_shape. If `chunk_border_alignment` is set, all border coordinates *between two chunks* will be divisible by that value. Parameters: - **`chunk_shape`** (`VecIntLike`) – The size of the chunks to generate. - **`chunk_border_alignments`** (`VecIntLike | None`, default: `None` ) – The alignment of the chunk borders. Yields: - `_T` – Generator\[NDBoundingBox\]: A generator of the chunks. ### contains ``` contains(coord: VecIntLike) -> bool ``` Check whether a point is inside of the bounding box. Note that the point may have float coordinates in the ndarray case Parameters: - **`coord`** (`VecIntLike`) – The coordinates to check. Returns: - **`bool`** ( `bool` ) – True if the point is inside of the bounding box, False otherwise. ### contains_bbox ``` contains_bbox(inner_bbox: NDBoundingBox) -> bool ``` Check whether a bounding box is completely inside this bounding box. When checking containment of a BoundingBox, only the spatial (x, y, z) dimensions are considered, ignoring the channel axis. ### denormalize ``` denormalize() -> NDBoundingBox ``` ### extended_by ``` extended_by(other: NDBoundingBox) -> NormalizedBoundingBox ``` Returns the smallest bounding box that contains both bounding boxes. When extending with a BoundingBox, the operation is performed on the spatial (x, y, z) dimensions only, ignoring the channel axis. The result is a NormalizedBoundingBox with the channel count preserved. ### from_mag_to_mag1 ``` from_mag_to_mag1(from_mag: Mag) -> _T ``` Returns the bounging box in the finest magnification (Mag(1)). Parameters: - **`from_mag`** (`Mag`) – The current magnification of the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – The bounding box in the given magnification. ### from_wkw_dict ``` from_wkw_dict(bbox: dict) -> NDBoundingBox ``` Create an instance of NDBoundingBox from a dictionary representation. Parameters: - **`bbox`** (`Dict`) – The dictionary representation of the bounding box. Returns: - **`NDBoundingBox`** ( `NDBoundingBox` ) – An instance of NDBoundingBox (or a subclass). Raises: - `AssertionError` – If additionalAxes are present but axisOrder is not provided. ### get_bounds ``` get_bounds(axis: str) -> tuple[int, int] ``` Returns the bounds of the given axis. Parameters: - **`axis`** (`str`) – The name of the axis to get the bounds for. Returns: - `tuple[int, int]` – tuple\[int, int\]: A tuple containing the top-left and bottom-right coordinates along the specified axis. ### get_shape ``` get_shape(axis_name: str) -> int ``` Returns the size of the bounding box along the specified axis. Parameters: - **`axis_name`** (`str`) – The name of the axis to get the size for. Returns: - **`int`** ( `int` ) – The size of the bounding box along the specified axis. ### group_boxes_with_aligned_mag ``` group_boxes_with_aligned_mag( bounding_boxes: Iterable[NDBoundingBox], aligning_mag: Mag, ) -> dict[NDBoundingBox, list[NDBoundingBox]] ``` Groups the given BoundingBox instances by aligning each bbox to the given mag and using that as the key. For example, bounding boxes of size 256**3 could be grouped into the corresponding 1024**3 chunks to which they belong by using aligning_mag = Mag(1024). ### in_mag ``` in_mag(mag: Mag) -> _T ``` Returns the bounding box in the given mag. Parameters: - **`mag`** (`Mag`) – The magnification to convert the bounding box to. Returns: - **`NDBoundingBox`** ( `_T` ) – The bounding box in the given magnification. ### intersected_with ``` intersected_with( other: NDBoundingBox, dont_assert: bool = False ) -> NormalizedBoundingBox ``` Returns the intersection of two bounding boxes. When intersecting with a BoundingBox, the operation is performed on the spatial (x, y, z) dimensions only, ignoring the channel axis. The result is a NormalizedBoundingBox with the channel count preserved. ### is_empty ``` is_empty() -> bool ``` Boolean check whether the boundung box is empty. Returns: - **`bool`** ( `bool` ) – True if the bounding box is empty, False otherwise. ### normalize_axes ``` normalize_axes(num_channels: int) -> NormalizedBoundingBox ``` ### offset ``` offset(vector: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified offset. Parameters: - **`vector`** (`VecIntLike`) – The offset to apply to the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the specified offset. ### padded_with_margins ``` padded_with_margins( margins_left: Vec3IntLike, margins_right: Vec3IntLike | None = None, ) -> _T ``` ### slice_array ``` slice_array(array: ndarray) -> ndarray ``` Returns a slice of the given array that corresponds to the bounding box. ### to_checkpoint_name ``` to_checkpoint_name() -> str ``` Returns a string representation of the bounding box that can be used as a checkpoint name. Returns: - **`str`** ( `str` ) – A string representation of the bounding box. ### to_config_dict ``` to_config_dict() -> dict ``` Returns a dictionary representation of the bounding box. Returns: - **`dict`** ( `dict` ) – A dictionary representation of the bounding box. ### to_slices ``` to_slices() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box. ### to_slices_xyz ``` to_slices_xyz() -> tuple[slice, ...] ``` Returns a tuple of slices that corresponds to the bounding box in x, y, z and leaves all other axes one dimensional without offset. ### to_wkw_dict ``` to_wkw_dict() -> dict ``` Converts the bounding box object to a json dictionary. Returns: - **`dict`** ( `dict` ) – A json dictionary representing the bounding box. ### volume ``` volume() -> int ``` Returns the volume of the bounding box. ### with_bottomright ``` with_bottomright(new_bottomright: VecIntLike) -> _T ``` Returns a new NDBoundingBox with an updated bottomright value. Parameters: - **`new_bottomright`** (`VecIntLike`) – The new bottom right corner coordinates. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated bottom right corner. ### with_bottomright_xyz ``` with_bottomright_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the bottomright corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. ### with_bounds ``` with_bounds( axis: str, new_topleft: int | None = None, new_size: int | None = None, ) -> _T ``` Returns a new NDBoundingBox object with updated bounds along the specified axis. Parameters: - **`axis`** (`str`) – The name of the axis to update. - **`new_topleft`** (`int | None`, default: `None` ) – The new value for the top-left coordinate along the specified axis. - **`new_size`** (`int | None`, default: `None` ) – The new size along the specified axis. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with updated bounds. Raises: - `KeyError` – If the given axis name does not exist. ### with_color ``` with_color(color: tuple[float, float, float, float]) -> _T ``` Returns a new instance of NDBoundingBox with the specified color. Parameters: - **`color`** (`tuple[float, float, float, float] | None`) – The color to set for the bounding box. The color should be specified as a tuple of four floats representing RGBA values. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified color. ### with_index ``` with_index(new_index: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified index. Parameters: - **`new_index`** (`VecIntLike`) – The new axis order for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated index. ### with_index_xyz ``` with_index_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z index. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z index for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z index. ### with_is_visible ``` with_is_visible(is_visible: bool) -> _T ``` Returns a new NDBoundingBox object with the specified visibility. Parameters: - **`is_visible`** (`bool`) – The visibility value to set. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated visibility value. ### with_name ``` with_name(name: str | None) -> _T ``` Returns a new instance of `NDBoundingBox` with the specified name. Parameters: - **`name`** (`str | None`) – The name to assign to the new NDBoundingBox instance. Returns: - **`NDBoundingBox`** ( `_T` ) – A new instance of NDBoundingBox with the specified name. ### with_size ``` with_size(new_size: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified size. Parameters: - **`new_size`** (`VecIntLike`) – The new size of the bounding box. Can be a VecInt or any object that can be converted to a VecInt. Returns: - `_T` – A new NDBoundingBox object with the specified size. ### with_size_xyz ``` with_size_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z size. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z size for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z size. ### with_topleft ``` with_topleft(new_topleft: VecIntLike) -> _T ``` Returns a new NDBoundingBox object with the specified top left coordinates. Parameters: - **`new_topleft`** (`VecIntLike`) – The new top left coordinates for the bounding box. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated top left coordinates. ### with_topleft_xyz ``` with_topleft_xyz(new_xyz: Vec3IntLike) -> _T ``` Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. Parameters: - **`new_xyz`** (`Vec3IntLike`) – The new x, y and z coordinates for the topleft corner. Returns: - **`NDBoundingBox`** ( `_T` ) – A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. ### xyz_array_to_bbox_shape ``` xyz_array_to_bbox_shape(data: ndarray) -> ndarray ``` Transforms data array with xyz axes to the shape of the bounding box. This is only possible for bboxes that are flat in all dimensions except xyz. # webknossos.geometry ## Vec3Int Bases: `VecInt` ### axes ``` axes: tuple[str, ...] ``` ### c ``` c: int ``` Returns the c component of the vector. ### x ``` x: int ``` ### xyz ``` xyz: Vec3Int ``` ### y ``` y: int ``` ### z ``` z: int ``` ### add_or_none ``` add_or_none(other: Optional[VecInt]) -> _T | None ``` Adds two VecInts or returns None if the other is None. Parameters: - **`other`** (`VecInt | None`) – The other vector to add. Returns: - `_T | None` – VecInt | None: The sum of the two vectors or None if the other is None. ### ceildiv ``` ceildiv(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the ceil division of each element by the other. ### contains ``` contains(needle: int) -> bool ``` Checks if the vector contains a given element. ### from_str ``` from_str(string: str) -> Vec3Int ``` ### from_vec3_float ``` from_vec3_float(vec: tuple[float, float, float]) -> Vec3Int ``` ### from_vec_or_int ``` from_vec_or_int( vec_or_int: Union[Vec3IntLike, int], ) -> Vec3Int ``` ### from_xyz ``` from_xyz(x: int, y: int, z: int) -> Vec3Int ``` Use Vec3Int.from_xyz for fast construction. ### full ``` full( an_int: int, _axes: tuple[str, ...] = ("x", "y", "z") ) -> Vec3Int ``` ### get ``` get(axis: str, default: int | None = None) -> int ``` Returns the value of the specified axis. Parameters: - **`axis`** (`str`) – The name of the axis to get the value for. - **`default`** (`int`, default: `None` ) – The default value to return if the axis is not present. Defaults to None. Returns: - **`int`** ( `int` ) – The value of the specified axis. ### is_positive ``` is_positive(strictly_positive: bool = False) -> bool ``` Checks if all elements in the vector are positive. Parameters: - **`strictly_positive`** (`bool`, default: `False` ) – If True, checks if all elements are strictly positive. Returns: - **`bool`** ( `bool` ) – True if all elements are positive, False otherwise. ### is_uniform ``` is_uniform() -> bool ``` Checks if all elements in the vector are the same. ### moveaxis ``` moveaxis( source: int | list[int], target: int | list[int] ) -> _T ``` Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified source so that the other elements move when necessary. Parameters: - **`source`** (`int | list[int]`) – The index of the element to move. - **`target`** (`int | list[int]`) – The index where the element should be moved to. Returns: - **`VecInt`** ( `_T` ) – A new vector with the moved element. ### ones ``` ones(_axes: tuple[str, ...] = ('x', 'y', 'z')) -> Vec3Int ``` ### pairmax ``` pairmax(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the maximum of each pair of elements from the two vectors. ### pairmin ``` pairmin(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the minimum of each pair of elements from the two vectors. ### prod ``` prod() -> int ``` Returns the product of all elements in the vector. ### to_list ``` to_list() -> list[int] ``` Returns the vector as a list. ### to_np ``` to_np() -> ndarray ``` Returns the vector as a numpy array. ### to_tuple ``` to_tuple() -> tuple[int, int, int] ``` ### with_c ``` with_c(new_c: int) -> _T ``` Returns a new ND Vector with the c component replaced by the given value. ### with_replaced ``` with_replaced(axis: str | int, new_element: int) -> _T ``` Returns a new ND Vector with a replaced element at a given axis (or index for backwards compatibility). ### with_x ``` with_x(new_x: int) -> Vec3Int ``` ### with_xyz ``` with_xyz(new_xyz: Vec3Int) -> _T ``` Returns a new ND Vector with the x, y and z components replaced by the given vector. Components absent from this vector are silently skipped. ### with_y ``` with_y(new_y: int) -> Vec3Int ``` ### with_z ``` with_z(new_z: int) -> Vec3Int ``` ### zeros ``` zeros(_axes: tuple[str, ...] = ('x', 'y', 'z')) -> Vec3Int ``` # webknossos.geometry ## VecInt Bases: `Sequence[int]` A specialized vector class for storing and manipulating integer values with named axes. This class uses composition (an internal `_data` tuple) to provide vector operations while preserving axis information. It allows for initialization with both positional and named arguments. Attributes: - **`axes`** (`tuple[str, ...]`) – Names of the vector's axes, e.g. ('x', 'y', 'z') Examples: Create a vector with 4 named dimensions: ``` vector_1 = VecInt(1, 2, 3, 4, axes=("x", "y", "z", "t")) vector_1 = VecInt([1, 2, 3, 4], axes=("x", "y", "z", "t")) vector_1 = VecInt(x=1, y=2, z=3, t=4) ``` Create a vector filled with ones: ``` vector_2 = VecInt.full(1, axes=("x", "y", "z", "t")) assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] ``` Perform vector addition: ``` assert vector_1 + vector_2 == VecInt(2, 3, 4, 5) ``` ### axes ``` axes: tuple[str, ...] ``` ### c ``` c: int ``` Returns the c component of the vector. ### x ``` x: int ``` Returns the x component of the vector. ### xyz ``` xyz: Vec3Int ``` ### y ``` y: int ``` Returns the y component of the vector. ### z ``` z: int ``` Returns the z component of the vector. ### add_or_none ``` add_or_none(other: Optional[VecInt]) -> _T | None ``` Adds two VecInts or returns None if the other is None. Parameters: - **`other`** (`VecInt | None`) – The other vector to add. Returns: - `_T | None` – VecInt | None: The sum of the two vectors or None if the other is None. ### ceildiv ``` ceildiv(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the ceil division of each element by the other. ### contains ``` contains(needle: int) -> bool ``` Checks if the vector contains a given element. ### from_str ``` from_str(string: str) -> VecInt ``` Returns a new ND Vector from a string representation. Parameters: - **`string`** (`str`) – The string representation of the vector. Returns: - **`VecInt`** ( `VecInt` ) – The new vector. ### full ``` full(an_int: int, axes: tuple[str, ...]) -> VecInt ``` Returns a new ND Vector with all elements set to the same value. Parameters: - **`an_int`** (`int`) – The value to set all elements to. - **`axes`** (`tuple[str, ...]`) – The axes of the vector. Returns: - **`VecInt`** ( `VecInt` ) – The new vector. ### get ``` get(axis: str, default: int | None = None) -> int ``` Returns the value of the specified axis. Parameters: - **`axis`** (`str`) – The name of the axis to get the value for. - **`default`** (`int`, default: `None` ) – The default value to return if the axis is not present. Defaults to None. Returns: - **`int`** ( `int` ) – The value of the specified axis. ### is_positive ``` is_positive(strictly_positive: bool = False) -> bool ``` Checks if all elements in the vector are positive. Parameters: - **`strictly_positive`** (`bool`, default: `False` ) – If True, checks if all elements are strictly positive. Returns: - **`bool`** ( `bool` ) – True if all elements are positive, False otherwise. ### is_uniform ``` is_uniform() -> bool ``` Checks if all elements in the vector are the same. ### moveaxis ``` moveaxis( source: int | list[int], target: int | list[int] ) -> _T ``` Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified source so that the other elements move when necessary. Parameters: - **`source`** (`int | list[int]`) – The index of the element to move. - **`target`** (`int | list[int]`) – The index where the element should be moved to. Returns: - **`VecInt`** ( `_T` ) – A new vector with the moved element. ### ones ``` ones(axes: tuple[str, ...]) -> VecInt ``` Returns a new ND Vector with all elements set to 1. Parameters: - **`axes`** (`tuple[str, ...]`) – The axes of the vector. Returns: - **`VecInt`** ( `VecInt` ) – The new vector. ### pairmax ``` pairmax(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the maximum of each pair of elements from the two vectors. ### pairmin ``` pairmin(other: Union[int, VecIntLike]) -> _T ``` Returns a new VecInt with the minimum of each pair of elements from the two vectors. ### prod ``` prod() -> int ``` Returns the product of all elements in the vector. ### to_list ``` to_list() -> list[int] ``` Returns the vector as a list. ### to_np ``` to_np() -> ndarray ``` Returns the vector as a numpy array. ### to_tuple ``` to_tuple() -> tuple[int, ...] ``` Returns the vector as a tuple. ### with_c ``` with_c(new_c: int) -> _T ``` Returns a new ND Vector with the c component replaced by the given value. ### with_replaced ``` with_replaced(axis: str | int, new_element: int) -> _T ``` Returns a new ND Vector with a replaced element at a given axis (or index for backwards compatibility). ### with_x ``` with_x(new_x: int) -> _T ``` Returns a new ND Vector with the x component replaced by the given value. ### with_xyz ``` with_xyz(new_xyz: Vec3Int) -> _T ``` Returns a new ND Vector with the x, y and z components replaced by the given vector. Components absent from this vector are silently skipped. ### with_y ``` with_y(new_y: int) -> _T ``` Returns a new ND Vector with the y component replaced by the given value. ### with_z ``` with_z(new_z: int) -> _T ``` Returns a new ND Vector with the z component replaced by the given value. ### zeros ``` zeros(axes: tuple[str, ...]) -> VecInt ``` Returns a new ND Vector with all elements set to 0. Parameters: - **`axes`** (`tuple[str, ...]`) – The axes of the vector. Returns: - **`VecInt`** ( `VecInt` ) – The new vector. # webknossos.proofreading # webknossos.skeleton ## Group A hierarchical container for organizing trees and subgroups in WEBKNOSSOS skeleton annotations. The Group class provides a way to organize skeleton trees into logical collections, supporting nested hierarchies of groups and trees. Groups can contain both trees (collections of connected nodes) and other groups, enabling flexible organization of complex annotations. Attributes: - **`name`** (`str`) – Name of the group. - **`id`** (`int`) – Read-only unique identifier for the group. - **`children`** (`Iterator[GroupOrTree]`) – Iterator over all immediate children (both groups and trees). - **`groups`** (`Iterator[Group]`) – Iterator over immediate subgroups. - **`trees`** (`Iterator[Tree]`) – Iterator over immediate trees. The group hierarchy supports - Nested organization (groups within groups) - Tree management (adding, removing, retrieving trees) - Node access across all contained trees - Flattened views of the hierarchy Examples: Create a hierarchical structure: ``` # Create groups for different neuron parts neuron = skeleton.add_group("neuron_42") dendrites = neuron.add_group("dendrites") axons = neuron.add_group("axons") # Add trees to groups basal = dendrites.add_tree("basal_dendrite") apical = dendrites.add_tree("apical_dendrite", color=(1, 0, 0, 1)) axon_tree = axons.add_tree("main_axon") # Work with the hierarchy print(f"Total nodes: {neuron.get_total_node_count()}") for tree in dendrites.trees: print(f"Dendrite tree: {tree.name}") # Access nodes across all trees node = neuron.get_node_by_id(123) ``` Copy existing trees: ``` # Copy a tree to another group template = existing_group.get_tree_by_id(42) copy = new_group.add_tree(template, color=(0, 1, 0, 1)) ``` Notes - Groups maintain unique IDs for all contained elements - Use flattened\_\* methods to access nested elements recursively - Trees should be added using add_tree rather than created directly - The group hierarchy is part of a Skeleton instance See Also - Tree: Class representing connected node structures - Node: Class representing individual 3D points - Skeleton: Root container for all annotation data ### children ``` children: Iterator[GroupOrTree] ``` Returns an iterator over all immediate children (groups and trees). This property provides access to both groups and trees that are direct children of this group, in no particular order. For nested access, use flattened_trees() or flattened_groups(). Returns: - `Iterator[GroupOrTree]` – Iterator\[GroupOrTree\]: Iterator yielding all immediate child groups and trees. Examples: ``` # Print all immediate children for child in group.children: if isinstance(child, Tree): print(f"Tree: {child.name}") else: print(f"Group: {child.name}") ``` ### groups ``` groups: Iterator[Group] ``` Returns all (immediate) group children as an iterator. Use flattened_groups if you need also need groups within subgroups. ### id ``` id: int ``` Read-only property. ### name ``` name: str ``` ### trees ``` trees: Iterator[Tree] ``` Returns all (immediate) tree children as an iterator. Use flattened_trees if you also need trees within subgroups. ### add_group ``` add_group( name: str, _enforced_id: int | None = None ) -> Group ``` Creates and adds a new subgroup to this group. Parameters: - **`name`** (`str`) – Name for the new group. - **`_enforced_id`** (`int | None`, default: `None` ) – Optional specific ID for the group (internal use). Returns: - **`Group`** ( `Group` ) – The newly created group. Examples: ``` # Create nested group hierarchy dendrites = neuron.add_group("dendrites") basal = dendrites.add_group("basal") apical = dendrites.add_group("apical") ``` ### add_tree ``` add_tree( name_or_tree: str | Tree, color: Vector4 | Vector3 | None = None, _enforced_id: int | None = None, metadata: dict[ str, str | int | float | Sequence[str] ] = {}, is_visible: bool = True, ) -> Tree ``` Adds a new tree or copies an existing tree to this group. This method supports two ways of adding trees: 1. Creating a new tree by providing a name 1. Copying an existing tree from another location Parameters: - **`name_or_tree`** (`str | Tree`) – Either a string name for a new tree or an existing Tree instance to copy. - **`color`** (`Vector4 | Vector3 | None`, default: `None` ) – Optional RGBA color tuple (r, g, b, a) or RGB tuple (r, g, b). If an RGB tuple is provided, alpha will be set to 1.0. - **`_enforced_id`** (`int | None`, default: `None` ) – Optional specific ID for the tree (internal use). - **`metadata`** (`dict[str, str | int | float | Sequence[str]]`, default: `{}` ) – Optional key-value metadata for the tree. - **`is_visible`** (`bool`, default: `True` ) – Whether the tree is visible in WEBKNOSSOS. Defaults to True. Returns: - **`Tree`** ( `Tree` ) – The newly created or copied tree. Examples: ``` # Create new tree tree = group.add_tree("dendrite_1", color=(1, 0, 0, 1)) # Copy existing tree copy = group.add_tree(existing_tree) ``` Notes When copying a tree, a new ID will be generated if the original ID already exists in this group. ### as_nml_group ``` as_nml_group() -> Group ``` Converts this group to its NML representation. This method creates a lightweight representation of the group suitable for serialization in the NML format. Returns: - `Group` – wknml.Group: NML representation of this group. Notes This is primarily used internally for file I/O operations. ### flattened_groups ``` flattened_groups() -> Iterator[Group] ``` Returns an iterator of all groups within this group (and its subgroups). ### flattened_trees ``` flattened_trees() -> Iterator[Tree] ``` Returns an iterator of all trees in this group and its subgroups. This method performs a recursive traversal of the group hierarchy, yielding all trees regardless of their nesting level. Returns: - `Iterator[Tree]` – Iterator\[Tree\]: Iterator yielding all contained trees. Examples: ``` # Process all trees regardless of grouping for tree in group.flattened_trees(): print(f"Tree {tree.name} has {len(tree.nodes)} nodes") ``` ### get_group_by_id ``` get_group_by_id(group_id: int) -> Group ``` Returns the group which has the specified group id. ### get_max_node_id ``` get_max_node_id() -> int ``` Returns the highest node id of all nodes of all trees within this group (and its subgroups). ### get_max_tree_id ``` get_max_tree_id() -> int ``` Returns the highest tree id of all trees within this group (and its subgroups). ### get_node_by_id ``` get_node_by_id(node_id: int) -> Node ``` Retrieves a node by its ID from any tree in this group or its subgroups. Parameters: - **`node_id`** (`int`) – The ID of the node to find. Returns: - **`Node`** ( `Node` ) – The node with the specified ID. Raises: - `ValueError` – If no node with the given ID exists in any tree. Examples: ``` try: node = group.get_node_by_id(42) print(f"Found node at position {node.position}") except ValueError: print("Node not found") ``` ### get_total_node_count ``` get_total_node_count() -> int ``` Counts all nodes in all trees within this group and its subgroups. Returns: - **`int`** ( `int` ) – Total number of nodes across all contained trees. Examples: ``` # Check total annotation points count = group.get_total_node_count() print(f"Total annotation points: {count}") ``` ### get_tree_by_id ``` get_tree_by_id(tree_id: int) -> Tree ``` Retrieves a tree by its ID from this group or its subgroups. Parameters: - **`tree_id`** (`int`) – The ID of the tree to find. Returns: - **`Tree`** ( `Tree` ) – The tree with the specified ID. Raises: - `ValueError` – If no tree with the given ID exists. Examples: ``` try: tree = group.get_tree_by_id(42) print(f"Found tree '{tree.name}'") except ValueError: print("Tree not found") ``` ### has_tree_id ``` has_tree_id(tree_id: int) -> bool ``` Checks if a tree with the given ID exists in this group or its subgroups. Parameters: - **`tree_id`** (`int`) – The ID to check for. Returns: - **`bool`** ( `bool` ) – True if a tree with the ID exists, False otherwise. Examples: ``` if group.has_tree_id(42): tree = group.get_tree_by_id(42) print(f"Tree exists: {tree.name}") ``` ### remove_tree_by_id ``` remove_tree_by_id(tree_id: int) -> None ``` # webknossos.skeleton ## Node A node in a skeleton tree representing a point in 3D space with additional metadata. The Node class represents individual points in a skeleton annotation. Each node has a 3D position and can contain additional metadata such as comments, radius, rotation, and viewport information. Nodes are typically created and managed through Tree instances rather than directly. Attributes: - **`position`** (`Vec3Int`) – 3D coordinates of the node as (x, y, z). - **`comment`** (`str | None`) – Optional text annotation for the node. - **`radius`** (`float | None`) – Optional radius value, useful for representing varying thicknesses. - **`rotation`** (`Vec3Float | None`) – Optional 3D rotation as (x, y, z) in radians. - **`inVp`** (`int | None`) – Optional viewport number where the node was created. - **`inMag`** (`int | None`) – Optional magnification level at which the node was created. - **`bitDepth`** (`int | None`) – Optional bit depth of the data at node creation. - **`interpolation`** (`bool | None`) – Optional flag indicating if the node was created through interpolation. - **`time`** (`int | None`) – Optional timestamp for node creation. - **`is_branchpoint`** (`bool`) – Boolean indicating if this node is a branching point. - **`branchpoint_time`** (`int | None`) – Optional timestamp when the node was marked as a branchpoint. Notes Nodes should typically be created using `Tree.add_node()` rather than instantiated directly. This ensures proper integration with the skeleton structure. Examples: ``` # Create a skeleton and tree skeleton = Skeleton(name="example") tree = skeleton.add_tree("dendrite") # Add nodes and connect them node1 = tree.add_node(position=(0, 0, 0), comment="soma") node2 = tree.add_node(position=(100, 0, 0), radius=1.5) tree.add_edge(node1, node2) # Mark as branchpoint if needed node1.is_branchpoint = True ``` ### bitDepth ``` bitDepth: int | None = None ``` ### branchpoint_time ``` branchpoint_time: int | None = None ``` ### comment ``` comment: str | None = None ``` ### id ``` id: int ``` ### inMag ``` inMag: int | None = None ``` ### inVp ``` inVp: int | None = None ``` ### interpolation ``` interpolation: bool | None = None ``` ### is_branchpoint ``` is_branchpoint: bool = False ``` ### position ``` position: Vec3Int ``` ### radius ``` radius: float | None = None ``` ### rotation ``` rotation: Vec3Float | None = None ``` ### time ``` time: int | None = None ``` ### get_dict ``` get_dict() -> dict[str, Any] ``` # webknossos.skeleton ## Skeleton Bases: `Group` A hierarchical representation of skeleton annotations in WEBKNOSSOS. The Skeleton class serves as the root container for all skeleton annotation data, organizing nodes and edges into a hierarchical structure of groups and trees. It contains dataset metadata and provides methods for loading, saving, and manipulating skeleton annotations. Attributes: - **`voxel_size`** (`Vector3`) – 3D tuple (x, y, z) specifying the size of voxels in nanometers. - **`dataset_name`** (`str`) – Name of the dataset this skeleton belongs to. - **`organization_id`** (`str | None`) – Optional ID of the organization owning this skeleton. - **`description`** (`str | None`) – Optional description of the skeleton annotation. - **`name`** (`str`) – Always set to "Root" as this is the root group of the hierarchy. The skeleton structure follows a hierarchical organization - Skeleton (root) - Groups (optional organizational units) - Trees (collections of connected nodes) - Nodes (3D points with metadata) - Edges (connections between nodes) Examples: Create and populate a new skeleton: ``` # Create skeleton through an annotation annotation = Annotation( name="dendrite_trace", dataset_name="cortex_sample", voxel_size=(11, 11, 24) ) skeleton = annotation.skeleton # Add hierarchical structure dendrites = skeleton.add_group("dendrites") basal = dendrites.add_group("basal") tree = basal.add_tree("dendrite_1") # Add and connect nodes soma = tree.add_node(position=(100, 100, 100), comment="soma") branch = tree.add_node(position=(200, 150, 100), radius=1.5) tree.add_edge(soma, branch) ``` Load an existing skeleton: ``` # Load from NML file skeleton = Skeleton.load("annotation.nml") # Access existing structure for group in skeleton.groups: for tree in group.trees: print(f"Tree {tree.name} has {len(tree.nodes)} nodes") ``` Notes - The Skeleton class inherits from Group, providing group and tree management methods. - To upload a skeleton to WEBKNOSSOS, create an Annotation with it. - For complex examples, see the skeleton synapse candidates example in the documentation. See Also - Group: Base class providing group and tree management - Tree: Class representing connected node structures - Node: Class representing individual 3D points - Annotation: Container class for working with WEBKNOSSOS ### children ``` children: Iterator[GroupOrTree] ``` Returns an iterator over all immediate children (groups and trees). This property provides access to both groups and trees that are direct children of this group, in no particular order. For nested access, use flattened_trees() or flattened_groups(). Returns: - `Iterator[GroupOrTree]` – Iterator\[GroupOrTree\]: Iterator yielding all immediate child groups and trees. Examples: ``` # Print all immediate children for child in group.children: if isinstance(child, Tree): print(f"Tree: {child.name}") else: print(f"Group: {child.name}") ``` ### dataset_id ``` dataset_id: str | None = None ``` ### dataset_name ``` dataset_name: str ``` ### description ``` description: str | None = None ``` ### groups ``` groups: Iterator[Group] ``` Returns all (immediate) group children as an iterator. Use flattened_groups if you need also need groups within subgroups. ### id ``` id: int ``` Read-only property. ### name ``` name: str = field( default="Root", init=False, eq=False, repr=False ) ``` Should not be used with `Skeleton`, this attribute is only useful for sub-groups. Set to `Root`. ### organization_id ``` organization_id: str | None = None ``` ### trees ``` trees: Iterator[Tree] ``` Returns all (immediate) tree children as an iterator. Use flattened_trees if you also need trees within subgroups. ### voxel_size ``` voxel_size: Vector3 ``` Get the voxel size of the skeleton in nanometers. Returns: - **`Vector3`** ( `Vector3` ) – A tuple (x, y, z) representing the voxel size in nanometers. ### voxel_size_with_unit ``` voxel_size_with_unit: VoxelSize ``` Get the voxel size of the skeleton with unit. Returns: - **`VoxelSize`** ( `VoxelSize` ) – An instance of VoxelSize containing the scale factor and unit. ### add_group ``` add_group( name: str, _enforced_id: int | None = None ) -> Group ``` Creates and adds a new subgroup to this group. Parameters: - **`name`** (`str`) – Name for the new group. - **`_enforced_id`** (`int | None`, default: `None` ) – Optional specific ID for the group (internal use). Returns: - **`Group`** ( `Group` ) – The newly created group. Examples: ``` # Create nested group hierarchy dendrites = neuron.add_group("dendrites") basal = dendrites.add_group("basal") apical = dendrites.add_group("apical") ``` ### add_nx_graphs ``` add_nx_graphs( tree_dict: list[Graph] | dict[str, list[Graph]], ) -> None ``` Import NetworkX graphs as skeleton trees. Converts [NetworkX Graph objects](https://networkx.org) into skeleton trees, preserving node positions and edge connections. The graphs can be provided either as a list or as a dictionary mapping group names to lists of graphs. Parameters: - **`tree_dict`** (`list[Graph] | dict[str, list[Graph]]`) – Either: - A list of NetworkX graphs to be added directly to the skeleton - A dictionary mapping group names to lists of graphs, which will create new groups with the specified names containing the graphs Raises: - `ValueError` – If any graph nodes lack required position attributes. - `TypeError` – If tree_dict is neither a list nor a dictionary. Examples: Add graphs directly to skeleton: ``` import networkx as nx # Create sample graphs g1 = nx.Graph() g1.add_node(1, position=(0, 0, 0)) g1.add_node(2, position=(100, 0, 0)) g1.add_edge(1, 2) g2 = nx.Graph() g2.add_node(1, position=(0, 100, 0)) g2.add_node(2, position=(100, 100, 0)) g2.add_edge(1, 2) # Add graphs directly skeleton.add_nx_graphs([g1, g2]) # Or organize graphs into groups graphs_by_group = { "dendrites": [g1], "axons": [g2] } skeleton.add_nx_graphs(graphs_by_group) ``` Note - Each node in the input graphs must have a 'position' attribute containing (x, y, z) coordinates - Other node attributes (e.g., radius, rotation) will be preserved - Edge attributes are currently not preserved in the conversion ### add_tree ``` add_tree( name_or_tree: str | Tree, color: Vector4 | Vector3 | None = None, _enforced_id: int | None = None, metadata: dict[ str, str | int | float | Sequence[str] ] = {}, is_visible: bool = True, ) -> Tree ``` Adds a new tree or copies an existing tree to this group. This method supports two ways of adding trees: 1. Creating a new tree by providing a name 1. Copying an existing tree from another location Parameters: - **`name_or_tree`** (`str | Tree`) – Either a string name for a new tree or an existing Tree instance to copy. - **`color`** (`Vector4 | Vector3 | None`, default: `None` ) – Optional RGBA color tuple (r, g, b, a) or RGB tuple (r, g, b). If an RGB tuple is provided, alpha will be set to 1.0. - **`_enforced_id`** (`int | None`, default: `None` ) – Optional specific ID for the tree (internal use). - **`metadata`** (`dict[str, str | int | float | Sequence[str]]`, default: `{}` ) – Optional key-value metadata for the tree. - **`is_visible`** (`bool`, default: `True` ) – Whether the tree is visible in WEBKNOSSOS. Defaults to True. Returns: - **`Tree`** ( `Tree` ) – The newly created or copied tree. Examples: ``` # Create new tree tree = group.add_tree("dendrite_1", color=(1, 0, 0, 1)) # Copy existing tree copy = group.add_tree(existing_tree) ``` Notes When copying a tree, a new ID will be generated if the original ID already exists in this group. ### as_nml_group ``` as_nml_group() -> Group ``` Converts this group to its NML representation. This method creates a lightweight representation of the group suitable for serialization in the NML format. Returns: - `Group` – wknml.Group: NML representation of this group. Notes This is primarily used internally for file I/O operations. ### flattened_groups ``` flattened_groups() -> Iterator[Group] ``` Returns an iterator of all groups within this group (and its subgroups). ### flattened_trees ``` flattened_trees() -> Iterator[Tree] ``` Returns an iterator of all trees in this group and its subgroups. This method performs a recursive traversal of the group hierarchy, yielding all trees regardless of their nesting level. Returns: - `Iterator[Tree]` – Iterator\[Tree\]: Iterator yielding all contained trees. Examples: ``` # Process all trees regardless of grouping for tree in group.flattened_trees(): print(f"Tree {tree.name} has {len(tree.nodes)} nodes") ``` ### get_group_by_id ``` get_group_by_id(group_id: int) -> Group ``` Returns the group which has the specified group id. ### get_max_node_id ``` get_max_node_id() -> int ``` Returns the highest node id of all nodes of all trees within this group (and its subgroups). ### get_max_tree_id ``` get_max_tree_id() -> int ``` Returns the highest tree id of all trees within this group (and its subgroups). ### get_node_by_id ``` get_node_by_id(node_id: int) -> Node ``` Retrieves a node by its ID from any tree in this group or its subgroups. Parameters: - **`node_id`** (`int`) – The ID of the node to find. Returns: - **`Node`** ( `Node` ) – The node with the specified ID. Raises: - `ValueError` – If no node with the given ID exists in any tree. Examples: ``` try: node = group.get_node_by_id(42) print(f"Found node at position {node.position}") except ValueError: print("Node not found") ``` ### get_total_node_count ``` get_total_node_count() -> int ``` Counts all nodes in all trees within this group and its subgroups. Returns: - **`int`** ( `int` ) – Total number of nodes across all contained trees. Examples: ``` # Check total annotation points count = group.get_total_node_count() print(f"Total annotation points: {count}") ``` ### get_tree_by_id ``` get_tree_by_id(tree_id: int) -> Tree ``` Retrieves a tree by its ID from this group or its subgroups. Parameters: - **`tree_id`** (`int`) – The ID of the tree to find. Returns: - **`Tree`** ( `Tree` ) – The tree with the specified ID. Raises: - `ValueError` – If no tree with the given ID exists. Examples: ``` try: tree = group.get_tree_by_id(42) print(f"Found tree '{tree.name}'") except ValueError: print("Tree not found") ``` ### has_tree_id ``` has_tree_id(tree_id: int) -> bool ``` Checks if a tree with the given ID exists in this group or its subgroups. Parameters: - **`tree_id`** (`int`) – The ID to check for. Returns: - **`bool`** ( `bool` ) – True if a tree with the ID exists, False otherwise. Examples: ``` if group.has_tree_id(42): tree = group.get_tree_by_id(42) print(f"Tree exists: {tree.name}") ``` ### load ``` load(file_path: PathLike | UPath | str) -> Skeleton ``` Load a skeleton annotation from a file. This method can load skeleton annotations from either a .nml file or a .zip file that contains an NML file. The .zip file may also contain volume layers. Parameters: - **`file_path`** (`PathLike | str`) – Path to the .nml or .zip file containing the skeleton annotation. Returns: - **`Skeleton`** ( `Skeleton` ) – A new Skeleton instance containing the loaded annotation data. Raises: - `FileNotFoundError` – If the specified file does not exist. - `ValueError` – If the file format is not supported or the file is corrupted. Examples: Load from an NML file: ``` # Load a simple NML file skeleton = Skeleton.load("dendrite_trace.nml") # Load from a ZIP archive containing NML and volume data skeleton = Skeleton.load("full_annotation.zip") ``` Note If you need access to volume layers or other annotation data, use `Annotation.load()` instead, which returns an Annotation object containing both the skeleton and any additional data. ### remove_tree_by_id ``` remove_tree_by_id(tree_id: int) -> None ``` ### save ``` save(out_path: str | PathLike | UPath) -> None ``` Save the skeleton annotation to a file. Saves the skeleton data to either a .nml file or a .zip archive. The .zip format is recommended when the annotation includes volume layers or when you want to compress the data. Parameters: - **`out_path`** (`str | PathLike`) – Destination path for the saved file. Must end with either .nml or .zip extension. Raises: - `AssertionError` – If the file extension is not .nml or .zip. - `OSError` – If there are permission issues or insufficient disk space. Examples: ``` # Save as NML file skeleton.save("dendrite_annotation.nml") # Save as ZIP archive (recommended for complex annotations) skeleton.save("full_annotation.zip") ``` Note - The name of the annotation will be derived from the filename stem - When saving as .zip, any associated volume layers will be included - The .nml format is human-readable XML but may be larger in size - The .zip format provides compression and can store additional data # webknossos.skeleton ## Tree ``` Tree( name: str, group: Group, skeleton: Skeleton, color: Vector4 | None = None, enforced_id: int | None = None, metadata: dict[ str, str | int | float | Sequence[str] ] = {}, is_visible: bool = True, ) ``` Bases: `Graph` Contains a collection of nodes and edges in a graph structure. Despite the name, trees may contain cycles. This class inherits from networkx.Graph and provides additional functionality specific to neural annotation tasks. Parameters: - **`name`** (`str`) – The name of the tree. - **`group`** (`Group`) – The group this tree belongs to. - **`skeleton`** (`Skeleton`) – The skeleton this tree is part of. - **`color`** (`Vector4 | None`, default: `None` ) – RGBA color values for the tree. Defaults to None. - **`enforced_id`** (`int | None`, default: `None` ) – Specific ID to use for the tree. Defaults to None. - **`metadata`** (`dict`, default: `{}` ) – Key-value metadata associated with the tree. Defaults to {}. - **`is_visible`** (`bool`, default: `True` ) – Whether the tree is visible in WEBKNOSSOS. Defaults to True. Returns: - **`Tree`** – A new Tree instance that represents a collection of nodes and edges. Raises: - `ValueError` – If the tree name is empty or if the group or skeleton is None. - `TypeError` – If the color value is not a valid Vector4 type when provided. Note It is recommended to create trees using `Skeleton.add_tree` or `Group.add_tree` instead of instantiating this class directly. This ensures proper parent-child relationships are maintained. Examples: Create a new tree with nodes and edges: ``` # First create a skeleton (parent object) skeleton = Skeleton("example_skeleton") # Add a new tree to the skeleton tree = skeleton.add_tree("dendrite_1") # Add nodes with 3D positions soma = tree.add_node(position=(0, 0, 0), comment="soma") branch1 = tree.add_node(position=(100, 0, 0), comment="branch1") branch2 = tree.add_node(position=(0, 100, 0), comment="branch2") # Connect nodes with edges tree.add_edge(soma, branch1) tree.add_edge(soma, branch2) # Access node positions positions = tree.get_node_positions() # Returns numpy array of all positions ``` For additional graph operations, see the [networkx documentation](https://networkx.org/documentation/stable/reference/classes/graph.html#methods). To create a tree, it is recommended to use `Skeleton.add_tree` or `Group.add_tree`. That way, the newly created tree is automatically attached as a child to the object the method was called on. ### color ``` color = color ``` ### group ``` group = group ``` ### id ``` id: int ``` The unique identifier of the tree. Returns: - **`int`** ( `int` ) – A unique identifier for this tree instance. Note This is a read-only property that is set during tree creation. ### is_visible ``` is_visible = is_visible ``` ### metadata ``` metadata = metadata ``` ### name ``` name = name ``` ### node_dict_factory ``` node_dict_factory = _NodeDict ``` ### add_node ``` add_node( position: Vec3IntLike, comment: str | None = None, radius: float | None = None, rotation: Vector3 | None = None, inVp: int | None = None, inMag: int | None = None, bitDepth: int | None = None, interpolation: bool | None = None, time: int | None = None, is_branchpoint: bool = False, branchpoint_time: int | None = None, _enforced_id: int | None = None, ) -> Node ``` Add a new node to the tree. Creates a new node at the specified position and adds it to the tree. Parameters: - **`position`** (`Vec3IntLike`) – The 3D coordinates (x, y, z) of the node. - **`comment`** (`str | None`, default: `None` ) – A text comment associated with the node. Visible in the WEBKNOSSOS UI. Defaults to None. - **`radius`** (`float | None`, default: `None` ) – Node radius for visualization. Defaults to None. - **`rotation`** (`Vector3 | None`, default: `None` ) – 3D rotation vector for the node. Defaults to None. - **`inVp`** (`int | None`, default: `None` ) – Viewport information. Defaults to None. - **`inMag`** (`int | None`, default: `None` ) – Magnification level. Defaults to None. - **`bitDepth`** (`int | None`, default: `None` ) – Bit depth for node data. Defaults to None. - **`interpolation`** (`bool | None`, default: `None` ) – Whether to use interpolation. Defaults to None. - **`time`** (`int | None`, default: `None` ) – Timestamp for the node. Defaults to None. - **`is_branchpoint`** (`bool`, default: `False` ) – Whether this node is a branch point. Defaults to False. - **`branchpoint_time`** (`int | None`, default: `None` ) – Timestamp for branch point creation. Defaults to None. - **`_enforced_id`** (`int | None`, default: `None` ) – Internal use only. Forces a specific node ID. Defaults to None. Returns: - **`Node`** ( `Node` ) – The newly created and added node. Examples: ``` # Add a simple node with just position node1 = tree.add_node(position=(100, 200, 300)) # Add a node with additional properties node2 = tree.add_node( position=(150, 250, 350), comment="Dendrite branch point", radius=2.5, is_branchpoint=True ) ``` ### adjlist_inner_dict_factory ``` adjlist_inner_dict_factory() -> _AdjDict ``` ### adjlist_outer_dict_factory ``` adjlist_outer_dict_factory() -> _AdjDict ``` ### get_max_node_id ``` get_max_node_id() -> int ``` Get the highest node ID in the tree. Returns: - **`int`** ( `int` ) – The maximum node ID present in the tree. Returns 0 if the tree has no nodes. ### get_node_by_id ``` get_node_by_id(node_id: int) -> Node ``` Retrieve a node using its unique identifier. Parameters: - **`node_id`** (`int`) – The unique identifier of the node to retrieve. Returns: - **`Node`** ( `Node` ) – The node with the specified ID. Raises: - `KeyError` – If no node exists with the given ID in this tree. ### get_node_positions ``` get_node_positions() -> ndarray ``` Get positions of all nodes in the tree. Returns: - `ndarray` – np.ndarray: A numpy array of shape (N, 3) containing the 3D positions of all N nodes in the tree. Each row represents a node's (x, y, z) coordinates.