Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ if(NOT CMAKE_BUILD_TYPE)
endif()

set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(SOURCE
set(SOURCE
src/cpp/ts_driver/tiled_tiff/omexml.cc
src/cpp/ts_driver/tiled_tiff/tiled_tiff_key_value_store.cc
src/cpp/ts_driver/ometiff/metadata.cc
src/cpp/ts_driver/ometiff/driver.cc
src/cpp/interface/interface.cpp
src/cpp/reader/tsreader.cpp
src/cpp/reader/niftireader.cpp
src/cpp/utilities/utilities.cpp
src/cpp/writer/tswriter.cpp
src/cpp/writer/niftiwriter.cpp
)

include(FetchContent)
Expand Down Expand Up @@ -61,6 +63,9 @@ else ()
message(STATUS "Unable to find threads. bfio_cpp must have a threading library i.e. pthreads.")
endif ()

#==== ZLIB (system, required for NIfTI .nii.gz decompression)
find_package(ZLIB REQUIRED)

#==== Pybind11
find_package(pybind11 CONFIG REQUIRED)

Expand All @@ -76,7 +81,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(libbfiocpp PRIVATE stdc++fs)
endif()

target_link_libraries(libbfiocpp PRIVATE
tensorstore::tensorstore
tensorstore::all_drivers)
target_link_libraries(libbfiocpp PRIVATE
tensorstore::tensorstore
tensorstore::all_drivers
ZLIB::ZLIB)
target_link_libraries(libbfiocpp PRIVATE ${Build_LIBRARIES})
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
This is the new backend for `bfio`, using `Tensorstore` and other high-throughput IO library

## Supported Formats

| Format | Read | Write |
|--------|------|-------|
| OME-TIFF | Yes | No |
| OME-Zarr v2 | Yes | Yes |
| OME-Zarr v3 | Yes | Yes |
| NIfTI (.nii, .nii.gz) | Yes | Yes |

## Build Requirements

`bfiocpp` uses `Tensorstore` for reading and writing OME Tiff and OME Zarr files. So `Tensorstore` build requirements are needed to be satisfied for `bfiocpp` also.
Expand Down
38 changes: 23 additions & 15 deletions ci-utils/install_prereq_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,54 @@ fi

mkdir -p $LOCAL_INSTALL_DIR

# Set CMAKE_INSTALL_PREFIX to /usr/local when running in GitHub Actions,
# otherwise install into LOCAL_INSTALL_DIR.
if [ -n "$SYS_INSTALL" ]; then
DEPS_INSTALL_PREFIX="/usr/local"
else
DEPS_INSTALL_PREFIX="$PWD/$LOCAL_INSTALL_DIR"
fi



curl -L https://github.com/pybind/pybind11/archive/refs/tags/v2.12.0.zip -o v2.12.0.zip
unzip v2.12.0.zip
unzip -o v2.12.0.zip
cd pybind11-2.12.0
mkdir build_man
mkdir -p build_man
cd build_man
cmake -DCMAKE_INSTALL_PREFIX=../../$LOCAL_INSTALL_DIR/ -DPYBIND11_TEST=OFF ..
cmake -DCMAKE_INSTALL_PREFIX="$DEPS_INSTALL_PREFIX" -DPYBIND11_TEST=OFF ..
make install -j4
cd ../../


curl -L https://github.com/madler/zlib/releases/download/v1.3.1/zlib131.zip -o zlib131.zip
unzip zlib131.zip
unzip -o zlib131.zip
cd zlib-1.3.1
mkdir build_man
mkdir -p build_man
cd build_man
cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=/usr/local ..
cmake --build .
cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX="$DEPS_INSTALL_PREFIX" ..
cmake --build .
cmake --build . --target install
cd ../../

curl -L https://github.com/libjpeg-turbo/libjpeg-turbo/archive/refs/tags/3.1.0.zip -o 3.1.0.zip
unzip 3.1.0.zip
unzip -o 3.1.0.zip
cd libjpeg-turbo-3.1.0
mkdir build_man
mkdir -p build_man
cd build_man
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DENABLE_STATIC=FALSE -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_INSTALL_PREFIX="$DEPS_INSTALL_PREFIX" -DENABLE_STATIC=FALSE -DCMAKE_BUILD_TYPE=Release ..
if [[ "$OSTYPE" == "darwin"* ]]; then
sudo make install -j4
else
make install -j4
fi
cd ../../
make install -j4
cd ../../

curl -L https://github.com/glennrp/libpng/archive/refs/tags/v1.6.53.zip -o v1.6.53.zip
unzip v1.6.53.zip
unzip -o v1.6.53.zip
cd libpng-1.6.53
mkdir build_man
mkdir -p build_man
cd build_man
cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX=/usr/local ..
cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX="$DEPS_INSTALL_PREFIX" ..
make install -j4
cd ../../
51 changes: 49 additions & 2 deletions src/cpp/interface/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
#include <pybind11/numpy.h>
#include <tuple>
#include "../reader/tsreader.h"
#include "../reader/niftireader.h"
#include "../utilities/sequence.h"
#include "../utilities/utilities.h"
#include "../writer/tswriter.h"
#include "../writer/niftiwriter.h"

namespace py = pybind11;
using bfiocpp::Seq;
Expand Down Expand Up @@ -69,6 +71,19 @@ py::array get_iterator_requested_tile_data(bfiocpp::TsReaderCPP& tl, std::int64
return as_pyarray_shared_5d(tmp, ih, iw, id, nc, nt) ;
}

py::array get_nifti_image_data(bfiocpp::NiftiReaderCPP& nr,
const Seq& rows, const Seq& cols,
const Seq& layers, const Seq& channels,
const Seq& tsteps) {
auto tmp = nr.GetImageData(rows, cols, layers, channels, tsteps);
auto ih = rows.Stop() - rows.Start() + 1;
auto iw = cols.Stop() - cols.Start() + 1;
auto id = layers.Stop() - layers.Start() + 1;
auto nc = channels.Stop()- channels.Start()+ 1;
auto nt = tsteps.Stop() - tsteps.Start() + 1;
return as_pyarray_shared_5d(tmp, ih, iw, id, nc, nt);
}

PYBIND11_MODULE(libbfiocpp, m) {
py::class_<Seq, std::shared_ptr<Seq>>(m, "Seq")
.def(py::init<const size_t, const size_t, const size_t>());
Expand Down Expand Up @@ -116,12 +131,44 @@ PYBIND11_MODULE(libbfiocpp, m) {
.value("OmeTiff", bfiocpp::FileType::OmeTiff)
.value("OmeZarrV2", bfiocpp::FileType::OmeZarrV2)
.value("OmeZarrV3", bfiocpp::FileType::OmeZarrV3)
.value("Nifti", bfiocpp::FileType::Nifti)
.value("NiftiGz", bfiocpp::FileType::NiftiGz)
.export_values();

py::class_<bfiocpp::NiftiReaderCPP, std::shared_ptr<bfiocpp::NiftiReaderCPP>>(m, "NiftiReaderCPP")
.def(py::init<const std::string&>())
.def("get_image_height", &bfiocpp::NiftiReaderCPP::GetImageHeight)
.def("get_image_width", &bfiocpp::NiftiReaderCPP::GetImageWidth)
.def("get_image_depth", &bfiocpp::NiftiReaderCPP::GetImageDepth)
.def("get_tile_height", &bfiocpp::NiftiReaderCPP::GetTileHeight)
.def("get_tile_width", &bfiocpp::NiftiReaderCPP::GetTileWidth)
.def("get_tile_depth", &bfiocpp::NiftiReaderCPP::GetTileDepth)
.def("get_channel_count", &bfiocpp::NiftiReaderCPP::GetChannelCount)
.def("get_tstep_count", &bfiocpp::NiftiReaderCPP::GetTstepCount)
.def("get_datatype", &bfiocpp::NiftiReaderCPP::GetDataType)
.def("get_physical_size_x", &bfiocpp::NiftiReaderCPP::GetPhysicalSizeX)
.def("get_physical_size_y", &bfiocpp::NiftiReaderCPP::GetPhysicalSizeY)
.def("get_physical_size_z", &bfiocpp::NiftiReaderCPP::GetPhysicalSizeZ)
.def("get_image_data",
[](bfiocpp::NiftiReaderCPP& nr, const Seq& rows, const Seq& cols,
const Seq& layers, const Seq& channels, const Seq& tsteps) {
return get_nifti_image_data(nr, rows, cols, layers, channels, tsteps);
}, py::return_value_policy::reference);

m.def("get_ome_xml", &bfiocpp::GetOmeXml);


// Writer class
// NIfTI writer
py::class_<bfiocpp::NiftiWriterCPP, std::shared_ptr<bfiocpp::NiftiWriterCPP>>(m, "NiftiWriterCPP")
.def(py::init<const std::string&, const std::vector<std::int64_t>&,
const std::string&, const std::string&>(),
py::arg("filename"),
py::arg("image_shape"),
py::arg("dtype"),
py::arg("dimension_order"))
.def("write_image_data", &bfiocpp::NiftiWriterCPP::WriteImageData)
.def("close", &bfiocpp::NiftiWriterCPP::Close);

// Zarr/OME-TIFF writer
py::class_<bfiocpp::TsWriterCPP, std::shared_ptr<bfiocpp::TsWriterCPP>>(m, "TsWriterCPP")
.def(py::init<const std::string&, const std::vector<std::int64_t>&, const std::vector<std::int64_t>&, const std::string&, const std::string&, bfiocpp::FileType>(),
py::arg("filename"),
Expand Down
Loading
Loading