mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-05 12:30:39 +02:00
Merge pull request #52 from slsdetectorgroup/feature/formatting-in-cmake
add formatting as target in cmake
This commit is contained in:
commit
818ad608d9
6
.github/workflows/format.yml
vendored
6
.github/workflows/format.yml
vendored
@ -11,9 +11,13 @@ jobs:
|
||||
# find all examples in build/examples and run them
|
||||
run: |
|
||||
pwd
|
||||
find -name "*.cpp" -not -path "./build/*" | xargs -I {} -n 1 -P 10 clang-format {} -Werror --dry-run -style='file:.clang-format'
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --target=check-format
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -164,3 +164,22 @@ add_subdirectory(examples)
|
||||
if(AARE_PYTHON_BINDINGS)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
|
||||
# custom target to run check formatting with clang-format
|
||||
add_custom_target(
|
||||
check-format
|
||||
COMMAND find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Checking code formatting with clang-format"
|
||||
VERBATIM
|
||||
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
format-files
|
||||
COMMAND find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Formatting with clang-format"
|
||||
VERBATIM
|
||||
)
|
@ -14,29 +14,27 @@ template <class ItemType> class CircularFifo {
|
||||
uint32_t fifo_size;
|
||||
folly::ProducerConsumerQueue<ItemType> free_slots;
|
||||
folly::ProducerConsumerQueue<ItemType> filled_slots;
|
||||
|
||||
|
||||
public:
|
||||
CircularFifo() : CircularFifo(100){};
|
||||
CircularFifo(uint32_t size)
|
||||
: fifo_size(size), free_slots(size+1), filled_slots(size+1) {
|
||||
CircularFifo(uint32_t size) : fifo_size(size), free_slots(size + 1), filled_slots(size + 1) {
|
||||
|
||||
// TODO! how do we deal with alignment for writing? alignas???
|
||||
// Do we give the user a chance to provide memory locations?
|
||||
// Do we give the user a chance to provide memory locations?
|
||||
// Templated allocator?
|
||||
for (size_t i = 0; i < fifo_size; ++i) {
|
||||
free_slots.write(ItemType{});
|
||||
}
|
||||
}
|
||||
|
||||
bool next(){
|
||||
//TODO! avoid default constructing ItemType
|
||||
ItemType it;
|
||||
if(!filled_slots.read(it))
|
||||
return false;
|
||||
if(!free_slots.write(std::move(it)))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
bool next() {
|
||||
// TODO! avoid default constructing ItemType
|
||||
ItemType it;
|
||||
if (!filled_slots.read(it))
|
||||
return false;
|
||||
if (!free_slots.write(std::move(it)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
~CircularFifo() {}
|
||||
@ -47,66 +45,53 @@ template <class ItemType> class CircularFifo {
|
||||
auto numFreeSlots() const noexcept { return free_slots.sizeGuess(); }
|
||||
auto isFull() const noexcept { return filled_slots.isFull(); }
|
||||
|
||||
ItemType pop_free() {
|
||||
ItemType v;
|
||||
while (!free_slots.read(v))
|
||||
;
|
||||
return std::move(v);
|
||||
// return v;
|
||||
}
|
||||
|
||||
bool try_pop_free(ItemType& v){
|
||||
return free_slots.read(v);
|
||||
}
|
||||
|
||||
ItemType pop_value(std::chrono::nanoseconds wait,
|
||||
std::atomic<bool> &stopped) {
|
||||
ItemType v;
|
||||
while (!filled_slots.read(v) && !stopped) {
|
||||
std::this_thread::sleep_for(wait);
|
||||
ItemType pop_free() {
|
||||
ItemType v;
|
||||
while (!free_slots.read(v))
|
||||
;
|
||||
return std::move(v);
|
||||
// return v;
|
||||
}
|
||||
return std::move(v);
|
||||
}
|
||||
|
||||
ItemType pop_value() {
|
||||
ItemType v;
|
||||
while (!filled_slots.read(v))
|
||||
;
|
||||
return std::move(v);
|
||||
}
|
||||
bool try_pop_free(ItemType &v) { return free_slots.read(v); }
|
||||
|
||||
ItemType* frontPtr(){
|
||||
return filled_slots.frontPtr();
|
||||
}
|
||||
ItemType pop_value(std::chrono::nanoseconds wait, std::atomic<bool> &stopped) {
|
||||
ItemType v;
|
||||
while (!filled_slots.read(v) && !stopped) {
|
||||
std::this_thread::sleep_for(wait);
|
||||
}
|
||||
return std::move(v);
|
||||
}
|
||||
|
||||
// TODO! Add function to move item from filled to free to be used
|
||||
// with the frontPtr function
|
||||
ItemType pop_value() {
|
||||
ItemType v;
|
||||
while (!filled_slots.read(v))
|
||||
;
|
||||
return std::move(v);
|
||||
}
|
||||
|
||||
ItemType *frontPtr() { return filled_slots.frontPtr(); }
|
||||
|
||||
template <class... Args>
|
||||
void push_value(Args&&... recordArgs) {
|
||||
while (!filled_slots.write(std::forward<Args>(recordArgs)...))
|
||||
;
|
||||
}
|
||||
// TODO! Add function to move item from filled to free to be used
|
||||
// with the frontPtr function
|
||||
|
||||
template <class... Args>
|
||||
bool try_push_value(Args&&... recordArgs) {
|
||||
return filled_slots.write(std::forward<Args>(recordArgs)...);
|
||||
template <class... Args> void push_value(Args &&...recordArgs) {
|
||||
while (!filled_slots.write(std::forward<Args>(recordArgs)...))
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
template <class... Args> bool try_push_value(Args &&...recordArgs) {
|
||||
return filled_slots.write(std::forward<Args>(recordArgs)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void push_free(Args&&... recordArgs) {
|
||||
while (!free_slots.write(std::forward<Args>(recordArgs)...))
|
||||
;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
bool try_push_free(Args&&... recordArgs) {
|
||||
return free_slots.write(std::forward<Args>(recordArgs)...);
|
||||
|
||||
}
|
||||
template <class... Args> void push_free(Args &&...recordArgs) {
|
||||
while (!free_slots.write(std::forward<Args>(recordArgs)...))
|
||||
;
|
||||
}
|
||||
|
||||
template <class... Args> bool try_push_free(Args &&...recordArgs) {
|
||||
return free_slots.write(std::forward<Args>(recordArgs)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -19,7 +19,7 @@ enum class endian {
|
||||
};
|
||||
|
||||
class DType {
|
||||
//TODO! support for non native endianess?
|
||||
// TODO! support for non native endianess?
|
||||
static_assert(sizeof(long) == sizeof(int64_t), "long should be 64bits");
|
||||
|
||||
public:
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
@ -27,15 +26,13 @@ class Frame {
|
||||
Frame(std::byte *fp, ssize_t rows, ssize_t cols, ssize_t m_bitdepth);
|
||||
std::byte *get(int row, int col);
|
||||
|
||||
|
||||
//TODO! can we, or even want to remove the template?
|
||||
template <typename T>
|
||||
void set(int row, int col, T data) {
|
||||
assert(sizeof(T) == m_bitdepth/8);
|
||||
// TODO! can we, or even want to remove the template?
|
||||
template <typename T> void set(int row, int col, T data) {
|
||||
assert(sizeof(T) == m_bitdepth / 8);
|
||||
if (row < 0 || row >= m_rows || col < 0 || col >= m_cols) {
|
||||
throw std::out_of_range("Invalid row or column index");
|
||||
}
|
||||
std::memcpy(m_data+(row*m_cols + col)*(m_bitdepth/8), &data, m_bitdepth/8);
|
||||
std::memcpy(m_data + (row * m_cols + col) * (m_bitdepth / 8), &data, m_bitdepth / 8);
|
||||
}
|
||||
|
||||
ssize_t rows() const { return m_rows; }
|
||||
@ -43,7 +40,7 @@ class Frame {
|
||||
ssize_t bitdepth() const { return m_bitdepth; }
|
||||
ssize_t size() const { return m_rows * m_cols * m_bitdepth / 8; }
|
||||
std::byte *data() const { return m_data; }
|
||||
|
||||
|
||||
Frame &operator=(Frame &other) {
|
||||
m_rows = other.rows();
|
||||
m_cols = other.cols();
|
||||
@ -62,20 +59,15 @@ class Frame {
|
||||
other.m_rows = other.m_cols = other.m_bitdepth = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NDView<T> view() {
|
||||
template <typename T> NDView<T> view() {
|
||||
std::vector<ssize_t> shape = {m_rows, m_cols};
|
||||
T* data = reinterpret_cast<T *>(m_data);
|
||||
T *data = reinterpret_cast<T *>(m_data);
|
||||
return NDView<T>(data, shape);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NDArray<T> image() {
|
||||
return NDArray<T>(this->view<T>());
|
||||
}
|
||||
template <typename T> NDArray<T> image() { return NDArray<T>(this->view<T>()); }
|
||||
|
||||
~Frame() { delete[] m_data; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace aare
|
@ -22,31 +22,24 @@ namespace aare {
|
||||
|
||||
template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
public:
|
||||
NDArray()
|
||||
: shape_(), strides_(c_strides<Ndim>(shape_)), size_(0),
|
||||
data_(nullptr){};
|
||||
NDArray() : shape_(), strides_(c_strides<Ndim>(shape_)), size_(0), data_(nullptr){};
|
||||
|
||||
explicit NDArray(std::array<ssize_t, Ndim> shape)
|
||||
: shape_(shape), strides_(c_strides<Ndim>(shape_)),
|
||||
size_(std::accumulate(shape_.begin(), shape_.end(), 1,
|
||||
std::multiplies<ssize_t>())),
|
||||
data_(new T[size_]){};
|
||||
size_(std::accumulate(shape_.begin(), shape_.end(), 1, std::multiplies<ssize_t>())), data_(new T[size_]){};
|
||||
|
||||
NDArray(std::array<ssize_t, Ndim> shape, T value) : NDArray(shape) {
|
||||
this->operator=(value);
|
||||
}
|
||||
NDArray(std::array<ssize_t, Ndim> shape, T value) : NDArray(shape) { this->operator=(value); }
|
||||
|
||||
/* When constructing from a NDView we need to copy the data since
|
||||
NDArray expect to own its data, and span is just a view*/
|
||||
NDArray(NDView<T, Ndim> span):NDArray(span.shape()){
|
||||
NDArray(NDView<T, Ndim> span) : NDArray(span.shape()) {
|
||||
std::copy(span.begin(), span.end(), begin());
|
||||
// fmt::print("NDArray(NDView<T, Ndim> span)\n");
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
NDArray(NDArray &&other)
|
||||
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
|
||||
size_(other.size_), data_(nullptr) {
|
||||
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)), size_(other.size_), data_(nullptr) {
|
||||
data_ = other.data_;
|
||||
other.reset();
|
||||
// fmt::print("NDArray(NDArray &&other)\n");
|
||||
@ -54,20 +47,17 @@ template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
|
||||
// Copy constructor
|
||||
NDArray(const NDArray &other)
|
||||
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
|
||||
size_(other.size_), data_(new T[size_]) {
|
||||
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)), size_(other.size_), data_(new T[size_]) {
|
||||
std::copy(other.data_, other.data_ + size_, data_);
|
||||
// fmt::print("NDArray(const NDArray &other)\n");
|
||||
}
|
||||
|
||||
~NDArray() {
|
||||
delete[] data_;
|
||||
}
|
||||
~NDArray() { delete[] data_; }
|
||||
|
||||
auto begin() { return data_; }
|
||||
auto end() { return data_ + size_; }
|
||||
|
||||
using value_type = T;
|
||||
using value_type = T;
|
||||
|
||||
NDArray &operator=(NDArray &&other); // Move assign
|
||||
NDArray &operator=(const NDArray &other); // Copy assign
|
||||
@ -80,8 +70,7 @@ template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
NDArray &operator*=(const NDArray &other);
|
||||
NDArray operator/(const NDArray &other);
|
||||
// NDArray& operator/=(const NDArray& other);
|
||||
template <typename V>
|
||||
NDArray &operator/=(const NDArray<V, Ndim> &other) {
|
||||
template <typename V> NDArray &operator/=(const NDArray<V, Ndim> &other) {
|
||||
// check shape
|
||||
if (shape_ == other.shape()) {
|
||||
for (int i = 0; i < size_; ++i) {
|
||||
@ -118,21 +107,15 @@ template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
|
||||
NDArray &operator++(); // pre inc
|
||||
|
||||
template <typename... Ix>
|
||||
typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type
|
||||
operator()(Ix... index) {
|
||||
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type operator()(Ix... index) {
|
||||
return data_[element_offset(strides_, index...)];
|
||||
}
|
||||
|
||||
template <typename... Ix>
|
||||
typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type
|
||||
operator()(Ix... index) const{
|
||||
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type operator()(Ix... index) const {
|
||||
return data_[element_offset(strides_, index...)];
|
||||
}
|
||||
|
||||
|
||||
template <typename... Ix>
|
||||
typename std::enable_if<sizeof...(Ix) == Ndim, T>::type value(Ix... index) {
|
||||
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T>::type value(Ix... index) {
|
||||
return data_[element_offset(strides_, index...)];
|
||||
}
|
||||
|
||||
@ -142,7 +125,7 @@ template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
T *data() { return data_; }
|
||||
std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); }
|
||||
ssize_t size() const { return size_; }
|
||||
size_t total_bytes() const {return size_*sizeof(T);}
|
||||
size_t total_bytes() const { return size_ * sizeof(T); }
|
||||
std::array<ssize_t, Ndim> shape() const noexcept { return shape_; }
|
||||
ssize_t shape(ssize_t i) const noexcept { return shape_[i]; }
|
||||
std::array<ssize_t, Ndim> strides() const noexcept { return strides_; }
|
||||
@ -175,8 +158,7 @@ template <typename T, ssize_t Ndim = 2> class NDArray {
|
||||
};
|
||||
|
||||
// Move assign
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) {
|
||||
if (this != &other) {
|
||||
delete[] data_;
|
||||
data_ = other.data_;
|
||||
@ -188,15 +170,12 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const NDArray &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const NDArray &other) {
|
||||
NDArray result(*this);
|
||||
result += other;
|
||||
return result;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &
|
||||
NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
||||
// check shape
|
||||
if (shape_ == other.shape_) {
|
||||
for (int i = 0; i < size_; ++i) {
|
||||
@ -208,16 +187,13 @@ NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const NDArray &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const NDArray &other) {
|
||||
NDArray result{*this};
|
||||
result -= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &
|
||||
NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
||||
// check shape
|
||||
if (shape_ == other.shape_) {
|
||||
for (int i = 0; i < size_; ++i) {
|
||||
@ -228,16 +204,13 @@ NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
||||
throw(std::runtime_error("Shape of ImageDatas must match"));
|
||||
}
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const NDArray &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const NDArray &other) {
|
||||
NDArray result = *this;
|
||||
result *= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &
|
||||
NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
||||
// check shape
|
||||
if (shape_ == other.shape_) {
|
||||
for (int i = 0; i < size_; ++i) {
|
||||
@ -249,15 +222,13 @@ NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const NDArray &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const NDArray &other) {
|
||||
NDArray result = *this;
|
||||
result /= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
*it &= mask;
|
||||
return *this;
|
||||
@ -278,8 +249,7 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
|
||||
// }
|
||||
// }
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
||||
if (shape_ == other.shape_) {
|
||||
NDArray<bool> result{shape_};
|
||||
for (int i = 0; i < size_; ++i) {
|
||||
@ -291,9 +261,7 @@ NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &
|
||||
NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
||||
if (this != &other) {
|
||||
delete[] data_;
|
||||
shape_ = other.shape_;
|
||||
@ -305,8 +273,7 @@ NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
||||
template <typename T, ssize_t Ndim> bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
||||
if (shape_ != other.shape_)
|
||||
return false;
|
||||
|
||||
@ -317,68 +284,57 @@ bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
bool NDArray<T, Ndim>::operator!=(const NDArray<T, Ndim> &other) const {
|
||||
template <typename T, ssize_t Ndim> bool NDArray<T, Ndim>::operator!=(const NDArray<T, Ndim> &other) const {
|
||||
return !((*this) == other);
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator++() {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator++() {
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i] += 1;
|
||||
return *this;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const T &value) {
|
||||
std::fill_n(data_, size_, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const T &value) {
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i] += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const T &value) {
|
||||
NDArray result = *this;
|
||||
result += value;
|
||||
return result;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const T &value) {
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i] -= value;
|
||||
return *this;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const T &value) {
|
||||
NDArray result = *this;
|
||||
result -= value;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator/=(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator/=(const T &value) {
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i] /= value;
|
||||
return *this;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const T &value) {
|
||||
NDArray result = *this;
|
||||
result /= value;
|
||||
return result;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const T &value) {
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i] *= value;
|
||||
return *this;
|
||||
}
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const T &value) {
|
||||
template <typename T, ssize_t Ndim> NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const T &value) {
|
||||
NDArray result = *this;
|
||||
result *= value;
|
||||
return result;
|
||||
@ -408,8 +364,7 @@ template <typename T, ssize_t Ndim> void NDArray<T, Ndim>::Print_some() {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
void save(NDArray<T, Ndim> &img, std::string pathname) {
|
||||
template <typename T, ssize_t Ndim> void save(NDArray<T, Ndim> &img, std::string pathname) {
|
||||
std::ofstream f;
|
||||
f.open(pathname, std::ios::binary);
|
||||
f.write(img.buffer(), img.size() * sizeof(T));
|
||||
@ -417,8 +372,7 @@ void save(NDArray<T, Ndim> &img, std::string pathname) {
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
NDArray<T, Ndim> load(const std::string &pathname,
|
||||
std::array<ssize_t, Ndim> shape) {
|
||||
NDArray<T, Ndim> load(const std::string &pathname, std::array<ssize_t, Ndim> shape) {
|
||||
NDArray<T, Ndim> img{shape};
|
||||
std::ifstream f;
|
||||
f.open(pathname, std::ios::binary);
|
||||
@ -427,5 +381,4 @@ NDArray<T, Ndim> load(const std::string &pathname,
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
} // namespace aare
|
@ -4,17 +4,16 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace aare {
|
||||
|
||||
template <ssize_t Ndim> using Shape = std::array<ssize_t, Ndim>;
|
||||
|
||||
//TODO! fix mismatch between signed and unsigned
|
||||
template <ssize_t Ndim>
|
||||
Shape<Ndim> make_shape(const std::vector<size_t>& shape){
|
||||
if(shape.size() != Ndim)
|
||||
// TODO! fix mismatch between signed and unsigned
|
||||
template <ssize_t Ndim> Shape<Ndim> make_shape(const std::vector<size_t> &shape) {
|
||||
if (shape.size() != Ndim)
|
||||
throw std::runtime_error("Shape size mismatch");
|
||||
Shape<Ndim> arr;
|
||||
std::copy_n(shape.begin(), Ndim, arr.begin());
|
||||
@ -44,11 +43,11 @@ template <ssize_t Ndim> std::array<ssize_t, Ndim> make_array(const std::vector<s
|
||||
return arr;
|
||||
}
|
||||
|
||||
template <typename T, ssize_t Ndim=2> class NDView {
|
||||
template <typename T, ssize_t Ndim = 2> class NDView {
|
||||
public:
|
||||
NDView(){};
|
||||
|
||||
NDView(T* buffer, std::array<ssize_t, Ndim> shape) {
|
||||
NDView(T *buffer, std::array<ssize_t, Ndim> shape) {
|
||||
buffer_ = buffer;
|
||||
strides_ = c_strides<Ndim>(shape);
|
||||
shape_ = shape;
|
||||
@ -60,7 +59,6 @@ template <typename T, ssize_t Ndim=2> class NDView {
|
||||
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>());
|
||||
|
||||
}
|
||||
|
||||
template <typename... Ix> typename std::enable_if<sizeof...(Ix) == Ndim, T &>::type operator()(Ix... index) {
|
||||
|
@ -31,158 +31,151 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
constexpr std::size_t hardware_destructive_interference_size = 128;
|
||||
constexpr std::size_t hardware_destructive_interference_size = 128;
|
||||
namespace folly {
|
||||
|
||||
/*
|
||||
* ProducerConsumerQueue is a one producer and one consumer queue
|
||||
* without locks.
|
||||
*/
|
||||
template <class T>
|
||||
struct ProducerConsumerQueue {
|
||||
typedef T value_type;
|
||||
template <class T> struct ProducerConsumerQueue {
|
||||
typedef T value_type;
|
||||
|
||||
ProducerConsumerQueue(const ProducerConsumerQueue&) = delete;
|
||||
ProducerConsumerQueue& operator=(const ProducerConsumerQueue&) = delete;
|
||||
ProducerConsumerQueue(const ProducerConsumerQueue &) = delete;
|
||||
ProducerConsumerQueue &operator=(const ProducerConsumerQueue &) = delete;
|
||||
|
||||
// size must be >= 2.
|
||||
//
|
||||
// Also, note that the number of usable slots in the queue at any
|
||||
// given time is actually (size-1), so if you start with an empty queue,
|
||||
// isFull() will return true after size-1 insertions.
|
||||
explicit ProducerConsumerQueue(uint32_t size)
|
||||
: size_(size),
|
||||
records_(static_cast<T*>(std::malloc(sizeof(T) * size))),
|
||||
readIndex_(0),
|
||||
writeIndex_(0) {
|
||||
assert(size >= 2);
|
||||
if (!records_) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
~ProducerConsumerQueue() {
|
||||
// We need to destruct anything that may still exist in our queue.
|
||||
// (No real synchronization needed at destructor time: only one
|
||||
// thread can be doing this.)
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
size_t readIndex = readIndex_;
|
||||
size_t endIndex = writeIndex_;
|
||||
while (readIndex != endIndex) {
|
||||
records_[readIndex].~T();
|
||||
if (++readIndex == size_) {
|
||||
readIndex = 0;
|
||||
// size must be >= 2.
|
||||
//
|
||||
// Also, note that the number of usable slots in the queue at any
|
||||
// given time is actually (size-1), so if you start with an empty queue,
|
||||
// isFull() will return true after size-1 insertions.
|
||||
explicit ProducerConsumerQueue(uint32_t size)
|
||||
: size_(size), records_(static_cast<T *>(std::malloc(sizeof(T) * size))), readIndex_(0), writeIndex_(0) {
|
||||
assert(size >= 2);
|
||||
if (!records_) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::free(records_);
|
||||
}
|
||||
~ProducerConsumerQueue() {
|
||||
// We need to destruct anything that may still exist in our queue.
|
||||
// (No real synchronization needed at destructor time: only one
|
||||
// thread can be doing this.)
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
size_t readIndex = readIndex_;
|
||||
size_t endIndex = writeIndex_;
|
||||
while (readIndex != endIndex) {
|
||||
records_[readIndex].~T();
|
||||
if (++readIndex == size_) {
|
||||
readIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
bool write(Args&&... recordArgs) {
|
||||
auto const currentWrite = writeIndex_.load(std::memory_order_relaxed);
|
||||
auto nextRecord = currentWrite + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
}
|
||||
if (nextRecord != readIndex_.load(std::memory_order_acquire)) {
|
||||
new (&records_[currentWrite]) T(std::forward<Args>(recordArgs)...);
|
||||
writeIndex_.store(nextRecord, std::memory_order_release);
|
||||
return true;
|
||||
std::free(records_);
|
||||
}
|
||||
|
||||
// queue is full
|
||||
return false;
|
||||
}
|
||||
template <class... Args> bool write(Args &&...recordArgs) {
|
||||
auto const currentWrite = writeIndex_.load(std::memory_order_relaxed);
|
||||
auto nextRecord = currentWrite + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
}
|
||||
if (nextRecord != readIndex_.load(std::memory_order_acquire)) {
|
||||
new (&records_[currentWrite]) T(std::forward<Args>(recordArgs)...);
|
||||
writeIndex_.store(nextRecord, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
// move (or copy) the value at the front of the queue to given variable
|
||||
bool read(T& record) {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
if (currentRead == writeIndex_.load(std::memory_order_acquire)) {
|
||||
// queue is empty
|
||||
return false;
|
||||
// queue is full
|
||||
return false;
|
||||
}
|
||||
|
||||
auto nextRecord = currentRead + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
// move (or copy) the value at the front of the queue to given variable
|
||||
bool read(T &record) {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
if (currentRead == writeIndex_.load(std::memory_order_acquire)) {
|
||||
// queue is empty
|
||||
return false;
|
||||
}
|
||||
|
||||
auto nextRecord = currentRead + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
}
|
||||
record = std::move(records_[currentRead]);
|
||||
records_[currentRead].~T();
|
||||
readIndex_.store(nextRecord, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
record = std::move(records_[currentRead]);
|
||||
records_[currentRead].~T();
|
||||
readIndex_.store(nextRecord, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
// pointer to the value at the front of the queue (for use in-place) or
|
||||
// nullptr if empty.
|
||||
T* frontPtr() {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
if (currentRead == writeIndex_.load(std::memory_order_acquire)) {
|
||||
// queue is empty
|
||||
return nullptr;
|
||||
// pointer to the value at the front of the queue (for use in-place) or
|
||||
// nullptr if empty.
|
||||
T *frontPtr() {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
if (currentRead == writeIndex_.load(std::memory_order_acquire)) {
|
||||
// queue is empty
|
||||
return nullptr;
|
||||
}
|
||||
return &records_[currentRead];
|
||||
}
|
||||
return &records_[currentRead];
|
||||
}
|
||||
|
||||
// queue must not be empty
|
||||
void popFront() {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
assert(currentRead != writeIndex_.load(std::memory_order_acquire));
|
||||
// queue must not be empty
|
||||
void popFront() {
|
||||
auto const currentRead = readIndex_.load(std::memory_order_relaxed);
|
||||
assert(currentRead != writeIndex_.load(std::memory_order_acquire));
|
||||
|
||||
auto nextRecord = currentRead + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
auto nextRecord = currentRead + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
}
|
||||
records_[currentRead].~T();
|
||||
readIndex_.store(nextRecord, std::memory_order_release);
|
||||
}
|
||||
records_[currentRead].~T();
|
||||
readIndex_.store(nextRecord, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return readIndex_.load(std::memory_order_acquire) ==
|
||||
writeIndex_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
bool isFull() const {
|
||||
auto nextRecord = writeIndex_.load(std::memory_order_acquire) + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
bool isEmpty() const {
|
||||
return readIndex_.load(std::memory_order_acquire) == writeIndex_.load(std::memory_order_acquire);
|
||||
}
|
||||
if (nextRecord != readIndex_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
|
||||
bool isFull() const {
|
||||
auto nextRecord = writeIndex_.load(std::memory_order_acquire) + 1;
|
||||
if (nextRecord == size_) {
|
||||
nextRecord = 0;
|
||||
}
|
||||
if (nextRecord != readIndex_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
// queue is full
|
||||
return true;
|
||||
}
|
||||
// queue is full
|
||||
return true;
|
||||
}
|
||||
|
||||
// * If called by consumer, then true size may be more (because producer may
|
||||
// be adding items concurrently).
|
||||
// * If called by producer, then true size may be less (because consumer may
|
||||
// be removing items concurrently).
|
||||
// * It is undefined to call this from any other thread.
|
||||
size_t sizeGuess() const {
|
||||
int ret = writeIndex_.load(std::memory_order_acquire) -
|
||||
readIndex_.load(std::memory_order_acquire);
|
||||
if (ret < 0) {
|
||||
ret += size_;
|
||||
// * If called by consumer, then true size may be more (because producer may
|
||||
// be adding items concurrently).
|
||||
// * If called by producer, then true size may be less (because consumer may
|
||||
// be removing items concurrently).
|
||||
// * It is undefined to call this from any other thread.
|
||||
size_t sizeGuess() const {
|
||||
int ret = writeIndex_.load(std::memory_order_acquire) - readIndex_.load(std::memory_order_acquire);
|
||||
if (ret < 0) {
|
||||
ret += size_;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// maximum number of items in the queue.
|
||||
size_t capacity() const { return size_ - 1; }
|
||||
// maximum number of items in the queue.
|
||||
size_t capacity() const { return size_ - 1; }
|
||||
|
||||
private:
|
||||
using AtomicIndex = std::atomic<unsigned int>;
|
||||
private:
|
||||
using AtomicIndex = std::atomic<unsigned int>;
|
||||
|
||||
char pad0_[hardware_destructive_interference_size];
|
||||
const uint32_t size_;
|
||||
T* const records_;
|
||||
char pad0_[hardware_destructive_interference_size];
|
||||
const uint32_t size_;
|
||||
T *const records_;
|
||||
|
||||
alignas(hardware_destructive_interference_size) AtomicIndex readIndex_;
|
||||
alignas(hardware_destructive_interference_size) AtomicIndex writeIndex_;
|
||||
alignas(hardware_destructive_interference_size) AtomicIndex readIndex_;
|
||||
alignas(hardware_destructive_interference_size) AtomicIndex writeIndex_;
|
||||
|
||||
char pad1_[hardware_destructive_interference_size - sizeof(AtomicIndex)];
|
||||
char pad1_[hardware_destructive_interference_size - sizeof(AtomicIndex)];
|
||||
};
|
||||
|
||||
} // namespace folly
|
@ -5,7 +5,6 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "aare/NDArray.hpp"
|
||||
|
||||
const int MAX_CLUSTER_SIZE = 200;
|
||||
@ -23,9 +22,9 @@ template <typename T> class ClusterFinder {
|
||||
|
||||
// std::vector<int16_t> rows{};
|
||||
// std::vector<int16_t> cols{};
|
||||
int16_t rows[MAX_CLUSTER_SIZE]={0};
|
||||
int16_t cols[MAX_CLUSTER_SIZE]={0};
|
||||
double enes[MAX_CLUSTER_SIZE]={0};
|
||||
int16_t rows[MAX_CLUSTER_SIZE] = {0};
|
||||
int16_t cols[MAX_CLUSTER_SIZE] = {0};
|
||||
double enes[MAX_CLUSTER_SIZE] = {0};
|
||||
};
|
||||
|
||||
private:
|
||||
@ -39,11 +38,11 @@ template <typename T> class ClusterFinder {
|
||||
bool use_noise_map = false;
|
||||
int peripheralThresholdFactor_ = 5;
|
||||
int current_label;
|
||||
const std::array<int, 4> di{{0, -1, -1, -1}}; // row ### 8-neighbour by scaning from left to right
|
||||
const std::array<int, 4> dj{{-1, -1, 0, 1}}; // col ### 8-neighbour by scaning from top to bottom
|
||||
const std::array<int, 4> di{{0, -1, -1, -1}}; // row ### 8-neighbour by scaning from left to right
|
||||
const std::array<int, 4> dj{{-1, -1, 0, 1}}; // col ### 8-neighbour by scaning from top to bottom
|
||||
const std::array<int, 8> di_{{0, 0, -1, 1, -1, 1, -1, 1}}; // row
|
||||
const std::array<int, 8> dj_{{-1, 1, 0, 0, 1, -1, -1, 1}}; // col
|
||||
std::map<int, int> child; // heirachy: key: child; val: parent
|
||||
const std::array<int, 8> dj_{{-1, 1, 0, 0, 1, -1, -1, 1}}; // col
|
||||
std::map<int, int> child; // heirachy: key: child; val: parent
|
||||
std::unordered_map<int, Hit> h_size;
|
||||
std::vector<Hit> hits;
|
||||
// std::vector<std::vector<int16_t>> row
|
||||
@ -51,14 +50,16 @@ template <typename T> class ClusterFinder {
|
||||
|
||||
public:
|
||||
ClusterFinder(image_shape shape, T threshold)
|
||||
: shape_(shape), labeled_(shape, 0), peripheral_labeled_(shape, 0), binary_(shape),
|
||||
threshold_(threshold) {
|
||||
: shape_(shape), labeled_(shape, 0), peripheral_labeled_(shape, 0), binary_(shape), threshold_(threshold) {
|
||||
hits.reserve(2000);
|
||||
}
|
||||
|
||||
NDArray<int, 2> labeled() { return labeled_; }
|
||||
|
||||
void set_noiseMap(NDView<T, 2> noise_map) { noiseMap = noise_map; use_noise_map = true; }
|
||||
void set_noiseMap(NDView<T, 2> noise_map) {
|
||||
noiseMap = noise_map;
|
||||
use_noise_map = true;
|
||||
}
|
||||
void set_peripheralThresholdFactor(int factor) { peripheralThresholdFactor_ = factor; }
|
||||
void find_clusters(NDView<T, 2> img);
|
||||
void find_clusters_X(NDView<T, 2> img);
|
||||
@ -81,8 +82,8 @@ template <typename T> class ClusterFinder {
|
||||
fmt::print("{} -> {}\n", it->first, it->second);
|
||||
}
|
||||
}
|
||||
size_t total_clusters() const{
|
||||
//TODO! fix for stealing
|
||||
size_t total_clusters() const {
|
||||
// TODO! fix for stealing
|
||||
return hits.size();
|
||||
}
|
||||
|
||||
@ -103,8 +104,8 @@ template <typename T> class ClusterFinder {
|
||||
auto old = it->second;
|
||||
it->second = to;
|
||||
add_link(old, to);
|
||||
}else{
|
||||
//found value is smaller than what we want to link
|
||||
} else {
|
||||
// found value is smaller than what we want to link
|
||||
add_link(to, it->second);
|
||||
}
|
||||
}
|
||||
@ -117,7 +118,7 @@ template <typename T> int ClusterFinder<T>::check_neighbours(int i, int j) {
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
const auto row = i + di[k];
|
||||
const auto col = j + dj[k];
|
||||
if (row >= 0 && col >= 0 && row<shape_[0] && col < shape_[1]) {
|
||||
if (row >= 0 && col >= 0 && row < shape_[0] && col < shape_[1]) {
|
||||
auto tmp = labeled_.value(i + di[k], j + dj[k]);
|
||||
if (tmp != 0)
|
||||
neighbour_labels.push_back(tmp);
|
||||
@ -139,8 +140,7 @@ template <typename T> int ClusterFinder<T>::check_neighbours(int i, int j) {
|
||||
auto next = current + 1;
|
||||
add_link(*current, *next);
|
||||
}
|
||||
return neighbour_labels.back(); //already sorted
|
||||
|
||||
return neighbour_labels.back(); // already sorted
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ template <typename T> void ClusterFinder<T>::find_clusters_X(NDView<T, 2> img) {
|
||||
for (int i = 0; i < shape_[0]; ++i) {
|
||||
for (int j = 0; j < shape_[1]; ++j) {
|
||||
if (use_noise_map)
|
||||
threshold_ = 5*noiseMap(i, j);
|
||||
threshold_ = 5 * noiseMap(i, j);
|
||||
if (original_(i, j) > threshold_) {
|
||||
// printf("========== Cluster index: %d\n", clusterIndex);
|
||||
rec_FillHit(clusterIndex, i, j);
|
||||
@ -178,7 +178,7 @@ template <typename T> void ClusterFinder<T>::find_clusters_X(NDView<T, 2> img) {
|
||||
template <typename T> void ClusterFinder<T>::rec_FillHit(int clusterIndex, int i, int j) {
|
||||
// printf("original_(%d, %d)=%f\n", i, j, original_(i,j));
|
||||
// printf("h_size[%d].size=%d\n", clusterIndex, h_size[clusterIndex].size);
|
||||
if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE){
|
||||
if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE) {
|
||||
h_size[clusterIndex].rows[h_size[clusterIndex].size] = i;
|
||||
h_size[clusterIndex].cols[h_size[clusterIndex].size] = j;
|
||||
h_size[clusterIndex].enes[h_size[clusterIndex].size] = original_(i, j);
|
||||
@ -197,11 +197,10 @@ template <typename T> void ClusterFinder<T>::rec_FillHit(int clusterIndex, int i
|
||||
const auto col = j + dj_[k];
|
||||
if (row >= 0 && col >= 0 && row < shape_[0] && col < shape_[1]) {
|
||||
if (use_noise_map)
|
||||
threshold_ = peripheralThresholdFactor_*noiseMap(row, col);
|
||||
if (original_(row, col) > threshold_){
|
||||
threshold_ = peripheralThresholdFactor_ * noiseMap(row, col);
|
||||
if (original_(row, col) > threshold_) {
|
||||
rec_FillHit(clusterIndex, row, col);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
// if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE){
|
||||
// h_size[clusterIndex].size += 1;
|
||||
// h_size[clusterIndex].rows[h_size[clusterIndex].size] = row;
|
||||
@ -229,7 +228,7 @@ template <typename T> void ClusterFinder<T>::first_pass() {
|
||||
|
||||
for (int i = 0; i < original_.size(); ++i) {
|
||||
if (use_noise_map)
|
||||
threshold_ = 5*noiseMap(i);
|
||||
threshold_ = 5 * noiseMap(i);
|
||||
binary_(i) = (original_(i) > threshold_);
|
||||
}
|
||||
|
||||
@ -258,8 +257,8 @@ template <typename T> void ClusterFinder<T>::second_pass() {
|
||||
while (it != child.end()) {
|
||||
current_label = it->second;
|
||||
it = child.find(current_label);
|
||||
//do this once before doing the second pass?
|
||||
//all values point to the final one...
|
||||
// do this once before doing the second pass?
|
||||
// all values point to the final one...
|
||||
}
|
||||
labeled_(i) = current_label;
|
||||
}
|
||||
@ -280,14 +279,13 @@ template <typename T> void ClusterFinder<T>::store_clusters() {
|
||||
// (j-1 >= 0 and labeled_(i, j-1) != 0) or
|
||||
// (i+1 < shape_[0] and labeled_(i+1, j) != 0) or
|
||||
// (j+1 < shape_[1] and labeled_(i, j+1) != 0)
|
||||
){
|
||||
) {
|
||||
Hit &record = h_size[labeled_(i, j)];
|
||||
if (record.size < MAX_CLUSTER_SIZE){
|
||||
if (record.size < MAX_CLUSTER_SIZE) {
|
||||
record.rows[record.size] = i;
|
||||
record.cols[record.size] = j;
|
||||
record.enes[record.size] = original_(i, j);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
record.size += 1;
|
||||
@ -301,10 +299,9 @@ template <typename T> void ClusterFinder<T>::store_clusters() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (const auto &h : h_size)
|
||||
hits.push_back(h.second);
|
||||
|
||||
}
|
||||
|
||||
} // namespace aare
|
||||
|
@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
// Socket to receive data from a ZMQ publisher
|
||||
// needs to be in sync with the main library (or maybe better use the versioning in the header)
|
||||
@ -12,7 +11,7 @@
|
||||
// forward declare zmq_msg_t to avoid including zmq.h in the header
|
||||
class zmq_msg_t;
|
||||
|
||||
namespace aare{
|
||||
namespace aare {
|
||||
|
||||
/** zmq header structure (from slsDetectorPackage)*/
|
||||
struct zmqHeader {
|
||||
@ -65,24 +64,23 @@ struct zmqHeader {
|
||||
std::array<int, 4> rx_roi{};
|
||||
};
|
||||
|
||||
|
||||
class ZmqSocket{
|
||||
class ZmqSocket {
|
||||
void *m_context{nullptr};
|
||||
void *m_socket{nullptr};
|
||||
std::string m_endpoint;
|
||||
int m_zmq_hwm{1000};
|
||||
int m_timeout_ms{1000};
|
||||
constexpr static size_t m_max_header_size = 1024;
|
||||
char* m_header_buffer = new char[m_max_header_size];
|
||||
char *m_header_buffer = new char[m_max_header_size];
|
||||
|
||||
bool decode_header(zmqHeader &h);
|
||||
|
||||
public:
|
||||
ZmqSocket(const std::string& endpoint);
|
||||
public:
|
||||
ZmqSocket(const std::string &endpoint);
|
||||
~ZmqSocket();
|
||||
ZmqSocket(const ZmqSocket&) = delete;
|
||||
ZmqSocket operator=(const ZmqSocket&) = delete;
|
||||
ZmqSocket(ZmqSocket&&) = delete;
|
||||
ZmqSocket(const ZmqSocket &) = delete;
|
||||
ZmqSocket operator=(const ZmqSocket &) = delete;
|
||||
ZmqSocket(ZmqSocket &&) = delete;
|
||||
|
||||
void connect();
|
||||
void disconnect();
|
||||
@ -90,8 +88,6 @@ public:
|
||||
void set_timeout_ms(int n);
|
||||
|
||||
int receive(zmqHeader &header, std::byte *data);
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <fmt/format.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sys/types.h>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace aare{
|
||||
namespace aare {
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
@ -26,7 +26,7 @@ typedef struct {
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
uint8_t packetMask[64];
|
||||
}__attribute__((packed)) sls_detector_header;
|
||||
} __attribute__((packed)) sls_detector_header;
|
||||
|
||||
struct xy {
|
||||
int row;
|
||||
@ -36,29 +36,21 @@ struct xy {
|
||||
// using image_shape = std::array<ssize_t, 2>;
|
||||
using dynamic_shape = std::vector<ssize_t>;
|
||||
|
||||
enum class DetectorType { Jungfrau, Eiger, Mythen3, Moench,ChipTestBoard };
|
||||
enum class DetectorType { Jungfrau, Eiger, Mythen3, Moench, ChipTestBoard };
|
||||
|
||||
enum class TimingMode {Auto, Trigger};
|
||||
enum class TimingMode { Auto, Trigger };
|
||||
|
||||
template<class T>
|
||||
T StringTo(std::string sv){
|
||||
return T(sv);
|
||||
}
|
||||
template <class T> T StringTo(std::string sv) { return T(sv); }
|
||||
|
||||
template<class T>
|
||||
std::string toString(T sv){
|
||||
return T(sv);
|
||||
}
|
||||
template <class T> std::string toString(T sv) { return T(sv); }
|
||||
|
||||
template <> DetectorType StringTo(std::string);
|
||||
template <> std::string toString(DetectorType type);
|
||||
|
||||
|
||||
template <> TimingMode StringTo(std::string);
|
||||
|
||||
using DataTypeVariants = std::variant<uint16_t, uint32_t>;
|
||||
|
||||
|
||||
struct RawFileConfig {
|
||||
int module_gap_row{};
|
||||
int module_gap_col{};
|
||||
@ -72,6 +64,4 @@ struct RawFileConfig {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace aare
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "aare/FileInterface.hpp"
|
||||
|
||||
namespace aare{
|
||||
namespace aare {
|
||||
class File {
|
||||
private:
|
||||
FileInterface *file_impl;
|
||||
@ -12,8 +12,8 @@ class File {
|
||||
// - w writing (overwrites existing file)
|
||||
// - a appending (appends to existing file)
|
||||
// TODO! do we need to support w+, r+ and a+?
|
||||
File(std::filesystem::path fname, std::string mode,FileConfig cfg = {});
|
||||
void write(Frame& frame);
|
||||
File(std::filesystem::path fname, std::string mode, FileConfig cfg = {});
|
||||
void write(Frame &frame);
|
||||
Frame read();
|
||||
Frame iread(size_t frame_number);
|
||||
std::vector<Frame> read(size_t n_frames);
|
||||
@ -27,10 +27,9 @@ class File {
|
||||
size_t total_frames() const;
|
||||
ssize_t rows() const;
|
||||
ssize_t cols() const;
|
||||
ssize_t bitdepth() const;
|
||||
ssize_t bitdepth() const;
|
||||
File(File &&other);
|
||||
|
||||
|
||||
~File();
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "aare/utils/logger.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace aare{
|
||||
namespace aare {
|
||||
|
||||
class FileFactory {
|
||||
// Class that will be used to create FileInterface objects
|
||||
@ -17,7 +17,7 @@ class FileFactory {
|
||||
// virtual int deleteFile() = 0;
|
||||
static FileInterface *load_file(std::filesystem::path p, std::string mode, FileConfig cfg = {}) {
|
||||
if ((mode == "r" or mode == "a") and not std::filesystem::exists(p)) {
|
||||
throw std::runtime_error(LOCATION+"File does not exist");
|
||||
throw std::runtime_error(LOCATION + "File does not exist");
|
||||
}
|
||||
|
||||
auto factory = get_factory(p);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "aare/DType.hpp"
|
||||
#include "aare/Frame.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/DType.hpp"
|
||||
#include "aare/utils/logger.hpp"
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
@ -96,4 +96,4 @@ class FileInterface {
|
||||
ssize_t m_bitdepth{};
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace aare
|
@ -1,19 +1,19 @@
|
||||
#pragma once
|
||||
#include "aare/DType.hpp"
|
||||
#include "aare/FileInterface.hpp"
|
||||
#include "aare/NumpyHelpers.hpp"
|
||||
#include "aare/DType.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <filesystem>
|
||||
|
||||
namespace aare{
|
||||
namespace aare {
|
||||
|
||||
class NumpyFile : public FileInterface {
|
||||
FILE *fp = nullptr;
|
||||
size_t initial_header_len = 0;
|
||||
size_t current_frame{};
|
||||
std::filesystem::path m_fname;
|
||||
std::filesystem::path m_fname;
|
||||
uint32_t header_len{};
|
||||
uint8_t header_len_size{};
|
||||
ssize_t header_size{};
|
||||
@ -26,9 +26,7 @@ class NumpyFile : public FileInterface {
|
||||
Frame get_frame(size_t frame_number);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
NumpyFile(const std::filesystem::path& fname);
|
||||
NumpyFile(const std::filesystem::path &fname);
|
||||
NumpyFile(FileConfig, NumpyHeader);
|
||||
void write(Frame &frame) override;
|
||||
Frame read() override { return get_frame(this->current_frame++); }
|
||||
@ -48,11 +46,10 @@ class NumpyFile : public FileInterface {
|
||||
|
||||
DType dtype() const { return m_header.dtype; }
|
||||
std::vector<size_t> shape() const { return m_header.shape; }
|
||||
|
||||
//load the full numpy file into a NDArray
|
||||
template<typename T, size_t NDim>
|
||||
NDArray<T,NDim> load(){
|
||||
NDArray<T,NDim> arr(make_shape<NDim>(m_header.shape));
|
||||
|
||||
// load the full numpy file into a NDArray
|
||||
template <typename T, size_t NDim> NDArray<T, NDim> load() {
|
||||
NDArray<T, NDim> arr(make_shape<NDim>(m_header.shape));
|
||||
fseek(fp, header_size, SEEK_SET);
|
||||
fread(arr.data(), sizeof(T), arr.size(), fp);
|
||||
return arr;
|
||||
|
@ -14,10 +14,9 @@ class NumpyFileFactory : public FileFactory {
|
||||
public:
|
||||
NumpyFileFactory(std::filesystem::path fpath);
|
||||
void parse_metadata(FileInterface *_file) override{/*TODO! remove after refactor*/};
|
||||
NumpyFile* load_file_read() override;
|
||||
NumpyFile* load_file_write(FileConfig) override;
|
||||
void parse_fname(FileInterface*)override{};
|
||||
|
||||
NumpyFile *load_file_read() override;
|
||||
NumpyFile *load_file_write(FileConfig) override;
|
||||
void parse_fname(FileInterface *) override{};
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -21,7 +21,7 @@ using shape_t = std::vector<size_t>;
|
||||
struct NumpyHeader {
|
||||
DType dtype{aare::DType::ERROR};
|
||||
bool fortran_order{false};
|
||||
shape_t shape{};
|
||||
shape_t shape{};
|
||||
|
||||
std::string to_string() const;
|
||||
};
|
||||
@ -51,9 +51,8 @@ template <typename T, size_t N> bool in_array(T val, const std::array<T, N> &arr
|
||||
bool is_digits(const std::string &str);
|
||||
|
||||
aare::DType parse_descr(std::string typestring);
|
||||
size_t write_header(std::filesystem::path fname, const NumpyHeader &header) ;
|
||||
size_t write_header(std::ostream &out, const NumpyHeader &header) ;
|
||||
|
||||
size_t write_header(std::filesystem::path fname, const NumpyHeader &header);
|
||||
size_t write_header(std::ostream &out, const NumpyHeader &header);
|
||||
|
||||
} // namespace NumpyHelpers
|
||||
} // namespace aare
|
@ -9,10 +9,9 @@ namespace aare {
|
||||
class RawFile : public FileInterface {
|
||||
|
||||
using config = RawFileConfig;
|
||||
|
||||
|
||||
public:
|
||||
std::filesystem::path m_fname; //TO be made private!
|
||||
std::filesystem::path m_fname; // TO be made private!
|
||||
void write(Frame &frame) override{};
|
||||
Frame read() override { return get_frame(this->current_frame++); };
|
||||
std::vector<Frame> read(size_t n_frames) override;
|
||||
@ -27,10 +26,10 @@ class RawFile : public FileInterface {
|
||||
size_t pixels() override { return m_rows * m_cols; }
|
||||
|
||||
// goto frame number
|
||||
void seek(size_t frame_number) override{ this->current_frame = frame_number; };
|
||||
void seek(size_t frame_number) override { this->current_frame = frame_number; };
|
||||
|
||||
// return the position of the file pointer (in number of frames)
|
||||
size_t tell() override{ return this->current_frame; };
|
||||
size_t tell() override { return this->current_frame; };
|
||||
|
||||
size_t n_subfiles;
|
||||
size_t n_subfile_parts;
|
||||
@ -66,8 +65,8 @@ class RawFile : public FileInterface {
|
||||
|
||||
size_t total_frames() const override { return m_total_frames; }
|
||||
ssize_t rows() const override { return m_rows; }
|
||||
ssize_t cols() const override{ return m_cols; }
|
||||
ssize_t bitdepth() const override{ return m_bitdepth; }
|
||||
ssize_t cols() const override { return m_cols; }
|
||||
ssize_t bitdepth() const override { return m_bitdepth; }
|
||||
|
||||
private:
|
||||
size_t current_frame{};
|
||||
@ -75,4 +74,4 @@ class RawFile : public FileInterface {
|
||||
Frame get_frame(size_t frame_number);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace aare
|
@ -10,10 +10,9 @@ class RawFileFactory : public FileFactory {
|
||||
void parse_raw_metadata(RawFile *file);
|
||||
|
||||
public:
|
||||
|
||||
RawFileFactory(std::filesystem::path fpath);
|
||||
RawFile *load_file_read() override;
|
||||
RawFile *load_file_write(FileConfig) override{return new RawFile();};
|
||||
RawFile *load_file_write(FileConfig) override { return new RawFile(); };
|
||||
void parse_metadata(FileInterface *) override;
|
||||
void parse_fname(FileInterface *) override;
|
||||
void open_subfiles(FileInterface *);
|
||||
@ -21,4 +20,4 @@ class RawFileFactory : public FileFactory {
|
||||
void find_geometry(FileInterface *);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace aare
|
@ -1 +1 @@
|
||||
//This is the top level header to include and what most users will use
|
||||
// This is the top level header to include and what most users will use
|
@ -115,7 +115,7 @@ template <typename... Strings> void error(const Strings... s) { internal::logger
|
||||
extern void set_streams(std::streambuf *out, std::streambuf *err);
|
||||
extern void set_streams(std::streambuf *out);
|
||||
extern void set_verbosity(LOGGING_LEVEL level);
|
||||
extern void set_output_file(std::string filename);
|
||||
extern void set_output_file(std::string filename);
|
||||
extern Logger &get_logger_instance();
|
||||
|
||||
} // namespace logger
|
||||
|
Loading…
x
Reference in New Issue
Block a user