diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index b130ea3..1f79d15 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -54,17 +54,16 @@ jobs: bash ci-utils/install_prereq_linux.sh && mkdir -p /tmp/bfiocpp_bld && cp -r local_install /tmp/bfiocpp_bld - CIBW_BEFORE_ALL_LINUX: yum -y install wget && - wget https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 && - tar -xjf nasm-2.15.05.tar.bz2 && - cd nasm-2.15.05 && - ./configure && - make && - make install && - cd .. && - bash ci-utils/install_prereq_linux.sh && - mkdir -p /tmp/bfiocpp_bld && - cp -r local_install /tmp/bfiocpp_bld + CIBW_BEFORE_ALL_LINUX: curl -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 -o nasm-2.15.05.tar.bz2 && + tar -xjf nasm-2.15.05.tar.bz2 && + cd nasm-2.15.05 && + ./configure && + make && + make install && + cd .. && + bash ci-utils/install_prereq_linux.sh && + mkdir -p /tmp/bfiocpp_bld && + cp -r local_install /tmp/bfiocpp_bld CIBW_BEFORE_ALL_WINDOWS: ci-utils\install_prereq_win.bat && xcopy /E /I /y local_install C:\TEMP\bfiocpp_bld\local_install CIBW_ENVIRONMENT_MACOS: REPAIR_LIBRARY_PATH="/tmp/bfiocpp_bld/local_install/lib:/tmp/bfiocpp_bld/local_install/lib64" ON_GITHUB="TRUE" BFIOCPP_DEP_DIR="/tmp/bfiocpp_bld/local_install" @@ -73,8 +72,11 @@ jobs: CIBW_ENVIRONMENT_WINDOWS: PATH="$TEMP\\bfiocpp\\bin;$PATH" ON_GITHUB="TRUE" BFIOCPP_DEP_DIR="C:\\TEMP\\bfiocpp_bld\\local_install" CMAKE_ARGS="-DCMAKE_GENERATOR=Ninja" CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -w {dest_dir} {wheel}" CIBW_ARCHS: ${{ matrix.cibw_archs }} - CIBW_BEFORE_TEST_LINUX: yum -y install maven java - CIBW_TEST_REQUIRES: bfio requests numpy ome_zarr + CIBW_BEFORE_TEST_LINUX: sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo && + sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo && + sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo && + yum -y install maven java + CIBW_TEST_REQUIRES: bfio requests numpy==1.24.0 ome_zarr CIBW_TEST_COMMAND: python -W default -m unittest discover -s {project}/tests -v - name: Install Dependencies diff --git a/.github/workflows/wheel_build.yml b/.github/workflows/wheel_build.yml index 111b4cd..06dec61 100644 --- a/.github/workflows/wheel_build.yml +++ b/.github/workflows/wheel_build.yml @@ -51,9 +51,8 @@ jobs: CIBW_BEFORE_ALL_MACOS: brew install nasm && bash ci-utils/install_prereq_linux.sh && mkdir -p /tmp/bfiocpp_bld && - cp -r local_install /tmp/bfiocpp_bld - CIBW_BEFORE_ALL_LINUX: yum -y install wget && - wget https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 && + cp -r local_install /tmp/bfiocpp_bld + CIBW_BEFORE_ALL_LINUX: curl -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 -o nasm-2.15.05.tar.bz2 && tar -xjf nasm-2.15.05.tar.bz2 && cd nasm-2.15.05 && ./configure && @@ -71,8 +70,11 @@ jobs: CIBW_ENVIRONMENT_WINDOWS: PATH="$TEMP\\bfiocpp\\bin;$PATH" ON_GITHUB="TRUE" BFIOCPP_DEP_DIR="C:\\TEMP\\bfiocpp_bld\\local_install" CMAKE_ARGS="-DCMAKE_GENERATOR=Ninja" CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -w {dest_dir} {wheel}" CIBW_ARCHS: ${{ matrix.cibw_archs }} - CIBW_BEFORE_TEST_LINUX: yum -y install maven java - CIBW_TEST_REQUIRES: bfio requests numpy ome_zarr + CIBW_BEFORE_TEST_LINUX: sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo && + sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo && + sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo && + yum -y install maven java + CIBW_TEST_REQUIRES: bfio requests numpy==1.24.0 ome_zarr CIBW_TEST_COMMAND: python -W default -m unittest discover -s {project}/tests -v - name: Upload Artifact diff --git a/src/cpp/interface/interface.cpp b/src/cpp/interface/interface.cpp index 5b5113c..ed7916f 100644 --- a/src/cpp/interface/interface.cpp +++ b/src/cpp/interface/interface.cpp @@ -4,7 +4,7 @@ #include #include #include "../reader/tsreader.h" -#include "../reader/sequence.h" +#include "../utilities/sequence.h" #include "../utilities/utilities.h" #include "../writer/tswriter.h" @@ -122,6 +122,6 @@ PYBIND11_MODULE(libbfiocpp, m) { // Writer class py::class_>(m, "TsWriterCPP") - .def(py::init&, const std::vector&, const std::string&>()) + .def(py::init&, const std::vector&, const std::string&, const std::string&>()) .def("write_image_data", &bfiocpp::TsWriterCPP::WriteImageData); } diff --git a/src/cpp/reader/tsreader.h b/src/cpp/reader/tsreader.h index 1029a33..4062856 100644 --- a/src/cpp/reader/tsreader.h +++ b/src/cpp/reader/tsreader.h @@ -9,7 +9,7 @@ #include #include #include "tensorstore/tensorstore.h" -#include "sequence.h" +#include "../utilities/sequence.h" using image_data = std::variant, std::vector, std::vector, @@ -58,6 +58,7 @@ class TsReaderCPP{ _num_tsteps; std::uint16_t _data_type_code; FileType _file_type; + std::optional_z_index, _c_index, _t_index; tensorstore::TensorStore source; diff --git a/src/cpp/reader/sequence.h b/src/cpp/utilities/sequence.h similarity index 100% rename from src/cpp/reader/sequence.h rename to src/cpp/utilities/sequence.h diff --git a/src/cpp/writer/tswriter.cpp b/src/cpp/writer/tswriter.cpp index ce3e234..844a751 100644 --- a/src/cpp/writer/tswriter.cpp +++ b/src/cpp/writer/tswriter.cpp @@ -2,6 +2,7 @@ #include "tensorstore/array.h" #include "tensorstore/open.h" +#include "tensorstore/index_space/dim_expression.h" #include "tswriter.h" #include "../utilities/utilities.h" @@ -10,126 +11,177 @@ namespace bfiocpp { TsWriterCPP::TsWriterCPP( - const std::string& fname, - const std::vector& image_shape, + const std::string& fname, + const std::vector& image_shape, const std::vector& chunk_shape, - const std::string& dtype_str - ): _filename(fname), - _image_shape(image_shape), - _chunk_shape(chunk_shape), + const std::string& dtype_str, + const std::string& dimension_order + ): _filename(fname), + _image_shape(image_shape), + _chunk_shape(chunk_shape), _dtype_code(GetDataTypeCode(dtype_str)) { - - TENSORSTORE_CHECK_OK_AND_ASSIGN(_source, tensorstore::Open( - GetZarrSpecToWrite(_filename, _image_shape, _chunk_shape, GetEncodedType(_dtype_code)), - tensorstore::OpenMode::create | - tensorstore::OpenMode::delete_existing, - tensorstore::ReadWriteMode::write).result()); -} + + TENSORSTORE_CHECK_OK_AND_ASSIGN(_source, tensorstore::Open( + GetZarrSpecToWrite(_filename, _image_shape, _chunk_shape, GetEncodedType(_dtype_code)), + tensorstore::OpenMode::create | + tensorstore::OpenMode::delete_existing, + tensorstore::ReadWriteMode::write).result() + ); -void TsWriterCPP::WriteImageData(py::array& py_image) { + auto position = dimension_order.find("X"); + if (position != std::string::npos) _x_index = position; - // use switch instead of template to avoid creating functions for each datatype - switch(_dtype_code) - { - case (1): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); + position = dimension_order.find("Y"); + if (position != std::string::npos) _y_index = position; - // Write data array to TensorStore - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); + position = dimension_order.find("C"); + if (position != std::string::npos) _c_index.emplace(position); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; - } + position = dimension_order.find("T"); + if (position != std::string::npos) _t_index.emplace(position); - break; - } - case (2): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); + position = dimension_order.find("Z"); + if (position != std::string::npos) _z_index.emplace(position); +} - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; - } - break; - } - case (4): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; - } - break; +void TsWriterCPP::WriteImageData( + py::array& py_image, + const Seq& rows, + const Seq& cols, + const std::optional& layers, + const std::optional& channels, + const std::optional& tsteps) { + + std::vector shape; + + auto output_transform = tensorstore::IdentityTransform(_source.domain()); + + if (_t_index.has_value() && tsteps.has_value()) { + output_transform = (std::move(output_transform) | tensorstore::Dims(_t_index.value()).ClosedInterval(tsteps.value().Start(), tsteps.value().Stop())).value(); + shape.emplace_back(tsteps.value().Stop() - tsteps.value().Start()+1); } - case (8): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; - } - break; + if (_c_index.has_value() && channels.has_value()) { + output_transform = (std::move(output_transform) | tensorstore::Dims(_c_index.value()).ClosedInterval(channels.value().Start(), channels.value().Stop())).value(); + shape.emplace_back(channels.value().Stop() - channels.value().Start()+1); } - case (16): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; - } - break; + if (_z_index.has_value() && layers.has_value()) { + output_transform = (std::move(output_transform) | tensorstore::Dims(_z_index.value()).ClosedInterval(layers.value().Start(), layers.value().Stop())).value(); + shape.emplace_back(layers.value().Stop() - layers.value().Start()+1); } - case (32): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; + output_transform = (std::move(output_transform) | tensorstore::Dims(_y_index).ClosedInterval(rows.Start(), rows.Stop()) | + tensorstore::Dims(_x_index).ClosedInterval(cols.Start(), cols.Stop())).value(); + + + + shape.emplace_back(rows.Stop() - rows.Start()+1); + shape.emplace_back(cols.Stop() - cols.Start()+1); + + // use switch instead of template to avoid creating functions for each datatype + switch(_dtype_code) + { + case (1): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + // Write data array to TensorStore + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + + break; } - break; - } - case (64): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; + case (2): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; } - break; - } - case (128): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - - // Write data array to TensorStore - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; + case (4): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; } - break; - } - case (256): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; + case (8): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; } - break; - } - case (512): { - auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), _image_shape, tensorstore::c_order); - - auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source).result(); - if (!write_result.ok()) { - std::cerr << "Error writing image: " << write_result.status() << std::endl; + case (16): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + case (32): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + case (64): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + case (128): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + // Write data array to TensorStore + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + case (256): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + case (512): { + auto data_array = tensorstore::Array(py_image.mutable_unchecked().data(0), shape, tensorstore::c_order); + + auto write_result = tensorstore::Write(tensorstore::UnownedToShared(data_array), _source | output_transform).result(); + if (!write_result.ok()) { + std::cerr << "Error writing image: " << write_result.status() << std::endl; + } + break; + } + default: { + // should not be reached + std::cerr << "Error writing image: unsupported data type" << std::endl; } - break; - } - default: { - // should not be reached - std::cerr << "Error writing image: unsupported data type" << std::endl; } - } - } -} +} + +} // end ns bfiocpp diff --git a/src/cpp/writer/tswriter.h b/src/cpp/writer/tswriter.h index c245ff2..92dbaa8 100644 --- a/src/cpp/writer/tswriter.h +++ b/src/cpp/writer/tswriter.h @@ -3,7 +3,7 @@ #include #include #include "tensorstore/tensorstore.h" -#include "../reader/sequence.h" +#include "../utilities/sequence.h" #include namespace py = pybind11; @@ -12,9 +12,22 @@ namespace bfiocpp{ class TsWriterCPP{ public: - TsWriterCPP(const std::string& fname, const std::vector& image_shape, const std::vector& chunk_shape, const std::string& dtype); - - void WriteImageData(py::array& py_image); + TsWriterCPP ( + const std::string& fname, + const std::vector& image_shape, + const std::vector& chunk_shape, + const std::string& dtype_str, + const std::string& dimension_order + ); + + void WriteImageData ( + py::array& py_image, + const Seq& rows, + const Seq& cols, + const std::optional& layers, + const std::optional& channels, + const std::optional& tsteps + ); private: std::string _filename; @@ -25,6 +38,9 @@ class TsWriterCPP{ tensorstore::TensorStore _source; + std::optional_z_index, _c_index, _t_index; + int _x_index, _y_index; + }; } diff --git a/src/python/bfiocpp/tswriter.py b/src/python/bfiocpp/tswriter.py index 261416c..2426a8f 100644 --- a/src/python/bfiocpp/tswriter.py +++ b/src/python/bfiocpp/tswriter.py @@ -1,11 +1,17 @@ import numpy as np +from typing import Optional from .libbfiocpp import TsWriterCPP class TSWriter: def __init__( - self, file_name: str, image_shape: list, chunk_shape: list, dtype: np.dtype + self, + file_name: str, + image_shape: list, + chunk_shape: list, + dtype: np.dtype, + dimension_order: str, ): """Initialize tensorstore Zarr writer @@ -13,10 +19,18 @@ def __init__( """ self._image_writer: TsWriterCPP = TsWriterCPP( - file_name, image_shape, chunk_shape, str(dtype) + file_name, image_shape, chunk_shape, str(dtype), dimension_order ) - def write_image_data(self, image_data: np.ndarray): + def write_image_data( + self, + image_data: np.ndarray, + rows: int, + cols: int, + layers: Optional[int] = None, + channels: Optional[int] = None, + tsteps: Optional[int] = None, + ): """Write image data to file image_data: 5d numpy array containing image data @@ -27,7 +41,9 @@ def write_image_data(self, image_data: np.ndarray): raise ValueError("Image data must be a 5d numpy array") try: - self._image_writer.write_image_data(image_data.flatten()) + self._image_writer.write_image_data( + image_data.flatten(), rows, cols, layers, channels, tsteps + ) except Exception as e: raise RuntimeError(f"Error writing image data: {e.what}") diff --git a/tests/test_write.py b/tests/test_write.py index 00ea27c..eced474 100644 --- a/tests/test_write.py +++ b/tests/test_write.py @@ -52,14 +52,15 @@ def tearDownModule(): class TestZarrWrite(unittest.TestCase): - def test_write_zarr_2d(self): - """test_write_zarr_2d - Write zarr using TSWrtier""" + def test_write_zarr_5d(self): + """test_write_zarr_5d - Write zarr using TSWriter""" br = TSReader( str(TEST_DIR.joinpath("5025551.zarr/0")), FileType.OmeZarr, "", ) + assert br._X == 2702 assert br._Y == 2700 assert br._Z == 1 @@ -77,8 +78,14 @@ def test_write_zarr_2d(self): # Use the temporary directory test_file_path = os.path.join(dir, 'out/test.ome.zarr') - bw = TSWriter(test_file_path, tmp.shape, tmp.shape, str(tmp.dtype)) - bw.write_image_data(tmp) + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + + bw = TSWriter(test_file_path, tmp.shape, tmp.shape, str(tmp.dtype), "TCZYX") + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) bw.close() br = TSReader( @@ -87,14 +94,253 @@ def test_write_zarr_2d(self): "", ) + tmp = br.data(rows, cols, layers, channels, tsteps) + + assert tmp.dtype == np.uint8 + assert tmp.sum() == 183750394 + assert tmp.shape == (1, 1, 1, 2700, 2702) + + def test_write_zarr_3d(self): + """test_write_zarr_5d - Write zarr using TSWriter""" + + br = TSReader( + str(TEST_DIR.joinpath("5025551.zarr/0")), + FileType.OmeZarr, + "", + ) + + assert br._X == 2702 + assert br._Y == 2700 + assert br._Z == 1 + assert br._C == 27 + assert br._T == 1 + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + tmp = br.data(rows, cols, layers, channels, tsteps) + + with tempfile.TemporaryDirectory() as dir: + # Use the temporary directory + test_file_path = os.path.join(dir, 'out/test.ome.zarr') + rows = Seq(0, br._Y - 1, 1) cols = Seq(0, br._X - 1, 1) layers = Seq(0, 0, 1) + + tmp = np.expand_dims(np.squeeze(tmp), axis=0) # modify image to be 3D instead of 5D + + bw = TSWriter(test_file_path, tmp.shape, tmp.shape, str(tmp.dtype), "ZYX") + bw.write_image_data(tmp, rows, cols, layers) + bw.close() + + br = TSReader( + str(test_file_path), + FileType.OmeZarr, + "", + ) + + tmp = br.data(rows, cols, layers) + + assert tmp.dtype == np.uint8 + assert tmp.sum() == 183750394 + assert tmp.shape == (1, 2700, 2702) + + def test_write_zarr_chunk_5d(self): + """test_write_zarr_5d - Write zarr using TsWriter""" + + br = TSReader( + str(TEST_DIR.joinpath("5025551.zarr/0")), + FileType.OmeZarr, + "", + ) + + assert br._X == 2702 + assert br._Y == 2700 + assert br._Z == 1 + assert br._C == 27 + assert br._T == 1 + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + tmp = br.data(rows, cols, layers, channels, tsteps) + + with tempfile.TemporaryDirectory() as dir: + # Use the temporary directory + test_file_path = os.path.join(dir, 'out/test.ome.zarr') + + print(tmp.shape) + chunk_shape = [1, 1, 1, 1350, 1351] + #chunk_shape = tmp.shape + print("dtype: " + str(tmp.dtype)) + bw = TSWriter(test_file_path, tmp.shape, chunk_shape, str(tmp.dtype), "TCZYX") + + rows = Seq(0, br._Y//2, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) channels = Seq(0, 0, 1) tsteps = Seq(0, 0, 1) tmp = br.data(rows, cols, layers, channels, tsteps) + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + + rows = Seq(br._Y//2 , br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + tmp = br.data(rows, cols, layers, channels, tsteps) + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + + bw.close() + + br = TSReader( + str(test_file_path), + FileType.OmeZarr, + "", + ) + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + + tmp = br.data(rows, cols, layers, channels, tsteps) + + print(tmp) assert tmp.dtype == np.uint8 - assert tmp.sum() == 183750394 assert tmp.shape == (1, 1, 1, 2700, 2702) + assert tmp.sum() == 183750394 + + def test_write_zarr_3d(self): + """test_write_zarr_5d - Write zarr using TsWriter""" + + br = TSReader( + str(TEST_DIR.joinpath("5025551.zarr/0")), + FileType.OmeZarr, + "", + ) + assert br._X == 2702 + assert br._Y == 2700 + assert br._Z == 1 + assert br._C == 27 + assert br._T == 1 + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + tmp = br.data(rows, cols, layers, channels, tsteps) + + # Update shape to (1, 3, 1, 2700, 2702) + tmp = np.repeat(tmp, 3, axis=1) + + with tempfile.TemporaryDirectory() as dir: + # Use the temporary directory + test_file_path = os.path.join(dir, 'out/test.ome.zarr') + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 2, 1) + tsteps = Seq(0, 0, 1) + + bw = TSWriter(test_file_path, tmp.shape, tmp.shape, str(tmp.dtype), "TCZYX") + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + bw.close() + + br = TSReader( + str(test_file_path), + FileType.OmeZarr, + "", + ) + + tmp = br.data(rows, cols, layers, channels, tsteps) + + assert tmp.dtype == np.uint8 + assert tmp.sum() == 3*183750394 + assert tmp.shape == (1, 3, 1, 2700, 2702) + + + def test_write_zarr_chunk_3d(self): + """test_write_zarr_5d - Write zarr using TsWriter""" + + br = TSReader( + str(TEST_DIR.joinpath("5025551.zarr/0")), + FileType.OmeZarr, + "", + ) + assert br._X == 2702 + assert br._Y == 2700 + assert br._Z == 1 + assert br._C == 27 + assert br._T == 1 + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + tmp = br.data(rows, cols, layers, channels, tsteps) + + # Update shape to (1, 3, 1, 2700, 2702) + tmp = np.repeat(tmp, 3, axis=1) + + with tempfile.TemporaryDirectory() as dir: + # Use the temporary directory + test_file_path = os.path.join(dir, 'out/test.ome.zarr') + + chunk_size = (1,1,1,2700,2702) + + bw = TSWriter(test_file_path, tmp.shape, chunk_size, str(tmp.dtype), "TCZYX") + + # write first channel + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 0, 1) + tsteps = Seq(0, 0, 1) + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + + # write second channel + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(1, 1, 1) + tsteps = Seq(0, 0, 1) + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + + # write third channel + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(2, 2, 1) + tsteps = Seq(0, 0, 1) + bw.write_image_data(tmp, rows, cols, layers, channels, tsteps) + + bw.close() + + br = TSReader( + str(test_file_path), + FileType.OmeZarr, + "", + ) + + rows = Seq(0, br._Y - 1, 1) + cols = Seq(0, br._X - 1, 1) + layers = Seq(0, 0, 1) + channels = Seq(0, 2, 1) + tsteps = Seq(0, 0, 1) + + tmp = br.data(rows, cols, layers, channels, tsteps) + + assert tmp.dtype == np.uint8 + assert tmp.sum() == 3*183750394 + assert tmp.shape == (1, 3, 1, 2700, 2702)