scran_markers
Marker detection for single-cell data
Loading...
Searching...
No Matches
score_markers_summary.hpp
Go to the documentation of this file.
1#ifndef SCRAN_SCORE_MARKERS_HPP
2#define SCRAN_SCORE_MARKERS_HPP
3
5#include "tatami/tatami.hpp"
6#include "sanisizer/sanisizer.hpp"
7#include "topicks/topicks.hpp"
8
9#include <array>
10#include <map>
11#include <vector>
12#include <optional>
13
14#include "scan_matrix.hpp"
15#include "cohens_d.hpp"
16#include "simple_diff.hpp"
17#include "block_averages.hpp"
19#include "average_group_stats.hpp"
20#include "create_combinations.hpp"
21#include "utils.hpp"
22
28namespace scran_markers {
29
39 double threshold = 0;
40
45 int num_threads = 1;
46
51 bool compute_group_mean = true;
52
58
63 bool compute_cohens_d = true;
64
69 bool compute_auc = true;
70
75 bool compute_delta_mean = true;
76
82
87 bool compute_min = true;
88
93 bool compute_mean = true;
94
99 bool compute_median = true;
100
105 bool compute_max = true;
106
112 std::optional<std::vector<double> > compute_summary_quantiles;
113
118 bool compute_min_rank = true;
119
125 std::size_t min_rank_limit = 500;
126
132 bool min_rank_preserve_ties = false;
133
139 BlockAveragePolicy block_average_policy = BlockAveragePolicy::MEAN;
140
153 scran_blocks::WeightPolicy block_weight_policy = scran_blocks::WeightPolicy::VARIABLE;
154
160 scran_blocks::VariableWeightParameters variable_block_weight_parameters;
161
166 double block_quantile = 0.5;
167};
168
174template<typename Stat_, typename Rank_>
183 std::vector<Stat_*> mean;
184
192 std::vector<Stat_*> detected;
193
201 std::vector<SummaryBuffers<Stat_, Rank_> > cohens_d;
202
210 std::vector<SummaryBuffers<Stat_, Rank_> > auc;
211
219 std::vector<SummaryBuffers<Stat_, Rank_> > delta_mean;
220
228 std::vector<SummaryBuffers<Stat_, Rank_> > delta_detected;
229};
230
236template<typename Stat_, typename Rank_>
242 std::vector<std::vector<Stat_> > mean;
243
248 std::vector<std::vector<Stat_> > detected;
249
257 std::vector<SummaryResults<Stat_, Rank_> > cohens_d;
258
266 std::vector<SummaryResults<Stat_, Rank_> > auc;
267
275 std::vector<SummaryResults<Stat_, Rank_> > delta_mean;
276
284 std::vector<SummaryResults<Stat_, Rank_> > delta_detected;
285};
286
290namespace internal {
291
292template<typename Stat_, typename Index_>
293using MinrankTopQueues = std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > >;
294
295template<typename Stat_, typename Index_, typename Rank_>
296void preallocate_minrank_queues(
297 const std::size_t ngroups,
298 std::vector<MinrankTopQueues<Stat_, Index_> >& all_queues,
299 const std::vector<SummaryBuffers<Stat_, Rank_> >& summaries,
300 const Index_ limit,
301 const bool keep_ties,
302 const int num_threads
303) {
305 qopt.keep_ties = keep_ties;
306 qopt.check_nan = true;
307
308 sanisizer::resize(all_queues, num_threads);
309 for (int t = 0; t < num_threads; ++t) {
310 sanisizer::resize(all_queues[t], ngroups);
311
312 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
313 if (summaries[g1].min_rank == NULL) {
314 continue;
315 }
316
317 for (I<decltype(ngroups)> g2 = 0; g2 < ngroups; ++g2) {
318 all_queues[t][g1].emplace_back(limit, true, qopt);
319 }
320 }
321 }
322}
323
324template<typename Stat_, typename Index_, typename Rank_>
325void compute_summary_stats_per_gene(
326 const Index_ gene,
327 const std::size_t ngroups,
328 const Stat_* const pairwise_buffer_ptr,
329 std::vector<Stat_>& summary_buffer,
330 MaybeMultipleQuantiles<Stat_>& summary_qcalcs,
331 MinrankTopQueues<Stat_, Index_>& minrank_queues,
332 const std::vector<SummaryBuffers<Stat_, Rank_> >& summaries
333) {
334 for (I<decltype(ngroups)> gr = 0; gr < ngroups; ++gr) {
335 auto& cursummary = summaries[gr];
336 const auto in_offset = sanisizer::product_unsafe<std::size_t>(ngroups, gr);
337 summarize_comparisons(ngroups, pairwise_buffer_ptr + in_offset, gr, gene, cursummary, summary_qcalcs, summary_buffer);
338
339 if (cursummary.min_rank) {
340 auto& cur_queues = minrank_queues[gr];
341 for (I<decltype(ngroups)> gr2 = 0; gr2 < ngroups; ++gr2) {
342 if (gr != gr2) {
343 cur_queues[gr2].emplace(pairwise_buffer_ptr[in_offset + gr2], gene);
344 }
345 }
346 }
347 }
348}
349
350template<typename Stat_, typename Index_, typename Rank_>
351void report_minrank_from_queues(
352 const Index_ ngenes,
353 const std::size_t ngroups,
354 std::vector<MinrankTopQueues<Stat_, Index_> >& all_queues,
355 const std::vector<SummaryBuffers<Stat_, Rank_> >& summaries,
356 const int num_threads,
357 const bool keep_ties
358) {
359 tatami::parallelize([&](const int, const std::size_t start, const std::size_t length) -> void {
360 std::vector<Index_> tie_buffer;
361
362 for (I<decltype(ngroups)> gr = start, grend = start + length; gr < grend; ++gr) {
363 const auto mr_out = summaries[gr].min_rank;
364 if (mr_out == NULL) {
365 continue;
366 }
367
368 // Using the maximum possible rank (i.e., 'ngenes') as the default.
369 const auto maxrank_placeholder = sanisizer::cast<Rank_>(ngenes);
370 std::fill_n(mr_out, ngenes, maxrank_placeholder);
371
372 for (I<decltype(ngroups)> gr2 = 0; gr2 < ngroups; ++gr2) {
373 if (gr == gr2) {
374 continue;
375 }
376 auto& current_out = all_queues.front()[gr][gr2];
377
378 const auto num_queues = all_queues.size();
379 for (I<decltype(num_queues)> q = 1; q < num_queues; ++q) {
380 auto& current_in = all_queues[q][gr][gr2];
381 while (!current_in.empty()) {
382 current_out.push(current_in.top());
383 current_in.pop();
384 }
385 }
386
387 // Cast to Rank_ is safe as current_out.size() <= ngenes,
388 // and we already checked that ngenes can fit into Rank_ in report_minrank_from_current_outs().
389 if (!keep_ties) {
390 while (!current_out.empty()) {
391 auto& mr = mr_out[current_out.top().second];
392 mr = std::min(mr, static_cast<Rank_>(current_out.size()));
393 current_out.pop();
394 }
395 } else {
396 while (!current_out.empty()) {
397 tie_buffer.clear();
398 const auto curtop = current_out.top();
399 current_out.pop();
400
401 while (!current_out.empty() && current_out.top().first == curtop.first) {
402 tie_buffer.push_back(current_out.top().second);
403 current_out.pop();
404 }
405
406 // Increment is safe as we already reduced the size at least once.
407 const Rank_ tied_rank = current_out.size() + 1;
408
409 mr_out[curtop.second] = std::min(mr_out[curtop.second], tied_rank);
410 for (const auto t : tie_buffer) {
411 mr_out[t] = std::min(mr_out[t], tied_rank);
412 }
413 }
414 }
415 }
416 }
417 }, ngroups, num_threads);
418}
419
420template<typename Index_, typename Stat_, typename Rank_>
421void process_simple_summary_effects(
422 const Index_ ngenes,
423 const std::size_t ngroups,
424 const std::size_t nblocks,
425 const std::size_t ncombos,
426 const std::vector<Stat_>& combo_means,
427 const std::vector<Stat_>& combo_vars,
428 const std::vector<Stat_>& combo_detected,
429 const double threshold,
430 const BlockAverageInfo<Stat_>& average_info,
431 const std::optional<std::vector<double> >& summary_quantiles,
432 const Index_ minrank_limit,
433 const bool minrank_keep_ties,
435 const int num_threads
436) {
437 std::vector<MinrankTopQueues<Stat_, Index_> > cohens_d_minrank_all_queues, delta_mean_minrank_all_queues, delta_detected_minrank_all_queues;
438 if (output.cohens_d.size()) {
439 preallocate_minrank_queues(ngroups, cohens_d_minrank_all_queues, output.cohens_d, minrank_limit, minrank_keep_ties, num_threads);
440 }
441 if (output.delta_mean.size()) {
442 preallocate_minrank_queues(ngroups, delta_mean_minrank_all_queues, output.delta_mean, minrank_limit, minrank_keep_ties, num_threads);
443 }
444 if (output.delta_detected.size()) {
445 preallocate_minrank_queues(ngroups, delta_detected_minrank_all_queues, output.delta_detected, minrank_limit, minrank_keep_ties, num_threads);
446 }
447
448 std::optional<std::vector<Stat_> > total_weights_per_group;
449 const Stat_* total_weights_ptr = NULL;
450 if (average_info.use_mean()) {
451 if (!output.mean.empty() || !output.detected.empty()) {
452 if (nblocks > 1) {
453 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, average_info.combo_weights().data());
454 total_weights_ptr = total_weights_per_group->data();
455 } else {
456 total_weights_ptr = average_info.combo_weights().data();
457 }
458 }
459 }
460
461 std::optional<PrecomputedPairwiseWeights<Stat_> > preweights;
462 if (average_info.use_mean()) {
463 if (!output.cohens_d.empty() || !output.delta_mean.empty() || !output.delta_detected.empty()) {
464 preweights = PrecomputedPairwiseWeights<Stat_>(ngroups, nblocks, average_info.combo_weights().data());
465 }
466 }
467
468 const auto ngroups2 = sanisizer::product<typename std::vector<Stat_>::size_type>(ngroups, ngroups);
469 tatami::parallelize([&](const int t, const Index_ start, const Index_ length) -> void {
470 std::vector<Stat_> pairwise_buffer(ngroups2);
471 std::vector<Stat_> summary_buffer(ngroups);
472 auto summary_qcalcs = setup_multiple_quantiles<Stat_>(summary_quantiles, ngroups);
473
474 std::optional<std::vector<Stat_> > qbuffer, qrevbuffer;
475 std::optional<scran_blocks::SingleQuantileVariable<Stat_, typename std::vector<Stat_>::iterator> > qcalc;
476 if (!average_info.use_mean()) {
477 qbuffer.emplace();
478 qrevbuffer.emplace();
479 qcalc.emplace(nblocks, average_info.quantile());
480 }
481
482 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
483 const auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, ncombos);
484
485 if (!output.mean.empty()) {
486 const auto tmp_means = combo_means.data() + in_offset;
487 if (average_info.use_mean()) {
488 average_group_stats_blockmean(gene, ngroups, nblocks, tmp_means, average_info.combo_weights().data(), total_weights_ptr, output.mean);
489 } else {
490 average_group_stats_blockquantile(gene, ngroups, nblocks, tmp_means, *qbuffer, *qcalc, output.mean);
491 }
492 }
493
494 if (!output.detected.empty()) {
495 const auto tmp_detected = combo_detected.data() + in_offset;
496 if (average_info.use_mean()) {
497 average_group_stats_blockmean(gene, ngroups, nblocks, tmp_detected, average_info.combo_weights().data(), total_weights_ptr, output.detected);
498 } else {
499 average_group_stats_blockquantile(gene, ngroups, nblocks, tmp_detected, *qbuffer, *qcalc, output.detected);
500 }
501 }
502
503 if (output.cohens_d.size()) {
504 const auto tmp_means = combo_means.data() + in_offset;
505 const auto tmp_variances = combo_vars.data() + in_offset;
506 if (average_info.use_mean()) {
507 compute_pairwise_cohens_d_blockmean(tmp_means, tmp_variances, ngroups, nblocks, threshold, *preweights, pairwise_buffer.data());
508 } else {
509 compute_pairwise_cohens_d_blockquantile(tmp_means, tmp_variances, ngroups, nblocks, threshold, *qbuffer, *qrevbuffer, *qcalc, pairwise_buffer.data());
510 }
511 compute_summary_stats_per_gene(gene, ngroups, pairwise_buffer.data(), summary_buffer, summary_qcalcs, cohens_d_minrank_all_queues[t], output.cohens_d);
512 }
513
514 if (output.delta_mean.size()) {
515 const auto tmp_means = combo_means.data() + in_offset;
516 if (average_info.use_mean()) {
517 compute_pairwise_simple_diff_blockmean(tmp_means, ngroups, nblocks, *preweights, pairwise_buffer.data());
518 } else {
519 compute_pairwise_simple_diff_blockquantile(tmp_means, ngroups, nblocks, *qbuffer, *qcalc, pairwise_buffer.data());
520 }
521 compute_summary_stats_per_gene(gene, ngroups, pairwise_buffer.data(), summary_buffer, summary_qcalcs, delta_mean_minrank_all_queues[t], output.delta_mean);
522 }
523
524 if (output.delta_detected.size()) {
525 const auto tmp_det = combo_detected.data() + in_offset;
526 if (average_info.use_mean()) {
527 compute_pairwise_simple_diff_blockmean(tmp_det, ngroups, nblocks, *preweights, pairwise_buffer.data());
528 } else {
529 compute_pairwise_simple_diff_blockquantile(tmp_det, ngroups, nblocks, *qbuffer, *qcalc, pairwise_buffer.data());
530 }
531 compute_summary_stats_per_gene(gene, ngroups, pairwise_buffer.data(), summary_buffer, summary_qcalcs, delta_detected_minrank_all_queues[t], output.delta_detected);
532 }
533 }
534 }, ngenes, num_threads);
535
536 if (output.cohens_d.size()) {
537 report_minrank_from_queues(ngenes, ngroups, cohens_d_minrank_all_queues, output.cohens_d, num_threads, minrank_keep_ties);
538 }
539
540 if (output.delta_mean.size()) {
541 report_minrank_from_queues(ngenes, ngroups, delta_mean_minrank_all_queues, output.delta_mean, num_threads, minrank_keep_ties);
542 }
543
544 if (output.delta_detected.size()) {
545 report_minrank_from_queues(ngenes, ngroups, delta_detected_minrank_all_queues, output.delta_detected, num_threads, minrank_keep_ties);
546 }
547}
548
549template<typename Index_, typename Stat_, typename Rank_>
550ScoreMarkersSummaryBuffers<Stat_, Rank_> preallocate_summary_results(
551 const Index_ ngenes,
552 const std::size_t ngroups,
554 const ScoreMarkersSummaryOptions& options)
555{
557
558 if (options.compute_group_mean) {
559 preallocate_average_results(ngenes, ngroups, store.mean, output.mean);
560 }
561
562 if (options.compute_group_detected) {
563 preallocate_average_results(ngenes, ngroups, store.detected, output.detected);
564 }
565
566 if (options.compute_cohens_d) {
567 output.cohens_d = fill_summary_results(
568 ngenes,
569 ngroups,
570 store.cohens_d,
571 options.compute_min,
572 options.compute_mean,
573 options.compute_median,
574 options.compute_max,
575 options.compute_summary_quantiles,
576 options.compute_min_rank
577 );
578 }
579
580 if (options.compute_auc) {
581 output.auc = fill_summary_results(
582 ngenes,
583 ngroups,
584 store.auc,
585 options.compute_min,
586 options.compute_mean,
587 options.compute_median,
588 options.compute_max,
589 options.compute_summary_quantiles,
590 options.compute_min_rank
591 );
592 }
593
594 if (options.compute_delta_mean) {
595 output.delta_mean = fill_summary_results(
596 ngenes,
597 ngroups,
598 store.delta_mean,
599 options.compute_min,
600 options.compute_mean,
601 options.compute_median,
602 options.compute_max,
603 options.compute_summary_quantiles,
604 options.compute_min_rank
605 );
606 }
607
608 if (options.compute_delta_detected) {
609 output.delta_detected = fill_summary_results(
610 ngenes,
611 ngroups,
612 store.delta_detected,
613 options.compute_min,
614 options.compute_mean,
615 options.compute_median,
616 options.compute_max,
617 options.compute_summary_quantiles,
618 options.compute_min_rank
619 );
620 }
621
622 return output;
623}
624
625template<
626 bool single_block_,
627 typename Value_,
628 typename Index_,
629 typename Group_,
630 typename Block_,
631 typename Stat_,
632 typename Rank_
633>
634void score_markers_summary(
635 const tatami::Matrix<Value_, Index_>& matrix,
636 const std::size_t ngroups,
637 const Group_* const group,
638 const std::size_t nblocks,
639 const Block_* const block,
640 const std::size_t ncombos,
641 const std::size_t* const combo,
642 const std::vector<Index_>& combo_sizes,
643 const ScoreMarkersSummaryOptions& options,
645) {
646 const auto ngenes = matrix.nrow();
647 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ncombos);
648 std::vector<Stat_> combo_means, combo_vars, combo_detected;
649 if (!output.mean.empty() || !output.cohens_d.empty() || !output.delta_mean.empty()) {
650 combo_means.resize(payload_size);
651 }
652 if (!output.cohens_d.empty()) {
653 combo_vars.resize(payload_size);
654 }
655 if (!output.detected.empty() || !output.delta_detected.empty()) {
656 combo_detected.resize(payload_size);
657 }
658
659 // For a single block, this usually doesn't really matter, but we do it for consistency with the multi-block case,
660 // and to account for variable weighting where non-zero block sizes get zero weight.
661 BlockAverageInfo<Stat_> average_info;
662 if (options.block_average_policy == BlockAveragePolicy::MEAN) {
663 average_info = BlockAverageInfo<Stat_>(
665 combo_sizes,
666 options.block_weight_policy,
667 options.variable_block_weight_parameters
668 )
669 );
670 } else {
671 average_info = BlockAverageInfo<Stat_>(options.block_quantile);
672 }
673
674 const Index_ minrank_limit = sanisizer::cap<Index_>(options.min_rank_limit);
675 internal::validate_quantiles(options.compute_summary_quantiles);
676
677 if (!output.auc.empty()) {
678 std::vector<MinrankTopQueues<Stat_, Index_> > auc_minrank_all_queues;
679 preallocate_minrank_queues(ngroups, auc_minrank_all_queues, output.auc, minrank_limit, options.min_rank_preserve_ties, options.num_threads);
680
681 struct AucResultWorkspace {
682 AucResultWorkspace(const std::size_t ngroups, MinrankTopQueues<Stat_, Index_>& queues, const std::optional<std::vector<double> >& summary_quantiles) :
683 pairwise_buffer(sanisizer::product<typename std::vector<Stat_>::size_type>(ngroups, ngroups)),
684 summary_buffer(sanisizer::cast<typename std::vector<Stat_>::size_type>(ngroups)),
685 queue_ptr(&queues),
686 summary_qcalcs(setup_multiple_quantiles<Stat_>(summary_quantiles, ngroups))
687 {};
688
689 public:
690 std::vector<Stat_> pairwise_buffer;
691 std::vector<Stat_> summary_buffer;
692 MinrankTopQueues<Stat_, Index_>* queue_ptr;
693 MaybeMultipleQuantiles<Stat_> summary_qcalcs;
694 };
695
696 scan_matrix_by_row_custom_auc<single_block_>(
697 matrix,
698 ngroups,
699 group,
700 nblocks,
701 block,
702 ncombos,
703 combo,
704 combo_sizes,
705 average_info,
706 combo_means,
707 combo_vars,
708 combo_detected,
709 /* do_auc = */ true,
710 /* auc_result_initialize = */ [&](const int t) -> AucResultWorkspace {
711 return AucResultWorkspace(ngroups, auc_minrank_all_queues[t], options.compute_summary_quantiles);
712 },
713 /* auc_result_process = */ [&](
714 const Index_ gene,
715 AucScanWorkspace<Value_, Group_, Stat_, Index_>& auc_work,
716 AucResultWorkspace& res_work
717 ) -> void {
718 process_auc_for_rows(auc_work, ngroups, nblocks, options.threshold, res_work.pairwise_buffer.data());
719 compute_summary_stats_per_gene(
720 gene,
721 ngroups,
722 res_work.pairwise_buffer.data(),
723 res_work.summary_buffer,
724 res_work.summary_qcalcs,
725 *(res_work.queue_ptr),
726 output.auc
727 );
728 },
729 options.num_threads
730 );
731
732 report_minrank_from_queues(ngenes, ngroups, auc_minrank_all_queues, output.auc, options.num_threads, options.min_rank_preserve_ties);
733
734 } else if (matrix.prefer_rows()) {
735 scan_matrix_by_row_full_auc<single_block_>(
736 matrix,
737 ngroups,
738 group,
739 nblocks,
740 block,
741 ncombos,
742 combo,
743 combo_sizes,
744 average_info,
745 combo_means,
746 combo_vars,
747 combo_detected,
748 static_cast<Stat_*>(NULL),
749 options.threshold,
750 options.num_threads
751 );
752
753 } else {
754 scan_matrix_by_column(
755 matrix,
756 [&]{
757 if constexpr(single_block_) {
758 return ngroups;
759 } else {
760 return ncombos;
761 }
762 }(),
763 [&]{
764 if constexpr(single_block_) {
765 return group;
766 } else {
767 return combo;
768 }
769 }(),
770 combo_sizes,
771 combo_means,
772 combo_vars,
773 combo_detected,
774 options.num_threads
775 );
776 }
777
778 process_simple_summary_effects(
779 matrix.nrow(),
780 ngroups,
781 nblocks,
782 ncombos,
783 combo_means,
784 combo_vars,
785 combo_detected,
786 options.threshold,
787 average_info,
788 options.compute_summary_quantiles,
789 minrank_limit,
790 options.min_rank_preserve_ties,
791 output,
792 options.num_threads
793 );
794}
795
796}
835template<typename Value_, typename Index_, typename Group_, typename Stat_, typename Rank_>
837 const tatami::Matrix<Value_, Index_>& matrix,
838 const Group_* const group,
839 const ScoreMarkersSummaryOptions& options,
841) {
842 const auto NC = matrix.ncol();
843 const auto group_sizes = tatami_stats::tabulate_groups(group, NC);
844 const auto ngroups = sanisizer::cast<std::size_t>(group_sizes.size());
845
846 internal::score_markers_summary<true>(
847 matrix,
848 ngroups,
849 group,
850 1,
851 static_cast<int*>(NULL),
852 ngroups,
853 static_cast<std::size_t*>(NULL),
854 group_sizes,
855 options,
856 output
857 );
858}
859
888template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_, typename Rank_>
890 const tatami::Matrix<Value_, Index_>& matrix,
891 const Group_* const group,
892 const Block_* const block,
893 const ScoreMarkersSummaryOptions& options,
895{
896 const auto NC = matrix.ncol();
897 const auto ngroups = output.mean.size();
898 const auto nblocks = tatami_stats::total_groups(block, NC);
899
900 const auto combinations = internal::create_combinations(ngroups, group, block, NC);
901 const auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
902 const auto ncombos = combo_sizes.size();
903
904 internal::score_markers_summary<false>(
905 matrix,
906 sanisizer::cast<std::size_t>(ngroups),
907 group,
908 sanisizer::cast<std::size_t>(nblocks),
909 block,
910 sanisizer::cast<std::size_t>(ncombos),
911 combinations.data(),
912 combo_sizes,
913 options,
914 output
915 );
916}
917
918
936template<typename Stat_ = double, typename Rank_ = int, typename Value_, typename Index_, typename Group_>
938 const tatami::Matrix<Value_, Index_>& matrix,
939 const Group_* const group,
940 const ScoreMarkersSummaryOptions& options)
941{
942 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
944 const auto buffers = internal::preallocate_summary_results(matrix.nrow(), ngroups, output, options);
945 score_markers_summary(matrix, group, options, buffers);
946 return output;
947}
948
969template<typename Stat_ = double, typename Rank_ = int, typename Value_, typename Index_, typename Group_, typename Block_>
971 const tatami::Matrix<Value_, Index_>& matrix,
972 const Group_* const group,
973 const Block_* const block,
974 const ScoreMarkersSummaryOptions& options)
975{
976 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
978 const auto buffers = internal::preallocate_summary_results(matrix.nrow(), ngroups, output, options);
979 score_markers_summary_blocked(matrix, group, block, options, buffers);
980 return output;
981}
982
983}
984
985#endif
Averaging statistics over blocks.
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
void compute_weights(const std::size_t num_blocks, const Size_ *const sizes, const WeightPolicy policy, const VariableWeightParameters &variable, Weight_ *const weights)
Marker detection for single-cell data.
Definition score_markers_pairwise.hpp:26
BlockAveragePolicy
Definition block_averages.hpp:27
void score_markers_summary(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const ScoreMarkersSummaryOptions &options, const ScoreMarkersSummaryBuffers< Stat_, Rank_ > &output)
Definition score_markers_summary.hpp:836
void score_markers_summary_blocked(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const Block_ *const block, const ScoreMarkersSummaryOptions &options, const ScoreMarkersSummaryBuffers< Stat_, Rank_ > &output)
Definition score_markers_summary.hpp:889
void parallelize(Function_ fun, const Index_ tasks, const int threads)
Buffers for score_markers_summary() and friends.
Definition score_markers_summary.hpp:175
std::vector< Stat_ * > detected
Definition score_markers_summary.hpp:192
std::vector< SummaryBuffers< Stat_, Rank_ > > delta_detected
Definition score_markers_summary.hpp:228
std::vector< Stat_ * > mean
Definition score_markers_summary.hpp:183
std::vector< SummaryBuffers< Stat_, Rank_ > > delta_mean
Definition score_markers_summary.hpp:219
std::vector< SummaryBuffers< Stat_, Rank_ > > cohens_d
Definition score_markers_summary.hpp:201
std::vector< SummaryBuffers< Stat_, Rank_ > > auc
Definition score_markers_summary.hpp:210
Options for score_markers_summary() and friends.
Definition score_markers_summary.hpp:33
bool compute_group_detected
Definition score_markers_summary.hpp:57
bool compute_max
Definition score_markers_summary.hpp:105
bool compute_delta_detected
Definition score_markers_summary.hpp:81
bool compute_auc
Definition score_markers_summary.hpp:69
bool compute_group_mean
Definition score_markers_summary.hpp:51
bool compute_min
Definition score_markers_summary.hpp:87
bool compute_median
Definition score_markers_summary.hpp:99
bool compute_mean
Definition score_markers_summary.hpp:93
double threshold
Definition score_markers_summary.hpp:39
bool compute_cohens_d
Definition score_markers_summary.hpp:63
int num_threads
Definition score_markers_summary.hpp:45
bool compute_delta_mean
Definition score_markers_summary.hpp:75
Results for score_markers_summary() and friends.
Definition score_markers_summary.hpp:237
std::vector< SummaryResults< Stat_, Rank_ > > cohens_d
Definition score_markers_summary.hpp:257
std::vector< std::vector< Stat_ > > mean
Definition score_markers_summary.hpp:242
std::vector< SummaryResults< Stat_, Rank_ > > auc
Definition score_markers_summary.hpp:266
std::vector< SummaryResults< Stat_, Rank_ > > delta_detected
Definition score_markers_summary.hpp:284
std::vector< std::vector< Stat_ > > detected
Definition score_markers_summary.hpp:248
std::vector< SummaryResults< Stat_, Rank_ > > delta_mean
Definition score_markers_summary.hpp:275
Pointers to arrays to hold the summary statistics.
Definition summarize_comparisons.hpp:32
Utilities for effect summarization.