scran_markers
Marker detection for single-cell data
Loading...
Searching...
No Matches
score_markers_pairwise.hpp
Go to the documentation of this file.
1#ifndef SCRAN_MARKERS_SCORE_MARKERS_PAIRWISE_HPP
2#define SCRAN_MARKERS_SCORE_MARKERS_PAIRWISE_HPP
3
4#include <vector>
5#include <cstddef>
6
8#include "tatami/tatami.hpp"
9#include "tatami_stats/tatami_stats.hpp"
10#include "sanisizer/sanisizer.hpp"
11
12#include "scan_matrix.hpp"
13#include "average_group_stats.hpp"
14#include "PrecomputedPairwiseWeights.hpp"
15#include "create_combinations.hpp"
16#include "cohens_d.hpp"
17#include "simple_diff.hpp"
18#include "utils.hpp"
19
25namespace scran_markers {
26
86
91template<typename Stat_>
98 std::vector<Stat_*> mean;
99
105 std::vector<Stat_*> detected;
106
122 Stat_* cohens_d = NULL;
123
136 Stat_* auc = NULL;
137
144 Stat_* delta_mean = NULL;
145
152 Stat_* delta_detected = NULL;
153};
154
159template<typename Stat_>
165 std::vector<std::vector<Stat_> > mean;
166
171 std::vector<std::vector<Stat_> > detected;
172
179 std::vector<Stat_> cohens_d;
180
187 std::vector<Stat_> auc;
188
195 std::vector<Stat_> delta_mean;
196
203 std::vector<Stat_> delta_detected;
204};
205
209namespace internal {
210
211template<typename Index_, typename Stat_>
212void process_simple_pairwise_effects(
213 const Index_ ngenes,
214 const std::size_t ngroups,
215 const std::size_t nblocks,
216 const std::size_t ncombos,
217 std::vector<Stat_>& combo_means,
218 std::vector<Stat_>& combo_vars,
219 std::vector<Stat_>& combo_detected,
221 const std::vector<Stat_>& combo_weights,
222 const double threshold,
223 const int num_threads)
224{
225 std::vector<Stat_> total_weights_per_group;
226 const Stat_* total_weights_ptr = combo_weights.data();
227 if (nblocks > 1) {
228 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, combo_weights.data());
229 total_weights_ptr = total_weights_per_group.data();
230 }
231 PrecomputedPairwiseWeights<Stat_> preweights(ngroups, nblocks, combo_weights.data());
232
233 tatami::parallelize([&](const int, const Index_ start, const Index_ length) -> void {
234 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
235 auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, ncombos);
236 const auto tmp_means = combo_means.data() + in_offset;
237 const auto tmp_variances = combo_vars.data() + in_offset;
238 const auto tmp_detected = combo_detected.data() + in_offset;
239 average_group_stats(gene, ngroups, nblocks, tmp_means, tmp_detected, combo_weights.data(), total_weights_ptr, output.mean, output.detected);
240
241 // Computing the effect sizes.
242 const auto out_offset = sanisizer::product_unsafe<std::size_t>(gene, ngroups, ngroups);
243 if (output.cohens_d != NULL) {
244 internal::compute_pairwise_cohens_d(tmp_means, tmp_variances, ngroups, nblocks, preweights, threshold, output.cohens_d + out_offset);
245 }
246
247 if (output.delta_detected != NULL) {
248 internal::compute_pairwise_simple_diff(tmp_detected, ngroups, nblocks, preweights, output.delta_detected + out_offset);
249 }
250
251 if (output.delta_mean != NULL) {
252 internal::compute_pairwise_simple_diff(tmp_means, ngroups, nblocks, preweights, output.delta_mean + out_offset);
253 }
254 }
255 }, ngenes, num_threads);
256}
257
258template<typename Index_, typename Stat_>
259ScoreMarkersPairwiseBuffers<Stat_> fill_pairwise_results(const Index_ ngenes, const std::size_t ngroups, ScoreMarkersPairwiseResults<Stat_>& store, const ScoreMarkersPairwiseOptions& opt) {
260 ScoreMarkersPairwiseBuffers<Stat_> output;
261
262 internal::fill_average_results(ngenes, ngroups, store.mean, store.detected, output.mean, output.detected);
263
264 const auto num_effect_sizes = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ngroups, ngroups);
265
266 if (opt.compute_cohens_d) {
267 store.cohens_d.resize(num_effect_sizes
268#ifdef SCRAN_MARKERS_TEST_INIT
269 , SCRAN_MARKERS_TEST_INIT
270#endif
271 );
272 output.cohens_d = store.cohens_d.data();
273 }
274 if (opt.compute_auc) {
275 store.auc.resize(num_effect_sizes
276#ifdef SCRAN_MARKERS_TEST_INIT
277 , SCRAN_MARKERS_TEST_INIT
278#endif
279 );
280 output.auc = store.auc.data();
281 }
282 if (opt.compute_delta_mean) {
283 store.delta_mean.resize(num_effect_sizes
284#ifdef SCRAN_MARKERS_TEST_INIT
285 , SCRAN_MARKERS_TEST_INIT
286#endif
287 );
288 output.delta_mean = store.delta_mean.data();
289 }
290 if (opt.compute_delta_detected) {
291 store.delta_detected.resize(num_effect_sizes
292#ifdef SCRAN_MARKERS_TEST_INIT
293 , SCRAN_MARKERS_TEST_INIT
294#endif
295 );
296 output.delta_detected = store.delta_detected.data();
297 }
298
299 return output;
300}
301
302}
377template<typename Value_, typename Index_, typename Group_, typename Stat_>
379 const tatami::Matrix<Value_, Index_>& matrix,
380 const Group_* const group,
381 const ScoreMarkersPairwiseOptions& options,
383{
384 const Index_ NC = matrix.ncol();
385 const auto group_sizes = tatami_stats::tabulate_groups(group, NC);
386
387 // In most cases this doesn't really matter, but we do it for consistency with the 1-block case,
388 // and to account for variable weighting where non-zero block sizes get zero weight.
389 const auto group_weights = scran_blocks::compute_weights<Stat_>(group_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
390
391 const auto ngroups = group_sizes.size();
392 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(matrix.nrow(), ngroups);
393 std::vector<Stat_> group_means(payload_size), group_vars(payload_size), group_detected(payload_size);
394
395 if (output.auc != NULL || matrix.prefer_rows()) {
396 internal::scan_matrix_by_row<true>(
397 matrix,
398 ngroups,
399 group,
400 1,
401 static_cast<int*>(NULL),
402 ngroups,
403 NULL,
404 group_means,
405 group_vars,
406 group_detected,
407 output.auc,
408 group_sizes,
409 group_weights,
410 options.threshold,
411 options.num_threads
412 );
413
414 } else {
415 internal::scan_matrix_by_column(
416 matrix,
417 ngroups,
418 group,
419 group_means,
420 group_vars,
421 group_detected,
422 group_sizes,
423 options.num_threads
424 );
425 }
426
427 internal::process_simple_pairwise_effects(
428 matrix.nrow(),
429 ngroups,
430 1,
431 ngroups,
432 group_means,
433 group_vars,
434 group_detected,
435 output,
436 group_weights,
437 options.threshold,
438 options.num_threads
439 );
440}
441
481template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_>
483 const tatami::Matrix<Value_, Index_>& matrix,
484 const Group_* const group,
485 const Block_* const block,
486 const ScoreMarkersPairwiseOptions& options,
488{
489 const Index_ NC = matrix.ncol();
490 const auto ngroups = output.mean.size();
491 const auto nblocks = tatami_stats::total_groups(block, NC);
492
493 const auto combinations = internal::create_combinations(ngroups, group, block, NC);
494 const auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
495 const auto ncombos = combo_sizes.size();
496 const auto combo_weights = scran_blocks::compute_weights<Stat_>(combo_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
497
498 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(matrix.nrow(), ncombos);
499 std::vector<Stat_> combo_means(payload_size), combo_vars(payload_size), combo_detected(payload_size);
500
501 if (output.auc != NULL || matrix.prefer_rows()) {
502 internal::scan_matrix_by_row<false>(
503 matrix,
504 ngroups,
505 group,
506 nblocks,
507 block,
508 ncombos,
509 combinations.data(),
510 combo_means,
511 combo_vars,
512 combo_detected,
513 output.auc,
514 combo_sizes,
515 combo_weights,
516 options.threshold,
517 options.num_threads
518 );
519
520 } else {
521 internal::scan_matrix_by_column(
522 matrix,
523 ncombos,
524 combinations.data(),
525 combo_means,
526 combo_vars,
527 combo_detected,
528 combo_sizes,
529 options.num_threads
530 );
531 }
532
533 internal::process_simple_pairwise_effects(
534 matrix.nrow(),
535 ngroups,
536 nblocks,
537 ncombos,
538 combo_means,
539 combo_vars,
540 combo_detected,
541 output,
542 combo_weights,
543 options.threshold,
544 options.num_threads
545 );
546}
547
564template<typename Stat_ = double, typename Value_, typename Index_, typename Group_>
566 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
568 auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
569 score_markers_pairwise(matrix, group, options, buffers);
570 return res;
571}
572
592template<typename Stat_ = double, typename Value_, typename Index_, typename Group_, typename Block_>
594 const tatami::Matrix<Value_, Index_>& matrix,
595 const Group_* const group,
596 const Block_* const block,
597 const ScoreMarkersPairwiseOptions& options)
598{
599 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
601 const auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
602 score_markers_pairwise_blocked(matrix, group, block, options, buffers);
603 return res;
604}
605
606}
607
608#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
void compute_weights(std::size_t num_blocks, const Size_ *sizes, WeightPolicy policy, const VariableWeightParameters &variable, Weight_ *weights)
Marker detection for single-cell data.
Definition score_markers_pairwise.hpp:25
void score_markers_pairwise(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const ScoreMarkersPairwiseOptions &options, const ScoreMarkersPairwiseBuffers< Stat_ > &output)
Definition score_markers_pairwise.hpp:378
void score_markers_pairwise_blocked(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *const group, const Block_ *const block, const ScoreMarkersPairwiseOptions &options, const ScoreMarkersPairwiseBuffers< Stat_ > &output)
Definition score_markers_pairwise.hpp:482
void parallelize(Function_ fun, Index_ tasks, int threads)
Buffers for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:92
Stat_ * delta_mean
Definition score_markers_pairwise.hpp:144
Stat_ * cohens_d
Definition score_markers_pairwise.hpp:122
std::vector< Stat_ * > detected
Definition score_markers_pairwise.hpp:105
Stat_ * delta_detected
Definition score_markers_pairwise.hpp:152
Stat_ * auc
Definition score_markers_pairwise.hpp:136
std::vector< Stat_ * > mean
Definition score_markers_pairwise.hpp:98
Options for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:30
scran_blocks::WeightPolicy block_weight_policy
Definition score_markers_pairwise.hpp:78
int num_threads
Definition score_markers_pairwise.hpp:42
bool compute_delta_mean
Definition score_markers_pairwise.hpp:60
double threshold
Definition score_markers_pairwise.hpp:36
bool compute_cohens_d
Definition score_markers_pairwise.hpp:48
bool compute_auc
Definition score_markers_pairwise.hpp:54
bool compute_delta_detected
Definition score_markers_pairwise.hpp:66
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition score_markers_pairwise.hpp:84
Results for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:160
std::vector< Stat_ > delta_mean
Definition score_markers_pairwise.hpp:195
std::vector< std::vector< Stat_ > > detected
Definition score_markers_pairwise.hpp:171
std::vector< Stat_ > cohens_d
Definition score_markers_pairwise.hpp:179
std::vector< Stat_ > auc
Definition score_markers_pairwise.hpp:187
std::vector< Stat_ > delta_detected
Definition score_markers_pairwise.hpp:203
std::vector< std::vector< Stat_ > > mean
Definition score_markers_pairwise.hpp:165