mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-07-20 07:12:51 +02:00
added SparseMask class
This commit is contained in:
+6
-3
@@ -419,7 +419,8 @@ set(PUBLICHEADERS
|
||||
include/aare/RawMasterFile.hpp
|
||||
include/aare/RawSubFile.hpp
|
||||
include/aare/VarClusterFinder.hpp
|
||||
include/aare/utils/task.hpp)
|
||||
include/aare/utils/task.hpp
|
||||
include/aare/utils/SparseMask.hpp)
|
||||
|
||||
set(SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.cpp
|
||||
@@ -444,7 +445,8 @@ set(SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/SparseMask.cpp)
|
||||
|
||||
add_library(aare_core STATIC ${SourceFiles} ${PUBLICHEADERS})
|
||||
target_include_directories(
|
||||
@@ -512,7 +514,8 @@ if(AARE_TESTS)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/SparseMask.test.cpp)
|
||||
target_sources(tests PRIVATE ${TestSources})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "aare/NDView.hpp"
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace aare {
|
||||
|
||||
enum STORAGEFORMAT : uint8_t { ROWMAJOR = 0, COLUMNMAJOR = 1 };
|
||||
|
||||
/**
|
||||
* @brief A class representing a sparse mask for a 2D array.
|
||||
*
|
||||
* The SparseMask class allows for efficient storage and retrieval of non-zero
|
||||
* elements in a 2D array. It supports both row-major and column-major storage
|
||||
* formats.
|
||||
*/
|
||||
class SparseMask {
|
||||
|
||||
public:
|
||||
SparseMask(const STORAGEFORMAT storage_format, const size_t rows,
|
||||
const size_t cols);
|
||||
|
||||
SparseMask(NDView<bool, 2> mask, const STORAGEFORMAT storage_format);
|
||||
|
||||
// TODO: think of storage hdf5 probably the best innerindices, outerindices
|
||||
// as datasets and storage_format as attribute
|
||||
SparseMask(const std::filesystem::path &filename);
|
||||
|
||||
void insert(const size_t row, const size_t col);
|
||||
|
||||
/**
|
||||
* @brief Check if the element at (row, col) is masked (non-zero).
|
||||
* @param row Row index of the element.
|
||||
* @param col Column index of the element.
|
||||
* @return true if the element is masked (non-zero), false otherwise.
|
||||
*/
|
||||
bool is_masked(const size_t row, const size_t col) const;
|
||||
|
||||
void write_to_file(const std::filesystem::path &filename) const;
|
||||
|
||||
private:
|
||||
/// @brief stoarge format of the sparse mask, either row major or column
|
||||
/// major
|
||||
STORAGEFORMAT storage_format_;
|
||||
|
||||
/// @brief for column major stores row indices of non-zero elements, for row
|
||||
/// major stores column indices of non-zero elements
|
||||
std::vector<uint32_t> innerindices_;
|
||||
|
||||
/// @brief for column major outerindices[j] gives the index in innerindices_
|
||||
/// of the first non-zero element in column j, for row major outerindices[i]
|
||||
/// gives the index in innerindices_ of the first non-zero element in row i
|
||||
std::vector<uint32_t> outerindices_;
|
||||
};
|
||||
|
||||
} // namespace aare
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "aare/utils/SparseMask.hpp"
|
||||
|
||||
namespace aare {
|
||||
|
||||
SparseMask::SparseMask(const STORAGEFORMAT storage_format, const size_t rows,
|
||||
const size_t cols)
|
||||
: storage_format_(storage_format) {
|
||||
if (storage_format_ == STORAGEFORMAT::ROWMAJOR) {
|
||||
outerindices_.resize(rows + 1, 0);
|
||||
} else if (storage_format_ == STORAGEFORMAT::COLUMNMAJOR) {
|
||||
outerindices_.resize(cols + 1, 0);
|
||||
} else {
|
||||
throw std::invalid_argument(
|
||||
"Invalid storage format: must be either ROWMAJOR or COLUMNMAJOR");
|
||||
}
|
||||
|
||||
innerindices_.reserve(rows * cols); // Reserve maximum possible size
|
||||
}
|
||||
|
||||
void SparseMask::insert(const size_t row, const size_t col) {
|
||||
|
||||
// TODO: can be very inefficient -> most generic so does not depend on row,
|
||||
// col order of insertion
|
||||
// -> maybe better std::vector<std::vector>> for each row, col flatten after
|
||||
// inserting all -> create innerindices from size
|
||||
|
||||
if (storage_format_ == STORAGEFORMAT::ROWMAJOR) {
|
||||
std::for_each(outerindices_.begin() + row + 1, outerindices_.end(),
|
||||
[](uint32_t &x) { ++x; });
|
||||
innerindices_.insert(innerindices_.begin() + outerindices_[row],
|
||||
static_cast<uint32_t>(col));
|
||||
} else {
|
||||
std::for_each(outerindices_.begin() + col + 1, outerindices_.end(),
|
||||
[](uint32_t &x) { ++x; });
|
||||
innerindices_.insert(innerindices_.begin() + outerindices_[col],
|
||||
static_cast<uint32_t>(row));
|
||||
}
|
||||
}
|
||||
|
||||
bool SparseMask::is_masked(const size_t row, const size_t col) const {
|
||||
|
||||
const size_t index_outer_indices =
|
||||
storage_format_ == STORAGEFORMAT::ROWMAJOR ? row : col;
|
||||
|
||||
const size_t nonzero_index =
|
||||
storage_format_ == STORAGEFORMAT::ROWMAJOR ? col : row;
|
||||
|
||||
if (outerindices_[index_outer_indices + 1] -
|
||||
outerindices_[index_outer_indices] ==
|
||||
0) {
|
||||
return false; // No non-zero elements in this row
|
||||
} else {
|
||||
auto start = outerindices_[index_outer_indices];
|
||||
auto end = outerindices_[index_outer_indices + 1];
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
if (innerindices_[i] == nonzero_index) {
|
||||
return true; // Found a non-zero element at (row, col)
|
||||
}
|
||||
}
|
||||
return false; // No non-zero element found at (row, col)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aare
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "aare/utils/SparseMask.hpp"
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
TEST_CASE("Create Sparse Mask") {
|
||||
|
||||
std::vector<std::pair<size_t, size_t>> masked_pairs = {
|
||||
{1, 1}, {1, 2}, {1, 4}, {2, 0}, {2, 2}, {2, 4}, {3, 4}, {4, 1}};
|
||||
|
||||
SECTION("Row Major") {
|
||||
aare::SparseMask mask(aare::STORAGEFORMAT::ROWMAJOR, 5, 5);
|
||||
|
||||
std::for_each(masked_pairs.begin(), masked_pairs.end(),
|
||||
[&mask](const std::pair<size_t, size_t> &p) {
|
||||
mask.insert(p.first, p.second);
|
||||
});
|
||||
|
||||
for (size_t row = 0; row < 5; ++row) {
|
||||
for (size_t col = 0; col < 5; ++col) {
|
||||
if (std::find(masked_pairs.begin(), masked_pairs.end(),
|
||||
std::make_pair(row, col)) != masked_pairs.end()) {
|
||||
CHECK(mask.is_masked(row, col) == true);
|
||||
} else {
|
||||
CHECK(mask.is_masked(row, col) == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("Column Major") {
|
||||
aare::SparseMask mask(aare::STORAGEFORMAT::COLUMNMAJOR, 5, 5);
|
||||
|
||||
std::for_each(masked_pairs.begin(), masked_pairs.end(),
|
||||
[&mask](const std::pair<size_t, size_t> &p) {
|
||||
mask.insert(p.first, p.second);
|
||||
});
|
||||
|
||||
for (size_t row = 0; row < 5; ++row) {
|
||||
for (size_t col = 0; col < 5; ++col) {
|
||||
if (std::find(masked_pairs.begin(), masked_pairs.end(),
|
||||
std::make_pair(row, col)) != masked_pairs.end()) {
|
||||
CHECK(mask.is_masked(row, col) == true);
|
||||
} else {
|
||||
CHECK(mask.is_masked(row, col) == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user