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
15#include "tatami/tatami.hpp"
16#include "tatami_stats/tatami_stats.hpp"
17
23namespace scran_markers {
24
76
81template<typename Stat_>
88 std::vector<Stat_*> mean;
89
95 std::vector<Stat_*> detected;
96
110 Stat_* cohens_d = NULL;
111
119 Stat_* auc = NULL;
120
127 Stat_* delta_mean = NULL;
128
135 Stat_* delta_detected = NULL;
136};
137
142template<typename Stat_>
148 std::vector<std::vector<Stat_> > mean;
149
154 std::vector<std::vector<Stat_> > detected;
155
162 std::vector<Stat_> cohens_d;
163
170 std::vector<Stat_> auc;
171
178 std::vector<Stat_> delta_mean;
179
186 std::vector<Stat_> delta_detected;
187};
188
192namespace internal {
193
194template<typename Index_, typename Stat_>
195void process_simple_pairwise_effects(
196 Index_ ngenes,
197 size_t ngroups,
198 size_t nblocks,
199 size_t ncombos,
200 std::vector<Stat_>& combo_means,
201 std::vector<Stat_>& combo_vars,
202 std::vector<Stat_>& combo_detected,
204 const std::vector<Stat_>& combo_weights,
205 double threshold,
206 int num_threads)
207{
208 std::vector<Stat_> total_weights_per_group;
209 const Stat_* total_weights_ptr = combo_weights.data();
210 if (nblocks > 1) {
211 total_weights_per_group = compute_total_weight_per_group(ngroups, nblocks, combo_weights.data());
212 total_weights_ptr = total_weights_per_group.data();
213 }
214 PrecomputedPairwiseWeights<Stat_> preweights(ngroups, nblocks, combo_weights.data());
215
216 tatami::parallelize([&](size_t, Index_ start, Index_ length) -> void {
217 size_t in_offset = ncombos * static_cast<size_t>(start);
218 const auto* tmp_means = combo_means.data() + in_offset;
219 const auto* tmp_variances = combo_vars.data() + in_offset;
220 const auto* tmp_detected = combo_detected.data() + in_offset;
221
222 size_t squared = ngroups * ngroups;
223 for (size_t gene = start, end = start + length; gene < end; ++gene) {
224 average_group_stats(gene, ngroups, nblocks, tmp_means, tmp_detected, combo_weights.data(), total_weights_ptr, output.mean, output.detected);
225
226 // Computing the effect sizes.
227 size_t out_offset = gene * squared;
228 if (output.cohens_d != NULL) {
229 internal::compute_pairwise_cohens_d(tmp_means, tmp_variances, ngroups, nblocks, preweights, threshold, output.cohens_d + out_offset);
230 }
231
232 if (output.delta_detected != NULL) {
233 internal::compute_pairwise_simple_diff(tmp_detected, ngroups, nblocks, preweights, output.delta_detected + out_offset);
234 }
235
236 if (output.delta_mean != NULL) {
237 internal::compute_pairwise_simple_diff(tmp_means, ngroups, nblocks, preweights, output.delta_mean + out_offset);
238 }
239
240 tmp_means += ncombos;
241 tmp_variances += ncombos;
242 tmp_detected += ncombos;
243 }
244 }, ngenes, num_threads);
245}
246
247template<typename Stat_>
248ScoreMarkersPairwiseBuffers<Stat_> fill_pairwise_results(size_t ngenes, size_t ngroups, ScoreMarkersPairwiseResults<Stat_>& store, const ScoreMarkersPairwiseOptions& opt) {
249 ScoreMarkersPairwiseBuffers<Stat_> output;
250
251 internal::fill_average_results(ngenes, ngroups, store.mean, store.detected, output.mean, output.detected);
252
253 size_t num_effect_sizes = ngenes * ngroups * ngroups; // already size_t's, no need to cast.
254
255 if (opt.compute_cohens_d) {
256 store.cohens_d.resize(num_effect_sizes);
257 output.cohens_d = store.cohens_d.data();
258 }
259 if (opt.compute_auc) {
260 store.auc.resize(num_effect_sizes);
261 output.auc = store.auc.data();
262 }
263 if (opt.compute_delta_mean) {
264 store.delta_mean.resize(num_effect_sizes);
265 output.delta_mean = store.delta_mean.data();
266 }
267 if (opt.compute_delta_detected) {
268 store.delta_detected.resize(num_effect_sizes);
269 output.delta_detected = store.delta_detected.data();
270 }
271
272 return output;
273}
274
275}
344template<typename Value_, typename Index_, typename Group_, typename Stat_>
347 const Group_* group,
350{
351 Index_ NC = matrix.ncol();
352 auto group_sizes = tatami_stats::tabulate_groups(group, NC);
353
354 // In most cases this doesn't really matter, but we do it for consistency with the 1-block case,
355 // and to account for variable weighting where non-zero block sizes get zero weight.
356 auto group_weights = scran_blocks::compute_weights<Stat_>(group_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
357
358 size_t ngroups = group_sizes.size();
359 size_t payload_size = static_cast<size_t>(matrix.nrow()) * ngroups; // cast to size_t to avoid overflow.
361
362 if (output.auc != NULL || matrix.prefer_rows()) {
363 internal::scan_matrix_by_row<true>(
364 matrix,
365 ngroups,
366 group,
367 1,
368 static_cast<int*>(NULL),
369 ngroups,
370 NULL,
374 output.auc,
377 options.threshold,
378 options.num_threads
379 );
380
381 } else {
382 internal::scan_matrix_by_column(
383 matrix,
384 ngroups,
385 group,
390 options.num_threads
391 );
392 }
393
394 internal::process_simple_pairwise_effects(
395 matrix.nrow(),
396 ngroups,
397 1,
398 ngroups,
402 output,
404 options.threshold,
405 options.num_threads);
406}
407
446template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_>
449 const Group_* group,
450 const Block_* block,
453{
454 Index_ NC = matrix.ncol();
455 size_t ngroups = output.mean.size();
456 size_t nblocks = tatami_stats::total_groups(block, NC);
457
458 auto combinations = internal::create_combinations(ngroups, group, block, NC);
459 auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
460 size_t ncombos = combo_sizes.size();
461 auto combo_weights = scran_blocks::compute_weights<Stat_>(combo_sizes, options.block_weight_policy, options.variable_block_weight_parameters);
462
463 size_t payload_size = static_cast<size_t>(matrix.nrow()) * ncombos; // cast to size_t to avoid overflow.
465
466 if (output.auc != NULL || matrix.prefer_rows()) {
467 internal::scan_matrix_by_row<false>(
468 matrix,
469 ngroups,
470 group,
471 nblocks,
472 block,
473 ncombos,
474 combinations.data(),
478 output.auc,
481 options.threshold,
482 options.num_threads
483 );
484
485 } else {
486 internal::scan_matrix_by_column(
487 matrix,
488 ncombos,
489 combinations.data(),
494 options.num_threads
495 );
496 }
497
498 internal::process_simple_pairwise_effects(
499 matrix.nrow(),
500 ngroups,
501 nblocks,
502 ncombos,
506 output,
508 options.threshold,
509 options.num_threads);
510}
511
527template<typename Stat_ = double, typename Value_, typename Index_, typename Group_>
529 size_t ngroups = tatami_stats::total_groups(group, matrix.ncol());
531 auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
533 return res;
534}
535
554template<typename Stat_ = double, typename Value_, typename Index_, typename Group_, typename Block_>
562
563}
564
565#endif
Marker detection for single-cell data.
Definition score_markers_pairwise.hpp:23
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:345
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:447
void parallelize(Function_ fun, Index_ tasks, int threads)
Buffers for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:82
Stat_ * delta_mean
Definition score_markers_pairwise.hpp:127
Stat_ * cohens_d
Definition score_markers_pairwise.hpp:110
std::vector< Stat_ * > detected
Definition score_markers_pairwise.hpp:95
Stat_ * delta_detected
Definition score_markers_pairwise.hpp:135
Stat_ * auc
Definition score_markers_pairwise.hpp:119
std::vector< Stat_ * > mean
Definition score_markers_pairwise.hpp:88
Options for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:28
scran_blocks::WeightPolicy block_weight_policy
Definition score_markers_pairwise.hpp:68
int num_threads
Definition score_markers_pairwise.hpp:39
bool compute_delta_mean
Definition score_markers_pairwise.hpp:57
double threshold
Definition score_markers_pairwise.hpp:33
bool compute_cohens_d
Definition score_markers_pairwise.hpp:45
bool compute_auc
Definition score_markers_pairwise.hpp:51
bool compute_delta_detected
Definition score_markers_pairwise.hpp:63
scran_blocks::VariableWeightParameters variable_block_weight_parameters
Definition score_markers_pairwise.hpp:74
Results for score_markers_pairwise() and friends.
Definition score_markers_pairwise.hpp:143
std::vector< Stat_ > delta_mean
Definition score_markers_pairwise.hpp:178
std::vector< std::vector< Stat_ > > detected
Definition score_markers_pairwise.hpp:154
std::vector< Stat_ > cohens_d
Definition score_markers_pairwise.hpp:162
std::vector< Stat_ > auc
Definition score_markers_pairwise.hpp:170
std::vector< Stat_ > delta_detected
Definition score_markers_pairwise.hpp:186
std::vector< std::vector< Stat_ > > mean
Definition score_markers_pairwise.hpp:148