From ad5cec48420bce646f4563554fb279d17111c645 Mon Sep 17 00:00:00 2001 From: Justin Eskesen Date: Tue, 23 Jul 2024 11:11:54 -0700 Subject: [PATCH] Added some missing functionality to the C++ and Python APIs, like adding stop() and calling reserve_image_shape() before starting. --- api/cpp/include/acquire-zarr/acquire-zarr.hh | 24 +++++++++++++++++++- api/cpp/src/acquire-zarr-writer-impl.cpp | 23 +++++++++++++++++-- api/cpp/src/acquire-zarr-writer.cpp | 5 ++++ api/python/acquire-zarr-py-api.cpp | 5 ++-- api/python/tests/test_zarr.py | 21 +++++++++-------- 5 files changed, 63 insertions(+), 15 deletions(-) diff --git a/api/cpp/include/acquire-zarr/acquire-zarr.hh b/api/cpp/include/acquire-zarr/acquire-zarr.hh index 95df5ec0..fbbbaff6 100644 --- a/api/cpp/include/acquire-zarr/acquire-zarr.hh +++ b/api/cpp/include/acquire-zarr/acquire-zarr.hh @@ -13,14 +13,36 @@ enum class AcquireZarrCompressionCodec } ; - class AcquireZarrWriter { public: AcquireZarrWriter() { create_impl();} ~AcquireZarrWriter() = default; + /** + * @brief Start the Zarr writer. + * + * This method must be called after all configuration has been set. + * This validates configuration before opening files so they can be appended. + * + */ void start(); + + /** + * @brief Stop the Zarr writer. + * + * This method must be called after all data has been appended. + * + */ + void stop(); + + /** + * @brief Append image data to the Zarr file. + * + * @param image_data pointer to the image data + * @param image_size size of the image data in bytes + * + */ void append(uint8_t* image_data, size_t image_size); diff --git a/api/cpp/src/acquire-zarr-writer-impl.cpp b/api/cpp/src/acquire-zarr-writer-impl.cpp index 732e12f2..fd98c6a2 100644 --- a/api/cpp/src/acquire-zarr-writer-impl.cpp +++ b/api/cpp/src/acquire-zarr-writer-impl.cpp @@ -20,7 +20,6 @@ std::string get_from_acquire_string(const String& src) AcquireZarrWriter::Impl::Impl() { - //zarr_sink_ = std::make_shared(); memset(&storage_properties_, 0, sizeof(struct StorageProperties)); memset(&shape_, 0, sizeof(struct ImageShape)); @@ -34,14 +33,34 @@ void AcquireZarrWriter::Impl::start() create_zarr_sink(); zarr_sink_->set(&storage_properties_); + + assert(storage_properties_.acquisition_dimensions.size > 0); + shape_.type = SampleType_u8; + + shape_.dims.channels = storage_properties_.acquisition_dimensions.size - 1 ; // one less than the size, since the last dimension is append + + shape_.dims.width = storage_properties_.acquisition_dimensions.data[0].array_size_px; + shape_.dims.height = storage_properties_.acquisition_dimensions.data[1].array_size_px; + shape_.dims.planes = + storage_properties_.acquisition_dimensions.data[2].array_size_px > 1 ? + storage_properties_.acquisition_dimensions.data[2].array_size_px : + 1; + + shape_.dims.channels = + storage_properties_.acquisition_dimensions.data[3].array_size_px > 1 ? + storage_properties_.acquisition_dimensions.data[3].array_size_px : + 1; + + zarr_sink_->reserve_image_shape(&shape_); zarr_sink_->start(); } + void AcquireZarrWriter::Impl::append(const uint8_t* image_data, size_t image_size) { // todo: check image size against expected size? - zarr_sink_->append_frame(image_data, image_size, shape_); + auto written = zarr_sink_->append_frame(image_data, image_size, shape_); } void AcquireZarrWriter::Impl::create_zarr_sink() diff --git a/api/cpp/src/acquire-zarr-writer.cpp b/api/cpp/src/acquire-zarr-writer.cpp index 507b696e..ddb7a6d6 100644 --- a/api/cpp/src/acquire-zarr-writer.cpp +++ b/api/cpp/src/acquire-zarr-writer.cpp @@ -12,6 +12,11 @@ void AcquireZarrWriter::start() impl_->start(); } +void AcquireZarrWriter::stop() +{ + impl_->zarr_sink_->stop(); +} + void AcquireZarrWriter::append(uint8_t* image_data, size_t image_size) { impl_->append(image_data, image_size); diff --git a/api/python/acquire-zarr-py-api.cpp b/api/python/acquire-zarr-py-api.cpp index 7f369539..bfd45d1d 100644 --- a/api/python/acquire-zarr-py-api.cpp +++ b/api/python/acquire-zarr-py-api.cpp @@ -56,6 +56,7 @@ PYBIND11_MODULE(acquire_zarr, m) { .def(py::init<>()) .def("append", &PyAcquireZarrWriter::append) .def("start", &PyAcquireZarrWriter::start) + .def("stop", &PyAcquireZarrWriter::stop) .def_property("use_v3", &PyAcquireZarrWriter::get_use_v3, &PyAcquireZarrWriter::set_use_v3) .def_property("shape", &PyAcquireZarrWriter::get_shape, &PyAcquireZarrWriter::set_shape) .def_property("uri", &PyAcquireZarrWriter::get_uri, &PyAcquireZarrWriter::set_uri) @@ -65,8 +66,8 @@ PYBIND11_MODULE(acquire_zarr, m) { .def_property("first_frame_id", &PyAcquireZarrWriter::get_first_frame_id, &PyAcquireZarrWriter::set_first_frame_id) .def_property("dimensions", &PyAcquireZarrWriter::get_dimensions, &PyAcquireZarrWriter::set_dimensions) .def_property("dimension_sizes", &PyAcquireZarrWriter::get_dimension_sizes, &PyAcquireZarrWriter::set_dimension_sizes) - .def_property("dimension_pixels_per_chunk", &PyAcquireZarrWriter::get_chunk_sizes, &PyAcquireZarrWriter::get_chunk_sizes) - .def_property("dimension_chunks_per_shard", &PyAcquireZarrWriter::get_shard_sizes, &PyAcquireZarrWriter::get_shard_sizes) + .def_property("chunk_sizes", &PyAcquireZarrWriter::get_chunk_sizes, &PyAcquireZarrWriter::set_chunk_sizes) + .def_property("shard_sizes", &PyAcquireZarrWriter::get_shard_sizes, &PyAcquireZarrWriter::set_shard_sizes) .def_property("enable_multiscale", &PyAcquireZarrWriter::get_enable_multiscale, &PyAcquireZarrWriter::set_enable_multiscale) .def_property("compression_codec", &PyAcquireZarrWriter::get_compression_codec, &PyAcquireZarrWriter::set_compression_codec) .def_property("compression_level", &PyAcquireZarrWriter::get_compression_level, &PyAcquireZarrWriter::set_compression_level) diff --git a/api/python/tests/test_zarr.py b/api/python/tests/test_zarr.py index 4f1eb188..4138a236 100644 --- a/api/python/tests/test_zarr.py +++ b/api/python/tests/test_zarr.py @@ -5,7 +5,7 @@ import acquire_zarr from time import sleep -data = np.arange(64, 64, dtype=np.uint8) +data = np.zeros((64, 64), dtype=np.uint8) def check_zarr(v3: bool, uri: str) -> None: zarr = acquire_zarr.AcquireZarrWriter() @@ -14,33 +14,34 @@ def check_zarr(v3: bool, uri: str) -> None: zarr.uri = uri zarr.dimensions = ["x", "y", "t"] - assert zarr.dimensions == ["x", "y", "t"] zarr.dimension_sizes = [64, 64, 0] - assert zarr.dimension_sizes == [64, 64, 0] - zarr.chunk_sizes = [64, 64, 1] zarr.chunk_sizes[-1] = 1 - assert zarr.chunk_sizes == [64, 64, 1] zarr.compression_codec = acquire_zarr.CompressionCodec.COMPRESSION_NONE - assert zarr.compression_codec == acquire_zarr.CompressionCodec.COMPRESSION_NONE #zarr.compression_codec = acquire_zarr.CompressionCodec.COMPRESSION_BLOSC_ZSTD #assert zarr.compression_codec == acquire_zarr.CompressionCodec.COMPRESSION_BLOSC_ZSTD zarr.compression_level = 5 - assert zarr.compression_level == 5 zarr.compression_shuffle = 0 + + # check that getters and setters work + assert zarr.dimensions == ["x", "y", "t"] + assert zarr.dimension_sizes == [64, 64, 0] + assert zarr.chunk_sizes == [64, 64, 1] + assert zarr.compression_codec == acquire_zarr.CompressionCodec.COMPRESSION_NONE + assert zarr.compression_level == 5 assert zarr.compression_shuffle == 0 - sleep(1) zarr.start() + for i in range(3): zarr.append(data) - sleep(0.5) - + zarr.stop() + def test_zarr_v2() -> None: check_zarr(False, "test_v2.zarr")