#include "aare/JungfrauDataFile.hpp" #include "aare/defs.hpp" #include #include #include #include #include #include #include #include namespace py = pybind11; using namespace ::aare; // Disable warnings for unused parameters, as we ignore some // in the __exit__ method #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" auto read_dat_frame(JungfrauDataFile &self) { py::array_t header(1); py::array_t image({ self.rows(), self.cols() }); self.read_into(reinterpret_cast(image.mutable_data()), header.mutable_data()); return py::make_tuple(header, image); } auto read_n_dat_frames(JungfrauDataFile &self, size_t n_frames) { // adjust for actual frames left in the file n_frames = std::min(n_frames, self.total_frames() - self.tell()); if (n_frames == 0) { throw std::runtime_error("No frames left in file"); } py::array_t header(n_frames); py::array_t image({ n_frames, self.rows(), self.cols()}); self.read_into(reinterpret_cast(image.mutable_data()), n_frames, header.mutable_data()); return py::make_tuple(header, image); } void define_jungfrau_data_file_io_bindings(py::module &m) { // Make the JungfrauDataHeader usable from numpy PYBIND11_NUMPY_DTYPE(JungfrauDataHeader, framenum, bunchid); py::class_(m, "JungfrauDataFile") .def(py::init()) .def("seek", &JungfrauDataFile::seek, R"( Seek to the given frame index. )") .def("tell", &JungfrauDataFile::tell, R"( Get the current frame index. )") .def_property_readonly("rows", &JungfrauDataFile::rows) .def_property_readonly("cols", &JungfrauDataFile::cols) .def_property_readonly("base_name", &JungfrauDataFile::base_name) .def_property_readonly("bytes_per_frame", &JungfrauDataFile::bytes_per_frame) .def_property_readonly("pixels_per_frame", &JungfrauDataFile::pixels_per_frame) .def_property_readonly("bytes_per_pixel", &JungfrauDataFile::bytes_per_pixel) .def_property_readonly("bitdepth", &JungfrauDataFile::bitdepth) .def_property_readonly("current_file", &JungfrauDataFile::current_file) .def_property_readonly("total_frames", &JungfrauDataFile::total_frames) .def_property_readonly("n_files", &JungfrauDataFile::n_files) .def("read_frame", &read_dat_frame, R"( Read a single frame from the file. )") .def("read_n", &read_n_dat_frames, R"( Read maximum n_frames frames from the file. )") .def( "read", [](JungfrauDataFile &self) { self.seek(0); auto n_frames = self.total_frames(); return read_n_dat_frames(self, n_frames); }, R"( Read all frames from the file. Seeks to the beginning before reading. )") .def("__enter__", [](JungfrauDataFile &self) { return &self; }) .def("__exit__", [](JungfrauDataFile &self, const std::optional &exc_type, const std::optional &exc_value, const std::optional &traceback) { // self.close(); }) .def("__iter__", [](JungfrauDataFile &self) { return &self; }) .def("__next__", [](JungfrauDataFile &self) { try { return read_dat_frame(self); } catch (std::runtime_error &e) { throw py::stop_iteration(); } }); } #pragma GCC diagnostic pop