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 "cohens_d.hpp"
5#include "simple_diff.hpp"
6
7#include "scan_matrix.hpp"
8#include "average_group_stats.hpp"
9#include "PrecomputedPairwiseWeights.hpp"
10#include "create_combinations.hpp"
11
12#include <vector>
13#include <cstddef>
14
16#include "tatami/tatami.hpp"
17#include "tatami_stats/tatami_stats.hpp"
18#include "sanisizer/sanisizer.hpp"
19
25namespace scran_markers {
26
78
83template<typename Stat_>
90 std::vector<Stat_*> mean;
91
97 std::vector<Stat_*> detected;
98
114 Stat_* cohens_d = NULL;
115
128 Stat_* auc = NULL;
129
136 Stat_* delta_mean = NULL;
137
144 Stat_* delta_detected = NULL;
145};
146
151template<typename Stat_>
157 std::vector<std::vector<Stat_> > mean;
158
163 std::vector<std::vector<Stat_> > detected;
164
171 std::vector<Stat_> cohens_d;
172
179 std::vector<Stat_> auc;
180
187 std::vector<Stat_> delta_mean;
188
195 std::vector<Stat_> delta_detected;
196};
197
201namespace internal {
202
203template<typename Index_, typename Stat_>
204void process_simple_pairwise_effects(
205 Index_ ngenes,
206 std::size_t ngroups,
207 std::size_t nblocks,
208 std::size_t ncombos,
209 std::vector<Stat_>& combo_means,
210 std::vector<Stat_>& combo_vars,
211 std::vector<Stat_>& combo_detected,
213 const std::vector<Stat_>& combo_weights,
214 double threshold,
215 int num_threads)
216{
217 std::vector<Stat_> total_weights_per_group;
218 const Stat_* total_weights_ptr = combo_weights.data();
219 if (nblocks > 1) {
220 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, combo_weights.data());
221 total_weights_ptr = total_weights_per_group.data();
222 }
223 PrecomputedPairwiseWeights<Stat_> preweights(ngroups, nblocks, combo_weights.data());
224
225 tatami::parallelize([&](int, Index_ start, Index_ length) -> void {
226 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
227 auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, ncombos);
228 const auto* tmp_means = combo_means.data() + in_offset;
229 const auto* tmp_variances = combo_vars.data() + in_offset;
230 const auto* tmp_detected = combo_detected.data() + in_offset;
231 average_group_stats(gene, ngroups, nblocks, tmp_means, tmp_detected, combo_weights.data(), total_weights_ptr, output.mean, output.detected);
232
233 // Computing the effect sizes.
234 auto out_offset = sanisizer::product_unsafe<std::size_t>(gene, ngroups, ngroups);
235 if (output.cohens_d != NULL) {
236 internal::compute_pairwise_cohens_d(tmp_means, tmp_variances, ngroups, nblocks, preweights, threshold, output.cohens_d + out_offset);
237 }
238
239 if (output.delta_detected != NULL) {
240 internal::compute_pairwise_simple_diff(tmp_detected, ngroups, nblocks, preweights, output.delta_detected + out_offset);
241 }
242
243 if (output.delta_mean != NULL) {
244 internal::compute_pairwise_simple_diff(tmp_means, ngroups, nblocks, preweights, output.delta_mean + out_offset);
245 }
246 }
247 }, ngenes, num_threads);
248}
249
250template<typename Index_, typename Stat_>
251ScoreMarkersPairwiseBuffers<Stat_> fill_pairwise_results(Index_ ngenes, std::size_t ngroups, ScoreMarkersPairwiseResults<Stat_>& store, const ScoreMarkersPairwiseOptions& opt) {
252 ScoreMarkersPairwiseBuffers<Stat_> output;
253
254 internal::fill_average_results(ngenes, ngroups, store.mean, store.detected, output.mean, output.detected);
255
256 auto num_effect_sizes = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ngroups, ngroups);
257
258 if (opt.compute_cohens_d) {
259 store.cohens_d.resize(num_effect_sizes
260#ifdef SCRAN_MARKERS_TEST_INIT
261 , SCRAN_MARKERS_TEST_INIT
262#endif
263 );
264 output.cohens_d = store.cohens_d.data();
265 }
266 if (opt.compute_auc) {
267 store.auc.resize(num_effect_sizes
268#ifdef SCRAN_MARKERS_TEST_INIT
269 , SCRAN_MARKERS_TEST_INIT
270#endif
271 );
272 output.auc = store.auc.data();
273 }
274 if (opt.compute_delta_mean) {
275 store.delta_mean.resize(num_effect_sizes
276#ifdef SCRAN_MARKERS_TEST_INIT
277 , SCRAN_MARKERS_TEST_INIT
278#endif
279 );
280 output.delta_mean = store.delta_mean.data();
281 }
282 if (opt.compute_delta_detected) {
283 store.delta_detected.resize(num_effect_sizes
284#ifdef SCRAN_MARKERS_TEST_INIT
285 , SCRAN_MARKERS_TEST_INIT
286#endif
287 );
288 output.delta_detected = store.delta_detected.data();
289 }
290
291 return output;
292}
293
294}
363template<typename Value_, typename Index_, typename Group_, typename Stat_>
365 const tatami::Matrix<Value_, Index_>& matrix,
366 const Group_* group,
367 const ScoreMarkersPairwiseOptions& options,
369{
370 Index_ NC = matrix.ncol();
371 auto group_sizes = tatami_stats::tabulate_groups(group, NC);
372
373 // In most cases this doesn't really matter, but we do it for consistency with the 1-block case,
374 // and to account for variable weighting where non-zero block sizes get zero weight.
375 auto group_weights = scran_blocks::compute_weights<Stat_>(group_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
376
377 auto ngroups = group_sizes.size();
378 auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(matrix.nrow(), ngroups);
379 std::vector<Stat_> group_means(payload_size), group_vars(payload_size), group_detected(payload_size);
380
381 if (output.auc != NULL || matrix.prefer_rows()) {
382 internal::scan_matrix_by_row<true>(
383 matrix,
384 ngroups,
385 group,
386 1,
387 static_cast<int*>(NULL),
388 ngroups,
389 NULL,
390 group_means,
391 group_vars,
392 group_detected,
393 output.auc,
394 group_sizes,
395 group_weights,
396 options.threshold,
397 options.num_threads
398 );
399
400 } else {
401 internal::scan_matrix_by_column(
402 matrix,
403 ngroups,
404 group,
405 group_means,
406 group_vars,
407 group_detected,
408 group_sizes,
409 options.num_threads
410 );
411 }
412
413 internal::process_simple_pairwise_effects(
414 matrix.nrow(),
415 ngroups,
416 1,
417 ngroups,
418 group_means,
419 group_vars,
420 group_detected,
421 output,
422 group_weights,
423 options.threshold,
424 options.num_threads);
425}
426
465template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_>
467 const tatami::Matrix<Value_, Index_>& matrix,
468 const Group_* group,
469 const Block_* block,
470 const ScoreMarkersPairwiseOptions& options,
472{
473 Index_ NC = matrix.ncol();
474 auto ngroups = output.mean.size();
475 auto nblocks = tatami_stats::total_groups(block, NC);
476
477 auto combinations = internal::create_combinations(ngroups, group, block, NC);
478 auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
479 auto ncombos = combo_sizes.size();
480 auto combo_weights = scran_blocks::compute_weights<Stat_>(combo_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
481
482 auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(matrix.nrow(), ncombos);
483 std::vector<Stat_> combo_means(payload_size), combo_vars(payload_size), combo_detected(payload_size);
484
485 if (output.auc != NULL || matrix.prefer_rows()) {
486 internal::scan_matrix_by_row<false>(
487 matrix,
488 ngroups,
489 group,
490 nblocks,
491 block,
492 ncombos,
493 combinations.data(),
494 combo_means,
495 combo_vars,
496 combo_detected,
497 output.auc,
498 combo_sizes,
499 combo_weights,
500 options.threshold,
501 options.num_threads
502 );
503
504 } else {
505 internal::scan_matrix_by_column(
506 matrix,
507 ncombos,
508 combinations.data(),
509 combo_means,
510 combo_vars,
511 combo_detected,
512 combo_sizes,
513 options.num_threads
514 );
515 }
516
517 internal::process_simple_pairwise_effects(
518 matrix.nrow(),
519 ngroups,
520 nblocks,
521 ncombos,
522 combo_means,
523 combo_vars,
524 combo_detected,
525 output,
526 combo_weights,
527 options.threshold,
528 options.num_threads);
529}
530
546template<typename Stat_ = double, typename Value_, typename Index_, typename Group_>
548 auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
550 auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
551 score_markers_pairwise(matrix, group, options, buffers);
552 return res;
553}
554
573template<typename Stat_ = double, typename Value_, typename Index_, typename Group_, typename Block_>
575 auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
577 auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
578 score_markers_pairwise_blocked(matrix, group, block, options, buffers);
579 return res;
580}
581
582}
583
584#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_ *group, const ScoreMarkersPairwiseOptions &options, const ScoreMarkersPairwiseBuffers< Stat_ > &output)
Definition score_markers_pairwise.hpp:364
void score_markers_pairwise_blocked(const tatami::Matrix< Value_, Index_ > &matrix, const Group_ *group, const Block_ *block, const ScoreMarkersPairwiseOptions &options, const ScoreMarkersPairwiseBuffers< Stat_ > &output)
Definition score_markers_pairwise.hpp:466
void parallelize(Function_ fun, Index_ tasks, int threads)
Buffers for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:84
Stat_ * delta_mean
Definition score_markers_pairwise.hpp:136
Stat_ * cohens_d
Definition score_markers_pairwise.hpp:114
std::vector< Stat_ * > detected
Definition score_markers_pairwise.hpp:97
Stat_ * delta_detected
Definition score_markers_pairwise.hpp:144
Stat_ * auc
Definition score_markers_pairwise.hpp:128
std::vector< Stat_ * > mean
Definition score_markers_pairwise.hpp:90
Options for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:30
scran_blocks::WeightPolicy block_weight_policy
Definition score_markers_pairwise.hpp:70
int num_threads
Definition score_markers_pairwise.hpp:41
bool compute_delta_mean
Definition score_markers_pairwise.hpp:59
double threshold
Definition score_markers_pairwise.hpp:35
bool compute_cohens_d
Definition score_markers_pairwise.hpp:47
bool compute_auc
Definition score_markers_pairwise.hpp:53
bool compute_delta_detected
Definition score_markers_pairwise.hpp:65
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition score_markers_pairwise.hpp:76
Results for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:152
std::vector< Stat_ > delta_mean
Definition score_markers_pairwise.hpp:187
std::vector< std::vector< Stat_ > > detected
Definition score_markers_pairwise.hpp:163
std::vector< Stat_ > cohens_d
Definition score_markers_pairwise.hpp:171
std::vector< Stat_ > auc
Definition score_markers_pairwise.hpp:179
std::vector< Stat_ > delta_detected
Definition score_markers_pairwise.hpp:195
std::vector< std::vector< Stat_ > > mean
Definition score_markers_pairwise.hpp:157