From 2a4bdc3ad3f8919bfa504a0895215e69033ad3f3 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Sat, 28 Sep 2024 13:04:37 +0200 Subject: [PATCH] Make constructors for To*Matrix transformers more flexible --- .../impl/to_dense_matrix_impl.hpp | 56 ++++++++++++------- .../impl/to_sparse_matrix_impl.hpp | 50 +++++++++++------ .../hictk/transformers/to_dense_matrix.hpp | 17 +++++- .../hictk/transformers/to_sparse_matrix.hpp | 17 +++++- 4 files changed, 101 insertions(+), 39 deletions(-) diff --git a/src/libhictk/transformers/include/hictk/transformers/impl/to_dense_matrix_impl.hpp b/src/libhictk/transformers/include/hictk/transformers/impl/to_dense_matrix_impl.hpp index a85a17f5..4152e047 100644 --- a/src/libhictk/transformers/include/hictk/transformers/impl/to_dense_matrix_impl.hpp +++ b/src/libhictk/transformers/include/hictk/transformers/impl/to_dense_matrix_impl.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -17,9 +18,17 @@ namespace hictk::transformers { template -inline ToDenseMatrix::ToDenseMatrix(PixelSelector&& sel, [[maybe_unused]] N n, +inline ToDenseMatrix::ToDenseMatrix(PixelSelector sel, [[maybe_unused]] N n, QuerySpan span) + : ToDenseMatrix(std::make_shared(std::move(sel)), n, span) {} + +template +inline ToDenseMatrix::ToDenseMatrix(std::shared_ptr sel, + [[maybe_unused]] N n, QuerySpan span) : _sel(std::move(sel)), _span(span) { + if (!_sel) { + throw std::runtime_error("hictk::transformers::ToDenseMatrix(): sel cannot be null"); + } if (chrom1() != chrom2() && span == QuerySpan::lower_triangle) { throw std::runtime_error( "hictk::transformers::ToDenseMatrix(): invalid parameters. Trans queries do not support " @@ -31,6 +40,7 @@ inline ToDenseMatrix::ToDenseMatrix(PixelSelector&& sel, [[may template inline auto ToDenseMatrix::operator()() -> MatrixT { + assert(!!_sel); const auto populate_lower_triangle = _span == QuerySpan::lower_triangle || _span == QuerySpan::full; const auto populate_upper_triangle = @@ -42,14 +52,14 @@ inline auto ToDenseMatrix::operator()() -> MatrixT { auto matrix = init_matrix(); if constexpr (internal::has_coord1_member_fx) { - if (chrom1() == chrom2() && _sel.coord1() != _sel.coord2()) { - auto coord3 = _sel.coord1(); - auto coord4 = _sel.coord2(); + if (chrom1() == chrom2() && _sel->coord1() != _sel->coord2()) { + auto coord3 = _sel->coord1(); + auto coord4 = _sel->coord2(); coord3.bin1 = std::min(coord3.bin1, coord4.bin1); coord3.bin2 = std::max(coord3.bin2, coord4.bin2); coord4 = coord3; - const auto new_sel = _sel.fetch(coord3, coord4); + const auto new_sel = _sel->fetch(coord3, coord4); internal::fill_matrix(new_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), populate_lower_triangle, populate_upper_triangle, matrix_setter); @@ -57,23 +67,25 @@ inline auto ToDenseMatrix::operator()() -> MatrixT { } } - internal::fill_matrix(_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), + internal::fill_matrix(*_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), populate_lower_triangle, populate_upper_triangle, matrix_setter); return matrix; } template inline std::string_view ToDenseMatrix::chrom1() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return _sel.coord1().bin1.chrom().name(); + return _sel->coord1().bin1.chrom().name(); } return "all"; } template inline std::string_view ToDenseMatrix::chrom2() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return _sel.coord2().bin1.chrom().name(); + return _sel->coord2().bin1.chrom().name(); } return "all"; } @@ -95,32 +107,36 @@ inline std::int64_t ToDenseMatrix::num_bins(const PixelCoordin template inline std::int64_t ToDenseMatrix::num_rows() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return num_bins(_sel.coord1(), _sel.bins()); + return num_bins(_sel->coord1(), _sel->bins()); } - return static_cast(_sel.bins().size()); + return static_cast(_sel->bins().size()); } template inline std::int64_t ToDenseMatrix::num_cols() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return num_bins(_sel.coord2(), _sel.bins()); + return num_bins(_sel->coord2(), _sel->bins()); } - return static_cast(_sel.bins().size()); + return static_cast(_sel->bins().size()); } template inline std::int64_t ToDenseMatrix::row_offset() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return offset(_sel.coord1()); + return offset(_sel->coord1()); } return 0; } template inline std::int64_t ToDenseMatrix::col_offset() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return offset(_sel.coord2()); + return offset(_sel->coord2()); } return 0; } @@ -134,7 +150,8 @@ inline std::int64_t ToDenseMatrix::offset( template inline auto ToDenseMatrix::init_matrix() const -> MatrixT { - const auto& [weights1, weights2] = slice_weights(_sel); + assert(!!_sel); + const auto& [weights1, weights2] = slice_weights(*_sel); if (weights1.size() == 0) { assert(weights2.size() == 0); @@ -158,8 +175,8 @@ inline std::pair, Eigen::Matrix> ToDenseMatrix::slice_weights(const hic::PixelSelector& sel) const { return slice_weights( - sel.weights1(), sel.weights2(), static_cast(_sel.coord1().bin1.rel_id()), - static_cast(_sel.coord2().bin1.rel_id()), num_rows(), num_cols()); + sel.weights1(), sel.weights2(), static_cast(_sel->coord1().bin1.rel_id()), + static_cast(_sel->coord2().bin1.rel_id()), num_rows(), num_cols()); } template @@ -218,6 +235,7 @@ ToDenseMatrix::slice_weights(const balancing::Weights& weights template inline void ToDenseMatrix::validate_dtype() const { + assert(!!_sel); if constexpr (std::is_floating_point_v) { return; } @@ -227,11 +245,11 @@ inline void ToDenseMatrix::validate_dtype() const { "type when fetching normalized interactions."; if constexpr (internal::has_weights_member_fx) { - if (!_sel.weights().is_vector_of_ones()) { + if (!_sel->weights().is_vector_of_ones()) { throw std::runtime_error(msg); } } else { - if (!_sel.weights1().is_vector_of_ones() || !_sel.weights2().is_vector_of_ones()) { + if (!_sel->weights1().is_vector_of_ones() || !_sel->weights2().is_vector_of_ones()) { throw std::runtime_error(msg); } } diff --git a/src/libhictk/transformers/include/hictk/transformers/impl/to_sparse_matrix_impl.hpp b/src/libhictk/transformers/include/hictk/transformers/impl/to_sparse_matrix_impl.hpp index a2420982..ff038380 100644 --- a/src/libhictk/transformers/include/hictk/transformers/impl/to_sparse_matrix_impl.hpp +++ b/src/libhictk/transformers/include/hictk/transformers/impl/to_sparse_matrix_impl.hpp @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include "hictk/pixel.hpp" @@ -15,9 +17,17 @@ namespace hictk::transformers { template -inline ToSparseMatrix::ToSparseMatrix(PixelSelector&& sel, [[maybe_unused]] N n, +inline ToSparseMatrix::ToSparseMatrix(PixelSelector sel, [[maybe_unused]] N n, QuerySpan span) + : ToSparseMatrix(std::make_shared(std::move(sel)), n, span) {} + +template +inline ToSparseMatrix::ToSparseMatrix(std::shared_ptr sel, + [[maybe_unused]] N n, QuerySpan span) : _sel(std::move(sel)), _span(span) { + if (!_sel) { + throw std::runtime_error("hictk::transformers::ToSparseMatrix(): sel cannot be null"); + } if (chrom1() != chrom2() && span == QuerySpan::lower_triangle) { throw std::runtime_error( "hictk::transformers::ToSparseMatrix(): invalid parameters. Trans queries do not support " @@ -28,6 +38,7 @@ inline ToSparseMatrix::ToSparseMatrix(PixelSelector&& sel, [[m template inline auto ToSparseMatrix::operator()() -> MatrixT { + assert(!!_sel); const auto populate_lower_triangle = _span == QuerySpan::lower_triangle || _span == QuerySpan::full; const auto populate_upper_triangle = @@ -39,14 +50,14 @@ inline auto ToSparseMatrix::operator()() -> MatrixT { MatrixT matrix(num_rows(), num_cols()); if constexpr (internal::has_coord1_member_fx) { - if (chrom1() == chrom2() && _sel.coord1() != _sel.coord2()) { - auto coord3 = _sel.coord1(); - auto coord4 = _sel.coord2(); + if (chrom1() == chrom2() && _sel->coord1() != _sel->coord2()) { + auto coord3 = _sel->coord1(); + auto coord4 = _sel->coord2(); coord3.bin1 = std::min(coord3.bin1, coord4.bin1); coord3.bin2 = std::max(coord3.bin2, coord4.bin2); coord4 = coord3; - internal::fill_matrix(_sel.fetch(coord3, coord4), matrix, matrix.rows(), matrix.cols(), + internal::fill_matrix(_sel->fetch(coord3, coord4), matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), populate_lower_triangle, populate_upper_triangle, matrix_setter); matrix.makeCompressed(); @@ -54,7 +65,7 @@ inline auto ToSparseMatrix::operator()() -> MatrixT { } } - internal::fill_matrix(_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), + internal::fill_matrix(*_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(), populate_lower_triangle, populate_upper_triangle, matrix_setter); matrix.makeCompressed(); return matrix; @@ -62,16 +73,18 @@ inline auto ToSparseMatrix::operator()() -> MatrixT { template inline std::string_view ToSparseMatrix::chrom1() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return _sel.coord1().bin1.chrom().name(); + return _sel->coord1().bin1.chrom().name(); } return "all"; } template inline std::string_view ToSparseMatrix::chrom2() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return _sel.coord2().bin1.chrom().name(); + return _sel->coord2().bin1.chrom().name(); } return "all"; } @@ -93,32 +106,36 @@ inline std::int64_t ToSparseMatrix::num_bins(const PixelCoordi template inline std::int64_t ToSparseMatrix::num_rows() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return num_bins(_sel.coord1(), _sel.bins()); + return num_bins(_sel->coord1(), _sel->bins()); } - return static_cast(_sel.bins().size()); + return static_cast(_sel->bins().size()); } template inline std::int64_t ToSparseMatrix::num_cols() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return num_bins(_sel.coord2(), _sel.bins()); + return num_bins(_sel->coord2(), _sel->bins()); } - return static_cast(_sel.bins().size()); + return static_cast(_sel->bins().size()); } template inline std::int64_t ToSparseMatrix::row_offset() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return offset(_sel.coord1()); + return offset(_sel->coord1()); } return 0; } template inline std::int64_t ToSparseMatrix::col_offset() const noexcept { + assert(!!_sel); if constexpr (internal::has_coord1_member_fx) { - return offset(_sel.coord2()); + return offset(_sel->coord2()); } return 0; } @@ -132,6 +149,7 @@ inline std::int64_t ToSparseMatrix::offset( template inline void ToSparseMatrix::validate_dtype() const { + assert(!!_sel); if constexpr (std::is_floating_point_v) { return; } @@ -141,11 +159,11 @@ inline void ToSparseMatrix::validate_dtype() const { "type when fetching normalized interactions."; if constexpr (internal::has_weights_member_fx) { - if (!_sel.weights().is_vector_of_ones()) { + if (!_sel->weights().is_vector_of_ones()) { throw std::runtime_error(msg); } } else { - if (!_sel.weights1().is_vector_of_ones() || !_sel.weights2().is_vector_of_ones()) { + if (!_sel->weights1().is_vector_of_ones() || !_sel->weights2().is_vector_of_ones()) { throw std::runtime_error(msg); } } diff --git a/src/libhictk/transformers/include/hictk/transformers/to_dense_matrix.hpp b/src/libhictk/transformers/include/hictk/transformers/to_dense_matrix.hpp index 04914cc4..4c2b8655 100644 --- a/src/libhictk/transformers/include/hictk/transformers/to_dense_matrix.hpp +++ b/src/libhictk/transformers/include/hictk/transformers/to_dense_matrix.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -26,12 +27,24 @@ class ToDenseMatrix { using PixelT = remove_cvref_t())>; static_assert(std::is_same_v>); - PixelSelector _sel{}; + std::shared_ptr _sel{}; QuerySpan _span{QuerySpan::full}; public: using MatrixT = Eigen::Matrix; - ToDenseMatrix(PixelSelector&& selector, N n, QuerySpan span = QuerySpan::full); + ToDenseMatrix() = delete; + ToDenseMatrix(PixelSelector selector, N n, QuerySpan span = QuerySpan::full); + ToDenseMatrix(std::shared_ptr selector, N n, + QuerySpan span = QuerySpan::full); + + ToDenseMatrix(const ToDenseMatrix& other) = delete; + ToDenseMatrix(ToDenseMatrix&& other) noexcept = default; + + ~ToDenseMatrix() noexcept = default; + + ToDenseMatrix& operator=(const ToDenseMatrix& other) = delete; + ToDenseMatrix& operator=(ToDenseMatrix&& other) noexcept = default; + [[nodiscard]] auto operator()() -> MatrixT; private: diff --git a/src/libhictk/transformers/include/hictk/transformers/to_sparse_matrix.hpp b/src/libhictk/transformers/include/hictk/transformers/to_sparse_matrix.hpp index 6b397a9f..069c23b7 100644 --- a/src/libhictk/transformers/include/hictk/transformers/to_sparse_matrix.hpp +++ b/src/libhictk/transformers/include/hictk/transformers/to_sparse_matrix.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "hictk/pixel.hpp" @@ -22,12 +23,24 @@ class ToSparseMatrix { using PixelT = remove_cvref_t())>; static_assert(std::is_same_v>); - PixelSelector _sel{}; + std::shared_ptr _sel{}; QuerySpan _span{QuerySpan::upper_triangle}; public: using MatrixT = Eigen::SparseMatrix; - ToSparseMatrix(PixelSelector&& selector, N n, QuerySpan span = QuerySpan::upper_triangle); + ToSparseMatrix() = delete; + ToSparseMatrix(PixelSelector selector, N n, QuerySpan span = QuerySpan::upper_triangle); + ToSparseMatrix(std::shared_ptr selector, N n, + QuerySpan span = QuerySpan::upper_triangle); + + ToSparseMatrix(const ToSparseMatrix& other) = delete; + ToSparseMatrix(ToSparseMatrix&& other) noexcept = default; + + ~ToSparseMatrix() noexcept = default; + + ToSparseMatrix& operator=(const ToSparseMatrix& other) = delete; + ToSparseMatrix& operator=(ToSparseMatrix&& other) noexcept = default; + [[nodiscard]] auto operator()() -> MatrixT; private: