1#ifndef SCRAN_PCA_BLOCKED_PCA_HPP
2#define SCRAN_PCA_BLOCKED_PCA_HPP
14#include "irlba_tatami/irlba_tatami.hpp"
17#include "sanisizer/sanisizer.hpp"
33template<
typename EigenVector_ = Eigen::VectorXd>
119template<
typename Index_,
class EigenVector_>
120struct BlockingDetails {
121 std::vector<Index_> block_size;
123 bool weighted =
false;
124 typedef typename EigenVector_::Scalar Weight;
127 std::vector<Weight> per_element_weight;
128 Weight total_block_weight = 0;
129 EigenVector_ expanded_weights;
132template<
class EigenVector_,
typename Index_,
typename Block_>
133BlockingDetails<Index_, EigenVector_> compute_blocking_details(
139 BlockingDetails<Index_, EigenVector_> output;
140 output.block_size = tatami_stats::tabulate_groups(block, ncells);
141 if (block_weight_policy == scran_blocks::WeightPolicy::NONE) {
145 const auto& block_size = output.block_size;
146 const auto nblocks = block_size.size();
147 output.weighted =
true;
148 auto& total_weight = output.total_block_weight;
149 auto& element_weight = output.per_element_weight;
150 sanisizer::resize(element_weight, nblocks);
152 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
153 const auto bsize = block_size[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 sanisizer::resize(expanded, ncells);
184 for (Index_ c = 0; c < ncells; ++c) {
185 expanded.coeffRef(c) = sqrt_weights[block[c]];
195template<
typename Num_,
typename Value_,
typename Index_,
typename Block_,
typename EigenVector_,
typename Float_>
196void compute_sparse_mean_and_variance_blocked(
197 const Num_ num_nonzero,
198 const Value_* values,
199 const Index_* indices,
201 const BlockingDetails<Index_, EigenVector_>& block_details,
204 std::vector<Index_>& block_copy,
207 const auto& block_size = block_details.block_size;
208 const auto nblocks = block_size.size();
210 std::fill_n(centers, nblocks, 0);
211 for (Num_ i = 0; i < num_nonzero; ++i) {
212 centers[block[indices[i]]] += values[i];
214 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
215 auto bsize = block_size[b];
226 std::copy(block_size.begin(), block_size.end(), block_copy.begin());
228 if (block_details.weighted) {
229 for (Num_ i = 0; i < num_nonzero; ++i) {
230 const Block_ curb = block[indices[i]];
231 const auto diff = values[i] - centers[curb];
232 variance += diff * diff * block_details.per_element_weight[curb];
235 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
236 const auto val = centers[b];
237 variance += val * val * block_copy[b] * block_details.per_element_weight[b];
240 for (Num_ i = 0; i < num_nonzero; ++i) {
241 const Block_ curb = block[indices[i]];
242 const auto diff = values[i] - centers[curb];
243 variance += diff * diff;
246 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
247 const auto val = centers[b];
248 variance += val * val * block_copy[b];
261 variance /= num_all - 1;
264template<
class IrlbaSparseMatrix_,
typename Block_,
class Index_,
class EigenVector_,
class EigenMatrix_>
265void compute_blockwise_mean_and_variance_realized_sparse(
266 const IrlbaSparseMatrix_& emat,
268 const BlockingDetails<Index_, EigenVector_>& block_details,
269 EigenMatrix_& centers,
270 EigenVector_& variances,
273 const auto ngenes = emat.cols();
274 tatami::parallelize([&](
const int,
const I<
decltype(ngenes)> start,
const I<
decltype(ngenes)> length) ->
void {
275 const auto ncells = emat.rows();
276 const auto& values = emat.get_values();
277 const auto& indices = emat.get_indices();
278 const auto& pointers = emat.get_pointers();
280 const auto nblocks = block_details.block_size.size();
281 static_assert(!EigenMatrix_::IsRowMajor);
282 auto block_copy = sanisizer::create<std::vector<Index_> >(nblocks);
284 for (I<
decltype(start)> g = start, end = start + length; g < end; ++g) {
285 const auto offset = pointers[g];
286 const auto next_offset = pointers[g + 1];
287 compute_sparse_mean_and_variance_blocked(
288 static_cast<I<decltype(ncells)
> >(next_offset - offset),
289 values.data() + offset,
290 indices.data() + offset,
293 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
299 }, ngenes, nthreads);
302template<
typename Num_,
typename Value_,
typename Block_,
typename Index_,
typename EigenVector_,
typename Float_>
303void compute_dense_mean_and_variance_blocked(
305 const Value_* values,
307 const BlockingDetails<Index_, EigenVector_>& block_details,
311 const auto& block_size = block_details.block_size;
312 const auto nblocks = block_size.size();
313 std::fill_n(centers, nblocks, 0);
314 for (Num_ i = 0; i < number; ++i) {
315 centers[block[i]] += values[i];
317 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
318 const auto& bsize = block_size[b];
326 if (block_details.weighted) {
327 for (Num_ i = 0; i < number; ++i) {
328 const auto curb = block[i];
329 const auto delta = values[i] - centers[curb];
330 variance += delta * delta * block_details.per_element_weight[curb];
333 for (Num_ i = 0; i < number; ++i) {
334 const auto curb = block[i];
335 const auto delta = values[i] - centers[curb];
336 variance += delta * delta;
340 variance /= number - 1;
343template<
class EigenMatrix_,
typename Block_,
class Index_,
class EigenVector_>
344void compute_blockwise_mean_and_variance_realized_dense(
345 const EigenMatrix_& emat,
347 const BlockingDetails<Index_, EigenVector_>& block_details,
348 EigenMatrix_& centers,
349 EigenVector_& variances,
352 const auto ngenes = emat.cols();
353 tatami::parallelize([&](
const int,
const I<
decltype(ngenes)> start,
const I<
decltype(ngenes)> length) ->
void {
354 const auto ncells = emat.rows();
355 static_assert(!EigenMatrix_::IsRowMajor);
356 const auto nblocks = block_details.block_size.size();
357 for (I<
decltype(start)> g = start, end = start + length; g < end; ++g) {
358 compute_dense_mean_and_variance_blocked(
360 emat.data() + sanisizer::product_unsafe<std::size_t>(g, ncells),
363 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
367 }, ngenes, nthreads);
370template<
typename Value_,
typename Index_,
typename Block_,
class EigenMatrix_,
class EigenVector_>
371void compute_blockwise_mean_and_variance_tatami(
374 const BlockingDetails<Index_, EigenVector_>& block_details,
375 EigenMatrix_& centers,
376 EigenVector_& variances,
379 const auto& block_size = block_details.block_size;
380 const auto nblocks = block_size.size();
381 const Index_ ngenes = mat.
nrow();
382 const Index_ ncells = mat.
ncol();
386 static_assert(!EigenMatrix_::IsRowMajor);
387 auto block_copy = sanisizer::create<std::vector<Index_> >(nblocks);
393 for (Index_ g = start, end = start + length; g < end; ++g) {
394 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
395 compute_sparse_mean_and_variance_blocked(
401 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
410 for (Index_ g = start, end = start + length; g < end; ++g) {
411 auto ptr = ext->fetch(vbuffer.data());
412 compute_dense_mean_and_variance_blocked(
417 centers.data() + sanisizer::product_unsafe<std::size_t>(g, nblocks),
422 }, ngenes, nthreads);
425 typedef typename EigenVector_::Scalar Scalar;
426 std::vector<std::pair<I<
decltype(nblocks)>, Scalar> > block_multipliers;
427 block_multipliers.reserve(nblocks);
429 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
430 const auto bsize = block_size[b];
432 Scalar mult = bsize - 1;
433 if (block_details.weighted) {
434 mult *= block_details.per_element_weight[b];
436 block_multipliers.emplace_back(b, mult);
441 std::vector<std::vector<Scalar> > re_centers, re_variances;
442 re_centers.reserve(nblocks);
443 re_variances.reserve(nblocks);
444 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
445 re_centers.emplace_back(length);
446 re_variances.emplace_back(length);
452 std::vector<tatami_stats::variances::RunningSparse<Scalar, Value_, Index_> > running;
453 running.reserve(nblocks);
454 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
455 running.emplace_back(length, re_centers[b].data(), re_variances[b].data(),
false, start);
460 for (Index_ c = 0; c < ncells; ++c) {
461 const auto range = ext->fetch(vbuffer.data(), ibuffer.data());
462 running[block[c]].add(range.value, range.index, range.number);
465 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
470 std::vector<tatami_stats::variances::RunningDense<Scalar, Value_, Index_> > running;
471 running.reserve(nblocks);
472 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
473 running.emplace_back(length, re_centers[b].data(), re_variances[b].data(),
false);
477 for (Index_ c = 0; c < ncells; ++c) {
478 auto ptr = ext->fetch(vbuffer.data());
479 running[block[c]].add(ptr);
482 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
487 static_assert(!EigenMatrix_::IsRowMajor);
488 for (Index_ i = 0; i < length; ++i) {
489 auto mptr = centers.data() + sanisizer::product_unsafe<std::size_t>(start + i, nblocks);
490 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
491 mptr[b] = re_centers[b][i];
494 auto& my_var = variances[start + i];
496 for (
const auto& bm : block_multipliers) {
497 my_var += re_variances[bm.first][i] * bm.second;
499 my_var /= ncells - 1;
501 }, ngenes, nthreads);
509template<
class EigenMatrix_,
class EigenVector_>
510const EigenMatrix_& scale_rotation_matrix(
const EigenMatrix_& rotation,
bool scale,
const EigenVector_& scale_v, EigenMatrix_& tmp) {
512 tmp = (rotation.array().colwise() / scale_v.array()).matrix();
519template<
class EigenVector_,
class IrlbaSparseMatrix_,
class EigenMatrix_>
520inline void project_matrix_realized_sparse(
521 const IrlbaSparseMatrix_& emat,
522 EigenMatrix_& components,
523 const EigenMatrix_& scaled_rotation,
526 const auto rank = scaled_rotation.cols();
527 const auto ncells = emat.rows();
528 const auto ngenes = emat.cols();
532 sanisizer::cast<I<
decltype(components.rows())> >(rank),
533 sanisizer::cast<I<
decltype(components.cols())> >(ncells)
535 components.setZero();
537 const auto& values = emat.get_values();
538 const auto& indices = emat.get_indices();
539 const auto& pointers = emat.get_pointers();
542 auto multipliers = sanisizer::create<EigenVector_>(rank);
543 for (I<
decltype(ngenes)> g = 0; g < ngenes; ++g) {
544 multipliers.noalias() = scaled_rotation.row(g);
545 const auto start = pointers[g], end = pointers[g + 1];
546 for (
auto i = start; i < end; ++i) {
547 components.col(indices[i]).noalias() += values[i] * multipliers;
557 const auto& primary_bounds = emat.get_primary_boundaries();
558 auto working = sanisizer::create<std::vector<EigenMatrix_> >(nthreads - 1);
565 auto& mat = working[t - 1];
566 mat.resize(components.rows(), components.cols());
571 const auto gstart = primary_bounds[t];
572 const auto gend = primary_bounds[t + 1];
573 auto multipliers = sanisizer::create<EigenVector_>(rank);
574 for (I<
decltype(ngenes)> g = gstart; g < gend; ++g) {
575 multipliers.noalias() = scaled_rotation.row(g);
576 const auto start = pointers[g], end = pointers[g + 1];
577 for (
auto i = start; i < end; ++i) {
578 ptr->col(indices[i]).noalias() += values[i] * multipliers;
583 for (
auto& w : working) {
589template<
typename Value_,
typename Index_,
class EigenMatrix_>
590void project_matrix_transposed_tatami(
592 EigenMatrix_& components,
593 const EigenMatrix_& scaled_rotation,
596 const auto rank = scaled_rotation.cols();
597 const auto ngenes = mat.
nrow();
598 const auto ncells = mat.
ncol();
599 typedef typename EigenMatrix_::Scalar Scalar;
603 sanisizer::cast<I<
decltype(components.rows())> >(rank),
604 sanisizer::cast<I<
decltype(components.cols())> >(ncells)
609 static_assert(!EigenMatrix_::IsRowMajor);
610 const auto vptr = scaled_rotation.data();
613 std::vector<std::vector<Scalar> > local_buffers;
614 local_buffers.reserve(rank);
615 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
622 for (Index_ g = 0; g < ngenes; ++g) {
623 const auto range = ext->fetch(vbuffer.data(), ibuffer.data());
624 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
625 const auto mult = vptr[sanisizer::nd_offset<std::size_t>(g, ngenes, r)];
626 auto& local_buffer = local_buffers[r];
627 for (Index_ i = 0; i < range.number; ++i) {
628 local_buffer[range.index[i] - start] += range.value[i] * mult;
635 for (Index_ g = 0; g < ngenes; ++g) {
636 const auto ptr = ext->fetch(vbuffer.data());
637 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
638 const auto mult = vptr[sanisizer::nd_offset<std::size_t>(g, ngenes, r)];
639 auto& local_buffer = local_buffers[r];
640 for (Index_ i = 0; i < length; ++i) {
641 local_buffer[i] += ptr[i] * mult;
647 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
648 for (Index_ c = 0; c < length; ++c) {
649 components.coeffRef(r, c + start) = local_buffers[r][c];
653 }, ncells, nthreads);
657 static_assert(!EigenMatrix_::IsRowMajor);
661 std::vector<Index_> ibuffer(ngenes);
664 for (Index_ c = start, end = start + length; c < end; ++c) {
665 const auto range = ext->fetch(vbuffer.data(), ibuffer.data());
666 static_assert(!EigenMatrix_::IsRowMajor);
667 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
668 auto& output = components.coeffRef(r, c);
670 const auto rotptr = scaled_rotation.data() + sanisizer::product_unsafe<std::size_t>(r, ngenes);
671 for (Index_ i = 0; i < range.number; ++i) {
672 output += rotptr[range.index[i]] * range.value[i];
679 for (Index_ c = start, end = start + length; c < end; ++c) {
680 const auto ptr = ext->fetch(vbuffer.data());
681 static_assert(!EigenMatrix_::IsRowMajor);
682 for (I<
decltype(rank)> r = 0; r < rank; ++r) {
683 const auto rotptr = scaled_rotation.data() + sanisizer::product_unsafe<std::size_t>(r, ngenes);
684 components.coeffRef(r, c) = std::inner_product(rotptr, rotptr + ngenes, ptr,
static_cast<Scalar
>(0));
688 }, ncells, nthreads);
692template<
class EigenMatrix_,
class EigenVector_>
693void clean_up_projected(EigenMatrix_& projected, EigenVector_& D) {
696 for (I<
decltype(projected.rows())> i = 0, prows = projected.rows(); i < prows; ++i) {
697 projected.row(i).array() -= projected.row(i).sum() / projected.cols();
701 const typename EigenMatrix_::Scalar denom = projected.cols() - 1;
711template<
class EigenVector_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
714 ResidualWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
715 my_work(matrix.new_known_workspace()),
718 my_sub(sanisizer::cast<I<decltype(my_sub.size())> >(my_means.rows()))
722 I<decltype(std::declval<IrlbaMatrix_>().new_known_workspace())> my_work;
723 const Block_* my_block;
724 const CenterMatrix_& my_means;
728 void multiply(
const EigenVector_& right, EigenVector_& output) {
729 my_work->multiply(right, output);
731 my_sub.noalias() = my_means * right;
732 for (I<
decltype(output.size())> i = 0, end = output.size(); i < end; ++i) {
733 auto& val = output.coeffRef(i);
734 val -= my_sub.coeff(my_block[i]);
739template<
class EigenVector_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
742 ResidualAdjointWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
743 my_work(matrix.new_known_adjoint_workspace()),
746 my_aggr(sanisizer::cast<I<decltype(my_aggr.size())> >(my_means.rows()))
750 I<decltype(std::declval<IrlbaMatrix_>().new_known_adjoint_workspace())> my_work;
751 const Block_* my_block;
752 const CenterMatrix_& my_means;
753 EigenVector_ my_aggr;
756 void multiply(
const EigenVector_& right, EigenVector_& output) {
757 my_work->multiply(right, output);
760 for (I<
decltype(right.size())> i = 0, end = right.size(); i < end; ++i) {
761 my_aggr.coeffRef(my_block[i]) += right.coeff(i);
764 output.noalias() -= my_means.adjoint() * my_aggr;
768template<
class EigenMatrix_,
class IrlbaMatrix_,
typename Block_,
class CenterMatrix_>
771 ResidualRealizeWorkspace(
const IrlbaMatrix_& matrix,
const Block_* block,
const CenterMatrix_& means) :
772 my_work(matrix.new_known_realize_workspace()),
778 I<decltype(std::declval<IrlbaMatrix_>().new_known_realize_workspace())> my_work;
779 const Block_* my_block;
780 const CenterMatrix_& my_means;
783 const EigenMatrix_& realize(EigenMatrix_& buffer) {
784 my_work->realize_copy(buffer);
785 for (I<
decltype(buffer.rows())> i = 0, end = buffer.rows(); i < end; ++i) {
786 buffer.row(i) -= my_means.row(my_block[i]);
794template<
class EigenVector_,
class EigenMatrix_,
class IrlbaMatrixPo
inter_,
class Block_,
class CenterMatrixPo
inter_>
795class ResidualMatrix final :
public irlba::Matrix<EigenVector_, EigenMatrix_> {
797 ResidualMatrix(IrlbaMatrixPointer_ mat,
const Block_* block, CenterMatrixPointer_ means) :
798 my_matrix(std::move(mat)),
800 my_means(std::move(means))
804 Eigen::Index rows()
const {
805 return my_matrix->rows();
808 Eigen::Index cols()
const {
809 return my_matrix->cols();
813 IrlbaMatrixPointer_ my_matrix;
814 const Block_* my_block;
815 CenterMatrixPointer_ my_means;
818 std::unique_ptr<irlba::Workspace<EigenVector_> > new_workspace()
const {
819 return new_known_workspace();
822 std::unique_ptr<irlba::AdjointWorkspace<EigenVector_> > new_adjoint_workspace()
const {
823 return new_known_adjoint_workspace();
826 std::unique_ptr<irlba::RealizeWorkspace<EigenMatrix_> > new_realize_workspace()
const {
827 return new_known_realize_workspace();
831 std::unique_ptr<ResidualWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_workspace()
const {
832 return std::make_unique<ResidualWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
835 std::unique_ptr<ResidualAdjointWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_adjoint_workspace()
const {
836 return std::make_unique<ResidualAdjointWorkspace<EigenVector_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
839 std::unique_ptr<ResidualRealizeWorkspace<EigenMatrix_,
decltype(*my_matrix), Block_,
decltype(*my_means)> > new_known_realize_workspace()
const {
840 return std::make_unique<ResidualRealizeWorkspace<EigenMatrix_,
decltype(*my_matrix), Block_,
decltype(*my_means)> >(*my_matrix, my_block, *my_means);
853template<
typename EigenMatrix_,
typename EigenVector_>
907template<
typename Value_,
typename Index_,
typename Block_,
typename EigenMatrix_,
class EigenVector_,
class SubsetFunction_>
908void blocked_pca_internal(
913 SubsetFunction_ subset_fun
918 const Index_ ngenes = mat.
nrow(), ncells = mat.
ncol();
919 const auto nblocks = block_details.block_size.size();
921 sanisizer::cast<I<
decltype(output.
center.rows())> >(nblocks),
922 sanisizer::cast<I<
decltype(output.
center.cols())> >(ngenes)
924 sanisizer::resize(output.
scale, ngenes);
926 std::unique_ptr<irlba::Matrix<EigenVector_, EigenMatrix_> > ptr;
927 std::function<void(
const EigenMatrix_&)> projector;
930 ptr.reset(
new irlba_tatami::Transposed<EigenVector_, EigenMatrix_, Value_, Index_,
decltype(&mat)>(&mat, options.
num_threads));
931 compute_blockwise_mean_and_variance_tatami(mat, block, block_details, output.
center, output.
scale, options.
num_threads);
933 projector = [&](
const EigenMatrix_& scaled_rotation) ->
void {
937 }
else if (mat.
sparse()) {
956 I<
decltype(extracted.value)>,
957 I<
decltype(extracted.index)>,
958 I<
decltype(extracted.pointers)>
962 std::move(extracted.value),
963 std::move(extracted.index),
964 std::move(extracted.pointers),
968 ptr.reset(sparse_ptr);
970 compute_blockwise_mean_and_variance_realized_sparse(*sparse_ptr, block, block_details, output.
center, output.
scale, options.
num_threads);
973 projector = [&,sparse_ptr](
const EigenMatrix_& scaled_rotation) ->
void {
974 project_matrix_realized_sparse<EigenVector_>(*sparse_ptr, output.
components, scaled_rotation, options.
num_threads);
979 auto tmp_ptr = std::make_unique<EigenMatrix_>(
980 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().rows())> >(ncells),
981 sanisizer::cast<I<
decltype(std::declval<EigenMatrix_>().cols())> >(ngenes)
983 static_assert(!EigenMatrix_::IsRowMajor);
990 tatami::ConvertToDenseOptions opt;
991 opt.num_threads = options.num_threads;
996 compute_blockwise_mean_and_variance_realized_dense(*tmp_ptr, block, block_details, output.
center, output.
scale, options.
num_threads);
997 const auto dense_ptr = tmp_ptr.get();
998 ptr.reset(
new irlba::SimpleMatrix<EigenVector_, EigenMatrix_,
decltype(tmp_ptr)>(std::move(tmp_ptr)));
1001 projector = [&,dense_ptr](
const EigenMatrix_& scaled_rotation) ->
void {
1002 output.
components.noalias() = (*dense_ptr * scaled_rotation).adjoint();
1008 std::unique_ptr<irlba::Matrix<EigenVector_, EigenMatrix_> > alt;
1015 I<
decltype(&(output.
center))>
1024 if (options.
scale) {
1030 I<
decltype(&(output.
scale))>
1041 if (block_details.weighted) {
1047 I<
decltype(&(block_details.expanded_weights))>
1050 &(block_details.expanded_weights),
1062 const auto& scaled_rotation = scale_rotation_matrix(output.
rotation, options.
scale, output.
scale, tmp);
1063 projector(scaled_rotation);
1067 EigenMatrix_ centering = (output.
center * scaled_rotation).adjoint();
1068 for (I<
decltype(ncells)> c =0 ; c < ncells; ++c) {
1069 output.
components.col(c) -= centering.col(block[c]);
1091 const auto& scaled_rotation = scale_rotation_matrix(output.
rotation, options.
scale, output.
scale, tmp);
1092 projector(scaled_rotation);
1101 if (!options.
scale) {
1102 output.
scale = EigenVector_();
1160template<
typename Value_,
typename Index_,
typename Block_,
typename EigenMatrix_,
class EigenVector_>
1163 const Block_* block,
1167 blocked_pca_internal<Value_, Index_, Block_, EigenMatrix_, EigenVector_>(
1172 [&](
const BlockingDetails<Index_, EigenVector_>&,
const EigenMatrix_&,
const EigenVector_&) ->
void {}
1195template<
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
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 BlockedPcaOptions< EigenVector_ > &options, BlockedPcaResults< EigenMatrix_, EigenVector_ > &output)
Definition blocked_pca.hpp:1161
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)
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const Index_ iter_length, Args_ &&... args)
Options for blocked_pca().
Definition blocked_pca.hpp:34
int number
Definition blocked_pca.hpp:51
irlba::Options< EigenVector_ > irlba_options
Definition blocked_pca.hpp:109
bool transpose
Definition blocked_pca.hpp:65
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition blocked_pca.hpp:82
scran_blocks::WeightPolicy block_weight_policy
Definition blocked_pca.hpp:76
bool scale
Definition blocked_pca.hpp:59
bool center_scores_by_block
Definition blocked_pca.hpp:90
bool realize_matrix
Definition blocked_pca.hpp:96
int num_threads
Definition blocked_pca.hpp:104
Results of blocked_pca().
Definition blocked_pca.hpp:854
EigenVector_::Scalar total_variance
Definition blocked_pca.hpp:876
EigenMatrix_ components
Definition blocked_pca.hpp:863
irlba::Metrics metrics
Definition blocked_pca.hpp:901
EigenMatrix_ rotation
Definition blocked_pca.hpp:883
EigenVector_ scale
Definition blocked_pca.hpp:896
EigenMatrix_ center
Definition blocked_pca.hpp:890
EigenVector_ variance_explained
Definition blocked_pca.hpp:870