scran_markers
Marker detection for single-cell data
Loading...
Searching...
No Matches
score_markers_best.hpp
Go to the documentation of this file.
1#ifndef SCRAN_MARKERS_SCORE_MARKERS_BEST_HPP
2#define SCRAN_MARKERS_SCORE_MARKERS_BEST_HPP
3
4#include <vector>
5#include <cstddef>
6#include <optional>
7
9#include "tatami/tatami.hpp"
10#include "tatami_stats/tatami_stats.hpp"
11#include "sanisizer/sanisizer.hpp"
12#include "topicks/topicks.hpp"
13#include "quickstats/quickstats.hpp"
14
15#include "scan_matrix.hpp"
16#include "average_group_stats.hpp"
17#include "block_averages.hpp"
18#include "create_combinations.hpp"
19#include "cohens_d.hpp"
20#include "simple_diff.hpp"
21#include "utils.hpp"
22
28namespace scran_markers {
29
39 double threshold = 0;
40
45 int num_threads = 1;
46
50 bool compute_group_mean = true;
51
56
60 bool compute_cohens_d = true;
61
65 bool compute_auc = true;
66
70 bool compute_delta_mean = true;
71
76
81 bool largest_cohens_d = true;
82
87 bool largest_auc = true;
88
93 bool largest_delta_mean = true;
94
100
106 std::optional<double> threshold_cohens_d = 0;
107
113 std::optional<double> threshold_auc = 0.5;
114
120 std::optional<double> threshold_delta_mean = 0;
121
127 std::optional<double> threshold_delta_detected = 0;
128
132 bool keep_ties = false;
133
139 BlockAveragePolicy block_average_policy = BlockAveragePolicy::MEAN;
140
153 scran_blocks::WeightPolicy block_weight_policy = scran_blocks::WeightPolicy::VARIABLE;
154
161
166 double block_quantile = 0.5;
167};
168
174template<typename Stat_, typename Index_>
180 std::vector<std::vector<Stat_> > mean;
181
186 std::vector<std::vector<Stat_> > detected;
187
201 std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > > cohens_d;
202
216 std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > > auc;
217
231 std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > > delta_mean;
232
246 std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > > delta_detected;
247};
248
261template<typename Stat_, typename Index_>
262std::vector<std::vector<std::vector<std::pair<Index_, Stat_> > > > queues_to_vectors(std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > >& queued) {
263 std::vector<std::vector<std::vector<std::pair<Index_, Stat_> > > > output;
264 const auto ngroups = queued.size();
265 sanisizer::resize(output, ngroups);
266
267 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
268 sanisizer::resize(output[g1], ngroups);
269 for (I<decltype(ngroups)> g2 = 0; g2 < ngroups; ++g2) {
270 if (g1 == g2) {
271 continue;
272 }
273
274 auto& current_in = queued[g1][g2];
275 auto& current_out = output[g1][g2];
276 current_out.reserve(current_in.size());
277
278 while (!current_in.empty()) {
279 const auto& best = current_in.top();
280 current_out.emplace_back(best.second, best.first);
281 current_in.pop();
282 }
283 std::reverse(current_out.begin(), current_out.end()); // earliest element should have the strongest effect sizes.
284 }
285 }
286
287 return output;
288}
289
293namespace internal {
294
295template<typename Stat_, typename Index_>
296using PairwiseTopQueues = std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > >;
297
298template<typename Stat_, typename Index_>
299void allocate_best_top_queues(
300 PairwiseTopQueues<Stat_, Index_>& pqueues,
301 const std::size_t ngroups,
302 const Index_ top,
303 const bool larger,
304 const bool keep_ties,
305 const std::optional<Stat_>& bound
306) {
308 opt.check_nan = true;
309 opt.keep_ties = keep_ties;
310 if (bound.has_value()) {
311 opt.bound = *bound;
312 }
313
314 sanisizer::resize(pqueues, ngroups);
315 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
316 auto& x = pqueues[g1];
317 x.reserve(ngroups);
318 for (I<decltype(ngroups)> g2 = 0; g2 < ngroups; ++g2) {
319 if (g1 == g2) {
320 x.emplace_back(0, larger, opt);
321 } else {
322 x.emplace_back(top, larger, opt);
323 }
324 }
325 }
326}
327
328template<typename Stat_, typename Index_>
329void add_best_top_queues(
330 PairwiseTopQueues<Stat_, Index_>& pqueues,
331 const Index_ gene,
332 std::size_t ngroups,
333 const std::vector<Stat_>& effects
334) {
335 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
336 for (I<decltype(ngroups)> g2 = 0; g2 < ngroups; ++g2) {
337 const auto val = effects[sanisizer::nd_offset<std::size_t>(g2, ngroups, g1)];
338 if (g1 != g2) {
339 pqueues[g1][g2].emplace(val, gene);
340 }
341 }
342 }
343}
344
345template<typename Stat_, typename Index_>
346void report_best_top_queues(
347 std::vector<std::optional<PairwiseTopQueues<Stat_, Index_> > >& pqueues,
348 std::size_t ngroups,
349 std::vector<std::vector<topicks::TopQueue<Stat_, Index_> > >& output
350) {
351 // We know it fits into an 'int' as this is what we got originally.
352 const int num_available = pqueues.size();
353
354 // If it's empty, we just create empty vectors and move on.
355 if (num_available == 0) {
356 sanisizer::resize(output, ngroups);
357 topicks::TopQueue<Stat_, Index_> placeholder(0, false, {});
358 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
359 sanisizer::resize(output[g1], ngroups, placeholder);
360 }
361 return;
362 }
363
364 // Consolidating all of the thread-specific queues into a single queue.
365 auto& true_pqueue = *(pqueues.front());
366 for (int t = 1; t < num_available; ++t) {
367 auto& current_pqueue = *(pqueues[t]);
368 for (I<decltype(ngroups)> g1 = 0; g1 < ngroups; ++g1) {
369 for (I<decltype(ngroups)> g2 = 0; g2 < ngroups; ++g2) {
370 auto& current_in = current_pqueue[g1][g2];
371 auto& current_out = true_pqueue[g1][g2];
372 while (!current_in.empty()) {
373 current_out.push(current_in.top());
374 current_in.pop();
375 }
376 }
377 }
378 }
379
380 output = std::move(true_pqueue);
381}
382
383template<typename Index_, typename Stat_>
384void find_best_simple_best_effects(
385 const Index_ ngenes,
386 const std::size_t ngroups,
387 const std::size_t nblocks,
388 const std::size_t ncombos,
389 const std::vector<Stat_>& combo_means,
390 const std::vector<Stat_>& combo_vars,
391 const std::vector<Stat_>& combo_detected,
392 const BlockAverageInfo<Stat_>& average_info,
393 const Index_ top,
394 const ScoreMarkersBestOptions& options,
395 ScoreMarkersBestResults<Stat_, Index_>& output
396) {
397 std::optional<std::vector<Stat_> > total_weights_per_group;
398 const Stat_* total_weights_ptr = NULL;
399 if (average_info.use_mean()) {
400 if (options.compute_group_mean || options.compute_group_detected) {
401 if (nblocks > 1) {
402 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, average_info.combo_weights().data());
403 total_weights_ptr = total_weights_per_group->data();
404 } else {
405 total_weights_ptr = average_info.combo_weights().data();
406 }
407 }
408 }
409
410 std::vector<Stat_*> mptrs;
411 if (options.compute_group_mean) {
412 mptrs.reserve(ngroups);
413 sanisizer::resize(output.mean, ngroups);
414 for (auto& x : output.mean) {
415 sanisizer::resize(x, ngenes);
416 mptrs.push_back(x.data());
417 }
418 }
419
420 std::vector<Stat_*> dptrs;
421 if (options.compute_group_detected) {
422 dptrs.reserve(ngroups);
423 sanisizer::resize(output.detected, ngroups);
424 for (auto& x : output.detected) {
425 sanisizer::resize(x, ngenes);
426 dptrs.push_back(x.data());
427 }
428 }
429
430 std::optional<PrecomputedPairwiseWeights<Stat_> > preweights;
431 if (average_info.use_mean()) {
432 if (options.compute_cohens_d || options.compute_delta_mean || options.compute_delta_detected) {
433 preweights.emplace(ngroups, nblocks, average_info.combo_weights().data());
434 }
435 }
436
437 // Setting up the output queues.
438 std::optional<std::vector<std::optional<PairwiseTopQueues<Stat_, Index_> > > > threaded_cohens_d_queues, threaded_delta_detected_queues, threaded_delta_mean_queues;
439 if (options.compute_cohens_d) {
440 threaded_cohens_d_queues.emplace(sanisizer::cast<I<decltype(threaded_cohens_d_queues->size())> >(options.num_threads));
441 }
442 if (options.compute_delta_mean) {
443 threaded_delta_mean_queues.emplace(sanisizer::cast<I<decltype(threaded_delta_mean_queues->size())> >(options.num_threads));
444 }
445 if (options.compute_delta_detected) {
446 threaded_delta_detected_queues.emplace(sanisizer::cast<I<decltype(threaded_delta_detected_queues->size())> >(options.num_threads));
447 }
448
449 const auto ngroups2 = sanisizer::product<typename std::vector<Stat_>::size_type>(ngroups, ngroups);
450
451 int num_used = tatami::parallelize([&](const int t, const Index_ start, const Index_ length) -> void {
452 std::optional<PairwiseTopQueues<Stat_, Index_> > local_cohens_d_queue, local_delta_mean_queue, local_delta_detected_queue;
453 if (options.compute_cohens_d) {
454 local_cohens_d_queue.emplace();
455 allocate_best_top_queues(*local_cohens_d_queue, ngroups, top, options.largest_cohens_d, options.keep_ties, options.threshold_cohens_d);
456 }
457 if (options.compute_delta_mean) {
458 local_delta_mean_queue.emplace();
459 allocate_best_top_queues(*local_delta_mean_queue, ngroups, top, options.largest_delta_mean, options.keep_ties, options.threshold_delta_mean);
460 }
461 if (options.compute_delta_detected) {
462 local_delta_detected_queue.emplace();
463 allocate_best_top_queues(*local_delta_detected_queue, ngroups, top, options.largest_delta_detected, options.keep_ties, options.threshold_delta_detected);
464 }
465
466 std::vector<Stat_> buffer;
467 if (options.compute_cohens_d || options.compute_delta_mean || options.compute_delta_detected) {
468 buffer.resize(ngroups2);
469 }
470
471 std::optional<std::vector<Stat_> > qbuffer, qrevbuffer;
472 std::optional<quickstats::SingleQuantileVariableNumber<Stat_, std::size_t> > qcalc;
473 if (!average_info.use_mean()) {
474 qbuffer.emplace();
475 qrevbuffer.emplace();
476 qcalc.emplace(nblocks, average_info.quantile());
477 }
478
479 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
480 auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, ncombos);
481
482 if (options.compute_group_mean) {
483 const auto tmp_means = combo_means.data() + in_offset;
484 if (average_info.use_mean()) {
485 average_group_stats_blockmean(gene, ngroups, nblocks, tmp_means, average_info.combo_weights().data(), total_weights_ptr, mptrs);
486 } else {
487 average_group_stats_blockquantile(gene, ngroups, nblocks, tmp_means, *qbuffer, *qcalc, mptrs);
488 }
489 }
490
491 if (options.compute_group_detected) {
492 const auto tmp_detected = combo_detected.data() + in_offset;
493 if (average_info.use_mean()) {
494 average_group_stats_blockmean(gene, ngroups, nblocks, tmp_detected, average_info.combo_weights().data(), total_weights_ptr, dptrs);
495 } else {
496 average_group_stats_blockquantile(gene, ngroups, nblocks, tmp_detected, *qbuffer, *qcalc, dptrs);
497 }
498 }
499
500 // Computing the effect sizes.
501 if (options.compute_cohens_d) {
502 const auto tmp_means = combo_means.data() + in_offset;
503 const auto tmp_variances = combo_vars.data() + in_offset;
504 if (average_info.use_mean()) {
505 compute_pairwise_cohens_d_blockmean(tmp_means, tmp_variances, ngroups, nblocks, options.threshold, *preweights, buffer.data());
506 } else {
507 compute_pairwise_cohens_d_blockquantile(tmp_means, tmp_variances, ngroups, nblocks, options.threshold, *qbuffer, *qrevbuffer, *qcalc, buffer.data());
508 }
509 add_best_top_queues(*local_cohens_d_queue, gene, ngroups, buffer);
510 }
511
512 if (options.compute_delta_mean) {
513 const auto tmp_means = combo_means.data() + in_offset;
514 if (average_info.use_mean()) {
515 compute_pairwise_simple_diff_blockmean(tmp_means, ngroups, nblocks, *preweights, buffer.data());
516 } else {
517 compute_pairwise_simple_diff_blockquantile(tmp_means, ngroups, nblocks, *qbuffer, *qcalc, buffer.data());
518 }
519 add_best_top_queues(*local_delta_mean_queue, gene, ngroups, buffer);
520 }
521
522 if (options.compute_delta_detected) {
523 const auto tmp_detected = combo_detected.data() + in_offset;
524 if (average_info.use_mean()) {
525 compute_pairwise_simple_diff_blockmean(tmp_detected, ngroups, nblocks, *preweights, buffer.data());
526 } else {
527 compute_pairwise_simple_diff_blockquantile(tmp_detected, ngroups, nblocks, *qbuffer, *qcalc, buffer.data());
528 }
529 add_best_top_queues(*local_delta_detected_queue, gene, ngroups, buffer);
530 }
531 }
532
533 // Only moving it into the shared buffer at the end to minimize false sharing.
534 if (options.compute_cohens_d) {
535 (*threaded_cohens_d_queues)[t] = std::move(local_cohens_d_queue);
536 }
537 if (options.compute_delta_mean) {
538 (*threaded_delta_mean_queues)[t] = std::move(local_delta_mean_queue);
539 }
540 if (options.compute_delta_detected) {
541 (*threaded_delta_detected_queues)[t] = std::move(local_delta_detected_queue);
542 }
543 }, ngenes, options.num_threads);
544
545 // Now figuring out which of these are the top dogs.
546 if (options.compute_cohens_d) {
547 threaded_cohens_d_queues->resize(num_used);
548 report_best_top_queues(*threaded_cohens_d_queues, ngroups, output.cohens_d);
549 }
550 if (options.compute_delta_mean) {
551 threaded_delta_mean_queues->resize(num_used);
552 report_best_top_queues(*threaded_delta_mean_queues, ngroups, output.delta_mean);
553 }
554 if (options.compute_delta_detected) {
555 threaded_delta_detected_queues->resize(num_used);
556 report_best_top_queues(*threaded_delta_detected_queues, ngroups, output.delta_detected);
557 }
558}
559
560template<
561 bool single_block_,
562 typename Stat_,
563 typename Value_,
564 typename Index_,
565 typename Group_,
566 typename Block_
567>
568ScoreMarkersBestResults<Stat_, Index_> score_markers_best(
569 const tatami::Matrix<Value_, Index_>& matrix,
570 const std::size_t ngroups,
571 const Group_* const group,
572 const std::size_t nblocks,
573 const Block_* const block,
574 const std::size_t ncombos,
575 const std::size_t* const combo,
576 const std::vector<Index_>& combo_sizes,
577 const Index_ top,
578 const ScoreMarkersBestOptions& options
579) {
580 const auto ngenes = matrix.nrow();
581 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ncombos);
582 std::vector<Stat_> combo_means, combo_vars, combo_detected;
583 if (options.compute_group_mean || options.compute_cohens_d || options.compute_delta_mean) {
584 combo_means.resize(payload_size);
585 }
586 if (options.compute_cohens_d) {
587 combo_vars.resize(payload_size);
588 }
589 if (options.compute_group_detected || options.compute_delta_detected) {
590 combo_detected.resize(payload_size);
591 }
592
593 // For a single block, this usually doesn't really matter, but we do it for consistency with the multi-block case,
594 // and to account for variable weighting where non-zero block sizes get zero weight.
595 BlockAverageInfo<Stat_> average_info;
596 if (options.block_average_policy == BlockAveragePolicy::MEAN) {
597 average_info = BlockAverageInfo<Stat_>(
599 combo_sizes,
600 options.block_weight_policy,
601 options.variable_block_weight_parameters
602 )
603 );
604 } else {
605 average_info = BlockAverageInfo<Stat_>(options.block_quantile);
606 }
607
608 ScoreMarkersBestResults<Stat_, Index_> output;
609
610 if (options.compute_auc) {
611 auto auc_queues = sanisizer::create<std::vector<std::optional<PairwiseTopQueues<Stat_, Index_> > > >(options.num_threads);
612
613 struct AucResultWorkspace {
614 AucResultWorkspace(const std::size_t ngroups) : pairwise_buffer(sanisizer::product<typename std::vector<Stat_>::size_type>(ngroups, ngroups)) {};
615 std::vector<Stat_> pairwise_buffer;
616 PairwiseTopQueues<Stat_, Index_> queue;
617 };
618
619 const auto num_used = scan_matrix_by_row_custom_auc<single_block_>(
620 matrix,
621 ngroups,
622 group,
623 nblocks,
624 block,
625 ncombos,
626 combo,
627 combo_sizes,
628 average_info,
629 combo_means,
630 combo_vars,
631 combo_detected,
632 /* do_auc = */ true,
633 /* auc_result_initialize = */ [&](const int) -> AucResultWorkspace {
634 AucResultWorkspace res_work(ngroups);
635 allocate_best_top_queues(res_work.queue, ngroups, top, options.largest_auc, options.keep_ties, options.threshold_auc);
636 return res_work;
637 },
638 /* auc_result_process = */ [&](const Index_ gene, AucScanWorkspace<Value_, Group_, Stat_, Index_>& auc_work, AucResultWorkspace& res_work) -> void {
639 process_auc_for_rows(auc_work, ngroups, nblocks, options.threshold, res_work.pairwise_buffer.data());
640 add_best_top_queues(res_work.queue, gene, ngroups, res_work.pairwise_buffer);
641 },
642 /* auc_result_finalize = */ [&](const int t, AucResultWorkspace& res_work) -> void {
643 auc_queues[t] = std::move(res_work.queue);
644 },
645 options.num_threads
646 );
647
648 auc_queues.resize(num_used);
649 report_best_top_queues(auc_queues, ngroups, output.auc);
650
651 } else if (matrix.prefer_rows()) {
652 scan_matrix_by_row_full_auc<single_block_>(
653 matrix,
654 ngroups,
655 group,
656 nblocks,
657 block,
658 ncombos,
659 combo,
660 combo_sizes,
661 average_info,
662 combo_means,
663 combo_vars,
664 combo_detected,
665 static_cast<Stat_*>(NULL),
666 options.threshold,
667 options.num_threads
668 );
669
670 } else {
671 scan_matrix_by_column(
672 matrix,
673 [&]{
674 if constexpr(single_block_) {
675 return ngroups;
676 } else {
677 return ncombos;
678 }
679 }(),
680 [&]{
681 if constexpr(single_block_) {
682 return group;
683 } else {
684 return combo;
685 }
686 }(),
687 combo_sizes,
688 combo_means,
689 combo_vars,
690 combo_detected,
691 options.num_threads
692 );
693 }
694
695 find_best_simple_best_effects(
696 matrix.nrow(),
697 ngroups,
698 nblocks,
699 ncombos,
700 combo_means,
701 combo_vars,
702 combo_detected,
703 average_info,
704 top,
705 options,
706 output
707 );
708
709 return output;
710}
711
712}
738template<typename Stat_, typename Value_, typename Index_, typename Group_>
740 const tatami::Matrix<Value_, Index_>& matrix,
741 const Group_* const group,
742 const Index_ top,
743 const ScoreMarkersBestOptions& options
744) {
745 const Index_ NC = matrix.ncol();
746 const auto group_sizes = tatami_stats::tabulate_groups(group, NC);
747 const auto ngroups = sanisizer::cast<std::size_t>(group_sizes.size());
748
749 return internal::score_markers_best<true, Stat_>(
750 matrix,
751 ngroups,
752 group,
753 1,
754 static_cast<int*>(NULL),
755 ngroups,
756 static_cast<std::size_t*>(NULL),
757 group_sizes,
758 top,
759 options
760 );
761}
762
787template<typename Stat_, typename Value_, typename Index_, typename Group_, typename Block_>
789 const tatami::Matrix<Value_, Index_>& matrix,
790 const Group_* const group,
791 const Block_* const block,
792 const Index_ top,
793 const ScoreMarkersBestOptions& options
794) {
795 const Index_ NC = matrix.ncol();
796 const auto ngroups = tatami_stats::total_groups(group, NC);
797 const auto nblocks = tatami_stats::total_groups(block, NC);
798
799 const auto combinations = internal::create_combinations(ngroups, group, nblocks, block, NC);
800 const auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
801 const auto ncombos = combo_sizes.size();
802
803 return internal::score_markers_best<false, Stat_>(
804 matrix,
805 sanisizer::cast<std::size_t>(ngroups),
806 group,
807 sanisizer::cast<std::size_t>(nblocks),
808 block,
809 sanisizer::cast<std::size_t>(ncombos),
810 combinations.data(),
811 combo_sizes,
812 top,
813 options
814 );
815}
816
817}
818
819#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:27
std::vector< std::vector< std::vector< std::pair< Index_, Stat_ > > > > queues_to_vectors(std::vector< std::vector< topicks::TopQueue< Stat_, Index_ > > > &queued)
Definition score_markers_best.hpp:262
BlockAveragePolicy
Definition block_averages.hpp:27
ScoreMarkersBestResults< Stat_, Index_ > score_markers_best_blocked(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const Block_ *const block, const Index_ top, const ScoreMarkersBestOptions &options)
Definition score_markers_best.hpp:788
ScoreMarkersBestResults< Stat_, Index_ > score_markers_best(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const Index_ top, const ScoreMarkersBestOptions &options)
Definition score_markers_best.hpp:739
int parallelize(Function_ fun, const Index_ tasks, const int workers)
Options for score_markers_best() and friends.
Definition score_markers_best.hpp:33
bool compute_cohens_d
Definition score_markers_best.hpp:60
std::optional< double > threshold_delta_mean
Definition score_markers_best.hpp:120
double threshold
Definition score_markers_best.hpp:39
bool compute_auc
Definition score_markers_best.hpp:65
bool largest_cohens_d
Definition score_markers_best.hpp:81
BlockAveragePolicy block_average_policy
Definition score_markers_best.hpp:139
bool compute_delta_mean
Definition score_markers_best.hpp:70
bool largest_delta_mean
Definition score_markers_best.hpp:93
bool compute_group_detected
Definition score_markers_best.hpp:55
bool compute_group_mean
Definition score_markers_best.hpp:50
double block_quantile
Definition score_markers_best.hpp:166
std::optional< double > threshold_cohens_d
Definition score_markers_best.hpp:106
std::optional< double > threshold_delta_detected
Definition score_markers_best.hpp:127
bool largest_delta_detected
Definition score_markers_best.hpp:99
bool largest_auc
Definition score_markers_best.hpp:87
scran_blocks::WeightPolicy block_weight_policy
Definition score_markers_best.hpp:153
std::optional< double > threshold_auc
Definition score_markers_best.hpp:113
int num_threads
Definition score_markers_best.hpp:45
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition score_markers_best.hpp:160
bool compute_delta_detected
Definition score_markers_best.hpp:75
bool keep_ties
Definition score_markers_best.hpp:132
Results for score_markers_best() and friends.
Definition score_markers_best.hpp:175
std::vector< std::vector< topicks::TopQueue< Stat_, Index_ > > > delta_detected
Definition score_markers_best.hpp:246
std::vector< std::vector< topicks::TopQueue< Stat_, Index_ > > > auc
Definition score_markers_best.hpp:216
std::vector< std::vector< topicks::TopQueue< Stat_, Index_ > > > cohens_d
Definition score_markers_best.hpp:201
std::vector< std::vector< Stat_ > > mean
Definition score_markers_best.hpp:180
std::vector< std::vector< topicks::TopQueue< Stat_, Index_ > > > delta_mean
Definition score_markers_best.hpp:231
std::vector< std::vector< Stat_ > > detected
Definition score_markers_best.hpp:186
std::optional< Stat_ > bound