webknossos 4.2.2__tar.gz → 4.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {webknossos-4.2.2 → webknossos-4.2.3}/PKG-INFO +2 -2
- {webknossos-4.2.2 → webknossos-4.2.3}/pyproject.toml +2 -2
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_cli.py +41 -1
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/annotation/annotation_info.py +2 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/export_as_tiff.py +2 -2
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/models.py +2 -1
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/export.py +8 -1
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/layer.py +6 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/view/_array.py +48 -18
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/view/mag_view.py +30 -6
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/view/remote_mag_view.py +9 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/view/view.py +58 -4
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/dataset_properties.py +5 -0
- webknossos-4.2.3/webknossos/version.py +1 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/PKG-INFO +2 -2
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/requires.txt +1 -1
- webknossos-4.2.2/webknossos/version.py +0 -1
- {webknossos-4.2.2 → webknossos-4.2.3}/README.md +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/setup.cfg +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_annotation.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_api_client.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_cli_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_skeleton.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/tests/test_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/branchpoint.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/comment.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/edge.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/group.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/meta.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/metadata_entry.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/nml.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/node.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/parameters.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/segment.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/tree.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/_nml/volume.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/administration/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/administration/project.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/administration/task.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/administration/team.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/administration/user.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/ai_model/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/ai_model/ai_model_category.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/ai_model/remote_ai_model.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/annotation/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/annotation/_nml_conversion.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/annotation/annotation.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/annotation/volume_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/check_equality.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/compress.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/convert.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/convert_knossos.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/convert_raw.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/convert_zarr.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/copy_dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/download.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/downsample.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/main.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/merge_fallback.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/upload.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/cli/upsample.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_defaults.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_download_dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resolve_short_link.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resumable/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resumable/chunk.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resumable/core.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resumable/file.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_resumable/util.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/_upload_dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/_abstract_api_client.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/_serialization.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/datastore_api_client.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/errors.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/tracingstore_api_client.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/api_client/wk_api_client.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/client/context.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/chunked_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/common_slice_readers.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/czi_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/dm_slice_reader.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/image_conversion.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/image_source_registry.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/ims_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/infer_bounding_box_existing_files.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/mrc_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/n5_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/neuroglancer_precomputed_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/ome_zarr_helpers.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/ozx_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/segmentation_recognition.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/slice_reader.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/sliced_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/tensorstore_chunked_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/tiff_slice_reader.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/vendor/dm3.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/vendor/dm4.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_image_conversion/zarr_image_source.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_metadata.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_utils/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_utils/buffered_slice_reader.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_utils/buffered_slice_writer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_utils/tensorstore_helpers.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/_utils/tinywkw.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/abstract_dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/defaults.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/errors.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/_downsampling_numba.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/_downsampling_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/_transform_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/_upsampling_utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/abstract_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/layer_to_link.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/remote_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/abstract_segmentation_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/attachments/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/attachments/agglomerate_attachment.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/attachments/attachment.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/attachments/attachments.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/remote_segmentation_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/segmentation_layer/segmentation_layer.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/layer/view/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/ome_metadata.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/remote_access_mode.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/remote_dataset.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/remote_dataset_registry.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/remote_folder.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/sampling_modes.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset/transfer_mode.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/_bigint_envelope.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/coordinate_transformations.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/data_format.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/dtype_conversion.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/layer_categories.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/length_unit.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/dataset_properties/structuring.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/datastore/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/datastore/datastore.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/bounding_box.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/constants.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/mag.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/nd_bounding_box.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/normalized_bounding_box.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/vec3_float.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/vec3_int.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/geometry/vec_int.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/proofreading/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/proofreading/agglomerate_graph_data.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/proofreading/generated/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/proofreading/generated/agglomerate_graph_pb2.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/proofreading/generated/agglomerate_graph_pb2.pyi +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/py.typed +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/skeleton/__init__.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/skeleton/group.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/skeleton/node.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/skeleton/skeleton.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/skeleton/tree.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/ssl_context.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos/utils.py +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/SOURCES.txt +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/dependency_links.txt +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/entry_points.txt +0 -0
- {webknossos-4.2.2 → webknossos-4.2.3}/webknossos.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webknossos
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.3
|
|
4
4
|
Summary: Python API for working with WEBKNOSSOS datasets, annotations, and for WEBKNOSSOS server interaction.
|
|
5
5
|
Author-email: scalable minds <hello@scalableminds.com>
|
|
6
6
|
License: AGPL-3.0
|
|
@@ -37,7 +37,7 @@ Requires-Dist: boltons>=21.0.0
|
|
|
37
37
|
Requires-Dist: cattrs>=22.0.0
|
|
38
38
|
Requires-Dist: certifi>=2023
|
|
39
39
|
Requires-Dist: click<8.2.0
|
|
40
|
-
Requires-Dist: cluster-tools==4.2.
|
|
40
|
+
Requires-Dist: cluster-tools==4.2.3
|
|
41
41
|
Requires-Dist: httpx~=0.27.0
|
|
42
42
|
Requires-Dist: imageio>=2.37.0
|
|
43
43
|
Requires-Dist: lz4>=4.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "webknossos"
|
|
3
|
-
version = "4.2.
|
|
3
|
+
version = "4.2.3" # filled by dunamai
|
|
4
4
|
description = "Python API for working with WEBKNOSSOS datasets, annotations, and for WEBKNOSSOS server interaction."
|
|
5
5
|
authors = [{ name = "scalable minds", email = "hello@scalableminds.com" }]
|
|
6
6
|
readme = "README.md"
|
|
@@ -39,7 +39,7 @@ dependencies = [
|
|
|
39
39
|
"cattrs >=22.0.0",
|
|
40
40
|
"certifi >=2023",
|
|
41
41
|
"click <8.2.0", # pinned because of incompatibility with typer
|
|
42
|
-
"cluster-tools==4.2.
|
|
42
|
+
"cluster-tools==4.2.3",
|
|
43
43
|
"httpx ~=0.27.0",
|
|
44
44
|
"imageio >=2.37.0",
|
|
45
45
|
"lz4 >=4.0.0",
|
|
@@ -25,7 +25,7 @@ from tests.constants import (
|
|
|
25
25
|
TESTDATA_DIR,
|
|
26
26
|
)
|
|
27
27
|
from tests.data_fixtures import download_wklibs_sample_archive
|
|
28
|
-
from webknossos import BoundingBox, DataFormat, Dataset, Mag
|
|
28
|
+
from webknossos import BoundingBox, DataFormat, Dataset, Mag, NDBoundingBox
|
|
29
29
|
from webknossos.cli.export_as_tiff import _apply_mapping, _make_tiff_name
|
|
30
30
|
from webknossos.cli.main import app
|
|
31
31
|
from webknossos.dataset._utils.tensorstore_helpers import (
|
|
@@ -629,6 +629,46 @@ def test_export_tiff_stack(tmp_upath: UPath) -> None:
|
|
|
629
629
|
)
|
|
630
630
|
|
|
631
631
|
|
|
632
|
+
def test_export_tiff_stack_nd_layer(tmp_upath: UPath) -> None:
|
|
633
|
+
"""Tests export of a layer whose array is stored as (c, t, x, y, z)."""
|
|
634
|
+
|
|
635
|
+
source_path = tmp_upath / "nd_dataset"
|
|
636
|
+
destination_path = tmp_upath / "nd_dataset_tiff"
|
|
637
|
+
nd_bbox = NDBoundingBox(
|
|
638
|
+
(0, 0, 0, 0, 0),
|
|
639
|
+
(1, 1, 16, 16, 8),
|
|
640
|
+
axes=("c", "t", "x", "y", "z"),
|
|
641
|
+
index=(0, 1, 2, 3, 4),
|
|
642
|
+
)
|
|
643
|
+
data = np.random.default_rng(0).integers(0, 255, (1, 1, 16, 16, 8), dtype="uint8")
|
|
644
|
+
layer = Dataset(source_path, voxel_size=(11, 11, 25)).add_layer(
|
|
645
|
+
"color", "color", dtype="uint8", data_format="zarr3", bounding_box=nd_bbox
|
|
646
|
+
)
|
|
647
|
+
layer.add_mag(1).write(data=data, absolute_bounding_box=nd_bbox)
|
|
648
|
+
assert layer.get_mag(1).info.bounding_box.axes == ("c", "t", "x", "y", "z")
|
|
649
|
+
|
|
650
|
+
result = runner.invoke(
|
|
651
|
+
app,
|
|
652
|
+
[
|
|
653
|
+
"export-as-tiff",
|
|
654
|
+
"--layer-name",
|
|
655
|
+
"color",
|
|
656
|
+
"--bbox",
|
|
657
|
+
"2,4,1,8,10,5",
|
|
658
|
+
str(source_path),
|
|
659
|
+
str(destination_path),
|
|
660
|
+
],
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
assert result.exit_code == 0, result.stdout
|
|
664
|
+
for slice_index in range(5):
|
|
665
|
+
with (destination_path / _make_tiff_name("", slice_index)).open("rb") as f:
|
|
666
|
+
test_image = np.array(Image.open(f)).T
|
|
667
|
+
np.testing.assert_array_equal(
|
|
668
|
+
test_image, data[0, 0, 2:10, 4:14, 1 + slice_index]
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
|
|
632
672
|
def test_export_tiff_stack_tile_size(tmp_upath: UPath) -> None:
|
|
633
673
|
"""Tests the tile size support of exporting a tiff stack."""
|
|
634
674
|
|
|
@@ -16,6 +16,7 @@ class AnnotationInfo:
|
|
|
16
16
|
state: AnnotationState
|
|
17
17
|
duration_in_seconds: float | None
|
|
18
18
|
modified: int | None
|
|
19
|
+
created: int | None = None
|
|
19
20
|
|
|
20
21
|
def download_annotation(self) -> Annotation:
|
|
21
22
|
"""Downloads and returns the annotation that is described by this AnnotationInfo object"""
|
|
@@ -35,6 +36,7 @@ class AnnotationInfo:
|
|
|
35
36
|
if api_annotation.tracing_time is not None
|
|
36
37
|
else None,
|
|
37
38
|
modified=api_annotation.modified,
|
|
39
|
+
created=api_annotation.created,
|
|
38
40
|
)
|
|
39
41
|
|
|
40
42
|
@classmethod
|
|
@@ -109,7 +109,7 @@ def export_tiff_slice_batch(
|
|
|
109
109
|
mapping_array = open_zarr3_array(mapping_path, context=ts_context)
|
|
110
110
|
|
|
111
111
|
if tiling_size is None:
|
|
112
|
-
tiff_data = view.
|
|
112
|
+
tiff_data = view.read_cxyz()
|
|
113
113
|
if mapping_array is not None:
|
|
114
114
|
tiff_data = _apply_mapping(tiff_data, mapping_array)
|
|
115
115
|
else:
|
|
@@ -118,7 +118,7 @@ def export_tiff_slice_batch(
|
|
|
118
118
|
tiling_size[1] * ceil(tiff_bbox.size.y / tiling_size[1]),
|
|
119
119
|
tiff_bbox.size.z,
|
|
120
120
|
)
|
|
121
|
-
tiff_data = view.
|
|
121
|
+
tiff_data = view.read_cxyz()
|
|
122
122
|
if mapping_array is not None:
|
|
123
123
|
tiff_data = _apply_mapping(tiff_data, mapping_array)
|
|
124
124
|
padded_tiff_data = np.zeros(
|
|
@@ -451,10 +451,11 @@ class ApiAnnotation:
|
|
|
451
451
|
name: str
|
|
452
452
|
description: str
|
|
453
453
|
state: str
|
|
454
|
-
modified: int
|
|
455
454
|
annotation_layers: list[ApiAnnotationLayer] | None
|
|
455
|
+
modified: int
|
|
456
456
|
data_store: ApiDataStore | None = None
|
|
457
457
|
tracing_time: int | None = None # millis
|
|
458
|
+
created: int | None = None
|
|
458
459
|
|
|
459
460
|
|
|
460
461
|
@attr.s(auto_attribs=True)
|
|
@@ -64,7 +64,7 @@ def _resolve_export_bbox(
|
|
|
64
64
|
The layer's bounding box can't be used for that: for remote layers it may
|
|
65
65
|
lack the channel axis that the streamed array has (or vice versa). The
|
|
66
66
|
request is clipped to the layer per axis name, axes the array doesn't
|
|
67
|
-
have are ignored and the channel axis always spans all channels.
|
|
67
|
+
have are ignored and the channel axis always spans all channels of the layer.
|
|
68
68
|
"""
|
|
69
69
|
layer_bbox = layer.normalized_bounding_box
|
|
70
70
|
if bounding_box is None:
|
|
@@ -73,7 +73,14 @@ def _resolve_export_bbox(
|
|
|
73
73
|
topleft, size = [], []
|
|
74
74
|
for axis in array_axes:
|
|
75
75
|
if axis == C_AXIS:
|
|
76
|
+
mag_bbox = mag_view.normalized_bounding_box
|
|
77
|
+
array_start, array_end = mag_view.info.bounding_box.get_bounds(C_AXIS)
|
|
76
78
|
start, end = 0, layer.num_channels
|
|
79
|
+
if C_AXIS in mag_bbox.axes:
|
|
80
|
+
mag_start, mag_end = mag_bbox.get_bounds(C_AXIS)
|
|
81
|
+
# Streamed arrays might only contain the layer's channels.
|
|
82
|
+
if array_start <= mag_start and mag_end <= array_end:
|
|
83
|
+
start, end = mag_start, mag_end
|
|
77
84
|
elif axis in layer_bbox.axes:
|
|
78
85
|
start, end = layer_bbox.get_bounds(axis)
|
|
79
86
|
if axis in bounding_box.axes:
|
|
@@ -868,6 +868,12 @@ class Layer(AbstractLayer):
|
|
|
868
868
|
mag=mag,
|
|
869
869
|
path=dump_path(foreign_mag_view.path, self.dataset.resolved_path),
|
|
870
870
|
cube_length=foreign_mag_view._properties.cube_length,
|
|
871
|
+
# Not set for remote mags whose arrays are served by the datastore.
|
|
872
|
+
axis_order=(
|
|
873
|
+
foreign_mag_view._properties.axis_order
|
|
874
|
+
if foreign_mag_view._get_dimension_names() is not None
|
|
875
|
+
else None
|
|
876
|
+
),
|
|
871
877
|
)
|
|
872
878
|
)
|
|
873
879
|
self._save_layer_properties()
|
|
@@ -436,12 +436,35 @@ class WKWArray(BaseArray):
|
|
|
436
436
|
class TensorStoreArray(BaseArray):
|
|
437
437
|
_cached_array: tensorstore.TensorStore | None
|
|
438
438
|
_tensorstore_data_format: str
|
|
439
|
+
_dimension_names: tuple[str, ...] | None
|
|
439
440
|
|
|
440
441
|
def __init__(
|
|
441
|
-
self,
|
|
442
|
+
self,
|
|
443
|
+
path: UPath,
|
|
444
|
+
_cached_array: tensorstore.TensorStore | None = None,
|
|
445
|
+
dimension_names: tuple[str, ...] | None = None,
|
|
442
446
|
):
|
|
447
|
+
"""`dimension_names` (e.g. from the `axisOrder` of the layer properties)
|
|
448
|
+
take precedence over the dimension names in the array's metadata, if their
|
|
449
|
+
number matches the array's rank."""
|
|
443
450
|
super().__init__(path)
|
|
444
|
-
self.
|
|
451
|
+
self._dimension_names = dimension_names
|
|
452
|
+
self._cached_array = (
|
|
453
|
+
None
|
|
454
|
+
if _cached_array is None
|
|
455
|
+
else self._apply_dimension_names(_cached_array)
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
def _apply_dimension_names(
|
|
459
|
+
self, array: tensorstore.TensorStore
|
|
460
|
+
) -> tensorstore.TensorStore:
|
|
461
|
+
if (
|
|
462
|
+
self._dimension_names is not None
|
|
463
|
+
and len(self._dimension_names) == array.rank
|
|
464
|
+
and array.domain.labels != self._dimension_names
|
|
465
|
+
):
|
|
466
|
+
return array[tensorstore.d[:].label[self._dimension_names]]
|
|
467
|
+
return array
|
|
445
468
|
|
|
446
469
|
@staticmethod
|
|
447
470
|
def _get_array_dimensions(
|
|
@@ -560,7 +583,7 @@ class TensorStoreArray(BaseArray):
|
|
|
560
583
|
}
|
|
561
584
|
|
|
562
585
|
@classmethod
|
|
563
|
-
def _open(cls, path: UPath) -> Self:
|
|
586
|
+
def _open(cls, path: UPath, dimension_names: tuple[str, ...] | None = None) -> Self:
|
|
564
587
|
try:
|
|
565
588
|
_array = call_with_retries(
|
|
566
589
|
lambda: tensorstore.open(
|
|
@@ -572,7 +595,7 @@ class TensorStoreArray(BaseArray):
|
|
|
572
595
|
).result(),
|
|
573
596
|
description="Opening tensorstore array",
|
|
574
597
|
) # check that everything exists
|
|
575
|
-
return cls(path, _array)
|
|
598
|
+
return cls(path, _array, dimension_names=dimension_names)
|
|
576
599
|
except Exception as exc:
|
|
577
600
|
raise ArrayException(f"Could not open array at {path}.") from exc
|
|
578
601
|
|
|
@@ -620,16 +643,18 @@ class TensorStoreArray(BaseArray):
|
|
|
620
643
|
|
|
621
644
|
if new_domain != array.domain:
|
|
622
645
|
# Check on-disk for changes to shape
|
|
623
|
-
current_array =
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
646
|
+
current_array = self._apply_dimension_names(
|
|
647
|
+
call_with_retries(
|
|
648
|
+
lambda: tensorstore.open(
|
|
649
|
+
{
|
|
650
|
+
"driver": self._tensorstore_data_format,
|
|
651
|
+
"kvstore": _make_kvstore(self._path),
|
|
652
|
+
},
|
|
653
|
+
context=TS_CONTEXT,
|
|
654
|
+
recheck_cached="open",
|
|
655
|
+
).result(),
|
|
656
|
+
description="Opening tensorstore array for resizing",
|
|
657
|
+
)
|
|
633
658
|
)
|
|
634
659
|
if array.domain != current_array.domain:
|
|
635
660
|
raise RuntimeError(
|
|
@@ -739,6 +764,7 @@ class TensorStoreArray(BaseArray):
|
|
|
739
764
|
).result(),
|
|
740
765
|
description="Creating tensorstore array",
|
|
741
766
|
)
|
|
767
|
+
self._cached_array = self._apply_dimension_names(self._cached_array)
|
|
742
768
|
except Exception as e:
|
|
743
769
|
raise ArrayException(
|
|
744
770
|
f"Exception while opening array for {_make_kvstore(self._path)}"
|
|
@@ -767,8 +793,10 @@ class Zarr3Array(TensorStoreArray):
|
|
|
767
793
|
_tensorstore_data_format = "zarr3"
|
|
768
794
|
|
|
769
795
|
@classmethod
|
|
770
|
-
def open(
|
|
771
|
-
|
|
796
|
+
def open(
|
|
797
|
+
cls, path: UPath, dimension_names: tuple[str, ...] | None = None
|
|
798
|
+
) -> "Zarr3Array":
|
|
799
|
+
return cls._open(path, dimension_names)
|
|
772
800
|
|
|
773
801
|
@property
|
|
774
802
|
def info(self) -> Zarr3ArrayInfo:
|
|
@@ -887,8 +915,10 @@ class Zarr2Array(TensorStoreArray):
|
|
|
887
915
|
_tensorstore_data_format = "zarr"
|
|
888
916
|
|
|
889
917
|
@classmethod
|
|
890
|
-
def open(
|
|
891
|
-
|
|
918
|
+
def open(
|
|
919
|
+
cls, path: UPath, dimension_names: tuple[str, ...] | None = None
|
|
920
|
+
) -> "Zarr2Array":
|
|
921
|
+
return cls._open(path, dimension_names)
|
|
892
922
|
|
|
893
923
|
@property
|
|
894
924
|
def info(self) -> ArrayInfo:
|
|
@@ -17,7 +17,7 @@ from webknossos.utils import (
|
|
|
17
17
|
warn_deprecated,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
-
from ....dataset_properties import DataFormat, MagViewProperties
|
|
20
|
+
from ....dataset_properties import DataFormat, LayerProperties, MagViewProperties
|
|
21
21
|
from ....geometry import (
|
|
22
22
|
Mag,
|
|
23
23
|
NDBoundingBox,
|
|
@@ -202,6 +202,7 @@ class MagView(View, Generic[LayerTypeT]):
|
|
|
202
202
|
read_only=read_only,
|
|
203
203
|
)
|
|
204
204
|
self._layer = layer
|
|
205
|
+
self._cached_dimension_names: tuple[str, ...] | None = None
|
|
205
206
|
|
|
206
207
|
def _ensure_writable(self) -> None:
|
|
207
208
|
if self._read_only:
|
|
@@ -241,6 +242,29 @@ class MagView(View, Generic[LayerTypeT]):
|
|
|
241
242
|
"""
|
|
242
243
|
return self.layer.num_channels
|
|
243
244
|
|
|
245
|
+
def _get_dimension_names(self) -> tuple[str, ...] | None:
|
|
246
|
+
# An explicit `axisOrder` takes precedence over the array's metadata.
|
|
247
|
+
# The bounding box's axes are sorted by their index in the array.
|
|
248
|
+
if self._cached_dimension_names is None:
|
|
249
|
+
mag_properties = self._find_properties()
|
|
250
|
+
if mag_properties is None or mag_properties.axis_order is None:
|
|
251
|
+
return None
|
|
252
|
+
self._cached_dimension_names = self.normalized_bounding_box.axes
|
|
253
|
+
return self._cached_dimension_names
|
|
254
|
+
|
|
255
|
+
def _get_layer_properties(self) -> LayerProperties:
|
|
256
|
+
return self.layer._properties
|
|
257
|
+
|
|
258
|
+
def _find_properties(self) -> MagViewProperties | None:
|
|
259
|
+
return next(
|
|
260
|
+
(
|
|
261
|
+
mag_property
|
|
262
|
+
for mag_property in self._get_layer_properties().mags
|
|
263
|
+
if mag_property.mag == self._mag
|
|
264
|
+
),
|
|
265
|
+
None,
|
|
266
|
+
)
|
|
267
|
+
|
|
244
268
|
# Own methods:
|
|
245
269
|
|
|
246
270
|
@property
|
|
@@ -395,6 +419,7 @@ class MagView(View, Generic[LayerTypeT]):
|
|
|
395
419
|
rel_mag1_bbox=relative_bounding_box,
|
|
396
420
|
current_mag_size=data_shape,
|
|
397
421
|
)
|
|
422
|
+
self._check_write_shape(data, mag1_bbox)
|
|
398
423
|
|
|
399
424
|
# Only update the layer's bbox if we are actually larger
|
|
400
425
|
# than the mag-aligned, rounded up bbox (self.bounding_box):
|
|
@@ -872,11 +897,10 @@ class MagView(View, Generic[LayerTypeT]):
|
|
|
872
897
|
MagViewProperties: Properties object for this magnification level.
|
|
873
898
|
|
|
874
899
|
"""
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
for
|
|
878
|
-
|
|
879
|
-
)
|
|
900
|
+
mag_properties = self._find_properties()
|
|
901
|
+
if mag_properties is None:
|
|
902
|
+
raise KeyError(f"No properties found for mag {self._mag}.")
|
|
903
|
+
return mag_properties
|
|
880
904
|
|
|
881
905
|
def __repr__(self) -> str:
|
|
882
906
|
return f"MagView(name={repr(self.name)}, bounding_box={self.bounding_box})"
|
|
@@ -93,6 +93,15 @@ class RemoteMagView(MagView["RemoteLayer"]):
|
|
|
93
93
|
def num_channels(self) -> int:
|
|
94
94
|
return self.normalized_bounding_box.size.get("c", 1)
|
|
95
95
|
|
|
96
|
+
def _get_layer_properties(self) -> "LayerProperties":
|
|
97
|
+
return self._layer_properties
|
|
98
|
+
|
|
99
|
+
def _get_dimension_names(self) -> tuple[str, ...] | None:
|
|
100
|
+
# Arrays served by the datastore have their own axis order.
|
|
101
|
+
if self._access_mode != RemoteAccessMode.DIRECT_PATH:
|
|
102
|
+
return None
|
|
103
|
+
return super()._get_dimension_names()
|
|
104
|
+
|
|
96
105
|
@property
|
|
97
106
|
def paths_by_access_mode(self) -> Mapping[RemoteAccessMode, UPath]:
|
|
98
107
|
"""All paths at which this mag's data can be reached, keyed by access mode.
|
|
@@ -28,7 +28,7 @@ from ....utils import (
|
|
|
28
28
|
wait_and_ensure_success,
|
|
29
29
|
warn_deprecated,
|
|
30
30
|
)
|
|
31
|
-
from ._array import ArrayInfo, BaseArray
|
|
31
|
+
from ._array import ArrayInfo, BaseArray, Zarr2Array, Zarr3Array
|
|
32
32
|
|
|
33
33
|
if TYPE_CHECKING:
|
|
34
34
|
from ..._utils.buffered_slice_reader import BufferedSliceReader
|
|
@@ -81,6 +81,7 @@ class View:
|
|
|
81
81
|
data_format: DataFormat,
|
|
82
82
|
read_only: bool = False,
|
|
83
83
|
cached_array: BaseArray | None = None,
|
|
84
|
+
dimension_names: tuple[str, ...] | None = None,
|
|
84
85
|
):
|
|
85
86
|
"""Initialize a View instance for accessing and manipulating dataset regions.
|
|
86
87
|
|
|
@@ -113,6 +114,7 @@ class View:
|
|
|
113
114
|
self._normalized_bounding_box = bounding_box
|
|
114
115
|
self._read_only = read_only
|
|
115
116
|
self._cached_array = cached_array
|
|
117
|
+
self._dimension_names = dimension_names
|
|
116
118
|
self._mag = mag
|
|
117
119
|
|
|
118
120
|
@property
|
|
@@ -225,6 +227,22 @@ class View:
|
|
|
225
227
|
"""
|
|
226
228
|
return self._read_only
|
|
227
229
|
|
|
230
|
+
def _normalize_axes_with_channel_start(
|
|
231
|
+
self, bbox: NDBoundingBox
|
|
232
|
+
) -> NormalizedBoundingBox:
|
|
233
|
+
normalized_bbox = bbox.normalize_axes(self.num_channels)
|
|
234
|
+
if (
|
|
235
|
+
C_AXIS not in bbox.axes
|
|
236
|
+
and C_AXIS in normalized_bbox.axes
|
|
237
|
+
and C_AXIS in self.normalized_bounding_box.axes
|
|
238
|
+
):
|
|
239
|
+
# Start at the view's first channel, which is non-zero for
|
|
240
|
+
# layers with a `channelIndex`.
|
|
241
|
+
normalized_bbox = normalized_bbox.with_bounds(
|
|
242
|
+
C_AXIS, self.normalized_bounding_box.topleft.c, self.num_channels
|
|
243
|
+
)
|
|
244
|
+
return normalized_bbox
|
|
245
|
+
|
|
228
246
|
def _get_mag1_bbox(
|
|
229
247
|
self,
|
|
230
248
|
*,
|
|
@@ -255,10 +273,10 @@ class View:
|
|
|
255
273
|
)
|
|
256
274
|
|
|
257
275
|
if abs_mag1_bbox is not None:
|
|
258
|
-
return
|
|
276
|
+
return self._normalize_axes_with_channel_start(abs_mag1_bbox)
|
|
259
277
|
|
|
260
278
|
if rel_mag1_bbox is not None:
|
|
261
|
-
return
|
|
279
|
+
return self._normalize_axes_with_channel_start(rel_mag1_bbox).offset(
|
|
262
280
|
self.bounding_box.topleft
|
|
263
281
|
)
|
|
264
282
|
|
|
@@ -335,6 +353,7 @@ class View:
|
|
|
335
353
|
- Number of channels doesn't match the dataset
|
|
336
354
|
- Write region is outside the view's bounding box
|
|
337
355
|
- Multiple positioning parameters are provided
|
|
356
|
+
ValueError: If the data shape doesn't match the size of the target region.
|
|
338
357
|
|
|
339
358
|
Examples:
|
|
340
359
|
```python
|
|
@@ -434,6 +453,8 @@ class View:
|
|
|
434
453
|
|
|
435
454
|
current_mag_bbox = mag1_bbox.in_mag(self._mag)
|
|
436
455
|
|
|
456
|
+
self._check_write_shape(data, mag1_bbox)
|
|
457
|
+
|
|
437
458
|
if not allow_unaligned:
|
|
438
459
|
if self._data_format == DataFormat.WKW and not self._is_compressed():
|
|
439
460
|
try:
|
|
@@ -456,6 +477,28 @@ class View:
|
|
|
456
477
|
else:
|
|
457
478
|
self._array.write(current_mag_bbox, data)
|
|
458
479
|
|
|
480
|
+
def _check_write_shape(
|
|
481
|
+
self, data: np.ndarray, mag1_bbox: NormalizedBoundingBox
|
|
482
|
+
) -> None:
|
|
483
|
+
current_mag_bbox = mag1_bbox.in_mag(self._mag)
|
|
484
|
+
c_index = current_mag_bbox.index.c if C_AXIS in current_mag_bbox.axes else None
|
|
485
|
+
expected_shape = tuple(current_mag_bbox.size)
|
|
486
|
+
data_shape = tuple(data.shape)
|
|
487
|
+
if c_index is not None and len(data_shape) + 1 == len(expected_shape):
|
|
488
|
+
# data without channel axis
|
|
489
|
+
data_shape = data_shape[:c_index] + (1,) + data_shape[c_index:]
|
|
490
|
+
# the number of channels is validated separately
|
|
491
|
+
if len(data_shape) != len(expected_shape) or any(
|
|
492
|
+
actual != expected
|
|
493
|
+
for i, (actual, expected) in enumerate(zip(data_shape, expected_shape))
|
|
494
|
+
if i != c_index
|
|
495
|
+
):
|
|
496
|
+
raise ValueError(
|
|
497
|
+
f"The shape of the passed data {data.shape} does not match the size "
|
|
498
|
+
f"of the bounding box to write {expected_shape} "
|
|
499
|
+
f"(axes {current_mag_bbox.axes}, in {self._mag})."
|
|
500
|
+
)
|
|
501
|
+
|
|
459
502
|
def _resolve_cxyz_write(
|
|
460
503
|
self,
|
|
461
504
|
data: np.ndarray,
|
|
@@ -1094,6 +1137,7 @@ class View:
|
|
|
1094
1137
|
data_format=self._data_format,
|
|
1095
1138
|
read_only=read_only,
|
|
1096
1139
|
cached_array=self._cached_array,
|
|
1140
|
+
dimension_names=self._get_dimension_names(),
|
|
1097
1141
|
)
|
|
1098
1142
|
|
|
1099
1143
|
def get_buffered_slice_writer(
|
|
@@ -1669,10 +1713,20 @@ class View:
|
|
|
1669
1713
|
def _get_file_dimensions_mag1(self) -> Vec3Int:
|
|
1670
1714
|
return Vec3Int(self._get_file_dimensions() * self.mag.to_vec3_int())
|
|
1671
1715
|
|
|
1716
|
+
def _get_dimension_names(self) -> tuple[str, ...] | None:
|
|
1717
|
+
return self._dimension_names
|
|
1718
|
+
|
|
1672
1719
|
@property
|
|
1673
1720
|
def _array(self) -> BaseArray:
|
|
1674
1721
|
if self._cached_array is None:
|
|
1675
|
-
|
|
1722
|
+
array_class = BaseArray.get_class(self._data_format)
|
|
1723
|
+
dimension_names = self._get_dimension_names()
|
|
1724
|
+
if dimension_names is not None and issubclass(
|
|
1725
|
+
array_class, (Zarr3Array, Zarr2Array)
|
|
1726
|
+
):
|
|
1727
|
+
self._cached_array = array_class.open(self._path, dimension_names)
|
|
1728
|
+
else:
|
|
1729
|
+
self._cached_array = array_class.open(self._path)
|
|
1676
1730
|
return self._cached_array
|
|
1677
1731
|
|
|
1678
1732
|
@_array.deleter
|
|
@@ -79,6 +79,11 @@ class MagViewProperties:
|
|
|
79
79
|
Could be None for older datasource-proterties.json files.
|
|
80
80
|
"""
|
|
81
81
|
cube_length: int | None = None
|
|
82
|
+
axis_order: dict[str, int] | None = attr.field(default=None, eq=False)
|
|
83
|
+
"""
|
|
84
|
+
Index of each axis in the array, as read from the datasource-properties.json.
|
|
85
|
+
None if not set there. On save, it is derived from the layer's bounding box.
|
|
86
|
+
"""
|
|
82
87
|
|
|
83
88
|
|
|
84
89
|
@attr.define
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '4.2.3'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webknossos
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.3
|
|
4
4
|
Summary: Python API for working with WEBKNOSSOS datasets, annotations, and for WEBKNOSSOS server interaction.
|
|
5
5
|
Author-email: scalable minds <hello@scalableminds.com>
|
|
6
6
|
License: AGPL-3.0
|
|
@@ -37,7 +37,7 @@ Requires-Dist: boltons>=21.0.0
|
|
|
37
37
|
Requires-Dist: cattrs>=22.0.0
|
|
38
38
|
Requires-Dist: certifi>=2023
|
|
39
39
|
Requires-Dist: click<8.2.0
|
|
40
|
-
Requires-Dist: cluster-tools==4.2.
|
|
40
|
+
Requires-Dist: cluster-tools==4.2.3
|
|
41
41
|
Requires-Dist: httpx~=0.27.0
|
|
42
42
|
Requires-Dist: imageio>=2.37.0
|
|
43
43
|
Requires-Dist: lz4>=4.0.0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '4.2.2'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|