1#ifndef SCRAN_PCA_BLOCKED_PCA_HPP
2#define SCRAN_PCA_BLOCKED_PCA_HPP
16#include "irlba_tatami/irlba_tatami.hpp"
19#include "sanisizer/sanisizer.hpp"
35template<
typename EigenVector_ = Eigen::VectorXd>
121template<
class EigenVector_>
122struct BlockingDetails {
123 template<
typename Index_>
124 BlockingDetails(std::size_t num_blocks, Index_ num_cells) :
125 per_element_weight(sanisizer::cast<I<
decltype(per_element_weight.size())> >(num_blocks)),
129 typedef typename EigenVector_::Scalar Weight;
130 std::vector<Weight> per_element_weight;
131 Weight total_block_weight = 0;
132 EigenVector_ expanded_weights;
135template<
class EigenVector_,
typename Index_,
typename Block_>
136std::optional<BlockingDetails<EigenVector_> > compute_blocking_details(
139 const std::size_t num_blocks,
140 const std::vector<Index_>& block_sizes,
144 if (block_weight_policy == scran_blocks::WeightPolicy::NONE) {
145 return std::optional<BlockingDetails<EigenVector_> >();
148 BlockingDetails<EigenVector_> output(num_blocks, ncells);
149 auto& total_weight = output.total_block_weight;
150 auto& element_weight = output.per_element_weight;
152 for (std::size_t b = 0; b < num_blocks; ++b) {
153 const auto bsize = block_sizes[b];
159 typename EigenVector_::Scalar block_weight = 1;
160 if (block_weight_policy == scran_blocks::WeightPolicy::VARIABLE) {
164 element_weight[b] = block_weight / bsize;
165 total_weight += block_weight;
167 element_weight[b] = 0;
172 if (total_weight == 0) {
177 auto sqrt_weights = element_weight;
178 for (
auto& s : sqrt_weights) {
182 auto& expanded = output.expanded_weights;
183 for (Index_ c = 0; c < ncells; ++c) {
184 expanded.coeffRef(c) = sqrt_weights[block[c]];
194template<
class IrlbaSparseMatrix_,
typename Block_,
class Index_,
class EigenVector_,
class EigenMatrix_>
195void compute_blockwise_mean_and_variance_realized_sparse(
196 const IrlbaSparseMatrix_& emat,
198 const std::size_t num_blocks,
199 const std::vector<Index_>& block_sizes,
200 const std::optional<BlockingDetails<EigenVector_> >& block_details,
201 EigenMatrix_& centers,
202 EigenVector_& variances,
205 const auto ngenes = emat.cols();
206 const auto ncells = emat.rows();
207 const auto& values = emat.get_values();
208 const auto& indices = emat.get_indices();
209 const auto& pointers = emat.get_pointers();
210 static_assert(!EigenMatrix_::IsRowMajor);
212 assert(sanisizer::is_equal(ngenes, variances.size()));
213 assert(sanisizer::is_equal(ngenes, centers.cols()));
214 assert(sanisizer::is_equal(num_blocks, centers.rows()));
217 auto block_zeros = sanisizer::create<std::vector<Index_> >(num_blocks);
218 auto block_rss = sanisizer::create<std::vector<typename EigenVector_::Scalar> >(num_blocks);
219 auto block_centers = sanisizer::create<std::vector<typename EigenMatrix_::Scalar> >(num_blocks);
221 for (I<
decltype(start)> g = start, end = start + length; g < end; ++g) {
222 const auto offset = pointers[g];
223 const auto num_nonzero = pointers[g + 1] - offset;
225 const auto vptr = values.data() + offset;
226 const auto iptr = indices.data() + offset;
228 std::fill(block_centers.begin(), block_centers.end(), 0);
229 for (I<
decltype(num_nonzero)> i = 0; i < num_nonzero; ++i) {
230 block_centers[block[iptr[i]]] += vptr[i];
232 for (std::size_t b = 0; b < num_blocks; ++b) {
233 const auto bsize = block_sizes[b];
235 block_centers[b] /= bsize;
241 std::copy(block_sizes.begin(), block_sizes.end(), block_zeros.begin());
242 std::fill(block_rss.begin(), block_rss.end(), 0);
244 for (I<
decltype(num_nonzero)> i = 0; i < num_nonzero; ++i) {
245 const Block_ curb = block[iptr[i]];
246 const auto diff = vptr[i] - block_centers[curb];
247 block_rss[curb] += diff * diff;
251 typename EigenVector_::Scalar rss = 0;
252 for (std::size_t b = 0; b < num_blocks; ++b) {
253 const auto bsize = block_sizes[b];
255 const auto val = block_centers[b];
256 const auto final_rss = block_rss[b] + val * val * block_zeros[b];
257 if (block_details.has_value()) {
258 rss += final_rss * block_details->per_element_weight[b];
276 variances[g] = rss / (ncells - 1);
281 std::copy(block_centers.begin(), block_centers.end(), centers.data() + sanisizer::product_unsafe<std::size_t>(g, num_blocks));
283 }, ngenes, nthreads);
286template<
class EigenMatrix_,
typename Block_,
class Index_,
class EigenVector_>
287void compute_blockwise_mean_and_variance_realized_dense(
288 const EigenMatrix_& emat,
290 const std::size_t num_blocks,
291 const std::vector<Index_>& block_sizes,
292 const std::optional<BlockingDetails<EigenVector_> >& block_details,
293 EigenMatrix_& centers,
294 EigenVector_& variances,
297 const auto ngenes = emat.cols();
298 const auto ncells = emat.rows();
299 static_assert(!EigenMatrix_::IsRowMajor);
301 assert(sanisizer::is_equal(ngenes, variances.size()));
302 assert(sanisizer::is_equal(ngenes, centers.cols()));
303 assert(sanisizer::is_equal(num_blocks, centers.rows()));
306 auto block_rss = sanisizer::create<std::vector<typename EigenVector_::Scalar> >(num_blocks);
307 auto block_centers = sanisizer::create<std::vector<typename EigenMatrix_::Scalar> >(num_blocks);
309 for (Index_ g = start, end = start + length; g < end; ++g) {
310 const auto values = emat.data() + sanisizer::product_unsafe<std::size_t>(g, ncells);
312 std::fill(block_centers.begin(), block_centers.end(), 0);
313 for (I<
decltype(ncells)> i = 0; i < ncells; ++i) {
314 block_centers[block[i]] += values[i];
316 for (std::size_t b = 0; b < num_blocks; ++b) {
317 const auto bsize = block_sizes[b];
319 block_centers[b] /= bsize;
324 std::fill(block_rss.begin(), block_rss.end(), 0);
325 for (I<
decltype(ncells)> i = 0; i < ncells; ++i) {
326 const auto curb = block[i];
327 const auto delta = values[i] - block_centers[curb];
328 block_rss[curb] += delta * delta;
331 typename EigenVector_::Scalar rss = 0;
332 for (std::size_t b = 0; b < num_blocks; ++b) {
333 if (block_sizes[b]) {
334 if (block_details.has_value()) {
335 rss += block_rss[b] * block_details->per_element_weight[b];
344 variances[g] = rss / (ncells - 1);
349 std::copy(block_centers.begin(), block_centers.end(), centers.data() + sanisizer::product_unsafe<std::size_t>(g, num_blocks));
351 }, ngenes, nthreads);
354template<
typename Value_,
typename Index_,
typename Block_,
class EigenMatrix_,
class EigenVector_>
355void compute_blockwise_mean_and_variance_tatami(
358 const std::size_t num_blocks,
359 const std::vector<Index_>& block_sizes,
360 const std::optional<BlockingDetails<EigenVector_> >& block_details,
361 EigenMatrix_& centers,
362 EigenVector_& variances,
365 static_assert(!EigenMatrix_::IsRowMajor);
366 typedef typename EigenMatrix_::Scalar Float;
368 const auto ngenes = mat.
nrow();
369 EigenMatrix_ tmp_mean(
370 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().rows())> >(ngenes),
371 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().cols())> >(num_blocks)
374 tatami_stats::GroupRssBuffers<Float> buffers;
375 buffers.mean.reserve(num_blocks);
376 buffers.rss.reserve(num_blocks);
377 auto tmp_rss = sanisizer::create<std::vector<std::vector<Float> > >(num_blocks);
379 for (std::size_t b = 0; b < num_blocks; ++b) {
380 buffers.mean.push_back(tmp_mean.data() + sanisizer::product_unsafe<std::size_t>(ngenes, b));
382 buffers.rss.push_back(tmp_rss[b].data());
385 tatami_stats::GroupRssOptions<Float> opt;
386 opt.num_threads = nthreads;
387 opt.mean_placeholder = 0;
388 tatami_stats::group_rss(
true, mat, block, num_blocks, block_sizes.data(), buffers, opt);
390 assert(sanisizer::is_equal(variances.size(), ngenes));
392 for (std::size_t b = 0; b < num_blocks; ++b) {
393 if (block_sizes[b]) {
394 const auto& currss = tmp_rss[b];
395 if (block_details.has_value()) {
396 for (Index_ g = 0; g < ngenes; ++g) {
397 variances.coeffRef(g) += currss[g] * block_details->per_element_weight[b];
400 for (Index_ g = 0; g < ngenes; ++g) {
401 variances.coeffRef(g) += currss[g];
407 centers = tmp_mean.adjoint();
410 const auto ncells = mat.
ncol();
412 for (Index_ g = 0; g < ngenes; ++g) {
413 variances.coeffRef(g) /= ncells - 1;
422template<
class EigenMatrix_,
class EigenVector_>
423const EigenMatrix_& scale_rotation_matrix(
const EigenMatrix_& rotation,
bool scale,
const EigenVector_& scale_v, EigenMatrix_& tmp) {
425 tmp = (rotation.array().colwise() / scale_v.array()).matrix();
432template<
class EigenVector_,
class IrlbaSparseMatrix_,
class EigenMatrix_>
433inline void project_matrix_realized_sparse(
434 const IrlbaSparseMatrix_& emat,
435 EigenMatrix_& components,
436 const EigenMatrix_& scaled_rotation,
439 const auto rank = scaled_rotation.cols();
440 const auto ncells = emat.rows();
441 const auto ngenes = emat.cols();
445 sanisizer::cast<I<
decltype(components.rows())> >(rank),
446 sanisizer::cast<I<
decltype(components.cols())> >(ncells)
448 components.setZero();
450 const auto& values = emat.get_values();
451 const auto& indices = emat.get_indices();
452 const auto& pointers = emat.get_pointers();
455 auto multipliers = sanisizer::create<EigenVector_>(rank);
456 for (I<
decltype(ngenes)> g = 0; g < ngenes; ++g) {
457 multipliers.noalias() = scaled_rotation.row(g);
458 const auto start = pointers[g], end = pointers[g + 1];
459 for (
auto i = start; i < end; ++i) {
460 components.col(indices[i]).noalias() += values[i] * multipliers;
470 const auto& primary_bounds = emat.get_primary_boundaries();
471 auto working = sanisizer::create<std::vector<EigenMatrix_> >(nthreads - 1);
478 auto& mat = working[t - 1];
479 mat.resize(components.rows(), components.cols());
484 const auto gstart = primary_bounds[t];
485 const auto gend = primary_bounds[t + 1];
486 auto multipliers = sanisizer::create<EigenVector_>(rank);
487 for (I<
decltype(ngenes)> g = gstart; g < gend; ++g) {
488 multipliers.noalias() = scaled_rotation.row(g);
489 const auto start = pointers[g], end = pointers[g + 1];
490 for (
auto i = start; i < end; ++i) {
491 ptr->col(indices[i]).noalias() += values[i] * multipliers;
496 for (
auto& w : working) {
502template<
typename Value_,
typename Index_,
class EigenMatrix_>
503void project_matrix_transposed_tatami(
505 EigenMatrix_& components,
506 const EigenMatrix_& scaled_rotation,
509 const auto rank = scaled_rotation.cols();
510 const auto ngenes = mat.
nrow();
511 const auto ncells = mat.
ncol();
516 sanisizer::cast<I<
decltype(components.rows())> >(rank),
517 sanisizer::cast<I<
decltype(components.cols())> >(ncells)
521 static_assert(!EigenMatrix_::IsRowMajor);
522 auto get_right = [&](I<
decltype(rank)> r) ->
auto {
523 return scaled_rotation.data() + sanisizer::product_unsafe<std::size_t>(r, ngenes);
526 if (tmat.is_sparse()) {
527 if (tmat.prefer_rows()) {
528 tatami_mult::MultiplySparseRowWithDenseColumnMatrixToRowOutputOptions options;
529 options.num_threads = nthreads;
530 tatami_mult::multiply_sparse_row_with_dense_column_matrix_to_row_output(tmat, rank, get_right, components.data(), options);
532 tatami_mult::MultiplySparseColumnWithDenseColumnMatrixToRowOutputOptions options;
533 options.num_threads = nthreads;
534 tatami_mult::multiply_sparse_column_with_dense_column_matrix_to_row_output(tmat, rank, get_right, components.data(), options);
537 if (tmat.prefer_rows()) {
538 tatami_mult::MultiplyDenseRowWithDenseColumnMatrixToRowOutputOptions options;
539 options.num_threads = nthreads;
540 tatami_mult::multiply_dense_row_with_dense_column_matrix_to_row_output(tmat, rank, get_right, components.data(), options);
542 tatami_mult::MultiplyDenseColumnWithDenseColumnMatrixToRowOutputOptions options;
543 options.num_threads = nthreads;
544 tatami_mult::multiply_dense_column_with_dense_column_matrix_to_row_output(tmat, rank, get_right, components.data(), options);
549template<
class EigenMatrix_,
class EigenVector_>
550void clean_up_projected(EigenMatrix_& projected, EigenVector_& D) {
553 for (I<
decltype(projected.rows())> i = 0, prows = projected.rows(); i < prows; ++i) {
554 projected.row(i).array() -= projected.row(i).sum() / projected.cols();
558 const typename EigenMatrix_::Scalar denom = projected.cols() - 1;
570template<
class EigenVector_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
573 ResidualWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
574 my_work(matrix.new_known_workspace()),
577 my_sub(sanisizer::cast<I<decltype(my_sub.size())> >(my_means.rows()))
581 I<decltype(std::declval<IrlbaMatrix_>().new_known_workspace())> my_work;
582 const Block_* my_block;
583 const CenterMatrix_& my_means;
587 void multiply(
const EigenVector_& right, EigenVector_& output) {
588 my_work->multiply(right, output);
590 my_sub.noalias() = my_means * right;
591 for (I<
decltype(output.size())> i = 0, end = output.size(); i < end; ++i) {
592 auto& val = output.coeffRef(i);
593 val -= my_sub.coeff(my_block[i]);
598template<
class EigenVector_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
601 ResidualAdjointWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
602 my_work(matrix.new_known_adjoint_workspace()),
605 my_aggr(sanisizer::cast<I<decltype(my_aggr.size())> >(my_means.rows()))
609 I<decltype(std::declval<IrlbaMatrix_>().new_known_adjoint_workspace())> my_work;
610 const Block_* my_block;
611 const CenterMatrix_& my_means;
612 EigenVector_ my_aggr;
615 void multiply(
const EigenVector_& right, EigenVector_& output) {
616 my_work->multiply(right, output);
619 for (I<
decltype(right.size())> i = 0, end = right.size(); i < end; ++i) {
620 my_aggr.coeffRef(my_block[i]) += right.coeff(i);
623 output.noalias() -= my_means.adjoint() * my_aggr;
627template<
class EigenMatrix_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
630 ResidualRealizeWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
631 my_work(matrix.new_known_realize_workspace()),
637 I<decltype(std::declval<IrlbaMatrix_>().new_known_realize_workspace())> my_work;
638 const Block_* my_block;
639 const CenterMatrix_& my_means;
642 const EigenMatrix_& realize(EigenMatrix_& buffer) {
643 my_work->realize_copy(buffer);
644 for (I<
decltype(buffer.rows())> i = 0, end = buffer.rows(); i < end; ++i) {
645 buffer.row(i) -= my_means.row(my_block[i]);
653template<
class EigenVector_,
class EigenMatrix_,
class IrlbaMatrixPo
inter_,
class Block_,
class CenterMatrixPo
inter_>
654class ResidualMatrix final :
public irlba::Matrix<EigenVector_, EigenMatrix_> {
656 ResidualMatrix(IrlbaMatrixPointer_ mat,
const Block_* block, CenterMatrixPointer_ means) :
657 my_matrix(std::move(mat)),
659 my_means(std::move(means))
663 Eigen::Index rows()
const {
664 return my_matrix->rows();
667 Eigen::Index cols()
const {
668 return my_matrix->cols();
672 IrlbaMatrixPointer_ my_matrix;
673 const Block_* my_block;
674 CenterMatrixPointer_ my_means;
677 std::unique_ptr<irlba::Workspace<EigenVector_> > new_workspace()
const {
678 return new_known_workspace();
681 std::unique_ptr<irlba::AdjointWorkspace<EigenVector_> > new_adjoint_workspace()
const {
682 return new_known_adjoint_workspace();
685 std::unique_ptr<irlba::RealizeWorkspace<EigenMatrix_> > new_realize_workspace()
const {
686 return new_known_realize_workspace();
690 std::unique_ptr<ResidualWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_workspace()
const {
691 return std::make_unique<ResidualWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
694 std::unique_ptr<ResidualAdjointWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_adjoint_workspace()
const {
695 return std::make_unique<ResidualAdjointWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
698 std::unique_ptr<ResidualRealizeWorkspace<EigenMatrix_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_realize_workspace()
const {
699 return std::make_unique<ResidualRealizeWorkspace<EigenMatrix_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
712template<
typename EigenMatrix_,
typename EigenVector_>
770template<
typename Value_,
typename Index_,
typename Block_,
typename EigenMatrix_,
class EigenVector_,
class SubsetFunction_>
771void blocked_pca_internal(
774 const std::size_t num_blocks,
777 SubsetFunction_ subset_fun
780 std::unique_ptr<irlba::Matrix<EigenVector_, EigenMatrix_> > ptr;
781 std::function<void(
const EigenMatrix_&)> projector;
783 const Index_ ngenes = mat.
nrow(), ncells = mat.
ncol();
785 sanisizer::cast<I<
decltype(output.
center.rows())> >(num_blocks),
786 sanisizer::cast<I<
decltype(output.
center.cols())> >(ngenes)
790 auto block_sizes = sanisizer::create<std::vector<Index_> >(num_blocks);
791 for (Index_ c = 0; c < ncells; ++c) {
792 block_sizes[block[c]] += 1;
794 auto block_details = compute_blocking_details<EigenVector_>(
804 compute_blockwise_mean_and_variance_tatami(
814 ptr.reset(
new irlba_tatami::Transposed<EigenVector_, EigenMatrix_, Value_, Index_,
decltype(&mat)>(&mat, options.
num_threads));
815 projector = [&](
const EigenMatrix_& scaled_rotation) ->
void {
819 }
else if (mat.
sparse()) {
838 I<
decltype(extracted.value)>,
839 I<
decltype(extracted.index)>,
840 I<
decltype(extracted.pointers)>
844 std::move(extracted.value),
845 std::move(extracted.index),
846 std::move(extracted.pointers),
850 ptr.reset(sparse_ptr);
852 compute_blockwise_mean_and_variance_realized_sparse(
864 projector = [&,sparse_ptr](
const EigenMatrix_& scaled_rotation) ->
void {
865 project_matrix_realized_sparse<EigenVector_>(*sparse_ptr, output.
components, scaled_rotation, options.
num_threads);
870 auto tmp_ptr = std::make_unique<EigenMatrix_>(
871 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().rows())> >(ncells),
872 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().cols())> >(ngenes)
874 static_assert(!EigenMatrix_::IsRowMajor);
881 tatami::ConvertToDenseOptions opt;
882 opt.num_threads = options.num_threads;
887 compute_blockwise_mean_and_variance_realized_dense(
898 const auto dense_ptr = tmp_ptr.get();
899 ptr.reset(
new irlba::SimpleMatrix<EigenVector_, EigenMatrix_,
decltype(tmp_ptr)>(std::move(tmp_ptr)));
902 projector = [&,dense_ptr](
const EigenMatrix_& scaled_rotation) ->
void {
903 output.
components.noalias() = (*dense_ptr * scaled_rotation).adjoint();
909 std::unique_ptr<irlba::Matrix<EigenVector_, EigenMatrix_> > alt;
916 I<
decltype(&(output.
center))>
931 I<
decltype(&(scale))>
942 if (block_details.has_value()) {
948 I<
decltype(&(block_details->expanded_weights))>
951 &(block_details->expanded_weights),
962 const auto& scaled_rotation = scale_rotation_matrix(output.
rotation, options.
scale, scale, tmp);
963 projector(scaled_rotation);
967 EigenMatrix_ centering = (output.
center * scaled_rotation).adjoint();
968 for (I<
decltype(ncells)> c =0 ; c < ncells; ++c) {
969 output.
components.col(c) -= centering.col(block[c]);
990 const auto& scaled_rotation = scale_rotation_matrix(output.
rotation, options.
scale, scale, tmp);
991 projector(scaled_rotation);
1000 if (options.
scale) {
1001 output.
scale = std::move(scale);
1059template<
typename Value_,
typename Index_,
typename Block_,
typename EigenMatrix_,
class EigenVector_>
1062 const Block_* block,
1063 const std::size_t num_blocks,
1067 blocked_pca_internal<Value_, Index_, Block_, EigenMatrix_, EigenVector_>(
1075 const std::vector<Index_>&,
1076 const std::optional<BlockingDetails<EigenVector_> >&,
1077 const EigenMatrix_&,
1102template<
typename EigenMatrix_ = Eigen::MatrixXd,
class EigenVector_ = Eigen::VectorXd,
typename Value_,
typename Index_,
typename Block_>
1105 const Block_* block,
1106 const std::size_t num_blocks,
1110 blocked_pca(mat, block, num_blocks, options, output);
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
Metrics compute(const Matrix_ &matrix, const Eigen::Index number, EigenMatrix_ &outU, EigenMatrix_ &outV, EigenVector_ &outD, const Options< EigenVector_ > &options)
void parallelize(Task_ num_tasks, Run_ run_task)
double compute_variable_weight(const double s, const VariableWeightParameters ¶ms)
Principal component analysis on single-cell data.
void blocked_pca(const tatami::Matrix< Value_, Index_ > &mat, const Block_ *block, const std::size_t num_blocks, const BlockedPcaOptions< EigenVector_ > &options, BlockedPcaResults< EigenMatrix_, EigenVector_ > &output)
Definition blocked_pca.hpp:1060
std::shared_ptr< const Matrix< Value_, Index_ > > wrap_shared_ptr(const Matrix< Value_, Index_ > *const ptr)
void resize_container_to_Index_size(Container_ &container, const Index_ x, Args_ &&... args)
CompressedSparseContents< StoredValue_, StoredIndex_, StoredPointer_ > retrieve_compressed_sparse_contents(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row, const RetrieveCompressedSparseContentsOptions &options)
int parallelize(Function_ fun, const Index_ tasks, const int workers)
void convert_to_dense(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row_major, StoredValue_ *const store, const ConvertToDenseOptions &options)
I< decltype(std::declval< Container_ >().size())> cast_Index_to_container_size(const Index_ x)
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
Options for blocked_pca().
Definition blocked_pca.hpp:36
int number
Definition blocked_pca.hpp:53
irlba::Options< EigenVector_ > irlba_options
Definition blocked_pca.hpp:111
bool transpose
Definition blocked_pca.hpp:67
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition blocked_pca.hpp:84
scran_blocks::WeightPolicy block_weight_policy
Definition blocked_pca.hpp:78
bool scale
Definition blocked_pca.hpp:61
bool center_scores_by_block
Definition blocked_pca.hpp:92
bool realize_matrix
Definition blocked_pca.hpp:98
int num_threads
Definition blocked_pca.hpp:106
Results of blocked_pca().
Definition blocked_pca.hpp:713
EigenVector_::Scalar total_variance
Definition blocked_pca.hpp:735
EigenMatrix_ components
Definition blocked_pca.hpp:722
std::optional< EigenVector_ > scale
Definition blocked_pca.hpp:759
irlba::Metrics metrics
Definition blocked_pca.hpp:764
EigenMatrix_ rotation
Definition blocked_pca.hpp:742
EigenMatrix_ center
Definition blocked_pca.hpp:750
EigenVector_ variance_explained
Definition blocked_pca.hpp:729