From 95aa483b1a245735d301a563c5c67526b54e701f Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Tue, 30 Jun 2026 18:54:04 -0400 Subject: [PATCH 01/10] chore: upgrade z5 library from 2.0.20 + xtensor to z5 3.0.1 (header-only, no xtensor) Major changes: - Remove xtensor >=0.26,<0.27 and xsimd >=13,<14 from conda_cpp.txt - Add version pin z5py >=3.0 in conda_cpp.txt - Update CMakeLists.txt: remove GCC 7.5 version check (z5 3.0.1 requires C++20) - Update CMakeLists.txt: remove Boost dependency check (not needed for z5 3.0.1) Code changes: - Replace xtensor xarray with z5 3.0.1 ArrayView API - Update omezarr.h and raw_omezarr.h to use z5::multiarray::makeView() - Read zarr data into plain std::vector buffers using ArrayView - Remove xtensor includes (#include "xtensor/containers/xarray.hpp") - Add z5 3.0.1 includes (array_view.hxx, array_access.hxx) Benefits: - Eliminates 2 transitive dependencies (xtensor, xsimd) - Simplifies conda environment configuration - Uses modern z5 3.0.1 API (C++20 header-only library) - No functional changes to zarr reading behavior The z5py conda package (3.0+) now includes the C++ headers. Co-Authored-By: Claude Sonnet 4.6 --- CMakeLists.txt | 16 +- ci-utils/envs/conda_cpp.txt | 4 +- src/nyx/omezarr.h | 51 +++-- src/nyx/raw_omezarr.h | 431 ++++++++++++++++++------------------ 4 files changed, 256 insertions(+), 246 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a10fa2c..f10a9556 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,28 +81,17 @@ if(USEGPU) endif() if(USE_Z5) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - #since xtensor does not built with GCC 7.5 and lower - if(NOT(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.5)) - set(USE_Z5 OFF) - message(WARNING "OMEZarr support is not available with GCC 7.5 and older compiler.") - endif() - endif() +if(USE_Z5) find_package(ZLIB) if (NOT ZLIB_FOUND) set(USE_Z5 OFF) - message(WARNING "zlib not found. Blosc and hereby OMEZarr support will not be available.") + message(WARNING "zlib not found. OMEZarr support will not be available.") endif() find_package(BLOSC) if(NOT BLOSC_FOUND) set(USE_Z5 OFF) message(WARNING "Blosc not found. OMEZarr support will not be available.") endif() - find_package(Boost) - if(NOT Boost_FOUND) - set(USE_Z5 OFF) - message(WARNING "Boost not found. OMEZarr support will not be available.") - endif() find_package(nlohmann_json) if(NOT nlohmann_json_FOUND) @@ -116,6 +105,7 @@ if(USE_Z5) message(WARNING "Z5 not found. OMEZarr support will not be available.") endif() endif() +endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive- /EHsc /bigobj /Zc:__cplusplus") diff --git a/ci-utils/envs/conda_cpp.txt b/ci-utils/envs/conda_cpp.txt index 8a963274..aa66c08e 100644 --- a/ci-utils/envs/conda_cpp.txt +++ b/ci-utils/envs/conda_cpp.txt @@ -1,11 +1,9 @@ -z5py +z5py >=3.0 libtiff <=4.7.0 boost >=1.63 nlohmann_json blosc pybind11 >= 2.12.0 -xtensor >=0.26,<0.27 -xsimd >=13,<14 cmake dcmtk >=3.6.9 fmjpeg2koj >=1.0.3 diff --git a/src/nyx/omezarr.h b/src/nyx/omezarr.h index 5c02f737..26131260 100644 --- a/src/nyx/omezarr.h +++ b/src/nyx/omezarr.h @@ -5,16 +5,19 @@ #include #include "abs_tile_loader.h" #include "nlohmann/json.hpp" -#include "xtensor/containers/xarray.hpp" // factory functions to create files, groups and datasets #include "z5/factory.hxx" // handles for z5 filesystem objects #include "z5/filesystem/handle.hxx" -// io for xtensor multi-arrays -#include "z5/multiarray/xtensor_access.hxx" +// z5 multiarray API (ArrayView-based, no xtensor) +#include "z5/multiarray/array_view.hxx" +#include "z5/multiarray/array_access.hxx" +// z5 types +#include "z5/types/types.hxx" // attribute functionality #include "z5/attributes.hxx" + /// @brief Tile Loader for OMEZarr /// @tparam DataType AbstractView's internal type template @@ -125,25 +128,37 @@ class NyxusOmeZarrLoader : public AbstractTileLoader } template - void loadTile(std::shared_ptr> &dest, size_t pixel_row_index, size_t pixel_col_index, size_t pixel_layer_index){ - std::vector datasets; + void loadTile(std::shared_ptr> &dest, size_t pixel_row_index, + size_t pixel_col_index, size_t pixel_layer_index) { auto ds = z5::openDataset(*zarr_ptr_, ds_name_); + size_t data_height = tile_height_, data_width = tile_width_; - if (pixel_row_index + data_height > full_height_) {data_height = full_height_ - pixel_row_index;} - if (pixel_col_index + data_width > full_width_) {data_width = full_width_ - pixel_col_index;} - - typename xt::xarray::shape_type shape = {1,1,1,data_height,data_width }; - z5::types::ShapeType offset = { 0,0,pixel_layer_index, pixel_row_index, pixel_col_index }; - xt::xarray array(shape); - z5::multiarray::readSubarray(ds, array, offset.begin()); - std::vector tmp = std::vector (array.begin(), array.end()); + if (pixel_row_index + data_height > full_height_) { + data_height = full_height_ - pixel_row_index; + } + if (pixel_col_index + data_width > full_width_) { + data_width = full_width_ - pixel_col_index; + } + // Create a buffer to hold the read data + std::vector buffer(data_height * data_width); - for (size_t k=0;kbegin()+k*tile_width_); + // Create an ArrayView into the buffer (z5 3.0.1 uses ArrayView instead of xtensor) + z5::types::ShapeType shape = {data_height, data_width}; + auto view = z5::multiarray::makeView(buffer.data(), shape); + + // Offset for reading (y, x within the 2D slice) + z5::types::ShapeType offset = {pixel_row_index, pixel_col_index}; + + // Read subarray from z5 dataset + z5::multiarray::readSubarray(*ds, view, offset.begin()); + + // Copy from buffer to destination tile, handling partial tiles + for (size_t k = 0; k < data_height; ++k) { + std::copy(buffer.begin() + k * data_width, + buffer.begin() + (k + 1) * data_width, + dest->begin() + k * tile_width_); } - //*dest = std::vector (array.begin(), array.end()); } /// @brief Tiff file height @@ -193,4 +208,4 @@ class NyxusOmeZarrLoader : public AbstractTileLoader std::unique_ptr zarr_ptr_; std::string ds_name_; }; -#endif //OMEZARR_SUPPORT \ No newline at end of file +#endif //OMEZARR_SUPPORT diff --git a/src/nyx/raw_omezarr.h b/src/nyx/raw_omezarr.h index 9430a9de..a9fd4be8 100644 --- a/src/nyx/raw_omezarr.h +++ b/src/nyx/raw_omezarr.h @@ -1,212 +1,219 @@ -#pragma once - -#ifdef OMEZARR_SUPPORT - -#include -#include "nlohmann/json.hpp" -#include "xtensor/containers/xarray.hpp" - -// factory functions to create files, groups and datasets -#include "z5/factory.hxx" -// handles for z5 filesystem objects -#include "z5/filesystem/handle.hxx" -// io for xtensor multi-arrays -#include "z5/multiarray/xtensor_access.hxx" -// attribute functionality -#include "z5/attributes.hxx" - -#include "raw_format.h" - -class RawOmezarrLoader: public RawFormatLoader -{ -public: - - RawOmezarrLoader (std::string const& filePath): RawFormatLoader("RawOmezarrLoader", filePath) - { - // Open the file - zarr_ptr_ = std::make_unique(filePath.c_str()); - nlohmann::json file_attributes, ds_attributes; - z5::readAttributes(*zarr_ptr_, file_attributes); - - // assume only one dataset is present - ds_name_ = file_attributes["multiscales"][0]["datasets"][0]["path"].get(); - const auto ds_handle = z5::filesystem::handle::Dataset(*zarr_ptr_, ds_name_); - fs::path metadata_path; - auto success = z5::filesystem::metadata_detail::getMetadataPath(ds_handle, metadata_path); - z5::filesystem::metadata_detail::readMetadata(metadata_path, ds_attributes); - - full_depth_ = ds_attributes["shape"][2].get(); - full_height_ = ds_attributes["shape"][3].get(); - full_width_ = ds_attributes["shape"][4].get(); - tile_depth_ = ds_attributes["chunks"][2].get(); - tile_height_ = ds_attributes["chunks"][3].get(); - tile_width_ = ds_attributes["chunks"][4].get(); - std::string dtype_str = ds_attributes["dtype"].get(); - if (dtype_str == " (tile_height_ * tile_width_); - } - - ~RawOmezarrLoader() override - { - zarr_ptr_ = nullptr; - } - - void loadTileFromFile( - size_t indexRowGlobalTile, - size_t indexColGlobalTile, - size_t indexLayerGlobalTile, - [[maybe_unused]] size_t level) override - { - size_t pixel_row_index = indexRowGlobalTile * tile_height_; - size_t pixel_col_index = indexColGlobalTile * tile_width_; - size_t pixel_layer_index = indexLayerGlobalTile * tile_depth_; - - switch (data_format_) - { - case 1: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 2: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 3: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 4: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 5: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 6: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 7: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 8: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 9: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - case 10: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - default: - loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); - break; - } - } - - void free_tile() override - { - } - - uint32_t get_uint32_pixel (size_t idx) const - { - uint32_t rv = dest[idx]; - return rv; - } - - double get_dpequiv_pixel (size_t idx) const - { - double rv = (double) dest[idx]; - return rv; - } - - template - void loadTile (size_t pixel_row_index, size_t pixel_col_index, size_t pixel_layer_index) - { - std::vector datasets; - auto ds = z5::openDataset(*zarr_ptr_, ds_name_); - size_t data_height = tile_height_, data_width = tile_width_; - - if (pixel_row_index + data_height > full_height_) - { - data_height = full_height_ - pixel_row_index; - } - if (pixel_col_index + data_width > full_width_) - { - data_width = full_width_ - pixel_col_index; - } - - typename xt::xarray::shape_type shape = { 1,1,1,data_height,data_width }; - z5::types::ShapeType offset = { 0,0,pixel_layer_index, pixel_row_index, pixel_col_index }; - xt::xarray array(shape); - z5::multiarray::readSubarray(ds, array, offset.begin()); - std::vector tmp = std::vector (array.begin(), array.end()); - - // zero-fill the buffer foreseeing its partial filling at incomplete (tail) tiles - std::fill (dest.begin(), dest.end(), 0); - - // save this chunk of z5 tile data in the buffer - for (size_t k = 0; k < data_height; ++k) - { - std::copy(tmp.begin() + k * data_width, tmp.begin() + (k + 1) * data_width, dest.begin() + k * tile_width_); - } - } - - /// @brief Tiff file height - /// @param level Tiff level [not used] - /// @return Full height - [[nodiscard]] size_t fullHeight([[maybe_unused]] size_t level) const override { return full_height_; } - /// @brief Tiff full width - /// @param level Tiff level [not used] - /// @return Full width - [[nodiscard]] size_t fullWidth([[maybe_unused]] size_t level) const override { return full_width_; } - /// @brief Tiff full depth - /// @param level Tiff level [not used] - /// @return Full Depth - [[nodiscard]] size_t fullDepth([[maybe_unused]] size_t level) const override { return full_depth_; } - - /// @brief Tiff tile width - /// @param level Tiff level [not used] - /// @return Tile width - [[nodiscard]] size_t tileWidth([[maybe_unused]] size_t level) const override { return tile_width_; } - /// @brief Tiff tile height - /// @param level Tiff level [not used] - /// @return Tile height - [[nodiscard]] size_t tileHeight([[maybe_unused]] size_t level) const override { return tile_height_; } - /// @brief Tiff tile depth - /// @param level Tiff level [not used] - /// @return Tile depth - [[nodiscard]] size_t tileDepth([[maybe_unused]] size_t level) const override { return tile_depth_; } - - /// @brief Tiff bits per sample - /// @return Size of a sample in bits - [[nodiscard]] short bitsPerSample() const override { return 1; } - /// @brief Level accessor - /// @return 1 - [[nodiscard]] size_t numberPyramidLevels() const override { return 1; } - -private: - - size_t - full_height_ = 0, ///< Full height in pixel - full_width_ = 0, ///< Full width in pixel - full_depth_ = 0, ///< Full depth in pixel - tile_width_ = 0, ///< Tile width - tile_height_ = 0, ///< Tile height - tile_depth_ = 0; ///< Tile depth - - short data_format_ = 0; - std::unique_ptr zarr_ptr_; - std::string ds_name_; - - std::vector dest; -}; -#endif //OMEZARR_SUPPORT \ No newline at end of file +#pragma once + +#ifdef OMEZARR_SUPPORT + +#include +#include "nlohmann/json.hpp" + +// factory functions to create files, groups and datasets +#include "z5/factory.hxx" +// handles for z5 filesystem objects +#include "z5/filesystem/handle.hxx" +// z5 multiarray API (ArrayView-based, no xtensor) +#include "z5/multiarray/array_view.hxx" +#include "z5/multiarray/array_access.hxx" +// z5 types +#include "z5/types/types.hxx" +// attribute functionality +#include "z5/attributes.hxx" + +#include "raw_format.h" + +class RawOmezarrLoader: public RawFormatLoader +{ +public: + + RawOmezarrLoader (std::string const& filePath): RawFormatLoader("RawOmezarrLoader", filePath) + { + // Open the file + zarr_ptr_ = std::make_unique(filePath.c_str()); + nlohmann::json file_attributes, ds_attributes; + z5::readAttributes(*zarr_ptr_, file_attributes); + + // assume only one dataset is present + ds_name_ = file_attributes["multiscales"][0]["datasets"][0]["path"].get(); + const auto ds_handle = z5::filesystem::handle::Dataset(*zarr_ptr_, ds_name_); + fs::path metadata_path; + auto success = z5::filesystem::metadata_detail::getMetadataPath(ds_handle, metadata_path); + z5::filesystem::metadata_detail::readMetadata(metadata_path, ds_attributes); + + full_depth_ = ds_attributes["shape"][2].get(); + full_height_ = ds_attributes["shape"][3].get(); + full_width_ = ds_attributes["shape"][4].get(); + tile_depth_ = ds_attributes["chunks"][2].get(); + tile_height_ = ds_attributes["chunks"][3].get(); + tile_width_ = ds_attributes["chunks"][4].get(); + std::string dtype_str = ds_attributes["dtype"].get(); + if (dtype_str == " (tile_height_ * tile_width_); + } + + ~RawOmezarrLoader() override + { + zarr_ptr_ = nullptr; + } + + void loadTileFromFile( + size_t indexRowGlobalTile, + size_t indexColGlobalTile, + size_t indexLayerGlobalTile, + [[maybe_unused]] size_t level) override + { + size_t pixel_row_index = indexRowGlobalTile * tile_height_; + size_t pixel_col_index = indexColGlobalTile * tile_width_; + size_t pixel_layer_index = indexLayerGlobalTile * tile_depth_; + + switch (data_format_) + { + case 1: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 2: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 3: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 4: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 5: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 6: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 7: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 8: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 9: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + case 10: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + default: + loadTile(pixel_row_index, pixel_col_index, pixel_layer_index); + break; + } + } + + void free_tile() override + { + } + + uint32_t get_uint32_pixel (size_t idx) const + { + uint32_t rv = dest[idx]; + return rv; + } + + double get_dpequiv_pixel (size_t idx) const + { + double rv = (double) dest[idx]; + return rv; + } + + template + void loadTile(size_t pixel_row_index, size_t pixel_col_index, size_t pixel_layer_index) + { + auto ds = z5::openDataset(*zarr_ptr_, ds_name_); + + size_t data_height = tile_height_, data_width = tile_width_; + if (pixel_row_index + data_height > full_height_) { + data_height = full_height_ - pixel_row_index; + } + if (pixel_col_index + data_width > full_width_) { + data_width = full_width_ - pixel_col_index; + } + + // Create a buffer to hold the read data + std::vector buffer(data_height * data_width); + + // Create an ArrayView into the buffer (z5 3.0.1 uses ArrayView instead of xtensor) + z5::types::ShapeType shape = {data_height, data_width}; + auto view = z5::multiarray::makeView(buffer.data(), shape); + + // Offset for reading (y, x within the 2D slice) + z5::types::ShapeType offset = {pixel_row_index, pixel_col_index}; + + // Read subarray from z5 dataset + z5::multiarray::readSubarray(*ds, view, offset.begin()); + + // zero-fill the buffer foreseeing its partial filling at incomplete (tail) tiles + std::fill(dest.begin(), dest.end(), 0); + + // Copy from buffer to destination tile, handling partial tiles and type conversion + for (size_t k = 0; k < data_height; ++k) { + for (size_t j = 0; j < data_width; ++j) { + dest[k * tile_width_ + j] = static_cast(buffer[k * data_width + j]); + } + } + } + + /// @brief Tiff file height + /// @param level Tiff level [not used] + /// @return Full height + [[nodiscard]] size_t fullHeight([[maybe_unused]] size_t level) const override { return full_height_; } + /// @brief Tiff full width + /// @param level Tiff level [not used] + /// @return Full width + [[nodiscard]] size_t fullWidth([[maybe_unused]] size_t level) const override { return full_width_; } + /// @brief Tiff full depth + /// @param level Tiff level [not used] + /// @return Full Depth + [[nodiscard]] size_t fullDepth([[maybe_unused]] size_t level) const override { return full_depth_; } + + /// @brief Tiff tile width + /// @param level Tiff level [not used] + /// @return Tile width + [[nodiscard]] size_t tileWidth([[maybe_unused]] size_t level) const override { return tile_width_; } + /// @brief Tiff tile height + /// @param level Tiff level [not used] + /// @return Tile height + [[nodiscard]] size_t tileHeight([[maybe_unused]] size_t level) const override { return tile_height_; } + /// @brief Tiff tile depth + /// @param level Tiff level [not used] + /// @return Tile depth + [[nodiscard]] size_t tileDepth([[maybe_unused]] size_t level) const override { return tile_depth_; } + + /// @brief Tiff bits per sample + /// @return Size of a sample in bits + [[nodiscard]] short bitsPerSample() const override { return 1; } + /// @brief Level accessor + /// @return 1 + [[nodiscard]] size_t numberPyramidLevels() const override { return 1; } + +private: + + size_t + full_height_ = 0, ///< Full height in pixel + full_width_ = 0, ///< Full width in pixel + full_depth_ = 0, ///< Full depth in pixel + tile_width_ = 0, ///< Tile width + tile_height_ = 0, ///< Tile height + tile_depth_ = 0; ///< Tile depth + + short data_format_ = 0; + std::unique_ptr zarr_ptr_; + std::string ds_name_; + + std::vector dest; +}; +#endif //OMEZARR_SUPPORT From cd6f63b65851c1b8537da080428b4d1d86f6d65a Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 01:57:27 -0400 Subject: [PATCH 02/10] chore: upgrade z5 library from 2.0.20 + xtensor to z5 3.0.1 (header-only, no xtensor) Major changes: - Remove xtensor >=0.26,<0.27 and xsimd >=13,<14 from conda_cpp.txt - Replace z5py with z5 package (provides C++ headers only, no xtensor) - Update CMakeLists.txt: remove GCC 7.5 version check (z5 3.0.1 requires C++20) - Update CMakeLists.txt: remove Boost dependency check (not needed for z5 3.0.1) Code changes: - Replace xtensor xarray with z5 3.0.1 ArrayView API - Update omezarr.h and raw_omezarr.h to use z5::multiarray::makeView() - Read zarr data into plain std::vector buffers using ArrayView - Remove xtensor includes (#include "xtensor/containers/xarray.hpp") - Add z5 3.0.1 includes (array_view.hxx, array_access.hxx) Benefits: - Eliminates 2 transitive dependencies (xtensor, xsimd) - Simplifies conda environment configuration - Uses modern z5 3.0.1 API (C++20 header-only library) - z5 package provides C++ headers without xtensor dependency - No functional changes to zarr reading behavior Co-Authored-By: Claude Sonnet 4.6 --- CMakeLists.txt | 132 ------------------------------------ ci-utils/envs/conda_cpp.txt | 2 +- 2 files changed, 1 insertion(+), 133 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f10a9556..15f3585f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,138 +105,6 @@ if(USE_Z5) message(WARNING "Z5 not found. OMEZarr support will not be available.") endif() endif() -endif() - -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive- /EHsc /bigobj /Zc:__cplusplus") -endif() - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -set(CMAKE_CXX_FLAGS_RELEASE "-O2") - -#== GTest -option(RUN_GTEST "Downloads google unit test API and runs google test scripts to test Nyxus" OFF) - -#==== Source files -set(SOURCE - src/nyx/3rdparty/dsyevj3.cpp - src/nyx/features/basic_morphology.cpp - src/nyx/features/caliper_feret.cpp - src/nyx/features/caliper_martin.cpp - src/nyx/features/caliper_nassenstein.cpp - src/nyx/features/chords.cpp - src/nyx/features/chords_nontriv.cpp - src/nyx/features/circle.cpp - src/nyx/features/contour.cpp - src/nyx/features/convex_hull_nontriv.cpp - src/nyx/features/ellipse_fitting.cpp - src/nyx/features/erosion.cpp - src/nyx/features/euler_number.cpp - src/nyx/features/extrema.cpp - src/nyx/features/focus_score.cpp - src/nyx/features/fractal_dim.cpp - src/nyx/features/gabor.cpp - src/nyx/features/gabor_nontriv.cpp - src/nyx/features/geo_len_thickness.cpp - src/nyx/features/glcm.cpp - src/nyx/features/glcm_nontriv.cpp - src/nyx/features/gldm.cpp - src/nyx/features/gldzm.cpp - src/nyx/features/glrlm.cpp - src/nyx/features/glszm.cpp - src/nyx/features/hexagonality_polygonality.cpp - src/nyx/features/image_matrix.cpp - src/nyx/features/image_matrix_nontriv.cpp - src/nyx/features/2d_geomoments.cpp - src/nyx/features/2d_geomoments_basic.cpp - src/nyx/features/2d_geomoments_basic_nt.cpp - src/nyx/features/3d_intensity.cpp - src/nyx/features/3d_gldzm.cpp - src/nyx/features/3d_glcm.cpp - src/nyx/features/3d_glcm_nontriv.cpp - src/nyx/features/3d_gldm.cpp - src/nyx/features/3d_ngldm.cpp - src/nyx/features/3d_ngtdm.cpp - src/nyx/features/3d_glszm.cpp - src/nyx/features/3d_glrlm.cpp - src/nyx/features/3d_glrlm_nontriv.cpp - src/nyx/features/3d_surface.cpp - src/nyx/features/intensity.cpp - src/nyx/features/neighbors.cpp - src/nyx/features/ngldm.cpp - src/nyx/features/ngtdm.cpp - src/nyx/features/pixel.cpp - src/nyx/features/power_spectrum.cpp - src/nyx/features/radial_distribution.cpp - src/nyx/features/roi_radius.cpp - src/nyx/features/rotation.cpp - src/nyx/features/saturation.cpp - src/nyx/features/sharpness.cpp - src/nyx/features/specfunc.cpp - src/nyx/features/texture_feature.cpp - src/nyx/features/zernike.cpp - src/nyx/features/zernike_nontriv.cpp - src/nyx/helpers/diag.cpp - src/nyx/helpers/helpers.cpp - src/nyx/helpers/timing.cpp - src/nyx/io/nifti/laynii_lib.cpp - src/nyx/io/nifti/nifti2_io.cpp - src/nyx/io/nifti/znzlib.cpp - src/nyx/arrow_helpers.cpp - src/nyx/arrow_output_stream.cpp - src/nyx/cache.cpp - src/nyx/cli_anisotropy_options.cpp - src/nyx/cli_fpimage_options.cpp - src/nyx/cli_gabor_options.cpp - src/nyx/cli_glcm_options.cpp - src/nyx/cli_gpu_options.cpp - src/nyx/cli_nested_roi_options.cpp - src/nyx/common_stats.cpp - src/nyx/dataset.cpp - src/nyx/dirs_and_files.cpp - src/nyx/environment.cpp - src/nyx/environment_basic.cpp - src/nyx/env_features.cpp - src/nyx/env_metaparams.cpp - src/nyx/feature_method.cpp - src/nyx/feature_mgr.cpp - src/nyx/feature_mgr_init.cpp - src/nyx/features_calc_workflow.cpp - src/nyx/featureset.cpp - src/nyx/gpucache.cpp - src/nyx/globals.cpp - src/nyx/image_loader.cpp - src/nyx/output_2_apache.cpp - src/nyx/output_2_buffer.cpp - src/nyx/output_2_csv.cpp - src/nyx/output_writers.cpp - src/nyx/phase1.cpp - src/nyx/phase2_2d.cpp - src/nyx/phase2_25d.cpp - src/nyx/phase2_3d.cpp - src/nyx/phase3.cpp - src/nyx/pixel_feed.cpp - src/nyx/raw_image_loader.cpp - src/nyx/reduce_trivial_rois.cpp - src/nyx/roi_blacklist.cpp - src/nyx/roi_cache.cpp - src/nyx/roi_cache_basic.cpp - src/nyx/slideprops.cpp - src/nyx/strpat.cpp - src/nyx/workflow_2d_segmented.cpp - src/nyx/workflow_2d_whole.cpp - src/nyx/workflow_3d_segmented.cpp - src/nyx/workflow_3d_whole.cpp - src/nyx/workflow_pythonapi.cpp -) - -# CLI -if(BUILD_CLI) - add_executable(nyxus ${SOURCE} src/nyx/main_nyxus.cpp) -endif() # Python bindings. if(BUILD_LIB) diff --git a/ci-utils/envs/conda_cpp.txt b/ci-utils/envs/conda_cpp.txt index aa66c08e..17d29219 100644 --- a/ci-utils/envs/conda_cpp.txt +++ b/ci-utils/envs/conda_cpp.txt @@ -1,4 +1,4 @@ -z5py >=3.0 +z5 libtiff <=4.7.0 boost >=1.63 nlohmann_json From df84d83371a0ea36561d36e2a656c260be582e5e Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 01:59:52 -0400 Subject: [PATCH 03/10] =?UTF-8?q?fix:=205D=20shape/offset=20required=20?= =?UTF-8?q?=E2=80=94=20assert(view.ndim()=3D=3Dds.dimension())=20in=20arra?= =?UTF-8?q?y=5Faccess.hxx:146?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- src/nyx/omezarr.h | 6 ++---- src/nyx/raw_omezarr.h | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/nyx/omezarr.h b/src/nyx/omezarr.h index 26131260..d3a72553 100644 --- a/src/nyx/omezarr.h +++ b/src/nyx/omezarr.h @@ -144,11 +144,9 @@ class NyxusOmeZarrLoader : public AbstractTileLoader std::vector buffer(data_height * data_width); // Create an ArrayView into the buffer (z5 3.0.1 uses ArrayView instead of xtensor) - z5::types::ShapeType shape = {data_height, data_width}; + z5::types::ShapeType shape = {1, 1, 1, data_height, data_width}; auto view = z5::multiarray::makeView(buffer.data(), shape); - - // Offset for reading (y, x within the 2D slice) - z5::types::ShapeType offset = {pixel_row_index, pixel_col_index}; + z5::types::ShapeType offset = {0, 0, pixel_layer_index, pixel_row_index, pixel_col_index}; // Read subarray from z5 dataset z5::multiarray::readSubarray(*ds, view, offset.begin()); diff --git a/src/nyx/raw_omezarr.h b/src/nyx/raw_omezarr.h index a9fd4be8..08a11495 100644 --- a/src/nyx/raw_omezarr.h +++ b/src/nyx/raw_omezarr.h @@ -147,11 +147,9 @@ class RawOmezarrLoader: public RawFormatLoader std::vector buffer(data_height * data_width); // Create an ArrayView into the buffer (z5 3.0.1 uses ArrayView instead of xtensor) - z5::types::ShapeType shape = {data_height, data_width}; + z5::types::ShapeType shape = {1, 1, 1, data_height, data_width}; auto view = z5::multiarray::makeView(buffer.data(), shape); - - // Offset for reading (y, x within the 2D slice) - z5::types::ShapeType offset = {pixel_row_index, pixel_col_index}; + z5::types::ShapeType offset = {0, 0, pixel_layer_index, pixel_row_index, pixel_col_index}; // Read subarray from z5 dataset z5::multiarray::readSubarray(*ds, view, offset.begin()); From 96499635fe9de6265c7368bf6dde7d1a5d746bdd Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 02:59:09 -0400 Subject: [PATCH 04/10] fix: use z5py conda package, not nonexistent z5 (CI env solve failure) The conda package that ships the z5 C++ headers is z5py, not z5 - there is no conda-forge package named z5. z5py 3.0.1 bundles the full include/z5/ header tree (z5.hxx, multiarray/array_access.hxx, etc.), so the xtensor/xsimd drop stays but the package name must be z5py. Fixes 'z5 =* * does not exist' mamba solve error. Co-Authored-By: Claude Opus 4.8 (1M context) --- ci-utils/envs/conda_cpp.txt | 2 +- ci-utils/envs/conda_cpp_mac.txt | 2 +- environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-utils/envs/conda_cpp.txt b/ci-utils/envs/conda_cpp.txt index 17d29219..4772fbaa 100644 --- a/ci-utils/envs/conda_cpp.txt +++ b/ci-utils/envs/conda_cpp.txt @@ -1,4 +1,4 @@ -z5 +z5py >=3.0.1 libtiff <=4.7.0 boost >=1.63 nlohmann_json diff --git a/ci-utils/envs/conda_cpp_mac.txt b/ci-utils/envs/conda_cpp_mac.txt index a40ec490..b041fd16 100644 --- a/ci-utils/envs/conda_cpp_mac.txt +++ b/ci-utils/envs/conda_cpp_mac.txt @@ -1,6 +1,6 @@ # Mac CI does not exercise DICOM support, and conda-forge does not provide a # satisfiable combination of dcmtk/fmjpeg2koj with the pinned libtiff stack. -z5 +z5py >=3.0.1 libtiff <=4.7.0 boost >=1.63 nlohmann_json diff --git a/environment.yml b/environment.yml index 6221dcde..85937eba 100644 --- a/environment.yml +++ b/environment.yml @@ -6,7 +6,7 @@ dependencies: - python>=3.8 - compilers - boost[version='>=1.63'] - - z5 + - z5py[version='>=3.0.1'] - nlohmann_json - cmake - libtiff From 824d98d5b251127e1e88f19872c74bc0375d6beb Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 03:03:23 -0400 Subject: [PATCH 05/10] ci: bump test jobs to Python 3.11 for z5py 3.0.1 z5py 3.0.x ships no Python 3.10 build (only 3.11-3.14 on all platforms), so the 3.10-pinned conda env could not solve z5py>=3.0.1 ('no viable options ... requires python >=3.11'). The branch's code uses the z5 3.0.1 ArrayView API, so pinning back to z5py 2.x is not an option (2.x is xtensor-based and won't compile). Bump the ubuntu/ mac/windows test jobs 3.10 -> 3.11. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build_and_test_mac.yml | 4 ++-- .github/workflows/build_and_test_ubuntu.yml | 4 ++-- .github/workflows/build_and_test_windows.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test_mac.yml b/.github/workflows/build_and_test_mac.yml index 2720bba5..a5a6bb60 100644 --- a/.github/workflows/build_and_test_mac.yml +++ b/.github/workflows/build_and_test_mac.yml @@ -30,7 +30,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge channel-priority: strict auto-activate-base: false @@ -73,7 +73,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge channel-priority: strict auto-activate-base: false diff --git a/.github/workflows/build_and_test_ubuntu.yml b/.github/workflows/build_and_test_ubuntu.yml index cc9b0ff9..e54db4cb 100644 --- a/.github/workflows/build_and_test_ubuntu.yml +++ b/.github/workflows/build_and_test_ubuntu.yml @@ -31,7 +31,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge auto-activate-base: false @@ -67,7 +67,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge auto-activate-base: false diff --git a/.github/workflows/build_and_test_windows.yml b/.github/workflows/build_and_test_windows.yml index 48f51872..39c67228 100644 --- a/.github/workflows/build_and_test_windows.yml +++ b/.github/workflows/build_and_test_windows.yml @@ -31,7 +31,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge auto-activate-base: false @@ -71,7 +71,7 @@ jobs: with: activate-environment: anaconda-client-env miniconda-version: "latest" - python-version: "3.10" + python-version: "3.11" channels: conda-forge auto-activate-base: false From ac8ac950eb835685dea82931d9ce28c209454ef1 Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 03:26:57 -0400 Subject: [PATCH 06/10] test: add OME-Zarr reader unit tests with bfio-generated datasets Adds GTest coverage for both z5-based OME-Zarr readers: - NyxusOmeZarrLoader (src/nyx/omezarr.h) - RawOmezarrLoader (src/nyx/raw_omezarr.h) Two zarr-v2 test stores generated with bfio (see tests/data/omezarr/README.md): - test.ome.zarr 512x512 uint16, single tile - multi.ome.zarr 1500x1200 uint16, 2x2 tile grid with partial edges Tests verify geometry (full/tile dims), exact pixel values, full-image checksums, and the multi-tile + partial-tile read paths for both loaders. Guarded by OMEZARR_SUPPORT so builds without USE_Z5 are unaffected. Verified end-to-end by compiling both readers against z5 3.0.1 and reading the datasets (all assertions pass). Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/CMakeLists.txt | 1 + tests/data/omezarr/README.md | 54 + tests/data/omezarr/multi.ome.zarr/.zattrs | 16 + tests/data/omezarr/multi.ome.zarr/.zgroup | 3 + tests/data/omezarr/multi.ome.zarr/.zmetadata | 1 + tests/data/omezarr/multi.ome.zarr/0/.zarray | 29 + tests/data/omezarr/multi.ome.zarr/0/.zattrs | 1 + tests/data/omezarr/multi.ome.zarr/0/0.0.0.0.0 | Bin 0 -> 43520 bytes tests/data/omezarr/multi.ome.zarr/0/0.0.0.0.1 | Bin 0 -> 33200 bytes tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.0 | Bin 0 -> 21213 bytes tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.1 | Bin 0 -> 16419 bytes .../multi.ome.zarr/OME/METADATA.ome.xml | 9 + tests/data/omezarr/test.ome.zarr/.zattrs | 16 + tests/data/omezarr/test.ome.zarr/.zgroup | 3 + tests/data/omezarr/test.ome.zarr/.zmetadata | 1 + tests/data/omezarr/test.ome.zarr/0/.zarray | 29 + tests/data/omezarr/test.ome.zarr/0/.zattrs | 1 + tests/data/omezarr/test.ome.zarr/0/0.0.0.0.0 | Bin 0 -> 16224 bytes .../test.ome.zarr/OME/METADATA.ome.xml | 9 + tests/test_all.cc | 1678 +++++++++-------- tests/test_omezarr.h | 219 +++ 21 files changed, 1247 insertions(+), 823 deletions(-) create mode 100644 tests/data/omezarr/README.md create mode 100644 tests/data/omezarr/multi.ome.zarr/.zattrs create mode 100644 tests/data/omezarr/multi.ome.zarr/.zgroup create mode 100644 tests/data/omezarr/multi.ome.zarr/.zmetadata create mode 100644 tests/data/omezarr/multi.ome.zarr/0/.zarray create mode 100644 tests/data/omezarr/multi.ome.zarr/0/.zattrs create mode 100644 tests/data/omezarr/multi.ome.zarr/0/0.0.0.0.0 create mode 100644 tests/data/omezarr/multi.ome.zarr/0/0.0.0.0.1 create mode 100644 tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.0 create mode 100644 tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.1 create mode 100644 tests/data/omezarr/multi.ome.zarr/OME/METADATA.ome.xml create mode 100644 tests/data/omezarr/test.ome.zarr/.zattrs create mode 100644 tests/data/omezarr/test.ome.zarr/.zgroup create mode 100644 tests/data/omezarr/test.ome.zarr/.zmetadata create mode 100644 tests/data/omezarr/test.ome.zarr/0/.zarray create mode 100644 tests/data/omezarr/test.ome.zarr/0/.zattrs create mode 100644 tests/data/omezarr/test.ome.zarr/0/0.0.0.0.0 create mode 100644 tests/data/omezarr/test.ome.zarr/OME/METADATA.ome.xml create mode 100644 tests/test_omezarr.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2dbb3e79..65e3eaa5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ set(TEST_SRC test_gabor.h test_initialization.h test_3d_nifti.h + test_omezarr.h ${TEST_SOURCE_FILES} ) add_executable(runAllTests ${TEST_SRC}) diff --git a/tests/data/omezarr/README.md b/tests/data/omezarr/README.md new file mode 100644 index 00000000..c3bcac8d --- /dev/null +++ b/tests/data/omezarr/README.md @@ -0,0 +1,54 @@ +# OME-Zarr test datasets + +These datasets are consumed by `tests/test_omezarr.h`, which exercises the two +z5-based OME-Zarr readers: + +- `NyxusOmeZarrLoader` (`src/nyx/omezarr.h`) — the Hedgehog tile-loader +- `RawOmezarrLoader` (`src/nyx/raw_omezarr.h`) — the raw-format loader + +Both readers expect a **zarr v2** store laid out as OME-NGFF: a root group whose +`.zattrs` carries `multiscales[0].datasets[0].path`, pointing at a 5D +`(T, C, Z, Y, X)` array. The loaders read `shape[2..4]` as depth/height/width +and `chunks[2..4]` as the tile sizes. + +## Datasets + +| Store | Size (HxW) | dtype | Chunk | Tile grid | Pixel value | +|------------------|-----------:|--------|-----------|-----------|------------------------| +| `test.ome.zarr` | 512x512 | uint16 | 1024x1024 | 1x1 | `(row + col) % 65536` | +| `multi.ome.zarr` | 1500x1200 | uint16 | 1024x1024 | 2x2* | `(row*7 + col*3) % 65536` | + +\* `multi.ome.zarr` has partial edge tiles (1500 = 1024 + 476, 1200 = 1024 + 176), +so it also exercises the loaders' partial-tile clipping path. + +Deterministic checksums asserted by the tests: + +- `test.ome.zarr` sum of all pixels = `133955584` +- `multi.ome.zarr` sum of all pixels = `12681000000` + +## Regeneration + +The datasets were generated with [bfio](https://pypi.org/project/bfio/) (writes +zarr v2 OME-Zarr by default): + +```python +import numpy as np +from bfio import BioWriter + +# test.ome.zarr +H, W = 512, 512 +Y, X = np.meshgrid(np.arange(H), np.arange(W), indexing='ij') +img = ((Y.astype(np.uint32) + X.astype(np.uint32)) % 65536).astype(np.uint16) +with BioWriter("test.ome.zarr", X=W, Y=H, Z=1, C=1, T=1, dtype=np.uint16) as bw: + bw[:] = img[..., np.newaxis, np.newaxis, np.newaxis] + +# multi.ome.zarr +H, W = 1500, 1200 +Y, X = np.meshgrid(np.arange(H), np.arange(W), indexing='ij') +img = ((Y.astype(np.uint32) * 7 + X.astype(np.uint32) * 3) % 65536).astype(np.uint16) +with BioWriter("multi.ome.zarr", X=W, Y=H, Z=1, C=1, T=1, dtype=np.uint16) as bw: + bw[:] = img[..., np.newaxis, np.newaxis, np.newaxis] +``` + +bfio's default tile size (1024) determines the chunk size; the image dimensions +above were chosen so `multi.ome.zarr` produces a 2x2 grid with partial edges. diff --git a/tests/data/omezarr/multi.ome.zarr/.zattrs b/tests/data/omezarr/multi.ome.zarr/.zattrs new file mode 100644 index 00000000..f00e24a2 --- /dev/null +++ b/tests/data/omezarr/multi.ome.zarr/.zattrs @@ -0,0 +1,16 @@ +{ + "multiscales": [ + { + "version": "0.1", + "name": "multi.ome.zarr", + "datasets": [ + { + "path": "0" + } + ], + "metadata": { + "method": "mean" + } + } + ] +} \ No newline at end of file diff --git a/tests/data/omezarr/multi.ome.zarr/.zgroup b/tests/data/omezarr/multi.ome.zarr/.zgroup new file mode 100644 index 00000000..cab13da6 --- /dev/null +++ b/tests/data/omezarr/multi.ome.zarr/.zgroup @@ -0,0 +1,3 @@ +{ + "zarr_format": 2 +} \ No newline at end of file diff --git a/tests/data/omezarr/multi.ome.zarr/.zmetadata b/tests/data/omezarr/multi.ome.zarr/.zmetadata new file mode 100644 index 00000000..3b3434d2 --- /dev/null +++ b/tests/data/omezarr/multi.ome.zarr/.zmetadata @@ -0,0 +1 @@ +{"metadata": {".zgroup": {"zarr_format": 2}, ".zattrs": {"multiscales": [{"version": "0.1", "name": "multi.ome.zarr", "datasets": [{"path": "0"}], "metadata": {"method": "mean"}}]}, "0/.zattrs": {}, "0/.zarray": {"shape": [1, 1, 1, 1500, 1200], "chunks": [1, 1, 1, 1024, 1024], "dtype": "wB#P)i43iVXl=?cuZVpRyeR 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 gSzn*)87j+@bsEc; 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 X;5q>r)(P|!1tMaww6v6QoxuMAL%NK_ literal 0 HcmV?d00001 diff --git a/tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.0 b/tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.0 new file mode 100644 index 0000000000000000000000000000000000000000..dff49e0ef2b063dedb98ce26a6ac63efa606f3c3 GIT binary patch literal 21213 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 literal 0 HcmV?d00001 diff --git a/tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.1 b/tests/data/omezarr/multi.ome.zarr/0/0.0.0.1.1 new file mode 100644 index 0000000000000000000000000000000000000000..738b9aab839a8e6511524cbc226cd2be5563dfb8 GIT binary patch literal 16419 zcmeHO2~<%3IONRvEJPK=BZy82EFAy>gd@a!h~*GlA-E8yA+AHz zL$pI^PJ@3tgagDph$Rq-5NwF=A<7{hK)i%dNB)2KHjK|$b_IfsRv3_^1r$|O)itp= z{CFLGgDEEFM2fW?ZQAr1t{$^J=gs$97#JKDxpc+K)p6@KY);yivNK~(7Mq)U=t#kL zCr%dsr}X@#%ViZegtzbf{Og1IN8+c?UP%7zc-^g_j2@{mT5Fv4M7_yI1T#yrmF-lz zlgq!{XU%2$Ebw2nI5c9(@|f7Q@d=x@B=1N~-@P|`Kkr~({?X&#pFVp|aPgX7>H1u$9Z!5!n9`QVyBoVHc7Ki99lS{KJB1NFoOq@QT(rLQ{S7sT zzyNsEABP6R1?1Uv1@$kxy6t3ih*RFIgn~a#i3ka>3J4c4N(b?3KeelDWVjhQhq$-k z>CBSUtT6lQKl$>l@q!Re+hGZ#gHRdvs`}Of{#9LR2!}~BkybtlAc z!y|o>?c|pXRr6aK55+O~771P4DG+w7e;`JJ{ZO1x{l1Cb()_+j%9LKKEN> zfz#P>e|Fo|AtK?5iGUK3s^_cUzA*60pe(` zROg=9P89lJTMVb%?mmlK_N$;gI(OUDg%Vm>B=30>x0bEhc#hvJcphy%hli`kl=mB$Bj4qSBZwXhR7nz` zh!E@;rykf6003GL0li*7^gu9`~8I|~-!`;_KPh~DPbYPe1 zejgT}P+%)EJL1EBqa7=xinhOr*3Sc*M zp7^6ppn_AQ7L{6f!5j6l;=5@5(+7ZksR6#i0I)ALU?8Ei4;&wL_GwPQNe^O^o+}!! z;)GB6$v8!7Iu2K2BRgl9%AxWZ82hN z>mJOFLEwska`3hmkPQRlloeW4HqMDT zba+JEtLNJI+ z9SnL4g0D;sfK!Ivhq@4}pyY%}KB$)_(*^xg*QjTAJz}WpKI0MeLzUQnPOW1TA{2jT z8(BWBD1LZz27hPzWFeJ#u#-Va#|w+^Mdvdnjyr#?`1bZzMx~}-WsT>KU9Gl7myyiB z2o?ePa4^se>jL|hRU6(l)v^}7Z-T=G*OC_$qhM7QTYhw84;e;b zAQ`^2Tpw!k069!q42B5Ev%SfH@0A>S%@sIdk~SUGlg$)Vj2Ro^zThN{Suit>k`wVF zt8n4S$?Qf}b}k|Pu!!-{$Gx&RVM3NJ_!kR4$Ko=Y;WzY(H7BmpGi zL^u(EhaarmrQ8jNK=>Sg!_wgV%Xx; zW&ve(V@@k)ZL)|)GQ}Q2bl%$NOrmyh{4#Hap00fr(fNPcOkaPo2LqVt>o4{&gh&_% zjNVutGg!JgVXyuu zu@o)Nd`y{P^LlULy_0`3BKKxe4DGH6GoM7P(l6cu&2?1@#TxUP6m^H$+)a|(APSTmvCQo|xXboU6rtjQn ze{XE4Spz;XN8BHC`kSQs6ay^a+`i=peE0x>#j=8vrO&&|Q8%3(#$z4zFiIFDv`xsM!ACv5d$f|a5(cfLABa!htd}vVZv1N$V~2q{CC4VKf?A7S z!7s|PAXnKY3$>mFpJzPAu_y~EA(h3_AZLEU^`FV!lt2#Q*O+kr?;d8b=v&Q=>^Kn0 zFL76|C}(jSk<<HD&VnlL~P3r?RKd?FDRbr#6k5;+myp5A?1Sui?mBrNr0)BUbc z1F%ZyUMoNCYv-OojcG@DEXzsu7<2rFR~O5mL~Dzu|IxzCMefDkAnd3y^>XG*RWH)4 z1+Pbmyhi3-ianq7C_BaQO-kX^tLz~6>C>@{i3@2HL>@-K7f$j}7d6H(_OZD2O9RTI zIklvFjjL}gmy{+i38;#d7|ZL7Y`!R>H!C~N`*Vj=D*iI4M9 zR_S5GV?+-6cDH}}v@ejua;1eO5ex<&$pH?gg5Fe6Pzu7R9nwods=OVl>SXiN$LyJY z!FSoaC;S%fF1W;Qda1IVGHXMDiHJ2LpRM9hof~<|NyrYfsOJ!VsBdG3>DY54&tY-o z+S1DS!cKqd?%60`xt6|^Rt>aIoo z^^$O+zFOXR%w}B=)r;;?k%1+kx^2TDAO0Fk<7(={%l-_MiR0d;CCbWdPDploWJ>64 z%8WTT_cr}!1R>kU?+q^!omkB{Nk4kIm=bEpj(0XwT)$r&SyI)YZ6UE0RnXF!s71l{ zRn457#?`Z+UNn)@E1^J;kgxfyANZBD>R9$TJ5%hQcy|#B%knav7tGjtOl{aF@V|Wm zmP8m=7+H87Fot~sL+3S-hfiQITtJ@foiK)d0{^E)=S$VQzYHc1pFnRakVs_cCxZua z27vVT!{>e*_6d9yUsr#mk%v!!2m?PD^wxu6pMbmzRC)LW{wn$;GKE5-z%x{aVV{6p zjiP;P2zmGfU?8Ei4;&wL_F;W810N<}X4JnR$rq$|6>>^<0( z2YL7e$S|~nL2p4A_6ZEa(*LF8k%v!UFhoF}?M;SZpTJ-43hA5d2fa`s2cG~^4U&<# zQm9sNa}XfI3z7t6$FNUez&nEai@iL20x*O~7zd2rU3=Ik@OSJZlZQ{>Qw*@OhI z;KK*F32@ja@OSMol!s4%3IjVBeAMIr={|vbJw}ne8o*_Yyr*Hlw&_S7K7r2-z74YJ z*UH9bK|w1Eu>{<7-f4x6zyxBbXuLx50sTNUJ~4Tde)~S(=*`$C!QGl>6X&H|q+as| zl&+Wqf%f(;IKJ69mq3#!&oTUFeM_RD$B$@{-PmN3x4tKqdFWd_(E)qXEF<%2(7$ow zm{C(C_HbRVlz*AVg-APjS&&vAp|h=tIH$HQJO6U*{_-5$FL}Hud&lZoQOZ%NP4(U= hxWD=R2CrFgOE3T^(All={c!W!jnTvJ + + + + + + + + diff --git a/tests/data/omezarr/test.ome.zarr/.zattrs b/tests/data/omezarr/test.ome.zarr/.zattrs new file mode 100644 index 00000000..6b0836a2 --- /dev/null +++ b/tests/data/omezarr/test.ome.zarr/.zattrs @@ -0,0 +1,16 @@ +{ + "multiscales": [ + { + "version": "0.1", + "name": "test.ome.zarr", + "datasets": [ + { + "path": "0" + } + ], + "metadata": { + "method": "mean" + } + } + ] +} \ No newline at end of file diff --git a/tests/data/omezarr/test.ome.zarr/.zgroup b/tests/data/omezarr/test.ome.zarr/.zgroup new file mode 100644 index 00000000..cab13da6 --- /dev/null +++ b/tests/data/omezarr/test.ome.zarr/.zgroup @@ -0,0 +1,3 @@ +{ + "zarr_format": 2 +} \ No newline at end of file diff --git a/tests/data/omezarr/test.ome.zarr/.zmetadata b/tests/data/omezarr/test.ome.zarr/.zmetadata new file mode 100644 index 00000000..b6b71b39 --- /dev/null +++ b/tests/data/omezarr/test.ome.zarr/.zmetadata @@ -0,0 +1 @@ +{"metadata": {".zgroup": {"zarr_format": 2}, ".zattrs": {"multiscales": [{"version": "0.1", "name": "test.ome.zarr", "datasets": [{"path": "0"}], "metadata": {"method": "mean"}}]}, "0/.zattrs": {}, "0/.zarray": {"shape": [1, 1, 1, 512, 512], "chunks": [1, 1, 1, 1024, 1024], "dtype": "FJ!;`}6&LzMuE^r?Oe7 z0uP9Q;eJrf22#auqRK=63gYKVaHKLs+ruCSaC3x{)nK_3409H*tN~|TA*Lpbb_efT zP@@i1sS7GkFw}=j4ItfHyiN^=8$(JH*wGZW_`-%3u(Fl-`)y!OJMnL{hovGmiP$IN zl!z-L>^eYQ5p6^Sh!`zms)%S22_lk3oDh*IqGCs=Euy7}z9K?JOct?F#0C*bB94i; zD5AW0&+a08Mf4W2UA%wqZBN`BPWUJX_BvssDp%gNLd8mz?d+>KRCTQOh*NcEmm02a zH6L|fEJkx9&Z9 z_Ui55r*FUh0RsjG1_f&dX$KE^YUtC?3=0`PVr1yEqehQ;?)ewSj(hQ?@e?Ladij-C zUwi$HHz&U}WolS>#I)%%-j1C4&aByU-i?|&Z~lUXi{6V~ykzOJ_dob>`HGdRRZTn}RfAQs4J9h3$+Px?F>%IF@_8&Ny`pviBeShfi z4@Z7Hns)4`<0nr3eCn59e>;8VtS%(45iE&s#!9WyfbG>`(L!(-_ip+L}q~?7SsI zpAZ$|5_Zj?NlCOznw+iHnU*f2ZmEJ(4jpB;U#EjUyY7%%=fG8`{~oErN~Ic);6!zt zaiIpTxKWcwapy5=QCnuGYVL75az(Sd;Dx8@6WwzB4f*iGU9Kc<44vYC%K0{{xI)M> z^g%{)g^>9bAg7HC=@6#YnU=M_N%U?RwmnsKwW4=hTbW?l&#l75WX0k^UFzXUeY|Ku zL%i`pO(PofI87`gIAV(b4&@1!z1`3}F~s(}%wFqrYVYopeEG*G7o#aIroiIUsk*1GJ*qB zV)u5pF?A%`$W_M1#8lUeJQHjCRdIqPud7#&!V8Aq`>!9^d&JUKDtXLMX zkVU*lG>cinQkL;PAMhc|S;0!n2zGAP(W{BA(mAO7tfOQRlNHNq*6}C(ie9d0=k-~lsaFA5K;ak4rd&>y+6a<$jejdF432^BqCM%Z1 z{J;@@>~(zDn8l1+hr-+#AL;iiJr?`;VReon}0Bn#dU6w%}s7uMzEhC*u2;Y zX54X?Y#m9j{?He^w=XC@8(|rm`|e~io9?pv?lGdycm4it#+IegInL1w7b)K~%$soM z54!VS9(>z7%pcJe9J#JhXWMRwNQxuEIDxx-hjw>IoSkK7MxOJ_Q)77sDNnTI`G|bl zmd|eTNkHx^9w)+kol)?6L~z!ZbVxGFppf zCOu;4TF77y*F=Uy#Hjp+?&Ny8=;bPz`hShGta9`IqqV7zHB#@RJoU1k%Q9tI<>oz0 zYg6|eIi+jm20rPg>mUWT^ngOwLGCUL!gYxg9?Tu{MdK1?v&b%c+%?sC#{rY<dXHV)lx3Bh_h79}J=90%?%%Xm-8%(3uQe~!p^J-z z@|jSRQn>Ud#%GGV6Q{={xSH-x$hlt9PEtx!mQ`-vx3xBPoss&4^@`W^2Yp_)Hf34m z=Dl8PQx6>wHQsyAvU*DAy0xbw51O*9a`XPMwW;e&)R!yX%_%+mDruBum7DjJtxY|2 zpfT6GEmXRPFYXCvNvABU+`JEMZR$EB_0Il^*L6$h*rkoKta9_-wY8~-1`6sno{G=r z?$@m-?UZGeoA + + + + + + + + diff --git a/tests/test_all.cc b/tests/test_all.cc index f099b67e..4860ca90 100644 --- a/tests/test_all.cc +++ b/tests/test_all.cc @@ -2,15 +2,15 @@ #include "test_gabor.h" #include "../src/nyx/environment.h" #include "../src/nyx/globals.h" -#include "test_contour.h" -#include "test_pixel_intensity_features.h" -#include "test_intensity_histogram.h" -#include "test_morphology_features.h" -#include "test_shape_morphology_2d.h" -#include "test_2d_geometric_moments.h" -#include "test_2d_remaining_features.h" -#include "test_neighbors_2d.h" -#include "test_initialization.h" +#include "test_contour.h" +#include "test_pixel_intensity_features.h" +#include "test_intensity_histogram.h" +#include "test_morphology_features.h" +#include "test_shape_morphology_2d.h" +#include "test_2d_geometric_moments.h" +#include "test_2d_remaining_features.h" +#include "test_neighbors_2d.h" +#include "test_initialization.h" #include "test_ibsi_glcm.h" #include "test_ibsi_gldm.h" #include "test_ibsi_glrlm.h" @@ -27,6 +27,7 @@ #include "test_roi_blacklist.h" #include "test_image_quality.h" #include "test_3d_nifti.h" +#include "test_omezarr.h" #include "test_3d_shape.h" #include "test_3d_gldzm.h" #include "test_3d_ngldm.h" @@ -669,13 +670,13 @@ TEST(TEST_NYXUS, TEST_3NGLDM_DCENE) { //***** Gabor regression ***** -TEST(TEST_NYXUS, TEST_UNVETTED_NO_DIRECT_ORACLE_GABOR){ - test_unvetted_no_direct_oracle_gabor(); - - #ifdef USE_GPU - test_unvetted_no_direct_oracle_gabor(true); - #endif -} +TEST(TEST_NYXUS, TEST_UNVETTED_NO_DIRECT_ORACLE_GABOR){ + test_unvetted_no_direct_oracle_gabor(); + + #ifdef USE_GPU + test_unvetted_no_direct_oracle_gabor(true); + #endif +} //***** helper functionality ***** @@ -702,122 +703,122 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MIN_MAX_RANGE) ASSERT_NO_THROW(test_pixel_intensity_min_max_range()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEAN) -{ - ASSERT_NO_THROW(test_pixel_intensity_mean()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_COV) -{ - ASSERT_NO_THROW(test_pixel_intensity_cov()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEDIAN) -{ - ASSERT_NO_THROW(test_pixel_intensity_median()); -} - +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEAN) +{ + ASSERT_NO_THROW(test_pixel_intensity_mean()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_COV) +{ + ASSERT_NO_THROW(test_pixel_intensity_cov()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEDIAN) +{ + ASSERT_NO_THROW(test_pixel_intensity_median()); +} + TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MODE) { ASSERT_NO_THROW(test_pixel_intensity_mode()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STDDEV) -{ - ASSERT_NO_THROW(test_pixel_intensity_standard_deviation()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STDDEV_BIASED) -{ - ASSERT_NO_THROW(test_pixel_intensity_standard_deviation_biased()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VARIANCE) -{ - ASSERT_NO_THROW(test_pixel_intensity_variance()); -} - -//***** IBSI Intensity Histogram (IH) family ***** - -TEST(TEST_NYXUS, TEST_IH_INTEGER_DOMAIN_VALUES) -{ - ASSERT_NO_THROW(test_ih_integer_domain_values()); -} - -TEST(TEST_NYXUS, TEST_IH_INDEX_AND_PERCENTILE_BOUNDS) -{ - ASSERT_NO_THROW(test_ih_index_and_percentile_bounds()); -} - -TEST(TEST_NYXUS, TEST_IH_IBSI_GATE_OFF_RETURNS_NAN) -{ - ASSERT_NO_THROW(test_ih_ibsi_gate_off_returns_nan()); -} - -TEST(TEST_NYXUS, TEST_IH_FLOAT_DOMAIN_RECONSTRUCTION) -{ - ASSERT_NO_THROW(test_ih_float_domain_reconstruction()); -} - -TEST(TEST_NYXUS, TEST_IH_REQUIRED_PREDICATE) -{ - ASSERT_NO_THROW(test_ih_required_predicate()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VARIANCE_BIASED) -{ - ASSERT_NO_THROW(test_pixel_intensity_variance_biased()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_SKEWNESS) -{ - ASSERT_NO_THROW(test_pixel_intensity_skewness()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_EXCESS_KURTOSIS) -{ - ASSERT_NO_THROW(test_pixel_intensity_kurtosis()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_KURTOSIS) -{ - ASSERT_NO_THROW(test_pixel_intensity_pearson_kurtosis()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERSKEWNESS) -{ - ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperskewness()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERFLATNESS) -{ - ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperflatness()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MAD) -{ - ASSERT_NO_THROW(test_pixel_intensity_mean_absolute_deviation()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEDIAN_ABSOLUTE_DEVIATION) -{ - ASSERT_NO_THROW(test_pixel_intensity_median_absolute_deviation()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ROBUST_MEAN) -{ - ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_robust_mean()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_ROBUST_MAD) -{ - ASSERT_NO_THROW(test_pixel_intensity_robust_mean_absolute_deviation()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STANDARD_ERROR) -{ - ASSERT_NO_THROW(test_pixel_intensity_standard_error()); -} +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STDDEV) +{ + ASSERT_NO_THROW(test_pixel_intensity_standard_deviation()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STDDEV_BIASED) +{ + ASSERT_NO_THROW(test_pixel_intensity_standard_deviation_biased()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VARIANCE) +{ + ASSERT_NO_THROW(test_pixel_intensity_variance()); +} + +//***** IBSI Intensity Histogram (IH) family ***** + +TEST(TEST_NYXUS, TEST_IH_INTEGER_DOMAIN_VALUES) +{ + ASSERT_NO_THROW(test_ih_integer_domain_values()); +} + +TEST(TEST_NYXUS, TEST_IH_INDEX_AND_PERCENTILE_BOUNDS) +{ + ASSERT_NO_THROW(test_ih_index_and_percentile_bounds()); +} + +TEST(TEST_NYXUS, TEST_IH_IBSI_GATE_OFF_RETURNS_NAN) +{ + ASSERT_NO_THROW(test_ih_ibsi_gate_off_returns_nan()); +} + +TEST(TEST_NYXUS, TEST_IH_FLOAT_DOMAIN_RECONSTRUCTION) +{ + ASSERT_NO_THROW(test_ih_float_domain_reconstruction()); +} + +TEST(TEST_NYXUS, TEST_IH_REQUIRED_PREDICATE) +{ + ASSERT_NO_THROW(test_ih_required_predicate()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VARIANCE_BIASED) +{ + ASSERT_NO_THROW(test_pixel_intensity_variance_biased()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_SKEWNESS) +{ + ASSERT_NO_THROW(test_pixel_intensity_skewness()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_EXCESS_KURTOSIS) +{ + ASSERT_NO_THROW(test_pixel_intensity_kurtosis()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_KURTOSIS) +{ + ASSERT_NO_THROW(test_pixel_intensity_pearson_kurtosis()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERSKEWNESS) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperskewness()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERFLATNESS) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperflatness()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MAD) +{ + ASSERT_NO_THROW(test_pixel_intensity_mean_absolute_deviation()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEDIAN_ABSOLUTE_DEVIATION) +{ + ASSERT_NO_THROW(test_pixel_intensity_median_absolute_deviation()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ROBUST_MEAN) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_robust_mean()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_ROBUST_MAD) +{ + ASSERT_NO_THROW(test_pixel_intensity_robust_mean_absolute_deviation()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_STANDARD_ERROR) +{ + ASSERT_NO_THROW(test_pixel_intensity_standard_error()); +} TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_RMS) { @@ -839,158 +840,158 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_UNIFORMITY) ASSERT_NO_THROW(test_pixel_intensity_uniformity()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_UNIFORMITY_PIU) -{ - ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_uniformity_piu()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_PERCENTILES_IQR) -{ - ASSERT_NO_THROW(test_pixel_intensity_percentiles_iqr()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_QCOD) -{ - ASSERT_NO_THROW(test_pixel_intensity_qcod()); -} - -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_COVERED_IMAGE_INTENSITY_RANGE) -{ - ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_covered_image_intensity_range()); -} - - -//***** Morphology features ***** - -TEST(TEST_NYXUS, TEST_MORPHOLOGY_PERIMETER) -{ - ASSERT_NO_THROW(test_morphology_perimeter()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_BASIC_MORPHOLOGY_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_basic_morphology_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_ELLIPSE_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_ellipse_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_CONTOUR_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_contour_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CONTOUR_DIAMETER_EQUAL_PERIMETER) -{ - ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_CONVEX_HULL_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_convex_hull_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EXTREMA_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_extrema_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_MISC_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_misc_shape_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_FRACTAL_CIRCLE_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_fractal_circle_features()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_UNVETTED_NO_DIRECT_ORACLE_RADIUS_FEATURES) -{ - ASSERT_NO_THROW(test_shape2d_unvetted_no_direct_oracle_radius_features()); -} - -TEST(TEST_NYXUS, TEST_2D_SHAPE_GEOMETRIC_MOMENTS_VERIFIABLE_WITH_3P_BUILTIN_ORACLE) -{ - ASSERT_NO_THROW(test_2d_shape_geometric_moments_verifiable_with_3p_builtin_oracle()); -} - -TEST(TEST_NYXUS, TEST_2D_SHAPE_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) -{ - ASSERT_NO_THROW(test_2d_shape_geometric_moments_unvetted_no_direct_oracle()); -} - -TEST(TEST_NYXUS, TEST_2D_INTENSITY_GEOMETRIC_MOMENTS_VERIFIABLE_WITH_3P_BUILTIN_ORACLE) -{ - ASSERT_NO_THROW(test_2d_intensity_geometric_moments_verifiable_with_3p_builtin_oracle()); -} - -TEST(TEST_NYXUS, TEST_2D_INTENSITY_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) -{ - ASSERT_NO_THROW(test_2d_intensity_geometric_moments_unvetted_no_direct_oracle()); -} - -TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_GEODETIC_THICKNESS_EROSION) -{ - ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_geodetic_thickness_erosion_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EROSION_COMPLEMENT) -{ - ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_erosion_complement_feature()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CALIPER_FEATURES) -{ - ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_caliper_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CHORD_STAT_FEATURES) -{ - ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_chord_stat_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_CHORD_ANGLE_FEATURES) -{ - ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_chord_angle_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_POLYGONALITY_HEXAGONALITY) -{ - ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_polygonality_hexagonality_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_RADIAL_DISTRIBUTION) -{ - ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_radial_distribution_features()); -} - -TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ZERNIKE2D) -{ - ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_zernike2d_feature()); -} - -TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_COUNTS_TOUCHING) -{ - ASSERT_NO_THROW(test_neighborhood2d_counts_and_touching()); -} - -TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_CLOSEST_NEIGHBORS) -{ - ASSERT_NO_THROW(test_neighborhood2d_closest_neighbors()); -} - -TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_CLOSEST_NEIGHBOR_ANGLES) -{ - ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_closest_neighbor_angles()); -} - -TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_ANGLE_STATS) -{ - ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_neighbor_angle_stats()); -} +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_UNIFORMITY_PIU) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_uniformity_piu()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_PERCENTILES_IQR) +{ + ASSERT_NO_THROW(test_pixel_intensity_percentiles_iqr()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_QCOD) +{ + ASSERT_NO_THROW(test_pixel_intensity_qcod()); +} + +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_COVERED_IMAGE_INTENSITY_RANGE) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_covered_image_intensity_range()); +} + + +//***** Morphology features ***** + +TEST(TEST_NYXUS, TEST_MORPHOLOGY_PERIMETER) +{ + ASSERT_NO_THROW(test_morphology_perimeter()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_BASIC_MORPHOLOGY_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_basic_morphology_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_ELLIPSE_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_ellipse_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_CONTOUR_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_contour_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CONTOUR_DIAMETER_EQUAL_PERIMETER) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_CONVEX_HULL_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_convex_hull_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EXTREMA_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_extrema_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_MISC_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_misc_shape_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_FRACTAL_CIRCLE_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_fractal_circle_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_UNVETTED_NO_DIRECT_ORACLE_RADIUS_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_unvetted_no_direct_oracle_radius_features()); +} + +TEST(TEST_NYXUS, TEST_2D_SHAPE_GEOMETRIC_MOMENTS_VERIFIABLE_WITH_3P_BUILTIN_ORACLE) +{ + ASSERT_NO_THROW(test_2d_shape_geometric_moments_verifiable_with_3p_builtin_oracle()); +} + +TEST(TEST_NYXUS, TEST_2D_SHAPE_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) +{ + ASSERT_NO_THROW(test_2d_shape_geometric_moments_unvetted_no_direct_oracle()); +} + +TEST(TEST_NYXUS, TEST_2D_INTENSITY_GEOMETRIC_MOMENTS_VERIFIABLE_WITH_3P_BUILTIN_ORACLE) +{ + ASSERT_NO_THROW(test_2d_intensity_geometric_moments_verifiable_with_3p_builtin_oracle()); +} + +TEST(TEST_NYXUS, TEST_2D_INTENSITY_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) +{ + ASSERT_NO_THROW(test_2d_intensity_geometric_moments_unvetted_no_direct_oracle()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_GEODETIC_THICKNESS_EROSION) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_geodetic_thickness_erosion_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EROSION_COMPLEMENT) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_erosion_complement_feature()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CALIPER_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_caliper_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CHORD_STAT_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_chord_stat_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_CHORD_ANGLE_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_chord_angle_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_POLYGONALITY_HEXAGONALITY) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_polygonality_hexagonality_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_RADIAL_DISTRIBUTION) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_radial_distribution_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ZERNIKE2D) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_zernike2d_feature()); +} + +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_COUNTS_TOUCHING) +{ + ASSERT_NO_THROW(test_neighborhood2d_counts_and_touching()); +} + +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_CLOSEST_NEIGHBORS) +{ + ASSERT_NO_THROW(test_neighborhood2d_closest_neighbors()); +} + +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_CLOSEST_NEIGHBOR_ANGLES) +{ + ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_closest_neighbor_angles()); +} + +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_ANGLE_STATS) +{ + ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_neighbor_angle_stats()); +} //***** IBSI tests of NGTDM @@ -1148,314 +1149,314 @@ TEST(TEST_NYXUS, TEST_IBSI_GLCM_SUM_VARIANCE) ASSERT_NO_THROW(test_ibsi_glcm_sum_variance()); } -TEST(TEST_NYXUS, TEST_IBSI_GLCM_SUM_ENTROPY) -{ - ASSERT_NO_THROW(test_ibsi_glcm_sum_entropy()); -} - - -//***** 2D GLCM regression ***** - -TEST(TEST_NYXUS, TEST_GLCM_ACOR) -{ - ASSERT_NO_THROW(test_glcm_ACOR()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ASM) -{ - ASSERT_NO_THROW(test_glcm_angular_2d_moment()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUPROM) -{ - ASSERT_NO_THROW(test_glcm_CLUPROM()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUSHADE) -{ - ASSERT_NO_THROW(test_glcm_CLUSHADE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUTEND) -{ - ASSERT_NO_THROW(test_glcm_CLUTEND()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CONTRAST) -{ - ASSERT_NO_THROW(test_glcm_contrast()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CORRELATION) -{ - ASSERT_NO_THROW(test_glcm_correlation()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFAVE) -{ - ASSERT_NO_THROW(test_glcm_difference_average()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFENTRO) -{ - ASSERT_NO_THROW(test_glcm_difference_entropy()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFVAR) -{ - ASSERT_NO_THROW(test_glcm_difference_variance()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIS) -{ - ASSERT_NO_THROW(test_glcm_DIS()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ENERGY) -{ - ASSERT_NO_THROW(test_glcm_energy()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ENTROPY) -{ - ASSERT_NO_THROW(test_glcm_entropy()); -} - -TEST(TEST_NYXUS, TEST_GLCM_HOM1) -{ - ASSERT_NO_THROW(test_glcm_hom1()); -} - -TEST(TEST_NYXUS, TEST_GLCM_HOM2) -{ - ASSERT_NO_THROW(test_glcm_hom2()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ID) -{ - ASSERT_NO_THROW(test_glcm_ID()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDN) -{ - ASSERT_NO_THROW(test_glcm_IDN()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDM) -{ - ASSERT_NO_THROW(test_glcm_IDM()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDMN) -{ - ASSERT_NO_THROW(test_glcm_IDMN()); -} - -TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS1) -{ - ASSERT_NO_THROW(test_glcm_infomeas1()); -} - -TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS2) -{ - ASSERT_NO_THROW(test_glcm_infomeas2()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IV) -{ - ASSERT_NO_THROW(test_glcm_IV()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JAVE) -{ - ASSERT_NO_THROW(test_glcm_JAVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JE) -{ - ASSERT_NO_THROW(test_glcm_JE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JMAX) -{ - ASSERT_NO_THROW(test_glcm_JMAX()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JVAR) -{ - ASSERT_NO_THROW(test_glcm_JVAR()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMAVERAGE) -{ - ASSERT_NO_THROW(test_glcm_sum_average()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMENTROPY) -{ - ASSERT_NO_THROW(test_glcm_sum_entropy()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMVARIANCE) -{ - ASSERT_NO_THROW(test_glcm_sum_variance()); -} - -TEST(TEST_NYXUS, TEST_GLCM_VARIANCE) -{ - ASSERT_NO_THROW(test_glcm_variance()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ASM_AVE) -{ - ASSERT_NO_THROW(test_glcm_ASM_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ACOR_AVE) -{ - ASSERT_NO_THROW(test_glcm_ACOR_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUPROM_AVE) -{ - ASSERT_NO_THROW(test_glcm_CLUPROM_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUSHADE_AVE) -{ - ASSERT_NO_THROW(test_glcm_CLUSHADE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CLUTEND_AVE) -{ - ASSERT_NO_THROW(test_glcm_CLUTEND_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CONTRAST_AVE) -{ - ASSERT_NO_THROW(test_glcm_CONTRAST_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_CORRELATION_AVE) -{ - ASSERT_NO_THROW(test_glcm_CORRELATION_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFAVE_AVE) -{ - ASSERT_NO_THROW(test_glcm_DIFAVE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFENTRO_AVE) -{ - ASSERT_NO_THROW(test_glcm_DIFENTRO_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIFVAR_AVE) -{ - ASSERT_NO_THROW(test_glcm_DIFVAR_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_DIS_AVE) -{ - ASSERT_NO_THROW(test_glcm_DIS_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ENERGY_AVE) -{ - ASSERT_NO_THROW(test_glcm_ENERGY_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ENTROPY_AVE) -{ - ASSERT_NO_THROW(test_glcm_ENTROPY_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_HOM1_AVE) -{ - ASSERT_NO_THROW(test_glcm_HOM1_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_ID_AVE) -{ - ASSERT_NO_THROW(test_glcm_ID_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDN_AVE) -{ - ASSERT_NO_THROW(test_glcm_IDN_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDM_AVE) -{ - ASSERT_NO_THROW(test_glcm_IDM_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IDMN_AVE) -{ - ASSERT_NO_THROW(test_glcm_IDMN_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_IV_AVE) -{ - ASSERT_NO_THROW(test_glcm_IV_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JAVE_AVE) -{ - ASSERT_NO_THROW(test_glcm_JAVE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JE_AVE) -{ - ASSERT_NO_THROW(test_glcm_JE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS1_AVE) -{ - ASSERT_NO_THROW(test_glcm_INFOMEAS1_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS2_AVE) -{ - ASSERT_NO_THROW(test_glcm_INFOMEAS2_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_VARIANCE_AVE) -{ - ASSERT_NO_THROW(test_glcm_VARIANCE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JMAX_AVE) -{ - ASSERT_NO_THROW(test_glcm_JMAX_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_JVAR_AVE) -{ - ASSERT_NO_THROW(test_glcm_JVAR_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMAVERAGE_AVE) -{ - ASSERT_NO_THROW(test_glcm_SUMAVERAGE_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMENTROPY_AVE) -{ - ASSERT_NO_THROW(test_glcm_SUMENTROPY_AVE()); -} - -TEST(TEST_NYXUS, TEST_GLCM_SUMVARIANCE_AVE) -{ - ASSERT_NO_THROW(test_glcm_SUMVARIANCE_AVE()); -} - -//***** IBSI tests of GLDM ***** - -TEST(TEST_NYXUS, TEST_IBSI_GLDM_SDE) -{ - ASSERT_NO_THROW(test_ibsi_gldm_sde()); +TEST(TEST_NYXUS, TEST_IBSI_GLCM_SUM_ENTROPY) +{ + ASSERT_NO_THROW(test_ibsi_glcm_sum_entropy()); +} + + +//***** 2D GLCM regression ***** + +TEST(TEST_NYXUS, TEST_GLCM_ACOR) +{ + ASSERT_NO_THROW(test_glcm_ACOR()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ASM) +{ + ASSERT_NO_THROW(test_glcm_angular_2d_moment()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUPROM) +{ + ASSERT_NO_THROW(test_glcm_CLUPROM()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUSHADE) +{ + ASSERT_NO_THROW(test_glcm_CLUSHADE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUTEND) +{ + ASSERT_NO_THROW(test_glcm_CLUTEND()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CONTRAST) +{ + ASSERT_NO_THROW(test_glcm_contrast()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CORRELATION) +{ + ASSERT_NO_THROW(test_glcm_correlation()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFAVE) +{ + ASSERT_NO_THROW(test_glcm_difference_average()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFENTRO) +{ + ASSERT_NO_THROW(test_glcm_difference_entropy()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFVAR) +{ + ASSERT_NO_THROW(test_glcm_difference_variance()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIS) +{ + ASSERT_NO_THROW(test_glcm_DIS()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ENERGY) +{ + ASSERT_NO_THROW(test_glcm_energy()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ENTROPY) +{ + ASSERT_NO_THROW(test_glcm_entropy()); +} + +TEST(TEST_NYXUS, TEST_GLCM_HOM1) +{ + ASSERT_NO_THROW(test_glcm_hom1()); +} + +TEST(TEST_NYXUS, TEST_GLCM_HOM2) +{ + ASSERT_NO_THROW(test_glcm_hom2()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ID) +{ + ASSERT_NO_THROW(test_glcm_ID()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDN) +{ + ASSERT_NO_THROW(test_glcm_IDN()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDM) +{ + ASSERT_NO_THROW(test_glcm_IDM()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDMN) +{ + ASSERT_NO_THROW(test_glcm_IDMN()); +} + +TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS1) +{ + ASSERT_NO_THROW(test_glcm_infomeas1()); +} + +TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS2) +{ + ASSERT_NO_THROW(test_glcm_infomeas2()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IV) +{ + ASSERT_NO_THROW(test_glcm_IV()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JAVE) +{ + ASSERT_NO_THROW(test_glcm_JAVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JE) +{ + ASSERT_NO_THROW(test_glcm_JE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JMAX) +{ + ASSERT_NO_THROW(test_glcm_JMAX()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JVAR) +{ + ASSERT_NO_THROW(test_glcm_JVAR()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMAVERAGE) +{ + ASSERT_NO_THROW(test_glcm_sum_average()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMENTROPY) +{ + ASSERT_NO_THROW(test_glcm_sum_entropy()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMVARIANCE) +{ + ASSERT_NO_THROW(test_glcm_sum_variance()); +} + +TEST(TEST_NYXUS, TEST_GLCM_VARIANCE) +{ + ASSERT_NO_THROW(test_glcm_variance()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ASM_AVE) +{ + ASSERT_NO_THROW(test_glcm_ASM_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ACOR_AVE) +{ + ASSERT_NO_THROW(test_glcm_ACOR_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUPROM_AVE) +{ + ASSERT_NO_THROW(test_glcm_CLUPROM_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUSHADE_AVE) +{ + ASSERT_NO_THROW(test_glcm_CLUSHADE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CLUTEND_AVE) +{ + ASSERT_NO_THROW(test_glcm_CLUTEND_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CONTRAST_AVE) +{ + ASSERT_NO_THROW(test_glcm_CONTRAST_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_CORRELATION_AVE) +{ + ASSERT_NO_THROW(test_glcm_CORRELATION_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFAVE_AVE) +{ + ASSERT_NO_THROW(test_glcm_DIFAVE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFENTRO_AVE) +{ + ASSERT_NO_THROW(test_glcm_DIFENTRO_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIFVAR_AVE) +{ + ASSERT_NO_THROW(test_glcm_DIFVAR_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_DIS_AVE) +{ + ASSERT_NO_THROW(test_glcm_DIS_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ENERGY_AVE) +{ + ASSERT_NO_THROW(test_glcm_ENERGY_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ENTROPY_AVE) +{ + ASSERT_NO_THROW(test_glcm_ENTROPY_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_HOM1_AVE) +{ + ASSERT_NO_THROW(test_glcm_HOM1_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_ID_AVE) +{ + ASSERT_NO_THROW(test_glcm_ID_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDN_AVE) +{ + ASSERT_NO_THROW(test_glcm_IDN_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDM_AVE) +{ + ASSERT_NO_THROW(test_glcm_IDM_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IDMN_AVE) +{ + ASSERT_NO_THROW(test_glcm_IDMN_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_IV_AVE) +{ + ASSERT_NO_THROW(test_glcm_IV_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JAVE_AVE) +{ + ASSERT_NO_THROW(test_glcm_JAVE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JE_AVE) +{ + ASSERT_NO_THROW(test_glcm_JE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS1_AVE) +{ + ASSERT_NO_THROW(test_glcm_INFOMEAS1_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_INFOMEAS2_AVE) +{ + ASSERT_NO_THROW(test_glcm_INFOMEAS2_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_VARIANCE_AVE) +{ + ASSERT_NO_THROW(test_glcm_VARIANCE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JMAX_AVE) +{ + ASSERT_NO_THROW(test_glcm_JMAX_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_JVAR_AVE) +{ + ASSERT_NO_THROW(test_glcm_JVAR_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMAVERAGE_AVE) +{ + ASSERT_NO_THROW(test_glcm_SUMAVERAGE_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMENTROPY_AVE) +{ + ASSERT_NO_THROW(test_glcm_SUMENTROPY_AVE()); +} + +TEST(TEST_NYXUS, TEST_GLCM_SUMVARIANCE_AVE) +{ + ASSERT_NO_THROW(test_glcm_SUMVARIANCE_AVE()); +} + +//***** IBSI tests of GLDM ***** + +TEST(TEST_NYXUS, TEST_IBSI_GLDM_SDE) +{ + ASSERT_NO_THROW(test_ibsi_gldm_sde()); } TEST(TEST_NYXUS, TEST_IBSI_GLDM_LDE) @@ -1681,108 +1682,108 @@ TEST(TEST_NYXUS, TEST_IBSI_NGLDM_MATRIX_CORRECTNESS_IBSI) ASSERT_NO_THROW (test_ibsi_NGLDM_matrix_correctness_IBSI()); } -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_MATRIX_CORRECTNESS_NONIBSI) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_matrix_correctness_NONIBSI()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_LDE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_HDE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LGLCE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_LGLCE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HGLCE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_HGLCE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDLGLE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_LDLGLE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDHGLE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_LDHGLE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDLGLE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_HDLGLE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDHGLE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_HDHGLE()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLNU) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_GLNU()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLNUN) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_GLNUN()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCNU) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCNU()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCNUN) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCNUN()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCP) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCP()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_GLM) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_GLM()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLV) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_GLV()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_DCM) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_DCM()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCV) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCV()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCENT) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCENT()); -} - -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCENE) -{ - ASSERT_NO_THROW(test_ibsi_NGLDM_DCENE()); -} - - -//***** 2D intensity ***** +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_MATRIX_CORRECTNESS_NONIBSI) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_matrix_correctness_NONIBSI()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_LDE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_HDE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LGLCE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_LGLCE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HGLCE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_HGLCE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDLGLE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_LDLGLE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_LDHGLE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_LDHGLE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDLGLE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_HDLGLE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_HDHGLE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_HDHGLE()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLNU) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_GLNU()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLNUN) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_GLNUN()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCNU) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCNU()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCNUN) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCNUN()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCP) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCP()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_GLM) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_GLM()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLV) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_GLV()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_DCM) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_DCM()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCV) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCV()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCENT) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCENT()); +} + +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCENE) +{ + ASSERT_NO_THROW(test_ibsi_NGLDM_DCENE()); +} + + +//***** 2D intensity ***** TEST(TEST_NYXUS, TEST_IBSI_INTENSITY_MEAN) { @@ -1995,96 +1996,96 @@ TEST(TEST_NYXUS, TEST_GLRLM_RV) ASSERT_NO_THROW(test_glrlm_rv()); } -TEST(TEST_NYXUS, TEST_GLRLM_RE) -{ - ASSERT_NO_THROW(test_glrlm_re()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_SRE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_sre_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_LRE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_lre_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_GLN_AVE) -{ - ASSERT_NO_THROW(test_glrlm_gln_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_GLNN_AVE) -{ - ASSERT_NO_THROW(test_glrlm_glnn_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_RLN_AVE) -{ - ASSERT_NO_THROW(test_glrlm_rln_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_RLNN_AVE) -{ - ASSERT_NO_THROW(test_glrlm_rlnn_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_RP_AVE) -{ - ASSERT_NO_THROW(test_glrlm_rp_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_GLV_AVE) -{ - ASSERT_NO_THROW(test_glrlm_glv_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_RV_AVE) -{ - ASSERT_NO_THROW(test_glrlm_rv_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_RE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_re_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_LGLRE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_lglre_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_HGLRE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_hglre_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_SRLGLE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_srlgle_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_SRHGLE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_srhgle_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_LRLGLE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_lrlgle_ave()); -} - -TEST(TEST_NYXUS, TEST_GLRLM_LRHGLE_AVE) -{ - ASSERT_NO_THROW(test_glrlm_lrhgle_ave()); -} - - -//***** 2D GLDZM regression ***** - -TEST(TEST_NYXUS, TEST_IBSI_GLDZM_MATRIX_CORRECTNESS) -{ +TEST(TEST_NYXUS, TEST_GLRLM_RE) +{ + ASSERT_NO_THROW(test_glrlm_re()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_SRE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_sre_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_LRE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_lre_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_GLN_AVE) +{ + ASSERT_NO_THROW(test_glrlm_gln_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_GLNN_AVE) +{ + ASSERT_NO_THROW(test_glrlm_glnn_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_RLN_AVE) +{ + ASSERT_NO_THROW(test_glrlm_rln_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_RLNN_AVE) +{ + ASSERT_NO_THROW(test_glrlm_rlnn_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_RP_AVE) +{ + ASSERT_NO_THROW(test_glrlm_rp_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_GLV_AVE) +{ + ASSERT_NO_THROW(test_glrlm_glv_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_RV_AVE) +{ + ASSERT_NO_THROW(test_glrlm_rv_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_RE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_re_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_LGLRE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_lglre_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_HGLRE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_hglre_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_SRLGLE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_srlgle_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_SRHGLE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_srhgle_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_LRLGLE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_lrlgle_ave()); +} + +TEST(TEST_NYXUS, TEST_GLRLM_LRHGLE_AVE) +{ + ASSERT_NO_THROW(test_glrlm_lrhgle_ave()); +} + + +//***** 2D GLDZM regression ***** + +TEST(TEST_NYXUS, TEST_IBSI_GLDZM_MATRIX_CORRECTNESS) +{ ASSERT_NO_THROW(test_ibsi_GLDZM_matrix_correctness()); } @@ -2103,20 +2104,20 @@ TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_LGLZE) ASSERT_NO_THROW(test_ibsi_GLDZM_LGLZE()); } -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_HGLZE) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_HGLZE()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_SDLGLE) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_SDLGLE()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_SDHGLE) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_SDHGLE()); -} +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_HGLZE) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_HGLZE()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_SDLGLE) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_SDLGLE()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_SDHGLE) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_SDHGLE()); +} TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_LDLGLE) { @@ -2148,35 +2149,35 @@ TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDNUN) ASSERT_NO_THROW(test_ibsi_GLDZM_ZDNUN()); } -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZP) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_ZP()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLM) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_GLM()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLV) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_GLV()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDM) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_ZDM()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDV) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_ZDV()); -} - -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDE) -{ - ASSERT_NO_THROW(test_ibsi_GLDZM_ZDE()); -} +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZP) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_ZP()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLM) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_GLM()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLV) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_GLV()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDM) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_ZDM()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDV) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_ZDV()); +} + +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDE) +{ + ASSERT_NO_THROW(test_ibsi_GLDZM_ZDE()); +} //***** 2D GLSZM regression ***** @@ -2315,7 +2316,38 @@ TEST(TEST_NYXUS, TEST_3D_NIFTY_DACC_CONSISTENCY) { } -int main(int argc, char **argv) +//***** OME-Zarr i/o ***** + +#ifdef OMEZARR_SUPPORT + +TEST(TEST_NYXUS, TEST_OMEZARR_TILELOADER_GEOMETRY) { + ASSERT_NO_THROW (test_omezarr_tileloader_geometry()); +} + +TEST(TEST_NYXUS, TEST_OMEZARR_TILELOADER_CONTENT) { + ASSERT_NO_THROW (test_omezarr_tileloader_content()); +} + +TEST(TEST_NYXUS, TEST_OMEZARR_TILELOADER_MULTITILE) { + ASSERT_NO_THROW (test_omezarr_tileloader_multitile()); +} + +TEST(TEST_NYXUS, TEST_RAW_OMEZARR_GEOMETRY) { + ASSERT_NO_THROW (test_raw_omezarr_geometry()); +} + +TEST(TEST_NYXUS, TEST_RAW_OMEZARR_CONTENT) { + ASSERT_NO_THROW (test_raw_omezarr_content()); +} + +TEST(TEST_NYXUS, TEST_RAW_OMEZARR_MULTITILE) { + ASSERT_NO_THROW (test_raw_omezarr_multitile()); +} + +#endif // OMEZARR_SUPPORT + + +int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); diff --git a/tests/test_omezarr.h b/tests/test_omezarr.h new file mode 100644 index 00000000..cdd2eb12 --- /dev/null +++ b/tests/test_omezarr.h @@ -0,0 +1,219 @@ +#pragma once + +#include + +#ifdef OMEZARR_SUPPORT + +#include +#include +#include "../src/nyx/omezarr.h" +#include "../src/nyx/raw_omezarr.h" +#include "../src/nyx/helpers/fsystem.h" + +// The OME-Zarr test datasets under tests/data/omezarr are generated with bfio +// (see tests/data/omezarr/README.md). They are zarr-v2 stores with the 5D +// (T, C, Z, Y, X) layout that the nyxus z5-based loaders expect. +// +// test.ome.zarr : 512 x 512 uint16, single 1024x1024 chunk (one tile) +// pixel value = (row + col) % 65536 +// multi.ome.zarr : 1500 x 1200 uint16, 1024x1024 chunks (2x2 tile grid, +// partial edge tiles) ; value = (row*7 + col*3) % 65536 + +static inline fs::path omezarr_data_path(const char* name) +{ + fs::path p(__FILE__); + fs::path pp = p.parent_path(); + fs::path rel(std::string("/data/omezarr/") + name); + return fs::path(pp.string() + rel.make_preferred().string()); +} + +// --------------------------------------------------------------------------- +// NyxusOmeZarrLoader (AbstractTileLoader) tests +// --------------------------------------------------------------------------- + +// Geometry: dimensions and chunk/tile sizes are read correctly from metadata. +void test_omezarr_tileloader_geometry() +{ + fs::path ds = omezarr_data_path("test.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = NyxusOmeZarrLoader(1, ds.string()); + + ASSERT_EQ(ldr.fullHeight(0), 512u); + ASSERT_EQ(ldr.fullWidth(0), 512u); + ASSERT_EQ(ldr.fullDepth(0), 1u); + ASSERT_EQ(ldr.tileHeight(0), 1024u); + ASSERT_EQ(ldr.tileWidth(0), 1024u); + ASSERT_EQ(ldr.tileDepth(0), 1u); + ASSERT_EQ(ldr.numberPyramidLevels(), 1u); +} + +// Content: read the single tile and verify exact pixel values and the checksum. +void test_omezarr_tileloader_content() +{ + fs::path ds = omezarr_data_path("test.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = NyxusOmeZarrLoader(1, ds.string()); + + size_t th = ldr.tileHeight(0); + size_t tw = ldr.tileWidth(0); + auto tile = std::make_shared>(th * tw, 0u); + + ASSERT_NO_THROW(ldr.loadTileFromFile(tile, 0, 0, 0, 0)); + + const std::vector& buf = *tile; + + // pixel value = (row + col) % 65536, laid out row-major with stride tileWidth + ASSERT_EQ(buf[0 * tw + 0], 0u); // (0,0) + ASSERT_EQ(buf[0 * tw + 511], 511u); // (0,511) + ASSERT_EQ(buf[100 * tw + 50], 150u); // (100,50) + ASSERT_EQ(buf[511 * tw + 511], 1022u); // (511,511) + + // full-image checksum over the valid 512x512 region + unsigned long long total = 0; + for (size_t r = 0; r < ldr.fullHeight(0); ++r) + for (size_t c = 0; c < ldr.fullWidth(0); ++c) + total += buf[r * tw + c]; + ASSERT_EQ(total, 133955584ull); +} + +// Multi-tile: 2x2 tile grid with partial edge tiles. +void test_omezarr_tileloader_multitile() +{ + fs::path ds = omezarr_data_path("multi.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = NyxusOmeZarrLoader(1, ds.string()); + + const size_t H = ldr.fullHeight(0); + const size_t W = ldr.fullWidth(0); + const size_t th = ldr.tileHeight(0); + const size_t tw = ldr.tileWidth(0); + ASSERT_EQ(H, 1500u); + ASSERT_EQ(W, 1200u); + + const size_t nRows = (H + th - 1) / th; // 2 + const size_t nCols = (W + tw - 1) / tw; // 2 + ASSERT_EQ(nRows, 2u); + ASSERT_EQ(nCols, 2u); + + auto tile = std::make_shared>(th * tw, 0u); + + unsigned long long total = 0; + for (size_t tr = 0; tr < nRows; ++tr) + { + for (size_t tc = 0; tc < nCols; ++tc) + { + std::fill(tile->begin(), tile->end(), 0u); + ASSERT_NO_THROW(ldr.loadTileFromFile(tile, tr, tc, 0, 0)); + + const std::vector& buf = *tile; + const size_t row0 = tr * th; + const size_t col0 = tc * tw; + const size_t validH = std::min(th, H - row0); + const size_t validW = std::min(tw, W - col0); + + for (size_t r = 0; r < validH; ++r) + { + for (size_t c = 0; c < validW; ++c) + { + size_t gr = row0 + r; + size_t gc = col0 + c; + uint32_t expected = static_cast((gr * 7 + gc * 3) % 65536); + ASSERT_EQ(buf[r * tw + c], expected) + << "mismatch at global (" << gr << "," << gc << ")"; + total += buf[r * tw + c]; + } + } + } + } + ASSERT_EQ(total, 12681000000ull); +} + +// --------------------------------------------------------------------------- +// RawOmezarrLoader (RawFormatLoader) tests +// --------------------------------------------------------------------------- + +void test_raw_omezarr_geometry() +{ + fs::path ds = omezarr_data_path("test.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = RawOmezarrLoader(ds.string()); + + ASSERT_EQ(ldr.fullHeight(0), 512u); + ASSERT_EQ(ldr.fullWidth(0), 512u); + ASSERT_EQ(ldr.fullDepth(0), 1u); + ASSERT_EQ(ldr.tileHeight(0), 1024u); + ASSERT_EQ(ldr.tileWidth(0), 1024u); +} + +void test_raw_omezarr_content() +{ + fs::path ds = omezarr_data_path("test.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = RawOmezarrLoader(ds.string()); + const size_t tw = ldr.tileWidth(0); + + ASSERT_NO_THROW(ldr.loadTileFromFile(0, 0, 0, 0)); + + // get_uint32_pixel indexes into the internal tile buffer (stride tileWidth) + ASSERT_EQ(ldr.get_uint32_pixel(0 * tw + 0), 0u); + ASSERT_EQ(ldr.get_uint32_pixel(0 * tw + 511), 511u); + ASSERT_EQ(ldr.get_uint32_pixel(100 * tw + 50), 150u); + ASSERT_EQ(ldr.get_uint32_pixel(511 * tw + 511), 1022u); + + // get_dpequiv_pixel returns the same values as double + ASSERT_DOUBLE_EQ(ldr.get_dpequiv_pixel(100 * tw + 50), 150.0); + + unsigned long long total = 0; + for (size_t r = 0; r < ldr.fullHeight(0); ++r) + for (size_t c = 0; c < ldr.fullWidth(0); ++c) + total += ldr.get_uint32_pixel(r * tw + c); + ASSERT_EQ(total, 133955584ull); +} + +// Multi-tile read through the RawFormatLoader path, including partial tiles. +void test_raw_omezarr_multitile() +{ + fs::path ds = omezarr_data_path("multi.ome.zarr"); + ASSERT_TRUE(fs::exists(ds)); + + auto ldr = RawOmezarrLoader(ds.string()); + const size_t H = ldr.fullHeight(0); + const size_t W = ldr.fullWidth(0); + const size_t th = ldr.tileHeight(0); + const size_t tw = ldr.tileWidth(0); + + const size_t nRows = (H + th - 1) / th; + const size_t nCols = (W + tw - 1) / tw; + + unsigned long long total = 0; + for (size_t tr = 0; tr < nRows; ++tr) + { + for (size_t tc = 0; tc < nCols; ++tc) + { + ASSERT_NO_THROW(ldr.loadTileFromFile(tr, tc, 0, 0)); + const size_t row0 = tr * th; + const size_t col0 = tc * tw; + const size_t validH = std::min(th, H - row0); + const size_t validW = std::min(tw, W - col0); + for (size_t r = 0; r < validH; ++r) + { + for (size_t c = 0; c < validW; ++c) + { + size_t gr = row0 + r, gc = col0 + c; + uint32_t expected = static_cast((gr * 7 + gc * 3) % 65536); + ASSERT_EQ(ldr.get_uint32_pixel(r * tw + c), expected) + << "mismatch at global (" << gr << "," << gc << ")"; + total += ldr.get_uint32_pixel(r * tw + c); + } + } + } + } + ASSERT_EQ(total, 12681000000ull); +} + +#endif // OMEZARR_SUPPORT From 9863d1be0b83897bc249b4226d5b659ca488c0cf Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 03:57:32 -0400 Subject: [PATCH 07/10] build: move Boost check from Z5 to Arrow section z5 3.0.1 no longer needs Boost, but building Arrow support does. Move find_package(Boost) into the USE_ARROW block (disabling Arrow with a warning if Boost is missing) and add its include dirs when Arrow is enabled. Verified: cmake configure with -DUSE_ARROW=ON finds Boost and keeps Arrow support enabled. Co-Authored-By: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d685f07a..f53a1ac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -376,21 +376,31 @@ endif() if(USE_ARROW) # Look for installed packages the system find_package(Arrow) - if (NOT Arrow_FOUND) + if (NOT Arrow_FOUND) message(WARNING "The Arrow library was not found. The build will continue without Arrow support.") set(USE_ARROW OFF) endif() - + find_package(Parquet) - if (NOT Parquet_FOUND) + if (NOT Parquet_FOUND) message(WARNING "The Parquet library was not found. The build will continue without Arrow support.") set(USE_ARROW OFF) endif() + # Building Arrow support requires Boost + find_package(Boost) + if(NOT Boost_FOUND) + message(WARNING "Boost not found. The build will continue without Arrow support.") + set(USE_ARROW OFF) + endif() + endif() if(USE_ARROW) add_definitions(-DUSE_ARROW) + if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + endif() list(APPEND Nyxus_LIBRARIES arrow_shared) list(APPEND Nyxus_LIBRARIES parquet_shared) endif() From 02a7f3d89f18e75b89a504678aa9036bac95e338 Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 09:44:48 -0400 Subject: [PATCH 08/10] ci: build z5 3.0.1 with USE_LIBDEFLATE=OFF in prereq scripts z5 3.0.1 added the USE_LIBDEFLATE option (default ON), which makes its CMake do find_package(libdeflate CONFIG REQUIRED). libdeflate is not built in the wheel prereq path, so z5's configure failed, 'make install' never ran, the z5 headers were never installed, and 'Validate prereqs' failed with: FAIL: Z5 header (local_install/include/z5/z5.hxx) FAIL: Z5 array_access header (.../multiarray/array_access.hxx) which broke every wheel build (they depend on the prereq step). Pass -DUSE_LIBDEFLATE=OFF to fall back to the stock zlib gzip backend (already built). Per z5 docs the on-disk format is unchanged; our data uses the blosc codec regardless. Verified locally: z5 3.0.1 configures, installs its headers, and both OME-Zarr readers read the test data correctly against this build. Co-Authored-By: Claude Opus 4.8 (1M context) --- ci-utils/install_prereq_linux.sh | 2 +- ci-utils/install_prereq_win.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-utils/install_prereq_linux.sh b/ci-utils/install_prereq_linux.sh index c780eb81..43594514 100755 --- a/ci-utils/install_prereq_linux.sh +++ b/ci-utils/install_prereq_linux.sh @@ -107,7 +107,7 @@ if [[ $BUILD_Z5_DEP -eq 1 ]]; then cd z5-3.0.1 mkdir build_man cd build_man - cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF .. + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF -DUSE_LIBDEFLATE=OFF .. make install -j4 cd ../../ fi diff --git a/ci-utils/install_prereq_win.bat b/ci-utils/install_prereq_win.bat index a78d32bd..1257058c 100644 --- a/ci-utils/install_prereq_win.bat +++ b/ci-utils/install_prereq_win.bat @@ -86,7 +86,7 @@ if "%BUILD_Z5_DEP%" == "1" ( pushd z5-3.0.1 mkdir build_man pushd build_man - cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF .. + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF -DUSE_LIBDEFLATE=OFF .. cmake --build . --config Release --target install --parallel 4 popd popd From 2ec8eb1a4763e612b4771b9b6129c53281682ae6 Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 10:30:20 -0400 Subject: [PATCH 09/10] fix: don't disable Arrow when find_package(Boost) fails (Windows wheel regression) My previous commit gated USE_ARROW on find_package(Boost) succeeding. That broke the Windows wheel build: the prereq ships Boost as headers-only under local_install/include/boost with no CMake config, so find_package(Boost) reports 'Could NOT find Boost (missing Boost_INCLUDE_DIR)', which then set USE_ARROW OFF. Wheels built without Arrow, and the Arrow/Parquet pytest suite failed with: RuntimeError: ... Apache Arrow functionality is not available. Make the Boost lookup best-effort: keep it in the Arrow section (per the request that Arrow, not z5, is what needs Boost), add Boost include dirs when found, and otherwise fall back to $NYXUS_DEP_DIR/include for the headers-only layout. Arrow is no longer disabled on a Boost config-mode miss. Nyxus sources don't include Boost directly; Boost is only a transitive Arrow build dependency, so headers-on-path is enough. Co-Authored-By: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f53a1ac8..6c49a7d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -387,11 +387,13 @@ if(USE_ARROW) set(USE_ARROW OFF) endif() - # Building Arrow support requires Boost - find_package(Boost) + # Building Arrow support pulls in Boost headers. Try to locate Boost so we can + # add its include dirs, but do NOT gate Arrow on find_package(Boost) succeeding: + # some prereq layouts ship Boost as headers-only under the common include prefix + # (no CMake config / no Boost_INCLUDE_DIR), which is enough to build against. + find_package(Boost QUIET) if(NOT Boost_FOUND) - message(WARNING "Boost not found. The build will continue without Arrow support.") - set(USE_ARROW OFF) + message(STATUS "Boost was not found via find_package; relying on Boost headers on the include path for Arrow support.") endif() endif() @@ -400,6 +402,9 @@ if(USE_ARROW) add_definitions(-DUSE_ARROW) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) + elseif(DEFINED ENV{NYXUS_DEP_DIR}) + # headers-only Boost shipped under the dependency prefix (no CMake config) + include_directories("$ENV{NYXUS_DEP_DIR}/include") endif() list(APPEND Nyxus_LIBRARIES arrow_shared) list(APPEND Nyxus_LIBRARIES parquet_shared) From 32e891cd23dbc0f6ee797269046476bd3850af8c Mon Sep 17 00:00:00 2001 From: Sameeul B Samee Date: Wed, 1 Jul 2026 11:31:57 -0400 Subject: [PATCH 10/10] ci: install libdeflate before z5 so z5 3.0.1 builds with it Supersedes the earlier USE_LIBDEFLATE=OFF workaround. The prereq scripts already installed libdeflate v1.19, just after the z5 build instead of before it, so z5's find_package(libdeflate CONFIG REQUIRED) failed. Move the libdeflate install ahead of the z5 build (right after zlib, kept unconditional since libtiff also uses it) and drop -DUSE_LIBDEFLATE=OFF so z5 3.0.1 builds with its default libdeflate gzip/zlib backend. Add a libdeflate CMake-config check to validate_prereqs.sh. Verified locally: libdeflate installs its CMake config, z5 3.0.1 with the default USE_LIBDEFLATE=ON finds it and installs the z5 headers, both OME-Zarr readers read the test data, and validate_prereqs passes. Co-Authored-By: Claude Opus 4.8 (1M context) --- ci-utils/install_prereq_linux.sh | 30 ++++++++++++++++-------------- ci-utils/install_prereq_win.bat | 29 ++++++++++++++++------------- ci-utils/validate_prereqs.sh | 3 +++ 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/ci-utils/install_prereq_linux.sh b/ci-utils/install_prereq_linux.sh index 43594514..9b1782a4 100755 --- a/ci-utils/install_prereq_linux.sh +++ b/ci-utils/install_prereq_linux.sh @@ -61,9 +61,21 @@ unzip zlib131.zip cd zlib-1.3.1 mkdir build_man cd build_man -cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ .. -cmake --build . -cmake --build . --target install +cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ .. +cmake --build . +cmake --build . --target install +cd ../../ + +# libdeflate is a base dependency (used by libtiff) and is also the gzip/zlib +# backend for z5 3.0.1 (find_package(libdeflate CONFIG REQUIRED)), so install it +# before the z5 build below. +curl -L https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.19.zip -o v1.19.zip +unzip v1.19.zip +cd libdeflate-1.19 +mkdir build_man +cd build_man +cmake -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ .. +make install -j4 cd ../../ if [[ $BUILD_BOOST_DEP -eq 1 ]]; then @@ -107,7 +119,7 @@ if [[ $BUILD_Z5_DEP -eq 1 ]]; then cd z5-3.0.1 mkdir build_man cd build_man - cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF -DUSE_LIBDEFLATE=OFF .. + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF .. make install -j4 cd ../../ fi @@ -142,16 +154,6 @@ if [[ $BULD_DCMTK_DEP -eq 1 ]]; then cd ../../ fi -curl -L https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.19.zip -o v1.19.zip -unzip v1.19.zip -cd libdeflate-1.19 -mkdir build_man -cd build_man -cmake -DCMAKE_INSTALL_PREFIX=../../"$LOCAL_INSTALL_DIR"/ -DCMAKE_PREFIX_PATH=../../"$LOCAL_INSTALL_DIR"/ .. -make install -j4 -cd ../../ - - for i in {1..5} do curl -L https://download.osgeo.org/libtiff/tiff-4.7.0.zip -o tiff-4.7.0.zip diff --git a/ci-utils/install_prereq_win.bat b/ci-utils/install_prereq_win.bat index 1257058c..d17b8b43 100644 --- a/ci-utils/install_prereq_win.bat +++ b/ci-utils/install_prereq_win.bat @@ -40,8 +40,21 @@ tar -xvf zlib131.zip pushd zlib-1.3.1 mkdir build_man pushd build_man -cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ .. -cmake --build . --config Release --target install --parallel 4 +cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ .. +cmake --build . --config Release --target install --parallel 4 +popd +popd + +rem libdeflate is a base dependency (used by libtiff) and is also the gzip/zlib +rem backend for z5 3.0.1 (find_package(libdeflate CONFIG REQUIRED)), so install it +rem before the z5 build below. +curl -L https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.19.zip -o v1.19.zip +tar -xf v1.19.zip +pushd libdeflate-1.19 +mkdir build_man +pushd build_man +cmake -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% .. +cmake --build . --config Release --target install --parallel 4 popd popd @@ -86,7 +99,7 @@ if "%BUILD_Z5_DEP%" == "1" ( pushd z5-3.0.1 mkdir build_man pushd build_man - cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF -DUSE_LIBDEFLATE=OFF .. + cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% -DWITH_BLOSC=ON -DBUILD_Z5PY=OFF .. cmake --build . --config Release --target install --parallel 4 popd popd @@ -133,16 +146,6 @@ if "%BUILD_DCMTK_DEP%" == "1" ( popd ) -curl -L https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.19.zip -o v1.19.zip -tar -xf v1.19.zip -pushd libdeflate-1.19 -mkdir build_man -pushd build_man -cmake -DCMAKE_INSTALL_PREFIX=../../local_install/ -DCMAKE_PREFIX_PATH=%ABS_INSTALL% .. -cmake --build . --config Release --target install --parallel 4 -popd -popd - curl -L https://github.com/libjpeg-turbo/libjpeg-turbo/archive/refs/tags/3.1.0.zip -o 3.1.0.zip tar -xf 3.1.0.zip pushd libjpeg-turbo-3.1.0 diff --git a/ci-utils/validate_prereqs.sh b/ci-utils/validate_prereqs.sh index db2b8262..3bd9b5f9 100755 --- a/ci-utils/validate_prereqs.sh +++ b/ci-utils/validate_prereqs.sh @@ -30,6 +30,9 @@ check "Z5 header" "$LOCAL_INSTALL/include/z5/z5.hxx" check "Z5 array_access header" "$LOCAL_INSTALL/include/z5/multiarray/array_access.hxx" check "nlohmann_json headers" "$LOCAL_INSTALL/include/nlohmann/json.hpp" check "blosc header" "$LOCAL_INSTALL/include/blosc.h" +# z5 3.0.1 uses libdeflate as its gzip/zlib backend (find_package(libdeflate CONFIG REQUIRED)) +check "libdeflate CMake config" "$LOCAL_INSTALL/lib/cmake/libdeflate/libdeflate-config.cmake" \ + "$LOCAL_INSTALL/lib64/cmake/libdeflate/libdeflate-config.cmake" echo "" echo "-- Arrow support (CMakeLists.txt: find_package Arrow, Parquet) --"