Skip to content

Commit

Permalink
Merge pull request #266 from paulsengroup/fix/pixel-transformers
Browse files Browse the repository at this point in the history
Make constructors for To*Matrix transformers more flexible
  • Loading branch information
robomics authored Sep 28, 2024
2 parents ad75a32 + 2a4bdc3 commit d123eaa
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <utility>
#include <variant>

Expand All @@ -17,9 +18,17 @@
namespace hictk::transformers {

template <typename N, typename PixelSelector>
inline ToDenseMatrix<N, PixelSelector>::ToDenseMatrix(PixelSelector&& sel, [[maybe_unused]] N n,
inline ToDenseMatrix<N, PixelSelector>::ToDenseMatrix(PixelSelector sel, [[maybe_unused]] N n,
QuerySpan span)
: ToDenseMatrix(std::make_shared<const PixelSelector>(std::move(sel)), n, span) {}

template <typename N, typename PixelSelector>
inline ToDenseMatrix<N, PixelSelector>::ToDenseMatrix(std::shared_ptr<const PixelSelector> 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 "
Expand All @@ -31,6 +40,7 @@ inline ToDenseMatrix<N, PixelSelector>::ToDenseMatrix(PixelSelector&& sel, [[may

template <typename N, typename PixelSelector>
inline auto ToDenseMatrix<N, PixelSelector>::operator()() -> MatrixT {
assert(!!_sel);
const auto populate_lower_triangle =
_span == QuerySpan::lower_triangle || _span == QuerySpan::full;
const auto populate_upper_triangle =
Expand All @@ -42,38 +52,40 @@ inline auto ToDenseMatrix<N, PixelSelector>::operator()() -> MatrixT {

auto matrix = init_matrix();
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
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<N>(new_sel, matrix, matrix.rows(), matrix.cols(), row_offset(),
col_offset(), populate_lower_triangle, populate_upper_triangle,
matrix_setter);
return matrix;
}
}

internal::fill_matrix<N>(_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(),
internal::fill_matrix<N>(*_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(),
populate_lower_triangle, populate_upper_triangle, matrix_setter);
return matrix;
}

template <typename N, typename PixelSelector>
inline std::string_view ToDenseMatrix<N, PixelSelector>::chrom1() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return _sel.coord1().bin1.chrom().name();
return _sel->coord1().bin1.chrom().name();
}
return "all";
}

template <typename N, typename PixelSelector>
inline std::string_view ToDenseMatrix<N, PixelSelector>::chrom2() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return _sel.coord2().bin1.chrom().name();
return _sel->coord2().bin1.chrom().name();
}
return "all";
}
Expand All @@ -95,32 +107,36 @@ inline std::int64_t ToDenseMatrix<N, PixelSelector>::num_bins(const PixelCoordin

template <typename N, typename PixelSelector>
inline std::int64_t ToDenseMatrix<N, PixelSelector>::num_rows() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return num_bins(_sel.coord1(), _sel.bins());
return num_bins(_sel->coord1(), _sel->bins());
}
return static_cast<std::int64_t>(_sel.bins().size());
return static_cast<std::int64_t>(_sel->bins().size());
}

template <typename N, typename PixelSelector>
inline std::int64_t ToDenseMatrix<N, PixelSelector>::num_cols() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return num_bins(_sel.coord2(), _sel.bins());
return num_bins(_sel->coord2(), _sel->bins());
}
return static_cast<std::int64_t>(_sel.bins().size());
return static_cast<std::int64_t>(_sel->bins().size());
}

template <typename N, typename PixelSelector>
inline std::int64_t ToDenseMatrix<N, PixelSelector>::row_offset() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return offset(_sel.coord1());
return offset(_sel->coord1());
}
return 0;
}

template <typename N, typename PixelSelector>
inline std::int64_t ToDenseMatrix<N, PixelSelector>::col_offset() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return offset(_sel.coord2());
return offset(_sel->coord2());
}
return 0;
}
Expand All @@ -134,7 +150,8 @@ inline std::int64_t ToDenseMatrix<N, PixelSelector>::offset(

template <typename N, typename PixelSelector>
inline auto ToDenseMatrix<N, PixelSelector>::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);
Expand All @@ -158,8 +175,8 @@ inline std::pair<Eigen::Matrix<N, Eigen::Dynamic, Eigen::RowMajor>,
Eigen::Matrix<N, Eigen::Dynamic, Eigen::RowMajor>>
ToDenseMatrix<N, PixelSelector>::slice_weights(const hic::PixelSelector& sel) const {
return slice_weights(
sel.weights1(), sel.weights2(), static_cast<std::int64_t>(_sel.coord1().bin1.rel_id()),
static_cast<std::int64_t>(_sel.coord2().bin1.rel_id()), num_rows(), num_cols());
sel.weights1(), sel.weights2(), static_cast<std::int64_t>(_sel->coord1().bin1.rel_id()),
static_cast<std::int64_t>(_sel->coord2().bin1.rel_id()), num_rows(), num_cols());
}

template <typename N, typename PixelSelector>
Expand Down Expand Up @@ -218,6 +235,7 @@ ToDenseMatrix<N, PixelSelector>::slice_weights(const balancing::Weights& weights

template <typename N, typename PixelSelector>
inline void ToDenseMatrix<N, PixelSelector>::validate_dtype() const {
assert(!!_sel);
if constexpr (std::is_floating_point_v<N>) {
return;
}
Expand All @@ -227,11 +245,11 @@ inline void ToDenseMatrix<N, PixelSelector>::validate_dtype() const {
"type when fetching normalized interactions.";

if constexpr (internal::has_weights_member_fx<PixelSelector>) {
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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

#include <Eigen/SparseCore>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <utility>

#include "hictk/pixel.hpp"
Expand All @@ -15,9 +17,17 @@
namespace hictk::transformers {

template <typename N, typename PixelSelector>
inline ToSparseMatrix<N, PixelSelector>::ToSparseMatrix(PixelSelector&& sel, [[maybe_unused]] N n,
inline ToSparseMatrix<N, PixelSelector>::ToSparseMatrix(PixelSelector sel, [[maybe_unused]] N n,
QuerySpan span)
: ToSparseMatrix(std::make_shared<const PixelSelector>(std::move(sel)), n, span) {}

template <typename N, typename PixelSelector>
inline ToSparseMatrix<N, PixelSelector>::ToSparseMatrix(std::shared_ptr<const PixelSelector> 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 "
Expand All @@ -28,6 +38,7 @@ inline ToSparseMatrix<N, PixelSelector>::ToSparseMatrix(PixelSelector&& sel, [[m

template <typename N, typename PixelSelector>
inline auto ToSparseMatrix<N, PixelSelector>::operator()() -> MatrixT {
assert(!!_sel);
const auto populate_lower_triangle =
_span == QuerySpan::lower_triangle || _span == QuerySpan::full;
const auto populate_upper_triangle =
Expand All @@ -39,39 +50,41 @@ inline auto ToSparseMatrix<N, PixelSelector>::operator()() -> MatrixT {

MatrixT matrix(num_rows(), num_cols());
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
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<N>(_sel.fetch(coord3, coord4), matrix, matrix.rows(), matrix.cols(),
internal::fill_matrix<N>(_sel->fetch(coord3, coord4), matrix, matrix.rows(), matrix.cols(),
row_offset(), col_offset(), populate_lower_triangle,
populate_upper_triangle, matrix_setter);
matrix.makeCompressed();
return matrix;
}
}

internal::fill_matrix<N>(_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(),
internal::fill_matrix<N>(*_sel, matrix, matrix.rows(), matrix.cols(), row_offset(), col_offset(),
populate_lower_triangle, populate_upper_triangle, matrix_setter);
matrix.makeCompressed();
return matrix;
}

template <typename N, typename PixelSelector>
inline std::string_view ToSparseMatrix<N, PixelSelector>::chrom1() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return _sel.coord1().bin1.chrom().name();
return _sel->coord1().bin1.chrom().name();
}
return "all";
}

template <typename N, typename PixelSelector>
inline std::string_view ToSparseMatrix<N, PixelSelector>::chrom2() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return _sel.coord2().bin1.chrom().name();
return _sel->coord2().bin1.chrom().name();
}
return "all";
}
Expand All @@ -93,32 +106,36 @@ inline std::int64_t ToSparseMatrix<N, PixelSelector>::num_bins(const PixelCoordi

template <typename N, typename PixelSelector>
inline std::int64_t ToSparseMatrix<N, PixelSelector>::num_rows() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return num_bins(_sel.coord1(), _sel.bins());
return num_bins(_sel->coord1(), _sel->bins());
}
return static_cast<std::int64_t>(_sel.bins().size());
return static_cast<std::int64_t>(_sel->bins().size());
}

template <typename N, typename PixelSelector>
inline std::int64_t ToSparseMatrix<N, PixelSelector>::num_cols() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return num_bins(_sel.coord2(), _sel.bins());
return num_bins(_sel->coord2(), _sel->bins());
}
return static_cast<std::int64_t>(_sel.bins().size());
return static_cast<std::int64_t>(_sel->bins().size());
}

template <typename N, typename PixelSelector>
inline std::int64_t ToSparseMatrix<N, PixelSelector>::row_offset() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return offset(_sel.coord1());
return offset(_sel->coord1());
}
return 0;
}

template <typename N, typename PixelSelector>
inline std::int64_t ToSparseMatrix<N, PixelSelector>::col_offset() const noexcept {
assert(!!_sel);
if constexpr (internal::has_coord1_member_fx<PixelSelector>) {
return offset(_sel.coord2());
return offset(_sel->coord2());
}
return 0;
}
Expand All @@ -132,6 +149,7 @@ inline std::int64_t ToSparseMatrix<N, PixelSelector>::offset(

template <typename N, typename PixelSelector>
inline void ToSparseMatrix<N, PixelSelector>::validate_dtype() const {
assert(!!_sel);
if constexpr (std::is_floating_point_v<N>) {
return;
}
Expand All @@ -141,11 +159,11 @@ inline void ToSparseMatrix<N, PixelSelector>::validate_dtype() const {
"type when fetching normalized interactions.";

if constexpr (internal::has_weights_member_fx<PixelSelector>) {
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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <Eigen/Dense>
#include <cstdint>
#include <memory>
#include <string_view>
#include <type_traits>

Expand All @@ -26,12 +27,24 @@ class ToDenseMatrix {
using PixelT = remove_cvref_t<decltype(*std::declval<PixelIt>())>;
static_assert(std::is_same_v<PixelT, ThinPixel<N>>);

PixelSelector _sel{};
std::shared_ptr<const PixelSelector> _sel{};
QuerySpan _span{QuerySpan::full};

public:
using MatrixT = Eigen::Matrix<N, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
ToDenseMatrix(PixelSelector&& selector, N n, QuerySpan span = QuerySpan::full);
ToDenseMatrix() = delete;
ToDenseMatrix(PixelSelector selector, N n, QuerySpan span = QuerySpan::full);
ToDenseMatrix(std::shared_ptr<const PixelSelector> 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <Eigen/SparseCore>
#include <cstdint>
#include <memory>
#include <type_traits>

#include "hictk/pixel.hpp"
Expand All @@ -22,12 +23,24 @@ class ToSparseMatrix {
using PixelT = remove_cvref_t<decltype(*std::declval<PixelIt>())>;
static_assert(std::is_same_v<PixelT, ThinPixel<N>>);

PixelSelector _sel{};
std::shared_ptr<const PixelSelector> _sel{};
QuerySpan _span{QuerySpan::upper_triangle};

public:
using MatrixT = Eigen::SparseMatrix<N, Eigen::RowMajor>;
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<const PixelSelector> 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:
Expand Down

0 comments on commit d123eaa

Please sign in to comment.