mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-06 21:00:41 +02:00
Merge pull request #21 from slsdetectorgroup/feature/frame-wrappers2
Feature/frame wrappers2 (PR#2)
This commit is contained in:
commit
0e3e2df899
@ -17,9 +17,11 @@ endif()
|
|||||||
|
|
||||||
if(AARE_TESTS)
|
if(AARE_TESTS)
|
||||||
set(TestSources
|
set(TestSources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/defs.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ProducerConsumerQueue.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/ProducerConsumerQueue.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/CircularFifo.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/CircularFifo.test.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/wrappers.test.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
target_sources(tests PRIVATE ${TestSources} )
|
target_sources(tests PRIVATE ${TestSources} )
|
||||||
target_link_libraries(tests PRIVATE core)
|
target_link_libraries(tests PRIVATE core)
|
||||||
|
125
core/include/aare/DataSpan.hpp
Normal file
125
core/include/aare/DataSpan.hpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <numeric>
|
||||||
|
#include<aare/Frame.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
template <ssize_t Dim = 0, typename Strides> ssize_t element_offset(const Strides &) { return 0; }
|
||||||
|
|
||||||
|
template <ssize_t Dim = 0, typename Strides, typename... Ix>
|
||||||
|
ssize_t element_offset(const Strides &strides, ssize_t i, Ix... index) {
|
||||||
|
return i * strides[Dim] + element_offset<Dim + 1>(strides, index...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ssize_t Ndim> std::array<ssize_t, Ndim> c_strides(const std::array<ssize_t, Ndim> &shape) {
|
||||||
|
std::array<ssize_t, Ndim> strides;
|
||||||
|
std::fill(strides.begin(), strides.end(), 1);
|
||||||
|
for (ssize_t i = Ndim - 1; i > 0; --i) {
|
||||||
|
strides[i - 1] = strides[i] * shape[i];
|
||||||
|
}
|
||||||
|
return strides;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ssize_t Ndim> std::array<ssize_t, Ndim> make_array(const std::vector<ssize_t> &vec) {
|
||||||
|
assert(vec.size() == Ndim);
|
||||||
|
std::array<ssize_t, Ndim> arr;
|
||||||
|
std::copy_n(vec.begin(), Ndim, arr.begin());
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, ssize_t Ndim> class DataSpan {
|
||||||
|
public:
|
||||||
|
DataSpan(){};
|
||||||
|
|
||||||
|
DataSpan(T* buffer, std::array<ssize_t, Ndim> shape) {
|
||||||
|
buffer_ = buffer;
|
||||||
|
strides_ = c_strides<Ndim>(shape);
|
||||||
|
shape_ = shape;
|
||||||
|
size_ = std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<ssize_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSpan(T *buffer, const std::vector<ssize_t> &shape) {
|
||||||
|
buffer_ = buffer;
|
||||||
|
strides_ = c_strides<Ndim>(make_array<Ndim>(shape));
|
||||||
|
shape_ = make_array<Ndim>(shape);
|
||||||
|
size_ = std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<ssize_t>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSpan(Frame& frame) {
|
||||||
|
assert(Ndim == 2);
|
||||||
|
buffer_ = reinterpret_cast<T*>(frame._get_data());
|
||||||
|
strides_ = c_strides<Ndim>({frame.rows(), frame.cols()});
|
||||||
|
shape_ = {frame.rows(), frame.cols()};
|
||||||
|
size_ = frame.rows() * frame.cols();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type operator()(Ix... index) {
|
||||||
|
return buffer_[element_offset(strides_, index...)];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type operator()(Ix... index) const {
|
||||||
|
return buffer_[element_offset(strides_, index...)];
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t size() const { return size_; }
|
||||||
|
|
||||||
|
DataSpan(const DataSpan &) = default;
|
||||||
|
DataSpan(DataSpan &&) = default;
|
||||||
|
|
||||||
|
T *begin() { return buffer_; }
|
||||||
|
T *end() { return buffer_ + size_; }
|
||||||
|
T &operator()(ssize_t i) { return buffer_[i]; }
|
||||||
|
T &operator[](ssize_t i) { return buffer_[i]; }
|
||||||
|
|
||||||
|
DataSpan &operator+=(const T val) { return elemenwise(val, std::plus<T>()); }
|
||||||
|
DataSpan &operator-=(const T val) { return elemenwise(val, std::minus<T>()); }
|
||||||
|
DataSpan &operator*=(const T val) { return elemenwise(val, std::multiplies<T>()); }
|
||||||
|
DataSpan &operator/=(const T val) { return elemenwise(val, std::divides<T>()); }
|
||||||
|
|
||||||
|
DataSpan &operator/=(const DataSpan &other) { return elemenwise(other, std::divides<T>()); }
|
||||||
|
|
||||||
|
DataSpan &operator=(const T val) {
|
||||||
|
for (auto it = begin(); it != end(); ++it)
|
||||||
|
*it = val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSpan &operator=(const DataSpan &other) {
|
||||||
|
shape_ = other.shape_;
|
||||||
|
strides_ = other.strides_;
|
||||||
|
size_ = other.size_;
|
||||||
|
buffer_ = other.buffer_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
auto &shape() { return shape_; }
|
||||||
|
auto shape(ssize_t i) const { return shape_[i]; }
|
||||||
|
|
||||||
|
T *data() { return buffer_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T *buffer_{nullptr};
|
||||||
|
std::array<ssize_t, Ndim> strides_{};
|
||||||
|
std::array<ssize_t, Ndim> shape_{};
|
||||||
|
ssize_t size_{};
|
||||||
|
|
||||||
|
template <class BinaryOperation> DataSpan &elemenwise(T val, BinaryOperation op) {
|
||||||
|
for (ssize_t i = 0; i != size_; ++i) {
|
||||||
|
buffer_[i] = op(buffer_[i], val);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <class BinaryOperation> DataSpan &elemenwise(const DataSpan &other, BinaryOperation op) {
|
||||||
|
for (ssize_t i = 0; i != size_; ++i) {
|
||||||
|
buffer_[i] = op(buffer_[i], other.buffer_[i]);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template class DataSpan<uint16_t, 2>;
|
||||||
|
|
@ -23,6 +23,8 @@ class Frame {
|
|||||||
Frame(ssize_t rows, ssize_t cols,ssize_t m_bitdepth);
|
Frame(ssize_t rows, ssize_t cols,ssize_t m_bitdepth);
|
||||||
Frame(std::byte *fp, ssize_t rows, ssize_t cols,ssize_t m_bitdepth);
|
Frame(std::byte *fp, ssize_t rows, ssize_t cols,ssize_t m_bitdepth);
|
||||||
std::byte* get(int row, int col);
|
std::byte* get(int row, int col);
|
||||||
|
template <typename T>
|
||||||
|
void set(int row, int col,T data);
|
||||||
// std::vector<std::vector<DataType>> get_array();
|
// std::vector<std::vector<DataType>> get_array();
|
||||||
ssize_t rows() const{
|
ssize_t rows() const{
|
||||||
return m_rows;
|
return m_rows;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "aare/Frame.hpp"
|
#include "aare/Frame.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
Frame::Frame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth):
|
Frame::Frame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth):
|
||||||
m_rows(rows), m_cols(cols), m_bitdepth(bitdepth) {
|
m_rows(rows), m_cols(cols), m_bitdepth(bitdepth) {
|
||||||
m_data = new std::byte[rows*cols*bitdepth/8];
|
m_data = new std::byte[rows*cols*bitdepth/8];
|
||||||
@ -22,6 +22,19 @@ std::byte* Frame::get(int row, int col) {
|
|||||||
return m_data+(row*m_cols + col)*(m_bitdepth/8);
|
return m_data+(row*m_cols + col)*(m_bitdepth/8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Frame::set(int row, int col, T data) {
|
||||||
|
assert(sizeof(T) == m_bitdepth/8);
|
||||||
|
if (row < 0 || row >= m_rows || col < 0 || col >= m_cols) {
|
||||||
|
std::cerr << "Invalid row or column index" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::memcpy(m_data+(row*m_cols + col)*(m_bitdepth/8), &data, m_bitdepth/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
template void Frame::set(int row, int col, uint16_t data);
|
||||||
|
|
||||||
|
|
||||||
// std::vector<std::vector<DataType>> Frame<DataType>::get_array() {
|
// std::vector<std::vector<DataType>> Frame<DataType>::get_array() {
|
||||||
// std::vector<std::vector<DataType>> array;
|
// std::vector<std::vector<DataType>> array;
|
||||||
// for (int i = 0; i < m_rows; i++) {
|
// for (int i = 0; i < m_rows; i++) {
|
||||||
|
49
core/test/wrappers.test.cpp
Normal file
49
core/test/wrappers.test.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <aare/DataSpan.hpp>
|
||||||
|
#include <aare/Frame.hpp>
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
TEST_CASE("Frame") {
|
||||||
|
auto data = new uint16_t[100];
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
data[i] = i;
|
||||||
|
}
|
||||||
|
Frame f(reinterpret_cast<std::byte *>(data), 10, 10, 16);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
REQUIRE((uint16_t)*f.get(i / 10, i % 10) == data[i]);
|
||||||
|
}
|
||||||
|
REQUIRE(f.rows() == 10);
|
||||||
|
REQUIRE(f.cols() == 10);
|
||||||
|
REQUIRE(f.bitdepth() == 16);
|
||||||
|
|
||||||
|
uint16_t i = 44;
|
||||||
|
f.set(0, 0, i);
|
||||||
|
REQUIRE((uint16_t)*f.get(0, 0) == i);
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DataSpan") {
|
||||||
|
auto data = new uint16_t[100];
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
data[i] = i;
|
||||||
|
}
|
||||||
|
SECTION("constructors") {
|
||||||
|
DataSpan<uint16_t, 2> ds(data, std::vector<ssize_t>({10, 10}));
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
REQUIRE(ds(i / 10, i % 10) == data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("from Frame") {
|
||||||
|
Frame f(reinterpret_cast<std::byte *>(data), 10, 10, 16);
|
||||||
|
DataSpan<uint16_t, 2> ds(f);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
REQUIRE(ds(i / 10, i % 10) == data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.set(0, 0, (uint16_t)44);
|
||||||
|
REQUIRE((uint16_t)*f.get(0, 0) == 44); // check that set worked
|
||||||
|
REQUIRE(ds(0, 0) == 44);// check that ds is updated
|
||||||
|
REQUIRE(data[0] == 0); // check that data is not updated
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user