1#ifndef SCRAN_PCA_BLOCKED_PCA_HPP
2#define SCRAN_PCA_BLOCKED_PCA_HPP
15#include "sanisizer/sanisizer.hpp"
105template<
typename Index_,
class EigenVector_>
106struct BlockingDetails {
107 std::vector<Index_> block_size;
109 bool weighted =
false;
110 typedef typename EigenVector_::Scalar Weight;
113 std::vector<Weight> per_element_weight;
114 Weight total_block_weight = 0;
115 EigenVector_ expanded_weights;
118template<
class EigenVector_,
typename Index_,
typename Block_>
119BlockingDetails<Index_, EigenVector_> compute_blocking_details(
125 BlockingDetails<Index_, EigenVector_> output;
126 output.block_size = tatami_stats::tabulate_groups(block, ncells);
127 if (block_weight_policy == scran_blocks::WeightPolicy::NONE) {
131 const auto& block_size = output.block_size;
132 auto nblocks = block_size.size();
133 output.weighted =
true;
134 auto& total_weight = output.total_block_weight;
135 auto& element_weight = output.per_element_weight;
136 element_weight.resize(sanisizer::cast<
decltype(element_weight.size())>(nblocks));
138 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
139 auto bsize = block_size[b];
145 typename EigenVector_::Scalar block_weight = 1;
146 if (block_weight_policy == scran_blocks::WeightPolicy::VARIABLE) {
150 element_weight[b] = block_weight / bsize;
151 total_weight += block_weight;
153 element_weight[b] = 0;
158 if (total_weight == 0) {
163 auto sqrt_weights = element_weight;
164 for (
auto& s : sqrt_weights) {
168 auto& expanded = output.expanded_weights;
169 expanded.resize(sanisizer::cast<
decltype(expanded.size())>(ncells));
170 for (Index_ c = 0; c < ncells; ++c) {
171 expanded.coeffRef(c) = sqrt_weights[block[c]];
181template<
typename Num_,
typename Value_,
typename Index_,
typename Block_,
typename EigenVector_,
typename Float_>
182void compute_sparse_mean_and_variance_blocked(
184 const Value_* values,
185 const Index_* indices,
187 const BlockingDetails<Index_, EigenVector_>& block_details,
190 std::vector<Index_>& block_copy,
193 const auto& block_size = block_details.block_size;
194 auto nblocks = block_size.size();
196 std::fill_n(centers, nblocks, 0);
197 for (Num_ i = 0; i < num_nonzero; ++i) {
198 centers[block[indices[i]]] += values[i];
200 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
201 auto bsize = block_size[b];
212 std::copy(block_size.begin(), block_size.end(), block_copy.begin());
214 if (block_details.weighted) {
215 for (Num_ i = 0; i < num_nonzero; ++i) {
216 Block_ curb = block[indices[i]];
217 auto diff = values[i] - centers[curb];
218 variance += diff * diff * block_details.per_element_weight[curb];
221 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
222 auto val = centers[b];
223 variance += val * val * block_copy[b] * block_details.per_element_weight[b];
226 for (Num_ i = 0; i < num_nonzero; ++i) {
227 Block_ curb = block[indices[i]];
228 auto diff = values[i] - centers[curb];
229 variance += diff * diff;
232 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
233 auto val = centers[b];
234 variance += val * val * block_copy[b];
247 variance /= num_all - 1;
250template<
class IrlbaSparseMatrix_,
typename Block_,
class Index_,
class EigenVector_,
class EigenMatrix_>
251void compute_blockwise_mean_and_variance_realized_sparse(
252 const IrlbaSparseMatrix_& emat,
254 const BlockingDetails<Index_, EigenVector_>& block_details,
255 EigenMatrix_& centers,
256 EigenVector_& variances,
259 auto ngenes = emat.cols();
261 auto ncells = emat.rows();
262 const auto& values = emat.get_values();
263 const auto& indices = emat.get_indices();
264 const auto& pointers = emat.get_pointers();
266 auto nblocks = block_details.block_size.size();
267 static_assert(!EigenMatrix_::IsRowMajor);
268 auto block_copy = sanisizer::create<std::vector<Index_> >(nblocks);
270 for (
auto g = start, end = start + length; g < end; ++g) {
271 auto offset = pointers[g];
272 auto next_offset = pointers[g + 1];
273 compute_sparse_mean_and_variance_blocked(
274 static_cast<decltype(ncells)
>(next_offset - offset),
275 values.data() + offset,
276 indices.data() + offset,
279 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
285 }, ngenes, nthreads);
288template<
typename Num_,
typename Value_,
typename Block_,
typename Index_,
typename EigenVector_,
typename Float_>
289void compute_dense_mean_and_variance_blocked(
291 const Value_* values,
293 const BlockingDetails<Index_, EigenVector_>& block_details,
297 const auto& block_size = block_details.block_size;
298 auto nblocks = block_size.size();
299 std::fill_n(centers, nblocks, 0);
300 for (Num_ i = 0; i < number; ++i) {
301 centers[block[i]] += values[i];
303 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
304 const auto& bsize = block_size[b];
312 if (block_details.weighted) {
313 for (Num_ i = 0; i < number; ++i) {
314 auto curb = block[i];
315 auto delta = values[i] - centers[curb];
316 variance += delta * delta * block_details.per_element_weight[curb];
319 for (Num_ i = 0; i < number; ++i) {
320 auto curb = block[i];
321 auto delta = values[i] - centers[curb];
322 variance += delta * delta;
326 variance /= number - 1;
329template<
class EigenMatrix_,
typename Block_,
class Index_,
class EigenVector_>
330void compute_blockwise_mean_and_variance_realized_dense(
331 const EigenMatrix_& emat,
333 const BlockingDetails<Index_, EigenVector_>& block_details,
334 EigenMatrix_& centers,
335 EigenVector_& variances,
338 auto ngenes = emat.cols();
340 auto ncells = emat.rows();
341 static_assert(!EigenMatrix_::IsRowMajor);
342 auto nblocks = block_details.block_size.size();
343 for (
auto g = start, end = start + length; g < end; ++g) {
344 compute_dense_mean_and_variance_blocked(
346 emat.data() + sanisizer::product_unsafe<std::size_t>(g, ncells),
349 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
353 }, ngenes, nthreads);
356template<
typename Value_,
typename Index_,
typename Block_,
class EigenMatrix_,
class EigenVector_>
357void compute_blockwise_mean_and_variance_tatami(
360 const BlockingDetails<Index_, EigenVector_>& block_details,
361 EigenMatrix_& centers,
362 EigenVector_& variances,
365 const auto& block_size = block_details.block_size;
366 auto nblocks = block_size.size();
367 Index_ ngenes = mat.
nrow();
368 Index_ ncells = mat.
ncol();
372 static_assert(!EigenMatrix_::IsRowMajor);
373 auto block_copy = sanisizer::create<std::vector<Index_> >(nblocks);
379 for (Index_ g = start, end = start + length; g < end; ++g) {
380 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
381 compute_sparse_mean_and_variance_blocked(
387 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
395 for (Index_ g = start, end = start + length; g < end; ++g) {
396 auto ptr = ext->fetch(vbuffer.data());
397 compute_dense_mean_and_variance_blocked(
402 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
407 }, ngenes, nthreads);
410 typedef typename EigenVector_::Scalar Scalar;
412 std::vector<std::pair<
decltype(nblocks), Scalar> > block_multipliers;
413 block_multipliers.reserve(nblocks);
414 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
415 auto bsize = block_size[b];
417 Scalar mult = bsize - 1;
418 if (block_details.weighted) {
419 mult *= block_details.per_element_weight[b];
421 block_multipliers.emplace_back(b, mult);
426 std::vector<std::vector<Scalar> > re_centers, re_variances;
427 re_centers.reserve(nblocks);
428 re_variances.reserve(nblocks);
429 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
430 re_centers.emplace_back(length);
431 re_variances.emplace_back(length);
437 std::vector<tatami_stats::variances::RunningSparse<Scalar, Value_, Index_> > running;
438 running.reserve(nblocks);
439 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
440 running.emplace_back(length, re_centers[b].data(), re_variances[b].data(),
false, start);
445 for (Index_ c = 0; c < ncells; ++c) {
446 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
447 running[block[c]].add(range.value, range.index, range.number);
450 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
455 std::vector<tatami_stats::variances::RunningDense<Scalar, Value_, Index_> > running;
456 running.reserve(nblocks);
457 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
458 running.emplace_back(length, re_centers[b].data(), re_variances[b].data(),
false);
462 for (Index_ c = 0; c < ncells; ++c) {
463 auto ptr = ext->fetch(vbuffer.data());
464 running[block[c]].add(ptr);
467 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
472 static_assert(!EigenMatrix_::IsRowMajor);
473 for (Index_ i = 0; i < length; ++i) {
474 auto mptr = centers.data() + sanisizer::product_unsafe<std::size_t>(start + i, nblocks);
475 for (
decltype(nblocks) b = 0; b < nblocks; ++b) {
476 mptr[b] = re_centers[b][i];
479 auto& my_var = variances[start + i];
481 for (
const auto& bm : block_multipliers) {
482 my_var += re_variances[bm.first][i] * bm.second;
484 my_var /= ncells - 1;
486 }, ngenes, nthreads);
494template<
class EigenMatrix_,
class EigenVector_>
495const EigenMatrix_& scale_rotation_matrix(
const EigenMatrix_& rotation,
bool scale,
const EigenVector_& scale_v, EigenMatrix_& tmp) {
497 tmp = (rotation.array().colwise() / scale_v.array()).matrix();
504template<
class IrlbaSparseMatrix_,
class EigenMatrix_>
505inline void project_matrix_realized_sparse(
506 const IrlbaSparseMatrix_& emat,
507 EigenMatrix_& components,
508 const EigenMatrix_& scaled_rotation,
511 auto rank = scaled_rotation.cols();
512 auto ncells = emat.rows();
513 auto ngenes = emat.cols();
517 sanisizer::cast<
decltype(components.rows())>(rank),
518 sanisizer::cast<
decltype(components.cols())>(ncells)
520 components.setZero();
522 const auto& values = emat.get_values();
523 const auto& indices = emat.get_indices();
526 const auto& pointers = emat.get_pointers();
527 auto multipliers = sanisizer::create<Eigen::VectorXd>(rank);
528 for (
decltype(ngenes) g = 0; g < ngenes; ++g) {
529 multipliers.noalias() = scaled_rotation.row(g);
530 auto start = pointers[g], end = pointers[g + 1];
531 for (
auto i = start; i < end; ++i) {
532 components.col(indices[i]).noalias() += values[i] * multipliers;
537 const auto& row_nonzero_starts = emat.get_secondary_nonzero_starts();
539 const auto& starts = row_nonzero_starts[t];
540 const auto& ends = row_nonzero_starts[t + 1];
541 auto multipliers = sanisizer::create<Eigen::VectorXd>(rank);
543 for (
decltype(ngenes) g = 0; g < ngenes; ++g) {
544 multipliers.noalias() = scaled_rotation.row(g);
545 auto start = starts[g], end = ends[g];
546 for (
auto i = start; i < end; ++i) {
547 components.col(indices[i]).noalias() += values[i] * multipliers;
554template<
typename Value_,
typename Index_,
class EigenMatrix_>
555void project_matrix_transposed_tatami(
557 EigenMatrix_& components,
558 const EigenMatrix_& scaled_rotation,
561 auto rank = scaled_rotation.cols();
562 auto ngenes = mat.
nrow();
563 auto ncells = mat.
ncol();
564 typedef typename EigenMatrix_::Scalar Scalar;
568 sanisizer::cast<
decltype(components.rows())>(rank),
569 sanisizer::cast<
decltype(components.cols())>(ncells)
574 static_assert(!EigenMatrix_::IsRowMajor);
575 auto vptr = scaled_rotation.data();
578 std::vector<std::vector<Scalar> > local_buffers;
579 local_buffers.reserve(rank);
580 for (
decltype(rank) r = 0; r < rank; ++r) {
587 for (Index_ g = 0; g < ngenes; ++g) {
588 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
589 for (
decltype(rank) r = 0; r < rank; ++r) {
590 auto mult = vptr[sanisizer::nd_offset<std::size_t>(g, ngenes, r)];
591 auto& local_buffer = local_buffers[r];
592 for (Index_ i = 0; i < range.number; ++i) {
593 local_buffer[range.index[i] - start] += range.value[i] * mult;
600 for (Index_ g = 0; g < ngenes; ++g) {
601 auto ptr = ext->fetch(vbuffer.data());
602 for (
decltype(rank) r = 0; r < rank; ++r) {
603 auto mult = vptr[sanisizer::nd_offset<std::size_t>(g, ngenes, r)];
604 auto& local_buffer = local_buffers[r];
605 for (Index_ i = 0; i < length; ++i) {
606 local_buffer[i] += ptr[i] * mult;
612 for (
decltype(rank) r = 0; r < rank; ++r) {
613 for (Index_ c = 0; c < length; ++c) {
614 components.coeffRef(r, c + start) = local_buffers[r][c];
618 }, ncells, nthreads);
622 static_assert(!EigenMatrix_::IsRowMajor);
626 std::vector<Index_> ibuffer(ngenes);
629 for (Index_ c = start, end = start + length; c < end; ++c) {
630 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
631 static_assert(!EigenMatrix_::IsRowMajor);
632 for (
decltype(rank) r = 0; r < rank; ++r) {
633 auto& output = components.coeffRef(r, c);
635 auto rotptr = scaled_rotation.data() + sanisizer::product_unsafe<std::size_t>(r, ngenes);
636 for (Index_ i = 0; i < range.number; ++i) {
637 output += rotptr[range.index[i]] * range.value[i];
644 for (Index_ c = start, end = start + length; c < end; ++c) {
645 auto ptr = ext->fetch(vbuffer.data());
646 static_assert(!EigenMatrix_::IsRowMajor);
647 for (
decltype(rank) r = 0; r < rank; ++r) {
648 auto rotptr = scaled_rotation.data() + sanisizer::product_unsafe<std::size_t>(r, ngenes);
649 components.coeffRef(r, c) = std::inner_product(rotptr, rotptr + ngenes, ptr,
static_cast<Scalar
>(0));
653 }, ncells, nthreads);
657template<
class EigenMatrix_,
class EigenVector_>
658void clean_up_projected(EigenMatrix_& projected, EigenVector_& D) {
661 for (
decltype(projected.rows()) i = 0, prows = projected.rows(); i < prows; ++i) {
662 projected.row(i).array() -= projected.row(i).sum() / projected.cols();
666 typename EigenMatrix_::Scalar denom = projected.cols() - 1;
678template<
class Matrix_,
typename Block_,
class EigenMatrix_,
class EigenVector_>
679class ResidualWrapper {
681 ResidualWrapper(
const Matrix_& mat,
const Block_* block,
const EigenMatrix_& means) : my_mat(mat), my_block(block), my_means(means) {}
684 Eigen::Index rows()
const {
return my_mat.rows(); }
685 Eigen::Index cols()
const {
return my_mat.cols(); }
689 template<
typename NumBlocks_>
691 sub(sanisizer::cast<decltype(sub.size())>(nblocks)),
696 EigenVector_ holding;
700 Workspace workspace()
const {
704 template<
class Right_>
705 void multiply(
const Right_& rhs, Workspace& work, EigenVector_& output)
const {
706 const auto& realized_rhs = [&]() ->
const auto& {
707 if constexpr(std::is_same<Right_, EigenVector_>::value) {
710 work.holding.noalias() = rhs;
717 work.sub.noalias() = my_means * realized_rhs;
718 for (
decltype(output.size()) i = 0, end = output.size(); i < end; ++i) {
719 auto& val = output.coeffRef(i);
720 val -= work.sub.coeff(my_block[i]);
725 struct AdjointWorkspace {
726 template<
typename NumBlocks_>
728 aggr(sanisizer::cast<decltype(aggr.size())>(nblocks)),
733 EigenVector_ holding;
737 AdjointWorkspace adjoint_workspace()
const {
741 template<
class Right_>
742 void adjoint_multiply(
const Right_& rhs, AdjointWorkspace& work, EigenVector_& output)
const {
743 const auto& realized_rhs = [&]() {
744 if constexpr(std::is_same<Right_, EigenVector_>::value) {
747 work.holding.noalias() = rhs;
755 for (
decltype(realized_rhs.size()) i = 0, end = realized_rhs.size(); i < end; ++i) {
756 work.aggr.coeffRef(my_block[i]) += realized_rhs.coeff(i);
759 output.noalias() -= my_means.adjoint() * work.aggr;
763 template<
class EigenMatrix2_>
764 EigenMatrix2_ realize()
const {
766 for (
decltype(output.rows()) i = 0, end = output.rows(); i < end; ++i) {
767 output.row(i) -= my_means.row(my_block[i]);
773 const Matrix_& my_mat;
774 const Block_* my_block;
775 const EigenMatrix_& my_means;
782template<
bool realize_matrix_,
bool sparse_,
typename Value_,
typename Index_,
typename Block_,
class EigenMatrix_,
class EigenVector_>
786 const BlockingDetails<Index_, EigenVector_>& block_details,
787 const BlockedPcaOptions& options,
788 EigenMatrix_& components,
789 EigenMatrix_& rotation,
790 EigenVector_& variance_explained,
791 EigenMatrix_& center_m,
792 EigenVector_& scale_v,
793 typename EigenVector_::Scalar& total_var,
796 Index_ ngenes = mat.
nrow(), ncells = mat.
ncol();
799 if constexpr(!realize_matrix_) {
800 return internal::TransposedTatamiWrapper<EigenVector_, Value_, Index_>(mat, options.num_threads);
802 }
else if constexpr(sparse_) {
814 return irlba::ParallelSparseMatrix(ncells, ngenes, std::move(extracted.value), std::move(extracted.index), std::move(extracted.pointers),
true, options.num_threads);
819 sanisizer::cast<
decltype(std::declval<EigenMatrix_>().rows())>(ncells),
820 sanisizer::cast<
decltype(std::declval<EigenMatrix_>().rows())>(ngenes)
822 static_assert(!EigenMatrix_::IsRowMajor);
828 tatami::ConvertToDenseOptions opt;
829 opt.num_threads = options.num_threads;
837 auto nblocks = block_details.block_size.size();
839 sanisizer::cast<
decltype(center_m.rows())>(nblocks),
840 sanisizer::cast<
decltype(center_m.cols())>(ngenes)
842 scale_v.resize(sanisizer::cast<
decltype(scale_v.size())>(ngenes));
844 if constexpr(!realize_matrix_) {
845 compute_blockwise_mean_and_variance_tatami(mat, block, block_details, center_m, scale_v, options.num_threads);
846 }
else if constexpr(sparse_) {
847 compute_blockwise_mean_and_variance_realized_sparse(emat, block, block_details, center_m, scale_v, options.num_threads);
849 compute_blockwise_mean_and_variance_realized_dense(emat, block, block_details, center_m, scale_v, options.num_threads);
851 total_var = internal::process_scale_vector(options.scale, scale_v);
853 ResidualWrapper<
decltype(emat), Block_, EigenMatrix_, EigenVector_> centered(emat, block, center_m);
855 if (block_details.weighted) {
857 irlba::Scaled<
true,
decltype(centered), EigenVector_> scaled(centered, scale_v,
true);
858 irlba::Scaled<
false,
decltype(scaled), EigenVector_> weighted(scaled, block_details.expanded_weights,
false);
859 auto out =
irlba::compute(weighted, options.number, components, rotation, variance_explained, options.irlba_options);
860 converged = out.first;
862 irlba::Scaled<
false,
decltype(centered), EigenVector_> weighted(centered, block_details.expanded_weights,
false);
863 auto out =
irlba::compute(weighted, options.number, components, rotation, variance_explained, options.irlba_options);
864 converged = out.first;
868 const auto& scaled_rotation = scale_rotation_matrix(rotation, options.scale, scale_v, tmp);
871 if constexpr(!realize_matrix_) {
872 project_matrix_transposed_tatami(mat, components, scaled_rotation, options.num_threads);
873 }
else if constexpr(sparse_) {
874 project_matrix_realized_sparse(emat, components, scaled_rotation, options.num_threads);
876 components.noalias() = (emat * scaled_rotation).adjoint();
880 if (options.components_from_residuals) {
881 EigenMatrix_ centering = (center_m * scaled_rotation).adjoint();
882 for (
decltype(ncells) c =0 ; c < ncells; ++c) {
883 components.col(c) -= centering.col(block[c]);
887 clean_up_projected(components, variance_explained);
888 if (!options.transpose) {
889 components.adjointInPlace();
894 irlba::Scaled<
true,
decltype(centered), EigenVector_> scaled(centered, scale_v,
true);
895 auto out =
irlba::compute(scaled, options.number, components, rotation, variance_explained, options.irlba_options);
896 converged = out.first;
898 auto out =
irlba::compute(centered, options.number, components, rotation, variance_explained, options.irlba_options);
899 converged = out.first;
902 if (options.components_from_residuals) {
903 internal::clean_up(mat.
ncol(), components, variance_explained);
904 if (options.transpose) {
905 components.adjointInPlace();
909 const auto& scaled_rotation = scale_rotation_matrix(rotation, options.scale, scale_v, tmp);
912 if constexpr(!realize_matrix_) {
913 project_matrix_transposed_tatami(mat, components, scaled_rotation, options.num_threads);
914 }
else if constexpr(sparse_) {
915 project_matrix_realized_sparse(emat, components, scaled_rotation, options.num_threads);
917 components.noalias() = (emat * scaled_rotation).adjoint();
920 clean_up_projected(components, variance_explained);
921 if (!options.transpose) {
922 components.adjointInPlace();
939template<
typename EigenMatrix_,
typename EigenVector_>
1031template<
typename Value_,
typename Index_,
typename Block_,
typename EigenMatrix_,
class EigenVector_>
1036 EigenMatrix_& components = output.
components;
1037 EigenMatrix_& rotation = output.
rotation;
1039 EigenMatrix_& center_m = output.
center;
1040 EigenVector_& scale_v = output.
scale;
1046 internal::run_blocked<true, true>(mat, block, bdetails, options, components, rotation, variance_explained, center_m, scale_v, total_var, converged);
1048 internal::run_blocked<false, true>(mat, block, bdetails, options, components, rotation, variance_explained, center_m, scale_v, total_var, converged);
1052 internal::run_blocked<true, false>(mat, block, bdetails, options, components, rotation, variance_explained, center_m, scale_v, total_var, converged);
1054 internal::run_blocked<false, false>(mat, block, bdetails, options, components, rotation, variance_explained, center_m, scale_v, total_var, converged);
1058 if (!options.
scale) {
1059 output.
scale = EigenVector_();
1082template<
typename EigenMatrix_ = Eigen::MatrixXd,
class EigenVector_ = Eigen::VectorXd,
typename Value_,
typename Index_,
typename Block_>
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual bool is_sparse() const=0
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
void wrapped_adjoint_multiply(const Matrix_ &matrix, const Right_ &rhs, WrappedAdjointWorkspace< Matrix_ > &work, EigenVector_ &out)
WrappedWorkspace< Matrix_ > wrapped_workspace(const Matrix_ &matrix)
std::pair< bool, int > compute(const Matrix_ &matrix, Eigen::Index number, EigenMatrix_ &outU, EigenMatrix_ &outV, EigenVector_ &outD, const Options &options)
void parallelize(Task_ num_tasks, Run_ run_task)
void wrapped_multiply(const Matrix_ &matrix, const Right_ &rhs, WrappedWorkspace< Matrix_ > &work, EigenVector_ &out)
WrappedAdjointWorkspace< Matrix_ > wrapped_adjoint_workspace(const Matrix_ &matrix)
typename get_adjoint_workspace< Matrix_ >::type WrappedAdjointWorkspace
EigenMatrix_ wrapped_realize(const Matrix_ &matrix)
typename get_workspace< Matrix_ >::type WrappedWorkspace
double compute_variable_weight(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 BlockedPcaOptions &options, BlockedPcaResults< EigenMatrix_, EigenVector_ > &output)
Definition blocked_pca.hpp:1032
CompressedSparseContents< StoredValue_, StoredIndex_, StoredPointer_ > retrieve_compressed_sparse_contents(const Matrix< InputValue_, InputIndex_ > &matrix, bool row, const RetrieveCompressedSparseContentsOptions &options)
decltype(std::declval< Container_ >().size()) cast_Index_to_container_size(Index_ x)
void parallelize(Function_ fun, Index_ tasks, int threads)
Container_ create_container_of_Index_size(Index_ x, Args_ &&... args)
void convert_to_dense(const Matrix< InputValue_, InputIndex_ > &matrix, bool row_major, StoredValue_ *store, const ConvertToDenseOptions &options)
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Options for blocked_pca().
Definition blocked_pca.hpp:30
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition blocked_pca.hpp:69
int num_threads
Definition blocked_pca.hpp:88
bool components_from_residuals
Definition blocked_pca.hpp:76
bool realize_matrix
Definition blocked_pca.hpp:82
irlba::Options irlba_options
Definition blocked_pca.hpp:93
bool transpose
Definition blocked_pca.hpp:58
scran_blocks::WeightPolicy block_weight_policy
Definition blocked_pca.hpp:63
int number
Definition blocked_pca.hpp:46
bool scale
Definition blocked_pca.hpp:52
Results of blocked_pca().
Definition blocked_pca.hpp:940
EigenVector_::Scalar total_variance
Definition blocked_pca.hpp:960
bool converged
Definition blocked_pca.hpp:985
EigenMatrix_ components
Definition blocked_pca.hpp:947
EigenMatrix_ rotation
Definition blocked_pca.hpp:967
EigenVector_ scale
Definition blocked_pca.hpp:980
EigenMatrix_ center
Definition blocked_pca.hpp:974
EigenVector_ variance_explained
Definition blocked_pca.hpp:954