From abb1d20ca3b1735099862fe8c0a6a1f77c5209f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Mon, 28 Oct 2024 12:25:47 +0100 Subject: [PATCH] WIP --- include/aare/File.hpp | 1 + python/CMakeLists.txt | 19 +++++- python/aare/__init__.py | 3 + python/examples/play.py | 14 +++++ python/src/file.hpp | 126 +++++++++++++++++++++++++++++++++++++++ python/src/module.cpp | 7 ++- python/src/np_helper.hpp | 115 +++++++++++++++++++++++++++++++++++ src/File.cpp | 1 + 8 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 python/aare/__init__.py create mode 100644 python/examples/play.py create mode 100644 python/src/file.hpp create mode 100644 python/src/np_helper.hpp diff --git a/include/aare/File.hpp b/include/aare/File.hpp index 6286cd2..958460c 100644 --- a/include/aare/File.hpp +++ b/include/aare/File.hpp @@ -40,6 +40,7 @@ class File { size_t rows() const; size_t cols() const; size_t bitdepth() const; + size_t bytes_per_pixel() const; void set_total_frames(size_t total_frames); DetectorType detector_type() const; xy geometry() const; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 9dd1e34..98436ac 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -10,8 +10,25 @@ else() endif() -pybind11_add_module(_aare src/module.cpp) +pybind11_add_module( + _aare + src/module.cpp + ) set_target_properties(_aare PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} ) target_link_libraries(_aare PRIVATE aare_core aare_compiler_flags) + +set( PYTHON_FILES + aare/__init__.py +) + +foreach(FILE ${PYTHON_FILES}) + configure_file( ${FILE} + ${CMAKE_BINARY_DIR}/${FILE} ) +endforeach(FILE ${PYTHON_FILES}) + + +configure_file( examples/play.py + ${CMAKE_BINARY_DIR}/play.py +) \ No newline at end of file diff --git a/python/aare/__init__.py b/python/aare/__init__.py new file mode 100644 index 0000000..96b9308 --- /dev/null +++ b/python/aare/__init__.py @@ -0,0 +1,3 @@ + + +from _aare import File \ No newline at end of file diff --git a/python/examples/play.py b/python/examples/play.py new file mode 100644 index 0000000..68efe94 --- /dev/null +++ b/python/examples/play.py @@ -0,0 +1,14 @@ +import matplotlib.pyplot as plt +import numpy as np +plt.ion() + +import aare +from pathlib import Path + +p = Path('/Users/erik/data/aare_test_data/jungfrau/jungfrau_single_master_0.json') + +f = aare.File(p) +frame = f.read_frame() + +fig, ax = plt.subplots() +im = ax.imshow(frame, cmap='viridis') \ No newline at end of file diff --git a/python/src/file.hpp b/python/src/file.hpp new file mode 100644 index 0000000..9324890 --- /dev/null +++ b/python/src/file.hpp @@ -0,0 +1,126 @@ +#include "aare/Frame.hpp" +#include "aare/File.hpp" +#include "aare/defs.hpp" +// #include "aare/fClusterFileV2.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace::aare; + +void define_file_io_bindings(py::module &m) { + py::class_(m, "xy") + .def(py::init<>()) + .def(py::init()) + .def_readwrite("row", &xy::row) + .def_readwrite("col", &xy::col) + .def("__eq__", &xy::operator==) + .def("__ne__", &xy::operator!=) + .def("__repr__", + [](const xy &a) { return ""; }); + + + py::class_(m, "File") + .def(py::init([](const std::filesystem::path &fname) { return File(fname, "r", {}); })) + .def( + py::init([](const std::filesystem::path &fname, const std::string &mode) { return File(fname, mode, {}); })) + .def(py::init()) + // .def("read", py::overload_cast<>(&File::read)) + // .def("read", py::overload_cast(&File::read)) + .def("iread", py::overload_cast(&File::iread),py::call_guard()) + .def("frame_number", &File::frame_number) + .def_property_readonly("bytes_per_frame", &File::bytes_per_frame) + .def_property_readonly("pixels_per_frame", &File::pixels_per_frame) + .def("seek", &File::seek) + .def("tell", &File::tell) + .def_property_readonly("total_frames", &File::total_frames) + .def_property_readonly("rows", &File::rows) + .def_property_readonly("cols", &File::cols) + .def_property_readonly("bitdepth", &File::bitdepth) + .def_property_readonly("detector_type", &File::detector_type) + .def_property_readonly("geometry", &File::geometry, + py::call_guard()) + // .def("set_total_frames", &File::set_total_frames) + .def("read_frame", [](File &self) { + const uint8_t item_size = self.bytes_per_pixel(); + py::array image; + std::vector shape; + shape.reserve(2); + shape.push_back(self.rows()); + shape.push_back(self.cols()); + if (item_size == 1) { + image = py::array_t(shape); + } else if (item_size == 2) { + image = py::array_t(shape); + } else if (item_size == 4) { + image = py::array_t(shape); + } + self.read_into(reinterpret_cast(image.mutable_data())); + return image; + }); + + py::class_(m, "FileConfig") + .def(py::init<>()) + .def_readwrite("rows", &FileConfig::rows) + .def_readwrite("cols", &FileConfig::cols) + .def_readwrite("version", &FileConfig::version) + .def_readwrite("geometry", &FileConfig::geometry) + .def_readwrite("detector_type", &FileConfig::detector_type) + .def_readwrite("max_frames_per_file", &FileConfig::max_frames_per_file) + .def_readwrite("total_frames", &FileConfig::total_frames) + .def_readwrite("dtype", &FileConfig::dtype) + .def("__eq__", &FileConfig::operator==) + .def("__ne__", &FileConfig::operator!=) + .def("__repr__", [](const FileConfig &a) { return ""; }); + + // py::class_(m, "ClusterHeader") + // .def(py::init<>()) + // .def_readwrite("frame_number", &ClusterHeader::frame_number) + // .def_readwrite("n_clusters", &ClusterHeader::n_clusters) + // .def("__repr__", [](const ClusterHeader &a) { return ""; }); + + // py::class_(m, "ClusterV2_") + // .def(py::init<>()) + // .def_readwrite("x", &ClusterV2_::x) + // .def_readwrite("y", &ClusterV2_::y) + // .def_readwrite("data", &ClusterV2_::data) + // .def("__repr__", [](const ClusterV2_ &a) { return ""; }); + + // py::class_(m, "ClusterV2") + // .def(py::init<>()) + // .def_readwrite("cluster", &ClusterV2::cluster) + // .def_readwrite("frame_number", &ClusterV2::frame_number) + // .def("__repr__", [](const ClusterV2 &a) { return ""; }); + + // py::class_(m, "ClusterFileV2") + // .def(py::init()) + // .def("read", py::overload_cast<>(&ClusterFileV2::read)) + // .def("read", py::overload_cast(&ClusterFileV2::read)) + // .def("frame_number", &ClusterFileV2::frame_number) + // .def("write", py::overload_cast const &>(&ClusterFileV2::write)) + + // .def("close", &ClusterFileV2::close); + + // m.def("to_clustV2", [](std::vector &clusters, const int frame_number) { + // std::vector clusters_; + // for (auto &c : clusters) { + // ClusterV2 cluster; + // cluster.cluster.x = c.x; + // cluster.cluster.y = c.y; + // int i=0; + // for(auto &d : cluster.cluster.data) { + // d=c.get(i++); + // } + // cluster.frame_number = frame_number; + // clusters_.push_back(cluster); + // } + // return clusters_; + // }); +} diff --git a/python/src/module.cpp b/python/src/module.cpp index 6379aa2..c6771b7 100644 --- a/python/src/module.cpp +++ b/python/src/module.cpp @@ -1,9 +1,14 @@ - +#include "file.hpp" #include +#include namespace py = pybind11; PYBIND11_MODULE(_aare, m) { + + + + define_file_io_bindings(m); } \ No newline at end of file diff --git a/python/src/np_helper.hpp b/python/src/np_helper.hpp new file mode 100644 index 0000000..3aa24cc --- /dev/null +++ b/python/src/np_helper.hpp @@ -0,0 +1,115 @@ +#pragma once + +#include +#include +#include +#include + +#include "aare/Frame.hpp" +#include "aare/NDArray.hpp" + +namespace py = pybind11; + +// Pass image data back to python as a numpy array +// template +// py::array return_image_data(pl::ImageData *image) { + +// py::capsule free_when_done(image, [](void *f) { +// pl::ImageData *foo = +// reinterpret_cast *>(f); +// delete foo; +// }); + +// return py::array_t( +// image->shape(), // shape +// image->byte_strides(), // C-style contiguous strides for double +// image->data(), // the data pointer +// free_when_done); // numpy array references this parent +// } + +// template py::array return_vector(std::vector *vec) { +// py::capsule free_when_done(vec, [](void *f) { +// std::vector *foo = reinterpret_cast *>(f); +// delete foo; +// }); +// return py::array_t({vec->size()}, // shape +// {sizeof(T)}, // C-style contiguous strides for double +// vec->data(), // the data pointer +// free_when_done); // numpy array references this parent +// } + +// template py::array do_read(Reader &r, size_t n_frames) { +// py::array image; +// if (n_frames == 0) +// n_frames = r.total_frames(); + +// std::array shape{static_cast(n_frames), r.rows(), +// r.cols()}; +// const uint8_t item_size = r.bytes_per_pixel(); +// if (item_size == 1) { +// image = py::array_t( +// shape); +// } else if (item_size == 2) { +// image = +// py::array_t( +// shape); +// } else if (item_size == 4) { +// image = +// py::array_t( +// shape); +// } +// r.read_into(reinterpret_cast(image.mutable_data()), n_frames); +// return image; +// } + +py::array return_frame(pl::Frame *ptr) { + py::capsule free_when_done(ptr, [](void *f) { + pl::Frame *foo = reinterpret_cast(f); + delete foo; + }); + + const uint8_t item_size = ptr->bytes_per_pixel(); + std::vector shape; + for (auto val : ptr->shape()) + if (val > 1) + shape.push_back(val); + + std::vector strides; + if (shape.size() == 1) + strides.push_back(item_size); + else if (shape.size() == 2) { + strides.push_back(item_size * shape[1]); + strides.push_back(item_size); + } + + if (item_size == 1) + return py::array_t( + shape, strides, + reinterpret_cast(ptr->data()), free_when_done); + else if (item_size == 2) + return py::array_t(shape, strides, + reinterpret_cast(ptr->data()), + free_when_done); + else if (item_size == 4) + return py::array_t(shape, strides, + reinterpret_cast(ptr->data()), + free_when_done); + return {}; +} + +// todo rewrite generic +template auto get_shape_3d(py::array_t arr) { + return pl::Shape<3>{arr.shape(0), arr.shape(1), arr.shape(2)}; +} + +template auto make_span_3d(py::array_t arr) { + return pl::DataSpan(arr.mutable_data(), get_shape_3d(arr)); +} + +template auto get_shape_2d(py::array_t arr) { + return pl::Shape<2>{arr.shape(0), arr.shape(1)}; +} + +template auto make_span_2d(py::array_t arr) { + return pl::DataSpan(arr.mutable_data(), get_shape_2d(arr)); +} \ No newline at end of file diff --git a/src/File.cpp b/src/File.cpp index 5a7c198..190b838 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -51,6 +51,7 @@ size_t File::tell() const { return file_impl->tell(); } size_t File::rows() const { return file_impl->rows(); } size_t File::cols() const { return file_impl->cols(); } size_t File::bitdepth() const { return file_impl->bitdepth(); } +size_t File::bytes_per_pixel() const { return file_impl->bitdepth()/8; } void File::set_total_frames(size_t total_frames) { return file_impl->set_total_frames(total_frames); } File::~File() { delete file_impl; } DetectorType File::detector_type() const { return file_impl->detector_type(); }