Python API
Warning
This feature is still experimental. The provided API might change in the future.
ImFusion Labels comes with a Python module that provides an API to interact with a project from Python.
The module can be imported with imfusion.labels
and is distributed together with the application.
See the documentation of imfusion Python module for detailed install instructions (replace ImFusion Suite
with ImFusion Labels
in the provided paths).
It is also available through pip: pip install imfusion-sdk
.
The imfusion.labels
module provides some documentation and examples in its Docstring (help(imfusion.labels)
).
Example 1: Create and edit a Project
Creating or editing a project programmatically is practical if the project contains many labels that are e.g. pulled from another source. This example creates a local or remote project depending on whether a path to an empty folder or a URL to a Labels server instance is passed.
import argparse
from imfusion.labels import ProjectSettings, Project, Tag, TagKind, Layer, LayerKind, Label
parser = argparse.ArgumentParser(description="Resets the grouping of datasets to the default.")
parser.add_argument("path", help="Path to a Labels project. Either a local folder or a remote project path (e.g. http://example.com/projects/1")
parser.add_argument("-u", "--username", default="")
parser.add_argument("-p", "--password", default="")
args = parser.parse_args()
settings = ProjectSettings(
name="My Project",
tags=[
Tag("Tag 1", TagKind.Bool, (255, 0, 255)),
Tag("Tag 2", TagKind.Float, (0, 0, 255)),
Tag("Tag 3", TagKind.Enum, (0, 0, 255), ["Value 1", "Value 2"]),
],
layers=[
Layer(
"Layer 1",
LayerKind.PIXELWISE,
[
Label("Background", LayerKind.PIXELWISE, (0, 0, 0), value=0),
Label("Label 1", LayerKind.PIXELWISE, (255, 0, 255), value=1),
Label("Label 2", LayerKind.PIXELWISE, (0, 255, 0), value=2),
],
),
Layer("Layer 2", LayerKind.LANDMARK),
],
)
# Create a new project
with Project.create(settings, args.path, username=args.username, password=args.password) as project:
# Edit the project
new_settings = project.settings()
new_settings.remove_tag(new_settings.tags["Tag 3"])
new_settings.add_tag(Tag("Tag 4", TagKind.Bool, (255, 255, 128)))
new_settings.add_layer(
Layer(
"Layer 3",
LayerKind.BOUNDINGBOX,
[
Label("BB Label 1", LayerKind.BOUNDINGBOX, (255, 255, 0)),
],
)
)
project.edit(new_settings)
Example 2: Clear labels of all datasets
A common requirement is to run an algorithm or filter on all datasets.
This example opens a project, iterates over each dataset and layer and calls the algorithm
function for each labelmap.
In this case, the algorithm
only clears all labels but can be extended to e.g. automatically segment some structures.
Since the image and labelmap can be converted to regular numpy arrays, they can be passed to any library that can handle numpy such as scipy or PyTorch.
import sys
from typing import Optional
import numpy
import imfusion
import imfusion.labels
if len(sys.argv) != 2:
print("Expected path to project folder as first argument")
sys.exit(1)
project = imfusion.labels.Project.load(sys.argv[1])
# This function will be called for each dataset together with its labelmap.
# Returns either a new labelmap or none if the labelmap should remain unchanged.
# This function uses the same signature that is expected by the Algorithms actions and the Experiments tab.
# If moved to a separate module, it could also be used on e.g. individual datasets.
# Note that the codes doesn't have to be structured like, it's just the recommended best practice.
def algorithm(imfInput: imfusion.SharedImageSet, imfCurrentLabels: imfusion.SharedImageSet) -> Optional[imfusion.SharedImageSet]:
currentLabels = numpy.array(imfCurrentLabels)
zeroLabels = 0*currentLabels
imfLabels = imfusion.SharedImageSet(zeroLabels)
return imfLabels
for descriptor in project.descriptors:
# lock the dataset so that it cannot be modified in parallel
# by another user (only relevent for remote projects).
with descriptor.lock() as lock:
image = descriptor.load_image(crop_to_roi=False)
for layer in descriptor.labelmap_layers:
labelmap = layer.load()
if not labelmap:
labelmap = layer.create_empty_labelmap()
new_labelmap = algorithm(image, labelmap)
if new_labelmap:
# Instead of None, the algorithm function could also return the labelmap unchanged.
# In that case, certain meta data such as the "Last Modified" time would change though.
layer.save_new_data(new_labelmap, lock)
project.save()
Example 3: Batch import datasets with custom grouping
The grouping option in the database view is currently only available for DICOMs. If your want to import non-DICOM data or need some custom grouping, the best way is to batch import your data. The following example uses the folder names for grouping.
import os
import pathlib
import argparse
import imfusion
import imfusion.labels as labels
parser = argparse.ArgumentParser(description="Imports all files found inside a given folders to a Labels project and uses the folder path for grouping. Expects that all files are exactly 3 subfolders deep.")
parser.add_argument("project", help="Path to a Labels project. Either a local folder or a remote project path (e.g. http://example.com/projects/1")
parser.add_argument("folder", help="Folder containing the files to import")
parser.add_argument("-u", "--username", default=None)
parser.add_argument("-p", "--password", default=None)
args = parser.parse_args()
# Load the project and assign the names of the grouping hierachy that should be shown in the UI
project = labels.Project.load(args.project, username=args.username, password=args.password)
project.grouping_hierachy = ["One", "Two", "Three"]
# In remote projects we cannot set the grouping directly
# after adding the descriptor, because the project needs to sync
# with the server first.
# Instead we track which descriptor id should receive which groups
# and assign them later
groups_for_descriptor = {}
base_folder = pathlib.Path(args.folder)
# Iterate the directory recursively
for (path, dirnames, filenames) in os.walk(base_folder):
path = pathlib.Path(path)
# split the path into folders that we are going to use for grouping
groups = path.relative_to(base_folder).parts
if len(groups) != 3:
# this example script expects all images being 3 folders deep (e.g. "one/two/three/file.png")
continue
for filename in filenames:
# Load all images and add them to the project
for image in imfusion.load(str(path / filename)):
print("Adding", path / filename)
desc = project.add_descriptor(image, name=filename)
if project.is_remote:
groups_for_descriptor[desc] = groups
else:
desc.grouping = groups
if project.is_remote:
# Syncing the project retrieves all descriptors from the server
project.sync()
for desc in project.descriptors:
if desc.identifier in groups_for_descriptor:
desc.grouping = groups_for_descriptor[desc.identifier]
else:
project.save()
Example 4: Reset grouping to default value
The following script iterates all datasets of a project, reads the meta-data and resets the grouping information to the default.
import argparse
import datetime
import imfusion.labels as labels
parser = argparse.ArgumentParser(description="Resets the grouping of datasets to the default.")
parser.add_argument("project", help="Path to a Labels project. Either a local folder or a remote project path (e.g. http://example.com/projects/1")
parser.add_argument("-u", "--username", default=None)
parser.add_argument("-p", "--password", default=None)
args = parser.parse_args()
# Load the project and assign the names of the grouping hierachy that should be shown in the UI
project = labels.Project.load(args.project, username=args.username, password=args.password)
project.grouping_hierachy = ["Patient", "Study", "Series"]
def format_description_and_date(desc, date):
"""
Formats a potential empty description and date into a combined string.
"""
try:
# the date is YYYYMMDD, but YYYY-MM-DD is more readable
date = datetime.datetime.strptime(date, "%Y%m%d").date().isoformat()
except ValueError:
date = ""
if date and desc:
return f"{desc} - {date}"
elif desc:
return desc;
elif date:
return "";
else:
return "<Unnamed>"
for desc in project.descriptors:
image = desc.load_image(crop_to_roi=False)
if not image:
print(f"Could not load {desc.identifier}. Skipping")
continue
# All images have additional meta-data attached in the form of
# DataComponents. The ImageInfoDataComponent provides patient, study
# and series information among other things.
info = image.components.image_info
if info:
# Assign the values the dataset should be grouped with.
# E.g. datasets with the same first value will be grouped as a
# single patient.
# The grouping values support an optional ||| separator. The complete value
# will be used for grouping, but only everything after the separator will be
# displayed in the UI (e.g. to hide very long ID strings).
desc.grouping = [
f"{info.patient_id}|||{info.patient_name}",
f"{info.study_instance_uid}|||{format_description_and_date(info.study_description, info.study_date)}",
f"{info.series_instance_uid}|||{format_description_and_date(info.series_description, info.series_date)}",
]
if project.is_local:
project.save()
Reference
This module offers a way of interacting with Labels projects from python.
The central class in this module is the Project
class. It allow you to either create a new local project or load an existing local project:
import imfusion
from imfusion import labels
new_project = labels.Project('New Project', 'path/to/new/project/folder')
existing_project = labels.Project.load('path/to/existing/project')
remote_project = labels.Project.load('http://example.com', '1', 'username', 'password123')
From there you can add new tag definitions, annotation definitions and data to the project:
project.add_tag('NewTag', labels.TagKind.Bool)
project.add_labelmap_layer('NewLabelmap')
project.add_descriptor(imfusion.io.open('/path/to/image')[0])
The Project
instance is also the central way to access this kind of data:
new_tag = project.tags['NewTag'] # can also be indexed with an integer, i.e. tags[0]
new_labelmap = project.labelmap_layers['NewLabelmap'] # can also be indexed with an interger, i.e. labelmap_layers[0]
new_descriptor = project.descriptors[0]
The DataDescriptor
class represents an entry in the project’s database and can be used to access the the entry’s metadata, tags and annotations.
The interface for accessing tags and annotations is the same as in Project
but also offers the additional value
attribute to get the value of the tag / annotation:
name = descriptor.name
shape = (descriptor.n_images, descriptor.n_channels, descriptor.n_slices, descriptor.height, descriptor.width)
new_tag = descriptor.tags['NewTag']
tag_value = descriptor.tags['NewTag'].value
labelmap = descriptor.labelmap_layers['NewLabelmap'].load()
roi = descriptor.roi
image = descriptor.load_image(crop_to_roi=True)
Note
Keep in mind that all modifications made to a local project are stored in memory and will only be saved to disk if you call Project.save()
.
Modifications to remote projects are applied immediately.
Alternatively, you can also use the Project
as a context manager:
with Project('SomeName', /some/path) as project:
... # will automatically save the project when exiting the context if there was no exception
Warning
Changing annotation data is the only exception to this rule. It is written immediately to disk (see :meth:LabelMapLayer.save_new_data`, :meth:LandmarkLayer.save_new_data`, :meth:BoundingBoxLayer.save_new_data`)
- class imfusion.labels.BoundingBox
Bases:
pybind11_object
- property color
- property descriptor
- property index
- property name
- property project
- class imfusion.labels.BoundingBoxAccessor
Bases:
pybind11_object
- property names
List of the names of
BoundingBox
s available through thisBoundingBoxAccessor
- size(self: imfusion.labels._bindings.BoundingBoxAccessor) int
- class imfusion.labels.BoundingBoxLayer
Bases:
pybind11_object
- add_annotation(self: imfusion.labels._bindings.BoundingBoxLayer, name: str, color: tuple[int, int, int] = (255, 255, 255)) imfusion.labels._bindings.BoundingBox
Define a new entry in this boundingbox layer. The definition consists of only the name, the actual coordinates for it are stored in the BoxSet.
- Args:
name (str): Name of the new boundingbox. color (tuple[int, int, int]): Color for displaying this boundingbox in the UI.
- add_boundingbox()
add_annotation(self: imfusion.labels._bindings.BoundingBoxLayer, name: str, color: tuple[int, int, int] = (255, 255, 255)) -> imfusion.labels._bindings.BoundingBox
Define a new entry in this boundingbox layer. The definition consists of only the name, the actual coordinates for it are stored in the BoxSet.
- Args:
name (str): Name of the new boundingbox. color (tuple[int, int, int]): Color for displaying this boundingbox in the UI.
- property annotations
- property boundingboxes
- property descriptor
- property folder
- property id
- property index
- load(self: imfusion.labels._bindings.BoundingBoxLayer) object
- property name
- property project
- save_new_data(self: imfusion.labels._bindings.BoundingBoxLayer, value: object, lock_token: imfusion.labels._bindings.LockToken = LockToken(token='')) None
Change the data of this layer.
Warning
Beware that, unlike other modifications, new layer data is immediately written to disk, regardless of calls to
Project.save()
.
- class imfusion.labels.BoundingBoxLayersAccessor
Bases:
pybind11_object
- property active
Return the currently active layer or None if no layer is active.
The active layer is usually only relevant when using Python inside the application. It can be set by the user to defined the layer that can be modified with e.g. the brush tool.
It’s currently not possible to change the active layer through the Python API but only in the UI.
- property names
List of the names of
BoundingBoxLayer
s available through thisBoundingBoxLayersAccessor
- size(self: imfusion.labels._bindings.BoundingBoxLayersAccessor) int
- class imfusion.labels.BoxSet
Bases:
pybind11_object
- add(self: imfusion.labels._bindings.BoxSet, type: str, frame: int, top_left: numpy.ndarray[numpy.float64[3, 1]], lower_right: numpy.ndarray[numpy.float64[3, 1]]) None
Add a box to the set.
- Args:
type (str): Type of box that should be added. frame (int): Frame for which this box should be added. top_left (tuple[int, int, int]): Coordinates of the top left corner of the box. lower_right (tuple[int, int, int]): Coordinates of the lower right corner of the box.
- asdict(self: imfusion.labels._bindings.BoxSet) dict
Convert this AnnotationSet into a dict. Modifying the dict does not reflect on the AnnotationSet.
- frame(self: imfusion.labels._bindings.BoxSet, which: int) imfusion.labels._bindings.BoxSet
Select only the points that belong to the specified frame.
- static from_descriptor(descriptor: imfusion.labels._bindings.Descriptor, layer_name: str) imfusion.labels._bindings.BoxSet
Create a BoxSet tailored to a specific annotation layer in a descriptor.
- type(*args, **kwargs)
Overloaded function.
type(self: imfusion.labels._bindings.BoxSet, type: str) -> imfusion.labels._bindings.BoxSet
Select only the points that belong to the specified type.
type(self: imfusion.labels._bindings.BoxSet, type: int) -> imfusion.labels._bindings.BoxSet
Select only the points that belong to the specified type.
- class imfusion.labels.DataType
Bases:
pybind11_object
Enum for specifying what is considered valid data in the project.
Members:
SingleChannelImages : Consider 2D greyscale images as valid data.
MultiChannelImages : Consider 2D color images as valid data.
SingleChannelVolumes : Consider 3D greyscale images as valid data.
MultiChannelVolumes : Consider 3D color images as valid data.
AnyDataType : Consider any kind of image data as valid data.
- AnyDataType = DataType.AnyDataType
- MultiChannelImages = DataType.MultiChannelImages
- MultiChannelVolumes = DataType.MultiChannelVolumes
- SingleChannelImages = DataType.SingleChannelImages
- SingleChannelVolumes = DataType.SingleChannelVolumes
- property name
- property value
- class imfusion.labels.Descriptor
Bases:
pybind11_object
Class representing an entry in the project’s database. It holds, amongst other things, meta data about the image, annotations and the location of the image.
- property boundingbox_layers
- property byte_size
- property comments
- consider_frame_annotated(self: imfusion.labels._bindings.Descriptor, frame: int, annotated: bool) None
- property grouping
- property has_data
- property height
- property identifier
- property import_time
- is_considered_annotated(self: imfusion.labels._bindings.Descriptor, frame: object = None) bool
- property is_locked
- property labelmap_layers
- property landmark_layers
- property latest_edit_time
- load_image(self: imfusion.labels._bindings.Descriptor, crop_to_roi: bool) imfusion.SharedImageSet
- property load_path
- load_thumbnail(self: imfusion.labels._bindings.Descriptor, generate: bool = True) imfusion.SharedImageSet
Return the image thumbnail as a SharedImageSet.
- Args:
generate (bool): Whether to generate the thumbnail if it’s missing. If this is False, the method will return None for missing thumbnails.
- property modality
- property n_channels
- property n_images
- property n_slices
- property name
- property original_data_path
- property own_copy
- property patient_name
- property project
- property region_of_interest
- property roi
- property scale
- property series_instance_uid
- property shift
- property spacing
- property sub_file_id
- property tags
- property thumbnail_path
- property top_down
- property type
- property width
- class imfusion.labels.Label
Bases:
pybind11_object
A single Label of
Layer
that defines its name and color among other things.- property color
- property id
- property kind
- property name
- property value
- class imfusion.labels.LabelLegacy
Bases:
pybind11_object
- property color
- property descriptor
- property index
- property name
- property project
- property value
- class imfusion.labels.LabelMapLayer
Bases:
pybind11_object
- add_annotation(self: imfusion.labels._bindings.LabelMapLayer, name: str, value: int, color: tuple[int, int, int] | None = None) imfusion.labels._bindings.LabelLegacy
Define a new entry in this labelmap layer. A label is represented by a name and a corresponding integer value for designating voxels in the labelmap.
- Args:
name (str): Name of the new label. value (int): Value for encoding this label in the labelmap. color (tuple[int, int, int]): Color for displaying this label in the UI. Int need to be in the range [0 255]. Default colors are picked if not provided.
- add_label()
add_annotation(self: imfusion.labels._bindings.LabelMapLayer, name: str, value: int, color: Optional[tuple[int, int, int]] = None) -> imfusion.labels._bindings.LabelLegacy
Define a new entry in this labelmap layer. A label is represented by a name and a corresponding integer value for designating voxels in the labelmap.
- Args:
name (str): Name of the new label. value (int): Value for encoding this label in the labelmap. color (tuple[int, int, int]): Color for displaying this label in the UI. Int need to be in the range [0 255]. Default colors are picked if not provided.
- property annotations
- create_empty_labelmap(self: imfusion.labels._bindings.LabelMapLayer) object
Create an empty labelmap that is compatible with this layer. The labelmap will have the same size and meta data as the image. The labelmap is completely independent of the layer and does not replace the existing labelmap of the layer! To use this labelmap for the layer, call
LabelMapLayer.save_new_data()
.
- property descriptor
- property folder
- has_data(self: imfusion.labels._bindings.LabelMapLayer) bool
Return whether the labelmap exists and is not empty.
- property id
- property index
- property labels
- load(self: imfusion.labels._bindings.LabelMapLayer) object
Load the labelmap as a SharedImagetSet. If the labelmap is completely empty, None is returned. To create a new labelmap use
LabelMapLayer.create_empty_labelmap()
.
- property name
- path(self: imfusion.labels._bindings.LabelMapLayer) str
Returns the path where the labelmap is stored on disk. Empty for remote projects.
- property project
- save_new_data(self: imfusion.labels._bindings.LabelMapLayer, value: object, lock_token: imfusion.labels._bindings.LockToken = LockToken(token='')) None
Change the data of this layer.
Warning
Beware that, unlike other modifications, new layer data is immediately written to disk, regardless of calls to
Project.save()
.
- thumbnail_path(self: imfusion.labels._bindings.LabelMapLayer) str
Returns the path where the labelmap thumbnail is stored on disk. Empty for remote projects.
- class imfusion.labels.LabelMapsAccessor
Bases:
pybind11_object
- property active
Return the currently active layer or None if no layer is active.
The active layer is usually only relevant when using Python inside the application. It can be set by the user to defined the layer that can be modified with e.g. the brush tool.
It’s currently not possible to change the active layer through the Python API but only in the UI.
- property names
List of the names of
LabelMap
s available through thisLabelMapsAccessor
- size(self: imfusion.labels._bindings.LabelMapsAccessor) int
- class imfusion.labels.LabelsAccessor
Bases:
pybind11_object
Like a
list
ofLabel
, but allows indexing by index or name.- property names
List of the names of
Label
s available through thisLabelsAccessor
- class imfusion.labels.LabelsAccessorLegacy
Bases:
pybind11_object
- property names
List of the names of
LabelLegacy
s available through thisLabelsAccessorLegacy
- size(self: imfusion.labels._bindings.LabelsAccessorLegacy) int
- class imfusion.labels.Landmark
Bases:
pybind11_object
- property color
- property descriptor
- property index
- property name
- property project
- class imfusion.labels.LandmarkLayer
Bases:
pybind11_object
- add_annotation(self: imfusion.labels._bindings.LandmarkLayer, name: str, color: tuple[int, int, int] = (255, 255, 255)) imfusion.labels._bindings.Landmark
Define a new entry in this landmark layer. The definition consists of only the name, the actual coordinates for it are stored in the LandmarkSet.
- Args:
name (str): Name of the new landmark. color (tuple[int, int, int]): Color for displaying this annotation in the UI.
- add_landmark()
add_annotation(self: imfusion.labels._bindings.LandmarkLayer, name: str, color: tuple[int, int, int] = (255, 255, 255)) -> imfusion.labels._bindings.Landmark
Define a new entry in this landmark layer. The definition consists of only the name, the actual coordinates for it are stored in the LandmarkSet.
- Args:
name (str): Name of the new landmark. color (tuple[int, int, int]): Color for displaying this annotation in the UI.
- property annotations
- property descriptor
- property folder
- property id
- property index
- property landmarks
- load(self: imfusion.labels._bindings.LandmarkLayer) object
- property name
- property project
- save_new_data(self: imfusion.labels._bindings.LandmarkLayer, value: object, lock_token: imfusion.labels._bindings.LockToken = LockToken(token='')) None
Change the data of this layer.
Warning
Beware that, unlike other modifications, new layer data is immediately written to disk, regardless of calls to
Project.save()
.
- class imfusion.labels.LandmarkLayersAccessor
Bases:
pybind11_object
- property active
Return the currently active layer or None if no layer is active.
The active layer is usually only relevant when using Python inside the application. It can be set by the user to defined the layer that can be modified with e.g. the brush tool.
It’s currently not possible to change the active layer through the Python API but only in the UI.
- property names
List of the names of
LandmarkLayer
s available through thisLandmarkLayersAccessor
- size(self: imfusion.labels._bindings.LandmarkLayersAccessor) int
- class imfusion.labels.LandmarkSet
Bases:
pybind11_object
- add(self: imfusion.labels._bindings.LandmarkSet, type: str, frame: int, world: numpy.ndarray[numpy.float64[3, 1]]) None
Add a keypoint to the set.
- Args:
type (str): Type of keypoint that should be added. frame (int): Frame for which this keypoint should be added. world (tuple[int, int, int]): Coordinates of the point.
- asdict(self: imfusion.labels._bindings.LandmarkSet) dict
Convert this AnnotationSet into a dict. Modifying the dict does not reflect on the AnnotationSet.
- frame(self: imfusion.labels._bindings.LandmarkSet, which: int) imfusion.labels._bindings.LandmarkSet
Select only the points that belong to the specified frame.
- static from_descriptor(descriptor: imfusion.labels._bindings.Descriptor, layer_name: str) imfusion.labels._bindings.LandmarkSet
Create a LandmarkSet tailored to a specific annotation layer in a descriptor.
- type(*args, **kwargs)
Overloaded function.
type(self: imfusion.labels._bindings.LandmarkSet, type: str) -> imfusion.labels._bindings.LandmarkSet
Select only the points that belong to the specified type.
type(self: imfusion.labels._bindings.LandmarkSet, type: int) -> imfusion.labels._bindings.LandmarkSet
Select only the points that belong to the specified type.
- class imfusion.labels.LandmarksAccessor
Bases:
pybind11_object
- property names
List of the names of
Landmark
s available through thisLandmarksAccessor
- size(self: imfusion.labels._bindings.LandmarksAccessor) int
- class imfusion.labels.Layer
Bases:
pybind11_object
A single layer that defines which labels can be annotated for each
Descriptor
.- add_label(self: imfusion.labels._bindings.Layer, arg0: imfusion.labels._bindings.Label) None
- property id
- property kind
- property labels
- property name
- class imfusion.labels.LayerKind
Bases:
pybind11_object
The kind of a layer defines what can be labelled in that layer.
Members:
PIXELWISE
BOUNDINGBOX
LANDMARK
- BOUNDINGBOX = <LayerKind.BOUNDINGBOX: 1>
- LANDMARK = <LayerKind.LANDMARK: 2>
- PIXELWISE = <LayerKind.PIXELWISE: 0>
- property name
- property value
- class imfusion.labels.LayersAccessor
Bases:
pybind11_object
Like a
list
ofLayer
, but allows indexing by index or name.- property names
List of the names of
Layer
s available through thisLayersAccessor
- class imfusion.labels.LockToken
Bases:
pybind11_object
A token representing a lock of a DataDescriptor.
Only the holder of the token can modify the layers of a locked
Descriptor
. Locking is only supported in remote projects. Local projects ignore the locking mechanism. A LockToken can be acquired throughlock()
. It can be used as a context manager so that it is unlocked automatically, when exiting the context. Tokens expire automatically after a certain time depending on the server (default: after 5 minutes).descriptor = project.descriptors[0] with descriptor.lock() as lock: ...
- unlock(self: imfusion.labels._bindings.LockToken) None
Releases the lock. The token will become invalid afters and should not be used anymore.
- class imfusion.labels.Project
Bases:
pybind11_object
Class that represents a Labels project. A project holds all information regarding defined annotations and data samples
- add_boundingbox_layer(self: imfusion.labels._bindings.Project, name: str) imfusion.labels._bindings.BoundingBoxLayer
Define a new boundingbox layer for this project.
- Args:
name (str): Name of the new boundingbox layer.
- add_descriptor(*args, **kwargs)
Overloaded function.
add_descriptor(self: imfusion.labels._bindings.Project, shared_image_set: imfusion.SharedImageSet, name: str = ‘’, own_copy: bool = False) -> object
Create a new entry in the project’s database from a given image. For local project, the descriptor to the dataset is returned immediately. For remote project, only the identifier of the descriptor is returned. The actual dataset will only become available after a call to sync().
- Args:
name (str): Name of the new database entry. shared_image_set (imfusion.SharedImageSet): Image for which the new entry will be created. own_copy (bool): If True, Labels will save a copy of the image in the project folder.
Automatically set to True if the image does not have a DataSourceComponent, as this implies that is was created rather then loaded.
add_descriptor(self: imfusion.labels._bindings.Project, name: str, shared_image_set: imfusion.SharedImageSet, own_copy: bool = False) -> object
Create a new entry in the project’s database from a given image. For local project, the descriptor to the dataset is returned immediately. For remote project, only the identifier of the descriptor is returned. The actual dataset will only become available after a call to sync().
- Args:
name (str): Name of the new database entry. shared_image_set (imfusion.SharedImageSet): Image for which the new entry will be created. own_copy (bool): If True, Labels will save a copy of the image in the project folder.
Automatically set to True if the image does not have a DataSourceComponent, as this implies that is was created rather then loaded.
- add_labelmap_layer(self: imfusion.labels._bindings.Project, name: str) imfusion.labels._bindings.LabelMapLayer
Define a new labelmap layer for this project.
- Args:
name (str): Name of the new labelmap layer.
- add_landmark_layer(self: imfusion.labels._bindings.Project, name: str) imfusion.labels._bindings.LandmarkLayer
Define a new landmark layer for this project.
- Args:
name (str): Name of the new landmark layer.
- add_tag(self: imfusion.labels._bindings.Project, name: str, kind: imfusion.labels._bindings.TagKind, color: tuple[int, int, int] = (255, 255, 255), options: list[str] = []) imfusion.labels._bindings.TagLegacy
Define a new tag for this project.
- Args:
name (str): Name of the new tag. kind (imfusion.labels.TagKind): Type of the new tag (Bool, Float or Enum). color (tuple[int, int, int]): Color of the tag in the UI. options (list[str]): Options that the user can choose from. Only applies to Enum tags.
- property boundingbox_layers
Returns an
BoundingBoxLayersAccessor
to the boundingbox layers defined in the project.
- property configuration
- static create(settings: imfusion.labels._bindings.ProjectSettings, path: str = '', username: str = '', password: str = '') imfusion.labels._bindings.Project
Create a new project with the given settings.
path
can be either a path or URL.Passing a folder will create a local project. The folder must be empty otherwise an exception is raised.
When passing a http(s) URL, it must point to the base URL of a Labels server (e.g. https://example.com and not https://example.com/api/v1/projects). Additionally, a valid username and password must be specified. The server might reject a project, e.g. because a project with the same name already exists. In this case, an exception is raised.
- property data_type
- delete_descriptors(self: imfusion.labels._bindings.Project, descriptors: list[imfusion.labels._bindings.Descriptor]) None
“Remove the given descriptors from the project.
- Args:
descriptors (list[Descriptors]): list of descriptors that should be deleted from the project.
- property descriptors
- edit(self: imfusion.labels._bindings.Project, arg0: imfusion.labels._bindings.ProjectSettings) None
Edit the project settings by applying the given settings.
Editing a project is a potentially destructive action that cannot be reverted.
When adding new tags, layers or label their “id” field should be empty (an id will be automatically assigned).
Warning
Remote project are not edited in-place at the moment. After calling this method, you need to reload the project from the server. Otherwise, the project settings will be out of sync with the server.
- property grouping_hierachy
- property id
Return the unique id of a remote project.
- property is_local
Returns whether the project is local
- property is_remote
Returns whether the project is remote
- property labelmap_layers
Returns an Accessor to the labelmap layers defined in the project.
- property landmark_layers
Returns an
LandmarkLayerAccessor
to the landmark layers defined in the project.
- static load(path: str, project_id: str | None = None, username: str | None = None, password: str | None = None) imfusion.labels._bindings.Project
Load an existing project from disk or from a remote server.
- Args:
path (str): Either a folder containing a local project or an URL to a remote project. project_id (str): the ID of the project to load username (str): the username with which to authenticate password (str): the password with which to authenticate
- property path
- refresh_access_token(self: imfusion.labels._bindings.Project) None
Refresh the access token of a remote project. Access tokens expire after a predefined period of time, and need to be refreshed in order to make further requests.
- save(self: imfusion.labels._bindings.Project) None
Save the modifications performed in memory to disk.
- settings(self: imfusion.labels._bindings.Project) imfusion.labels._bindings.ProjectSettings
Return the current settings of a project.
The settings are not connected to the project, so changing the settings object does not change the project. Use
edit()
to apply new settings.
- sync(self: imfusion.labels._bindings.Project) int
Synchronize the local state of a remote project. Any “event” that occured between the last sync() call and this one are replayed locally, such that the local Project reflects the last known state of the project on the server. An “event” refers to any change being made on the project data by any client (including this one), such as a dataset being added or deleted, a new label map being uploaded, a tag value being changed, etc.
Returns the number of events applied to the project.
- property tags
Returns an Accessor to the tags defined in the project.
- class imfusion.labels.ProjectSettings
Bases:
pybind11_object
Contains the invididual elements that make up a project definition.
- add_layer(self: imfusion.labels._bindings.ProjectSettings, arg0: imfusion.labels._bindings.Layer) None
Add a new layer to the settings.
- add_tag(self: imfusion.labels._bindings.ProjectSettings, arg0: imfusion.labels._bindings.Tag) None
Add a new tag to the settings.
- property layers
- property name
- remove_layer(self: imfusion.labels._bindings.ProjectSettings, arg0: imfusion.labels._bindings.Layer) None
- remove_tag(self: imfusion.labels._bindings.ProjectSettings, arg0: imfusion.labels._bindings.Tag) None
- property tags
- class imfusion.labels.Tag
Bases:
pybind11_object
A Tag definition. Tag values can be set on a
Descriptor
according to this definition.- property color
- property id
- property kind
- property name
- property options
- property readonly
- class imfusion.labels.TagKind
Bases:
pybind11_object
Enum for differentiating different kinds of tags.
Members:
Bool : Tag that stores a single boolean value.
Enum : Tag that stores a list of string options.
Float : Tag that stores a single float value.
- Bool = <TagKind.Bool: 0>
- Enum = <TagKind.Enum: 1>
- Float = <TagKind.Float: 2>
- property name
- property value
- class imfusion.labels.TagLegacy
Bases:
pybind11_object
- add_option(self: imfusion.labels._bindings.TagLegacy, option: str) None
Add a new value option for this tag (only works with enum tags).
- Args:
option: New option to be added to this tag.
- property color
- property descriptor
- property id
- property index
- property kind
- property locked
- property name
- property options
- property project
- property value
- class imfusion.labels.TagsAccessor
Bases:
pybind11_object
Like a
list
ofTag
, but allows indexing by index or name.- property names
List of the names of
Tag
s available through thisTagsAccessor
- class imfusion.labels.TagsAccessorLegacy
Bases:
pybind11_object
- property names
List of the names of
TagLegacy
s available through thisTagsAccessorLegacy
- size(self: imfusion.labels._bindings.TagsAccessorLegacy) int
- imfusion.labels.deprecate(old: str, new: str, owner: object, is_property=False)
- imfusion.labels.wraps(wrapped, assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotations__'), updated=('__dict__',))
Decorator factory to apply update_wrapper() to a wrapper function
Returns a decorator that invokes update_wrapper() with the decorated function as the wrapper argument and the arguments to wraps() as the remaining arguments. Default arguments are as for update_wrapper(). This is a convenience function to simplify applying partial() to update_wrapper().