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
98
103template<typename Stat_>
112 std::vector<Stat_*> mean;
113
121 std::vector<Stat_*> detected;
122
138 Stat_* cohens_d = NULL;
139
152 Stat_* auc = NULL;
153
161 Stat_* delta_mean = NULL;
162
170 Stat_* delta_detected = NULL;
171};
172
177template<typename Stat_>
185 std::vector<std::vector<Stat_> > mean;
186
193 std::vector<std::vector<Stat_> > detected;
194
202 std::vector<Stat_> cohens_d;
203
211 std::vector<Stat_> auc;
212
220 std::vector<Stat_> delta_mean;
221
229 std::vector<Stat_> delta_detected;
230};
231
235namespace internal {
236
237template<typename Index_, typename Stat_>
238void process_simple_pairwise_effects(
239 const Index_ ngenes,
240 const std::size_t ngroups,
241 const std::size_t nblocks,
242 const std::size_t ncombos,
243 std::vector<Stat_>& combo_means,
244 std::vector<Stat_>& combo_vars,
245 std::vector<Stat_>& combo_detected,
247 const std::vector<Stat_>& combo_weights,
248 const double threshold,
249 const int num_threads)
250{
251 std::vector<Stat_> total_weights_per_group;
252 const Stat_* total_weights_ptr = combo_weights.data();
253 if (nblocks > 1) {
254 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, combo_weights.data());
255 total_weights_ptr = total_weights_per_group.data();
256 }
257 PrecomputedPairwiseWeights<Stat_> preweights(ngroups, nblocks, combo_weights.data());
258
259 tatami::parallelize([&](const int, const Index_ start, const Index_ length) -> void {
260 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
261 auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, ncombos);
262
263 if (!output.mean.empty()) {
264 const auto tmp_means = combo_means.data() + in_offset;
265 average_group_stats(gene, ngroups, nblocks, tmp_means, combo_weights.data(), total_weights_ptr, output.mean);
266 }
267 if (!output.detected.empty()) {
268 const auto tmp_detected = combo_detected.data() + in_offset;
269 average_group_stats(gene, ngroups, nblocks, tmp_detected, combo_weights.data(), total_weights_ptr, output.detected);
270 }
271
272 // Computing the effect sizes.
273 const auto out_offset = sanisizer::product_unsafe<std::size_t>(gene, ngroups, ngroups);
274
275 if (output.cohens_d != NULL) {
276 const auto tmp_means = combo_means.data() + in_offset;
277 const auto tmp_variances = combo_vars.data() + in_offset;
278 compute_pairwise_cohens_d(tmp_means, tmp_variances, ngroups, nblocks, preweights, threshold, output.cohens_d + out_offset);
279 }
280
281 if (output.delta_detected != NULL) {
282 const auto tmp_detected = combo_detected.data() + in_offset;
283 compute_pairwise_simple_diff(tmp_detected, ngroups, nblocks, preweights, output.delta_detected + out_offset);
284 }
285
286 if (output.delta_mean != NULL) {
287 const auto tmp_means = combo_means.data() + in_offset;
288 compute_pairwise_simple_diff(tmp_means, ngroups, nblocks, preweights, output.delta_mean + out_offset);
289 }
290 }
291 }, ngenes, num_threads);
292}
293
294template<typename Index_, typename Stat_>
295ScoreMarkersPairwiseBuffers<Stat_> preallocate_pairwise_results(const Index_ ngenes, const std::size_t ngroups, ScoreMarkersPairwiseResults<Stat_>& store, const ScoreMarkersPairwiseOptions& opt) {
296 ScoreMarkersPairwiseBuffers<Stat_> output;
297
298 if (opt.compute_group_mean) {
299 preallocate_average_results(ngenes, ngroups, store.mean, output.mean);
300 }
301 if (opt.compute_group_detected) {
302 preallocate_average_results(ngenes, ngroups, store.detected, output.detected);
303 }
304
305 const auto num_effect_sizes = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ngroups, ngroups);
306
307 if (opt.compute_cohens_d) {
308 store.cohens_d.resize(num_effect_sizes
309#ifdef SCRAN_MARKERS_TEST_INIT
310 , SCRAN_MARKERS_TEST_INIT
311#endif
312 );
313 output.cohens_d = store.cohens_d.data();
314 }
315 if (opt.compute_auc) {
316 store.auc.resize(num_effect_sizes
317#ifdef SCRAN_MARKERS_TEST_INIT
318 , SCRAN_MARKERS_TEST_INIT
319#endif
320 );
321 output.auc = store.auc.data();
322 }
323 if (opt.compute_delta_mean) {
324 store.delta_mean.resize(num_effect_sizes
325#ifdef SCRAN_MARKERS_TEST_INIT
326 , SCRAN_MARKERS_TEST_INIT
327#endif
328 );
329 output.delta_mean = store.delta_mean.data();
330 }
331 if (opt.compute_delta_detected) {
332 store.delta_detected.resize(num_effect_sizes
333#ifdef SCRAN_MARKERS_TEST_INIT
334 , SCRAN_MARKERS_TEST_INIT
335#endif
336 );
337 output.delta_detected = store.delta_detected.data();
338 }
339
340 return output;
341}
342
343template<
344 bool single_block_,
345 typename Value_,
346 typename Index_,
347 typename Group_,
348 typename Block_,
349 typename Stat_
350>
352 const tatami::Matrix<Value_, Index_>& matrix,
353 const std::size_t ngroups,
354 const Group_* const group,
355 const std::size_t nblocks,
356 const Block_* const block,
357 const std::size_t ncombos,
358 const std::size_t* const combo,
359 const std::vector<Index_>& combo_sizes,
360 const ScoreMarkersPairwiseOptions& options,
361 const ScoreMarkersPairwiseBuffers<Stat_>& output
362) {
363 const auto ngenes = matrix.nrow();
364 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ncombos);
365 std::vector<Stat_> combo_means, combo_vars, combo_detected;
366 if (!output.mean.empty() || output.cohens_d != NULL || output.delta_mean != NULL) {
367 combo_means.resize(payload_size);
368 }
369 if (output.cohens_d != NULL) {
370 combo_vars.resize(payload_size);
371 }
372 if (!output.detected.empty() || output.delta_detected != NULL) {
373 combo_detected.resize(payload_size);
374 }
375
376 // For a single block, this usually doesn't really matter, but we do it for consistency with the multi-block case,
377 // and to account for variable weighting where non-zero block sizes get zero weight.
378 const auto combo_weights = scran_blocks::compute_weights<Stat_>(
379 combo_sizes,
380 options.block_weight_policy,
381 options.variable_block_weight_parameters
382 );
383
384 if (output.auc != NULL || matrix.prefer_rows()) {
385 scan_matrix_by_row_full_auc<single_block_>(
386 matrix,
387 ngroups,
388 group,
389 nblocks,
390 block,
391 ncombos,
392 combo,
393 combo_means,
394 combo_vars,
395 combo_detected,
396 output.auc,
397 combo_sizes,
398 combo_weights,
399 options.threshold,
400 options.num_threads
401 );
402
403 } else {
404 scan_matrix_by_column(
405 matrix,
406 [&]{
407 if constexpr(single_block_) {
408 return ngroups;
409 } else {
410 return ncombos;
411 }
412 }(),
413 [&]{
414 if constexpr(single_block_) {
415 return group;
416 } else {
417 return combo;
418 }
419 }(),
420 combo_means,
421 combo_vars,
422 combo_detected,
423 combo_sizes,
424 options.num_threads
425 );
426 }
427
428 process_simple_pairwise_effects(
429 matrix.nrow(),
430 ngroups,
431 nblocks,
432 ncombos,
433 combo_means,
434 combo_vars,
435 combo_detected,
436 output,
437 combo_weights,
438 options.threshold,
439 options.num_threads
440 );
441}
442
443}
518template<typename Value_, typename Index_, typename Group_, typename Stat_>
520 const tatami::Matrix<Value_, Index_>& matrix,
521 const Group_* const group,
522 const ScoreMarkersPairwiseOptions& options,
524) {
525 const Index_ NC = matrix.ncol();
526 const auto group_sizes = tatami_stats::tabulate_groups(group, NC);
527 const auto ngroups = sanisizer::cast<std::size_t>(group_sizes.size());
528
529 internal::score_markers_pairwise<true>(
530 matrix,
531 ngroups,
532 group,
533 1,
534 static_cast<int*>(NULL),
535 ngroups,
536 static_cast<std::size_t*>(NULL),
537 group_sizes,
538 options,
539 output
540 );
541}
542
582template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_>
584 const tatami::Matrix<Value_, Index_>& matrix,
585 const Group_* const group,
586 const Block_* const block,
587 const ScoreMarkersPairwiseOptions& options,
589) {
590 const Index_ NC = matrix.ncol();
591 const auto ngroups = output.mean.size();
592 const auto nblocks = tatami_stats::total_groups(block, NC);
593
594 const auto combinations = internal::create_combinations(ngroups, group, block, NC);
595 const auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
596 const auto ncombos = combo_sizes.size();
597
598 internal::score_markers_pairwise<false>(
599 matrix,
600 sanisizer::cast<std::size_t>(ngroups),
601 group,
602 sanisizer::cast<std::size_t>(nblocks),
603 block,
604 sanisizer::cast<std::size_t>(ncombos),
605 combinations.data(),
606 combo_sizes,
607 options,
608 output
609 );
610}
611
628template<typename Stat_ = double, typename Value_, typename Index_, typename Group_>
630 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
632 auto buffers = internal::preallocate_pairwise_results(matrix.nrow(), ngroups, res, options);
633 score_markers_pairwise(matrix, group, options, buffers);
634 return res;
635}
636
656template<typename Stat_ = double, typename Value_, typename Index_, typename Group_, typename Block_>
658 const tatami::Matrix<Value_, Index_>& matrix,
659 const Group_* const group,
660 const Block_* const block,
661 const ScoreMarkersPairwiseOptions& options)
662{
663 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
665 const auto buffers = internal::preallocate_pairwise_results(matrix.nrow(), ngroups, res, options);
666 score_markers_pairwise_blocked(matrix, group, block, options, buffers);
667 return res;
668}
669
670}
671
672#endif
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: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:519
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:583
void parallelize(Function_ fun, const Index_ tasks, const int threads)
Buffers for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:104
Stat_ * delta_mean
Definition score_markers_pairwise.hpp:161
Stat_ * cohens_d
Definition score_markers_pairwise.hpp:138
std::vector< Stat_ * > detected
Definition score_markers_pairwise.hpp:121
Stat_ * delta_detected
Definition score_markers_pairwise.hpp:170
Stat_ * auc
Definition score_markers_pairwise.hpp:152
std::vector< Stat_ * > mean
Definition score_markers_pairwise.hpp:112
Options for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:30
bool compute_group_mean
Definition score_markers_pairwise.hpp:48
scran_blocks::WeightPolicy block_weight_policy
Definition score_markers_pairwise.hpp:90
int num_threads
Definition score_markers_pairwise.hpp:42
bool compute_delta_mean
Definition score_markers_pairwise.hpp:72
double threshold
Definition score_markers_pairwise.hpp:36
bool compute_group_detected
Definition score_markers_pairwise.hpp:54
bool compute_cohens_d
Definition score_markers_pairwise.hpp:60
bool compute_auc
Definition score_markers_pairwise.hpp:66
bool compute_delta_detected
Definition score_markers_pairwise.hpp:78
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition score_markers_pairwise.hpp:96
Results for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:178
std::vector< Stat_ > delta_mean
Definition score_markers_pairwise.hpp:220
std::vector< std::vector< Stat_ > > detected
Definition score_markers_pairwise.hpp:193
std::vector< Stat_ > cohens_d
Definition score_markers_pairwise.hpp:202
std::vector< Stat_ > auc
Definition score_markers_pairwise.hpp:211
std::vector< Stat_ > delta_detected
Definition score_markers_pairwise.hpp:229
std::vector< std::vector< Stat_ > > mean
Definition score_markers_pairwise.hpp:185